From dc895a6f73ace40d48d008ba447d80d1283061aa Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 25 Jul 2026 07:12:54 +0000 Subject: [PATCH 1/3] feat(api): api update --- .stats.yml | 4 +- packages/mcp-server/src/local-docs-search.ts | 22 ++-- src/resources/monitors.ts | 119 ++++++++++--------- tests/api-resources/monitors.test.ts | 18 +-- 4 files changed, 82 insertions(+), 81 deletions(-) diff --git a/.stats.yml b/.stats.yml index 0ac1eb3..6da4682 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 32 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-242450ea46eb8c3e843fd6c4bf87e73192b5f62f6da697cd091d13c6aa7a991b.yml -openapi_spec_hash: c1c561976de1abcacede71fd5ab9b3d9 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-2bf2b44f6593c44b2948683469bbb2b09cd8e90c97b12057fac6220cf0d2eee7.yml +openapi_spec_hash: ae8b5109ec997cac8d3e6ec96040f6c8 config_hash: 70e7e80b5e87f94981bee396c6cd41e8 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index a392002..0675fc2 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -1180,52 +1180,52 @@ const EMBEDDED_METHODS: MethodEntry[] = [ stainlessPath: '(resource) monitors > (method) create', qualified: 'client.monitors.create', params: [ - "change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; };", 'name: string;', - "schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; };", "target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; };", + "change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; };", "mode?: 'web';", + "schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; };", 'tags?: string[];', "webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; };", ], response: - "{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }", + "{ id: string; change_detection: object | object; created_at: string; initial_run_id: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }", markdown: - "## create\n\n`client.monitors.create(change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }, name: string, schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }, target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }, mode?: 'web', tags?: string[], webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }): { id: string; change_detection: object | object; created_at: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }`\n\n**post** `/monitors`\n\nCreates a monitor. The request body is a union of the supported target/change detection combinations. The monitor runs immediately after creation to create its initial baseline.\n\n### Parameters\n\n- `change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n Discriminated union describing how changes are detected.\n\n- `name: string`\n\n- `schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n Run the monitor on a fixed interval defined by a frequency and a unit, e.g. every 6 hours or every 2 days. The total interval (frequency × unit) must be between 10 minutes and 1 year.\n - `frequency: number`\n Number of units between runs. The resulting interval (frequency × unit) must be at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; maximum 365 when unit is days).\n - `type: 'interval'`\n - `unit: 'minutes' | 'hours' | 'days'`\n\n- `target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n Discriminated union describing what the monitor watches.\n\n- `mode?: 'web'`\n Top-level monitor category. Always `web` today; the concrete behavior is described by `target` and `change_detection`.\n\n- `tags?: string[]`\n User-defined tags for grouping and filtering monitors and their changes. Duplicates are removed.\n\n- `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `url: string`\n Webhook URL events are delivered to.\n - `events?: 'change.detected' | 'run.completed'[]`\n Events delivered to this endpoint. `change.detected` fires only when a run detects a change; `run.completed` fires on every completed run — including runs that detected no change — and embeds the change when one was detected. Defaults to `[\"change.detected\"]` when omitted.\n - `secret?: string`\n Signing secret used to verify webhook authenticity. Each delivery includes an `X-Context-Signature: t=,v1=` header, where the HMAC is SHA-256 over `\"{t}.{rawRequestBody}\"` keyed by this secret. Recompute it with a constant-time compare and reject stale timestamps to prevent replay. Generated by the API; cannot be set by clients.\n\n### Returns\n\n- `{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }`\n A web monitor. `mode` is the constant `web`; behavior is described by `target` (page/sitemap/extract) and `change_detection` (exact/semantic).\n\n - `id: string`\n - `change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n - `created_at: string`\n - `mode: 'web'`\n - `name: string`\n - `schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n - `status: 'active' | 'paused' | 'failed'`\n - `target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n - `updated_at: string`\n - `baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }`\n - `last_change_at?: string`\n - `last_error?: { code: string; message: string; }`\n - `last_run_at?: string`\n - `next_run_at?: string`\n - `tags?: string[]`\n - `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitor = await client.monitors.create({\n change_detection: { type: 'exact' },\n name: 'Acme pricing page',\n schedule: {\n frequency: 6,\n type: 'interval',\n unit: 'hours',\n},\n target: { type: 'page', url: 'https://acme.com/pricing' },\n});\n\nconsole.log(monitor);\n```", + "## create\n\n`client.monitors.create(name: string, target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }, change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }, mode?: 'web', schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }, tags?: string[], webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }): { id: string; change_detection: object | object; created_at: string; initial_run_id: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }`\n\n**post** `/monitors`\n\nCreates a monitor. The request body is a union of the supported target/change detection combinations. The monitor runs immediately after creation to create its initial baseline.\n\n### Parameters\n\n- `name: string`\n\n- `target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n Discriminated union describing what the monitor watches.\n\n- `change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n Discriminated union describing how changes are detected.\n\n- `mode?: 'web'`\n Top-level monitor category. Always `web` today; the concrete behavior is described by `target` and `change_detection`.\n\n- `schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n Run the monitor on a fixed interval defined by a frequency and a unit, e.g. every 6 hours or every 2 days. The total interval (frequency × unit) must be between 10 minutes and 1 year.\n - `frequency: number`\n Number of units between runs. The resulting interval (frequency × unit) must be at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; maximum 365 when unit is days).\n - `type: 'interval'`\n - `unit: 'minutes' | 'hours' | 'days'`\n\n- `tags?: string[]`\n User-defined tags for grouping and filtering monitors and their changes. Duplicates are removed.\n\n- `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `url: string`\n Webhook URL events are delivered to.\n - `events?: 'change.detected' | 'run.completed'[]`\n Events delivered to this endpoint. `change.detected` fires only when a run detects a change; `run.completed` fires on every completed run — including runs that detected no change — and embeds the change when one was detected. Defaults to `[\"change.detected\"]` when omitted.\n - `secret?: string`\n Signing secret used to verify webhook authenticity. Each delivery includes an `X-Context-Signature: t=,v1=` header, where the HMAC is SHA-256 over `\"{t}.{rawRequestBody}\"` keyed by this secret. Recompute it with a constant-time compare and reject stale timestamps to prevent replay. Generated by the API; cannot be set by clients.\n\n### Returns\n\n- `{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; initial_run_id: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }`\n A newly created monitor plus `initial_run_id`, the id of the baseline run queued at creation.\n\n - `id: string`\n - `change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n - `created_at: string`\n - `initial_run_id: string`\n - `mode: 'web'`\n - `name: string`\n - `schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n - `status: 'active' | 'paused' | 'failed'`\n - `target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n - `updated_at: string`\n - `baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }`\n - `last_change_at?: string`\n - `last_error?: { code: string; message: string; }`\n - `last_run_at?: string`\n - `next_run_at?: string`\n - `tags?: string[]`\n - `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitor = await client.monitors.create({\n name: 'Acme pricing page',\n target: { type: 'page', url: 'https://acme.com/pricing' },\n});\n\nconsole.log(monitor);\n```", perLanguage: { typescript: { method: 'client.monitors.create', example: - "import ContextDev from 'context.dev';\n\nconst client = new ContextDev({\n apiKey: process.env['CONTEXT_DEV_API_KEY'], // This is the default and can be omitted\n});\n\nconst monitor = await client.monitors.create({\n change_detection: { type: 'exact' },\n name: 'Acme pricing page',\n schedule: {\n type: 'interval',\n frequency: 6,\n unit: 'hours',\n },\n target: { type: 'page', url: 'https://acme.com/pricing' },\n mode: 'web',\n webhook: { url: 'https://example.com/webhook' },\n});\n\nconsole.log(monitor.id);", + "import ContextDev from 'context.dev';\n\nconst client = new ContextDev({\n apiKey: process.env['CONTEXT_DEV_API_KEY'], // This is the default and can be omitted\n});\n\nconst monitor = await client.monitors.create({\n name: 'Acme pricing page',\n target: { type: 'page', url: 'https://acme.com/pricing' },\n change_detection: { type: 'exact' },\n mode: 'web',\n schedule: {\n type: 'interval',\n frequency: 6,\n unit: 'hours',\n },\n webhook: { url: 'https://example.com/webhook' },\n});\n\nconsole.log(monitor.id);", }, python: { method: 'monitors.create', example: - 'import os\nfrom context.dev import ContextDev\n\nclient = ContextDev(\n api_key=os.environ.get("CONTEXT_DEV_API_KEY"), # This is the default and can be omitted\n)\nmonitor = client.monitors.create(\n change_detection={\n "type": "exact"\n },\n name="Acme pricing page",\n schedule={\n "type": "interval",\n "frequency": 6,\n "unit": "hours",\n },\n target={\n "type": "page",\n "url": "https://acme.com/pricing",\n },\n mode="web",\n webhook={\n "url": "https://example.com/webhook"\n },\n)\nprint(monitor.id)', + 'import os\nfrom context.dev import ContextDev\n\nclient = ContextDev(\n api_key=os.environ.get("CONTEXT_DEV_API_KEY"), # This is the default and can be omitted\n)\nmonitor = client.monitors.create(\n name="Acme pricing page",\n target={\n "type": "page",\n "url": "https://acme.com/pricing",\n },\n change_detection={\n "type": "exact"\n },\n mode="web",\n schedule={\n "type": "interval",\n "frequency": 6,\n "unit": "hours",\n },\n webhook={\n "url": "https://example.com/webhook"\n },\n)\nprint(monitor.id)', }, go: { method: 'client.Monitors.New', example: - 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/context-dot-dev/context-go-sdk"\n\t"github.com/context-dot-dev/context-go-sdk/option"\n)\n\nfunc main() {\n\tclient := contextdev.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tmonitor, err := client.Monitors.New(context.TODO(), contextdev.MonitorNewParams{\n\t\tChangeDetection: contextdev.MonitorNewParamsChangeDetectionUnion{\n\t\t\tOfExact: &contextdev.MonitorNewParamsChangeDetectionExact{},\n\t\t},\n\t\tName: "Acme pricing page",\n\t\tSchedule: contextdev.MonitorNewParamsSchedule{\n\t\t\tType: "interval",\n\t\t\tFrequency: 6,\n\t\t\tUnit: "hours",\n\t\t},\n\t\tTarget: contextdev.MonitorNewParamsTargetUnion{\n\t\t\tOfPage: &contextdev.MonitorNewParamsTargetPage{\n\t\t\t\tURL: "https://acme.com/pricing",\n\t\t\t},\n\t\t},\n\t\tMode: contextdev.MonitorNewParamsModeWeb,\n\t\tWebhook: contextdev.MonitorNewParamsWebhook{\n\t\t\tURL: "https://example.com/webhook",\n\t\t},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", monitor.ID)\n}\n', + 'package main\n\nimport (\n\t"context"\n\t"fmt"\n\n\t"github.com/context-dot-dev/context-go-sdk"\n\t"github.com/context-dot-dev/context-go-sdk/option"\n)\n\nfunc main() {\n\tclient := contextdev.NewClient(\n\t\toption.WithAPIKey("My API Key"),\n\t)\n\tmonitor, err := client.Monitors.New(context.TODO(), contextdev.MonitorNewParams{\n\t\tName: "Acme pricing page",\n\t\tTarget: contextdev.MonitorNewParamsTargetUnion{\n\t\t\tOfPage: &contextdev.MonitorNewParamsTargetPage{\n\t\t\t\tURL: "https://acme.com/pricing",\n\t\t\t},\n\t\t},\n\t\tChangeDetection: contextdev.MonitorNewParamsChangeDetectionUnion{\n\t\t\tOfExact: &contextdev.MonitorNewParamsChangeDetectionExact{},\n\t\t},\n\t\tMode: contextdev.MonitorNewParamsModeWeb,\n\t\tSchedule: contextdev.MonitorNewParamsSchedule{\n\t\t\tType: "interval",\n\t\t\tFrequency: 6,\n\t\t\tUnit: "hours",\n\t\t},\n\t\tWebhook: contextdev.MonitorNewParamsWebhook{\n\t\t\tURL: "https://example.com/webhook",\n\t\t},\n\t})\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf("%+v\\n", monitor.ID)\n}\n', }, ruby: { method: 'monitors.create', example: - 'require "context_dev"\n\ncontext_dev = ContextDev::Client.new(api_key: "My API Key")\n\nmonitor = context_dev.monitors.create(\n change_detection: {type: :exact},\n name: "Acme pricing page",\n schedule: {frequency: 6, type: :interval, unit: :hours},\n target: {type: :page, url: "https://acme.com/pricing"}\n)\n\nputs(monitor)', + 'require "context_dev"\n\ncontext_dev = ContextDev::Client.new(api_key: "My API Key")\n\nmonitor = context_dev.monitors.create(\n name: "Acme pricing page",\n target: {type: :page, url: "https://acme.com/pricing"}\n)\n\nputs(monitor)', }, cli: { method: 'monitors create', example: - "context-dev monitors create \\\n --api-key 'My API Key' \\\n --change-detection '{type: exact}' \\\n --name 'Acme pricing page' \\\n --schedule '{frequency: 6, type: interval, unit: hours}' \\\n --target '{type: page, url: https://acme.com/pricing}'", + "context-dev monitors create \\\n --api-key 'My API Key' \\\n --name 'Acme pricing page' \\\n --target '{type: page, url: https://acme.com/pricing}'", }, php: { method: 'monitors->create', example: - "monitors->create(\n changeDetection: ['type' => 'exact'],\n name: 'Acme pricing page',\n schedule: ['frequency' => 6, 'type' => 'interval', 'unit' => 'hours'],\n target: [\n 'type' => 'page',\n 'url' => 'https://acme.com/pricing',\n 'normalizeWhitespace' => true,\n ],\n mode: 'web',\n tags: ['pricing', 'competitor'],\n webhook: [\n 'url' => 'https://example.com/webhook',\n 'events' => ['change.detected', 'run.completed'],\n ],\n);\n\nvar_dump($monitor);", + "monitors->create(\n name: 'Acme pricing page',\n target: [\n 'type' => 'page',\n 'url' => 'https://acme.com/pricing',\n 'normalizeWhitespace' => true,\n ],\n changeDetection: ['type' => 'exact'],\n mode: 'web',\n schedule: ['frequency' => 6, 'type' => 'interval', 'unit' => 'hours'],\n tags: ['pricing', 'competitor'],\n webhook: [\n 'url' => 'https://example.com/webhook',\n 'events' => ['change.detected', 'run.completed'],\n ],\n);\n\nvar_dump($monitor);", }, http: { example: - 'curl https://api.context.dev/v1/monitors \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \\\n -d \'{\n "change_detection": {\n "type": "exact"\n },\n "name": "Acme pricing page",\n "schedule": {\n "frequency": 6,\n "type": "interval",\n "unit": "hours"\n },\n "target": {\n "type": "page",\n "url": "https://acme.com/pricing"\n },\n "mode": "web",\n "tags": [\n "pricing",\n "competitor"\n ],\n "webhook": {\n "url": "https://example.com/webhook"\n }\n }\'', + 'curl https://api.context.dev/v1/monitors \\\n -H \'Content-Type: application/json\' \\\n -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \\\n -d \'{\n "name": "Acme pricing page",\n "target": {\n "type": "page",\n "url": "https://acme.com/pricing"\n },\n "change_detection": {\n "type": "exact"\n },\n "mode": "web",\n "schedule": {\n "frequency": 6,\n "type": "interval",\n "unit": "hours"\n },\n "tags": [\n "pricing",\n "competitor"\n ],\n "webhook": {\n "url": "https://example.com/webhook"\n }\n }\'', }, }, }, diff --git a/src/resources/monitors.ts b/src/resources/monitors.ts index 9d8d990..ab0b610 100644 --- a/src/resources/monitors.ts +++ b/src/resources/monitors.ts @@ -18,15 +18,15 @@ export class Monitors extends APIResource { * @example * ```ts * const monitor = await client.monitors.create({ - * change_detection: { type: 'exact' }, * name: 'Acme pricing page', + * target: { type: 'page', url: 'https://acme.com/pricing' }, + * change_detection: { type: 'exact' }, + * mode: 'web', * schedule: { * type: 'interval', * frequency: 6, * unit: 'hours', * }, - * target: { type: 'page', url: 'https://acme.com/pricing' }, - * mode: 'web', * webhook: { url: 'https://example.com/webhook' }, * }); * ``` @@ -262,8 +262,8 @@ export namespace WebhookDelivery { } /** - * A web monitor. `mode` is the constant `web`; behavior is described by `target` - * (page/sitemap/extract) and `change_detection` (exact/semantic). + * A newly created monitor plus `initial_run_id`, the id of the baseline run queued + * at creation. */ export interface MonitorCreateResponse { id: string; @@ -277,6 +277,13 @@ export interface MonitorCreateResponse { created_at: string; + /** + * The baseline run queued by this create call, or null if it could not be queued + * immediately (in which case the baseline runs on the next scheduled tick). Poll + * GET /monitors/{monitor_id}/runs/{run_id}. + */ + initial_run_id: string | null; + /** * Top-level monitor category. Always `web` today; the concrete behavior is * described by `target` and `change_detection`. @@ -2062,22 +2069,8 @@ export interface MonitorRunResponse { } export interface MonitorCreateParams { - /** - * Discriminated union describing how changes are detected. - */ - change_detection: - | MonitorCreateParams.MonitorsExactChangeDetection - | MonitorCreateParams.MonitorsSemanticChangeDetection; - name: string; - /** - * Run the monitor on a fixed interval defined by a frequency and a unit, e.g. - * every 6 hours or every 2 days. The total interval (frequency × unit) must be - * between 10 minutes and 1 year. - */ - schedule: MonitorCreateParams.Schedule; - /** * Discriminated union describing what the monitor watches. */ @@ -2086,12 +2079,26 @@ export interface MonitorCreateParams { | MonitorCreateParams.MonitorsSitemapTarget | MonitorCreateParams.MonitorsExtractTarget; + /** + * Discriminated union describing how changes are detected. + */ + change_detection?: + | MonitorCreateParams.MonitorsExactChangeDetection + | MonitorCreateParams.MonitorsSemanticChangeDetection; + /** * Top-level monitor category. Always `web` today; the concrete behavior is * described by `target` and `change_detection`. */ mode?: 'web'; + /** + * Run the monitor on a fixed interval defined by a frequency and a unit, e.g. + * every 6 hours or every 2 days. The total interval (frequency × unit) must be + * between 10 minutes and 1 year. + */ + schedule?: MonitorCreateParams.Schedule; + /** * User-defined tags for grouping and filtering monitors and their changes. * Duplicates are removed. @@ -2102,43 +2109,6 @@ export interface MonitorCreateParams { } export namespace MonitorCreateParams { - /** - * Detect exact changes. For page targets, this means visible text diffs. For - * sitemap targets, this means URL additions and removals. - */ - export interface MonitorsExactChangeDetection { - type: 'exact'; - } - - /** - * Detect meaning-level changes to tracked page content, ignoring cosmetic or - * paraphrase-only differences. Which changes are meaningful is judged against the - * extract target's `instructions` (and `schema`, when provided). - */ - export interface MonitorsSemanticChangeDetection { - type: 'semantic'; - - confidence_threshold?: number; - } - - /** - * Run the monitor on a fixed interval defined by a frequency and a unit, e.g. - * every 6 hours or every 2 days. The total interval (frequency × unit) must be - * between 10 minutes and 1 year. - */ - export interface Schedule { - /** - * Number of units between runs. The resulting interval (frequency × unit) must be - * at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; - * maximum 365 when unit is days). - */ - frequency: number; - - type: 'interval'; - - unit: 'minutes' | 'hours' | 'days'; - } - /** * Watch a single web page. */ @@ -2230,6 +2200,43 @@ export namespace MonitorCreateParams { schema?: { [key: string]: unknown }; } + /** + * Detect exact changes. For page targets, this means visible text diffs. For + * sitemap targets, this means URL additions and removals. + */ + export interface MonitorsExactChangeDetection { + type: 'exact'; + } + + /** + * Detect meaning-level changes to tracked page content, ignoring cosmetic or + * paraphrase-only differences. Which changes are meaningful is judged against the + * extract target's `instructions` (and `schema`, when provided). + */ + export interface MonitorsSemanticChangeDetection { + type: 'semantic'; + + confidence_threshold?: number; + } + + /** + * Run the monitor on a fixed interval defined by a frequency and a unit, e.g. + * every 6 hours or every 2 days. The total interval (frequency × unit) must be + * between 10 minutes and 1 year. + */ + export interface Schedule { + /** + * Number of units between runs. The resulting interval (frequency × unit) must be + * at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; + * maximum 365 when unit is days). + */ + frequency: number; + + type: 'interval'; + + unit: 'minutes' | 'hours' | 'days'; + } + export interface Webhook { /** * Webhook URL events are delivered to. diff --git a/tests/api-resources/monitors.test.ts b/tests/api-resources/monitors.test.ts index 26a89f3..fa69e07 100644 --- a/tests/api-resources/monitors.test.ts +++ b/tests/api-resources/monitors.test.ts @@ -11,13 +11,7 @@ describe('resource monitors', () => { // Mock server tests are disabled test.skip('create: only required params', async () => { const responsePromise = client.monitors.create({ - change_detection: { type: 'exact' }, name: 'Acme pricing page', - schedule: { - frequency: 6, - type: 'interval', - unit: 'hours', - }, target: { type: 'page', url: 'https://acme.com/pricing' }, }); const rawResponse = await responsePromise.asResponse(); @@ -32,19 +26,19 @@ describe('resource monitors', () => { // Mock server tests are disabled test.skip('create: required and optional params', async () => { const response = await client.monitors.create({ - change_detection: { type: 'exact' }, name: 'Acme pricing page', - schedule: { - frequency: 6, - type: 'interval', - unit: 'hours', - }, target: { type: 'page', url: 'https://acme.com/pricing', normalize_whitespace: true, }, + change_detection: { type: 'exact' }, mode: 'web', + schedule: { + frequency: 6, + type: 'interval', + unit: 'hours', + }, tags: ['pricing', 'competitor'], webhook: { url: 'https://example.com/webhook', events: ['change.detected', 'run.completed'] }, }); From 09c34c9d22462550b52a3468818b28848a291cf9 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 06:43:25 +0000 Subject: [PATCH 2/3] feat(api): api update --- .stats.yml | 4 +- packages/mcp-server/src/local-docs-search.ts | 20 ++-- src/resources/monitors.ts | 96 +++++++++++++++----- tests/api-resources/monitors.test.ts | 2 + 4 files changed, 86 insertions(+), 36 deletions(-) diff --git a/.stats.yml b/.stats.yml index 6da4682..3f4cd2e 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 32 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-2bf2b44f6593c44b2948683469bbb2b09cd8e90c97b12057fac6220cf0d2eee7.yml -openapi_spec_hash: ae8b5109ec997cac8d3e6ec96040f6c8 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/context-dev/context.dev-91f4286859fc23813c5255b877395c87dd81520c3913fdfdae3cfa343e1a4873.yml +openapi_spec_hash: 71746b5b65f20617ee021e071d5f7f92 config_hash: 70e7e80b5e87f94981bee396c6cd41e8 diff --git a/packages/mcp-server/src/local-docs-search.ts b/packages/mcp-server/src/local-docs-search.ts index 0675fc2..6b45eca 100644 --- a/packages/mcp-server/src/local-docs-search.ts +++ b/packages/mcp-server/src/local-docs-search.ts @@ -1181,7 +1181,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.monitors.create', params: [ 'name: string;', - "target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; };", + "target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; };", "change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; };", "mode?: 'web';", "schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; };", @@ -1191,7 +1191,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ id: string; change_detection: object | object; created_at: string; initial_run_id: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }", markdown: - "## create\n\n`client.monitors.create(name: string, target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }, change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }, mode?: 'web', schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }, tags?: string[], webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }): { id: string; change_detection: object | object; created_at: string; initial_run_id: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }`\n\n**post** `/monitors`\n\nCreates a monitor. The request body is a union of the supported target/change detection combinations. The monitor runs immediately after creation to create its initial baseline.\n\n### Parameters\n\n- `name: string`\n\n- `target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n Discriminated union describing what the monitor watches.\n\n- `change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n Discriminated union describing how changes are detected.\n\n- `mode?: 'web'`\n Top-level monitor category. Always `web` today; the concrete behavior is described by `target` and `change_detection`.\n\n- `schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n Run the monitor on a fixed interval defined by a frequency and a unit, e.g. every 6 hours or every 2 days. The total interval (frequency × unit) must be between 10 minutes and 1 year.\n - `frequency: number`\n Number of units between runs. The resulting interval (frequency × unit) must be at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; maximum 365 when unit is days).\n - `type: 'interval'`\n - `unit: 'minutes' | 'hours' | 'days'`\n\n- `tags?: string[]`\n User-defined tags for grouping and filtering monitors and their changes. Duplicates are removed.\n\n- `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `url: string`\n Webhook URL events are delivered to.\n - `events?: 'change.detected' | 'run.completed'[]`\n Events delivered to this endpoint. `change.detected` fires only when a run detects a change; `run.completed` fires on every completed run — including runs that detected no change — and embeds the change when one was detected. Defaults to `[\"change.detected\"]` when omitted.\n - `secret?: string`\n Signing secret used to verify webhook authenticity. Each delivery includes an `X-Context-Signature: t=,v1=` header, where the HMAC is SHA-256 over `\"{t}.{rawRequestBody}\"` keyed by this secret. Recompute it with a constant-time compare and reject stale timestamps to prevent replay. Generated by the API; cannot be set by clients.\n\n### Returns\n\n- `{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; initial_run_id: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }`\n A newly created monitor plus `initial_run_id`, the id of the baseline run queued at creation.\n\n - `id: string`\n - `change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n - `created_at: string`\n - `initial_run_id: string`\n - `mode: 'web'`\n - `name: string`\n - `schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n - `status: 'active' | 'paused' | 'failed'`\n - `target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n - `updated_at: string`\n - `baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }`\n - `last_change_at?: string`\n - `last_error?: { code: string; message: string; }`\n - `last_run_at?: string`\n - `next_run_at?: string`\n - `tags?: string[]`\n - `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitor = await client.monitors.create({\n name: 'Acme pricing page',\n target: { type: 'page', url: 'https://acme.com/pricing' },\n});\n\nconsole.log(monitor);\n```", + "## create\n\n`client.monitors.create(name: string, target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }, change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }, mode?: 'web', schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }, tags?: string[], webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }): { id: string; change_detection: object | object; created_at: string; initial_run_id: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }`\n\n**post** `/monitors`\n\nCreates a monitor. The request body is a union of the supported target/change detection combinations. The monitor runs immediately after creation to create its initial baseline.\n\n### Parameters\n\n- `name: string`\n\n- `target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n Discriminated union describing what the monitor watches.\n\n- `change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n Discriminated union describing how changes are detected.\n\n- `mode?: 'web'`\n Top-level monitor category. Always `web` today; the concrete behavior is described by `target` and `change_detection`.\n\n- `schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n Run the monitor on a fixed interval defined by a frequency and a unit, e.g. every 6 hours or every 2 days. The total interval (frequency × unit) must be between 10 minutes and 1 year.\n - `frequency: number`\n Number of units between runs. The resulting interval (frequency × unit) must be at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; maximum 365 when unit is days).\n - `type: 'interval'`\n - `unit: 'minutes' | 'hours' | 'days'`\n\n- `tags?: string[]`\n User-defined tags for grouping and filtering monitors and their changes. Duplicates are removed.\n\n- `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `url: string`\n Webhook URL events are delivered to.\n - `events?: 'change.detected' | 'run.completed'[]`\n Events delivered to this endpoint. `change.detected` fires only when a run detects a change; `run.completed` fires on every completed run — including runs that detected no change — and embeds the change when one was detected. Defaults to `[\"change.detected\"]` when omitted.\n - `secret?: string`\n Signing secret used to verify webhook authenticity. Each delivery includes an `X-Context-Signature: t=,v1=` header, where the HMAC is SHA-256 over `\"{t}.{rawRequestBody}\"` keyed by this secret. Recompute it with a constant-time compare and reject stale timestamps to prevent replay. Generated by the API; cannot be set by clients.\n\n### Returns\n\n- `{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; initial_run_id: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }`\n A newly created monitor plus `initial_run_id`, the id of the baseline run queued at creation.\n\n - `id: string`\n - `change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n - `created_at: string`\n - `initial_run_id: string`\n - `mode: 'web'`\n - `name: string`\n - `schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n - `status: 'active' | 'paused' | 'failed'`\n - `target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n - `updated_at: string`\n - `baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }`\n - `last_change_at?: string`\n - `last_error?: { code: string; message: string; }`\n - `last_run_at?: string`\n - `next_run_at?: string`\n - `tags?: string[]`\n - `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitor = await client.monitors.create({\n name: 'Acme pricing page',\n target: { type: 'page', url: 'https://acme.com/pricing' },\n});\n\nconsole.log(monitor);\n```", perLanguage: { typescript: { method: 'client.monitors.create', @@ -1221,7 +1221,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ php: { method: 'monitors->create', example: - "monitors->create(\n name: 'Acme pricing page',\n target: [\n 'type' => 'page',\n 'url' => 'https://acme.com/pricing',\n 'normalizeWhitespace' => true,\n ],\n changeDetection: ['type' => 'exact'],\n mode: 'web',\n schedule: ['frequency' => 6, 'type' => 'interval', 'unit' => 'hours'],\n tags: ['pricing', 'competitor'],\n webhook: [\n 'url' => 'https://example.com/webhook',\n 'events' => ['change.detected', 'run.completed'],\n ],\n);\n\nvar_dump($monitor);", + "monitors->create(\n name: 'Acme pricing page',\n target: [\n 'type' => 'page',\n 'url' => 'https://acme.com/pricing',\n 'instructions' => 'Report pricing or plan availability changes. Ignore counters, timestamps, testimonials, and navigation.',\n 'normalizeWhitespace' => true,\n ],\n changeDetection: ['type' => 'exact'],\n mode: 'web',\n schedule: ['frequency' => 6, 'type' => 'interval', 'unit' => 'hours'],\n tags: ['pricing', 'competitor'],\n webhook: [\n 'url' => 'https://example.com/webhook',\n 'events' => ['change.detected', 'run.completed'],\n ],\n);\n\nvar_dump($monitor);", }, http: { example: @@ -1253,7 +1253,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ response: "{ data: { id: string; change_detection: object | object; created_at: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }[]; has_more: boolean; next_cursor: string; }", markdown: - "## list\n\n`client.monitors.list(change_detection_type?: 'exact' | 'semantic', cursor?: string, limit?: number, q?: string, search_by?: 'name' | 'url' | 'instructions' | 'tags'[], search_type?: 'exact' | 'prefix', status?: 'active' | 'paused' | 'failed', tag?: string, tags?: string[], target_type?: 'page' | 'sitemap' | 'extract'): { data: object[]; has_more: boolean; next_cursor: string; }`\n\n**get** `/monitors`\n\nLists monitors for the authenticated organization. Supports free-text search (`q` over `search_by` fields, `prefix` or `exact` via `search_type`) plus status/type/tag filters. Results are paginated via the opaque `cursor`.\n\n### Parameters\n\n- `change_detection_type?: 'exact' | 'semantic'`\n Filter by change detection type.\n\n- `cursor?: string`\n Opaque pagination cursor from a previous response.\n\n- `limit?: number`\n Maximum number of items to return per page (1-100). Defaults to 25.\n\n- `q?: string`\n Free-text search term, matched against the fields named in `search_by`.\n\n- `search_by?: 'name' | 'url' | 'instructions' | 'tags'[]`\n Comma-separated fields to search with `q`. Defaults to all of them. Note `instructions` only exists on extract monitors.\n\n- `search_type?: 'exact' | 'prefix'`\n `prefix` for as-you-type prefix matching (default), `exact` for full-token matching.\n\n- `status?: 'active' | 'paused' | 'failed'`\n Filter monitors by lifecycle status.\n\n- `tag?: string`\n Filter to items that have this tag.\n\n- `tags?: string[]`\n Comma-separated list of tags to filter by (matches monitors having any of them).\n\n- `target_type?: 'page' | 'sitemap' | 'extract'`\n Filter by target type.\n\n### Returns\n\n- `{ data: { id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }[]; has_more: boolean; next_cursor: string; }`\n\n - `data: { id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }[]`\n - `has_more: boolean`\n - `next_cursor: string`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitors = await client.monitors.list();\n\nconsole.log(monitors);\n```", + "## list\n\n`client.monitors.list(change_detection_type?: 'exact' | 'semantic', cursor?: string, limit?: number, q?: string, search_by?: 'name' | 'url' | 'instructions' | 'tags'[], search_type?: 'exact' | 'prefix', status?: 'active' | 'paused' | 'failed', tag?: string, tags?: string[], target_type?: 'page' | 'sitemap' | 'extract'): { data: object[]; has_more: boolean; next_cursor: string; }`\n\n**get** `/monitors`\n\nLists monitors for the authenticated organization. Supports free-text search (`q` over `search_by` fields, `prefix` or `exact` via `search_type`) plus status/type/tag filters. Results are paginated via the opaque `cursor`.\n\n### Parameters\n\n- `change_detection_type?: 'exact' | 'semantic'`\n Filter by change detection type.\n\n- `cursor?: string`\n Opaque pagination cursor from a previous response.\n\n- `limit?: number`\n Maximum number of items to return per page (1-100). Defaults to 25.\n\n- `q?: string`\n Free-text search term, matched against the fields named in `search_by`.\n\n- `search_by?: 'name' | 'url' | 'instructions' | 'tags'[]`\n Comma-separated fields to search with `q`. Defaults to all of them. Note `instructions` only exists on extract monitors.\n\n- `search_type?: 'exact' | 'prefix'`\n `prefix` for as-you-type prefix matching (default), `exact` for full-token matching.\n\n- `status?: 'active' | 'paused' | 'failed'`\n Filter monitors by lifecycle status.\n\n- `tag?: string`\n Filter to items that have this tag.\n\n- `tags?: string[]`\n Comma-separated list of tags to filter by (matches monitors having any of them).\n\n- `target_type?: 'page' | 'sitemap' | 'extract'`\n Filter by target type.\n\n### Returns\n\n- `{ data: { id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }[]; has_more: boolean; next_cursor: string; }`\n\n - `data: { id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }[]`\n - `has_more: boolean`\n - `next_cursor: string`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitors = await client.monitors.list();\n\nconsole.log(monitors);\n```", perLanguage: { typescript: { method: 'client.monitors.list', @@ -1300,9 +1300,9 @@ const EMBEDDED_METHODS: MethodEntry[] = [ qualified: 'client.monitors.retrieve', params: ['monitor_id: string;'], response: - "{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }", + "{ id: string; change_detection: object | object; created_at: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }", markdown: - "## retrieve\n\n`client.monitors.retrieve(monitor_id: string): { id: string; change_detection: object | object; created_at: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }`\n\n**get** `/monitors/{monitor_id}`\n\nGet a monitor\n\n### Parameters\n\n- `monitor_id: string`\n\n### Returns\n\n- `{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }`\n A web monitor. `mode` is the constant `web`; behavior is described by `target` (page/sitemap/extract) and `change_detection` (exact/semantic).\n\n - `id: string`\n - `change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n - `created_at: string`\n - `mode: 'web'`\n - `name: string`\n - `schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n - `status: 'active' | 'paused' | 'failed'`\n - `target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n - `updated_at: string`\n - `baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }`\n - `last_change_at?: string`\n - `last_error?: { code: string; message: string; }`\n - `last_run_at?: string`\n - `next_run_at?: string`\n - `tags?: string[]`\n - `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitor = await client.monitors.retrieve('mon_123');\n\nconsole.log(monitor);\n```", + "## retrieve\n\n`client.monitors.retrieve(monitor_id: string): { id: string; change_detection: object | object; created_at: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }`\n\n**get** `/monitors/{monitor_id}`\n\nGet a monitor\n\n### Parameters\n\n- `monitor_id: string`\n\n### Returns\n\n- `{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }`\n A web monitor. `mode` is the constant `web`; behavior is described by `target` (page/sitemap/extract) and `change_detection` (exact/semantic).\n\n - `id: string`\n - `change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n - `created_at: string`\n - `mode: 'web'`\n - `name: string`\n - `schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n - `status: 'active' | 'paused' | 'failed'`\n - `target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n - `updated_at: string`\n - `baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }`\n - `last_change_at?: string`\n - `last_error?: { code: string; message: string; }`\n - `last_run_at?: string`\n - `next_run_at?: string`\n - `tags?: string[]`\n - `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitor = await client.monitors.retrieve('mon_123');\n\nconsole.log(monitor);\n```", perLanguage: { typescript: { method: 'client.monitors.retrieve', @@ -1355,13 +1355,13 @@ const EMBEDDED_METHODS: MethodEntry[] = [ "schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; };", "status?: 'active' | 'paused';", 'tags?: string[];', - "target?: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; };", + "target?: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; };", "webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; };", ], response: - "{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }", + "{ id: string; change_detection: object | object; created_at: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }", markdown: - "## update\n\n`client.monitors.update(monitor_id: string, change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }, name?: string, schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }, status?: 'active' | 'paused', tags?: string[], target?: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }, webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }): { id: string; change_detection: object | object; created_at: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }`\n\n**patch** `/monitors/{monitor_id}`\n\nUpdates a monitor. If `target` or `change_detection` changes, the monitor creates a new baseline. Unsupported target/change detection combinations are rejected.\n\n### Parameters\n\n- `monitor_id: string`\n\n- `change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n Discriminated union describing how changes are detected.\n\n- `name?: string`\n\n- `schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n Run the monitor on a fixed interval defined by a frequency and a unit, e.g. every 6 hours or every 2 days. The total interval (frequency × unit) must be between 10 minutes and 1 year.\n - `frequency: number`\n Number of units between runs. The resulting interval (frequency × unit) must be at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; maximum 365 when unit is days).\n - `type: 'interval'`\n - `unit: 'minutes' | 'hours' | 'days'`\n\n- `status?: 'active' | 'paused'`\n\n- `tags?: string[]`\n User-defined tags for grouping and filtering monitors and their changes. Duplicates are removed.\n\n- `target?: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n Discriminated union describing what the monitor watches.\n\n- `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n Set to null to remove the webhook.\n - `url: string`\n Webhook URL events are delivered to.\n - `events?: 'change.detected' | 'run.completed'[]`\n Events delivered to this endpoint. `change.detected` fires only when a run detects a change; `run.completed` fires on every completed run — including runs that detected no change — and embeds the change when one was detected. Defaults to `[\"change.detected\"]` when omitted.\n - `secret?: string`\n Signing secret used to verify webhook authenticity. Each delivery includes an `X-Context-Signature: t=,v1=` header, where the HMAC is SHA-256 over `\"{t}.{rawRequestBody}\"` keyed by this secret. Recompute it with a constant-time compare and reject stale timestamps to prevent replay. Generated by the API; cannot be set by clients.\n\n### Returns\n\n- `{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }`\n A web monitor. `mode` is the constant `web`; behavior is described by `target` (page/sitemap/extract) and `change_detection` (exact/semantic).\n\n - `id: string`\n - `change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n - `created_at: string`\n - `mode: 'web'`\n - `name: string`\n - `schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n - `status: 'active' | 'paused' | 'failed'`\n - `target: { type: 'page'; url: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n - `updated_at: string`\n - `baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }`\n - `last_change_at?: string`\n - `last_error?: { code: string; message: string; }`\n - `last_run_at?: string`\n - `next_run_at?: string`\n - `tags?: string[]`\n - `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitor = await client.monitors.update('mon_123');\n\nconsole.log(monitor);\n```", + "## update\n\n`client.monitors.update(monitor_id: string, change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }, name?: string, schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }, status?: 'active' | 'paused', tags?: string[], target?: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }, webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }): { id: string; change_detection: object | object; created_at: string; mode: 'web'; name: string; schedule: object; status: 'active' | 'paused' | 'failed'; target: object | object | object; updated_at: string; baseline?: object | object | object; last_change_at?: string; last_error?: object; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: object; webhook_failure?: object; }`\n\n**patch** `/monitors/{monitor_id}`\n\nUpdates a monitor. If `target` or `change_detection` changes, the monitor creates a new baseline. Unsupported target/change detection combinations are rejected.\n\n### Parameters\n\n- `monitor_id: string`\n\n- `change_detection?: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n Discriminated union describing how changes are detected.\n\n- `name?: string`\n\n- `schedule?: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n Run the monitor on a fixed interval defined by a frequency and a unit, e.g. every 6 hours or every 2 days. The total interval (frequency × unit) must be between 10 minutes and 1 year.\n - `frequency: number`\n Number of units between runs. The resulting interval (frequency × unit) must be at least 10 minutes and at most 1 year (e.g. minimum 10 when unit is minutes; maximum 365 when unit is days).\n - `type: 'interval'`\n - `unit: 'minutes' | 'hours' | 'days'`\n\n- `status?: 'active' | 'paused'`\n\n- `tags?: string[]`\n User-defined tags for grouping and filtering monitors and their changes. Duplicates are removed.\n\n- `target?: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n Discriminated union describing what the monitor watches.\n\n- `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n Set to null to remove the webhook.\n - `url: string`\n Webhook URL events are delivered to.\n - `events?: 'change.detected' | 'run.completed'[]`\n Events delivered to this endpoint. `change.detected` fires only when a run detects a change; `run.completed` fires on every completed run — including runs that detected no change — and embeds the change when one was detected. Defaults to `[\"change.detected\"]` when omitted.\n - `secret?: string`\n Signing secret used to verify webhook authenticity. Each delivery includes an `X-Context-Signature: t=,v1=` header, where the HMAC is SHA-256 over `\"{t}.{rawRequestBody}\"` keyed by this secret. Recompute it with a constant-time compare and reject stale timestamps to prevent replay. Generated by the API; cannot be set by clients.\n\n### Returns\n\n- `{ id: string; change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }; created_at: string; mode: 'web'; name: string; schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }; status: 'active' | 'paused' | 'failed'; target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }; updated_at: string; baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }; last_change_at?: string; last_error?: { code: string; message: string; }; last_run_at?: string; next_run_at?: string; tags?: string[]; webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }; webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }; }`\n A web monitor. `mode` is the constant `web`; behavior is described by `target` (page/sitemap/extract) and `change_detection` (exact/semantic).\n\n - `id: string`\n - `change_detection: { type: 'exact'; } | { type: 'semantic'; confidence_threshold?: number; }`\n - `created_at: string`\n - `mode: 'web'`\n - `name: string`\n - `schedule: { frequency: number; type: 'interval'; unit: 'minutes' | 'hours' | 'days'; }`\n - `status: 'active' | 'paused' | 'failed'`\n - `target: { type: 'page'; url: string; instructions?: string; normalize_whitespace?: boolean; } | { type: 'sitemap'; url: string; exclude?: string[]; include?: string[]; max_urls?: number; } | { instructions: string; type: 'extract'; url: string; follow_subdomains?: boolean; max_depth?: number; max_pages?: number; schema?: object; }`\n - `updated_at: string`\n - `baseline?: { captured_at: string; text: string; } | { captured_at: string; url_count: number; urls: string[]; } | { captured_at: string; data: object; urls_analyzed: string[]; }`\n - `last_change_at?: string`\n - `last_error?: { code: string; message: string; }`\n - `last_run_at?: string`\n - `next_run_at?: string`\n - `tags?: string[]`\n - `webhook?: { url: string; events?: 'change.detected' | 'run.completed'[]; secret?: string; }`\n - `webhook_failure?: { consecutive_failures: number; last_failed_at: string; last_message: string; last_status: 'rejected' | 'failed' | 'skipped_unsafe_url'; }`\n\n### Example\n\n```typescript\nimport ContextDev from 'context.dev';\n\nconst client = new ContextDev();\n\nconst monitor = await client.monitors.update('mon_123');\n\nconsole.log(monitor);\n```", perLanguage: { typescript: { method: 'client.monitors.update', @@ -1390,7 +1390,7 @@ const EMBEDDED_METHODS: MethodEntry[] = [ php: { method: 'monitors->update', example: - "monitors->update(\n 'mon_123',\n changeDetection: ['type' => 'exact'],\n name: 'Acme pricing monitor',\n schedule: ['frequency' => 1, 'type' => 'interval', 'unit' => 'hours'],\n status: 'active',\n tags: ['pricing', 'competitor'],\n target: [\n 'type' => 'page',\n 'url' => 'https://acme.com/pricing',\n 'normalizeWhitespace' => true,\n ],\n webhook: [\n 'url' => 'https://example.com/webhook',\n 'events' => ['change.detected', 'run.completed'],\n ],\n);\n\nvar_dump($monitor);", + "monitors->update(\n 'mon_123',\n changeDetection: ['type' => 'exact'],\n name: 'Acme pricing monitor',\n schedule: ['frequency' => 1, 'type' => 'interval', 'unit' => 'hours'],\n status: 'active',\n tags: ['pricing', 'competitor'],\n target: [\n 'type' => 'page',\n 'url' => 'https://acme.com/pricing',\n 'instructions' => 'Report pricing or plan availability changes. Ignore counters, timestamps, testimonials, and navigation.',\n 'normalizeWhitespace' => true,\n ],\n webhook: [\n 'url' => 'https://example.com/webhook',\n 'events' => ['change.detected', 'run.completed'],\n ],\n);\n\nvar_dump($monitor);", }, http: { example: diff --git a/src/resources/monitors.ts b/src/resources/monitors.ts index ab0b610..e2f6302 100644 --- a/src/resources/monitors.ts +++ b/src/resources/monitors.ts @@ -370,9 +370,10 @@ export namespace MonitorCreateResponse { } /** - * Detect meaning-level changes to tracked page content, ignoring cosmetic or - * paraphrase-only differences. Which changes are meaningful is judged against the - * extract target's `instructions` (and `schema`, when provided). + * Detect meaning-level changes to page content, ignoring cosmetic or + * instruction-irrelevant differences. Which changes are meaningful is judged + * against the page or extract target's `instructions` (and an extract target's + * `schema`, when provided). */ export interface MonitorsSemanticChangeDetection { type: 'semantic'; @@ -399,13 +400,20 @@ export namespace MonitorCreateResponse { } /** - * Watch a single web page. + * Watch a single web page. Exact detection reports visible-text diffs; semantic + * detection judges confirmed stable diffs against `instructions`. */ export interface MonitorsPageTarget { type: 'page'; url: string; + /** + * Plain-language goal describing which page changes matter. When provided without + * change_detection, semantic detection is inferred. + */ + instructions?: string; + /** * Normalize whitespace before comparing or analyzing text. */ @@ -711,9 +719,10 @@ export namespace MonitorRetrieveResponse { } /** - * Detect meaning-level changes to tracked page content, ignoring cosmetic or - * paraphrase-only differences. Which changes are meaningful is judged against the - * extract target's `instructions` (and `schema`, when provided). + * Detect meaning-level changes to page content, ignoring cosmetic or + * instruction-irrelevant differences. Which changes are meaningful is judged + * against the page or extract target's `instructions` (and an extract target's + * `schema`, when provided). */ export interface MonitorsSemanticChangeDetection { type: 'semantic'; @@ -740,13 +749,20 @@ export namespace MonitorRetrieveResponse { } /** - * Watch a single web page. + * Watch a single web page. Exact detection reports visible-text diffs; semantic + * detection judges confirmed stable diffs against `instructions`. */ export interface MonitorsPageTarget { type: 'page'; url: string; + /** + * Plain-language goal describing which page changes matter. When provided without + * change_detection, semantic detection is inferred. + */ + instructions?: string; + /** * Normalize whitespace before comparing or analyzing text. */ @@ -1052,9 +1068,10 @@ export namespace MonitorUpdateResponse { } /** - * Detect meaning-level changes to tracked page content, ignoring cosmetic or - * paraphrase-only differences. Which changes are meaningful is judged against the - * extract target's `instructions` (and `schema`, when provided). + * Detect meaning-level changes to page content, ignoring cosmetic or + * instruction-irrelevant differences. Which changes are meaningful is judged + * against the page or extract target's `instructions` (and an extract target's + * `schema`, when provided). */ export interface MonitorsSemanticChangeDetection { type: 'semantic'; @@ -1081,13 +1098,20 @@ export namespace MonitorUpdateResponse { } /** - * Watch a single web page. + * Watch a single web page. Exact detection reports visible-text diffs; semantic + * detection judges confirmed stable diffs against `instructions`. */ export interface MonitorsPageTarget { type: 'page'; url: string; + /** + * Plain-language goal describing which page changes matter. When provided without + * change_detection, semantic detection is inferred. + */ + instructions?: string; + /** * Normalize whitespace before comparing or analyzing text. */ @@ -1393,9 +1417,10 @@ export namespace MonitorListResponse { } /** - * Detect meaning-level changes to tracked page content, ignoring cosmetic or - * paraphrase-only differences. Which changes are meaningful is judged against the - * extract target's `instructions` (and `schema`, when provided). + * Detect meaning-level changes to page content, ignoring cosmetic or + * instruction-irrelevant differences. Which changes are meaningful is judged + * against the page or extract target's `instructions` (and an extract target's + * `schema`, when provided). */ export interface MonitorsSemanticChangeDetection { type: 'semantic'; @@ -1422,13 +1447,20 @@ export namespace MonitorListResponse { } /** - * Watch a single web page. + * Watch a single web page. Exact detection reports visible-text diffs; semantic + * detection judges confirmed stable diffs against `instructions`. */ export interface MonitorsPageTarget { type: 'page'; url: string; + /** + * Plain-language goal describing which page changes matter. When provided without + * change_detection, semantic detection is inferred. + */ + instructions?: string; + /** * Normalize whitespace before comparing or analyzing text. */ @@ -2110,13 +2142,20 @@ export interface MonitorCreateParams { export namespace MonitorCreateParams { /** - * Watch a single web page. + * Watch a single web page. Exact detection reports visible-text diffs; semantic + * detection judges confirmed stable diffs against `instructions`. */ export interface MonitorsPageTarget { type: 'page'; url: string; + /** + * Plain-language goal describing which page changes matter. When provided without + * change_detection, semantic detection is inferred. + */ + instructions?: string; + /** * Normalize whitespace before comparing or analyzing text. */ @@ -2209,9 +2248,10 @@ export namespace MonitorCreateParams { } /** - * Detect meaning-level changes to tracked page content, ignoring cosmetic or - * paraphrase-only differences. Which changes are meaningful is judged against the - * extract target's `instructions` (and `schema`, when provided). + * Detect meaning-level changes to page content, ignoring cosmetic or + * instruction-irrelevant differences. Which changes are meaningful is judged + * against the page or extract target's `instructions` (and an extract target's + * `schema`, when provided). */ export interface MonitorsSemanticChangeDetection { type: 'semantic'; @@ -2302,9 +2342,10 @@ export namespace MonitorUpdateParams { } /** - * Detect meaning-level changes to tracked page content, ignoring cosmetic or - * paraphrase-only differences. Which changes are meaningful is judged against the - * extract target's `instructions` (and `schema`, when provided). + * Detect meaning-level changes to page content, ignoring cosmetic or + * instruction-irrelevant differences. Which changes are meaningful is judged + * against the page or extract target's `instructions` (and an extract target's + * `schema`, when provided). */ export interface MonitorsSemanticChangeDetection { type: 'semantic'; @@ -2331,13 +2372,20 @@ export namespace MonitorUpdateParams { } /** - * Watch a single web page. + * Watch a single web page. Exact detection reports visible-text diffs; semantic + * detection judges confirmed stable diffs against `instructions`. */ export interface MonitorsPageTarget { type: 'page'; url: string; + /** + * Plain-language goal describing which page changes matter. When provided without + * change_detection, semantic detection is inferred. + */ + instructions?: string; + /** * Normalize whitespace before comparing or analyzing text. */ diff --git a/tests/api-resources/monitors.test.ts b/tests/api-resources/monitors.test.ts index fa69e07..cd7c960 100644 --- a/tests/api-resources/monitors.test.ts +++ b/tests/api-resources/monitors.test.ts @@ -30,6 +30,8 @@ describe('resource monitors', () => { target: { type: 'page', url: 'https://acme.com/pricing', + instructions: + 'Report pricing or plan availability changes. Ignore counters, timestamps, testimonials, and navigation.', normalize_whitespace: true, }, change_detection: { type: 'exact' }, From 623b1d6b9455eb5002bc0e63178db70544dc08e1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 27 Jul 2026 06:43:50 +0000 Subject: [PATCH 3/3] release: 2.7.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ 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, 15 insertions(+), 6 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 69e82f1..6ed9c80 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "2.6.0" + ".": "2.7.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 54d170a..bf8ef66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 2.7.0 (2026-07-27) + +Full Changelog: [v2.6.0...v2.7.0](https://github.com/context-dot-dev/context-typescript-sdk/compare/v2.6.0...v2.7.0) + +### Features + +* **api:** api update ([09c34c9](https://github.com/context-dot-dev/context-typescript-sdk/commit/09c34c9d22462550b52a3468818b28848a291cf9)) +* **api:** api update ([dc895a6](https://github.com/context-dot-dev/context-typescript-sdk/commit/dc895a6f73ace40d48d008ba447d80d1283061aa)) + ## 2.6.0 (2026-07-22) Full Changelog: [v2.5.0...v2.6.0](https://github.com/context-dot-dev/context-typescript-sdk/compare/v2.5.0...v2.6.0) diff --git a/package.json b/package.json index 008caa7..2c4dd1a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "context.dev", - "version": "2.6.0", + "version": "2.7.0", "description": "The official TypeScript library for the Context Dev API", "author": "Context Dev ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/manifest.json b/packages/mcp-server/manifest.json index a024e4d..82f5835 100644 --- a/packages/mcp-server/manifest.json +++ b/packages/mcp-server/manifest.json @@ -1,7 +1,7 @@ { "dxt_version": "0.2", "name": "context.dev-mcp", - "version": "2.6.0", + "version": "2.7.0", "description": "The official MCP Server for the Context Dev API", "author": { "name": "Context Dev", diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index d964768..f80a63e 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "context.dev-mcp", - "version": "2.6.0", + "version": "2.7.0", "description": "The official MCP Server for the Context Dev API", "author": "Context Dev ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index a954c9b..b8ff8c7 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: 'context_dev_api', - version: '2.6.0', + version: '2.7.0', }, { instructions: await getInstructions({ stainlessApiKey, customInstructionsPath }), diff --git a/src/version.ts b/src/version.ts index cc6e4a8..9556c21 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.7.0'; // x-release-please-version