diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d51879e..78728c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,12 +1,14 @@ name: CI on: push: - branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + branches: + - '**' + - '!integrated/**' + - '!stl-preview-head/**' + - '!stl-preview-base/**' + - '!generated' + - '!codegen/**' + - 'codegen/stl/**' pull_request: branches-ignore: - 'stl-preview-head/**' @@ -17,7 +19,7 @@ jobs: timeout-minutes: 10 name: lint runs-on: ${{ github.repository == 'stainless-sdks/isaacus-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - uses: actions/checkout@v6 @@ -36,7 +38,7 @@ jobs: timeout-minutes: 5 name: build runs-on: ${{ github.repository == 'stainless-sdks/isaacus-typescript' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} - if: github.event_name == 'push' || github.event.pull_request.head.repo.fork + if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') permissions: contents: read id-token: write diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 7e970b4..0ed68e0 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -33,13 +33,14 @@ jobs: - name: Publish to NPM run: | - if [ -n "${{ github.event.inputs.path }}" ]; then - PATHS_RELEASED='[\"${{ github.event.inputs.path }}\"]' + if [ -n "$INPUT_PATH" ]; then + PATHS_RELEASED="[\"$INPUT_PATH\"]" else PATHS_RELEASED='[\".\", \"packages/mcp-server\"]' fi yarn tsn scripts/publish-packages.ts "{ \"paths_released\": \"$PATHS_RELEASED\" }" env: + INPUT_PATH: ${{ github.event.inputs.path }} NPM_TOKEN: ${{ secrets.ISAACUS_NPM_TOKEN || secrets.NPM_TOKEN }} - name: Upload MCP Server DXT GitHub release asset diff --git a/.gitignore b/.gitignore index d62bea5..b7d4f6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .prism.log +.stdy.log node_modules yarn-error.log codegen.log diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 788b0fa..ae8c97a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.22.0" + ".": "0.22.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 682ed59..d8d6f7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog +## 0.22.1 (2026-03-28) + +Full Changelog: [v0.22.0...v0.22.1](https://github.com/isaacus-dev/isaacus-typescript/compare/v0.22.0...v0.22.1) + +### Chores + +* **ci:** escape input path in publish-npm workflow ([37de3db](https://github.com/isaacus-dev/isaacus-typescript/commit/37de3db4c34147f751a6fa8ae60f8dcc9ad477b7)) +* **ci:** skip lint on metadata-only changes ([03c9e5f](https://github.com/isaacus-dev/isaacus-typescript/commit/03c9e5fc53ddd4c08aa66fd3b93afa067d21e185)) +* **internal:** bump @modelcontextprotocol/sdk, @hono/node-server, and minimatch ([2721387](https://github.com/isaacus-dev/isaacus-typescript/commit/27213877706a51093af4eb15e3ed1eeb71af9e97)) +* **internal:** codegen related update ([dc8c9d9](https://github.com/isaacus-dev/isaacus-typescript/commit/dc8c9d98bbeb42dac7bd9b8166a59097031759e6)) +* **internal:** fix MCP server TS errors that occur with required client options ([c834dba](https://github.com/isaacus-dev/isaacus-typescript/commit/c834dba3466004f1385dabbea908480217988d2b)) +* **internal:** make generated MCP servers compatible with Cloudflare worker environments ([6e1fbb2](https://github.com/isaacus-dev/isaacus-typescript/commit/6e1fbb2ceef03158f8a1b4be24bb30608069faad)) +* **internal:** support custom-instructions-path flag in MCP servers ([9c72691](https://github.com/isaacus-dev/isaacus-typescript/commit/9c726913496aa66da7acac78b5501f95946dcbb2)) +* **internal:** support local docs search in MCP servers ([0f9290d](https://github.com/isaacus-dev/isaacus-typescript/commit/0f9290dac91e2e7c42218e660fb267db751ee19f)) +* **internal:** support x-stainless-mcp-client-envs header in MCP servers ([274f5c2](https://github.com/isaacus-dev/isaacus-typescript/commit/274f5c2620d69c0d97e5933d7b0804b3583570f8)) +* **internal:** support x-stainless-mcp-client-permissions headers in MCP servers ([aba6116](https://github.com/isaacus-dev/isaacus-typescript/commit/aba6116403bede7f968a37e080b8e6ed52893d51)) +* **internal:** tweak CI branches ([b97f70d](https://github.com/isaacus-dev/isaacus-typescript/commit/b97f70db25ccb1a838a92751ae1384d4220e2ac8)) +* **internal:** update gitignore ([971e5bd](https://github.com/isaacus-dev/isaacus-typescript/commit/971e5bd2076c311e7a90b346f9ea9dca013f2760)) + ## 0.22.0 (2026-03-11) Full Changelog: [v0.21.0...v0.22.0](https://github.com/isaacus-dev/isaacus-typescript/compare/v0.21.0...v0.22.0) diff --git a/package.json b/package.json index 69d7249..9c90338 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "isaacus", - "version": "0.22.0", + "version": "0.22.1", "description": "The official TypeScript library for the Isaacus API", "author": "Isaacus ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index 6ee684b..084aeac 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -1,7 +1,7 @@ { "dxt_version": "0.2", "name": "isaacus-mcp", - "version": "0.22.0", + "version": "0.22.1", "description": "The official MCP Server for the Isaacus API", "author": { "name": "Isaacus", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index d8cff83..74d3b91 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "isaacus-mcp", - "version": "0.22.0", + "version": "0.22.1", "description": "The official MCP Server for the Isaacus API", "author": "Isaacus ", "types": "dist/index.d.ts", @@ -41,6 +41,7 @@ "cors": "^2.8.5", "express": "^5.1.0", "fuse.js": "^7.1.0", + "minisearch": "^7.2.0", "jq-web": "https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz", "pino": "^10.3.1", "pino-http": "^11.0.0", diff --git a/packages/mcp-server/src/code-tool-paths.cts b/packages/mcp-server/src/code-tool-paths.cts index 15ce7f5..78263e4 100644 --- a/packages/mcp-server/src/code-tool-paths.cts +++ b/packages/mcp-server/src/code-tool-paths.cts @@ -1,3 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -export const workerPath = require.resolve('./code-tool-worker.mjs'); +export function getWorkerPath(): string { + return require.resolve('./code-tool-worker.mjs'); +} diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 6396cb7..ef93b1d 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -1,10 +1,5 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -import fs from 'node:fs'; -import path from 'node:path'; -import url from 'node:url'; -import { newDenoHTTPWorker } from '@valtown/deno-http-worker'; -import { workerPath } from './code-tool-paths.cjs'; import { ContentBlock, McpRequestContext, @@ -153,19 +148,23 @@ const remoteStainlessHandler = async ({ const codeModeEndpoint = readEnv('CODE_MODE_ENDPOINT_URL') ?? 'https://api.stainless.com/api/ai/code-tool'; + const localClientEnvs = { + ISAACUS_API_KEY: requireValue( + readEnv('ISAACUS_API_KEY') ?? client.apiKey, + 'set ISAACUS_API_KEY environment variable or provide apiKey client option', + ), + ISAACUS_BASE_URL: readEnv('ISAACUS_BASE_URL') ?? client.baseURL ?? undefined, + }; + // Merge any upstream client envs from the request header, with upstream values taking precedence. + const mergedClientEnvs = { ...localClientEnvs, ...reqContext.upstreamClientEnvs }; + // Setting a Stainless API key authenticates requests to the code tool endpoint. const res = await fetch(codeModeEndpoint, { method: 'POST', headers: { ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }), 'Content-Type': 'application/json', - 'x-stainless-mcp-client-envs': JSON.stringify({ - ISAACUS_API_KEY: requireValue( - readEnv('ISAACUS_API_KEY') ?? client.apiKey, - 'set ISAACUS_API_KEY environment variable or provide apiKey client option', - ), - ISAACUS_BASE_URL: readEnv('ISAACUS_BASE_URL') ?? client.baseURL ?? undefined, - }), + 'x-stainless-mcp-client-envs': JSON.stringify(mergedClientEnvs), }, body: JSON.stringify({ project_name: 'isaacus', @@ -208,6 +207,13 @@ const localDenoHandler = async ({ reqContext: McpRequestContext; args: unknown; }): Promise => { + const fs = await import('node:fs'); + const path = await import('node:path'); + const url = await import('node:url'); + const { newDenoHTTPWorker } = await import('@valtown/deno-http-worker'); + const { getWorkerPath } = await import('./code-tool-paths.cjs'); + const workerPath = getWorkerPath(); + const client = reqContext.client; const baseURLHostname = new URL(client.baseURL).hostname; const { code } = args as { code: string }; @@ -269,6 +275,9 @@ const localDenoHandler = async ({ printOutput: true, spawnOptions: { cwd: path.dirname(workerPath), + // Merge any upstream client envs into the Deno subprocess environment, + // with the upstream env vars taking precedence. + env: { ...process.env, ...reqContext.upstreamClientEnvs }, }, }); @@ -278,13 +287,15 @@ const localDenoHandler = async ({ reject(new Error(`Worker exited with code ${exitCode}`)); }); - const opts: ClientOptions = { - baseURL: client.baseURL, - apiKey: client.apiKey, + // Strip null/undefined values so that the worker SDK client can fall back to + // reading from environment variables (including any upstreamClientEnvs). + const opts = { + ...(client.baseURL != null ? { baseURL: client.baseURL } : undefined), + ...(client.apiKey != null ? { apiKey: client.apiKey } : undefined), defaultHeaders: { 'X-Stainless-MCP': 'true', }, - }; + } satisfies Partial as ClientOptions; const req = worker.request( 'http://localhost', diff --git a/packages/mcp-server/src/docs-search-tool.ts b/packages/mcp-server/src/docs-search-tool.ts index 7d8688f..9c061f0 100644 --- a/packages/mcp-server/src/docs-search-tool.ts +++ b/packages/mcp-server/src/docs-search-tool.ts @@ -3,6 +3,7 @@ import { Tool } from '@modelcontextprotocol/sdk/types.js'; import { Metadata, McpRequestContext, asTextContentResult } from './types'; import { getLogger } from './logger'; +import type { LocalDocsSearch } from './local-docs-search'; export const metadata: Metadata = { resource: 'all', @@ -43,20 +44,49 @@ export const tool: Tool = { const docsSearchURL = process.env['DOCS_SEARCH_URL'] || 'https://api.stainless.com/api/projects/isaacus/docs/search'; -export const handler = async ({ - reqContext, - args, -}: { - reqContext: McpRequestContext; - args: Record | undefined; -}) => { +let _localSearch: LocalDocsSearch | undefined; + +export function setLocalSearch(search: LocalDocsSearch): void { + _localSearch = search; +} + +const SUPPORTED_LANGUAGES = new Set(['http', 'typescript', 'javascript']); + +async function searchLocal(args: Record): Promise { + if (!_localSearch) { + throw new Error('Local search not initialized'); + } + + const query = (args['query'] as string) ?? ''; + const language = (args['language'] as string) ?? 'typescript'; + const detail = (args['detail'] as string) ?? 'verbose'; + + if (!SUPPORTED_LANGUAGES.has(language)) { + throw new Error( + `Local docs search only supports HTTP, TypeScript, and JavaScript. Got language="${language}". ` + + `Use --docs-search-mode stainless-api for other languages, or set language to "http", "typescript", or "javascript".`, + ); + } + + return _localSearch.search({ + query, + language, + detail, + maxResults: 10, + }).results; +} + +async function searchRemote( + args: Record, + stainlessApiKey: string | undefined, +): Promise { const body = args as any; const query = new URLSearchParams(body).toString(); const startTime = Date.now(); const result = await fetch(`${docsSearchURL}?${query}`, { headers: { - ...(reqContext.stainlessApiKey && { Authorization: reqContext.stainlessApiKey }), + ...(stainlessApiKey && { Authorization: stainlessApiKey }), }, }); @@ -75,7 +105,7 @@ export const handler = async ({ 'Got error response from docs search tool', ); - if (result.status === 404 && !reqContext.stainlessApiKey) { + if (result.status === 404 && !stainlessApiKey) { throw new Error( 'Could not find docs for this project. You may need to provide a Stainless API key via the STAINLESS_API_KEY environment variable, the --stainless-api-key flag, or the x-stainless-api-key HTTP header.', ); @@ -94,7 +124,23 @@ export const handler = async ({ }, 'Got docs search result', ); - return asTextContentResult(resultBody); + return resultBody; +} + +export const handler = async ({ + reqContext, + args, +}: { + reqContext: McpRequestContext; + args: Record | undefined; +}) => { + const body = args ?? {}; + + if (_localSearch) { + return asTextContentResult(await searchLocal(body)); + } + + return asTextContentResult(await searchRemote(body, reqContext.stainlessApiKey)); }; export default { metadata, tool, handler }; diff --git a/packages/mcp-server/src/http.ts b/packages/mcp-server/src/http.ts index 9606565..902d9e8 100644 --- a/packages/mcp-server/src/http.ts +++ b/packages/mcp-server/src/http.ts @@ -23,18 +23,61 @@ const newServer = async ({ res: express.Response; }): Promise => { const stainlessApiKey = getStainlessApiKey(req, mcpOptions); - const server = await newMcpServer(stainlessApiKey); + const customInstructionsPath = mcpOptions.customInstructionsPath; + const server = await newMcpServer({ stainlessApiKey, customInstructionsPath }); const authOptions = parseClientAuthHeaders(req, false); + let upstreamClientEnvs: Record | undefined; + const clientEnvsHeader = req.headers['x-stainless-mcp-client-envs']; + if (typeof clientEnvsHeader === 'string') { + try { + const parsed = JSON.parse(clientEnvsHeader); + if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { + upstreamClientEnvs = parsed; + } + } catch { + // Ignore malformed header + } + } + + // Parse x-stainless-mcp-client-permissions header to override permission options + // + // Note: Permissions are best-effort and intended to prevent clients from doing unexpected things; + // they're not a hard security boundary, so we allow arbitrary, client-driven overrides. + // + // See the Stainless MCP documentation for more details. + let effectiveMcpOptions = mcpOptions; + const clientPermissionsHeader = req.headers['x-stainless-mcp-client-permissions']; + if (typeof clientPermissionsHeader === 'string') { + try { + const parsed = JSON.parse(clientPermissionsHeader); + if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { + effectiveMcpOptions = { + ...mcpOptions, + ...(typeof parsed.allow_http_gets === 'boolean' && { codeAllowHttpGets: parsed.allow_http_gets }), + ...(Array.isArray(parsed.allowed_methods) && { codeAllowedMethods: parsed.allowed_methods }), + ...(Array.isArray(parsed.blocked_methods) && { codeBlockedMethods: parsed.blocked_methods }), + }; + getLogger().info( + { clientPermissions: parsed }, + 'Overriding code execution permissions from x-stainless-mcp-client-permissions header', + ); + } + } catch (error) { + getLogger().warn({ error }, 'Failed to parse x-stainless-mcp-client-permissions header'); + } + } + await initMcpServer({ server: server, - mcpOptions: mcpOptions, + mcpOptions: effectiveMcpOptions, clientOptions: { ...clientOptions, ...authOptions, }, stainlessApiKey: stainlessApiKey, + upstreamClientEnvs, }); return server; @@ -72,7 +115,7 @@ const del = async (req: express.Request, res: express.Response) => { }; const redactHeaders = (headers: Record) => { - const hiddenHeaders = /auth|cookie|key|token/i; + const hiddenHeaders = /auth|cookie|key|token|x-stainless-mcp-client-envs/i; const filtered = { ...headers }; Object.keys(filtered).forEach((key) => { if (hiddenHeaders.test(key)) { diff --git a/packages/mcp-server/src/instructions.ts b/packages/mcp-server/src/instructions.ts index 06403de..0cd094b 100644 --- a/packages/mcp-server/src/instructions.ts +++ b/packages/mcp-server/src/instructions.ts @@ -1,5 +1,6 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +import fs from 'fs/promises'; import { readEnv } from './util'; import { getLogger } from './logger'; @@ -12,33 +13,50 @@ interface InstructionsCacheEntry { const instructionsCache = new Map(); -// Periodically evict stale entries so the cache doesn't grow unboundedly. -const _cacheCleanupInterval = setInterval(() => { +export async function getInstructions({ + stainlessApiKey, + customInstructionsPath, +}: { + stainlessApiKey?: string | undefined; + customInstructionsPath?: string | undefined; +}): Promise { const now = Date.now(); + const cacheKey = customInstructionsPath ?? stainlessApiKey ?? ''; + const cached = instructionsCache.get(cacheKey); + + if (cached && now - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) { + return cached.fetchedInstructions; + } + + // Evict stale entries so the cache doesn't grow unboundedly. for (const [key, entry] of instructionsCache) { if (now - entry.fetchedAt > INSTRUCTIONS_CACHE_TTL_MS) { instructionsCache.delete(key); } } -}, INSTRUCTIONS_CACHE_TTL_MS); -// Don't keep the process alive just for cleanup. -_cacheCleanupInterval.unref(); + let fetchedInstructions: string; -export async function getInstructions(stainlessApiKey: string | undefined): Promise { - const cacheKey = stainlessApiKey ?? ''; - const cached = instructionsCache.get(cacheKey); - - if (cached && Date.now() - cached.fetchedAt <= INSTRUCTIONS_CACHE_TTL_MS) { - return cached.fetchedInstructions; + if (customInstructionsPath) { + fetchedInstructions = await fetchLatestInstructionsFromFile(customInstructionsPath); + } else { + fetchedInstructions = await fetchLatestInstructionsFromApi(stainlessApiKey); } - const fetchedInstructions = await fetchLatestInstructions(stainlessApiKey); - instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: Date.now() }); + instructionsCache.set(cacheKey, { fetchedInstructions, fetchedAt: now }); return fetchedInstructions; } -async function fetchLatestInstructions(stainlessApiKey: string | undefined): Promise { +async function fetchLatestInstructionsFromFile(path: string): Promise { + try { + return await fs.readFile(path, 'utf-8'); + } catch (error) { + getLogger().error({ error, path }, 'Error fetching instructions from file'); + throw error; + } +} + +async function fetchLatestInstructionsFromApi(stainlessApiKey: string | undefined): Promise { // Setting the stainless API key is optional, but may be required // to authenticate requests to the Stainless API. const response = await fetch( diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts new file mode 100644 index 0000000..41a1e7a --- /dev/null +++ b/packages/mcp-server/src/local-docs-search.ts @@ -0,0 +1,378 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +import MiniSearch from 'minisearch'; +import * as fs from 'node:fs/promises'; +import * as path from 'node:path'; +import { getLogger } from './logger'; + +type MethodEntry = { + name: string; + endpoint: string; + httpMethod: string; + summary: string; + description: string; + stainlessPath: string; + qualified: string; + params?: string[]; + response?: string; + markdown?: string; +}; + +type ProseChunk = { + content: string; + tag: string; + sectionContext?: string; + source?: string; +}; + +type MiniSearchDocument = { + id: string; + kind: 'http_method' | 'prose'; + name?: string; + endpoint?: string; + summary?: string; + description?: string; + qualified?: string; + stainlessPath?: string; + content?: string; + sectionContext?: string; + _original: Record; +}; + +type SearchResult = { + results: (string | Record)[]; +}; + +const EMBEDDED_METHODS: MethodEntry[] = [ + { + name: 'create', + endpoint: '/embeddings', + httpMethod: 'post', + summary: 'Embedding', + description: 'Vectorize content with an Isaacus embedding model.', + stainlessPath: '(resource) embeddings > (method) create', + qualified: 'client.embeddings.create', + params: [ + "model: 'kanon-2-embedder';", + 'texts: string[] | string;', + "task?: 'retrieval/query' | 'retrieval/document';", + "overflow_strategy?: 'drop_end';", + 'dimensions?: number;', + ], + response: '{ embeddings: { index: number; embedding: number[]; }[]; usage: { input_tokens: number; }; }', + markdown: + "## create\n\n`client.embeddings.create(model: 'kanon-2-embedder', texts: string[] | string, task?: 'retrieval/query' | 'retrieval/document', overflow_strategy?: 'drop_end', dimensions?: number): { embeddings: object[]; usage: object; }`\n\n**post** `/embeddings`\n\nVectorize content with an Isaacus embedding model.\n\n### Parameters\n\n- `model: 'kanon-2-embedder'`\n The ID of the [model](https://docs.isaacus.com/models#embedding) to use for embedding.\n\n- `texts: string[] | string`\n The text or array of texts to embed.\n\nEach text must contain at least one non-whitespace character.\n\nNo more than 128 texts can be embedded in a single request.\n\n- `task?: 'retrieval/query' | 'retrieval/document'`\n The task the embeddings will be used for.\n\n`retrieval/query` is meant for queries and statements, and `retrieval/document` is meant for anything to be retrieved using query embeddings.\n\nIf `null`, which is the default setting, embeddings will not be optimized for any particular task.\n\n- `overflow_strategy?: 'drop_end'`\n The strategy to employ when content exceeds the model's maximum input length.\n\n`drop_end`, which is the default setting, drops tokens from the end of the content exceeding the limit.\n\nIf `null`, an error will be raised if any content exceeds the model's maximum input length.\n\n- `dimensions?: number`\n A whole number greater than or equal to 1.\n\n### Returns\n\n- `{ embeddings: { index: number; embedding: number[]; }[]; usage: { input_tokens: number; }; }`\n\n - `embeddings: { index: number; embedding: number[]; }[]`\n - `usage: { input_tokens: number; }`\n\n### Example\n\n```typescript\nimport Isaacus from 'isaacus';\n\nconst client = new Isaacus();\n\nconst embeddingResponse = await client.embeddings.create({ model: 'kanon-2-embedder', texts: ['Are restraints of trade enforceable under English law?', 'What is a non-compete clause?'] });\n\nconsole.log(embeddingResponse);\n```", + }, + { + name: 'create', + endpoint: '/classifications/universal', + httpMethod: 'post', + summary: 'Universal classification', + description: 'Classify documents with an Isaacus universal classification model.', + stainlessPath: '(resource) classifications.universal > (method) create', + qualified: 'client.classifications.universal.create', + params: [ + "model: 'kanon-universal-classifier';", + 'query: string;', + 'texts: string[];', + 'is_iql?: boolean;', + "scoring_method?: 'auto' | 'chunk_max' | 'chunk_avg' | 'chunk_min';", + 'chunking_options?: { size?: number; overlap_ratio?: number; overlap_tokens?: number; };', + ], + response: + '{ classifications: { index: number; score: number; chunks: { index: number; start: number; end: number; score: number; text: string; }[]; }[]; usage: { input_tokens: number; }; }', + markdown: + "## create\n\n`client.classifications.universal.create(model: 'kanon-universal-classifier', query: string, texts: string[], is_iql?: boolean, scoring_method?: 'auto' | 'chunk_max' | 'chunk_avg' | 'chunk_min', chunking_options?: { size?: number; overlap_ratio?: number; overlap_tokens?: number; }): { classifications: object[]; usage: object; }`\n\n**post** `/classifications/universal`\n\nClassify documents with an Isaacus universal classification model.\n\n### Parameters\n\n- `model: 'kanon-universal-classifier'`\n The ID of the [model](https://docs.isaacus.com/models#universal-classification) to use for universal classification.\n\n- `query: string`\n The [Isaacus Query Language (IQL)](https://docs.isaacus.com/iql) query or, if IQL is disabled, the statement, to evaluate the texts against.\n\nThe query must contain at least one non-whitespace character.\n\nUnlike the texts being classified, the query cannot be so long that it exceeds the maximum input length of the universal classifier.\n\n- `texts: string[]`\n The texts to classify.\n\nEach text must contain at least one non-whitespace character.\n\n- `is_iql?: boolean`\n Whether the query should be interpreted as an [IQL](https://docs.isaacus.com/iql) query or else as a statement.\n\n- `scoring_method?: 'auto' | 'chunk_max' | 'chunk_avg' | 'chunk_min'`\n The method to use for producing an overall confidence score.\n\n`auto` is the default scoring method and is recommended for most use cases. Currently, it is equivalent to `chunk_max`. In the future, it will automatically select the best method based on the model and inputs.\n\n`chunk_max` uses the highest confidence score of all of the texts' chunks.\n\n`chunk_avg` averages the confidence scores of all of the texts' chunks.\n\n`chunk_min` uses the lowest confidence score of all of the texts' chunks.\n\n- `chunking_options?: { size?: number; overlap_ratio?: number; overlap_tokens?: number; }`\n Options for how to split text into smaller chunks.\n - `size?: number`\n A whole number greater than or equal to 1.\n - `overlap_ratio?: number`\n A number greater than or equal to 0 and less than 1.\n - `overlap_tokens?: number`\n A whole number greater than or equal to 0.\n\n### Returns\n\n- `{ classifications: { index: number; score: number; chunks: { index: number; start: number; end: number; score: number; text: string; }[]; }[]; usage: { input_tokens: number; }; }`\n\n - `classifications: { index: number; score: number; chunks: { index: number; start: number; end: number; score: number; text: string; }[]; }[]`\n - `usage: { input_tokens: number; }`\n\n### Example\n\n```typescript\nimport Isaacus from 'isaacus';\n\nconst client = new Isaacus();\n\nconst universalClassificationResponse = await client.classifications.universal.create({\n model: 'kanon-universal-classifier',\n query: 'This is a confidentiality clause.',\n texts: ['I agree not to tell anyone about the document.'],\n});\n\nconsole.log(universalClassificationResponse);\n```", + }, + { + name: 'create', + endpoint: '/rerankings', + httpMethod: 'post', + summary: 'Reranking', + description: 'Score and rank documents by their relevance to queries with an Isaacus reranker.', + stainlessPath: '(resource) rerankings > (method) create', + qualified: 'client.rerankings.create', + params: [ + "model: 'kanon-2-reranker' | 'kanon-universal-classifier';", + 'query: string;', + 'texts: string[];', + 'top_n?: number;', + 'is_iql?: boolean;', + "scoring_method?: 'auto' | 'chunk_max' | 'chunk_avg' | 'chunk_min';", + 'chunking_options?: { size?: number; overlap_ratio?: number; overlap_tokens?: number; };', + ], + response: '{ results: { index: number; score: number; }[]; usage: { input_tokens: number; }; }', + markdown: + "## create\n\n`client.rerankings.create(model: 'kanon-2-reranker' | 'kanon-universal-classifier', query: string, texts: string[], top_n?: number, is_iql?: boolean, scoring_method?: 'auto' | 'chunk_max' | 'chunk_avg' | 'chunk_min', chunking_options?: { size?: number; overlap_ratio?: number; overlap_tokens?: number; }): { results: object[]; usage: object; }`\n\n**post** `/rerankings`\n\nScore and rank documents by their relevance to queries with an Isaacus reranker.\n\n### Parameters\n\n- `model: 'kanon-2-reranker' | 'kanon-universal-classifier'`\n The ID of the model to use for reranking, being either a [reranking model](https://docs.isaacus.com/models/introduction#reranking) or [universal classification model](https://docs.isaacus.com/models/introduction#universal-classification).\n\n- `query: string`\n The query to evaluate the relevance of the texts to.\n\nThe query must contain at least one non-whitespace character.\n\nUnlike the texts being reranked, the query cannot be so long that it exceeds the maximum input length of the reranker.\n\n- `texts: string[]`\n The texts to rerank.\n\nThere must be at least one text.\n\nEach text must contain at least one non-whitespace character.\n\n- `top_n?: number`\n A whole number greater than or equal to 1.\n\n- `is_iql?: boolean`\n Whether the query should be interpreted as an [Isaacus Query Language (IQL)](https://docs.isaacus.com/iql) query, which is not the case by default.\n\nIf you allow untrusted users to construct their own queries, think carefully before enabling IQL since queries can be crafted to consume an excessively large amount of tokens.\n\n- `scoring_method?: 'auto' | 'chunk_max' | 'chunk_avg' | 'chunk_min'`\n The method to use for producing an overall relevance score for a text that exceeds the model's local context window and has, therefore, been split into multiple chunks.\n\n`auto` is the default scoring method and is recommended for most use cases. Currently, it is equivalent to `chunk_max`. In the future, it will automatically select the best method based on the model and inputs.\n\n`chunk_max` uses the highest relevance score of all of a text's chunks.\n\n`chunk_avg` averages the relevance scores of all of a text's chunks.\n\n`chunk_min` uses the lowest relevance score of all of a text's chunks.\n\n- `chunking_options?: { size?: number; overlap_ratio?: number; overlap_tokens?: number; }`\n Options for how to split text into smaller chunks.\n - `size?: number`\n A whole number greater than or equal to 1.\n - `overlap_ratio?: number`\n A number greater than or equal to 0 and less than 1.\n - `overlap_tokens?: number`\n A whole number greater than or equal to 0.\n\n### Returns\n\n- `{ results: { index: number; score: number; }[]; usage: { input_tokens: number; }; }`\n\n - `results: { index: number; score: number; }[]`\n - `usage: { input_tokens: number; }`\n\n### Example\n\n```typescript\nimport Isaacus from 'isaacus';\n\nconst client = new Isaacus();\n\nconst rerankingResponse = await client.rerankings.create({\n model: 'kanon-2-reranker',\n query: 'What are the essential elements required to establish a negligence claim?',\n texts: ['To form a contract, there must be an offer, acceptance, consideration, and mutual intent to be bound.', 'Criminal cases involve a completely different standard, requiring proof beyond a reasonable doubt.', 'In a negligence claim, the plaintiff must prove duty, breach, causation, and damages.', 'Negligence in tort law requires establishing a duty of care that the defendant owed to the plaintiff.', 'The concept of negligence is central to tort law, with courts assessing whether a breach of duty caused harm.'],\n});\n\nconsole.log(rerankingResponse);\n```", + }, + { + name: 'create', + endpoint: '/extractions/qa', + httpMethod: 'post', + summary: 'Extractive question answering', + description: 'Extract information from documents with an Isaacus extractive question answering model.', + stainlessPath: '(resource) extractions.qa > (method) create', + qualified: 'client.extractions.qa.create', + params: [ + "model: 'kanon-answer-extractor';", + 'query: string;', + 'texts: string[];', + 'ignore_inextractability?: boolean;', + 'top_k?: number;', + 'chunking_options?: { size?: number; overlap_ratio?: number; overlap_tokens?: number; };', + ], + response: + '{ extractions: { index: number; answers: { text: string; start: number; end: number; score: number; }[]; inextractability_score: number; }[]; usage: { input_tokens: number; }; }', + markdown: + "## create\n\n`client.extractions.qa.create(model: 'kanon-answer-extractor', query: string, texts: string[], ignore_inextractability?: boolean, top_k?: number, chunking_options?: { size?: number; overlap_ratio?: number; overlap_tokens?: number; }): { extractions: object[]; usage: object; }`\n\n**post** `/extractions/qa`\n\nExtract information from documents with an Isaacus extractive question answering model.\n\n### Parameters\n\n- `model: 'kanon-answer-extractor'`\n The ID of the [model](https://docs.isaacus.com/models#extractive-question-answering) to use for extractive question answering.\n\n- `query: string`\n The query to extract the answer to.\n\nThe query must contain at least one non-whitespace character.\n\nUnlike the texts from which the answer will be extracted, the query cannot be so long that it exceeds the maximum input length of the model.\n\n- `texts: string[]`\n The texts to search for the answer in and extract the answer from.\n\nThere must be at least one text.\n\nEach text must contain at least one non-whitespace character.\n\n- `ignore_inextractability?: boolean`\n Whether to, if the model's score of the likelihood that an answer can not be extracted from a text is greater than the highest score of all possible answers, still return the highest scoring answers for that text.\n\nIf you have already determined that the texts answer the query, for example, by using one of our classification or reranker models, then you should set this to `true`.\n\n- `top_k?: number`\n The number of highest scoring answers to return.\n\nIf `null`, which is the default, all answers will be returned.\n\n- `chunking_options?: { size?: number; overlap_ratio?: number; overlap_tokens?: number; }`\n Options for how to split text into smaller chunks.\n - `size?: number`\n A whole number greater than or equal to 1.\n - `overlap_ratio?: number`\n A number greater than or equal to 0 and less than 1.\n - `overlap_tokens?: number`\n A whole number greater than or equal to 0.\n\n### Returns\n\n- `{ extractions: { index: number; answers: { text: string; start: number; end: number; score: number; }[]; inextractability_score: number; }[]; usage: { input_tokens: number; }; }`\n\n - `extractions: { index: number; answers: { text: string; start: number; end: number; score: number; }[]; inextractability_score: number; }[]`\n - `usage: { input_tokens: number; }`\n\n### Example\n\n```typescript\nimport Isaacus from 'isaacus';\n\nconst client = new Isaacus();\n\nconst answerExtractionResponse = await client.extractions.qa.create({\n model: 'kanon-answer-extractor',\n query: 'What is the punishment for murder in Victoria?',\n texts: ['The standard sentence for murder in the State of Victoria is 30 years if the person murdered was a police officer and 25 years in any other case.'],\n});\n\nconsole.log(answerExtractionResponse);\n```", + }, + { + name: 'create', + endpoint: '/enrichments', + httpMethod: 'post', + summary: 'Enrichment', + description: 'Enrich documents with an Isaacus enrichment model.', + stainlessPath: '(resource) enrichments > (method) create', + qualified: 'client.enrichments.create', + params: [ + "model: 'kanon-2-enricher';", + 'texts: string[] | string;', + "overflow_strategy?: 'auto' | 'drop_end' | 'chunk';", + ], + response: '{ results: { index: number; document: object; }[]; usage: { input_tokens: number; }; }', + markdown: + "## create\n\n`client.enrichments.create(model: 'kanon-2-enricher', texts: string[] | string, overflow_strategy?: 'auto' | 'drop_end' | 'chunk'): { results: object[]; usage: object; }`\n\n**post** `/enrichments`\n\nEnrich documents with an Isaacus enrichment model.\n\n### Parameters\n\n- `model: 'kanon-2-enricher'`\n The ID of the [model](https://docs.isaacus.com/models#enrichment) to use for enrichment.\n\n- `texts: string[] | string`\n A text or array of texts to be enriched, each containing at least one non-whitespace character.\n\nNo more than 8 texts can be enriched in a single request.\n\n- `overflow_strategy?: 'auto' | 'drop_end' | 'chunk'`\n The strategy for handling content exceeding the model's maximum input length.\n\n`auto`, which is the recommended setting, currently behaves the same as `chunk`, which intelligently breaks the input up into smaller chunks and then stitches the results back together into a single prediction. In the future `auto` may implement even more sophisticated strategies for handling long contexts such as leveraging chunk overlap and/or a specialized stitching model.\n\n`chunk` breaks the input up into smaller chunks that fit within the model's context window and then intelligently merges the results into a single prediction at the cost of a minor accuracy drop.\n\n`drop_end` drops tokens from the end of input exceeding the model's maximum input length.\n\n`null`, which is the default setting, raises an error if the input exceeds the model's maximum input length.\n\n### Returns\n\n- `{ results: { index: number; document: object; }[]; usage: { input_tokens: number; }; }`\n\n - `results: { index: number; document: { text: string; title: object; subtitle: object; type: 'statute' | 'regulation' | 'decision' | 'contract' | 'other'; jurisdiction: string; segments: object[]; crossreferences: object[]; locations: object[]; persons: object[]; emails: object[]; websites: object[]; phone_numbers: object[]; id_numbers: object[]; terms: object[]; external_documents: object[]; quotes: object[]; dates: object[]; headings: object[]; junk: object[]; version: 'ilgs@1'; }; }[]`\n - `usage: { input_tokens: number; }`\n\n### Example\n\n```typescript\nimport Isaacus from 'isaacus';\n\nconst client = new Isaacus();\n\nconst enrichmentResponse = await client.enrichments.create({ model: 'kanon-2-enricher', texts: ['1.5 You (the \"User\") agree to be bound by these Terms.'] });\n\nconsole.log(enrichmentResponse);\n```", + }, +]; + +const INDEX_OPTIONS = { + fields: [ + 'name', + 'endpoint', + 'summary', + 'description', + 'qualified', + 'stainlessPath', + 'content', + 'sectionContext', + ], + storeFields: ['kind', '_original'], + searchOptions: { + prefix: true, + fuzzy: 0.2, + boost: { + name: 3, + endpoint: 2, + summary: 2, + qualified: 2, + content: 1, + } as Record, + }, +}; + +/** + * Self-contained local search engine backed by MiniSearch. + * Method data is embedded at SDK build time; prose documents + * can be loaded from an optional docs directory at runtime. + */ +export class LocalDocsSearch { + private methodIndex: MiniSearch; + private proseIndex: MiniSearch; + + private constructor() { + this.methodIndex = new MiniSearch(INDEX_OPTIONS); + this.proseIndex = new MiniSearch(INDEX_OPTIONS); + } + + static async create(opts?: { docsDir?: string }): Promise { + const instance = new LocalDocsSearch(); + instance.indexMethods(EMBEDDED_METHODS); + if (opts?.docsDir) { + await instance.loadDocsDirectory(opts.docsDir); + } + return instance; + } + + // Note: Language is accepted for interface consistency with remote search, but currently has no + // effect since this local search only supports TypeScript docs. + search(props: { + query: string; + language?: string; + detail?: string; + maxResults?: number; + maxLength?: number; + }): SearchResult { + const { query, detail = 'default', maxResults = 5, maxLength = 100_000 } = props; + + const useMarkdown = detail === 'verbose' || detail === 'high'; + + // Search both indices and merge results by score + const methodHits = this.methodIndex + .search(query) + .map((hit) => ({ ...hit, _kind: 'http_method' as const })); + const proseHits = this.proseIndex.search(query).map((hit) => ({ ...hit, _kind: 'prose' as const })); + const merged = [...methodHits, ...proseHits].sort((a, b) => b.score - a.score); + const top = merged.slice(0, maxResults); + + const fullResults: (string | Record)[] = []; + + for (const hit of top) { + const original = (hit as Record)['_original']; + if (hit._kind === 'http_method') { + const m = original as MethodEntry; + if (useMarkdown && m.markdown) { + fullResults.push(m.markdown); + } else { + fullResults.push({ + method: m.qualified, + summary: m.summary, + description: m.description, + endpoint: `${m.httpMethod.toUpperCase()} ${m.endpoint}`, + ...(m.params ? { params: m.params } : {}), + ...(m.response ? { response: m.response } : {}), + }); + } + } else { + const c = original as ProseChunk; + fullResults.push({ + content: c.content, + ...(c.source ? { source: c.source } : {}), + }); + } + } + + let totalLength = 0; + const results: (string | Record)[] = []; + for (const result of fullResults) { + const len = typeof result === 'string' ? result.length : JSON.stringify(result).length; + totalLength += len; + if (totalLength > maxLength) break; + results.push(result); + } + + if (results.length < fullResults.length) { + results.unshift(`Truncated; showing ${results.length} of ${fullResults.length} results.`); + } + + return { results }; + } + + private indexMethods(methods: MethodEntry[]): void { + const docs: MiniSearchDocument[] = methods.map((m, i) => ({ + id: `method-${i}`, + kind: 'http_method' as const, + name: m.name, + endpoint: m.endpoint, + summary: m.summary, + description: m.description, + qualified: m.qualified, + stainlessPath: m.stainlessPath, + _original: m as unknown as Record, + })); + if (docs.length > 0) { + this.methodIndex.addAll(docs); + } + } + + private async loadDocsDirectory(docsDir: string): Promise { + let entries; + try { + entries = await fs.readdir(docsDir, { withFileTypes: true }); + } catch (err) { + getLogger().warn({ err, docsDir }, 'Could not read docs directory'); + return; + } + + const files = entries + .filter((e) => e.isFile()) + .filter((e) => e.name.endsWith('.md') || e.name.endsWith('.markdown') || e.name.endsWith('.json')); + + for (const file of files) { + try { + const filePath = path.join(docsDir, file.name); + const content = await fs.readFile(filePath, 'utf-8'); + + if (file.name.endsWith('.json')) { + const texts = extractTexts(JSON.parse(content)); + if (texts.length > 0) { + this.indexProse(texts.join('\n\n'), file.name); + } + } else { + this.indexProse(content, file.name); + } + } catch (err) { + getLogger().warn({ err, file: file.name }, 'Failed to index docs file'); + } + } + } + + private indexProse(markdown: string, source: string): void { + const chunks = chunkMarkdown(markdown); + const baseId = this.proseIndex.documentCount; + + const docs: MiniSearchDocument[] = chunks.map((chunk, i) => ({ + id: `prose-${baseId + i}`, + kind: 'prose' as const, + content: chunk.content, + ...(chunk.sectionContext != null ? { sectionContext: chunk.sectionContext } : {}), + _original: { ...chunk, source } as unknown as Record, + })); + + if (docs.length > 0) { + this.proseIndex.addAll(docs); + } + } +} + +/** Lightweight markdown chunker — splits on headers, chunks by word count. */ +function chunkMarkdown(markdown: string): { content: string; tag: string; sectionContext?: string }[] { + // Strip YAML frontmatter + const stripped = markdown.replace(/^---\n[\s\S]*?\n---\n?/, ''); + const lines = stripped.split('\n'); + + const chunks: { content: string; tag: string; sectionContext?: string }[] = []; + const headers: string[] = []; + let current: string[] = []; + + const flush = () => { + const text = current.join('\n').trim(); + if (!text) return; + const sectionContext = headers.length > 0 ? headers.join(' > ') : undefined; + // Split into ~200-word chunks + const words = text.split(/\s+/); + for (let i = 0; i < words.length; i += 200) { + const slice = words.slice(i, i + 200).join(' '); + if (slice) { + chunks.push({ content: slice, tag: 'p', ...(sectionContext != null ? { sectionContext } : {}) }); + } + } + current = []; + }; + + for (const line of lines) { + const headerMatch = line.match(/^(#{1,6})\s+(.+)/); + if (headerMatch) { + flush(); + const level = headerMatch[1]!.length; + const text = headerMatch[2]!.trim(); + while (headers.length >= level) headers.pop(); + headers.push(text); + } else { + current.push(line); + } + } + flush(); + + return chunks; +} + +/** Recursively extracts string values from a JSON structure. */ +function extractTexts(data: unknown, depth = 0): string[] { + if (depth > 10) return []; + if (typeof data === 'string') return data.trim() ? [data] : []; + if (Array.isArray(data)) return data.flatMap((item) => extractTexts(item, depth + 1)); + if (typeof data === 'object' && data !== null) { + return Object.values(data).flatMap((v) => extractTexts(v, depth + 1)); + } + return []; +} diff --git a/packages/mcp-server/src/options.ts b/packages/mcp-server/src/options.ts index b9e8e8a..f151876 100644 --- a/packages/mcp-server/src/options.ts +++ b/packages/mcp-server/src/options.ts @@ -18,10 +18,13 @@ export type McpOptions = { includeCodeTool?: boolean | undefined; includeDocsTools?: boolean | undefined; stainlessApiKey?: string | undefined; + docsSearchMode?: 'stainless-api' | 'local' | undefined; + docsDir?: string | undefined; codeAllowHttpGets?: boolean | undefined; codeAllowedMethods?: string[] | undefined; codeBlockedMethods?: string[] | undefined; codeExecutionMode: McpCodeExecutionMode; + customInstructionsPath?: string | undefined; }; export type McpCodeExecutionMode = 'stainless-sandbox' | 'local'; @@ -52,7 +55,23 @@ export function parseCLIOptions(): CLIOptions { description: "Where to run code execution in code tool; 'stainless-sandbox' will execute code in Stainless-hosted sandboxes whereas 'local' will execute code locally on the MCP server machine.", }) + .option('custom-instructions-path', { + type: 'string', + description: 'Path to custom instructions for the MCP server', + }) .option('debug', { type: 'boolean', description: 'Enable debug logging' }) + .option('docs-dir', { + type: 'string', + description: + 'Path to a directory of local documentation files (markdown/JSON) to include in local docs search.', + }) + .option('docs-search-mode', { + type: 'string', + choices: ['stainless-api', 'local'], + default: 'stainless-api', + description: + "Where to search documentation; 'stainless-api' uses the Stainless-hosted search API whereas 'local' uses an in-memory search index built from embedded SDK method data and optional local docs files.", + }) .option('log-format', { type: 'string', choices: ['json', 'pretty'], @@ -113,10 +132,13 @@ export function parseCLIOptions(): CLIOptions { ...(includeDocsTools !== undefined && { includeDocsTools }), debug: !!argv.debug, stainlessApiKey: argv.stainlessApiKey, + docsSearchMode: argv.docsSearchMode as 'stainless-api' | 'local' | undefined, + docsDir: argv.docsDir, codeAllowHttpGets: argv.codeAllowHttpGets, codeAllowedMethods: argv.codeAllowedMethods, codeBlockedMethods: argv.codeBlockedMethods, codeExecutionMode: argv.codeExecutionMode as McpCodeExecutionMode, + customInstructionsPath: argv.customInstructionsPath, transport, logFormat, port: argv.port, @@ -157,5 +179,7 @@ export function parseQueryOptions(defaultOptions: McpOptions, query: unknown): M ...(codeTool !== undefined && { includeCodeTool: codeTool }), ...(docsTools !== undefined && { includeDocsTools: docsTools }), codeExecutionMode: defaultOptions.codeExecutionMode, + docsSearchMode: defaultOptions.docsSearchMode, + docsDir: defaultOptions.docsDir, }; } diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 7df14f6..80ff2cd 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -11,19 +11,27 @@ import { ClientOptions } from 'isaacus'; import Isaacus from 'isaacus'; import { codeTool } from './code-tool'; import docsSearchTool from './docs-search-tool'; +import { setLocalSearch } from './docs-search-tool'; +import { LocalDocsSearch } from './local-docs-search'; import { getInstructions } from './instructions'; import { McpOptions } from './options'; import { blockedMethodsForCodeTool } from './methods'; import { HandlerFunction, McpRequestContext, ToolCallResult, McpTool } from './types'; -export const newMcpServer = async (stainlessApiKey: string | undefined) => +export const newMcpServer = async ({ + stainlessApiKey, + customInstructionsPath, +}: { + stainlessApiKey?: string | undefined; + customInstructionsPath?: string | undefined; +}) => new McpServer( { name: 'isaacus_api', - version: '0.22.0', + version: '0.22.1', }, { - instructions: await getInstructions(stainlessApiKey), + instructions: await getInstructions({ stainlessApiKey, customInstructionsPath }), capabilities: { tools: {}, logging: {} }, }, ); @@ -37,6 +45,7 @@ export async function initMcpServer(params: { clientOptions?: ClientOptions; mcpOptions?: McpOptions; stainlessApiKey?: string | undefined; + upstreamClientEnvs?: Record | undefined; }) { const server = params.server instanceof McpServer ? params.server.server : params.server; @@ -55,6 +64,12 @@ export async function initMcpServer(params: { error: logAtLevel('error'), }; + if (params.mcpOptions?.docsSearchMode === 'local') { + const docsDir = params.mcpOptions?.docsDir; + const localSearch = await LocalDocsSearch.create(docsDir ? { docsDir } : undefined); + setLocalSearch(localSearch); + } + let _client: Isaacus | undefined; let _clientError: Error | undefined; let _logLevel: 'debug' | 'info' | 'warn' | 'error' | 'off' | undefined; @@ -118,6 +133,7 @@ export async function initMcpServer(params: { reqContext: { client, stainlessApiKey: params.stainlessApiKey ?? params.mcpOptions?.stainlessApiKey, + upstreamClientEnvs: params.upstreamClientEnvs, }, args, }); diff --git a/packages/mcp-server/src/stdio.ts b/packages/mcp-server/src/stdio.ts index e8bcbb1..b04a544 100644 --- a/packages/mcp-server/src/stdio.ts +++ b/packages/mcp-server/src/stdio.ts @@ -4,7 +4,10 @@ import { initMcpServer, newMcpServer } from './server'; import { getLogger } from './logger'; export const launchStdioServer = async (mcpOptions: McpOptions) => { - const server = await newMcpServer(mcpOptions.stainlessApiKey); + const server = await newMcpServer({ + stainlessApiKey: mcpOptions.stainlessApiKey, + customInstructionsPath: mcpOptions.customInstructionsPath, + }); await initMcpServer({ server, mcpOptions, stainlessApiKey: mcpOptions.stainlessApiKey }); diff --git a/packages/mcp-server/src/types.ts b/packages/mcp-server/src/types.ts index 3fa4498..d1f4d8c 100644 --- a/packages/mcp-server/src/types.ts +++ b/packages/mcp-server/src/types.ts @@ -45,6 +45,7 @@ export type ToolCallResult = { export type McpRequestContext = { client: Isaacus; stainlessApiKey?: string | undefined; + upstreamClientEnvs?: Record | undefined; }; export type HandlerFunction = ({ diff --git a/packages/mcp-server/yarn.lock b/packages/mcp-server/yarn.lock index fe10277..c7e3769 100644 --- a/packages/mcp-server/yarn.lock +++ b/packages/mcp-server/yarn.lock @@ -297,61 +297,101 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": +"@eslint-community/eslint-utils@^4.4.0", "@eslint-community/eslint-utils@^4.8.0": version "4.9.1" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz#4e90af67bc51ddee6cdef5284edf572ec376b595" integrity sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ== dependencies: eslint-visitor-keys "^3.4.3" -"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": version "4.12.2" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== -"@eslint/eslintrc@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" - integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== +"@eslint/config-array@^0.21.2": + version "0.21.2" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.2.tgz#f29e22057ad5316cf23836cee9a34c81fffcb7e6" + integrity sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw== dependencies: - ajv "^6.12.4" + "@eslint/object-schema" "^2.1.7" + debug "^4.3.1" + minimatch "^3.1.5" + +"@eslint/config-helpers@^0.4.2": + version "0.4.2" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.2.tgz#1bd006ceeb7e2e55b2b773ab318d300e1a66aeda" + integrity sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw== + dependencies: + "@eslint/core" "^0.17.0" + +"@eslint/core@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.17.0.tgz#77225820413d9617509da9342190a2019e78761c" + integrity sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.3.5": + version "3.3.5" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.5.tgz#c131793cfc1a7b96f24a83e0a8bbd4b881558c60" + integrity sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg== + dependencies: + ajv "^6.14.0" debug "^4.3.2" - espree "^9.6.0" - globals "^13.19.0" + espree "^10.0.1" + globals "^14.0.0" ignore "^5.2.0" import-fresh "^3.2.1" - js-yaml "^4.1.0" - minimatch "^3.1.2" + js-yaml "^4.1.1" + minimatch "^3.1.5" strip-json-comments "^3.1.1" -"@eslint/js@8.57.1": - version "8.57.1" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2" - integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q== +"@eslint/js@9.39.4": + version "9.39.4" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.39.4.tgz#a3f83bfc6fd9bf33a853dfacd0b49b398eb596c1" + integrity sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw== -"@hono/node-server@^1.19.7": - version "1.19.9" - resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.19.9.tgz#8f37119b1acf283fd3f6035f3d1356fdb97a09ac" - integrity sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw== +"@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== -"@humanwhocodes/config-array@^0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748" - integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw== +"@eslint/plugin-kit@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz#9779e3fd9b7ee33571a57435cf4335a1794a6cb2" + integrity sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA== dependencies: - "@humanwhocodes/object-schema" "^2.0.3" - debug "^4.3.1" - minimatch "^3.0.5" + "@eslint/core" "^0.17.0" + levn "^0.4.1" + +"@hono/node-server@^1.19.10", "@hono/node-server@^1.19.9": + version "1.19.11" + resolved "https://registry.yarnpkg.com/@hono/node-server/-/node-server-1.19.11.tgz#dc419f0826dd2504e9fc86ad289d5636a0444e2f" + integrity sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g== + +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.7.tgz#822cb7b3a12c5a240a24f621b5a2413e27a45f26" + integrity sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.4.0" "@humanwhocodes/module-importer@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.3": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" - integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== +"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@inquirer/checkbox@^3.0.1": version "3.0.1" @@ -741,12 +781,12 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@modelcontextprotocol/sdk@^1.25.2": - version "1.25.2" - resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.25.2.tgz#2284560b4e044b4ce5f328ee180931110cb8c5cf" - integrity sha512-LZFeo4F9M5qOhC/Uc1aQSrBHxMrvxett+9KLHt7OhcExtoiRN9DKgbZffMP/nxjutWDQpfMDfP3nkHI4X9ijww== +"@modelcontextprotocol/sdk@^1.27.1": + version "1.27.1" + resolved "https://registry.yarnpkg.com/@modelcontextprotocol/sdk/-/sdk-1.27.1.tgz#a602cf823bf8a68e13e7112f50aeb02b09fb83b9" + integrity sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA== dependencies: - "@hono/node-server" "^1.19.7" + "@hono/node-server" "^1.19.9" ajv "^8.17.1" ajv-formats "^3.0.1" content-type "^1.0.5" @@ -754,14 +794,15 @@ cross-spawn "^7.0.5" eventsource "^3.0.2" eventsource-parser "^3.0.0" - express "^5.0.1" - express-rate-limit "^7.5.0" - jose "^6.1.1" + express "^5.2.1" + express-rate-limit "^8.2.1" + hono "^4.11.4" + jose "^6.1.3" json-schema-typed "^8.0.2" pkce-challenge "^5.0.0" raw-body "^3.0.0" zod "^3.25 || ^4.0" - zod-to-json-schema "^3.25.0" + zod-to-json-schema "^3.25.1" "@nodelib/fs.scandir@2.1.5": version "2.1.5" @@ -776,7 +817,7 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== -"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": +"@nodelib/fs.walk@^1.2.3": version "1.2.8" resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== @@ -784,6 +825,11 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@pinojs/redact@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@pinojs/redact/-/redact-0.4.0.tgz#c3de060dd12640dcc838516aa2a6803cc7b2e9d6" + integrity sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg== + "@pkgr/core@^0.2.9": version "0.2.9" resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" @@ -886,6 +932,11 @@ dependencies: "@types/node" "*" +"@types/cookie-parser@^1.4.10": + version "1.4.10" + resolved "https://registry.yarnpkg.com/@types/cookie-parser/-/cookie-parser-1.4.10.tgz#a045272a383a30597a01955d4f9c790018f214e4" + integrity sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg== + "@types/cors@^2.8.19": version "2.8.19" resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.19.tgz#d93ea2673fd8c9f697367f5eeefc2bbfa94f0342" @@ -893,6 +944,11 @@ dependencies: "@types/node" "*" +"@types/estree@^1.0.6": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + "@types/express-serve-static-core@^5.0.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz#1a77faffee9572d39124933259be2523837d7eaa" @@ -951,6 +1007,11 @@ expect "^29.0.0" pretty-format "^29.0.0" +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/mute-stream@^0.0.4": version "0.0.4" resolved "https://registry.yarnpkg.com/@types/mute-stream/-/mute-stream-0.0.4.tgz#77208e56a08767af6c5e1237be8888e2f255c478" @@ -1100,11 +1161,6 @@ "@typescript-eslint/types" "8.31.1" eslint-visitor-keys "^4.2.0" -"@ungap/structured-clone@^1.2.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" - integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== - "@valtown/deno-http-worker@^0.0.21": version "0.0.21" resolved "https://registry.yarnpkg.com/@valtown/deno-http-worker/-/deno-http-worker-0.0.21.tgz#9ce3b5c1d0db211fe7ea8297881fe551838474ad" @@ -1130,11 +1186,16 @@ acorn-walk@^8.1.1: dependencies: acorn "^8.11.0" -acorn@^8.11.0, acorn@^8.4.1, acorn@^8.9.0: +acorn@^8.11.0, acorn@^8.4.1: version "8.15.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== +acorn@^8.15.0: + version "8.16.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.16.0.tgz#4ce79c89be40afe7afe8f3adb902a1f1ce9ac08a" + integrity sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw== + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -1150,10 +1211,10 @@ ajv-formats@^3.0.1: dependencies: ajv "^8.0.0" -ajv@^6.12.4: - version "6.12.6" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" - integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== +ajv@^6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a" + integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" @@ -1170,6 +1231,16 @@ ajv@^8.0.0, ajv@^8.17.1: json-schema-traverse "^1.0.0" require-from-string "^2.0.2" +ajv@^8.18.0: + version "8.18.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.18.0.tgz#8864186b6738d003eb3a933172bb3833e10cefbc" + integrity sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A== + dependencies: + fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + ansi-escapes@^4.2.1, ansi-escapes@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -1219,6 +1290,11 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -1474,6 +1550,11 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^2.0.7: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + commander@^13.1.0: version "13.1.0" resolved "https://registry.yarnpkg.com/commander/-/commander-13.1.0.tgz#776167db68c78f38dcce1f9b8d7b8b9a488abf46" @@ -1499,12 +1580,25 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie-parser@^1.4.6: + version "1.4.7" + resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.7.tgz#e2125635dfd766888ffe90d60c286404fa0e7b26" + integrity sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw== + dependencies: + cookie "0.7.2" + cookie-signature "1.0.6" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + cookie-signature@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== -cookie@^0.7.1: +cookie@0.7.2, cookie@^0.7.1: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -1535,7 +1629,7 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.5: +cross-spawn@^7.0.3, cross-spawn@^7.0.5, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -1544,6 +1638,11 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.5: shebang-command "^2.0.0" which "^2.0.1" +dateformat@^4.6.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-4.6.3.tgz#556fa6497e5217fedb78821424f8a1c22fa3f4b5" + integrity sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA== + debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.7, debug@^4.4.0, debug@^4.4.3: version "4.4.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" @@ -1586,13 +1685,6 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - dunder-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" @@ -1627,6 +1719,13 @@ encodeurl@^2.0.0: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== +end-of-stream@^1.1.0: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + error-ex@^1.3.1: version "1.3.4" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" @@ -1671,7 +1770,7 @@ escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -eslint-plugin-prettier@^5.0.1: +eslint-plugin-prettier@^5.4.1: version "5.5.5" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz#9eae11593faa108859c26f9a9c367d619a0769c0" integrity sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw== @@ -1679,95 +1778,84 @@ eslint-plugin-prettier@^5.0.1: prettier-linter-helpers "^1.0.1" synckit "^0.11.12" -eslint-plugin-unused-imports@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-3.2.0.tgz#63a98c9ad5f622cd9f830f70bc77739f25ccfe0d" - integrity sha512-6uXyn6xdINEpxE1MtDjxQsyXB37lfyO2yKGVVgtD7WEWQGORSOZjgrD6hBhvGv4/SO+TOlS+UnC6JppRqbuwGQ== - dependencies: - eslint-rule-composer "^0.3.0" - -eslint-rule-composer@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz#79320c927b0c5c0d3d3d2b76c8b4a488f25bbaf9" - integrity sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg== +eslint-plugin-unused-imports@^4.1.4: + version "4.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-unused-imports/-/eslint-plugin-unused-imports-4.4.1.tgz#a831f0a2937d7631eba30cb87091ab7d3a5da0e1" + integrity sha512-oZGYUz1X3sRMGUB+0cZyK2VcvRX5lm/vB56PgNNcU+7ficUCKm66oZWKUubXWnOuPjQ8PvmXtCViXBMONPe7tQ== -eslint-scope@^7.2.2: - version "7.2.2" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" - integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== dependencies: esrecurse "^4.3.0" estraverse "^5.2.0" -eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint-visitor-keys@^4.2.0: +eslint-visitor-keys@^4.2.0, eslint-visitor-keys@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== -eslint@^8.49.0: - version "8.57.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9" - integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA== - dependencies: - "@eslint-community/eslint-utils" "^4.2.0" - "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.1" - "@humanwhocodes/config-array" "^0.13.0" +eslint@^9.39.1: + version "9.39.4" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.4.tgz#855da1b2e2ad66dc5991195f35e262bcec8117b5" + integrity sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ== + dependencies: + "@eslint-community/eslint-utils" "^4.8.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.21.2" + "@eslint/config-helpers" "^0.4.2" + "@eslint/core" "^0.17.0" + "@eslint/eslintrc" "^3.3.5" + "@eslint/js" "9.39.4" + "@eslint/plugin-kit" "^0.4.1" + "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" - "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" - ajv "^6.12.4" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + ajv "^6.14.0" chalk "^4.0.0" - cross-spawn "^7.0.2" + cross-spawn "^7.0.6" debug "^4.3.2" - doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" - esquery "^1.4.2" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" + esquery "^1.5.0" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" + file-entry-cache "^8.0.0" find-up "^5.0.0" glob-parent "^6.0.2" - globals "^13.19.0" - graphemer "^1.4.0" ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" - is-path-inside "^3.0.3" - js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.4.1" lodash.merge "^4.6.2" - minimatch "^3.1.2" + minimatch "^3.1.5" natural-compare "^1.4.0" optionator "^0.9.3" - strip-ansi "^6.0.1" - text-table "^0.2.0" -espree@^9.6.0, espree@^9.6.1: - version "9.6.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" - integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== +espree@^10.0.1, espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== dependencies: - acorn "^8.9.0" + acorn "^8.15.0" acorn-jsx "^5.3.2" - eslint-visitor-keys "^3.4.1" + eslint-visitor-keys "^4.2.1" esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.4.2: +esquery@^1.5.0: version "1.7.0" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.7.0.tgz#08d048f261f0ddedb5bae95f46809463d9c9496d" integrity sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g== @@ -1839,12 +1927,14 @@ expect@^29.0.0, expect@^29.7.0: jest-message-util "^29.7.0" jest-util "^29.7.0" -express-rate-limit@^7.5.0: - version "7.5.1" - resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-7.5.1.tgz#8c3a42f69209a3a1c969890070ece9e20a879dec" - integrity sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw== +express-rate-limit@^8.2.1: + version "8.3.1" + resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-8.3.1.tgz#0aaba098eadd40f6737f30a98e6b16fa1a29edfb" + integrity sha512-D1dKN+cmyPWuvB+G2SREQDzPY1agpBIcTa9sJxOPMCNeH3gwzhqJRDWCXW3gg0y//+LQ/8j52JbMROWyrKdMdw== + dependencies: + ip-address "10.1.0" -express@^5.0.1, express@^5.1.0: +express@^5.1.0, express@^5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/express/-/express-5.2.1.tgz#8f21d15b6d327f92b4794ecf8cb08a72f956ac04" integrity sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw== @@ -1887,6 +1977,11 @@ external-editor@^3.1.0: iconv-lite "^0.4.24" tmp "^0.0.33" +fast-copy@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-4.0.2.tgz#57f14115e1edbec274f69090072a480aa29cbedd" + integrity sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1918,6 +2013,11 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-safe-stringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" + integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== + fast-uri@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.1.0.tgz#66eecff6c764c0df9b762e62ca7edcfb53b4edfa" @@ -1942,12 +2042,12 @@ fflate@^0.8.2: resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: - flat-cache "^3.0.4" + flat-cache "^4.0.0" fill-range@^7.1.1: version "7.1.1" @@ -1984,14 +2084,13 @@ find-up@^5.0.0: locate-path "^6.0.0" path-exists "^4.0.0" -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== dependencies: flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" + keyv "^4.5.4" flatted@^3.2.9: version "3.3.3" @@ -2129,12 +2228,10 @@ glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^13.19.0: - version "13.24.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171" - integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ== - dependencies: - type-fest "^0.20.2" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== gopd@^1.2.0: version "1.2.0" @@ -2180,6 +2277,16 @@ hasown@^2.0.2: dependencies: function-bind "^1.1.2" +help-me@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/help-me/-/help-me-5.0.0.tgz#b1ebe63b967b74060027c2ac61f9be12d354a6f6" + integrity sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg== + +hono@^4.11.4, hono@^4.12.4: + version "4.12.7" + resolved "https://registry.yarnpkg.com/hono/-/hono-4.12.7.tgz#ca000956e965c2b3d791e43540498e616d6c6442" + integrity sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -2264,6 +2371,11 @@ inherits@2, inherits@^2.0.3, inherits@~2.0.4: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ip-address@10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-10.1.0.tgz#d8dcffb34d0e02eb241427444a6e23f5b0595aa4" + integrity sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q== + ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" @@ -2308,11 +2420,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-path-inside@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" - integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== - is-promise@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" @@ -2739,10 +2846,15 @@ jest@^29.4.0: import-local "^3.0.2" jest-cli "^29.7.0" -jose@^6.1.1: - version "6.1.3" - resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.3.tgz#8453d7be88af7bb7d64a0481d6a35a0145ba3ea5" - integrity sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ== +jose@^6.1.3: + version "6.2.1" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.2.1.tgz#7a6b1de83816deaee9055a558e1278a7b2b9ea1b" + integrity sha512-jUaKr1yrbfaImV7R2TN/b3IcZzsw38/chqMpo2XJ7i2F8AfM/lA4G1goC3JVEwg0H7UldTmSt3P68nt31W7/mw== + +joycon@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03" + integrity sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw== "jq-web@https://github.com/stainless-api/jq-web/releases/download/v0.8.8/jq-web.tar.gz": version "0.8.8" @@ -2761,7 +2873,7 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: +js-yaml@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== @@ -2817,7 +2929,7 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -keyv@^4.5.3: +keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -2947,10 +3059,10 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.5.tgz#580c88f8d5445f2bd6aa8f3cadefa0de79fbd69e" + integrity sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w== dependencies: brace-expansion "^1.1.7" @@ -3040,6 +3152,11 @@ object-inspect@^1.13.3: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -3047,7 +3164,7 @@ on-finished@^2.4.1: dependencies: ee-first "1.1.1" -once@^1.3.0, once@^1.4.0: +once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== @@ -3187,6 +3304,64 @@ picomatch@^2.0.4, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pino-abstract-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz#b21e5f33a297e8c4c915c62b3ce5dd4a87a52c23" + integrity sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg== + dependencies: + split2 "^4.0.0" + +pino-http@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-11.0.0.tgz#ebadef4694fc59aadab9be7e5939aea625b4615f" + integrity sha512-wqg5XIAGRRIWtTk8qPGxkbrfiwEWz1lgedVLvhLALudKXvg1/L2lTFgTGPJ4Z2e3qcRmxoFxDuSdMdMGNM6I1g== + dependencies: + get-caller-file "^2.0.5" + pino "^10.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + +pino-pretty@^13.1.3: + version "13.1.3" + resolved "https://registry.yarnpkg.com/pino-pretty/-/pino-pretty-13.1.3.tgz#2274cccda925dd355c104079a5029f6598d0381b" + integrity sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg== + dependencies: + colorette "^2.0.7" + dateformat "^4.6.3" + fast-copy "^4.0.0" + fast-safe-stringify "^2.1.1" + help-me "^5.0.0" + joycon "^3.1.1" + minimist "^1.2.6" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pump "^3.0.0" + secure-json-parse "^4.0.0" + sonic-boom "^4.0.1" + strip-json-comments "^5.0.2" + +pino-std-serializers@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz#a7b0cd65225f29e92540e7853bd73b07479893fc" + integrity sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw== + +pino@^10.0.0, pino@^10.3.1: + version "10.3.1" + resolved "https://registry.yarnpkg.com/pino/-/pino-10.3.1.tgz#6552c8f8d8481844c9e452e7bf0be90bff1939ce" + integrity sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg== + dependencies: + "@pinojs/redact" "^0.4.0" + atomic-sleep "^1.0.0" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^3.0.0" + pino-std-serializers "^7.0.0" + process-warning "^5.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^4.0.1" + thread-stream "^4.0.0" + pirates@^4.0.4: version "4.0.7" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.7.tgz#643b4a18c4257c8a65104b73f3049ce9a0a15e22" @@ -3235,6 +3410,11 @@ pretty-format@^29.0.0, pretty-format@^29.7.0: ansi-styles "^5.0.0" react-is "^18.0.0" +process-warning@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-5.0.0.tgz#566e0bf79d1dff30a72d8bbbe9e8ecefe8d378d7" + integrity sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA== + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -3251,6 +3431,14 @@ proxy-addr@^2.0.7: forwarded "0.2.0" ipaddr.js "1.9.1" +pump@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.4.tgz#1f313430527fa8b905622ebd22fe1444e757ab3c" + integrity sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + punycode@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" @@ -3273,6 +3461,11 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + range-parser@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -3302,6 +3495,11 @@ readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -3348,13 +3546,6 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - router@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef" @@ -3378,11 +3569,21 @@ safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-stable-stringify@^2.3.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== + "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +secure-json-parse@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-4.1.0.tgz#4f1ab41c67a13497ea1b9131bb4183a22865477c" + integrity sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA== + semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -3497,6 +3698,13 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +sonic-boom@^4.0.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.2.1.tgz#28598250df4899c0ac572d7e2f0460690ba6a030" + integrity sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q== + dependencies: + atomic-sleep "^1.0.0" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -3510,6 +3718,11 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -3585,6 +3798,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-5.0.3.tgz#b7304249dd402ee67fd518ada993ab3593458bcf" + integrity sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw== + superstruct@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.4.tgz#0adb99a7578bd2f1c526220da6571b2d485d91ca" @@ -3625,10 +3843,12 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== +thread-stream@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-4.0.0.tgz#732f007c24da7084f729d6e3a7e3f5934a7380b7" + integrity sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA== + dependencies: + real-require "^0.2.0" tmp@^0.0.33: version "0.0.33" @@ -3742,11 +3962,6 @@ type-detect@4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== -type-fest@^0.20.2: - version "0.20.2" - resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" - integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== - type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -3933,7 +4148,7 @@ yoctocolors-cjs@^2.1.2: resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz#7e4964ea8ec422b7a40ac917d3a344cfd2304baa" integrity sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw== -zod-to-json-schema@^3.24.5, zod-to-json-schema@^3.24.6, zod-to-json-schema@^3.25.0: +zod-to-json-schema@^3.24.5, zod-to-json-schema@^3.24.6, zod-to-json-schema@^3.25.1: version "3.25.1" resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz#7f24962101a439ddade2bf1aeab3c3bfec7d84ba" integrity sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA== diff --git a/src/version.ts b/src/version.ts index db66d33..1b06697 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.22.0'; // x-release-please-version +export const VERSION = '0.22.1'; // x-release-please-version diff --git a/yarn.lock b/yarn.lock index 078f09a..e5e2a93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1220,9 +1220,9 @@ baseline-browser-mapping@^2.9.0: integrity sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg== brace-expansion@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" - integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== + version "2.0.3" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.3.tgz#0493338bdd58e319b1039c67cf7ee439892c01d9" + integrity sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA== dependencies: balanced-match "^1.0.0"