From 8ee7235bb02f5696aa8f0682b5c91d18a9755eac Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 20:26:40 +0000 Subject: [PATCH 01/10] chore(internal): codegen related update --- eslint.config.mjs | 3 +++ package.json | 1 + pnpm-lock.yaml | 3 +++ scripts/fast-format | 6 ++++-- scripts/format | 3 ++- scripts/lint | 3 --- scripts/utils/postprocess-files.cjs | 9 ++++++++- src/internal/types.ts | 14 ++++++++------ 8 files changed, 29 insertions(+), 13 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 6f9ae97..2259124 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,6 +1,7 @@ // @ts-check import tseslint from 'typescript-eslint'; import unusedImports from 'eslint-plugin-unused-imports'; +import prettier from 'eslint-plugin-prettier'; export default tseslint.config( { @@ -13,9 +14,11 @@ export default tseslint.config( plugins: { '@typescript-eslint': tseslint.plugin, 'unused-imports': unusedImports, + prettier, }, rules: { 'no-unused-vars': 'off', + 'prettier/prettier': 'error', 'unused-imports/no-unused-imports': 'error', 'no-restricted-imports': [ 'error', diff --git a/package.json b/package.json index 68a2514..059f337 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.39.1", + "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", "jest": "^29.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 94ab185..8d79bb4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,6 +34,9 @@ importers: eslint: specifier: ^9.39.1 version: 9.39.1 + eslint-plugin-prettier: + specifier: ^5.4.1 + version: 5.4.1(eslint@9.39.1)(prettier@3.1.1) eslint-plugin-unused-imports: specifier: ^4.1.4 version: 4.1.4(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.39.1)(typescript@5.8.3))(eslint@9.39.1)(typescript@5.8.3))(eslint@9.39.1) diff --git a/scripts/fast-format b/scripts/fast-format index e172313..53721ac 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -31,8 +31,10 @@ if ! [ -z "$ESLINT_FILES" ]; then fi echo "==> Running prettier --write" -PRETTIER_FILES="$(grep '\.\([mc]?tsx?\|[mc]?jsx?\|json\)$' "$FILE_LIST" || true)" +# format things eslint didn't +PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" if ! [ -z "$PRETTIER_FILES" ]; then echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ + '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' fi diff --git a/scripts/format b/scripts/format index b1b2c17..7a75640 100755 --- a/scripts/format +++ b/scripts/format @@ -8,4 +8,5 @@ echo "==> Running eslint --fix" ./node_modules/.bin/eslint --fix . echo "==> Running prettier --write" -./node_modules/.bin/prettier --write --cache --cache-strategy metadata . +# format things eslint didn't +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' diff --git a/scripts/lint b/scripts/lint index 1f53254..3ffb78a 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,9 +4,6 @@ set -e cd "$(dirname "$0")/.." -echo "==> Running prettier --check" -./node_modules/.bin/prettier --check . - echo "==> Running eslint" ./node_modules/.bin/eslint . diff --git a/scripts/utils/postprocess-files.cjs b/scripts/utils/postprocess-files.cjs index deae575..a8cdeb7 100644 --- a/scripts/utils/postprocess-files.cjs +++ b/scripts/utils/postprocess-files.cjs @@ -23,12 +23,19 @@ async function postprocess() { // strip out lib="dom", types="node", and types="react" references; these // are needed at build time, but would pollute the user's TS environment - const transformed = code.replace( + let transformed = code.replace( /^ *\/\/\/ * ' '.repeat(match.length - 1) + '\n', ); + // TypeScript's declaration emitter collapses /** @ts-ignore */ onto the same + // line as the type declaration, which doesn't work. So we convert to // @ts-ignore + // on its own line to properly suppresses errors. + if (file.endsWith('.d.ts') || file.endsWith('.d.mts') || file.endsWith('.d.cts')) { + transformed = transformed.replace(/\/\*\* @ts-ignore\b[^*]*\*\/ /gm, '// @ts-ignore\n'); + } + if (transformed !== code) { console.error(`wrote ${path.relative(process.cwd(), file)}`); await fs.promises.writeFile(file, transformed, 'utf8'); diff --git a/src/internal/types.ts b/src/internal/types.ts index a050513..b668dfc 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -40,6 +40,7 @@ type OverloadedParameters = : T extends (...args: infer A) => unknown ? A : never; +/* eslint-disable */ /** * These imports attempt to get types from a parent package's dependencies. * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which @@ -62,18 +63,19 @@ type OverloadedParameters = * * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition */ -/** @ts-ignore For users with \@types/node */ /* prettier-ignore */ +/** @ts-ignore For users with \@types/node */ type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with undici */ /* prettier-ignore */ +/** @ts-ignore For users with undici */ type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with \@types/bun */ /* prettier-ignore */ +/** @ts-ignore For users with \@types/bun */ type BunRequestInit = globalThis.FetchRequestInit; -/** @ts-ignore For users with node-fetch@2 */ /* prettier-ignore */ +/** @ts-ignore For users with node-fetch@2 */ type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ /* prettier-ignore */ +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users who use Deno */ /* prettier-ignore */ +/** @ts-ignore For users who use Deno */ type FetchRequestInit = NonNullable[1]>; +/* eslint-enable */ type RequestInits = | NotAny From dc80807af38c51ce4a041a6ba331c62897aace6d Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 22:26:59 +0000 Subject: [PATCH 02/10] feat: support setting headers via env --- src/client.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/client.ts b/src/client.ts index bea38b6..d17a3d3 100644 --- a/src/client.ts +++ b/src/client.ts @@ -184,6 +184,18 @@ export class Tabstack { this.fetch = options.fetch ?? Shims.getDefaultFetch(); this.#encoder = Opts.FallbackEncoder; + const customHeadersEnv = readEnv('TABSTACK_CUSTOM_HEADERS'); + if (customHeadersEnv) { + const parsed: Record = {}; + for (const line of customHeadersEnv.split('\n')) { + const colon = line.indexOf(':'); + if (colon >= 0) { + parsed[line.substring(0, colon).trim()] = line.substring(colon + 1).trim(); + } + } + options.defaultHeaders = { ...parsed, ...options.defaultHeaders }; + } + this._options = options; this.apiKey = apiKey; From 0d94d58968327fc93081582f0e4aa52c73ef3a77 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 19:45:15 +0000 Subject: [PATCH 03/10] chore(format): run eslint and prettier separately --- eslint.config.mjs | 3 --- package.json | 1 - pnpm-lock.yaml | 3 --- scripts/fast-format | 9 +++------ scripts/format | 3 +-- scripts/lint | 3 +++ src/internal/types.ts | 14 ++++++-------- 7 files changed, 13 insertions(+), 23 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 2259124..6f9ae97 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,7 +1,6 @@ // @ts-check import tseslint from 'typescript-eslint'; import unusedImports from 'eslint-plugin-unused-imports'; -import prettier from 'eslint-plugin-prettier'; export default tseslint.config( { @@ -14,11 +13,9 @@ export default tseslint.config( plugins: { '@typescript-eslint': tseslint.plugin, 'unused-imports': unusedImports, - prettier, }, rules: { 'no-unused-vars': 'off', - 'prettier/prettier': 'error', 'unused-imports/no-unused-imports': 'error', 'no-restricted-imports': [ 'error', diff --git a/package.json b/package.json index 059f337..68a2514 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "@typescript-eslint/eslint-plugin": "8.31.1", "@typescript-eslint/parser": "8.31.1", "eslint": "^9.39.1", - "eslint-plugin-prettier": "^5.4.1", "eslint-plugin-unused-imports": "^4.1.4", "iconv-lite": "^0.6.3", "jest": "^29.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8d79bb4..94ab185 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,9 +34,6 @@ importers: eslint: specifier: ^9.39.1 version: 9.39.1 - eslint-plugin-prettier: - specifier: ^5.4.1 - version: 5.4.1(eslint@9.39.1)(prettier@3.1.1) eslint-plugin-unused-imports: specifier: ^4.1.4 version: 4.1.4(@typescript-eslint/eslint-plugin@8.31.1(@typescript-eslint/parser@8.31.1(eslint@9.39.1)(typescript@5.8.3))(eslint@9.39.1)(typescript@5.8.3))(eslint@9.39.1) diff --git a/scripts/fast-format b/scripts/fast-format index 53721ac..f1873ae 100755 --- a/scripts/fast-format +++ b/scripts/fast-format @@ -31,10 +31,7 @@ if ! [ -z "$ESLINT_FILES" ]; then fi echo "==> Running prettier --write" -# format things eslint didn't -PRETTIER_FILES="$(grep '\.\(js\|json\)$' "$FILE_LIST" || true)" -if ! [ -z "$PRETTIER_FILES" ]; then - echo "$PRETTIER_FILES" | xargs ./node_modules/.bin/prettier \ - --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern \ - '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +if ! [ -z "$FILE_LIST" ]; then + cat "$FILE_LIST" | xargs ./node_modules/.bin/prettier \ + --write --cache --cache-strategy metadata --no-error-on-unmatched-pattern --ignore-unknown fi diff --git a/scripts/format b/scripts/format index 7a75640..b1b2c17 100755 --- a/scripts/format +++ b/scripts/format @@ -8,5 +8,4 @@ echo "==> Running eslint --fix" ./node_modules/.bin/eslint --fix . echo "==> Running prettier --write" -# format things eslint didn't -./node_modules/.bin/prettier --write --cache --cache-strategy metadata . '!**/dist' '!**/*.ts' '!**/*.mts' '!**/*.cts' '!**/*.js' '!**/*.mjs' '!**/*.cjs' +./node_modules/.bin/prettier --write --cache --cache-strategy metadata . diff --git a/scripts/lint b/scripts/lint index 3ffb78a..1f53254 100755 --- a/scripts/lint +++ b/scripts/lint @@ -4,6 +4,9 @@ set -e cd "$(dirname "$0")/.." +echo "==> Running prettier --check" +./node_modules/.bin/prettier --check . + echo "==> Running eslint" ./node_modules/.bin/eslint . diff --git a/src/internal/types.ts b/src/internal/types.ts index b668dfc..a050513 100644 --- a/src/internal/types.ts +++ b/src/internal/types.ts @@ -40,7 +40,6 @@ type OverloadedParameters = : T extends (...args: infer A) => unknown ? A : never; -/* eslint-disable */ /** * These imports attempt to get types from a parent package's dependencies. * Unresolved bare specifiers can trigger [automatic type acquisition][1] in some projects, which @@ -63,19 +62,18 @@ type OverloadedParameters = * * [1]: https://www.typescriptlang.org/tsconfig/#typeAcquisition */ -/** @ts-ignore For users with \@types/node */ +/** @ts-ignore For users with \@types/node */ /* prettier-ignore */ type UndiciTypesRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with undici */ +/** @ts-ignore For users with undici */ /* prettier-ignore */ type UndiciRequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with \@types/bun */ +/** @ts-ignore For users with \@types/bun */ /* prettier-ignore */ type BunRequestInit = globalThis.FetchRequestInit; -/** @ts-ignore For users with node-fetch@2 */ +/** @ts-ignore For users with node-fetch@2 */ /* prettier-ignore */ type NodeFetch2RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ +/** @ts-ignore For users with node-fetch@3, doesn't need file extension because types are at ./@types/index.d.ts */ /* prettier-ignore */ type NodeFetch3RequestInit = NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny | NotAny; -/** @ts-ignore For users who use Deno */ +/** @ts-ignore For users who use Deno */ /* prettier-ignore */ type FetchRequestInit = NonNullable[1]>; -/* eslint-enable */ type RequestInits = | NotAny From 51cc9894ca8b828dcfe5413e3cee66384b071149 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 00:21:32 +0000 Subject: [PATCH 04/10] feat(automate): emit task:trace_context SSE event with trace ID --- .stats.yml | 4 +-- packages/mcp-server/src/local-docs-search.ts | 4 +-- src/resources/agent.ts | 29 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/.stats.yml b/.stats.yml index 93a1821..e14e672 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 6 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla%2Ftabstack-5e6e6508dca15391d72cbea74ec33838c511cbc17e046699142f97d1573b069a.yml -openapi_spec_hash: b73b5922a495fd375736896912815d18 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla%2Ftabstack-1ccfa0fbdfebb542246f24972683742e8ffa175bee4fea8040e814695cde951c.yml +openapi_spec_hash: 8a4612fa101f82893c6edca118a86a2d config_hash: 57c64e5e8fe99c1bd7af536d82af4ad9 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 40a7b9f..760f80c 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -70,9 +70,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ 'url?: string;', ], response: - 'object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object', + 'object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object | object', markdown: - "## automate\n\n`client.agent.automate(task: string, data?: object, geo_target?: { country?: string; }, guardrails?: string, interactive?: boolean, maxIterations?: number, maxValidationAttempts?: number, url?: string): { data: object; event: 'agent:action'; } | { data: object; event: 'agent:extracted'; } | { data: object; event: 'agent:processing'; } | { data: object; event: 'agent:reasoned'; } | { data: object; event: 'agent:status'; } | { data: object; event: 'agent:step'; } | { data: object; event: 'agent:waiting'; } | { data: object; event: 'ai:generation'; } | { data: object; event: 'ai:generation:error'; } | { data: object; event: 'browser:action_completed'; } | { data: object; event: 'browser:action_started'; } | { data: object; event: 'browser:navigated'; } | { data: object; event: 'browser:reconnected'; } | { data: object; event: 'browser:screenshot_captured'; } | { data: object; event: 'browser:screenshot_captured_image'; } | { data: object; event: 'cdp:endpoint_connected'; } | { data: object; event: 'cdp:endpoint_cycle'; } | { data: object; event: 'complete'; } | { data: object; event: 'done'; } | { data: object; event: 'error'; } | { data: object; event: 'interactive:form_data:error'; } | { data: object; event: 'interactive:form_data:request'; } | { data: object; event: 'system:debug_compression'; } | { data: object; event: 'system:debug_message'; } | { data: object; event: 'task:aborted'; } | { data: object; event: 'task:completed'; } | { data: object; event: 'task:metrics'; } | { data: object; event: 'task:metrics_incremental'; } | { data: object; event: 'task:setup'; } | { data: object; event: 'task:started'; } | { data: object; event: 'task:validated'; } | { data: object; event: 'task:validation_error'; }`\n\n**post** `/automate`\n\nExecute AI-powered browser automation tasks using natural language with optional geotargeting. This endpoint **always streams** responses using Server-Sent Events (SSE).\n\n**Streaming Response:**\n- All responses are streamed using Server-Sent Events (`text/event-stream`)\n- Real-time progress updates and results as they're generated\n\n**Geotargeting:**\n- Optionally specify a country code for geotargeted browsing\n\n**Use Cases:**\n- Web scraping and data extraction\n- Form filling and interaction\n- Navigation and information gathering\n- Multi-step web workflows\n- Content analysis from web pages\n\n### Parameters\n\n- `task: string`\n The task description in natural language\n\n- `data?: object`\n JSON data to provide context for form filling or complex tasks\n\n- `geo_target?: { country?: string; }`\n Optional geotargeting parameters for proxy requests\n - `country?: string`\n Country code using ISO 3166-1 alpha-2 standard (2 letters, e.g., \"US\", \"GB\", \"JP\").\nSee: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2\n\n- `guardrails?: string`\n Safety constraints for execution\n\n- `interactive?: boolean`\n Enable interactive mode to allow human-in-the-loop input during task execution\n\n- `maxIterations?: number`\n Maximum task iterations\n\n- `maxValidationAttempts?: number`\n Maximum validation attempts\n\n- `url?: string`\n Starting URL for the task\n\n### Returns\n\n- `{ data: { action: string; iterationId: string; timestamp: number; ref?: string; value?: string; }; event: 'agent:action'; } | { data: { extractedData: string; iterationId: string; timestamp: number; }; event: 'agent:extracted'; } | { data: { hasScreenshot: boolean; iterationId: string; operation: string; timestamp: number; }; event: 'agent:processing'; } | { data: { iterationId: string; reasoning: string; timestamp: number; }; event: 'agent:reasoned'; } | { data: { iterationId: string; message: string; timestamp: number; }; event: 'agent:status'; } | { data: { currentIteration: number; iterationId: string; timestamp: number; }; event: 'agent:step'; } | { data: { iterationId: string; seconds: number; timestamp: number; }; event: 'agent:waiting'; } | { data: { finishReason: 'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'; iterationId: string; prompt: string; schema: object; timestamp: number; usage: { inputTokens?: number; outputTokens?: number; totalTokens?: number; }; messages?: { content: string; role: 'system'; providerOptions?: object; } | { content: string | object | object | object[]; role: 'user'; providerOptions?: object; } | { content: string | object | object | object | object | object | object[]; role: 'assistant'; providerOptions?: object; } | { content: object | object[]; role: 'tool'; providerOptions?: object; }[]; object?: object; providerMetadata?: object; temperature?: number; warnings?: object[]; }; event: 'ai:generation'; } | { data: { error: string; iterationId: string; prompt: string; schema: object; timestamp: number; messages?: object[]; }; event: 'ai:generation:error'; } | { data: { iterationId: string; success: boolean; timestamp: number; error?: string; }; event: 'browser:action_completed'; } | { data: { action: string; iterationId: string; timestamp: number; ref?: string; value?: string; }; event: 'browser:action_started'; } | { data: { iterationId: string; timestamp: number; title: string; url: string; }; event: 'browser:navigated'; } | { data: { endpointIndex: number; iterationId: string; startingUrl: string; timestamp: number; total: number; }; event: 'browser:reconnected'; } | { data: { format: 'jpeg' | 'png'; iterationId: string; size: number; timestamp: number; }; event: 'browser:screenshot_captured'; } | { data: { image: string; iterationId: string; mediaType: 'image/jpeg' | 'image/png'; timestamp: number; }; event: 'browser:screenshot_captured_image'; } | { data: { endpointIndex: number; iterationId: string; timestamp: number; total: number; }; event: 'cdp:endpoint_connected'; } | { data: { attempt: number; error: string; iterationId: string; timestamp: number; total: number; }; event: 'cdp:endpoint_cycle'; } | { data: { finalAnswer: string; stats: { actions: number; durationMs: number; endTime: number; iterations: number; startTime: number; }; success: boolean; error?: { code: 'TASK_ABORTED' | 'MAX_ITERATIONS' | 'MAX_ERRORS' | 'TASK_FAILED'; message: string; }; }; event: 'complete'; } | { data: object; event: 'done'; } | { data: { error: { code: string; message: string; timestamp: string; }; success: false; }; event: 'error'; } | { data: { fieldErrors: object; fields: { fieldType: string; label: string; ref: string; required: boolean; currentValue?: string; description?: string; options?: string[]; }[]; formDescription: string; iterationId: string; pageTitle: string; pageUrl: string; requestId: string; timestamp: number; }; event: 'interactive:form_data:error'; } | { data: { fields: { fieldType: string; label: string; ref: string; required: boolean; currentValue?: string; description?: string; options?: string[]; }[]; formDescription: string; iterationId: string; pageTitle: string; pageUrl: string; requestId: string; timestamp: number; }; event: 'interactive:form_data:request'; } | { data: { compressedSize: number; compressionPercent: number; iterationId: string; originalSize: number; timestamp: number; }; event: 'system:debug_compression'; } | { data: { iterationId: string; messages: object[]; timestamp: number; }; event: 'system:debug_message'; } | { data: { finalAnswer: string; iterationId: string; reason: string; timestamp: number; }; event: 'task:aborted'; } | { data: { finalAnswer: string; iterationId: string; timestamp: number; success?: boolean; }; event: 'task:completed'; } | { data: { aiGenerationCount: number; aiGenerationErrorCount: number; eventCounts: object; iterationId: string; stepCount: number; timestamp: number; totalInputTokens: number; totalOutputTokens: number; }; event: 'task:metrics'; } | { data: { aiGenerationCount: number; aiGenerationErrorCount: number; eventCounts: object; iterationId: string; stepCount: number; timestamp: number; totalInputTokens: number; totalOutputTokens: number; }; event: 'task:metrics_incremental'; } | { data: { browserName: string; iterationId: string; task: string; timestamp: number; data?: object; guardrails?: string; hasApiKey?: boolean; keySource?: 'global' | 'env' | 'not_set'; model?: string; provider?: string; proxy?: string; pwCdpEndpoint?: string; pwCdpEndpointCount?: number; pwCdpEndpoints?: string[]; pwEndpoint?: string; url?: string; vision?: boolean; }; event: 'task:setup'; } | { data: { iterationId: string; plan: string; successCriteria: string; task: string; timestamp: number; url: string; actionItems?: string[]; }; event: 'task:started'; } | { data: { completionQuality: 'failed' | 'partial' | 'complete' | 'excellent'; finalAnswer: string; iterationId: string; observation: string; timestamp: number; feedback?: string; }; event: 'task:validated'; } | { data: { errors: string[]; iterationId: string; rawResponse: object; retryCount: number; timestamp: number; }; event: 'task:validation_error'; }`\n A Server-Sent Event from /v1/automate. Typed discriminated union keyed on event.\n\n### Example\n\n```typescript\nimport Tabstack from '@tabstack/sdk';\n\nconst client = new Tabstack();\n\nconst stream = await client.agent.automate({ task: 'Find the top 3 trending repositories and extract their names, descriptions, and star counts' });\nfor await (const automateEvent of stream) {\n console.log(automateEvent);\n}\n```", + "## automate\n\n`client.agent.automate(task: string, data?: object, geo_target?: { country?: string; }, guardrails?: string, interactive?: boolean, maxIterations?: number, maxValidationAttempts?: number, url?: string): { data: object; event: 'agent:action'; } | { data: object; event: 'agent:extracted'; } | { data: object; event: 'agent:processing'; } | { data: object; event: 'agent:reasoned'; } | { data: object; event: 'agent:status'; } | { data: object; event: 'agent:step'; } | { data: object; event: 'agent:waiting'; } | { data: object; event: 'ai:generation'; } | { data: object; event: 'ai:generation:error'; } | { data: object; event: 'browser:action_completed'; } | { data: object; event: 'browser:action_started'; } | { data: object; event: 'browser:navigated'; } | { data: object; event: 'browser:reconnected'; } | { data: object; event: 'browser:screenshot_captured'; } | { data: object; event: 'browser:screenshot_captured_image'; } | { data: object; event: 'cdp:endpoint_connected'; } | { data: object; event: 'cdp:endpoint_cycle'; } | { data: object; event: 'complete'; } | { data: object; event: 'done'; } | { data: object; event: 'error'; } | { data: object; event: 'interactive:form_data:error'; } | { data: object; event: 'interactive:form_data:request'; } | { data: object; event: 'system:debug_compression'; } | { data: object; event: 'system:debug_message'; } | { data: object; event: 'task:aborted'; } | { data: object; event: 'task:completed'; } | { data: object; event: 'task:metrics'; } | { data: object; event: 'task:metrics_incremental'; } | { data: object; event: 'task:setup'; } | { data: object; event: 'task:started'; } | { data: object; event: 'task:trace_context'; } | { data: object; event: 'task:validated'; } | { data: object; event: 'task:validation_error'; }`\n\n**post** `/automate`\n\nExecute AI-powered browser automation tasks using natural language with optional geotargeting. This endpoint **always streams** responses using Server-Sent Events (SSE).\n\n**Streaming Response:**\n- All responses are streamed using Server-Sent Events (`text/event-stream`)\n- Real-time progress updates and results as they're generated\n\n**Geotargeting:**\n- Optionally specify a country code for geotargeted browsing\n\n**Use Cases:**\n- Web scraping and data extraction\n- Form filling and interaction\n- Navigation and information gathering\n- Multi-step web workflows\n- Content analysis from web pages\n\n### Parameters\n\n- `task: string`\n The task description in natural language\n\n- `data?: object`\n JSON data to provide context for form filling or complex tasks\n\n- `geo_target?: { country?: string; }`\n Optional geotargeting parameters for proxy requests\n - `country?: string`\n Country code using ISO 3166-1 alpha-2 standard (2 letters, e.g., \"US\", \"GB\", \"JP\").\nSee: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2\n\n- `guardrails?: string`\n Safety constraints for execution\n\n- `interactive?: boolean`\n Enable interactive mode to allow human-in-the-loop input during task execution\n\n- `maxIterations?: number`\n Maximum task iterations\n\n- `maxValidationAttempts?: number`\n Maximum validation attempts\n\n- `url?: string`\n Starting URL for the task\n\n### Returns\n\n- `{ data: { action: string; iterationId: string; timestamp: number; ref?: string; value?: string; }; event: 'agent:action'; } | { data: { extractedData: string; iterationId: string; timestamp: number; }; event: 'agent:extracted'; } | { data: { hasScreenshot: boolean; iterationId: string; operation: string; timestamp: number; }; event: 'agent:processing'; } | { data: { iterationId: string; reasoning: string; timestamp: number; }; event: 'agent:reasoned'; } | { data: { iterationId: string; message: string; timestamp: number; }; event: 'agent:status'; } | { data: { currentIteration: number; iterationId: string; timestamp: number; }; event: 'agent:step'; } | { data: { iterationId: string; seconds: number; timestamp: number; }; event: 'agent:waiting'; } | { data: { finishReason: 'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other'; iterationId: string; prompt: string; schema: object; timestamp: number; usage: { inputTokens?: number; outputTokens?: number; totalTokens?: number; }; messages?: { content: string; role: 'system'; providerOptions?: object; } | { content: string | object | object | object[]; role: 'user'; providerOptions?: object; } | { content: string | object | object | object | object | object | object[]; role: 'assistant'; providerOptions?: object; } | { content: object | object[]; role: 'tool'; providerOptions?: object; }[]; object?: object; providerMetadata?: object; temperature?: number; warnings?: object[]; }; event: 'ai:generation'; } | { data: { error: string; iterationId: string; prompt: string; schema: object; timestamp: number; messages?: object[]; }; event: 'ai:generation:error'; } | { data: { iterationId: string; success: boolean; timestamp: number; error?: string; }; event: 'browser:action_completed'; } | { data: { action: string; iterationId: string; timestamp: number; ref?: string; value?: string; }; event: 'browser:action_started'; } | { data: { iterationId: string; timestamp: number; title: string; url: string; }; event: 'browser:navigated'; } | { data: { endpointIndex: number; iterationId: string; startingUrl: string; timestamp: number; total: number; }; event: 'browser:reconnected'; } | { data: { format: 'jpeg' | 'png'; iterationId: string; size: number; timestamp: number; }; event: 'browser:screenshot_captured'; } | { data: { image: string; iterationId: string; mediaType: 'image/jpeg' | 'image/png'; timestamp: number; }; event: 'browser:screenshot_captured_image'; } | { data: { endpointIndex: number; iterationId: string; timestamp: number; total: number; }; event: 'cdp:endpoint_connected'; } | { data: { attempt: number; error: string; iterationId: string; timestamp: number; total: number; }; event: 'cdp:endpoint_cycle'; } | { data: { finalAnswer: string; stats: { actions: number; durationMs: number; endTime: number; iterations: number; startTime: number; }; success: boolean; error?: { code: 'TASK_ABORTED' | 'MAX_ITERATIONS' | 'MAX_ERRORS' | 'TASK_FAILED'; message: string; }; }; event: 'complete'; } | { data: object; event: 'done'; } | { data: { error: { code: string; message: string; timestamp: string; }; success: false; }; event: 'error'; } | { data: { fieldErrors: object; fields: { fieldType: string; label: string; ref: string; required: boolean; currentValue?: string; description?: string; options?: string[]; }[]; formDescription: string; iterationId: string; pageTitle: string; pageUrl: string; requestId: string; timestamp: number; }; event: 'interactive:form_data:error'; } | { data: { fields: { fieldType: string; label: string; ref: string; required: boolean; currentValue?: string; description?: string; options?: string[]; }[]; formDescription: string; iterationId: string; pageTitle: string; pageUrl: string; requestId: string; timestamp: number; }; event: 'interactive:form_data:request'; } | { data: { compressedSize: number; compressionPercent: number; iterationId: string; originalSize: number; timestamp: number; }; event: 'system:debug_compression'; } | { data: { iterationId: string; messages: object[]; timestamp: number; }; event: 'system:debug_message'; } | { data: { finalAnswer: string; iterationId: string; reason: string; timestamp: number; }; event: 'task:aborted'; } | { data: { finalAnswer: string; iterationId: string; timestamp: number; success?: boolean; }; event: 'task:completed'; } | { data: { aiGenerationCount: number; aiGenerationErrorCount: number; eventCounts: object; iterationId: string; stepCount: number; timestamp: number; totalInputTokens: number; totalOutputTokens: number; }; event: 'task:metrics'; } | { data: { aiGenerationCount: number; aiGenerationErrorCount: number; eventCounts: object; iterationId: string; stepCount: number; timestamp: number; totalInputTokens: number; totalOutputTokens: number; }; event: 'task:metrics_incremental'; } | { data: { browserName: string; iterationId: string; task: string; timestamp: number; data?: object; guardrails?: string; hasApiKey?: boolean; keySource?: 'global' | 'env' | 'not_set'; model?: string; provider?: string; proxy?: string; pwCdpEndpoint?: string; pwCdpEndpointCount?: number; pwCdpEndpoints?: string[]; pwEndpoint?: string; url?: string; vision?: boolean; }; event: 'task:setup'; } | { data: { iterationId: string; plan: string; successCriteria: string; task: string; timestamp: number; url: string; actionItems?: string[]; }; event: 'task:started'; } | { data: { traceId: string; }; event: 'task:trace_context'; } | { data: { completionQuality: 'failed' | 'partial' | 'complete' | 'excellent'; finalAnswer: string; iterationId: string; observation: string; timestamp: number; feedback?: string; }; event: 'task:validated'; } | { data: { errors: string[]; iterationId: string; rawResponse: object; retryCount: number; timestamp: number; }; event: 'task:validation_error'; }`\n A Server-Sent Event from /v1/automate. Typed discriminated union keyed on event.\n\n### Example\n\n```typescript\nimport Tabstack from '@tabstack/sdk';\n\nconst client = new Tabstack();\n\nconst stream = await client.agent.automate({ task: 'Find the top 3 trending repositories and extract their names, descriptions, and star counts' });\nfor await (const automateEvent of stream) {\n console.log(automateEvent);\n}\n```", perLanguage: { typescript: { method: 'client.agent.automate', diff --git a/src/resources/agent.ts b/src/resources/agent.ts index 448f899..b14e828 100644 --- a/src/resources/agent.ts +++ b/src/resources/agent.ts @@ -154,6 +154,7 @@ export type AutomateEvent = | AutomateEvent.V1AutomateEventTaskMetricsIncremental | AutomateEvent.V1AutomateEventTaskSetup | AutomateEvent.V1AutomateEventTaskStarted + | AutomateEvent.V1AutomateEventTaskTraceContext | AutomateEvent.V1AutomateEventTaskValidated | AutomateEvent.V1AutomateEventTaskValidationError; @@ -2674,6 +2675,34 @@ export namespace AutomateEvent { } } + /** + * Envelope for the "task:trace_context" event from /v1/automate. + */ + export interface V1AutomateEventTaskTraceContext { + /** + * Payload for the task:trace_context event. Carries the OpenTelemetry trace ID for + * this /v1/automate request so consumers can deep-link to distributed-tracing UIs + * (e.g. Cloud Trace, Cloud Logging) for the run. + */ + data: V1AutomateEventTaskTraceContext.Data; + + event: 'task:trace_context'; + } + + export namespace V1AutomateEventTaskTraceContext { + /** + * Payload for the task:trace_context event. Carries the OpenTelemetry trace ID for + * this /v1/automate request so consumers can deep-link to distributed-tracing UIs + * (e.g. Cloud Trace, Cloud Logging) for the run. + */ + export interface Data { + /** + * W3C trace ID — 32-character lowercase hexadecimal string. + */ + traceId: string; + } + } + /** * Envelope for the "task:validated" event from /v1/automate. */ From 8bcebec347f5b03762e7ff725a3c19a4425c0d3b Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 18:00:38 +0000 Subject: [PATCH 05/10] chore: avoid formatting file that gets changed during releases --- .prettierignore | 1 + packages/mcp-server/manifest.json | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.prettierignore b/.prettierignore index 7cc13dd..36afd3b 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,6 +2,7 @@ CHANGELOG.md /ecosystem-tests/*/** /node_modules /deno +/packages/mcp-server/manifest.json # don't format tsc output, will break source maps dist diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index bc32d20..480ecb7 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -16,7 +16,9 @@ "entry_point": "index.js", "mcp_config": { "command": "node", - "args": ["${__dirname}/index.js"], + "args": [ + "${__dirname}/index.js" + ], "env": { "TABSTACK_API_KEY": "${user_config.TABSTACK_API_KEY}" } @@ -37,5 +39,7 @@ "node": ">=18.0.0" } }, - "keywords": ["api"] + "keywords": [ + "api" + ] } From 93213f672cb2049bc8377550cbf99c0efe671c56 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 29 Apr 2026 18:13:27 +0000 Subject: [PATCH 06/10] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index e14e672..0e39953 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 6 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla%2Ftabstack-1ccfa0fbdfebb542246f24972683742e8ffa175bee4fea8040e814695cde951c.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla/tabstack-1ccfa0fbdfebb542246f24972683742e8ffa175bee4fea8040e814695cde951c.yml openapi_spec_hash: 8a4612fa101f82893c6edca118a86a2d config_hash: 57c64e5e8fe99c1bd7af536d82af4ad9 From 63f3d5d8b3e291adb48d2076ad79eaa6576ba082 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 30 Apr 2026 16:20:01 +0000 Subject: [PATCH 07/10] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 0e39953..8d539a5 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 6 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla/tabstack-1ccfa0fbdfebb542246f24972683742e8ffa175bee4fea8040e814695cde951c.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla/tabstack-7d424abc15447c30f5050aaf11eaf7d27b310b36f637537c51dedc6b7f884474.yml openapi_spec_hash: 8a4612fa101f82893c6edca118a86a2d config_hash: 57c64e5e8fe99c1bd7af536d82af4ad9 From 4d6bd2ec28d2424f239fd7fc763e0ed394f43a51 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 16:16:54 +0000 Subject: [PATCH 08/10] feat(api): add endpoint specfic timeouts The default timeout of 60 seconds regularly cuts off automate and research requests. These values have been updated to allow the slowest requests we have seen complete for the API --- .stats.yml | 4 ++-- packages/mcp-server/src/local-docs-search.ts | 10 +++++----- src/resources/agent.ts | 2 ++ src/resources/extract.ts | 12 ++++++++++-- src/resources/generate.ts | 6 +++++- 5 files changed, 24 insertions(+), 10 deletions(-) diff --git a/.stats.yml b/.stats.yml index 8d539a5..a838a7f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 6 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla/tabstack-7d424abc15447c30f5050aaf11eaf7d27b310b36f637537c51dedc6b7f884474.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla/tabstack-a587e9165648e2a318298ea7df679602eacb2d2126032fb1ef83de1aa34c3ff6.yml openapi_spec_hash: 8a4612fa101f82893c6edca118a86a2d -config_hash: 57c64e5e8fe99c1bd7af536d82af4ad9 +config_hash: ef374c8c9d6f0a94ef9163bd41bf9052 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 760f80c..a0affd1 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -91,7 +91,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - 'curl https://api.tabstack.ai/v1/automate \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n -d "{\n \\"task\\": \\"Find the top 3 trending repositories and extract their names, descriptions, and star counts\\",\n \\"guardrails\\": \\"browse and extract only, don\'t interact with repositories\\",\n \\"maxIterations\\": 50,\n \\"maxValidationAttempts\\": 3,\n \\"url\\": \\"https://github.com/trending\\"\n }"', + 'curl https://api.tabstack.ai/v1/automate \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n --max-time 600 \\\n -d "{\n \\"task\\": \\"Find the top 3 trending repositories and extract their names, descriptions, and star counts\\",\n \\"guardrails\\": \\"browse and extract only, don\'t interact with repositories\\",\n \\"maxIterations\\": 50,\n \\"maxValidationAttempts\\": 3,\n \\"url\\": \\"https://github.com/trending\\"\n }"', }, }, }, @@ -167,7 +167,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - 'curl https://api.tabstack.ai/v1/research \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n -d \'{\n "query": "What are the latest developments in quantum computing?",\n "fetch_timeout": 30,\n "mode": "fast"\n }\'', + 'curl https://api.tabstack.ai/v1/research \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n --max-time 600 \\\n -d \'{\n "query": "What are the latest developments in quantum computing?",\n "fetch_timeout": 30,\n "mode": "fast"\n }\'', }, }, }, @@ -207,7 +207,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - 'curl https://api.tabstack.ai/v1/extract/json \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n -d \'{\n "json_schema": {\n "properties": {\n "stories": {\n "items": {\n "properties": {\n "author": {\n "description": "Author username",\n "type": "string"\n },\n "points": {\n "description": "Story points",\n "type": "number"\n },\n "title": {\n "description": "Story title",\n "type": "string"\n }\n },\n "type": "object"\n },\n "type": "array"\n }\n },\n "type": "object"\n },\n "url": "https://news.ycombinator.com",\n "effort": "standard"\n }\'', + 'curl https://api.tabstack.ai/v1/extract/json \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n --max-time 300 \\\n -d \'{\n "json_schema": {\n "properties": {\n "stories": {\n "items": {\n "properties": {\n "author": {\n "description": "Author username",\n "type": "string"\n },\n "points": {\n "description": "Story points",\n "type": "number"\n },\n "title": {\n "description": "Story title",\n "type": "string"\n }\n },\n "type": "object"\n },\n "type": "array"\n }\n },\n "type": "object"\n },\n "url": "https://news.ycombinator.com",\n "effort": "standard"\n }\'', }, }, }, @@ -249,7 +249,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - 'curl https://api.tabstack.ai/v1/extract/markdown \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n -d \'{\n "url": "https://example.com/blog/article",\n "effort": "standard",\n "metadata": true\n }\'', + 'curl https://api.tabstack.ai/v1/extract/markdown \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n --max-time 180 \\\n -d \'{\n "url": "https://example.com/blog/article",\n "effort": "standard",\n "metadata": true\n }\'', }, }, }, @@ -291,7 +291,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ }, http: { example: - 'curl https://api.tabstack.ai/v1/generate/json \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n -d "{\n \\"instructions\\": \\"For each story, categorize it (tech/business/science/other) and write a one-sentence summary explaining what it\'s about in simple terms.\\",\n \\"json_schema\\": {\n \\"properties\\": {\n \\"summaries\\": {\n \\"items\\": {\n \\"properties\\": {\n \\"category\\": {\n \\"description\\": \\"Story category (tech/business/science/etc)\\",\n \\"type\\": \\"string\\"\n },\n \\"summary\\": {\n \\"description\\": \\"One-sentence summary of the story\\",\n \\"type\\": \\"string\\"\n },\n \\"title\\": {\n \\"description\\": \\"Story title\\",\n \\"type\\": \\"string\\"\n }\n },\n \\"type\\": \\"object\\"\n },\n \\"type\\": \\"array\\"\n }\n },\n \\"type\\": \\"object\\"\n },\n \\"url\\": \\"https://news.ycombinator.com\\",\n \\"effort\\": \\"standard\\"\n }"', + 'curl https://api.tabstack.ai/v1/generate/json \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $TABSTACK_API_KEY" \\\n --max-time 300 \\\n -d "{\n \\"instructions\\": \\"For each story, categorize it (tech/business/science/other) and write a one-sentence summary explaining what it\'s about in simple terms.\\",\n \\"json_schema\\": {\n \\"properties\\": {\n \\"summaries\\": {\n \\"items\\": {\n \\"properties\\": {\n \\"category\\": {\n \\"description\\": \\"Story category (tech/business/science/etc)\\",\n \\"type\\": \\"string\\"\n },\n \\"summary\\": {\n \\"description\\": \\"One-sentence summary of the story\\",\n \\"type\\": \\"string\\"\n },\n \\"title\\": {\n \\"description\\": \\"Story title\\",\n \\"type\\": \\"string\\"\n }\n },\n \\"type\\": \\"object\\"\n },\n \\"type\\": \\"array\\"\n }\n },\n \\"type\\": \\"object\\"\n },\n \\"url\\": \\"https://news.ycombinator.com\\",\n \\"effort\\": \\"standard\\"\n }"', }, }, }, diff --git a/src/resources/agent.ts b/src/resources/agent.ts index b14e828..9e35967 100644 --- a/src/resources/agent.ts +++ b/src/resources/agent.ts @@ -43,6 +43,7 @@ export class Agent extends APIResource { automate(body: AgentAutomateParams, options?: RequestOptions): APIPromise> { return this._client.post('/automate', { body, + timeout: (this._client as any)._options.timeout ?? 600000, ...options, headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), stream: true, @@ -112,6 +113,7 @@ export class Agent extends APIResource { research(body: AgentResearchParams, options?: RequestOptions): APIPromise> { return this._client.post('/research', { body, + timeout: (this._client as any)._options.timeout ?? 600000, ...options, headers: buildHeaders([{ Accept: 'text/event-stream' }, options?.headers]), stream: true, diff --git a/src/resources/extract.ts b/src/resources/extract.ts index 3c2fb80..4f871cb 100644 --- a/src/resources/extract.ts +++ b/src/resources/extract.ts @@ -41,7 +41,11 @@ export class Extract extends APIResource { * ``` */ json(body: ExtractJsonParams, options?: RequestOptions): APIPromise { - return this._client.post('/extract/json', { body, ...options }); + return this._client.post('/extract/json', { + body, + timeout: (this._client as any)._options.timeout ?? 300000, + ...options, + }); } /** @@ -56,7 +60,11 @@ export class Extract extends APIResource { * ``` */ markdown(body: ExtractMarkdownParams, options?: RequestOptions): APIPromise { - return this._client.post('/extract/markdown', { body, ...options }); + return this._client.post('/extract/markdown', { + body, + timeout: (this._client as any)._options.timeout ?? 180000, + ...options, + }); } } diff --git a/src/resources/generate.ts b/src/resources/generate.ts index bfc3ee5..18aca46 100644 --- a/src/resources/generate.ts +++ b/src/resources/generate.ts @@ -38,7 +38,11 @@ export class Generate extends APIResource { * ``` */ json(body: GenerateJsonParams, options?: RequestOptions): APIPromise { - return this._client.post('/generate/json', { body, ...options }); + return this._client.post('/generate/json', { + body, + timeout: (this._client as any)._options.timeout ?? 300000, + ...options, + }); } } From cc209097670fa44ec405ed1740681d4a12f50586 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 14:28:55 +0000 Subject: [PATCH 09/10] feat(api): manual updates --- .stats.yml | 4 +- api.md | 8 + packages/mcp-server/src/local-docs-search.ts | 2 +- src/client.ts | 6 + src/resources/agent.ts | 176 ++++++------------- src/resources/extract.ts | 31 +--- src/resources/generate.ts | 16 +- src/resources/index.ts | 3 + src/resources/shared.ts | 9 + 9 files changed, 85 insertions(+), 170 deletions(-) create mode 100644 src/resources/shared.ts diff --git a/.stats.yml b/.stats.yml index a838a7f..c91eb54 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 6 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla/tabstack-a587e9165648e2a318298ea7df679602eacb2d2126032fb1ef83de1aa34c3ff6.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mozilla/tabstack-c97fe4d7e39fd2f35a75dc7fdeb6d3f19aab2f9b56d4983c3376a5433dc9e268.yml openapi_spec_hash: 8a4612fa101f82893c6edca118a86a2d -config_hash: ef374c8c9d6f0a94ef9163bd41bf9052 +config_hash: 5827ec0cdbbac0e7c5db2f5456f67dca diff --git a/api.md b/api.md index 9162456..911eadc 100644 --- a/api.md +++ b/api.md @@ -1,9 +1,17 @@ +# Shared + +Types: + +- GeotargetGeoTarget + # Agent Types: - AutomateEvent - ResearchEvent +- V1GlobalBuffer +- V1ResearchQuestionAssessment - AgentAutomateInputResponse Methods: diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index a0affd1..b8e1805 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -148,7 +148,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ data: object; event: 'analyzing:end'; } | { data: object; event: 'analyzing:start'; } | { data: object; event: 'complete'; } | { data: object; event: 'error'; } | { data: object; event: 'evaluating:end'; } | { data: object; event: 'evaluating:start'; } | { data: object; event: 'following:end'; } | { data: object; event: 'following:start'; } | { data: object; event: 'iteration:end'; } | { data: object; event: 'iteration:start'; } | { data: object; event: 'judging:end'; } | { data: object; event: 'judging:start'; } | { data: object; event: 'outlining:end'; } | { data: object; event: 'outlining:start'; } | { data: object; event: 'planning:end'; } | { data: object; event: 'planning:start'; } | { data: object; event: 'prefetching:end'; } | { data: object; event: 'prefetching:start'; } | { data: object; event: 'searching:end'; } | { data: object; event: 'searching:start'; } | { data: object; event: 'start'; } | { data: object; event: 'writing:end'; } | { data: object; event: 'writing:start'; }", markdown: - "## research\n\n`client.agent.research(query: string, fetch_timeout?: number, mode?: 'fast' | 'balanced', nocache?: boolean): { data: object; event: 'analyzing:end'; } | { data: object; event: 'analyzing:start'; } | { data: object; event: 'complete'; } | { data: object; event: 'error'; } | { data: object; event: 'evaluating:end'; } | { data: object; event: 'evaluating:start'; } | { data: object; event: 'following:end'; } | { data: object; event: 'following:start'; } | { data: object; event: 'iteration:end'; } | { data: object; event: 'iteration:start'; } | { data: object; event: 'judging:end'; } | { data: object; event: 'judging:start'; } | { data: object; event: 'outlining:end'; } | { data: object; event: 'outlining:start'; } | { data: object; event: 'planning:end'; } | { data: object; event: 'planning:start'; } | { data: object; event: 'prefetching:end'; } | { data: object; event: 'prefetching:start'; } | { data: object; event: 'searching:end'; } | { data: object; event: 'searching:start'; } | { data: object; event: 'start'; } | { data: object; event: 'writing:end'; } | { data: object; event: 'writing:start'; }`\n\n**post** `/research`\n\nExecute AI-powered research queries that search the web, analyze sources, and synthesize comprehensive answers. This endpoint **always streams** responses using Server-Sent Events (SSE).\n\n**Streaming Response:**\n- All responses are streamed using Server-Sent Events (`text/event-stream`)\n- Real-time progress updates as research progresses through phases\n\n**Research Modes:**\n- `fast` - Quick answers with minimal web searches (default)\n- `balanced` - Standard research with multiple iterations\n\n**Use Cases:**\n- Answering complex questions with cited sources\n- Synthesizing information from multiple web sources\n- Research reports on specific topics\n- Fact-checking and verification tasks\n\n### Parameters\n\n- `query: string`\n The research query or question to answer. Maximum 10,000 characters.\n\n- `fetch_timeout?: number`\n Timeout in seconds for fetching web pages\n\n- `mode?: 'fast' | 'balanced'`\n Research mode: fast (quick answers, default), balanced (standard research)\n\n- `nocache?: boolean`\n Skip cache and force fresh research\n\n### Returns\n\n- `{ data: { analyzed: number; failed: number; iteration: number; message: string; samples: { domain: string; title: string; url: string; urlSource: 'user-input' | 'search-result' | 'extracted-link'; relevance?: 'low' | 'medium' | 'high'; reliability?: 'low' | 'medium' | 'high'; summary?: string; }[]; timestamp: number; }; event: 'analyzing:end'; } | { data: { iteration: number; message: string; pageCount: number; timestamp: number; }; event: 'analyzing:start'; } | { data: { message: string; metadata: { executedQueries: string[][]; mode: 'fast' | 'balanced' | 'deep' | 'max' | 'ultra'; prompt: string; queryComplexity: 'simple' | 'moderate' | 'complex'; researchObjective: string; researchPlan: string; researchQuestions: string[]; totalPagesAnalyzed: number; citedPages?: object[]; gapEvaluations?: object[]; judgments?: object[]; metrics?: object; outline?: object; urlSources?: object; }; report: string; timestamp: number; }; event: 'complete'; } | { data: { error: { message: string; name: string; stack?: string; }; message: string; timestamp: number; activity?: string; iteration?: number; }; event: 'error'; } | { data: { coverage: 'Light' | 'Moderate' | 'Solid' | 'Comprehensive'; gaps: string; iteration: number; message: string; nextQueries: string[]; questionAssessments: { findings: string; question: string; status: 'answered' | 'partial' | 'unanswered'; }[]; shouldContinue: boolean; timestamp: number; }; event: 'evaluating:end'; } | { data: { iteration: number; message: string; pagesAnalyzed: number; questionCount: number; timestamp: number; }; event: 'evaluating:start'; } | { data: { failed: number; followed: number; iteration: number; message: string; samples: { domain: string; title: string; url: string; urlSource: 'user-input' | 'search-result' | 'extracted-link'; relevance?: 'low' | 'medium' | 'high'; reliability?: 'low' | 'medium' | 'high'; summary?: string; }[]; timestamp: number; }; event: 'following:end'; } | { data: { iteration: number; linkCount: number; message: string; timestamp: number; }; event: 'following:start'; } | { data: { isLast: boolean; iteration: number; message: string; timestamp: number; stopReason?: 'max_iterations' | 'coverage_sufficient'; }; event: 'iteration:end'; } | { data: { iteration: number; maxIterations: number; message: string; queries: string[]; timestamp: number; }; event: 'iteration:start'; } | { data: { approved: boolean; attempt: number; message: string; score: number; timestamp: number; feedback?: string; }; event: 'judging:end'; } | { data: { attempt: number; maxAttempts: number; message: string; timestamp: number; }; event: 'judging:start'; } | { data: { message: string; sourcesSelected: number; timestamp: number; }; event: 'outlining:end'; } | { data: { message: string; pagesAnalyzed: number; qualityPageCount: number; timestamp: number; }; event: 'outlining:start'; } | { data: { complexity: 'simple' | 'moderate' | 'complex'; message: string; objective: string; plan: string; queries: string[]; questions: string[]; timestamp: number; }; event: 'planning:end'; } | { data: { hasPrefetchedContext: boolean; message: string; timestamp: number; }; event: 'planning:start'; } | { data: { failed: number; fetched: number; message: string; timestamp: number; }; event: 'prefetching:end'; } | { data: { message: string; timestamp: number; urlCount: number; urls: string[]; }; event: 'prefetching:start'; } | { data: { iteration: number; message: string; timestamp: number; urlsFound: number; urlsNew: number; }; event: 'searching:end'; } | { data: { iteration: number; message: string; queries: string[]; timestamp: number; }; event: 'searching:start'; } | { data: { message: string; timestamp: number; }; event: 'start'; } | { data: { attempt: number; message: string; timestamp: number; }; event: 'writing:end'; } | { data: { attempt: number; isRevision: boolean; maxAttempts: number; message: string; timestamp: number; previousScore?: number; }; event: 'writing:start'; }`\n A Server-Sent Event from /v1/research. Typed discriminated union keyed on event.\n\n### Example\n\n```typescript\nimport Tabstack from '@tabstack/sdk';\n\nconst client = new Tabstack();\n\nconst stream = await client.agent.research({ query: 'What are the latest developments in quantum computing?' });\nfor await (const researchEvent of stream) {\n console.log(researchEvent);\n}\n```", + "## research\n\n`client.agent.research(query: string, fetch_timeout?: number, mode?: 'fast' | 'balanced', nocache?: boolean): { data: object; event: 'analyzing:end'; } | { data: object; event: 'analyzing:start'; } | { data: object; event: 'complete'; } | { data: object; event: 'error'; } | { data: object; event: 'evaluating:end'; } | { data: object; event: 'evaluating:start'; } | { data: object; event: 'following:end'; } | { data: object; event: 'following:start'; } | { data: object; event: 'iteration:end'; } | { data: object; event: 'iteration:start'; } | { data: object; event: 'judging:end'; } | { data: object; event: 'judging:start'; } | { data: object; event: 'outlining:end'; } | { data: object; event: 'outlining:start'; } | { data: object; event: 'planning:end'; } | { data: object; event: 'planning:start'; } | { data: object; event: 'prefetching:end'; } | { data: object; event: 'prefetching:start'; } | { data: object; event: 'searching:end'; } | { data: object; event: 'searching:start'; } | { data: object; event: 'start'; } | { data: object; event: 'writing:end'; } | { data: object; event: 'writing:start'; }`\n\n**post** `/research`\n\nExecute AI-powered research queries that search the web, analyze sources, and synthesize comprehensive answers. This endpoint **always streams** responses using Server-Sent Events (SSE).\n\n**Streaming Response:**\n- All responses are streamed using Server-Sent Events (`text/event-stream`)\n- Real-time progress updates as research progresses through phases\n\n**Research Modes:**\n- `fast` - Quick answers with minimal web searches (default)\n- `balanced` - Standard research with multiple iterations\n\n**Use Cases:**\n- Answering complex questions with cited sources\n- Synthesizing information from multiple web sources\n- Research reports on specific topics\n- Fact-checking and verification tasks\n\n### Parameters\n\n- `query: string`\n The research query or question to answer. Maximum 10,000 characters.\n\n- `fetch_timeout?: number`\n Timeout in seconds for fetching web pages\n\n- `mode?: 'fast' | 'balanced'`\n Research mode: fast (quick answers, default), balanced (standard research)\n\n- `nocache?: boolean`\n Skip cache and force fresh research\n\n### Returns\n\n- `{ data: { analyzed: number; failed: number; iteration: number; message: string; samples: { domain: string; title: string; url: string; urlSource: 'user-input' | 'search-result' | 'extracted-link'; relevance?: 'low' | 'medium' | 'high'; reliability?: 'low' | 'medium' | 'high'; summary?: string; }[]; timestamp: number; }; event: 'analyzing:end'; } | { data: { iteration: number; message: string; pageCount: number; timestamp: number; }; event: 'analyzing:start'; } | { data: { message: string; metadata: { executedQueries: string[][]; mode: 'fast' | 'balanced' | 'deep' | 'max' | 'ultra'; prompt: string; queryComplexity: 'simple' | 'moderate' | 'complex'; researchObjective: string; researchPlan: string; researchQuestions: string[]; totalPagesAnalyzed: number; citedPages?: object[]; gapEvaluations?: object[]; judgments?: object[]; metrics?: object; outline?: object; urlSources?: object; }; report: string; timestamp: number; }; event: 'complete'; } | { data: { error: { message: string; name: string; stack?: string; }; message: string; timestamp: number; activity?: string; iteration?: number; }; event: 'error'; } | { data: { coverage: 'Light' | 'Moderate' | 'Solid' | 'Comprehensive'; gaps: string; iteration: number; message: string; nextQueries: string[]; questionAssessments: object[]; shouldContinue: boolean; timestamp: number; }; event: 'evaluating:end'; } | { data: { iteration: number; message: string; pagesAnalyzed: number; questionCount: number; timestamp: number; }; event: 'evaluating:start'; } | { data: { failed: number; followed: number; iteration: number; message: string; samples: { domain: string; title: string; url: string; urlSource: 'user-input' | 'search-result' | 'extracted-link'; relevance?: 'low' | 'medium' | 'high'; reliability?: 'low' | 'medium' | 'high'; summary?: string; }[]; timestamp: number; }; event: 'following:end'; } | { data: { iteration: number; linkCount: number; message: string; timestamp: number; }; event: 'following:start'; } | { data: { isLast: boolean; iteration: number; message: string; timestamp: number; stopReason?: 'max_iterations' | 'coverage_sufficient'; }; event: 'iteration:end'; } | { data: { iteration: number; maxIterations: number; message: string; queries: string[]; timestamp: number; }; event: 'iteration:start'; } | { data: { approved: boolean; attempt: number; message: string; score: number; timestamp: number; feedback?: string; }; event: 'judging:end'; } | { data: { attempt: number; maxAttempts: number; message: string; timestamp: number; }; event: 'judging:start'; } | { data: { message: string; sourcesSelected: number; timestamp: number; }; event: 'outlining:end'; } | { data: { message: string; pagesAnalyzed: number; qualityPageCount: number; timestamp: number; }; event: 'outlining:start'; } | { data: { complexity: 'simple' | 'moderate' | 'complex'; message: string; objective: string; plan: string; queries: string[]; questions: string[]; timestamp: number; }; event: 'planning:end'; } | { data: { hasPrefetchedContext: boolean; message: string; timestamp: number; }; event: 'planning:start'; } | { data: { failed: number; fetched: number; message: string; timestamp: number; }; event: 'prefetching:end'; } | { data: { message: string; timestamp: number; urlCount: number; urls: string[]; }; event: 'prefetching:start'; } | { data: { iteration: number; message: string; timestamp: number; urlsFound: number; urlsNew: number; }; event: 'searching:end'; } | { data: { iteration: number; message: string; queries: string[]; timestamp: number; }; event: 'searching:start'; } | { data: { message: string; timestamp: number; }; event: 'start'; } | { data: { attempt: number; message: string; timestamp: number; }; event: 'writing:end'; } | { data: { attempt: number; isRevision: boolean; maxAttempts: number; message: string; timestamp: number; previousScore?: number; }; event: 'writing:start'; }`\n A Server-Sent Event from /v1/research. Typed discriminated union keyed on event.\n\n### Example\n\n```typescript\nimport Tabstack from '@tabstack/sdk';\n\nconst client = new Tabstack();\n\nconst stream = await client.agent.research({ query: 'What are the latest developments in quantum computing?' });\nfor await (const researchEvent of stream) {\n console.log(researchEvent);\n}\n```", perLanguage: { typescript: { method: 'client.agent.research', diff --git a/src/client.ts b/src/client.ts index d17a3d3..1c64324 100644 --- a/src/client.ts +++ b/src/client.ts @@ -25,6 +25,8 @@ import { AgentResearchParams, AutomateEvent, ResearchEvent, + V1GlobalBuffer, + V1ResearchQuestionAssessment, } from './resources/agent'; import { Extract, @@ -762,6 +764,8 @@ export declare namespace Tabstack { Agent as Agent, type AutomateEvent as AutomateEvent, type ResearchEvent as ResearchEvent, + type V1GlobalBuffer as V1GlobalBuffer, + type V1ResearchQuestionAssessment as V1ResearchQuestionAssessment, type AgentAutomateInputResponse as AgentAutomateInputResponse, type AgentAutomateParams as AgentAutomateParams, type AgentAutomateInputParams as AgentAutomateInputParams, @@ -781,4 +785,6 @@ export declare namespace Tabstack { type GenerateJsonResponse as GenerateJsonResponse, type GenerateJsonParams as GenerateJsonParams, }; + + export type GeotargetGeoTarget = API.GeotargetGeoTarget; } diff --git a/src/resources/agent.ts b/src/resources/agent.ts index 9e35967..9047448 100644 --- a/src/resources/agent.ts +++ b/src/resources/agent.ts @@ -1,6 +1,8 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; +import * as AgentAPI from './agent'; +import * as Shared from './shared'; import { APIPromise } from '../core/api-promise'; import { Stream } from '../core/streaming'; import { buildHeaders } from '../internal/headers'; @@ -488,7 +490,7 @@ export namespace AutomateEvent { * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer * - URL: a URL that points to the image */ - image: string | Image.UnionMember1 | Image.ByteLength | Image.V1GlobalBuffer; + image: string | Image.UnionMember1 | Image.ByteLength | AgentAPI.V1GlobalBuffer; type: 'image'; @@ -538,26 +540,6 @@ export namespace AutomateEvent { export interface ByteLength { byteLength: number; } - - export interface V1GlobalBuffer { - buffer: V1GlobalBuffer.Buffer; - - byteLength: number; - - byteOffset: number; - - BYTES_PER_ELEMENT: number; - - length: number; - - [k: string]: number | V1GlobalBuffer.Buffer | undefined; - } - - export namespace V1GlobalBuffer { - export interface Buffer { - byteLength: number; - } - } } /** @@ -570,7 +552,7 @@ export namespace AutomateEvent { * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer * - URL: a URL that points to the image */ - data: string | File.UnionMember1 | File.ByteLength | File.V1GlobalBuffer; + data: string | File.UnionMember1 | File.ByteLength | AgentAPI.V1GlobalBuffer; /** * IANA media type of the file. @@ -625,26 +607,6 @@ export namespace AutomateEvent { export interface ByteLength { byteLength: number; } - - export interface V1GlobalBuffer { - buffer: V1GlobalBuffer.Buffer; - - byteLength: number; - - byteOffset: number; - - BYTES_PER_ELEMENT: number; - - length: number; - - [k: string]: number | V1GlobalBuffer.Buffer | undefined; - } - - export namespace V1GlobalBuffer { - export interface Buffer { - byteLength: number; - } - } } } @@ -726,7 +688,7 @@ export namespace AutomateEvent { * - data: a base64-encoded string, a Uint8Array, an ArrayBuffer, or a Buffer * - URL: a URL that points to the image */ - data: string | File.UnionMember1 | File.ByteLength | File.V1GlobalBuffer; + data: string | File.UnionMember1 | File.ByteLength | AgentAPI.V1GlobalBuffer; /** * IANA media type of the file. @@ -781,26 +743,6 @@ export namespace AutomateEvent { export interface ByteLength { byteLength: number; } - - export interface V1GlobalBuffer { - buffer: V1GlobalBuffer.Buffer; - - byteLength: number; - - byteOffset: number; - - BYTES_PER_ELEMENT: number; - - length: number; - - [k: string]: number | V1GlobalBuffer.Buffer | undefined; - } - - export namespace V1GlobalBuffer { - export interface Buffer { - byteLength: number; - } - } } /** @@ -3014,7 +2956,7 @@ export namespace ResearchEvent { /** * Assessment of each research question's status and findings */ - questionAssessments: Array; + questionAssessments: Array; /** * Research coverage level - assesses quality across all questions. @@ -3059,29 +3001,6 @@ export namespace ResearchEvent { searchQueries?: Array; } - export namespace GapEvaluation { - /** - * Assessment of a single research question - */ - export interface QuestionAssessment { - /** - * What we learned (if answered/partial) or what's missing (if unanswered) - */ - findings: string; - - /** - * The research question being assessed - */ - question: string; - - /** - * Status: answered (clear info), partial (some info, gaps remain), unanswered (no - * relevant info) - */ - status: 'answered' | 'partial' | 'unanswered'; - } - } - /** * Judgment result from research judge */ @@ -3273,35 +3192,12 @@ export namespace ResearchEvent { nextQueries: Array; - questionAssessments: Array; + questionAssessments: Array; shouldContinue: boolean; timestamp: number; } - - export namespace Data { - /** - * Assessment of a single research question - */ - export interface QuestionAssessment { - /** - * What we learned (if answered/partial) or what's missing (if unanswered) - */ - findings: string; - - /** - * The research question being assessed - */ - question: string; - - /** - * Status: answered (clear info), partial (some info, gaps remain), unanswered (no - * relevant info) - */ - status: 'answered' | 'partial' | 'unanswered'; - } - } } /** @@ -3768,6 +3664,47 @@ export namespace ResearchEvent { } } +export interface V1GlobalBuffer { + buffer: V1GlobalBuffer.Buffer; + + byteLength: number; + + byteOffset: number; + + BYTES_PER_ELEMENT: number; + + length: number; + + [k: string]: number | V1GlobalBuffer.Buffer | undefined; +} + +export namespace V1GlobalBuffer { + export interface Buffer { + byteLength: number; + } +} + +/** + * Assessment of a single research question + */ +export interface V1ResearchQuestionAssessment { + /** + * What we learned (if answered/partial) or what's missing (if unanswered) + */ + findings: string; + + /** + * The research question being assessed + */ + question: string; + + /** + * Status: answered (clear info), partial (some info, gaps remain), unanswered (no + * relevant info) + */ + status: 'answered' | 'partial' | 'unanswered'; +} + export interface AgentAutomateInputResponse { status?: string; } @@ -3786,7 +3723,7 @@ export interface AgentAutomateParams { /** * Optional geotargeting parameters for proxy requests */ - geo_target?: AgentAutomateParams.GeoTarget; + geo_target?: Shared.GeotargetGeoTarget; /** * Safety constraints for execution @@ -3814,19 +3751,6 @@ export interface AgentAutomateParams { url?: string; } -export namespace AgentAutomateParams { - /** - * Optional geotargeting parameters for proxy requests - */ - export interface GeoTarget { - /** - * Country code using ISO 3166-1 alpha-2 standard (2 letters, e.g., "US", "GB", - * "JP"). See: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 - */ - country?: string; - } -} - export interface AgentAutomateInputParams { /** * Set to true to cancel/decline the request @@ -3873,6 +3797,8 @@ export declare namespace Agent { export { type AutomateEvent as AutomateEvent, type ResearchEvent as ResearchEvent, + type V1GlobalBuffer as V1GlobalBuffer, + type V1ResearchQuestionAssessment as V1ResearchQuestionAssessment, type AgentAutomateInputResponse as AgentAutomateInputResponse, type AgentAutomateParams as AgentAutomateParams, type AgentAutomateInputParams as AgentAutomateInputParams, diff --git a/src/resources/extract.ts b/src/resources/extract.ts index 4f871cb..ca0b186 100644 --- a/src/resources/extract.ts +++ b/src/resources/extract.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; +import * as Shared from './shared'; import { APIPromise } from '../core/api-promise'; import { RequestOptions } from '../internal/request-options'; @@ -196,7 +197,7 @@ export interface ExtractJsonParams { /** * Optional geotargeting parameters for proxy requests */ - geo_target?: ExtractJsonParams.GeoTarget; + geo_target?: Shared.GeotargetGeoTarget; /** * Bypass cache and force fresh data retrieval @@ -204,19 +205,6 @@ export interface ExtractJsonParams { nocache?: boolean; } -export namespace ExtractJsonParams { - /** - * Optional geotargeting parameters for proxy requests - */ - export interface GeoTarget { - /** - * Country code using ISO 3166-1 alpha-2 standard (2 letters, e.g., "US", "GB", - * "JP"). See: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 - */ - country?: string; - } -} - export interface ExtractMarkdownParams { /** * URL to fetch and convert to markdown @@ -233,7 +221,7 @@ export interface ExtractMarkdownParams { /** * Optional geotargeting parameters for proxy requests */ - geo_target?: ExtractMarkdownParams.GeoTarget; + geo_target?: Shared.GeotargetGeoTarget; /** * Include extracted metadata (Open Graph and HTML metadata) as a separate field in @@ -247,19 +235,6 @@ export interface ExtractMarkdownParams { nocache?: boolean; } -export namespace ExtractMarkdownParams { - /** - * Optional geotargeting parameters for proxy requests - */ - export interface GeoTarget { - /** - * Country code using ISO 3166-1 alpha-2 standard (2 letters, e.g., "US", "GB", - * "JP"). See: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 - */ - country?: string; - } -} - export declare namespace Extract { export { type ExtractJsonResponse as ExtractJsonResponse, diff --git a/src/resources/generate.ts b/src/resources/generate.ts index 18aca46..70939bc 100644 --- a/src/resources/generate.ts +++ b/src/resources/generate.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; +import * as Shared from './shared'; import { APIPromise } from '../core/api-promise'; import { RequestOptions } from '../internal/request-options'; @@ -74,7 +75,7 @@ export interface GenerateJsonParams { /** * Optional geotargeting parameters for proxy requests */ - geo_target?: GenerateJsonParams.GeoTarget; + geo_target?: Shared.GeotargetGeoTarget; /** * Bypass cache and force fresh data retrieval @@ -82,19 +83,6 @@ export interface GenerateJsonParams { nocache?: boolean; } -export namespace GenerateJsonParams { - /** - * Optional geotargeting parameters for proxy requests - */ - export interface GeoTarget { - /** - * Country code using ISO 3166-1 alpha-2 standard (2 letters, e.g., "US", "GB", - * "JP"). See: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 - */ - country?: string; - } -} - export declare namespace Generate { export { type GenerateJsonResponse as GenerateJsonResponse, type GenerateJsonParams as GenerateJsonParams }; } diff --git a/src/resources/index.ts b/src/resources/index.ts index 1cc30e7..d92728a 100644 --- a/src/resources/index.ts +++ b/src/resources/index.ts @@ -1,9 +1,12 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. +export * from './shared'; export { Agent, type AutomateEvent, type ResearchEvent, + type V1GlobalBuffer, + type V1ResearchQuestionAssessment, type AgentAutomateInputResponse, type AgentAutomateParams, type AgentAutomateInputParams, diff --git a/src/resources/shared.ts b/src/resources/shared.ts new file mode 100644 index 0000000..095e4e1 --- /dev/null +++ b/src/resources/shared.ts @@ -0,0 +1,9 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +export interface GeotargetGeoTarget { + /** + * Country code using ISO 3166-1 alpha-2 standard (2 letters, e.g., "US", "GB", + * "JP"). See: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 + */ + country?: string; +} From 38141cdcb428b4e5016fa44d4c4378279159f020 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 15:36:17 +0000 Subject: [PATCH 10/10] release: 2.6.1 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 18 ++++++++++++++++++ package.json | 2 +- packages/mcp-server/manifest.json | 2 +- packages/mcp-server/package.json | 2 +- packages/mcp-server/src/server.ts | 2 +- src/version.ts | 2 +- 7 files changed, 24 insertions(+), 6 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 69e82f1..8ff2f5e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.6.0" + ".": "2.6.1" } diff --git a/CHANGELOG.md b/CHANGELOG.md index b8edaf9..d4ef133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +## 2.6.1 (2026-05-05) + +Full Changelog: [v2.6.0...v2.6.1](https://github.com/Mozilla-Ocho/tabstack-typescript/compare/v2.6.0...v2.6.1) + +### Features + +* **api:** add endpoint specfic timeouts ([4d6bd2e](https://github.com/Mozilla-Ocho/tabstack-typescript/commit/4d6bd2ec28d2424f239fd7fc763e0ed394f43a51)) +* **api:** manual updates ([cc20909](https://github.com/Mozilla-Ocho/tabstack-typescript/commit/cc209097670fa44ec405ed1740681d4a12f50586)) +* **automate:** emit task:trace_context SSE event with trace ID ([51cc989](https://github.com/Mozilla-Ocho/tabstack-typescript/commit/51cc9894ca8b828dcfe5413e3cee66384b071149)) +* support setting headers via env ([dc80807](https://github.com/Mozilla-Ocho/tabstack-typescript/commit/dc80807af38c51ce4a041a6ba331c62897aace6d)) + + +### Chores + +* avoid formatting file that gets changed during releases ([8bcebec](https://github.com/Mozilla-Ocho/tabstack-typescript/commit/8bcebec347f5b03762e7ff725a3c19a4425c0d3b)) +* **format:** run eslint and prettier separately ([0d94d58](https://github.com/Mozilla-Ocho/tabstack-typescript/commit/0d94d58968327fc93081582f0e4aa52c73ef3a77)) +* **internal:** codegen related update ([8ee7235](https://github.com/Mozilla-Ocho/tabstack-typescript/commit/8ee7235bb02f5696aa8f0682b5c91d18a9755eac)) + ## 2.6.0 (2026-04-24) Full Changelog: [v2.5.0...v2.6.0](https://github.com/Mozilla-Ocho/tabstack-typescript/compare/v2.5.0...v2.6.0) diff --git a/package.json b/package.json index 68a2514..59fa072 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@tabstack/sdk", - "version": "2.6.0", + "version": "2.6.1", "description": "The official TypeScript library for the Tabstack API", "author": "Tabstack <>", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index 480ecb7..3852213 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -1,7 +1,7 @@ { "dxt_version": "0.2", "name": "@tabstack/sdk-mcp", - "version": "2.6.0", + "version": "2.6.1", "description": "The official MCP Server for the Tabstack API", "author": { "name": "Tabstack" diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 4005555..26e9757 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "@tabstack/sdk-mcp", - "version": "2.6.0", + "version": "2.6.1", "description": "The official MCP Server for the Tabstack API", "author": "Tabstack <>", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index 96d5ca0..4434401 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -28,7 +28,7 @@ export const newMcpServer = async ({ new McpServer( { name: 'tabstack_sdk_api', - version: '2.6.0', + version: '2.6.1', }, { instructions: await getInstructions({ stainlessApiKey, customInstructionsPath }), diff --git a/src/version.ts b/src/version.ts index cc6e4a8..f9d065f 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '2.6.0'; // x-release-please-version +export const VERSION = '2.6.1'; // x-release-please-version