@cursor/july 0.1.88 → 0.1.90

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.
Files changed (193) hide show
  1. package/README.md +95 -94
  2. package/dist/ab.d.ts +1 -1
  3. package/dist/ab.js +1 -1
  4. package/dist/artifacts.d.ts +1 -1
  5. package/dist/artifacts.js +1 -1
  6. package/dist/bin/agent-serve.js +21 -8
  7. package/dist/channels.d.ts +1 -1
  8. package/dist/channels.js +1 -1
  9. package/dist/connections.d.ts +1 -1
  10. package/dist/connections.js +1 -1
  11. package/dist/docs/404.html +2 -2
  12. package/dist/docs/ab.html +3 -3
  13. package/dist/docs/assets/{app.DUOPbN18.js → app.wiNkt6G7.js} +1 -1
  14. package/dist/docs/assets/chunks/@localSearchIndexroot.FV0R6kOb.js +1 -0
  15. package/dist/docs/assets/chunks/{VPLocalSearchBox.CmWbGcGk.js → VPLocalSearchBox.ByhUGu47.js} +1 -1
  16. package/dist/docs/assets/chunks/{theme.S57OeOLA.js → theme.Dx7j_-0n.js} +2 -2
  17. package/dist/docs/assets/{concepts.md.BXAm6G-C.js → concepts.md.2NfkGjqM.js} +1 -1
  18. package/dist/docs/assets/{reference_project-layout.md.D3MdHM2z.js → reference_project-layout.md.CueaKpjr.js} +5 -20
  19. package/dist/docs/assets/reference_project-layout.md.CueaKpjr.lean.js +1 -0
  20. package/dist/docs/assets/{reference_tools.md.DTg_kEsx.js → reference_tools.md.XmeFP_3d.js} +23 -2
  21. package/dist/docs/assets/{reference_tools.md.DTg_kEsx.lean.js → reference_tools.md.XmeFP_3d.lean.js} +1 -1
  22. package/dist/docs/assets/{scaffolding-agents.md.CiGsJ1aw.js → scaffolding-agents.md.BpMFXv2J.js} +1 -1
  23. package/dist/docs/building-with-agents.html +3 -3
  24. package/dist/docs/concepts.html +5 -5
  25. package/dist/docs/deployment.html +3 -3
  26. package/dist/docs/evals.html +3 -3
  27. package/dist/docs/example-agents/approval-buddy.html +3 -3
  28. package/dist/docs/example-agents/benny.html +3 -3
  29. package/dist/docs/example-agents/bugbot.html +3 -3
  30. package/dist/docs/example-agents/codebase-wiki.html +3 -3
  31. package/dist/docs/example-agents/codeowners-review.html +3 -3
  32. package/dist/docs/example-agents/concierge.html +3 -3
  33. package/dist/docs/example-agents/fsd.html +3 -3
  34. package/dist/docs/example-agents/index.html +3 -3
  35. package/dist/docs/example-agents/knowledge-base.html +3 -3
  36. package/dist/docs/example-agents/oncall.html +3 -3
  37. package/dist/docs/example-agents/security-reviewer.html +3 -3
  38. package/dist/docs/example-agents/slack-agent.html +3 -3
  39. package/dist/docs/example-agents/weather-agent.html +3 -3
  40. package/dist/docs/guides/agent-to-agent.html +3 -3
  41. package/dist/docs/guides/cloud-runtime.html +3 -3
  42. package/dist/docs/guides/convert-automation.html +3 -3
  43. package/dist/docs/guides/github.html +3 -3
  44. package/dist/docs/guides/human-in-the-loop.html +3 -3
  45. package/dist/docs/guides/mcp-oauth.html +3 -3
  46. package/dist/docs/guides/opentelemetry.html +3 -3
  47. package/dist/docs/guides/slack.html +3 -3
  48. package/dist/docs/guides/webhooks.html +3 -3
  49. package/dist/docs/hashmap.json +1 -1
  50. package/dist/docs/hillclimbing.html +3 -3
  51. package/dist/docs/index.html +3 -3
  52. package/dist/docs/quickstart.html +3 -3
  53. package/dist/docs/reference/agent-config.html +3 -3
  54. package/dist/docs/reference/artifacts.html +3 -3
  55. package/dist/docs/reference/channels.html +3 -3
  56. package/dist/docs/reference/cli.html +3 -3
  57. package/dist/docs/reference/connections.html +3 -3
  58. package/dist/docs/reference/hooks.html +3 -3
  59. package/dist/docs/reference/http-api.html +3 -3
  60. package/dist/docs/reference/instructions.html +3 -3
  61. package/dist/docs/reference/playground.html +3 -3
  62. package/dist/docs/reference/project-layout.html +8 -23
  63. package/dist/docs/reference/prompt.html +3 -3
  64. package/dist/docs/reference/schedules.html +3 -3
  65. package/dist/docs/reference/sessions.html +3 -3
  66. package/dist/docs/reference/skills.html +3 -3
  67. package/dist/docs/reference/subagents.html +3 -3
  68. package/dist/docs/reference/tools.html +27 -6
  69. package/dist/docs/scaffolding-agents.html +5 -5
  70. package/dist/docs/storage.html +3 -3
  71. package/dist/docs/templates/agentic-owners.html +3 -3
  72. package/dist/docs/templates/demo.html +3 -3
  73. package/dist/docs/templates/pr-autofixer.html +3 -3
  74. package/dist/docs/templates/security-reviewer.html +3 -3
  75. package/dist/docs/templates/triage.html +3 -3
  76. package/dist/docs/troubleshooting.html +3 -3
  77. package/dist/evals.d.ts +1 -1
  78. package/dist/evals.js +1 -1
  79. package/dist/hooks.d.ts +1 -1
  80. package/dist/hooks.js +1 -1
  81. package/dist/index.d.ts +2 -2
  82. package/dist/index.js +2 -2
  83. package/dist/internal/advertise-tools.d.ts.map +1 -1
  84. package/dist/internal/advertise-tools.js +1 -1
  85. package/dist/internal/cli-ax.js +1 -1
  86. package/dist/internal/cli-convert-automation.d.ts +1 -1
  87. package/dist/internal/cli-convert-automation.js +1 -1
  88. package/dist/internal/cli-cursor.d.ts +12 -4
  89. package/dist/internal/cli-cursor.d.ts.map +1 -1
  90. package/dist/internal/cli-cursor.js +11 -4
  91. package/dist/internal/cli-deploy.d.ts +3 -2
  92. package/dist/internal/cli-deploy.d.ts.map +1 -1
  93. package/dist/internal/cli-deploy.js +84 -9
  94. package/dist/internal/convert-automation/convert-workflow.d.ts +1 -1
  95. package/dist/internal/convert-automation/convert-workflow.js +9 -9
  96. package/dist/internal/convert-automation/types.d.ts +1 -1
  97. package/dist/internal/convert-automation/types.js +1 -1
  98. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  99. package/dist/internal/cursor/account-mcp.js +8 -4
  100. package/dist/internal/cursor/backend-client.d.ts +17 -1
  101. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  102. package/dist/internal/cursor/backend-client.js +42 -7
  103. package/dist/internal/cursor/credentials.d.ts +35 -9
  104. package/dist/internal/cursor/credentials.d.ts.map +1 -1
  105. package/dist/internal/cursor/credentials.js +92 -39
  106. package/dist/internal/deploy-client.d.ts +42 -1
  107. package/dist/internal/deploy-client.d.ts.map +1 -1
  108. package/dist/internal/deploy-client.js +70 -2
  109. package/dist/internal/discovery.js +1 -1
  110. package/dist/internal/distribution.d.ts +18 -0
  111. package/dist/internal/distribution.d.ts.map +1 -1
  112. package/dist/internal/distribution.js +19 -0
  113. package/dist/internal/eval-runner.js +1 -1
  114. package/dist/internal/grokbot/runner.d.ts +5 -2
  115. package/dist/internal/grokbot/runner.d.ts.map +1 -1
  116. package/dist/internal/grokbot/runner.js +10 -6
  117. package/dist/internal/init-project.d.ts.map +1 -1
  118. package/dist/internal/init-project.js +8 -1
  119. package/dist/internal/mcp-endpoint.js +2 -1
  120. package/dist/internal/sdk-runner.d.ts +5 -0
  121. package/dist/internal/sdk-runner.d.ts.map +1 -1
  122. package/dist/internal/sdk-runner.js +10 -5
  123. package/dist/internal/server.d.ts.map +1 -1
  124. package/dist/internal/server.js +80 -36
  125. package/dist/internal/session-engine.d.ts +9 -2
  126. package/dist/internal/session-engine.d.ts.map +1 -1
  127. package/dist/internal/session-engine.js +85 -28
  128. package/dist/internal/tool-policy.d.ts +33 -1
  129. package/dist/internal/tool-policy.d.ts.map +1 -1
  130. package/dist/internal/tool-policy.js +53 -0
  131. package/dist/playground/assets/index-BpVS-paP.css +1 -0
  132. package/dist/playground/assets/{index-Bqn91tW4.js → index-DxapiDj_.js} +45 -45
  133. package/dist/playground/index.html +2 -2
  134. package/dist/reminders.d.ts +1 -1
  135. package/dist/reminders.js +1 -1
  136. package/dist/schedules.d.ts +1 -1
  137. package/dist/schedules.js +1 -1
  138. package/dist/skills.d.ts +1 -1
  139. package/dist/skills.js +1 -1
  140. package/dist/storage.d.ts +1 -1
  141. package/dist/storage.js +1 -1
  142. package/dist/tools.d.ts +1 -1
  143. package/dist/tools.js +1 -1
  144. package/dist/types.d.ts +24 -2
  145. package/dist/types.d.ts.map +1 -1
  146. package/dist/types.js +1 -1
  147. package/docs/concepts.md +2 -1
  148. package/docs/reference/project-layout.md +5 -20
  149. package/docs/reference/tools.md +53 -3
  150. package/docs/scaffolding-agents.md +2 -0
  151. package/package.json +2 -1
  152. package/skills/debug/SKILL.md +1 -2
  153. package/skills/framework-map/SKILL.md +1 -2
  154. package/src/ab.ts +1 -1
  155. package/src/artifacts.ts +1 -1
  156. package/src/bin/agent-serve.ts +21 -7
  157. package/src/channels.ts +1 -1
  158. package/src/connections.ts +1 -1
  159. package/src/evals.ts +1 -1
  160. package/src/hooks.ts +1 -1
  161. package/src/index.ts +2 -2
  162. package/src/internal/advertise-tools.ts +1 -0
  163. package/src/internal/cli-ax.ts +1 -1
  164. package/src/internal/cli-convert-automation.ts +1 -1
  165. package/src/internal/cli-cursor.ts +18 -5
  166. package/src/internal/cli-deploy.ts +123 -15
  167. package/src/internal/convert-automation/convert-workflow.ts +9 -9
  168. package/src/internal/convert-automation/types.ts +1 -1
  169. package/src/internal/cursor/account-mcp.ts +15 -1
  170. package/src/internal/cursor/backend-client.ts +62 -4
  171. package/src/internal/cursor/credentials.ts +87 -24
  172. package/src/internal/deploy-client.ts +122 -2
  173. package/src/internal/discovery.ts +1 -1
  174. package/src/internal/distribution.ts +31 -0
  175. package/src/internal/eval-runner.ts +1 -1
  176. package/src/internal/grokbot/runner.ts +15 -6
  177. package/src/internal/init-project.ts +11 -1
  178. package/src/internal/mcp-endpoint.ts +2 -1
  179. package/src/internal/sdk-runner.ts +10 -4
  180. package/src/internal/server.ts +95 -33
  181. package/src/internal/session-engine.ts +86 -6
  182. package/src/internal/tool-policy.ts +80 -1
  183. package/src/reminders.ts +1 -1
  184. package/src/schedules.ts +1 -1
  185. package/src/skills.ts +1 -1
  186. package/src/storage.ts +1 -1
  187. package/src/tools.ts +1 -1
  188. package/src/types.ts +21 -2
  189. package/dist/docs/assets/chunks/@localSearchIndexroot.CxCtxfDE.js +0 -1
  190. package/dist/docs/assets/reference_project-layout.md.D3MdHM2z.lean.js +0 -1
  191. package/dist/playground/assets/index-C0_5hOsf.css +0 -1
  192. /package/dist/docs/assets/{concepts.md.BXAm6G-C.lean.js → concepts.md.2NfkGjqM.lean.js} +0 -0
  193. /package/dist/docs/assets/{scaffolding-agents.md.CiGsJ1aw.lean.js → scaffolding-agents.md.BpMFXv2J.lean.js} +0 -0
@@ -61,6 +61,7 @@ import {
61
61
  import { cmdManifest } from "../internal/cli-manifest.js";
62
62
  import {
63
63
  CLI_COMMAND_NAME as CLI,
64
+ formatCliVersion,
64
65
  PACKAGE_NAME,
65
66
  packageVersion,
66
67
  } from "../internal/distribution.js";
@@ -135,7 +136,7 @@ Usage:
135
136
  ${CLI} logout
136
137
  ${CLI} whoami [--json]
137
138
  ${CLI} update
138
- ${CLI} version
139
+ ${CLI} version [--json]
139
140
  ${CLI} deploy [--dir <path>] [--slug <slug> | --all] [--team <id>] [--json]
140
141
  [--no-wait] [--repo <url>] [--ref <ref>]
141
142
  [--path <agentPath>] [--cursor-events-repo <owner/name>]...
@@ -192,7 +193,7 @@ Commands:
192
193
  (also: npx @cursor/july docs). No agent project required.
193
194
  --print skips opening a browser. Ctrl-C stops the server.
194
195
  run One-shot create→test loop: ephemeral server + JSON trajectory.
195
- Writes a single events.ndjson trace (visualize in the playground).
196
+ Writes a single events.ndjson trace (summarize with trajectory).
196
197
  Streams tool calls and reply text to stderr when stderr is a TTY.
197
198
  Pass --prod to hit the hosted deployment instead of a local server.
198
199
  trajectory Summarize an events.ndjson file into a trajectory.
@@ -205,7 +206,7 @@ Commands:
205
206
  prompt. --json is machine-readable and never blocks on
206
207
  login. No directory: print the setup guide.
207
208
  convert-automation
208
- Export a Cursor Automation into an agentkit project. <url> is
209
+ Export a Cursor Automation into an agentsdk project. <url> is
209
210
  the dashboard URL (…/automations/<uuid> or
210
211
  …/custom-agents/<uuid>) or a bare uuid. Fetches the definition
211
212
  with your Cursor credentials, writes the converted files into
@@ -258,7 +259,9 @@ Commands:
258
259
  whoami Show which Cursor account powers this host (and why).
259
260
  update Upgrade this install to the latest published version (detects
260
261
  global npm/pnpm/yarn/bun installs and project dependencies).
261
- version Print the installed ${CLI} version and exit (also --version / -V).
262
+ version Print the ${PACKAGE_NAME} version this CLI will use and exit
263
+ (also --version / -V). Text is the version number; --json
264
+ prints { name, version, cli }.
262
265
  deploy Deploy onto Cursor's managed agent-serve hosting, then wait for
263
266
  the engine to come up. --repo/--ref/--path stay available;
264
267
  inside an agent git checkout they are inferred when omitted
@@ -292,7 +295,7 @@ Agent loop:
292
295
  ${CLI} dev .
293
296
 
294
297
  Options:
295
- --version, -V Print the installed version and exit.
298
+ --version, -V Print the version number and exit.
296
299
  --dir Project root (defaults to the current directory).
297
300
  --port Port to listen on (default 3000). When the default is
298
301
  taken, serve tries the next free port and prints a notice.
@@ -400,7 +403,7 @@ Options:
400
403
  --skip-report eval: ignore reporters from evals.config.ts / eval files.
401
404
  --no-stream run/eval: silence live progress on stderr (JSON still prints).
402
405
  --json JSON output (init/convert-automation/install-skills/
403
- info/chat/eval/logs/
406
+ info/chat/eval/logs/version/
404
407
  sessions/session/github; run defaults to JSON). logs:
405
408
  NDJSON progress/log events. session: trajectory JSON
406
409
  (not raw events).
@@ -474,7 +477,7 @@ async function main(argv: string[]): Promise<number> {
474
477
  return command === undefined ? 1 : 0;
475
478
  }
476
479
  if (command === "version" || command === "--version" || command === "-V") {
477
- await writeStdout(`${CLI} ${packageVersion()}\n`);
480
+ await writeStdout(formatCliVersion({ json: restIn.includes("--json") }));
478
481
  return 0;
479
482
  }
480
483
 
@@ -574,9 +577,14 @@ async function main(argv: string[]): Promise<number> {
574
577
  "no-artifacts": { type: "boolean", default: false },
575
578
  "skip-report": { type: "boolean", default: false },
576
579
  "max-concurrency": { type: "string" },
580
+ version: { type: "boolean", short: "V", default: false },
577
581
  },
578
582
  });
579
583
  const dir = values.dir ?? ".";
584
+ if (values.version === true) {
585
+ await writeStdout(formatCliVersion({ json: values.json === true }));
586
+ return 0;
587
+ }
580
588
 
581
589
  // Best-effort, cached, and silent on failure. `update` does its own fresh
582
590
  // lookup, --json runs stay quiet for machine consumers, and `mcp` skips it
@@ -1301,8 +1309,14 @@ async function main(argv: string[]): Promise<number> {
1301
1309
  loadLocalEnv();
1302
1310
  // Model turns need a Cursor credential. Prompt login before listen
1303
1311
  // so the first playground turn does not fail with a late auth error.
1312
+ // `--allow-anonymous` is the hosted trust boundary (alias token /
1313
+ // freeze bake): skip the login gate so health can bind without a
1314
+ // key. v1 hosted injects CURSOR_API_KEY at exec; freeze bind drops
1315
+ // CURSOR_API_KEY / CURSOR_API_KEY_FILE onto the listening process.
1316
+ // Self-hosted omit the flag and still fail-fast unsigned on a TTY-less host.
1304
1317
  const loginExit = await ensureCursorLogin({
1305
1318
  apiKey: values["api-key"],
1319
+ allowAnonymous: values["allow-anonymous"] === true,
1306
1320
  });
1307
1321
  if (loginExit !== 0) {
1308
1322
  return { kind: "login-failed", exitCode: loginExit };
package/src/channels.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  * and are mounted under `/v1/channels/<name>`:
10
10
  *
11
11
  * ```ts
12
- * import { defineChannel, POST } from "@anysphere/agent-serve/channels";
12
+ * import { defineChannel, POST } from "@cursor/july/channels";
13
13
  * import { z } from "zod";
14
14
  *
15
15
  * export default defineChannel({
@@ -8,7 +8,7 @@
8
8
  * `hostOnly: true` to keep it off the model (still on `host.mcp`).
9
9
  *
10
10
  * ```ts
11
- * import { defineConnection } from "@anysphere/agent-serve/connections";
11
+ * import { defineConnection } from "@cursor/july/connections";
12
12
  *
13
13
  * export default defineConnection({
14
14
  * url: "https://mcp.linear.app/mcp",
package/src/evals.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * `t.messageIncludes(...)`, or `t.check(value, includes(...))`.
8
8
  *
9
9
  * ```ts
10
- * import { defineEval, includes } from "@anysphere/agent-serve/evals";
10
+ * import { defineEval, includes } from "@cursor/july/evals";
11
11
  *
12
12
  * // One datapoint — id is the file path (evals/weather/nyc.eval.ts → weather/nyc)
13
13
  * export default defineEval({
package/src/hooks.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  * transcripts to your own database). Handlers are observe-only.
7
7
  *
8
8
  * ```ts
9
- * import { defineHook } from "@anysphere/agent-serve/hooks";
9
+ * import { defineHook } from "@cursor/july/hooks";
10
10
  *
11
11
  * export default defineHook({
12
12
  * events: {
package/src/index.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  /**
2
- * @anysphere/agent-serve
2
+ * @cursor/july
3
3
  *
4
4
  * Filesystem-first framework for Cursor agents: define an agent as markdown
5
5
  * and TypeScript files under an `agent/` directory, and serve it over
6
6
  * channels with the Cursor SDK as the execution harness.
7
7
  *
8
8
  * ```ts
9
- * import { serve } from "@anysphere/agent-serve";
9
+ * import { serve } from "@cursor/july";
10
10
  *
11
11
  * const handle = await serve(".", { port: 3000 });
12
12
  * console.log(`agent listening on ${handle.url}`);
@@ -246,6 +246,7 @@ function toDiscoveredTool(
246
246
  ...(info.annotations === undefined
247
247
  ? {}
248
248
  : { annotations: info.annotations }),
249
+ advertised: true,
249
250
  definition,
250
251
  };
251
252
  }
@@ -685,7 +685,7 @@ export async function cmdRun(options: AxCliOptions): Promise<number> {
685
685
  : playgroundUrl !== null
686
686
  ? `Open ${playgroundUrl}`
687
687
  : eventsPath !== undefined
688
- ? `Start the playground (${CLI_COMMAND_NAME} serve --dir ${options.dir}), then Open trace → ${eventsPath}`
688
+ ? `${CLI_COMMAND_NAME} trajectory --events ${eventsPath}`
689
689
  : null,
690
690
  trajectory: result.trajectory,
691
691
  },
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `agent-serve convert-automation <url>` — export a Cursor Automation into
3
- * an agentkit project.
3
+ * an agentsdk project.
4
4
  *
5
5
  * Fetches the automation's workflow from the backend export endpoint
6
6
  * (Bearer user API key, same credential chain as deploy), runs the pure
@@ -148,10 +148,12 @@ export async function cmdLogin(options: CursorCliOptions): Promise<number> {
148
148
  /**
149
149
  * Gate for commands that need a Cursor credential before they can do useful
150
150
  * work (`serve`, `dev`, interactive `init`). Already-signed-in hosts
151
- * (`--api-key` / `CURSOR_API_KEY` / stored login) return immediately.
152
- * Otherwise an interactive host runs {@link cmdLogin}; a non-interactive
153
- * one (CI, Docker) fails fast with {@link SIGN_IN_HINT} instead of polling
154
- * a browser that will never open.
151
+ * (`--api-key` / `CURSOR_API_KEY` / `CURSOR_API_KEY_FILE` / stored login) return immediately.
152
+ * Hosted `--allow-anonymous` (v1 alias-token engines and v2 freeze bake)
153
+ * skips this gate so health/manifest can bind without a Cursor key.
154
+ * Self-hosted omit the flag: an interactive host runs {@link cmdLogin};
155
+ * a non-interactive one (CI, Docker) fails fast with {@link SIGN_IN_HINT}
156
+ * instead of polling a browser that will never open.
155
157
  */
156
158
  export async function ensureCursorLogin(
157
159
  options: {
@@ -161,6 +163,12 @@ export async function ensureCursorLogin(
161
163
  * TTY.
162
164
  */
163
165
  interactive?: boolean;
166
+ /**
167
+ * `serve --allow-anonymous`: listen without a Cursor credential.
168
+ * Model turns still fail later if a key is required; freeze only
169
+ * needs `/v1/health` and `/v1/manifest`.
170
+ */
171
+ allowAnonymous?: boolean;
164
172
  /** Test seam. */
165
173
  login?: (options: CursorCliOptions) => Promise<number>;
166
174
  } = {}
@@ -169,6 +177,9 @@ export async function ensureCursorLogin(
169
177
  if (resolved !== undefined) {
170
178
  return 0;
171
179
  }
180
+ if (options.allowAnonymous === true) {
181
+ return 0;
182
+ }
172
183
  const interactive = options.interactive ?? process.stderr.isTTY === true;
173
184
  if (!interactive) {
174
185
  process.stderr.write(`Not signed in to Cursor. ${SIGN_IN_HINT}\n`);
@@ -243,12 +254,14 @@ function formatIdentity(identity: CursorIdentity): string {
243
254
  return name === "" ? `${email}${team}` : `${name} <${email}>${team}`;
244
255
  }
245
256
 
246
- function describeSource(source: "option" | "env" | "login"): string {
257
+ function describeSource(source: "option" | "env" | "file" | "login"): string {
247
258
  switch (source) {
248
259
  case "option":
249
260
  return "explicit --api-key / serve({ apiKey })";
250
261
  case "env":
251
262
  return "CURSOR_API_KEY environment variable";
263
+ case "file":
264
+ return "CURSOR_API_KEY_FILE (task bind)";
252
265
  case "login":
253
266
  return `stored login (${credentialsFilePath()})`;
254
267
  }
@@ -5,13 +5,15 @@
5
5
  *
6
6
  * All intelligence is server-side (backend/server/src/agentServe/); these
7
7
  * handlers resolve parameters (credentials, team, slug, the project's
8
- * `hosting` manifest block), call the management API through
9
- * `deploy-client.ts`, poll status, and render.
8
+ * `hosting` / `architecture` manifest block), call the v1 agent-serve or
9
+ * v2 agentkit management API through `deploy-client.ts`, poll status, and
10
+ * render.
10
11
  */
11
12
 
12
13
  import { basename, resolve } from "node:path";
13
14
  import { isPublicEndpointPolicy } from "../channels.js";
14
15
  import {
16
+ type AgentArchitecture,
15
17
  type AgentHostingOptions,
16
18
  isCursorAccountTransport,
17
19
  } from "../types.js";
@@ -24,18 +26,21 @@ import {
24
26
  import { authorizeCursorAccountConnectors } from "./cursor-account-mcp-auth.js";
25
27
  import { readDeployTemplate } from "./cursor-agent-template.js";
26
28
  import {
29
+ type AgentkitDeployAccepted,
30
+ type AgentkitDeployStatus,
27
31
  AgentServeDeployClient,
28
32
  type DeleteAccepted,
29
33
  type DeployAccepted,
30
34
  DeployApiError,
31
35
  type Deployment,
32
36
  type DeploymentDetail,
33
- type DeploymentStatus,
37
+ type DeploymentProgress,
34
38
  type DeploySource,
35
39
  deploymentServiceAccountId,
36
40
  type SecretInfo,
37
41
  type StopAccepted,
38
42
  slugFromDirectoryName,
43
+ TERMINAL_AGENTKIT_DEPLOY_STATUSES,
39
44
  TERMINAL_DEPLOY_STATUSES,
40
45
  validateDeploymentSlug,
41
46
  } from "./deploy-client.js";
@@ -648,6 +653,19 @@ async function deployOne(
648
653
  );
649
654
  }
650
655
 
656
+ if (manifest?.architecture === "v2") {
657
+ if (!ctx.json) {
658
+ ctx.err(" architecture: v2\n");
659
+ }
660
+ return deployOneAgentkit(ctx, extras, {
661
+ slug,
662
+ gitRepoUrl,
663
+ gitRef,
664
+ agentPath,
665
+ repositories: options.cursorEventsRepos,
666
+ });
667
+ }
668
+
651
669
  // Today's only source shape: the control plane builds from a git ref.
652
670
  // See DeploySource for the artifact seam.
653
671
  const source: DeploySource = {
@@ -702,7 +720,9 @@ async function deployOne(
702
720
 
703
721
  let detail: DeploymentDetail;
704
722
  try {
705
- detail = await pollUntil(ctx, slug, TERMINAL_DEPLOY_STATUSES);
723
+ detail = await pollUntil(ctx, slug, TERMINAL_DEPLOY_STATUSES, () =>
724
+ ctx.client.getDeployment({ teamId: ctx.teamId, slug })
725
+ );
706
726
  } catch (error) {
707
727
  return renderApiError(error, ctx.err);
708
728
  }
@@ -756,6 +776,85 @@ async function deployOne(
756
776
  return 0;
757
777
  }
758
778
 
779
+ /**
780
+ * `architecture: "v2"` deploy: POST `/internal/agentkit/deployments` and
781
+ * poll the matching GET. The v2 accept path starts freeze bake; it does
782
+ * not mint an engine alias or alias token.
783
+ */
784
+ async function deployOneAgentkit(
785
+ ctx: DeployCliContext,
786
+ extras: { jsonCollect?: unknown[] } | undefined,
787
+ args: {
788
+ slug: string;
789
+ gitRepoUrl: string;
790
+ gitRef: string | undefined;
791
+ agentPath: string | undefined;
792
+ repositories: string[] | undefined;
793
+ }
794
+ ): Promise<number> {
795
+ const { slug } = args;
796
+ let accepted: AgentkitDeployAccepted;
797
+ try {
798
+ accepted = await ctx.client.deployAgentkit({
799
+ teamId: ctx.teamId,
800
+ slug,
801
+ gitRepoUrl: args.gitRepoUrl,
802
+ gitRef: args.gitRef,
803
+ agentPath: args.agentPath,
804
+ repositories: args.repositories,
805
+ });
806
+ } catch (error) {
807
+ return renderApiError(error, ctx.err);
808
+ }
809
+
810
+ if (ctx.noWait) {
811
+ if (extras?.jsonCollect !== undefined) {
812
+ extras.jsonCollect.push(accepted);
813
+ } else if (ctx.json) {
814
+ ctx.out(`${JSON.stringify(accepted, null, 2)}\n`);
815
+ } else {
816
+ ctx.out(
817
+ `Deploy accepted: ${slug} (team ${ctx.teamId}, v2)\n` +
818
+ ` application: ${accepted.applicationId}\n` +
819
+ ` release: ${accepted.releaseId}\n`
820
+ );
821
+ }
822
+ return 0;
823
+ }
824
+
825
+ let detail: AgentkitDeployStatus;
826
+ try {
827
+ detail = await pollUntil(ctx, slug, TERMINAL_AGENTKIT_DEPLOY_STATUSES, () =>
828
+ ctx.client.getAgentkitDeploy({ teamId: ctx.teamId, slug })
829
+ );
830
+ } catch (error) {
831
+ return renderApiError(error, ctx.err);
832
+ }
833
+
834
+ if (extras?.jsonCollect !== undefined) {
835
+ extras.jsonCollect.push(detail);
836
+ return detail.status === "running" ? 0 : 1;
837
+ }
838
+
839
+ if (ctx.json) {
840
+ ctx.out(`${JSON.stringify(detail, null, 2)}\n`);
841
+ return detail.status === "running" ? 0 : 1;
842
+ }
843
+
844
+ if (detail.status !== "running") {
845
+ ctx.err(`Deployment ${slug} ended ${detail.status}\n`);
846
+ return 1;
847
+ }
848
+ ctx.out(
849
+ `Deployed ${slug} (team ${ctx.teamId})\n` +
850
+ ` status: running\n` +
851
+ ` architecture: v2\n` +
852
+ ` application: ${detail.applicationId}\n` +
853
+ ` release: ${detail.releaseId}\n`
854
+ );
855
+ return 0;
856
+ }
857
+
759
858
  /**
760
859
  * Post-deploy connector authorization for `cursorAccount` connections: the
761
860
  * agent's connectors execute with tokens owned by the deployment's service
@@ -845,6 +944,7 @@ async function runPostDeployConnectorAuth(
845
944
 
846
945
  interface DeployManifest {
847
946
  hosting: AgentHostingOptions | undefined;
947
+ architecture: AgentArchitecture | undefined;
848
948
  /** `cursorAccount` connections declared by the agent. */
849
949
  cursorAccountConnections: Array<{
850
950
  name: string;
@@ -872,6 +972,7 @@ async function readDeployManifest(dir: string): Promise<DeployManifest> {
872
972
  const project = await loadAgentProject(dir);
873
973
  return {
874
974
  hosting: project.agent.hosting,
975
+ architecture: project.agent.architecture,
875
976
  cursorAccountConnections: project.agent.connections.flatMap((connection) =>
876
977
  isCursorAccountTransport(connection.transport)
877
978
  ? [{ name: connection.name, servers: connection.transport.servers }]
@@ -1102,7 +1203,9 @@ export async function cmdStop(
1102
1203
  }
1103
1204
  let detail: DeploymentDetail;
1104
1205
  try {
1105
- detail = await pollUntil(ctx, slug, new Set(["stopped"]));
1206
+ detail = await pollUntil(ctx, slug, new Set(["stopped"]), () =>
1207
+ ctx.client.getDeployment({ teamId: ctx.teamId, slug })
1208
+ );
1106
1209
  } catch (error) {
1107
1210
  return renderApiError(error, ctx.err);
1108
1211
  }
@@ -1517,17 +1620,24 @@ export function createLineReader(
1517
1620
  * status so create → checkout → start is visible. Throws DeployApiError
1518
1621
  * on request failures or timeout.
1519
1622
  */
1520
- async function pollUntil(
1623
+ async function pollUntil<
1624
+ T extends {
1625
+ status: string;
1626
+ progress?: DeploymentProgress;
1627
+ statusMessage?: string | null;
1628
+ },
1629
+ >(
1521
1630
  ctx: DeployCliContext,
1522
1631
  slug: string,
1523
- terminal: ReadonlySet<DeploymentStatus>
1524
- ): Promise<DeploymentDetail> {
1632
+ terminal: ReadonlySet<T["status"]>,
1633
+ fetchDetail: () => Promise<T>
1634
+ ): Promise<T> {
1525
1635
  const startedAt = Date.now();
1526
1636
  const tty = process.stderr.isTTY === true;
1527
1637
  let lastLabel: string | undefined;
1528
1638
  let sawProgress = false;
1529
1639
 
1530
- const report = (detail: DeploymentDetail): void => {
1640
+ const report = (detail: T): void => {
1531
1641
  if (ctx.json) {
1532
1642
  return;
1533
1643
  }
@@ -1548,12 +1658,10 @@ async function pollUntil(
1548
1658
  };
1549
1659
 
1550
1660
  for (;;) {
1551
- const detail = await ctx.client
1552
- .getDeployment({ teamId: ctx.teamId, slug })
1553
- .catch((error: unknown) => {
1554
- finishProgressLine();
1555
- throw error;
1556
- });
1661
+ const detail = await fetchDetail().catch((error: unknown) => {
1662
+ finishProgressLine();
1663
+ throw error;
1664
+ });
1557
1665
  report(detail);
1558
1666
  if (terminal.has(detail.status)) {
1559
1667
  finishProgressLine();
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Pure Workflow → agentkit project converter.
2
+ * Pure Workflow → agentsdk project converter.
3
3
  *
4
4
  * Maps an exported Cursor automation (proto3 workflow JSON + enriched MCP
5
5
  * server list) to project files, warnings, and setup steps. No I/O, no
@@ -185,7 +185,7 @@ function renderInstructions(
185
185
  }
186
186
 
187
187
  /**
188
- * Strip Cursor-backend prompt markup that means nothing in agentkit:
188
+ * Strip Cursor-backend prompt markup that means nothing in agentsdk:
189
189
  * `@[label](action:...)` action tokens become their label text, and
190
190
  * unresolvable `%%INLINECODE<n>%%` storage placeholders are flagged (their
191
191
  * content is not in the export).
@@ -972,7 +972,7 @@ function emitSlackChannel(
972
972
  ? "channel-created"
973
973
  : "reaction-added";
974
974
  out.warnings.push(
975
- `Slack ${kind} trigger has no agentkit equivalent — its config is inlined as a comment in ${path}; handle the Slack event yourself on a dedicated Socket Mode app.`
975
+ `Slack ${kind} trigger has no agentsdk equivalent — its config is inlined as a comment in ${path}; handle the Slack event yourself on a dedicated Socket Mode app.`
976
976
  );
977
977
  }
978
978
  let reactionDropped = false;
@@ -995,7 +995,7 @@ function emitSlackChannel(
995
995
  }
996
996
  if (reactionDropped) {
997
997
  out.warnings.push(
998
- "The Slack trigger marked triggering messages with a completion reaction; agentkit has no completion-reaction option, so that signal is lost unless agent/instructions.md tells the agent to add the reaction itself via Slack tools."
998
+ "The Slack trigger marked triggering messages with a completion reaction; agentsdk has no completion-reaction option, so that signal is lost unless agent/instructions.md tells the agent to add the reaction itself via Slack tools."
999
999
  );
1000
1000
  }
1001
1001
  if (socketMode) {
@@ -1042,8 +1042,8 @@ function emitSlackChannel(
1042
1042
  if (blocksUnauthenticated) {
1043
1043
  out.warnings.push(
1044
1044
  includeBotPosts
1045
- ? "Some Slack watches only fired for authenticated Cursor users while others allowed anyone; agentkit has one bot-post setting per channel, so the export keeps bot posts ENABLED (the open watches depend on them) and the authenticated-only watches lose both their sender gate and their bot exclusion. Split the channels or add an onChannelPost gate."
1046
- : "The Slack trigger only fired for authenticated Cursor users (linked accounts on the owning team); agentkit has no equivalent sender gate, so the exported watch dispatches for ANY channel member (bot posts stay excluded). Add an onChannelPost gate in the channel if that matters."
1045
+ ? "Some Slack watches only fired for authenticated Cursor users while others allowed anyone; agentsdk has one bot-post setting per channel, so the export keeps bot posts ENABLED (the open watches depend on them) and the authenticated-only watches lose both their sender gate and their bot exclusion. Split the channels or add an onChannelPost gate."
1046
+ : "The Slack trigger only fired for authenticated Cursor users (linked accounts on the owning team); agentsdk has no equivalent sender gate, so the exported watch dispatches for ANY channel member (bot posts stay excluded). Add an onChannelPost gate in the channel if that matters."
1047
1047
  );
1048
1048
  }
1049
1049
  const engagement: string[] = [];
@@ -1309,9 +1309,9 @@ const ACTION_STEPS: Partial<Record<keyof ActionJson, string>> = {
1309
1309
  resolveReviewThreads:
1310
1310
  "Verify: resolve_review_threads — no built-in equivalent; resolve threads via the GitHub GraphQL API in a hook or tool.",
1311
1311
  microsoftTeams:
1312
- "Verify: microsoft_teams post — agentkit has no Teams channel; wire the Microsoft Teams API yourself.",
1312
+ "Verify: microsoft_teams post — agentsdk has no Teams channel; wire the Microsoft Teams API yourself.",
1313
1313
  readMicrosoftTeams:
1314
- "Verify: read_microsoft_teams — agentkit has no Teams tools; wire the Microsoft Teams API yourself.",
1314
+ "Verify: read_microsoft_teams — agentsdk has no Teams tools; wire the Microsoft Teams API yourself.",
1315
1315
  };
1316
1316
 
1317
1317
  interface SlackIntegrationState {
@@ -1375,7 +1375,7 @@ function behaviorSteps(
1375
1375
  const disabled = workflow.disabledDefaultTools ?? [];
1376
1376
  if (disabled.length > 0) {
1377
1377
  steps.push(
1378
- `Verify: disabled_default_tools (${disabled.join(", ")}) — agentkit has no default automation tools; enforce the equivalent restriction in agent/instructions.md.`
1378
+ `Verify: disabled_default_tools (${disabled.join(", ")}) — agentsdk has no default automation tools; enforce the equivalent restriction in agent/instructions.md.`
1379
1379
  );
1380
1380
  }
1381
1381
  return steps;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Types for `convertWorkflow` — the pure automation → agentkit project
2
+ * Types for `convertWorkflow` — the pure automation → agentsdk project
3
3
  * converter behind `agent-serve convert-automation`.
4
4
  *
5
5
  * The workflow arrives as generic proto3 JSON (lowerCamelCase field names,
@@ -21,7 +21,11 @@ import {
21
21
  ListToolsRequestSchema,
22
22
  } from "@modelcontextprotocol/sdk/types.js";
23
23
  import { bearerAuth } from "../../channels.js";
24
- import type { AgentProject, AuthPolicy } from "../../types.js";
24
+ import type {
25
+ AgentProject,
26
+ AuthPolicy,
27
+ McpToolAnnotations,
28
+ } from "../../types.js";
25
29
  import { isCursorAccountTransport } from "../../types.js";
26
30
  import { probeConnectorAuthUrls } from "../cursor-account-mcp-auth.js";
27
31
  import { LOG_PREFIX } from "../distribution.js";
@@ -151,6 +155,8 @@ interface CatalogTool {
151
155
  inputSchema: Record<string, unknown>;
152
156
  /** Present only when the connector's server declares one. */
153
157
  outputSchema?: Record<string, unknown>;
158
+ /** MCP spec annotations, present only when the server declared them. */
159
+ annotations?: McpToolAnnotations;
154
160
  }
155
161
 
156
162
  interface Catalog {
@@ -335,6 +341,11 @@ export class CursorAccountMcpBridge {
335
341
  ...(tool.outputSchema === undefined
336
342
  ? {}
337
343
  : { outputSchema: tool.outputSchema }),
344
+ // Already bounded to the MCP-spec fields at the backend-client
345
+ // parse; absent stays absent so classifiers fail closed.
346
+ ...(tool.annotations === undefined
347
+ ? {}
348
+ : { annotations: tool.annotations }),
338
349
  })),
339
350
  };
340
351
  });
@@ -510,6 +521,9 @@ function buildCatalog(servers: AccountMcpServer[]): Catalog {
510
521
  ...(tool.outputSchema === undefined
511
522
  ? {}
512
523
  : { outputSchema: tool.outputSchema }),
524
+ ...(tool.annotations === undefined
525
+ ? {}
526
+ : { annotations: tool.annotations }),
513
527
  };
514
528
  tools.push(entry);
515
529
  byExposedName.set(entry.exposedName, entry);