@cursor/july 0.1.99 → 0.1.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -2
- package/dist/channels/github/defaults.d.ts.map +1 -1
- package/dist/channels/github/defaults.js +28 -3
- package/dist/channels/github/progress.d.ts +7 -0
- package/dist/channels/github/progress.d.ts.map +1 -1
- package/dist/channels/slack/api.d.ts +16 -7
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +29 -13
- package/dist/channels/slack/constants.d.ts +6 -0
- package/dist/channels/slack/constants.d.ts.map +1 -1
- package/dist/channels/slack/constants.js +6 -0
- package/dist/channels/slack/defaults.d.ts +9 -4
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +154 -76
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +3 -3
- package/dist/channels/slack/inbound.d.ts +9 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +14 -0
- package/dist/channels/slack/index.d.ts +1 -0
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +1 -0
- package/dist/channels/slack/live-delivery.d.ts +5 -0
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +107 -19
- package/dist/channels/slack/reasoning-card.d.ts +38 -0
- package/dist/channels/slack/reasoning-card.d.ts.map +1 -0
- package/dist/channels/slack/reasoning-card.js +104 -0
- package/dist/channels/slack/redact.d.ts +2 -0
- package/dist/channels/slack/redact.d.ts.map +1 -0
- package/dist/channels/slack/redact.js +5 -0
- package/dist/channels/slack/reply-options.d.ts +40 -0
- package/dist/channels/slack/reply-options.d.ts.map +1 -0
- package/dist/channels/slack/reply-options.js +150 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +8 -4
- package/dist/channels/slack/stream.d.ts +22 -10
- package/dist/channels/slack/stream.d.ts.map +1 -1
- package/dist/channels/slack/stream.js +9 -16
- package/dist/channels/slack/tool-cards.d.ts +22 -0
- package/dist/channels/slack/tool-cards.d.ts.map +1 -0
- package/dist/channels/slack/tool-cards.js +178 -0
- package/dist/channels/slack/types.d.ts +145 -6
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +6 -6
- package/dist/docs/ab.md +1 -1
- package/dist/docs/assets/{ab.md.DJo5r4R-.js → ab.md.mlVgqvSk.js} +1 -1
- package/dist/docs/assets/{app.BplEAZ3S.js → app.DZ1e0Ycq.js} +1 -1
- package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.js → building-with-agents.md.CUSWxlP_.js} +2 -2
- package/dist/docs/assets/chunks/@localSearchIndexroot.j70vvPL4.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CHXyv4wP.js → VPLocalSearchBox.l8omwc6D.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BTcsZmjQ.js → theme.JVcD6gel.js} +2 -2
- package/dist/docs/assets/{evals.md.lfJoEVc8.js → evals.md.CPzDAwoH.js} +1 -1
- package/dist/docs/assets/{guides_github.md.Cnh2mL4a.js → guides_github.md.BtPr9GaP.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.js → guides_mcp-oauth.md.Dp6cDP7f.js} +1 -1
- package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.js → guides_opentelemetry.md.BVTXDCRg.js} +2 -2
- package/dist/docs/assets/{guides_slack.md.VDXQV3ja.js → guides_slack.md.9oHPye9o.js} +19 -3
- package/dist/docs/assets/{guides_slack.md.VDXQV3ja.lean.js → guides_slack.md.9oHPye9o.lean.js} +1 -1
- package/dist/docs/assets/hillclimbing.md.CpTGTCle.js +4 -0
- package/dist/docs/assets/{index.md.CVeRUOeZ.js → index.md.Bb4k8kUm.js} +1 -1
- package/dist/docs/assets/{quickstart.md.Nj_LjW_a.js → quickstart.md.DdQOF7Y8.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.DxldvyIB.js → reference_connections.md.BiGoBAk2.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.em43xlY1.js +1 -0
- package/dist/docs/assets/skills_ab.md.CsFNatVx.js +26 -0
- package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +1 -0
- package/dist/docs/assets/skills_create-agent.md.BVoWPcan.js +8 -0
- package/dist/docs/assets/skills_create-agent.md.BVoWPcan.lean.js +1 -0
- package/dist/docs/assets/skills_debug.md.CDbPhHfg.js +1 -0
- package/dist/docs/assets/skills_debug.md.CDbPhHfg.lean.js +1 -0
- package/dist/docs/assets/skills_evals.md.723kpUmA.js +25 -0
- package/dist/docs/assets/skills_evals.md.723kpUmA.lean.js +1 -0
- package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +1 -0
- package/dist/docs/assets/skills_framework-map.md.BTi817yv.lean.js +1 -0
- package/dist/docs/assets/skills_github.md.D0JahM8c.js +16 -0
- package/dist/docs/assets/skills_github.md.D0JahM8c.lean.js +1 -0
- package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.js +7 -0
- package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.lean.js +1 -0
- package/dist/docs/assets/skills_index.md.DKwIxzGg.js +1 -0
- package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +1 -0
- package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.js +18 -0
- package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.lean.js +1 -0
- package/dist/docs/assets/skills_otel.md.CgiZryR3.js +8 -0
- package/dist/docs/assets/skills_otel.md.CgiZryR3.lean.js +1 -0
- package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.js +20 -0
- package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.lean.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.js → troubleshooting.md.Cus_YZga.js} +1 -1
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/building-with-agents.md +14 -11
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +6 -6
- package/dist/docs/evals.md +1 -1
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +5 -5
- package/dist/docs/guides/github.md +1 -1
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +5 -5
- package/dist/docs/guides/mcp-oauth.md +1 -1
- package/dist/docs/guides/opentelemetry.html +7 -7
- package/dist/docs/guides/opentelemetry.md +2 -2
- package/dist/docs/guides/slack.html +22 -6
- package/dist/docs/guides/slack.md +80 -1
- package/dist/docs/guides/webhooks.html +5 -5
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/hillclimbing.md +5 -5
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +1 -1
- package/dist/docs/llms-full.txt +1041 -30
- package/dist/docs/llms.txt +14 -0
- package/dist/docs/quickstart.html +5 -5
- package/dist/docs/quickstart.md +1 -1
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +4 -4
- package/dist/docs/reference/connections.html +6 -6
- package/dist/docs/reference/connections.md +1 -1
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +4 -4
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/scaffolding-agents.md +3 -3
- package/dist/docs/skills/ab.html +52 -0
- package/dist/docs/skills/ab.md +50 -0
- package/dist/docs/skills/create-agent.html +34 -0
- package/dist/docs/skills/create-agent.md +160 -0
- package/dist/docs/skills/debug.html +27 -0
- package/dist/docs/skills/debug.md +36 -0
- package/dist/docs/skills/evals.html +51 -0
- package/dist/docs/skills/evals.md +99 -0
- package/dist/docs/skills/framework-map.html +27 -0
- package/dist/docs/skills/framework-map.md +95 -0
- package/dist/docs/skills/github.html +42 -0
- package/dist/docs/skills/github.md +93 -0
- package/dist/docs/skills/hillclimb.html +33 -0
- package/dist/docs/skills/hillclimb.md +55 -0
- package/dist/docs/skills/index.html +27 -0
- package/dist/docs/skills/index.md +21 -0
- package/dist/docs/skills/mcp-auth.html +44 -0
- package/dist/docs/skills/mcp-auth.md +76 -0
- package/dist/docs/skills/otel.html +34 -0
- package/dist/docs/skills/otel.md +48 -0
- package/dist/docs/skills/setup-slack.html +46 -0
- package/dist/docs/skills/setup-slack.md +141 -0
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +4 -4
- package/dist/docs/templates/code-wiki.html +4 -4
- package/dist/docs/templates/demo.html +4 -4
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +4 -4
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +1 -1
- package/dist/files-backends/cursor-hosted.d.ts +6 -0
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +6 -9
- package/dist/internal/cli-deploy.js +2 -2
- package/dist/internal/conversation-mirror.d.ts.map +1 -1
- package/dist/internal/conversation-mirror.js +3 -4
- package/dist/internal/cursor/hosted-store-secrets.d.ts +15 -0
- package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -0
- package/dist/internal/cursor/hosted-store-secrets.js +48 -0
- package/dist/internal/deploy-client.d.ts +6 -6
- package/dist/internal/deploy-client.js +7 -7
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +11 -1
- package/dist/internal/framework-file-storage.d.ts +12 -5
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +36 -5
- package/dist/internal/framework-storage-selection.d.ts +12 -12
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +33 -39
- package/dist/internal/session-run-log.d.ts +3 -3
- package/dist/internal/session-run-log.d.ts.map +1 -1
- package/dist/internal/session-run-log.js +6 -7
- package/dist/internal/storage-coordinator.d.ts +0 -6
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +1 -9
- package/dist/playground/assets/index-BszoQDc6.css +1 -0
- package/dist/playground/assets/{index-jzNbJENa.js → index-DVs98vPL.js} +1 -1
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted-v2.d.ts +83 -0
- package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -0
- package/dist/storage-backends/cursor-hosted-v2.js +164 -0
- package/dist/storage-backends/cursor-hosted.d.ts +6 -0
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +6 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +1 -1
- package/docs/ab.md +1 -1
- package/docs/building-with-agents.md +14 -11
- package/docs/evals.md +1 -1
- package/docs/guides/github.md +1 -1
- package/docs/guides/mcp-oauth.md +1 -1
- package/docs/guides/opentelemetry.md +2 -2
- package/docs/guides/slack.md +80 -1
- package/docs/hillclimbing.md +5 -5
- package/docs/quickstart.md +1 -1
- package/docs/reference/connections.md +1 -1
- package/docs/scaffolding-agents.md +3 -3
- package/docs/skills/index.md +26 -0
- package/docs/troubleshooting.md +1 -1
- package/package.json +1 -1
- package/src/channels/github/defaults.ts +36 -3
- package/src/channels/github/progress.ts +7 -0
- package/src/channels/slack/api.ts +35 -17
- package/src/channels/slack/constants.ts +6 -0
- package/src/channels/slack/defaults.ts +173 -92
- package/src/channels/slack/dispatch.ts +8 -1
- package/src/channels/slack/inbound.ts +17 -0
- package/src/channels/slack/index.ts +1 -0
- package/src/channels/slack/live-delivery.ts +131 -20
- package/src/channels/slack/reasoning-card.ts +140 -0
- package/src/channels/slack/redact.ts +6 -0
- package/src/channels/slack/reply-options.ts +229 -0
- package/src/channels/slack/slack-channel.ts +7 -2
- package/src/channels/slack/stream.ts +31 -24
- package/src/channels/slack/tool-cards.ts +221 -0
- package/src/channels/slack/types.ts +159 -6
- package/src/files-backends/cursor-hosted.ts +15 -5
- package/src/internal/cli-deploy.ts +2 -2
- package/src/internal/conversation-mirror.ts +3 -8
- package/src/internal/cursor/hosted-store-secrets.ts +72 -0
- package/src/internal/deploy-client.ts +10 -10
- package/src/internal/discovery.ts +9 -1
- package/src/internal/framework-file-storage.ts +41 -5
- package/src/internal/framework-storage-selection.ts +31 -44
- package/src/internal/session-run-log.ts +6 -11
- package/src/internal/storage-coordinator.ts +1 -11
- package/src/storage-backends/cursor-hosted-v2.ts +219 -0
- package/src/storage-backends/cursor-hosted.ts +6 -1
- package/src/types.ts +5 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +0 -1
- package/dist/docs/assets/hillclimbing.md.DhESf3OO.js +0 -4
- package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +0 -1
- package/dist/internal/null-kv-storage.d.ts +0 -48
- package/dist/internal/null-kv-storage.d.ts.map +0 -1
- package/dist/internal/null-kv-storage.js +0 -58
- package/dist/playground/assets/index-D7rGZNjy.css +0 -1
- package/src/internal/null-kv-storage.ts +0 -74
- /package/dist/docs/assets/{ab.md.DJo5r4R-.lean.js → ab.md.mlVgqvSk.lean.js} +0 -0
- /package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.lean.js → building-with-agents.md.CUSWxlP_.lean.js} +0 -0
- /package/dist/docs/assets/{evals.md.lfJoEVc8.lean.js → evals.md.CPzDAwoH.lean.js} +0 -0
- /package/dist/docs/assets/{guides_github.md.Cnh2mL4a.lean.js → guides_github.md.BtPr9GaP.lean.js} +0 -0
- /package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.lean.js → guides_mcp-oauth.md.Dp6cDP7f.lean.js} +0 -0
- /package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.lean.js → guides_opentelemetry.md.BVTXDCRg.lean.js} +0 -0
- /package/dist/docs/assets/{hillclimbing.md.DhESf3OO.lean.js → hillclimbing.md.CpTGTCle.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.CVeRUOeZ.lean.js → index.md.Bb4k8kUm.lean.js} +0 -0
- /package/dist/docs/assets/{quickstart.md.Nj_LjW_a.lean.js → quickstart.md.DdQOF7Y8.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.DxldvyIB.lean.js → reference_connections.md.BiGoBAk2.lean.js} +0 -0
- /package/dist/docs/assets/{scaffolding-agents.md.D7UUkWw0.lean.js → scaffolding-agents.md.em43xlY1.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.lean.js → troubleshooting.md.Cus_YZga.lean.js} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Thin client for the Agent Serve deployment management API
|
|
3
3
|
* (`/internal/agent-serve/deployments` on the Cursor backend) and the v2
|
|
4
|
-
* AgentSDK accept path (`/internal/
|
|
4
|
+
* AgentSDK accept path (`/internal/agentsdk/deployments`). Pure
|
|
5
5
|
* request/response + error mapping — no console I/O, no polling loops;
|
|
6
6
|
* rendering lives in `cli-deploy.ts`.
|
|
7
7
|
*
|
|
@@ -214,7 +214,7 @@ export interface StopAccepted {
|
|
|
214
214
|
export type DeleteAccepted = StopAccepted;
|
|
215
215
|
|
|
216
216
|
/**
|
|
217
|
-
* `POST /internal/
|
|
217
|
+
* `POST /internal/agentsdk/deployments` 202 body. Distinct from v1
|
|
218
218
|
* {@link DeployAccepted}: the v2 control plane returns catalog ids, not
|
|
219
219
|
* an engine alias or one-shot alias token.
|
|
220
220
|
*/
|
|
@@ -234,7 +234,7 @@ export interface AgentkitDeployComponent {
|
|
|
234
234
|
agentPath?: string;
|
|
235
235
|
}
|
|
236
236
|
|
|
237
|
-
/** Customer-visible v2 deploy status (`GET /internal/
|
|
237
|
+
/** Customer-visible v2 deploy status (`GET /internal/agentsdk/deployments/:slug`). */
|
|
238
238
|
export type AgentkitCustomerStatus =
|
|
239
239
|
| "pending"
|
|
240
240
|
| "deploying"
|
|
@@ -273,7 +273,7 @@ export const TERMINAL_AGENTKIT_DEPLOY_STATUSES: ReadonlySet<AgentkitCustomerStat
|
|
|
273
273
|
new Set(["running", "failed", "stopped"]);
|
|
274
274
|
|
|
275
275
|
/**
|
|
276
|
-
* `POST /internal/
|
|
276
|
+
* `POST /internal/agentsdk/deployments/:slug/stop` 202 body. Like v1
|
|
277
277
|
* {@link StopAccepted} but keyed by catalog ids instead of the numeric
|
|
278
278
|
* deployment row id.
|
|
279
279
|
*/
|
|
@@ -594,7 +594,7 @@ export class AgentServeDeployClient {
|
|
|
594
594
|
|
|
595
595
|
/**
|
|
596
596
|
* Create or redeploy onto the v2 control plane
|
|
597
|
-
* (`POST /internal/
|
|
597
|
+
* (`POST /internal/agentsdk/deployments`). 202 means accepted; poll
|
|
598
598
|
* {@link getAgentkitDeploy} until a terminal status. `components` deploys
|
|
599
599
|
* one application with several release components (one per agent
|
|
600
600
|
* directory); it is mutually exclusive with `agentPath`.
|
|
@@ -625,7 +625,7 @@ export class AgentServeDeployClient {
|
|
|
625
625
|
}
|
|
626
626
|
const raw = await this.request({
|
|
627
627
|
method: "POST",
|
|
628
|
-
path: "/internal/
|
|
628
|
+
path: "/internal/agentsdk/deployments",
|
|
629
629
|
body: {
|
|
630
630
|
teamId: args.teamId,
|
|
631
631
|
slug: args.slug,
|
|
@@ -650,14 +650,14 @@ export class AgentServeDeployClient {
|
|
|
650
650
|
}): Promise<AgentkitDeployStatus> {
|
|
651
651
|
const raw = await this.request({
|
|
652
652
|
method: "GET",
|
|
653
|
-
path: `/internal/
|
|
653
|
+
path: `/internal/agentsdk/deployments/${encodeURIComponent(args.slug)}?teamId=${args.teamId}`,
|
|
654
654
|
context: { verb: "get deployment", slug: args.slug },
|
|
655
655
|
});
|
|
656
656
|
return agentkitDeployStatusSchema.parse(raw);
|
|
657
657
|
}
|
|
658
658
|
|
|
659
659
|
/**
|
|
660
|
-
* Stop a v2 deployment (`POST /internal/
|
|
660
|
+
* Stop a v2 deployment (`POST /internal/agentsdk/deployments/:slug/stop`).
|
|
661
661
|
* 202 means accepted; poll {@link getAgentkitDeploy} until `stopped`.
|
|
662
662
|
*/
|
|
663
663
|
async stopAgentkit(args: {
|
|
@@ -666,7 +666,7 @@ export class AgentServeDeployClient {
|
|
|
666
666
|
}): Promise<AgentkitStopAccepted> {
|
|
667
667
|
const raw = await this.request({
|
|
668
668
|
method: "POST",
|
|
669
|
-
path: `/internal/
|
|
669
|
+
path: `/internal/agentsdk/deployments/${encodeURIComponent(args.slug)}/stop?teamId=${args.teamId}`,
|
|
670
670
|
context: { verb: "stop", slug: args.slug },
|
|
671
671
|
});
|
|
672
672
|
return agentkitStopAcceptedSchema.parse(raw);
|
|
@@ -977,7 +977,7 @@ function mapErrorResponse(
|
|
|
977
977
|
// (api2 vs api.cursor.com), not a missing deployment / closed gate.
|
|
978
978
|
if (/Route \S+ not found/i.test(bodyText)) {
|
|
979
979
|
return new DeployApiError(
|
|
980
|
-
`Agent Serve deploy API not found on this host — use the default api.cursor.com (unset CURSOR_API_BASE_URL), or point CURSOR_API_BASE_URL at a backend that mounts /internal/agent-serve/* and /internal/
|
|
980
|
+
`Agent Serve deploy API not found on this host — use the default api.cursor.com (unset CURSOR_API_BASE_URL), or point CURSOR_API_BASE_URL at a backend that mounts /internal/agent-serve/* and /internal/agentsdk/*.`,
|
|
981
981
|
404
|
|
982
982
|
);
|
|
983
983
|
}
|
|
@@ -1928,7 +1928,15 @@ async function loadChannels(
|
|
|
1928
1928
|
});
|
|
1929
1929
|
continue;
|
|
1930
1930
|
}
|
|
1931
|
-
|
|
1931
|
+
const definition = mod.default as ChannelDefinition;
|
|
1932
|
+
for (const notice of definition.meta?.deprecations ?? []) {
|
|
1933
|
+
ctx.diagnostics.push({
|
|
1934
|
+
severity: "warning",
|
|
1935
|
+
path: displayPath(ctx, entryPath),
|
|
1936
|
+
message: notice,
|
|
1937
|
+
});
|
|
1938
|
+
}
|
|
1939
|
+
channels.push({ id, definition });
|
|
1932
1940
|
}
|
|
1933
1941
|
return { channels, httpChannelDefinition };
|
|
1934
1942
|
}
|
|
@@ -167,11 +167,8 @@ function decodeDocument(key: string, bytes: Uint8Array): JsonValue {
|
|
|
167
167
|
* Split one storage core by key kind: framework session state to `files`,
|
|
168
168
|
* everything else to `kv`. Spread over the KV backend when building the
|
|
169
169
|
* full definition so its `evals` / `abs` groups (and the cursor-hosted
|
|
170
|
-
* marker) ride along untouched
|
|
171
|
-
*
|
|
172
|
-
* `continuation/` key would read and write a different store than the
|
|
173
|
-
* routed plain core — silent split-brain. Nothing in the package CASes
|
|
174
|
-
* those kinds today.
|
|
170
|
+
* marker) ride along untouched; wrap the KV `cas` group with
|
|
171
|
+
* {@link frameworkGuardedCas} rather than spreading it as-is.
|
|
175
172
|
*/
|
|
176
173
|
export function composeFrameworkStorage(input: {
|
|
177
174
|
kv: FileSinkStorageCore;
|
|
@@ -192,3 +189,42 @@ export function composeFrameworkStorage(input: {
|
|
|
192
189
|
listNewest: undefined,
|
|
193
190
|
};
|
|
194
191
|
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* The KV backend's conditional writes, refusing framework-file keys.
|
|
195
|
+
*
|
|
196
|
+
* CAS runs on the KV proxy (a database row version); the plain core routes
|
|
197
|
+
* framework session state to the file store. A future coordination path
|
|
198
|
+
* that CASes a `session/` or `continuation/` key would otherwise read and
|
|
199
|
+
* write a different store than the plain path — silent split-brain. Fail
|
|
200
|
+
* loudly instead; nothing in the package CASes those kinds today.
|
|
201
|
+
*/
|
|
202
|
+
export function frameworkGuardedCas(
|
|
203
|
+
cas: NonNullable<StorageConfig["cas"]>
|
|
204
|
+
): NonNullable<StorageConfig["cas"]> {
|
|
205
|
+
const refuse = (key: string): void => {
|
|
206
|
+
if (isFrameworkFileKey(key)) {
|
|
207
|
+
throw new Error(
|
|
208
|
+
`framework file storage: conditional writes are KV-only, but "${key}" routes to the framework file store`
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
return {
|
|
213
|
+
getWithVersion: (key, ctx) => {
|
|
214
|
+
refuse(key);
|
|
215
|
+
return cas.getWithVersion(key, ctx);
|
|
216
|
+
},
|
|
217
|
+
putIfAbsent: (key, value, ctx) => {
|
|
218
|
+
refuse(key);
|
|
219
|
+
return cas.putIfAbsent(key, value, ctx);
|
|
220
|
+
},
|
|
221
|
+
putIfVersion: (key, value, expectedVersion, ctx) => {
|
|
222
|
+
refuse(key);
|
|
223
|
+
return cas.putIfVersion(key, value, expectedVersion, ctx);
|
|
224
|
+
},
|
|
225
|
+
listKeys: (prefix, ctx) => {
|
|
226
|
+
refuse(prefix);
|
|
227
|
+
return cas.listKeys(prefix, ctx);
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
}
|
|
@@ -18,18 +18,18 @@
|
|
|
18
18
|
* - **Cursor-managed hosting** (the deployment-generation environment
|
|
19
19
|
* variable is set, same signal that registers `GET /v1/manifest`):
|
|
20
20
|
* the deployment's **framework-level file store**
|
|
21
|
-
* (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID
|
|
22
|
-
* transcripts, and the continuation index —
|
|
23
|
-
* storage, apart from the author-facing user
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
21
|
+
* (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID`, bound at task time) holds
|
|
22
|
+
* session records, event transcripts, and the continuation index —
|
|
23
|
+
* file-shaped state on file storage, apart from the author-facing user
|
|
24
|
+
* store. Author `host.kv`, eval runs, A/B samples, and conditional writes
|
|
25
|
+
* ride the AgentSDK v2 KV proxy (cursor-hosted-v2.ts), which resolves the
|
|
26
|
+
* pod service account to the factorydb deployment row (the v1 Bugbot
|
|
27
|
+
* proxy cannot resolve v2 pods at all). Framework session state never
|
|
28
|
+
* routes to the KV proxy — the composite splits by key kind — so
|
|
29
|
+
* transcripts stay off the author-reachable KV namespace. The API key
|
|
30
|
+
* resolves through the full credential chain on every call because hosted
|
|
31
|
+
* freeze snapshots listen unsigned and the binder drops the key file
|
|
32
|
+
* after restore.
|
|
33
33
|
* - **Self-hosted**: no mirror. `--state-root` is the durable copy, which
|
|
34
34
|
* is correct when the operator owns the disk.
|
|
35
35
|
*
|
|
@@ -47,17 +47,15 @@ import {
|
|
|
47
47
|
cursorHostedFiles,
|
|
48
48
|
} from "../files-backends/cursor-hosted.js";
|
|
49
49
|
import { defineStorage, type StorageDefinition } from "../storage.js";
|
|
50
|
-
import {
|
|
50
|
+
import { cursorHostedStorageV2 } from "../storage-backends/cursor-hosted-v2.js";
|
|
51
51
|
import type { AgentArchitecture } from "../types.js";
|
|
52
52
|
import { resolveApiKeySync } from "./cursor/credentials.js";
|
|
53
53
|
import { AGENT_SERVE_GENERATION_ENV_VAR } from "./cursor-relay-core.js";
|
|
54
54
|
import {
|
|
55
55
|
composeFrameworkStorage,
|
|
56
56
|
fileSinkStorageCore,
|
|
57
|
+
frameworkGuardedCas,
|
|
57
58
|
} from "./framework-file-storage.js";
|
|
58
|
-
import { nullKvStorage } from "./null-kv-storage.js";
|
|
59
|
-
|
|
60
|
-
const cursorHostedMarker = { [CURSOR_HOSTED_STORAGE]: true } as const;
|
|
61
59
|
|
|
62
60
|
export interface FrameworkStorageSelectionInput {
|
|
63
61
|
/** `agent/storage.ts`, when the author wrote one (v1 only: discovery rejects it on v2). */
|
|
@@ -100,44 +98,33 @@ export function selectFrameworkStorageDefinition(
|
|
|
100
98
|
// comes up). Follow-ups restore lazily by continuation or session id;
|
|
101
99
|
// GET /v1/sessions lists from the sink either way.
|
|
102
100
|
const policy = { restore: "off" } as const;
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
if (frameworkStoreId === undefined) {
|
|
107
|
-
// Nothing to mirror to: the KV proxy rejects v2 service accounts, so a
|
|
108
|
-
// definition over it would fail every delivery that reads it. The state
|
|
109
|
-
// root is the durable copy, as when self-hosted.
|
|
110
|
-
return undefined;
|
|
111
|
-
}
|
|
112
|
-
// Full chain (env → key file → stored login): frozen engines listen
|
|
113
|
-
// unsigned and bind CURSOR_API_KEY_FILE at task time, after this
|
|
101
|
+
const envSnapshot = env as NodeJS.ProcessEnv;
|
|
102
|
+
// Full chain (env → bind file → stored login): frozen engines listen
|
|
103
|
+
// unsigned and bind store ids + CURSOR_API_KEY at task time, after this
|
|
114
104
|
// definition is constructed.
|
|
115
105
|
const resolveApiKey = (): string | undefined => resolveApiKeySync()?.apiKey;
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
// deployments also means restoring the guard its `cas` group needs: a
|
|
124
|
-
// conditional write over a `session/` or `continuation/` key would run on
|
|
125
|
-
// the KV database while the plain core routes that key to the file store.
|
|
126
|
-
const kv = nullKvStorage();
|
|
106
|
+
// v2 pods carry a factorydb-bound service account, which the v1 Bugbot
|
|
107
|
+
// storage proxy cannot resolve; author KV, CAS coordination, and the
|
|
108
|
+
// eval/A-B tables speak the AgentSDK v2 KV proxy instead. It also carries
|
|
109
|
+
// the cursor-hosted marker, so GET /v1/sessions prefers the durable list
|
|
110
|
+
// (session records are on the framework store, which the composed core
|
|
111
|
+
// lists).
|
|
112
|
+
const kv = cursorHostedStorageV2({ resolveApiKey });
|
|
127
113
|
return defineStorage({
|
|
128
114
|
name: "cursor-hosted (framework files)",
|
|
129
115
|
policy,
|
|
130
|
-
// GET /v1/sessions still prefers the durable list: session records live
|
|
131
|
-
// on the framework store, which the composed core lists. Spread rather
|
|
132
|
-
// than named, the way cursorHostedStorage carries it: the marker is a
|
|
133
|
-
// platform stamp, not part of the authored config surface.
|
|
134
|
-
...cursorHostedMarker,
|
|
135
116
|
...kv,
|
|
136
117
|
...composeFrameworkStorage({
|
|
137
118
|
kv,
|
|
138
119
|
files: fileSinkStorageCore(
|
|
139
|
-
cursorHostedFiles({
|
|
120
|
+
cursorHostedFiles({
|
|
121
|
+
resolveStoreSourceId: () => cursorFrameworkStoreSourceId(envSnapshot),
|
|
122
|
+
resolveApiKey,
|
|
123
|
+
})
|
|
140
124
|
),
|
|
141
125
|
}),
|
|
126
|
+
// CAS stays on the KV proxy but must refuse framework-file keys, or a
|
|
127
|
+
// future coordination path would split-brain against the plain core.
|
|
128
|
+
cas: frameworkGuardedCas(kv.cas),
|
|
142
129
|
});
|
|
143
130
|
}
|
|
@@ -547,9 +547,9 @@ export function createSessionRunLogStore(input: {
|
|
|
547
547
|
|
|
548
548
|
/**
|
|
549
549
|
* Same selection as the conversation mirror: architecture-v2 hosted
|
|
550
|
-
* engines
|
|
551
|
-
*
|
|
552
|
-
*
|
|
550
|
+
* engines (generation env set). Store ids resolve lazily from env or the
|
|
551
|
+
* task-bind files under `/run/cursor/secrets`. Self-hosted and v1 stay on
|
|
552
|
+
* local disk / today's behavior.
|
|
553
553
|
*/
|
|
554
554
|
export function selectSessionRunLogStore(input: {
|
|
555
555
|
project: AgentProject;
|
|
@@ -561,18 +561,13 @@ export function selectSessionRunLogStore(input: {
|
|
|
561
561
|
return undefined;
|
|
562
562
|
}
|
|
563
563
|
const env = input.env ?? process.env;
|
|
564
|
-
|
|
565
|
-
env as NodeJS.ProcessEnv
|
|
566
|
-
);
|
|
567
|
-
if (
|
|
568
|
-
env[AGENT_SERVE_GENERATION_ENV_VAR] === undefined ||
|
|
569
|
-
frameworkStoreId === undefined
|
|
570
|
-
) {
|
|
564
|
+
if (env[AGENT_SERVE_GENERATION_ENV_VAR] === undefined) {
|
|
571
565
|
return undefined;
|
|
572
566
|
}
|
|
567
|
+
const envSnapshot = env as NodeJS.ProcessEnv;
|
|
573
568
|
return createSessionRunLogStore({
|
|
574
569
|
sink: cursorHostedFiles({
|
|
575
|
-
|
|
570
|
+
resolveStoreSourceId: () => cursorFrameworkStoreSourceId(envSnapshot),
|
|
576
571
|
resolveApiKey: () => resolveApiKeySync()?.apiKey,
|
|
577
572
|
}),
|
|
578
573
|
agentName: input.project.name,
|
|
@@ -38,7 +38,6 @@ import type { JsonValue, SessionEvent, SessionRecord } from "../types.js";
|
|
|
38
38
|
import type { ABSnapshot } from "./ab-snapshot.js";
|
|
39
39
|
import { describeError } from "./describe-error.js";
|
|
40
40
|
import type { EvalRunStorage } from "./eval-run-store.js";
|
|
41
|
-
import { isAuthorKvUnsupported } from "./null-kv-storage.js";
|
|
42
41
|
import type {
|
|
43
42
|
AuthorKvStore,
|
|
44
43
|
EvalAbStore,
|
|
@@ -469,18 +468,9 @@ export class StorageCoordinator
|
|
|
469
468
|
/**
|
|
470
469
|
* Whether the sink can serve awaited author reads/writes (`get` is
|
|
471
470
|
* required — `put` is always present on {@link StorageConfig}).
|
|
472
|
-
*
|
|
473
|
-
* A sink may keep `get` for framework session state while refusing author
|
|
474
|
-
* KV: hosted v2 reads sessions from the framework file store but has no
|
|
475
|
-
* working KV backend, and author handlers that cannot read their own
|
|
476
|
-
* writes back are better served by the local-disk fallback than by a sink
|
|
477
|
-
* that accepts every write and forgets it.
|
|
478
471
|
*/
|
|
479
472
|
get supportsAuthorKv(): boolean {
|
|
480
|
-
return
|
|
481
|
-
this.definition.get !== undefined &&
|
|
482
|
-
!isAuthorKvUnsupported(this.definition)
|
|
483
|
-
);
|
|
473
|
+
return this.definition.get !== undefined;
|
|
484
474
|
}
|
|
485
475
|
|
|
486
476
|
/**
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cursor-managed durable KV for hosted **architecture v2** agents.
|
|
3
|
+
*
|
|
4
|
+
* Talks to the AgentSDK v2 KV proxy
|
|
5
|
+
* (`POST /internal/agentsdk/kv/*`) using the engine's pod
|
|
6
|
+
* `CURSOR_API_KEY`. The server resolves the v2 deployment from that service
|
|
7
|
+
* account (factorydb `agentsdk_deployment`) and persists rows in factorydb
|
|
8
|
+
* `agentsdk_kv` — v1's Bugbot-backed `/internal/agent-serve/storage/*`
|
|
9
|
+
* routes cannot resolve a v2 pod credential at all.
|
|
10
|
+
*
|
|
11
|
+
* The v2 wire protocol is four routes, not v1's eight:
|
|
12
|
+
*
|
|
13
|
+
* - `POST /internal/agentsdk/kv/get`
|
|
14
|
+
* `{ key }` → `{ found, value, version }` — reads always carry the CAS
|
|
15
|
+
* version token ({@link KvV2GetResponse}).
|
|
16
|
+
* - `POST /internal/agentsdk/kv/put`
|
|
17
|
+
* `{ key, value, ifAbsent? | ifVersion? }` → `{ ok, version, current }`
|
|
18
|
+
* ({@link KvV2PutResponse}) — one write primitive: last-write-wins when
|
|
19
|
+
* unconditional (still bumps the token), atomic create-if-absent with
|
|
20
|
+
* `ifAbsent: true`, atomic compare-and-swap with `ifVersion`.
|
|
21
|
+
* - `POST /internal/agentsdk/kv/delete` `{ key }` → `{ ok }`.
|
|
22
|
+
* - `POST /internal/agentsdk/kv/list`
|
|
23
|
+
* `{ prefix, limit?, cursor?, keysOnly? }` → `{ entries, nextCursor }`
|
|
24
|
+
* ({@link KvV2ListResponse}) — ascending key order with keyset
|
|
25
|
+
* pagination. `list` / `listKeys` below drain every page, so the v1
|
|
26
|
+
* truncated-scan failure mode does not exist here.
|
|
27
|
+
*
|
|
28
|
+
* Eval runs and A/B samples still ride the v1 storage proxy's dedicated
|
|
29
|
+
* tables (`evals` / `abs` below); moving them to factorydb is a separate
|
|
30
|
+
* follow-up from the KV cutover.
|
|
31
|
+
*
|
|
32
|
+
* This backend is platform-selected for architecture v2
|
|
33
|
+
* (framework-storage-selection.ts) — authors never import it; `agent/storage.ts`
|
|
34
|
+
* is rejected on v2.
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
import type {
|
|
38
|
+
StorageABTable,
|
|
39
|
+
StorageCasTable,
|
|
40
|
+
StorageConfig,
|
|
41
|
+
StorageEntry,
|
|
42
|
+
StorageEvalsTable,
|
|
43
|
+
} from "../storage.js";
|
|
44
|
+
import type { JsonValue, KvCasResult, KvVersionedEntry } from "../types.js";
|
|
45
|
+
import {
|
|
46
|
+
CURSOR_HOSTED_STORAGE,
|
|
47
|
+
type CursorHostedStorageOptions,
|
|
48
|
+
cursorHostedStorage,
|
|
49
|
+
storageRpc,
|
|
50
|
+
} from "./cursor-hosted.js";
|
|
51
|
+
|
|
52
|
+
const KV_V2_PREFIX = "/internal/agentsdk/kv";
|
|
53
|
+
|
|
54
|
+
/** Wire shape of the v2 `get` route. `null` ⇒ JSON `undefined`. */
|
|
55
|
+
export interface KvV2GetResponse {
|
|
56
|
+
found: boolean;
|
|
57
|
+
value: JsonValue | null;
|
|
58
|
+
version: string | null;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** Wire shape of the v2 `put` route (all three write modes). */
|
|
62
|
+
export interface KvV2PutResponse {
|
|
63
|
+
ok: boolean;
|
|
64
|
+
/** New version token on an accepted write, else `null`. */
|
|
65
|
+
version: string | null;
|
|
66
|
+
/** Entry observed when a conditional write lost; `null` when absent. */
|
|
67
|
+
current: { value: JsonValue | null; version: string } | null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Wire shape of the v2 `list` route. */
|
|
71
|
+
export interface KvV2ListResponse {
|
|
72
|
+
entries: Array<{
|
|
73
|
+
key: string;
|
|
74
|
+
/** Omitted when the request asked for keys only. */
|
|
75
|
+
value?: JsonValue | null;
|
|
76
|
+
version: string;
|
|
77
|
+
}>;
|
|
78
|
+
/** Last key of this page when more rows remain, else `null`. */
|
|
79
|
+
nextCursor: string | null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
type CursorHostedStorageV2Methods = Required<
|
|
83
|
+
Pick<StorageConfig, "put" | "get" | "delete" | "list">
|
|
84
|
+
> & {
|
|
85
|
+
readonly [CURSOR_HOSTED_STORAGE]: true;
|
|
86
|
+
cas: StorageCasTable;
|
|
87
|
+
evals: StorageEvalsTable;
|
|
88
|
+
abs: StorageABTable;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
function toCasResult(response: KvV2PutResponse): KvCasResult {
|
|
92
|
+
if (response.ok) {
|
|
93
|
+
if (response.version === null) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
"cursorHostedStorageV2: conditional write succeeded without a version token"
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
return { ok: true, version: response.version };
|
|
99
|
+
}
|
|
100
|
+
const current: KvVersionedEntry | undefined =
|
|
101
|
+
response.current === null
|
|
102
|
+
? undefined
|
|
103
|
+
: {
|
|
104
|
+
value: response.current.value ?? null,
|
|
105
|
+
version: response.current.version,
|
|
106
|
+
};
|
|
107
|
+
return { ok: false, current };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Drain every page of a v2 `list` scan. The server pages by keyset (each
|
|
112
|
+
* `nextCursor` is the strictly-greatest key returned so far), so a cursor
|
|
113
|
+
* that fails to advance means a broken server — fail loudly rather than
|
|
114
|
+
* loop forever.
|
|
115
|
+
*/
|
|
116
|
+
async function listAllPages(
|
|
117
|
+
options: CursorHostedStorageOptions,
|
|
118
|
+
body: { prefix: string; keysOnly?: boolean }
|
|
119
|
+
): Promise<KvV2ListResponse["entries"]> {
|
|
120
|
+
const entries: KvV2ListResponse["entries"] = [];
|
|
121
|
+
let cursor: string | undefined;
|
|
122
|
+
for (;;) {
|
|
123
|
+
const page = await storageRpc<KvV2ListResponse>(
|
|
124
|
+
options,
|
|
125
|
+
`${KV_V2_PREFIX}/list`,
|
|
126
|
+
cursor === undefined ? body : { ...body, cursor }
|
|
127
|
+
);
|
|
128
|
+
entries.push(...page.entries);
|
|
129
|
+
if (page.nextCursor === null) {
|
|
130
|
+
return entries;
|
|
131
|
+
}
|
|
132
|
+
if (cursor !== undefined && page.nextCursor <= cursor) {
|
|
133
|
+
throw new Error(
|
|
134
|
+
`cursorHostedStorageV2: list("${body.prefix}") cursor did not advance`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
cursor = page.nextCursor;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Architecture-v2 `defineStorage` methods (AgentSDK v2 KV proxy → factorydb
|
|
143
|
+
* `agentsdk_kv`). Platform-selected; spread into `defineStorage({...})` by
|
|
144
|
+
* framework-storage-selection.ts. No `listNewest`: v2 session records live
|
|
145
|
+
* on the framework file store, so the only consumer of write-time ordering
|
|
146
|
+
* never reaches this backend and the engine's `list` fallback covers the
|
|
147
|
+
* rest.
|
|
148
|
+
*/
|
|
149
|
+
export function cursorHostedStorageV2(
|
|
150
|
+
options: CursorHostedStorageOptions = {}
|
|
151
|
+
): CursorHostedStorageV2Methods {
|
|
152
|
+
// Eval runs and A/B samples stay on the v1 proxy's dedicated tables.
|
|
153
|
+
const v1 = cursorHostedStorage(options);
|
|
154
|
+
return {
|
|
155
|
+
[CURSOR_HOSTED_STORAGE]: true,
|
|
156
|
+
async put(key, value): Promise<void> {
|
|
157
|
+
await storageRpc(options, `${KV_V2_PREFIX}/put`, { key, value });
|
|
158
|
+
},
|
|
159
|
+
async get(key): Promise<JsonValue | undefined> {
|
|
160
|
+
const result = await storageRpc<KvV2GetResponse>(
|
|
161
|
+
options,
|
|
162
|
+
`${KV_V2_PREFIX}/get`,
|
|
163
|
+
{ key }
|
|
164
|
+
);
|
|
165
|
+
if (!result.found) {
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
return result.value ?? undefined;
|
|
169
|
+
},
|
|
170
|
+
async delete(key): Promise<void> {
|
|
171
|
+
await storageRpc(options, `${KV_V2_PREFIX}/delete`, { key });
|
|
172
|
+
},
|
|
173
|
+
async list(prefix): Promise<StorageEntry[]> {
|
|
174
|
+
const entries = await listAllPages(options, { prefix });
|
|
175
|
+
return entries.map((entry) => ({
|
|
176
|
+
key: entry.key,
|
|
177
|
+
value: entry.value ?? null,
|
|
178
|
+
}));
|
|
179
|
+
},
|
|
180
|
+
cas: {
|
|
181
|
+
async getWithVersion(key): Promise<KvVersionedEntry | undefined> {
|
|
182
|
+
const result = await storageRpc<KvV2GetResponse>(
|
|
183
|
+
options,
|
|
184
|
+
`${KV_V2_PREFIX}/get`,
|
|
185
|
+
{ key }
|
|
186
|
+
);
|
|
187
|
+
if (!result.found || result.version === null) {
|
|
188
|
+
return undefined;
|
|
189
|
+
}
|
|
190
|
+
return { value: result.value ?? null, version: result.version };
|
|
191
|
+
},
|
|
192
|
+
async putIfAbsent(key, value): Promise<KvCasResult> {
|
|
193
|
+
const result = await storageRpc<KvV2PutResponse>(
|
|
194
|
+
options,
|
|
195
|
+
`${KV_V2_PREFIX}/put`,
|
|
196
|
+
{ key, value, ifAbsent: true }
|
|
197
|
+
);
|
|
198
|
+
return toCasResult(result);
|
|
199
|
+
},
|
|
200
|
+
async putIfVersion(key, value, expectedVersion): Promise<KvCasResult> {
|
|
201
|
+
const result = await storageRpc<KvV2PutResponse>(
|
|
202
|
+
options,
|
|
203
|
+
`${KV_V2_PREFIX}/put`,
|
|
204
|
+
{ key, value, ifVersion: expectedVersion }
|
|
205
|
+
);
|
|
206
|
+
return toCasResult(result);
|
|
207
|
+
},
|
|
208
|
+
async listKeys(prefix): Promise<string[]> {
|
|
209
|
+
const entries = await listAllPages(options, {
|
|
210
|
+
prefix,
|
|
211
|
+
keysOnly: true,
|
|
212
|
+
});
|
|
213
|
+
return entries.map((entry) => entry.key);
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
evals: v1.evals,
|
|
217
|
+
abs: v1.abs,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
@@ -207,7 +207,12 @@ function resolveBaseUrl(options: CursorHostedStorageOptions): string {
|
|
|
207
207
|
return raw.endsWith("/") ? raw.slice(0, -1) : raw;
|
|
208
208
|
}
|
|
209
209
|
|
|
210
|
-
|
|
210
|
+
/**
|
|
211
|
+
* One authenticated POST to the control-plane proxy. Shared with the
|
|
212
|
+
* architecture-v2 backend (`cursor-hosted-v2.ts`), which speaks a different
|
|
213
|
+
* route family over the same transport and credential chain.
|
|
214
|
+
*/
|
|
215
|
+
export async function storageRpc<T>(
|
|
211
216
|
options: CursorHostedStorageOptions,
|
|
212
217
|
path: string,
|
|
213
218
|
body: Record<string, unknown>
|
package/src/types.ts
CHANGED
|
@@ -2314,6 +2314,11 @@ export interface ChannelMeta {
|
|
|
2314
2314
|
* by `info` so watched channels are auditable.
|
|
2315
2315
|
*/
|
|
2316
2316
|
slackChannelPosts?: readonly string[];
|
|
2317
|
+
/**
|
|
2318
|
+
* Author-facing notices about deprecated options the pack still honored.
|
|
2319
|
+
* Discovery surfaces each one as a `validate` warning on the channel file.
|
|
2320
|
+
*/
|
|
2321
|
+
deprecations?: readonly string[];
|
|
2317
2322
|
}
|
|
2318
2323
|
|
|
2319
2324
|
export interface ChannelConfig<TState = JsonValue> {
|