@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.
- package/README.md +95 -94
- package/dist/ab.d.ts +1 -1
- package/dist/ab.js +1 -1
- package/dist/artifacts.d.ts +1 -1
- package/dist/artifacts.js +1 -1
- package/dist/bin/agent-serve.js +21 -8
- package/dist/channels.d.ts +1 -1
- package/dist/channels.js +1 -1
- package/dist/connections.d.ts +1 -1
- package/dist/connections.js +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +3 -3
- package/dist/docs/assets/{app.DUOPbN18.js → app.wiNkt6G7.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.FV0R6kOb.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CmWbGcGk.js → VPLocalSearchBox.ByhUGu47.js} +1 -1
- package/dist/docs/assets/chunks/{theme.S57OeOLA.js → theme.Dx7j_-0n.js} +2 -2
- package/dist/docs/assets/{concepts.md.BXAm6G-C.js → concepts.md.2NfkGjqM.js} +1 -1
- package/dist/docs/assets/{reference_project-layout.md.D3MdHM2z.js → reference_project-layout.md.CueaKpjr.js} +5 -20
- package/dist/docs/assets/reference_project-layout.md.CueaKpjr.lean.js +1 -0
- package/dist/docs/assets/{reference_tools.md.DTg_kEsx.js → reference_tools.md.XmeFP_3d.js} +23 -2
- package/dist/docs/assets/{reference_tools.md.DTg_kEsx.lean.js → reference_tools.md.XmeFP_3d.lean.js} +1 -1
- package/dist/docs/assets/{scaffolding-agents.md.CiGsJ1aw.js → scaffolding-agents.md.BpMFXv2J.js} +1 -1
- package/dist/docs/building-with-agents.html +3 -3
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +3 -3
- package/dist/docs/evals.html +3 -3
- package/dist/docs/example-agents/approval-buddy.html +3 -3
- package/dist/docs/example-agents/benny.html +3 -3
- package/dist/docs/example-agents/bugbot.html +3 -3
- package/dist/docs/example-agents/codebase-wiki.html +3 -3
- package/dist/docs/example-agents/codeowners-review.html +3 -3
- package/dist/docs/example-agents/concierge.html +3 -3
- package/dist/docs/example-agents/fsd.html +3 -3
- package/dist/docs/example-agents/index.html +3 -3
- package/dist/docs/example-agents/knowledge-base.html +3 -3
- package/dist/docs/example-agents/oncall.html +3 -3
- package/dist/docs/example-agents/security-reviewer.html +3 -3
- package/dist/docs/example-agents/slack-agent.html +3 -3
- package/dist/docs/example-agents/weather-agent.html +3 -3
- package/dist/docs/guides/agent-to-agent.html +3 -3
- package/dist/docs/guides/cloud-runtime.html +3 -3
- package/dist/docs/guides/convert-automation.html +3 -3
- package/dist/docs/guides/github.html +3 -3
- package/dist/docs/guides/human-in-the-loop.html +3 -3
- package/dist/docs/guides/mcp-oauth.html +3 -3
- package/dist/docs/guides/opentelemetry.html +3 -3
- package/dist/docs/guides/slack.html +3 -3
- package/dist/docs/guides/webhooks.html +3 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +3 -3
- package/dist/docs/index.html +3 -3
- package/dist/docs/quickstart.html +3 -3
- package/dist/docs/reference/agent-config.html +3 -3
- package/dist/docs/reference/artifacts.html +3 -3
- package/dist/docs/reference/channels.html +3 -3
- package/dist/docs/reference/cli.html +3 -3
- package/dist/docs/reference/connections.html +3 -3
- package/dist/docs/reference/hooks.html +3 -3
- package/dist/docs/reference/http-api.html +3 -3
- package/dist/docs/reference/instructions.html +3 -3
- package/dist/docs/reference/playground.html +3 -3
- package/dist/docs/reference/project-layout.html +8 -23
- package/dist/docs/reference/prompt.html +3 -3
- package/dist/docs/reference/schedules.html +3 -3
- package/dist/docs/reference/sessions.html +3 -3
- package/dist/docs/reference/skills.html +3 -3
- package/dist/docs/reference/subagents.html +3 -3
- package/dist/docs/reference/tools.html +27 -6
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/storage.html +3 -3
- package/dist/docs/templates/agentic-owners.html +3 -3
- package/dist/docs/templates/demo.html +3 -3
- package/dist/docs/templates/pr-autofixer.html +3 -3
- package/dist/docs/templates/security-reviewer.html +3 -3
- package/dist/docs/templates/triage.html +3 -3
- package/dist/docs/troubleshooting.html +3 -3
- package/dist/evals.d.ts +1 -1
- package/dist/evals.js +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/internal/advertise-tools.d.ts.map +1 -1
- package/dist/internal/advertise-tools.js +1 -1
- package/dist/internal/cli-ax.js +1 -1
- package/dist/internal/cli-convert-automation.d.ts +1 -1
- package/dist/internal/cli-convert-automation.js +1 -1
- package/dist/internal/cli-cursor.d.ts +12 -4
- package/dist/internal/cli-cursor.d.ts.map +1 -1
- package/dist/internal/cli-cursor.js +11 -4
- package/dist/internal/cli-deploy.d.ts +3 -2
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +84 -9
- package/dist/internal/convert-automation/convert-workflow.d.ts +1 -1
- package/dist/internal/convert-automation/convert-workflow.js +9 -9
- package/dist/internal/convert-automation/types.d.ts +1 -1
- package/dist/internal/convert-automation/types.js +1 -1
- package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
- package/dist/internal/cursor/account-mcp.js +8 -4
- package/dist/internal/cursor/backend-client.d.ts +17 -1
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +42 -7
- package/dist/internal/cursor/credentials.d.ts +35 -9
- package/dist/internal/cursor/credentials.d.ts.map +1 -1
- package/dist/internal/cursor/credentials.js +92 -39
- package/dist/internal/deploy-client.d.ts +42 -1
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +70 -2
- package/dist/internal/discovery.js +1 -1
- package/dist/internal/distribution.d.ts +18 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +19 -0
- package/dist/internal/eval-runner.js +1 -1
- package/dist/internal/grokbot/runner.d.ts +5 -2
- package/dist/internal/grokbot/runner.d.ts.map +1 -1
- package/dist/internal/grokbot/runner.js +10 -6
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +8 -1
- package/dist/internal/mcp-endpoint.js +2 -1
- package/dist/internal/sdk-runner.d.ts +5 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +10 -5
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +80 -36
- package/dist/internal/session-engine.d.ts +9 -2
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +85 -28
- package/dist/internal/tool-policy.d.ts +33 -1
- package/dist/internal/tool-policy.d.ts.map +1 -1
- package/dist/internal/tool-policy.js +53 -0
- package/dist/playground/assets/index-BpVS-paP.css +1 -0
- package/dist/playground/assets/{index-Bqn91tW4.js → index-DxapiDj_.js} +45 -45
- package/dist/playground/index.html +2 -2
- package/dist/reminders.d.ts +1 -1
- package/dist/reminders.js +1 -1
- package/dist/schedules.d.ts +1 -1
- package/dist/schedules.js +1 -1
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +1 -1
- package/dist/types.d.ts +24 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/docs/concepts.md +2 -1
- package/docs/reference/project-layout.md +5 -20
- package/docs/reference/tools.md +53 -3
- package/docs/scaffolding-agents.md +2 -0
- package/package.json +2 -1
- package/skills/debug/SKILL.md +1 -2
- package/skills/framework-map/SKILL.md +1 -2
- package/src/ab.ts +1 -1
- package/src/artifacts.ts +1 -1
- package/src/bin/agent-serve.ts +21 -7
- package/src/channels.ts +1 -1
- package/src/connections.ts +1 -1
- package/src/evals.ts +1 -1
- package/src/hooks.ts +1 -1
- package/src/index.ts +2 -2
- package/src/internal/advertise-tools.ts +1 -0
- package/src/internal/cli-ax.ts +1 -1
- package/src/internal/cli-convert-automation.ts +1 -1
- package/src/internal/cli-cursor.ts +18 -5
- package/src/internal/cli-deploy.ts +123 -15
- package/src/internal/convert-automation/convert-workflow.ts +9 -9
- package/src/internal/convert-automation/types.ts +1 -1
- package/src/internal/cursor/account-mcp.ts +15 -1
- package/src/internal/cursor/backend-client.ts +62 -4
- package/src/internal/cursor/credentials.ts +87 -24
- package/src/internal/deploy-client.ts +122 -2
- package/src/internal/discovery.ts +1 -1
- package/src/internal/distribution.ts +31 -0
- package/src/internal/eval-runner.ts +1 -1
- package/src/internal/grokbot/runner.ts +15 -6
- package/src/internal/init-project.ts +11 -1
- package/src/internal/mcp-endpoint.ts +2 -1
- package/src/internal/sdk-runner.ts +10 -4
- package/src/internal/server.ts +95 -33
- package/src/internal/session-engine.ts +86 -6
- package/src/internal/tool-policy.ts +80 -1
- package/src/reminders.ts +1 -1
- package/src/schedules.ts +1 -1
- package/src/skills.ts +1 -1
- package/src/storage.ts +1 -1
- package/src/tools.ts +1 -1
- package/src/types.ts +21 -2
- package/dist/docs/assets/chunks/@localSearchIndexroot.CxCtxfDE.js +0 -1
- package/dist/docs/assets/reference_project-layout.md.D3MdHM2z.lean.js +0 -1
- package/dist/playground/assets/index-C0_5hOsf.css +0 -1
- /package/dist/docs/assets/{concepts.md.BXAm6G-C.lean.js → concepts.md.2NfkGjqM.lean.js} +0 -0
- /package/dist/docs/assets/{scaffolding-agents.md.CiGsJ1aw.lean.js → scaffolding-agents.md.BpMFXv2J.lean.js} +0 -0
package/src/bin/agent-serve.ts
CHANGED
|
@@ -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 (
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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 "@
|
|
12
|
+
* import { defineChannel, POST } from "@cursor/july/channels";
|
|
13
13
|
* import { z } from "zod";
|
|
14
14
|
*
|
|
15
15
|
* export default defineChannel({
|
package/src/connections.ts
CHANGED
|
@@ -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 "@
|
|
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 "@
|
|
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
package/src/index.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @
|
|
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 "@
|
|
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}`);
|
package/src/internal/cli-ax.ts
CHANGED
|
@@ -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
|
-
?
|
|
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
|
|
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
|
-
*
|
|
153
|
-
*
|
|
154
|
-
*
|
|
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
|
|
9
|
-
* `deploy-client.ts`, poll status, and
|
|
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
|
|
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<
|
|
1524
|
-
|
|
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:
|
|
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
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
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 →
|
|
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
|
|
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
|
|
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;
|
|
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;
|
|
1046
|
-
: "The Slack trigger only fired for authenticated Cursor users (linked accounts on the owning team);
|
|
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 —
|
|
1312
|
+
"Verify: microsoft_teams post — agentsdk has no Teams channel; wire the Microsoft Teams API yourself.",
|
|
1313
1313
|
readMicrosoftTeams:
|
|
1314
|
-
"Verify: read_microsoft_teams —
|
|
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(", ")}) —
|
|
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 →
|
|
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 {
|
|
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);
|