@cursor/july 0.1.104 → 0.1.107
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/dist/bin/agent-serve.js +1 -8
- package/dist/channels/bitbucket/types.d.ts +2 -4
- package/dist/channels/bitbucket/types.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +1 -0
- package/dist/channels/deployments/types.d.ts +7 -8
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/types.d.ts +2 -4
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/gitlab/types.d.ts +2 -5
- package/dist/channels/gitlab/types.d.ts.map +1 -1
- package/dist/channels/origin/types.d.ts +2 -3
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +3 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +1 -1
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +48 -11
- package/dist/channels/slack/types.d.ts +4 -3
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +3 -3
- package/dist/docs/ab.html +6 -6
- package/dist/docs/assets/{app.DbMWUyGb.js → app.CtuckIiL.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DXXZxiMv.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DcNeTh9o.js → VPLocalSearchBox.Bkkhnu8K.js} +2 -2
- package/dist/docs/assets/chunks/{theme.DMjhY3gl.js → theme.DhpIe0Pa.js} +2 -2
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.js +9 -0
- package/dist/docs/assets/guides_grokbot-agents.md.DVqdhBKb.lean.js +1 -0
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.js → guides_opentelemetry.md.SCRMskno.js} +3 -3
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.lean.js → guides_opentelemetry.md.SCRMskno.lean.js} +1 -1
- package/dist/docs/assets/index.md.BW_6tOgR.js +5 -0
- package/dist/docs/assets/index.md.BW_6tOgR.lean.js +1 -0
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.js → reference_channels.md.D-qTqwcq.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.lean.js → reference_channels.md.D-qTqwcq.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.CJNc_xYK.js → reference_cli.md.Dm67hd2D.js} +3 -2
- package/dist/docs/assets/{reference_extensions.md.DykHW3qL.js → reference_extensions.md.CGmMLblt.js} +1 -1
- package/dist/docs/assets/{skills_otel.md.CqhobH3B.js → skills_otel.md.B5Ddv1xH.js} +1 -1
- package/dist/docs/assets/{style.BRuM8477.css → style.DCD_zyg3.css} +1 -1
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.js +3 -0
- package/dist/docs/assets/templates_grokbot-agents.md.c1s6Flp9.lean.js +1 -0
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +6 -6
- package/dist/docs/evals.html +6 -6
- package/dist/docs/guides/agent-to-agent.html +6 -6
- package/dist/docs/guides/cloud-agents.html +6 -6
- package/dist/docs/guides/convert-automation.html +6 -6
- package/dist/docs/guides/github.html +6 -6
- package/dist/docs/guides/grokbot-agents.html +35 -0
- package/dist/docs/guides/grokbot-agents.md +88 -0
- package/dist/docs/guides/human-in-the-loop.html +6 -6
- package/dist/docs/guides/mcp-oauth.html +6 -6
- package/dist/docs/guides/opentelemetry.html +8 -8
- package/dist/docs/guides/opentelemetry.md +3 -4
- package/dist/docs/guides/slack.html +6 -6
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/index.html +8 -8
- package/dist/docs/index.md +6 -1
- package/dist/docs/llms-full.txt +178 -30
- package/dist/docs/llms.txt +2 -0
- package/dist/docs/quickstart.html +6 -6
- package/dist/docs/reference/agent-config.html +6 -6
- package/dist/docs/reference/artifacts.html +6 -6
- package/dist/docs/reference/channels.html +7 -7
- package/dist/docs/reference/channels.md +11 -19
- package/dist/docs/reference/cli.html +10 -9
- package/dist/docs/reference/cli.md +7 -3
- package/dist/docs/reference/connections.html +6 -6
- package/dist/docs/reference/extensions.html +7 -7
- package/dist/docs/reference/extensions.md +2 -0
- package/dist/docs/reference/hooks.html +6 -6
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/instructions.html +6 -6
- package/dist/docs/reference/playground.html +5 -5
- package/dist/docs/reference/project-layout.html +6 -6
- package/dist/docs/reference/prompt.html +6 -6
- package/dist/docs/reference/result.html +6 -6
- package/dist/docs/reference/schedules.html +6 -6
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/skills.html +6 -6
- package/dist/docs/reference/subagents.html +6 -6
- package/dist/docs/reference/tools.html +6 -6
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/skills/ab.html +6 -6
- package/dist/docs/skills/create-agent.html +6 -6
- package/dist/docs/skills/debug.html +5 -5
- package/dist/docs/skills/evals.html +6 -6
- package/dist/docs/skills/framework-map.html +5 -5
- package/dist/docs/skills/github.html +6 -6
- package/dist/docs/skills/hillclimb.html +6 -6
- package/dist/docs/skills/index.html +5 -5
- package/dist/docs/skills/mcp-auth.html +6 -6
- package/dist/docs/skills/otel.html +8 -8
- package/dist/docs/skills/otel.md +3 -3
- package/dist/docs/skills/setup-slack.html +6 -6
- package/dist/docs/storage.html +6 -6
- package/dist/docs/templates/agentic-owners.html +6 -6
- package/dist/docs/templates/agents-md.html +6 -6
- package/dist/docs/templates/code-wiki.html +6 -6
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/grokbot-agents.html +29 -0
- package/dist/docs/templates/grokbot-agents.md +48 -0
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/security-help.html +6 -6
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/triage.html +6 -6
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/files.d.ts +7 -2
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +7 -2
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +23 -11
- package/dist/internal/cursor/backend-client.d.ts +25 -0
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +57 -2
- package/dist/internal/cursor-agent-template.d.ts +1 -1
- package/dist/internal/cursor-agent-template.d.ts.map +1 -1
- package/dist/internal/cursor-agent-template.js +1 -0
- package/dist/internal/deploy-client.d.ts +8 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +14 -0
- package/dist/internal/deploy-manifest.d.ts +3 -0
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +15 -12
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +1 -0
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +7 -3
- package/dist/internal/discovery/modules.d.ts +1 -1
- package/dist/internal/discovery/modules.d.ts.map +1 -1
- package/dist/internal/discovery/modules.js +1 -0
- package/dist/internal/discovery/project.d.ts.map +1 -1
- package/dist/internal/discovery/project.js +3 -0
- package/dist/internal/discovery/reminders.d.ts +7 -0
- package/dist/internal/discovery/reminders.d.ts.map +1 -0
- package/dist/internal/discovery/reminders.js +65 -0
- package/dist/internal/discovery/subagent.js +1 -0
- package/dist/internal/distribution.d.ts +5 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +17 -0
- package/dist/internal/framework-file-storage.d.ts +3 -1
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +3 -1
- package/dist/internal/framework-storage-selection.d.ts +14 -3
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +36 -6
- package/dist/internal/guest-network.d.ts.map +1 -1
- package/dist/internal/guest-network.js +2 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +48 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +60 -0
- package/dist/internal/hosted-delivery.d.ts +17 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +112 -19
- package/dist/internal/hosted-managed-automation.d.ts.map +1 -1
- package/dist/internal/hosted-managed-automation.js +27 -2
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +4 -1
- package/dist/internal/local-control-plane.d.ts +18 -2
- package/dist/internal/local-control-plane.d.ts.map +1 -1
- package/dist/internal/local-control-plane.js +199 -17
- package/dist/internal/reminder-control-plane-protocol.d.ts +187 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -0
- package/dist/internal/reminder-control-plane-protocol.js +244 -0
- package/dist/internal/reminder-runner.d.ts +48 -6
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +336 -48
- package/dist/internal/reminder-schedule.d.ts +5 -2
- package/dist/internal/reminder-schedule.d.ts.map +1 -1
- package/dist/internal/reminder-schedule.js +8 -6
- package/dist/internal/reminder-store.d.ts +24 -7
- package/dist/internal/reminder-store.d.ts.map +1 -1
- package/dist/internal/reminder-store.js +6 -5
- package/dist/internal/request-error-status.d.ts +2 -0
- package/dist/internal/request-error-status.d.ts.map +1 -1
- package/dist/internal/request-error-status.js +22 -3
- package/dist/internal/scm/pr-url.d.ts +40 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -1
- package/dist/internal/scm/pr-url.js +93 -14
- package/dist/internal/sdk-runner.d.ts +12 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +18 -0
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +78 -30
- package/dist/internal/session-engine.d.ts +12 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +137 -52
- package/dist/internal/store-mirror.d.ts +2 -2
- package/dist/internal/store-mirror.js +2 -2
- package/dist/internal/tenant-slack/relay.d.ts +2 -0
- package/dist/internal/tenant-slack/relay.d.ts.map +1 -1
- package/dist/internal/tenant-slack/relay.js +18 -8
- package/dist/internal/workspace-sync.d.ts +31 -6
- package/dist/internal/workspace-sync.d.ts.map +1 -1
- package/dist/internal/workspace-sync.js +67 -12
- package/dist/internal/workspace.d.ts +9 -0
- package/dist/internal/workspace.d.ts.map +1 -1
- package/dist/internal/workspace.js +16 -0
- package/dist/playground/assets/index-Bq2HpEQB.js +67 -0
- package/dist/playground/assets/index-CZKKNlmb.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/reminders.d.ts +24 -5
- package/dist/reminders.d.ts.map +1 -1
- package/dist/reminders.js +28 -5
- package/dist/types.d.ts +98 -28
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +6 -1
- package/docs/guides/grokbot-agents.md +93 -0
- package/docs/guides/opentelemetry.md +3 -4
- package/docs/reference/channels.md +11 -19
- package/docs/reference/cli.md +7 -3
- package/docs/reference/extensions.md +2 -0
- package/docs/templates/grokbot-agents.md +53 -0
- package/package.json +12 -3
- package/skills/otel/SKILL.md +3 -3
- package/src/bin/agent-serve.ts +1 -9
- package/src/channels/bitbucket/types.ts +2 -4
- package/src/channels/deployments/deployments-channel.ts +1 -0
- package/src/channels/deployments/types.ts +7 -8
- package/src/channels/github/types.ts +2 -4
- package/src/channels/gitlab/types.ts +2 -5
- package/src/channels/origin/types.ts +2 -3
- package/src/channels/slack/defaults.ts +3 -0
- package/src/channels/slack/dispatch.ts +1 -0
- package/src/channels/slack/live-delivery.ts +53 -12
- package/src/channels/slack/types.ts +4 -3
- package/src/files.ts +9 -2
- package/src/index.ts +6 -3
- package/src/internal/cli-deploy.ts +30 -12
- package/src/internal/cursor/backend-client.ts +90 -2
- package/src/internal/cursor-agent-template.ts +1 -0
- package/src/internal/deploy-client.ts +16 -0
- package/src/internal/deploy-manifest.ts +16 -11
- package/src/internal/discovery/agent.ts +1 -0
- package/src/internal/discovery/info.ts +6 -0
- package/src/internal/discovery/modules.ts +2 -4
- package/src/internal/discovery/project.ts +3 -0
- package/src/internal/discovery/reminders.ts +65 -0
- package/src/internal/discovery/subagent.ts +1 -0
- package/src/internal/distribution.ts +20 -0
- package/src/internal/framework-file-storage.ts +3 -1
- package/src/internal/framework-storage-selection.ts +43 -6
- package/src/internal/guest-network.ts +3 -0
- package/src/internal/hosted-delivery-protocol.ts +96 -0
- package/src/internal/hosted-delivery.ts +207 -28
- package/src/internal/hosted-managed-automation.ts +49 -5
- package/src/internal/init-project.ts +4 -1
- package/src/internal/local-control-plane.ts +281 -22
- package/src/internal/reminder-control-plane-protocol.ts +499 -0
- package/src/internal/reminder-runner.ts +421 -48
- package/src/internal/reminder-schedule.ts +11 -6
- package/src/internal/reminder-store.ts +27 -7
- package/src/internal/request-error-status.ts +27 -3
- package/src/internal/scm/pr-url.ts +167 -20
- package/src/internal/sdk-runner.ts +19 -0
- package/src/internal/server.ts +85 -16
- package/src/internal/session-engine.ts +173 -56
- package/src/internal/store-mirror.ts +2 -2
- package/src/internal/tenant-slack/relay.ts +28 -4
- package/src/internal/workspace-sync.ts +84 -12
- package/src/internal/workspace.ts +20 -0
- package/src/reminders.ts +35 -4
- package/src/types.ts +104 -28
- package/templates/grokbot-agents/README.md +26 -0
- package/templates/grokbot-agents/agent/agent.ts +6 -0
- package/templates/grokbot-agents/agent/extensions/grokbot.ts +5 -0
- package/templates/grokbot-agents/agent/instructions.md +7 -0
- package/templates/grokbot-agents/evals/evals.config.ts +5 -0
- package/templates/grokbot-agents/evals/grokbot-agents.eval.ts +18 -0
- package/templates/grokbot-agents/init.json +18 -0
- package/templates/grokbot-agents/package.json +17 -0
- package/templates/grokbot-agents/tsconfig.json +12 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.Bqsulb9K.js +0 -1
- package/dist/docs/assets/index.md.D75GWhPl.js +0 -5
- package/dist/docs/assets/index.md.D75GWhPl.lean.js +0 -1
- package/dist/playground/assets/index-8YiozU89.js +0 -67
- package/dist/playground/assets/index-MbMxXg-y.css +0 -1
- /package/dist/docs/assets/{reference_cli.md.CJNc_xYK.lean.js → reference_cli.md.Dm67hd2D.lean.js} +0 -0
- /package/dist/docs/assets/{reference_extensions.md.DykHW3qL.lean.js → reference_extensions.md.CGmMLblt.lean.js} +0 -0
- /package/dist/docs/assets/{skills_otel.md.CqhobH3B.lean.js → skills_otel.md.B5Ddv1xH.lean.js} +0 -0
package/src/files.ts
CHANGED
|
@@ -163,8 +163,10 @@ export const AGENT_SERVE_USER_STORE_KEY_PREFIX = "agent-serve";
|
|
|
163
163
|
* Skills sit at store-root `skills/<name>/…` so exec-daemon's
|
|
164
164
|
* `--agent-store-skills-dir` walk finds them the same way it finds user-store
|
|
165
165
|
* skills. Workspace seeds sit at store-root `workspace/…` so the mount path
|
|
166
|
-
* the first cloud prompt names stays short.
|
|
167
|
-
*
|
|
166
|
+
* the first cloud prompt names stays short. Per-turn `workspaceFiles` sit at
|
|
167
|
+
* `sessions/<sessionId>/workspace/…` on that same shared mount (replace on
|
|
168
|
+
* later sends; wipe when a task session ends). Memory and artifacts stay
|
|
169
|
+
* under {@link STORAGE_KEY_ROOT}.
|
|
168
170
|
*/
|
|
169
171
|
function createAgentStoreKeys(root: string) {
|
|
170
172
|
return {
|
|
@@ -191,6 +193,11 @@ function createAgentStoreKeys(root: string) {
|
|
|
191
193
|
/** Personal-key cloud agents: namespaced like {@link userSkillsPrefix}. */
|
|
192
194
|
userWorkspacePrefix: (agent: string): string =>
|
|
193
195
|
`${AGENT_SERVE_USER_STORE_KEY_PREFIX}/${agent}/workspace/`,
|
|
196
|
+
sessionWorkspacePrefix: (sessionId: string): string =>
|
|
197
|
+
`sessions/${sessionId}/workspace/`,
|
|
198
|
+
/** Personal-key cloud agents: namespaced like {@link sessionWorkspacePrefix}. */
|
|
199
|
+
userSessionWorkspacePrefix: (agent: string, sessionId: string): string =>
|
|
200
|
+
`${AGENT_SERVE_USER_STORE_KEY_PREFIX}/${agent}/sessions/${sessionId}/workspace/`,
|
|
194
201
|
memoryDir: (agent: string): string => `${root}/${agent}/memory`,
|
|
195
202
|
memoryJournal: (agent: string): string =>
|
|
196
203
|
`${root}/${agent}/memory/journal.jsonl`,
|
package/src/index.ts
CHANGED
|
@@ -139,7 +139,9 @@ export {
|
|
|
139
139
|
TOOL_MCP_ENDPOINT_PATH,
|
|
140
140
|
} from "./internal/mcp-endpoint.js";
|
|
141
141
|
export {
|
|
142
|
+
REMINDER_ARGS_MAX_BYTES,
|
|
142
143
|
ReminderValidationError,
|
|
144
|
+
rejectAnonymousReminderHandlers,
|
|
143
145
|
UnknownReminderError,
|
|
144
146
|
} from "./internal/reminder-runner.js";
|
|
145
147
|
export type { AgentMount } from "./internal/server.js";
|
|
@@ -169,8 +171,10 @@ export { prompt } from "./prompt.js";
|
|
|
169
171
|
export type {
|
|
170
172
|
ReminderBusyPolicy,
|
|
171
173
|
ReminderCreateInput,
|
|
174
|
+
ReminderDefinition,
|
|
172
175
|
ReminderFireContext,
|
|
173
176
|
ReminderFireResult,
|
|
177
|
+
ReminderHandlerConfig,
|
|
174
178
|
ReminderHostApi,
|
|
175
179
|
ReminderInfo,
|
|
176
180
|
ReminderReschedule,
|
|
@@ -179,6 +183,7 @@ export type {
|
|
|
179
183
|
ReminderTarget,
|
|
180
184
|
ReminderUntilContext,
|
|
181
185
|
} from "./reminders.js";
|
|
186
|
+
export { defineReminder } from "./reminders.js";
|
|
182
187
|
export { defineResult } from "./result.js";
|
|
183
188
|
export { defineSchedule } from "./schedules.js";
|
|
184
189
|
export { defineSkill } from "./skills.js";
|
|
@@ -226,9 +231,7 @@ export {
|
|
|
226
231
|
|
|
227
232
|
/**
|
|
228
233
|
* Runtime config for an agent — authored at `agent/agent.ts` (the root
|
|
229
|
-
* agent) or `agent/subagents/<id>/agent.ts` (a subagent).
|
|
230
|
-
* `architecture: "v2"` to deploy onto the v2 control plane; omitted
|
|
231
|
-
* channel continuation then inherits kind `/v2` defaults.
|
|
234
|
+
* agent) or `agent/subagents/<id>/agent.ts` (a subagent).
|
|
232
235
|
*/
|
|
233
236
|
export function defineAgent(config: AgentConfig): AgentConfigDefinition {
|
|
234
237
|
return brandDefinition("agent", config);
|
|
@@ -1570,14 +1570,26 @@ export async function cmdDelete(
|
|
|
1570
1570
|
if (typeof ctx === "number") {
|
|
1571
1571
|
return ctx;
|
|
1572
1572
|
}
|
|
1573
|
-
|
|
1573
|
+
// Same dispatch as `stop`: v1 409s architecture-v2 slugs, so the v2
|
|
1574
|
+
// DELETE goes first. A v2 404 (missing slug, or an older backend)
|
|
1575
|
+
// falls through to the v1 agent-serve delete.
|
|
1576
|
+
let architecture: "v1" | "v2" = "v2";
|
|
1577
|
+
let accepted: DeleteAccepted | AgentkitStopAccepted;
|
|
1574
1578
|
try {
|
|
1575
|
-
accepted = await ctx.client.
|
|
1576
|
-
teamId: ctx.teamId,
|
|
1577
|
-
slug,
|
|
1578
|
-
});
|
|
1579
|
+
accepted = await ctx.client.deleteAgentkit({ teamId: ctx.teamId, slug });
|
|
1579
1580
|
} catch (error) {
|
|
1580
|
-
|
|
1581
|
+
if (!(error instanceof DeployApiError) || error.status !== 404) {
|
|
1582
|
+
return renderApiError(error, ctx.err);
|
|
1583
|
+
}
|
|
1584
|
+
try {
|
|
1585
|
+
accepted = await ctx.client.deleteDeployment({
|
|
1586
|
+
teamId: ctx.teamId,
|
|
1587
|
+
slug,
|
|
1588
|
+
});
|
|
1589
|
+
architecture = "v1";
|
|
1590
|
+
} catch (v1Error) {
|
|
1591
|
+
return renderApiError(v1Error, ctx.err);
|
|
1592
|
+
}
|
|
1581
1593
|
}
|
|
1582
1594
|
if (ctx.noWait) {
|
|
1583
1595
|
if (ctx.json) {
|
|
@@ -1588,7 +1600,11 @@ export async function cmdDelete(
|
|
|
1588
1600
|
return 0;
|
|
1589
1601
|
}
|
|
1590
1602
|
try {
|
|
1591
|
-
await pollUntilGone(ctx, slug)
|
|
1603
|
+
await pollUntilGone(ctx, slug, () =>
|
|
1604
|
+
architecture === "v2"
|
|
1605
|
+
? ctx.client.getAgentkitDeploy({ teamId: ctx.teamId, slug })
|
|
1606
|
+
: ctx.client.getDeployment({ teamId: ctx.teamId, slug })
|
|
1607
|
+
);
|
|
1592
1608
|
} catch (error) {
|
|
1593
1609
|
return renderApiError(error, ctx.err);
|
|
1594
1610
|
}
|
|
@@ -2103,7 +2119,12 @@ function transientDeployStatusWaitMs(
|
|
|
2103
2119
|
*/
|
|
2104
2120
|
async function pollUntilGone(
|
|
2105
2121
|
ctx: DeployCliContext,
|
|
2106
|
-
slug: string
|
|
2122
|
+
slug: string,
|
|
2123
|
+
getDetail: () => Promise<{
|
|
2124
|
+
status: string;
|
|
2125
|
+
progress?: DeploymentProgress;
|
|
2126
|
+
statusMessage?: string | null;
|
|
2127
|
+
}>
|
|
2107
2128
|
): Promise<void> {
|
|
2108
2129
|
const startedAt = Date.now();
|
|
2109
2130
|
const tty = process.stderr.isTTY === true;
|
|
@@ -2126,10 +2147,7 @@ async function pollUntilGone(
|
|
|
2126
2147
|
|
|
2127
2148
|
for (;;) {
|
|
2128
2149
|
try {
|
|
2129
|
-
const detail = await
|
|
2130
|
-
teamId: ctx.teamId,
|
|
2131
|
-
slug,
|
|
2132
|
-
});
|
|
2150
|
+
const detail = await getDetail();
|
|
2133
2151
|
report(deployProgressLabel(detail));
|
|
2134
2152
|
} catch (error: unknown) {
|
|
2135
2153
|
if (error instanceof DeployApiError && error.status === 404) {
|
|
@@ -82,6 +82,37 @@ const githubTokenResponseSchema: z.ZodType<CursorGithubToken> = z.object({
|
|
|
82
82
|
expiresAt: z.string().datetime(),
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
+
/** SCMs whose git fetches ride the backend's `/v0/scm-events/<provider>-git-proxy` routes. */
|
|
86
|
+
export type CursorScmCloneProvider = "gitlab" | "bitbucket";
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Proxied clone target for a GitLab / Bitbucket repository. The backend
|
|
90
|
+
* never hands out the provider credential: git fetches go to `remoteUrl`
|
|
91
|
+
* on the backend with the caller's own Cursor API key as a bearer token,
|
|
92
|
+
* and the backend adds the tenant credential per request.
|
|
93
|
+
*/
|
|
94
|
+
export interface CursorScmCloneTarget {
|
|
95
|
+
/** Absolute `<backend>/v0/scm-events/<provider>-git-proxy/<repo>.git`. */
|
|
96
|
+
remoteUrl: string;
|
|
97
|
+
/** Bearer credential git presents to the backend (the caller's API key). */
|
|
98
|
+
token: string;
|
|
99
|
+
/** ISO timestamp after which the caller re-resolves the target. */
|
|
100
|
+
expiresAt: string;
|
|
101
|
+
username: string;
|
|
102
|
+
authMode: "bearer";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const scmCloneTargetResponseSchema = z.object({
|
|
106
|
+
expiresAt: z.string().datetime(),
|
|
107
|
+
clone: z.object({
|
|
108
|
+
remotePath: z
|
|
109
|
+
.string()
|
|
110
|
+
.regex(/^\/v0\/scm-events\/[a-z]+-git-proxy\/.+\.git$/),
|
|
111
|
+
username: z.string().min(1),
|
|
112
|
+
authMode: z.literal("bearer"),
|
|
113
|
+
}),
|
|
114
|
+
});
|
|
115
|
+
|
|
85
116
|
const mcpToolSchema = z.object({
|
|
86
117
|
name: z.string(),
|
|
87
118
|
providerIdentifier: z.string().optional(),
|
|
@@ -490,6 +521,62 @@ export class CursorBackendClient {
|
|
|
490
521
|
return githubTokenResponseSchema.parse(parsed);
|
|
491
522
|
}
|
|
492
523
|
|
|
524
|
+
/**
|
|
525
|
+
* Resolve the proxied clone target for a GitLab / Bitbucket repository
|
|
526
|
+
* (`owner/name`; GitLab `path_with_namespace`). Same authorization as the
|
|
527
|
+
* provider proxy this host already calls; the returned remote lives on
|
|
528
|
+
* the backend and takes this client's API key, never a provider token.
|
|
529
|
+
*/
|
|
530
|
+
async getScmCloneTarget(
|
|
531
|
+
provider: CursorScmCloneProvider,
|
|
532
|
+
repo: string
|
|
533
|
+
): Promise<CursorScmCloneTarget> {
|
|
534
|
+
const label = provider === "gitlab" ? "GitLab" : "Bitbucket";
|
|
535
|
+
let response: Response;
|
|
536
|
+
try {
|
|
537
|
+
response = await this.fetchImpl(
|
|
538
|
+
`${this.backendUrl}/v0/scm-events/${provider}-clone-target`,
|
|
539
|
+
{
|
|
540
|
+
method: "POST",
|
|
541
|
+
headers: {
|
|
542
|
+
"content-type": "application/json",
|
|
543
|
+
authorization: `Bearer ${this.currentApiKey()}`,
|
|
544
|
+
},
|
|
545
|
+
body: JSON.stringify({ repo }),
|
|
546
|
+
signal: AbortSignal.timeout(30_000),
|
|
547
|
+
}
|
|
548
|
+
);
|
|
549
|
+
} catch (error) {
|
|
550
|
+
throw new CursorBackendError(
|
|
551
|
+
`Cursor ${label} clone target request failed: ${describeError(error)}`
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
const text = await response.text();
|
|
555
|
+
if (!response.ok) {
|
|
556
|
+
throw new CursorBackendError(
|
|
557
|
+
describeGithubTokenHttpFailure(response.status, text, label),
|
|
558
|
+
response.status,
|
|
559
|
+
retryAfterMsFromResponse(response)
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
let parsed: unknown;
|
|
563
|
+
try {
|
|
564
|
+
parsed = JSON.parse(text) as unknown;
|
|
565
|
+
} catch {
|
|
566
|
+
throw new CursorBackendError(
|
|
567
|
+
`Cursor backend returned a non-JSON ${label} clone target response.`
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
const body = scmCloneTargetResponseSchema.parse(parsed);
|
|
571
|
+
return {
|
|
572
|
+
remoteUrl: `${this.backendUrl}${body.clone.remotePath}`,
|
|
573
|
+
token: this.currentApiKey(),
|
|
574
|
+
expiresAt: body.expiresAt,
|
|
575
|
+
username: body.clone.username,
|
|
576
|
+
authMode: body.clone.authMode,
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
|
|
493
580
|
/**
|
|
494
581
|
* One unary Connect-JSON call on `aiserver.v1.<service>` with the same
|
|
495
582
|
* token exchange and 401 retry as the dashboard RPCs. Callers parse the
|
|
@@ -864,7 +951,8 @@ const MAX_GITHUB_TOKEN_RETRY_AFTER_MS = 60 * 60_000;
|
|
|
864
951
|
*/
|
|
865
952
|
function describeGithubTokenHttpFailure(
|
|
866
953
|
status: number,
|
|
867
|
-
bodyText: string
|
|
954
|
+
bodyText: string,
|
|
955
|
+
label = "GitHub"
|
|
868
956
|
): string {
|
|
869
957
|
const detail = githubTokenErrorFromBody(bodyText);
|
|
870
958
|
if (status === 401) {
|
|
@@ -875,7 +963,7 @@ function describeGithubTokenHttpFailure(
|
|
|
875
963
|
if (detail !== undefined) {
|
|
876
964
|
return detail;
|
|
877
965
|
}
|
|
878
|
-
return `Cursor
|
|
966
|
+
return `Cursor ${label} credential request failed (${status}).`;
|
|
879
967
|
}
|
|
880
968
|
|
|
881
969
|
function githubTokenErrorFromBody(bodyText: string): string | undefined {
|
|
@@ -675,6 +675,22 @@ export class AgentServeDeployClient {
|
|
|
675
675
|
return agentkitStopAcceptedSchema.parse(raw);
|
|
676
676
|
}
|
|
677
677
|
|
|
678
|
+
/**
|
|
679
|
+
* Delete a v2 deployment (`DELETE /internal/agentsdk/deployments/:slug`).
|
|
680
|
+
* 202 means accepted; poll {@link getAgentkitDeploy} until 404.
|
|
681
|
+
*/
|
|
682
|
+
async deleteAgentkit(args: {
|
|
683
|
+
teamId: number;
|
|
684
|
+
slug: string;
|
|
685
|
+
}): Promise<AgentkitStopAccepted> {
|
|
686
|
+
const raw = await this.request({
|
|
687
|
+
method: "DELETE",
|
|
688
|
+
path: `/internal/agentsdk/deployments/${encodeURIComponent(args.slug)}?teamId=${args.teamId}`,
|
|
689
|
+
context: { verb: "delete", slug: args.slug },
|
|
690
|
+
});
|
|
691
|
+
return agentkitStopAcceptedSchema.parse(raw);
|
|
692
|
+
}
|
|
693
|
+
|
|
678
694
|
async listDeployments(args: { teamId: number }): Promise<Deployment[]> {
|
|
679
695
|
const raw = await this.request({
|
|
680
696
|
method: "GET",
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
projectInfo,
|
|
48
48
|
runtimeArchitectureCompatibilityError,
|
|
49
49
|
} from "./discovery.js";
|
|
50
|
-
import { packageVersion } from "./distribution.js";
|
|
50
|
+
import { packageGitSha, packageVersion } from "./distribution.js";
|
|
51
51
|
|
|
52
52
|
export const DEPLOY_MANIFEST_VERSION: 1 = 1;
|
|
53
53
|
|
|
@@ -62,6 +62,10 @@ const agentDeployManifestV1Schema = z.object({
|
|
|
62
62
|
manifestVersion: z.literal(DEPLOY_MANIFEST_VERSION),
|
|
63
63
|
generatedAtMs: z.number().int().nonnegative(),
|
|
64
64
|
cliVersion: z.string().min(1),
|
|
65
|
+
cliGitSha: z
|
|
66
|
+
.string()
|
|
67
|
+
.regex(/^[0-9a-f]{40,64}$/)
|
|
68
|
+
.optional(),
|
|
65
69
|
declarations: z.object({
|
|
66
70
|
egressDomains: z.array(z.string().min(1)).max(64),
|
|
67
71
|
publicRoutePaths: z.array(z.string().min(1)).max(64),
|
|
@@ -115,6 +119,8 @@ export interface AgentDeployManifestV1 {
|
|
|
115
119
|
generatedAtMs: number;
|
|
116
120
|
/** `@cursor/july` version that produced the manifest. */
|
|
117
121
|
cliVersion: string;
|
|
122
|
+
/** Git commit for a checkout-built `@cursor/july`; absent for npm builds. */
|
|
123
|
+
cliGitSha?: string;
|
|
118
124
|
declarations: AgentDeployManifestDeclarations;
|
|
119
125
|
/**
|
|
120
126
|
* Full `projectInfo` payload (see `GET /v1/info`). Opaque to the wire
|
|
@@ -129,7 +135,7 @@ export interface AgentDeployManifestV1 {
|
|
|
129
135
|
*/
|
|
130
136
|
export function buildAgentDeployManifest(
|
|
131
137
|
project: AgentProject,
|
|
132
|
-
options?: { nowMs?: number; cliVersion?: string }
|
|
138
|
+
options?: { nowMs?: number; cliVersion?: string; cliGitSha?: string }
|
|
133
139
|
): AgentDeployManifestV1 {
|
|
134
140
|
const runtimeArchitectureError = runtimeArchitectureCompatibilityError(
|
|
135
141
|
project.agent
|
|
@@ -167,20 +173,19 @@ export function buildAgentDeployManifest(
|
|
|
167
173
|
manifestVersion: DEPLOY_MANIFEST_VERSION,
|
|
168
174
|
generatedAtMs: options?.nowMs ?? Date.now(),
|
|
169
175
|
cliVersion: options?.cliVersion ?? packageVersion(),
|
|
176
|
+
cliGitSha: options?.cliGitSha ?? packageGitSha(),
|
|
170
177
|
declarations: {
|
|
171
178
|
egressDomains: [...(project.agent.hosting?.egressDomains ?? [])],
|
|
172
179
|
publicRoutePaths,
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
//
|
|
180
|
+
// Deploy manifests describe Cursor-hosted deployments. When the agent
|
|
181
|
+
// authors no storage, framework-storage-selection.ts injects the
|
|
182
|
+
// platform Cursor-hosted mirror for both v1 and v2.
|
|
176
183
|
frameworkStorage:
|
|
177
|
-
project.
|
|
184
|
+
project.storage === undefined
|
|
178
185
|
? "cursor-hosted"
|
|
179
|
-
: project.storage
|
|
180
|
-
? "
|
|
181
|
-
:
|
|
182
|
-
? "cursor-hosted"
|
|
183
|
-
: "other",
|
|
186
|
+
: isCursorHostedStorage(project.storage)
|
|
187
|
+
? "cursor-hosted"
|
|
188
|
+
: "other",
|
|
184
189
|
...(project.agent.architecture === undefined
|
|
185
190
|
? {}
|
|
186
191
|
: { architecture: project.agent.architecture }),
|
|
@@ -151,6 +151,12 @@ export function projectInfo(project: AgentProject): AgentProjectInfo {
|
|
|
151
151
|
cron: schedule.cron,
|
|
152
152
|
kind: schedule.kind,
|
|
153
153
|
})),
|
|
154
|
+
reminders:
|
|
155
|
+
(project.reminders ?? []).length === 0
|
|
156
|
+
? undefined
|
|
157
|
+
: (project.reminders ?? []).map((reminder) => ({
|
|
158
|
+
name: reminder.name,
|
|
159
|
+
})),
|
|
154
160
|
hooks: project.hooks.map((hook) => hook.name),
|
|
155
161
|
abs: project.abs.map((experiment) => experiment.name),
|
|
156
162
|
...(project.abConfig === undefined && project.abs.length === 0
|
|
@@ -9,10 +9,7 @@ import { type DiscoveryContext, displayPath, errorMessage } from "./context.js";
|
|
|
9
9
|
import { isDirectory, isModuleFile, moduleStem, sortedEntries } from "./fs.js";
|
|
10
10
|
import { validateName } from "./names.js";
|
|
11
11
|
|
|
12
|
-
type ImportableKind = Exclude<
|
|
13
|
-
DefinitionKind,
|
|
14
|
-
"instructions" | "eval" | "reminder"
|
|
15
|
-
>;
|
|
12
|
+
type ImportableKind = Exclude<DefinitionKind, "instructions" | "eval">;
|
|
16
13
|
|
|
17
14
|
/** The module files of a slot directory whose filenames are valid names. */
|
|
18
15
|
export async function moduleEntries(
|
|
@@ -104,6 +101,7 @@ const DEFINE_HELPER_NAME: Record<ImportableKind, string> = {
|
|
|
104
101
|
channel: "defineChannel",
|
|
105
102
|
"http-channel": "httpChannel",
|
|
106
103
|
schedule: "defineSchedule",
|
|
104
|
+
reminder: "defineReminder",
|
|
107
105
|
hook: "defineHook",
|
|
108
106
|
ab: "defineAB",
|
|
109
107
|
storage: "defineStorage",
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from "./fs.js";
|
|
32
32
|
import { loadHooks } from "./hooks.js";
|
|
33
33
|
import { NAME_PATTERN } from "./names.js";
|
|
34
|
+
import { loadReminders } from "./reminders.js";
|
|
34
35
|
import { loadSchedules } from "./schedules.js";
|
|
35
36
|
import {
|
|
36
37
|
appendArtifactTool,
|
|
@@ -236,6 +237,7 @@ export async function loadAgentProject(
|
|
|
236
237
|
}
|
|
237
238
|
const schedules = await loadSchedules(ctx, join(agentDir, "schedules"));
|
|
238
239
|
schedules.push(...projectSlots.schedules);
|
|
240
|
+
const reminders = await loadReminders(ctx, join(agentDir, "reminders"));
|
|
239
241
|
const hooks = await loadHooks(ctx, join(agentDir, "hooks"));
|
|
240
242
|
hooks.push(...projectSlots.hooks);
|
|
241
243
|
const abs = await loadABs(ctx, agentDir);
|
|
@@ -291,6 +293,7 @@ export async function loadAgentProject(
|
|
|
291
293
|
httpChannel: resolvedHttpChannel,
|
|
292
294
|
channels,
|
|
293
295
|
schedules,
|
|
296
|
+
reminders,
|
|
294
297
|
hooks,
|
|
295
298
|
abs,
|
|
296
299
|
abConfig,
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agent/reminders/*.ts`: named durable reminder fire handlers.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { basename, extname, relative } from "node:path";
|
|
6
|
+
import type { DiscoveredReminder, ReminderDefinition } from "../../types.js";
|
|
7
|
+
import { getDefinitionKind } from "../brand.js";
|
|
8
|
+
import { type DiscoveryContext, displayPath } from "./context.js";
|
|
9
|
+
import { isDirectory, isModuleFile, toPosix, walkFiles } from "./fs.js";
|
|
10
|
+
import { importDefault } from "./modules.js";
|
|
11
|
+
import { NAME_PATTERN } from "./names.js";
|
|
12
|
+
|
|
13
|
+
export async function loadReminders(
|
|
14
|
+
ctx: DiscoveryContext,
|
|
15
|
+
remindersDir: string,
|
|
16
|
+
onDisable?: (name: string, path: string) => void
|
|
17
|
+
): Promise<DiscoveredReminder[]> {
|
|
18
|
+
if (!(await isDirectory(remindersDir))) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
const reminders: DiscoveredReminder[] = [];
|
|
22
|
+
for (const filePath of await walkFiles(remindersDir)) {
|
|
23
|
+
const rel = toPosix(relative(remindersDir, filePath));
|
|
24
|
+
if (!isModuleFile(basename(filePath))) {
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const name = rel.slice(0, -extname(rel).length);
|
|
28
|
+
if (!NAME_PATTERN.test(name) || name.includes("__")) {
|
|
29
|
+
ctx.diagnostics.push({
|
|
30
|
+
severity: "error",
|
|
31
|
+
path: displayPath(ctx, filePath),
|
|
32
|
+
message: name.includes("__")
|
|
33
|
+
? `Reminder name "${name}" may not contain "__"; it is reserved for extension contributions (\`<ns>__<name>\`).`
|
|
34
|
+
: `Reminder name "${name}" must match ${NAME_PATTERN}.`,
|
|
35
|
+
});
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const definition = await importDefault(
|
|
39
|
+
ctx,
|
|
40
|
+
filePath,
|
|
41
|
+
onDisable === undefined ? "reminder" : ["reminder", "disabled"]
|
|
42
|
+
);
|
|
43
|
+
if (definition === undefined) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (getDefinitionKind(definition) === "disabled") {
|
|
47
|
+
onDisable?.(name, filePath);
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const reminder = definition as ReminderDefinition;
|
|
51
|
+
if (typeof reminder.run !== "function") {
|
|
52
|
+
ctx.diagnostics.push({
|
|
53
|
+
severity: "error",
|
|
54
|
+
path: displayPath(ctx, filePath),
|
|
55
|
+
message: "Reminder handlers require a `run` function.",
|
|
56
|
+
});
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
reminders.push({
|
|
60
|
+
name,
|
|
61
|
+
definition: reminder,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
return reminders;
|
|
65
|
+
}
|
|
@@ -13,6 +13,8 @@ import { fileURLToPath, pathToFileURL } from "node:url";
|
|
|
13
13
|
|
|
14
14
|
/** Published npm package name (pre-launch codename for Agent SDK). */
|
|
15
15
|
export const PACKAGE_NAME = "@cursor/july";
|
|
16
|
+
const HOSTED_WORKTREE_SHA_FILENAME = ".cursor-hosted-worktree-sha";
|
|
17
|
+
const GIT_COMMIT_SHA_RE = /^[0-9a-f]{40,64}$/;
|
|
16
18
|
|
|
17
19
|
/**
|
|
18
20
|
* Bracketed product tag for stderr / ServeOptions.logger lines
|
|
@@ -59,6 +61,24 @@ export function packageVersion(): string {
|
|
|
59
61
|
return packageManifest().version;
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Git commit of a checkout-built framework distribution. Published npm
|
|
66
|
+
* packages do not carry this marker and return undefined.
|
|
67
|
+
*/
|
|
68
|
+
export function packageGitSha(): string | undefined {
|
|
69
|
+
try {
|
|
70
|
+
const sha = readFileSync(
|
|
71
|
+
join(packageRootDir(), "dist", HOSTED_WORKTREE_SHA_FILENAME),
|
|
72
|
+
"utf8"
|
|
73
|
+
)
|
|
74
|
+
.trim()
|
|
75
|
+
.toLowerCase();
|
|
76
|
+
return GIT_COMMIT_SHA_RE.test(sha) ? sha : undefined;
|
|
77
|
+
} catch {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
62
82
|
/** Facts `agent-sdk version` / `--version` print. */
|
|
63
83
|
export interface CliVersionInfo {
|
|
64
84
|
/** Published npm name (`@cursor/july`). */
|
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* - the **framework-level** store (`AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID`)
|
|
10
10
|
* holds engine-owned session state — session records, event transcripts,
|
|
11
11
|
* hosted-execution run logs, the continuation index, and the SDK
|
|
12
|
-
* conversation mirror — and is never
|
|
12
|
+
* conversation mirror — and is never mounted into author code or models.
|
|
13
|
+
* The authenticated dashboard may read diagnostic families, but never the
|
|
14
|
+
* continuation index.
|
|
13
15
|
*
|
|
14
16
|
* This module puts framework session state on the framework store. The
|
|
15
17
|
* {@link storageKeys} scheme was designed for exactly this: keys are a
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
* That selection is a hosting-mode question, not an authoring question.
|
|
14
14
|
* Architecture v2 moves it here: `agent/storage.ts` is rejected at
|
|
15
15
|
* discovery (error diagnostic, so serve and deploy fail early), and the
|
|
16
|
-
* platform picks the default
|
|
16
|
+
* platform picks the default. Architecture v1 with no authored file now
|
|
17
|
+
* uses the same hosted-vs-self-hosted split, so deleting `agent/storage.ts`
|
|
18
|
+
* (required to deploy the same tree onto v2) does not drop the Cursor-hosted
|
|
19
|
+
* session mirror on a still-v1 pod.
|
|
17
20
|
*
|
|
18
21
|
* - **Cursor-managed hosting** (the deployment-generation environment
|
|
19
22
|
* variable is set, same signal that registers `GET /v1/manifest`):
|
|
@@ -33,8 +36,10 @@
|
|
|
33
36
|
* - **Self-hosted**: no mirror. `--state-root` is the durable copy, which
|
|
34
37
|
* is correct when the operator owns the disk.
|
|
35
38
|
*
|
|
36
|
-
* v1
|
|
37
|
-
*
|
|
39
|
+
* v1 still honors an authored `agent/storage.ts` when present. Hosted v1
|
|
40
|
+
* pods with no authored file get the Cursor-hosted lazy mirror (gated on
|
|
41
|
+
* `AGENT_SERVE_DEPLOYMENT_ID`, the same signal the previous authored sinks
|
|
42
|
+
* used). Self-hosted v1 with no authored file stays disk-only.
|
|
38
43
|
*
|
|
39
44
|
* Local disk is not part of this decision. `<stateRoot>/sessions/<id>/`
|
|
40
45
|
* already holds `session.json` and `events.ndjson` unconditionally, through
|
|
@@ -44,6 +49,10 @@
|
|
|
44
49
|
|
|
45
50
|
import { cursorHostedFiles } from "../files-backends/cursor-hosted.js";
|
|
46
51
|
import { defineStorage, type StorageDefinition } from "../storage.js";
|
|
52
|
+
import {
|
|
53
|
+
AGENT_SERVE_DEPLOYMENT_ID_ENV_VAR,
|
|
54
|
+
cursorHostedStorage,
|
|
55
|
+
} from "../storage-backends/cursor-hosted.js";
|
|
47
56
|
import { cursorHostedStorageV2 } from "../storage-backends/cursor-hosted-v2.js";
|
|
48
57
|
import type { AgentArchitecture } from "../types.js";
|
|
49
58
|
import { resolveApiKeySync } from "./cursor/credentials.js";
|
|
@@ -54,6 +63,13 @@ import {
|
|
|
54
63
|
} from "./framework-file-storage.js";
|
|
55
64
|
import { resolveAgentV2Hosting } from "./v2-hosting.js";
|
|
56
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Hosted v2 event-chunk flush debounce. Matches the session view's live poll
|
|
68
|
+
* cadence; a streaming turn still caps each chunk at the coordinator's batch
|
|
69
|
+
* limit, so a long turn writes a few dozen chunks rather than one per event.
|
|
70
|
+
*/
|
|
71
|
+
export const HOSTED_V2_EVENT_FLUSH_DEBOUNCE_MS = 2_000;
|
|
72
|
+
|
|
57
73
|
export interface FrameworkStorageSelectionInput {
|
|
58
74
|
/** `agent/storage.ts`, when the author wrote one (v1 only: discovery rejects it on v2). */
|
|
59
75
|
readonly authored: StorageDefinition | undefined;
|
|
@@ -73,8 +89,21 @@ export function selectFrameworkStorageDefinition(
|
|
|
73
89
|
input: FrameworkStorageSelectionInput
|
|
74
90
|
): StorageDefinition | undefined {
|
|
75
91
|
if (input.architecture !== "v2") {
|
|
76
|
-
|
|
77
|
-
|
|
92
|
+
if (input.authored !== undefined) {
|
|
93
|
+
return input.authored;
|
|
94
|
+
}
|
|
95
|
+
const env = input.env ?? process.env;
|
|
96
|
+
if ((env[AGENT_SERVE_DEPLOYMENT_ID_ENV_VAR] ?? "").trim() !== "") {
|
|
97
|
+
// Hosted v1 pod with no authored sink: keep the Cursor-hosted
|
|
98
|
+
// mirror (lazy restore) so agents can delete `agent/storage.ts`
|
|
99
|
+
// without losing durability while they still run architecture v1.
|
|
100
|
+
return defineStorage({
|
|
101
|
+
name: "cursor-hosted (lazy restore)",
|
|
102
|
+
policy: { restore: "off" },
|
|
103
|
+
...cursorHostedStorage(),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return undefined;
|
|
78
107
|
}
|
|
79
108
|
if (input.authored !== undefined) {
|
|
80
109
|
// Discovery rejects agent/storage.ts on v2 before an engine is built;
|
|
@@ -97,7 +126,15 @@ export function selectFrameworkStorageDefinition(
|
|
|
97
126
|
// backend it is per-key HTTP round trips before the listener even
|
|
98
127
|
// comes up). Follow-ups restore lazily by continuation or session id;
|
|
99
128
|
// GET /v1/sessions lists from the sink either way.
|
|
100
|
-
|
|
129
|
+
//
|
|
130
|
+
// Events flush on a quiet-period debounce rather than only at turn end so
|
|
131
|
+
// the read-only session view and dashboard trace (which have no resident
|
|
132
|
+
// engine to ask) see steps mid-turn. The turn-end record still lands
|
|
133
|
+
// before the execution reply: drainSessionDurability forces the flush.
|
|
134
|
+
const policy = {
|
|
135
|
+
restore: "off",
|
|
136
|
+
debounceMs: HOSTED_V2_EVENT_FLUSH_DEBOUNCE_MS,
|
|
137
|
+
} as const;
|
|
101
138
|
// Full chain (env → bind file → stored login): frozen engines listen
|
|
102
139
|
// unsigned and bind store ids + CURSOR_API_KEY at task time, after this
|
|
103
140
|
// definition is constructed.
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
* with that message instead of throwing.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
import { HOSTED_GUEST_RETRY_TRANSIENT } from "./hosted-delivery-protocol.js";
|
|
23
|
+
|
|
22
24
|
export const GUEST_NETWORK_UNAVAILABLE = "guest_network_unavailable";
|
|
23
25
|
export const GUEST_CONNECT_STALLED = "guest_connect_stalled";
|
|
24
26
|
|
|
@@ -369,6 +371,7 @@ export async function guestNetworkReadinessResponse(
|
|
|
369
371
|
JSON.stringify({
|
|
370
372
|
ok: false,
|
|
371
373
|
error: GUEST_NETWORK_UNAVAILABLE,
|
|
374
|
+
retry: HOSTED_GUEST_RETRY_TRANSIENT,
|
|
372
375
|
message: error.message,
|
|
373
376
|
waitMs: error.waitMs,
|
|
374
377
|
probeAttempts: error.probeAttempts,
|