@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
|
@@ -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
|
|
@@ -119,7 +119,7 @@ function renderInstructions(automation, workflow, exportedAt, warnings) {
|
|
|
119
119
|
return `${header}\n\n${heading}${sanitizePromptText((_b = prompt.prompt) !== null && _b !== void 0 ? _b : "", warnings)}\n`;
|
|
120
120
|
}
|
|
121
121
|
/**
|
|
122
|
-
* Strip Cursor-backend prompt markup that means nothing in
|
|
122
|
+
* Strip Cursor-backend prompt markup that means nothing in agentsdk:
|
|
123
123
|
* `@[label](action:...)` action tokens become their label text, and
|
|
124
124
|
* unresolvable `%%INLINECODE<n>%%` storage placeholders are flagged (their
|
|
125
125
|
* content is not in the export).
|
|
@@ -662,7 +662,7 @@ function emitSlackChannel(automation, triggers, slugs, out) {
|
|
|
662
662
|
const kind = trigger.slackChannelCreated !== undefined
|
|
663
663
|
? "channel-created"
|
|
664
664
|
: "reaction-added";
|
|
665
|
-
out.warnings.push(`Slack ${kind} trigger has no
|
|
665
|
+
out.warnings.push(`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.`);
|
|
666
666
|
}
|
|
667
667
|
let reactionDropped = false;
|
|
668
668
|
for (const watch of watches) {
|
|
@@ -679,7 +679,7 @@ function emitSlackChannel(automation, triggers, slugs, out) {
|
|
|
679
679
|
}
|
|
680
680
|
}
|
|
681
681
|
if (reactionDropped) {
|
|
682
|
-
out.warnings.push("The Slack trigger marked triggering messages with a completion reaction;
|
|
682
|
+
out.warnings.push("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.");
|
|
683
683
|
}
|
|
684
684
|
if (socketMode) {
|
|
685
685
|
out.setupSteps.push(`Slack channel-watch / reaction / channel-created triggers need a dedicated Socket Mode Slack app (not the Cursor connection): run \`${CLI_COMMAND_NAME} slack create --channel-posts\`, then finish in the dashboard wizard.`);
|
|
@@ -708,8 +708,8 @@ function emitSlackChannel(automation, triggers, slugs, out) {
|
|
|
708
708
|
.blockUnauthenticatedSlackUsers !== true);
|
|
709
709
|
if (blocksUnauthenticated) {
|
|
710
710
|
out.warnings.push(includeBotPosts
|
|
711
|
-
? "Some Slack watches only fired for authenticated Cursor users while others allowed anyone;
|
|
712
|
-
: "The Slack trigger only fired for authenticated Cursor users (linked accounts on the owning team);
|
|
711
|
+
? "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."
|
|
712
|
+
: "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.");
|
|
713
713
|
}
|
|
714
714
|
const engagement = [];
|
|
715
715
|
if (allow.length > 0) {
|
|
@@ -912,8 +912,8 @@ const ACTION_STEPS = {
|
|
|
912
912
|
requestReviewers: "Verify: request_reviewers — no built-in equivalent; request reviewers via ctx.github in a github channel hook.",
|
|
913
913
|
approvePr: 'Verify: approve_pr — PR approval needs githubChannel "pr-write" plus explicit approval guidance in agent/instructions.md.',
|
|
914
914
|
resolveReviewThreads: "Verify: resolve_review_threads — no built-in equivalent; resolve threads via the GitHub GraphQL API in a hook or tool.",
|
|
915
|
-
microsoftTeams: "Verify: microsoft_teams post —
|
|
916
|
-
readMicrosoftTeams: "Verify: read_microsoft_teams —
|
|
915
|
+
microsoftTeams: "Verify: microsoft_teams post — agentsdk has no Teams channel; wire the Microsoft Teams API yourself.",
|
|
916
|
+
readMicrosoftTeams: "Verify: read_microsoft_teams — agentsdk has no Teams tools; wire the Microsoft Teams API yourself.",
|
|
917
917
|
};
|
|
918
918
|
function slackActionStep(action, { hasSlackChannel, hasSlackConnection }) {
|
|
919
919
|
const channels = dedupe(slackChannelList(action));
|
|
@@ -957,7 +957,7 @@ function behaviorSteps(workflow, warnings, slack) {
|
|
|
957
957
|
}
|
|
958
958
|
const disabled = (_c = workflow.disabledDefaultTools) !== null && _c !== void 0 ? _c : [];
|
|
959
959
|
if (disabled.length > 0) {
|
|
960
|
-
steps.push(`Verify: disabled_default_tools (${disabled.join(", ")}) —
|
|
960
|
+
steps.push(`Verify: disabled_default_tools (${disabled.join(", ")}) — agentsdk has no default automation tools; enforce the equivalent restriction in agent/instructions.md.`);
|
|
961
961
|
}
|
|
962
962
|
return steps;
|
|
963
963
|
}
|
|
@@ -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,
|
|
@@ -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,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"account-mcp.d.ts","sourceRoot":"","sources":["../../../src/internal/cursor/account-mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"account-mcp.d.ts","sourceRoot":"","sources":["../../../src/internal/cursor/account-mcp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EAEX,MAAM,gBAAgB,CAAC;AAUxB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EACV,gBAAgB,EAChB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AAU7B,0EAA0E;AAC1E,eAAO,MAAM,gCAAgC,8CACA,CAAC;AAC9C,2EAA2E;AAC3E,eAAO,MAAM,oCAAoC,yDACO,CAAC;AAMzD,MAAM,WAAW,0BAA0B;IACzC,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC,GACrD,GAAG,CAAC,MAAM,EAAE,0BAA0B,EAAE,CAAC,CAoB3C;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE;IACpD,IAAI,EAAE,0BAA0B,EAAE,CAAC;IACnC,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,wBAAwB,EAAE,CAkB7B;AAqCD,qBAAa,sBAAsB;IACjC,yEAAyE;IACzE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAmC;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkB;IAC1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAa;IAC1C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAU;IAC7C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAE5D,YAAY,IAAI,EAAE;QAChB,MAAM,EAAE,mBAAmB,CAAC;QAC5B,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,2EAA2E;QAC3E,OAAO,CAAC,EAAE,eAAe,CAAC;QAC1B;;;;WAIG;QACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;KAC9B,EAMA;IAED;;;;OAIG;IACH,UAAU,IAAI,UAAU,CAgBvB;IAED;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,0BAA0B,GAAG,OAAO,CAAC,QAAQ,CAAC,CAO3E;IAED;;;;;;;;OAQG;IACH,YAAY,CAAC,IAAI,EAAE,0BAA0B,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAI9D;YAEa,YAAY;IAiE1B,OAAO,CAAC,WAAW;IAmFnB,0EAA0E;YAC5D,QAAQ;IAatB;;;;OAIG;IACH,OAAO,CAAC,UAAU;CAwCnB;AA6ED,MAAM,WAAW,6BAA6B;IAC5C,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA+CD;;;GAGG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,EAAE;IACrD,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,SAAS,6BAA6B,EAAE,CAAC;IAClD,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,GAAG,MAAM,CAWT;AAwDD,yFAAyF;AACzF,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,gBAAgB,EACxB,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAkBR;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAE,uBAAuB,CAAC,EAC1D,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA4B7B"}
|
|
@@ -201,9 +201,11 @@ export class CursorAccountMcpBridge {
|
|
|
201
201
|
server.setRequestHandler(ListToolsRequestSchema, () => __awaiter(this, void 0, void 0, function* () {
|
|
202
202
|
const catalog = yield this.getCatalog(ref);
|
|
203
203
|
return {
|
|
204
|
-
tools: catalog.tools.map((tool) => (Object.assign({ name: tool.exposedName, description: tool.description, inputSchema: tool.inputSchema }, (tool.outputSchema === undefined
|
|
204
|
+
tools: catalog.tools.map((tool) => (Object.assign(Object.assign({ name: tool.exposedName, description: tool.description, inputSchema: tool.inputSchema }, (tool.outputSchema === undefined
|
|
205
205
|
? {}
|
|
206
|
-
: { outputSchema: tool.outputSchema }))
|
|
206
|
+
: { outputSchema: tool.outputSchema })), (tool.annotations === undefined
|
|
207
|
+
? {}
|
|
208
|
+
: { annotations: tool.annotations })))),
|
|
207
209
|
};
|
|
208
210
|
}));
|
|
209
211
|
server.setRequestHandler(CallToolRequestSchema, (request) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -347,9 +349,11 @@ function buildCatalog(servers) {
|
|
|
347
349
|
suffixIndex++;
|
|
348
350
|
exposedName = suffixMcpToolName(base, suffixIndex);
|
|
349
351
|
}
|
|
350
|
-
const entry = Object.assign({ exposedName, backendName: tool.name, serverIdentifier, description: tool.description, inputSchema: tool.inputSchema }, (tool.outputSchema === undefined
|
|
352
|
+
const entry = Object.assign(Object.assign({ exposedName, backendName: tool.name, serverIdentifier, description: tool.description, inputSchema: tool.inputSchema }, (tool.outputSchema === undefined
|
|
353
|
+
? {}
|
|
354
|
+
: { outputSchema: tool.outputSchema })), (tool.annotations === undefined
|
|
351
355
|
? {}
|
|
352
|
-
: {
|
|
356
|
+
: { annotations: tool.annotations }));
|
|
353
357
|
tools.push(entry);
|
|
354
358
|
byExposedName.set(entry.exposedName, entry);
|
|
355
359
|
});
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* cached until shortly before expiry and re-exchanged once on a 401.
|
|
14
14
|
*/
|
|
15
15
|
import { z } from "zod";
|
|
16
|
+
import type { McpToolAnnotations } from "../../types.js";
|
|
16
17
|
export declare class CursorBackendError extends Error {
|
|
17
18
|
readonly status?: number | undefined;
|
|
18
19
|
readonly retryAfterMs?: number | undefined;
|
|
@@ -57,6 +58,13 @@ export interface AccountMcpTool {
|
|
|
57
58
|
* matching the optional MCP `Tool.outputSchema` field.
|
|
58
59
|
*/
|
|
59
60
|
outputSchema?: Record<string, unknown>;
|
|
61
|
+
/**
|
|
62
|
+
* MCP spec tool annotations as the connector's server reported them,
|
|
63
|
+
* bounded to the spec fields at parse time. Absent stays absent —
|
|
64
|
+
* untrusted hints, and the fail-closed signal for consumers that classify
|
|
65
|
+
* on them (dry-run effect resolution).
|
|
66
|
+
*/
|
|
67
|
+
annotations?: McpToolAnnotations;
|
|
60
68
|
}
|
|
61
69
|
export interface AccountMcpServer {
|
|
62
70
|
serverIdentifier: string;
|
|
@@ -79,18 +87,26 @@ export interface AccountMcpCallResult {
|
|
|
79
87
|
export interface CursorBackendClientOptions {
|
|
80
88
|
backendUrl: string;
|
|
81
89
|
apiKey: string;
|
|
90
|
+
/**
|
|
91
|
+
* Re-read the key on each authenticated call. Hosted freeze listens
|
|
92
|
+
* unsigned and the binder drops the key after restore; a constructor-frozen
|
|
93
|
+
* key would miss that bind.
|
|
94
|
+
*/
|
|
95
|
+
getApiKey?: () => string;
|
|
82
96
|
logger?: (line: string) => void;
|
|
83
97
|
/** Test seam; defaults to global fetch. */
|
|
84
98
|
fetchImpl?: typeof fetch;
|
|
85
99
|
}
|
|
86
100
|
export declare class CursorBackendClient {
|
|
87
101
|
private readonly backendUrl;
|
|
88
|
-
private readonly
|
|
102
|
+
private readonly resolveApiKey;
|
|
89
103
|
private readonly logger;
|
|
90
104
|
private readonly fetchImpl;
|
|
91
105
|
private token;
|
|
92
106
|
private tokenExchange;
|
|
107
|
+
private lastExchangedApiKey;
|
|
93
108
|
constructor(options: CursorBackendClientOptions);
|
|
109
|
+
private currentApiKey;
|
|
94
110
|
/** Who this API key acts as. */
|
|
95
111
|
getMe(): Promise<CursorIdentity>;
|
|
96
112
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"backend-client.d.ts","sourceRoot":"","sources":["../../../src/internal/cursor/backend-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"backend-client.d.ts","sourceRoot":"","sources":["../../../src/internal/cursor/backend-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
23
23
|
};
|
|
24
24
|
import { randomUUID } from "node:crypto";
|
|
25
25
|
import { z } from "zod";
|
|
26
|
+
import { boundedToolAnnotations } from "../mcp-host.js";
|
|
26
27
|
const CLIENT_VERSION = "agent-serve-0.1.0";
|
|
27
28
|
const EXCHANGE_PATH = "/auth/exchange_user_api_key";
|
|
28
29
|
const SERVICE_PREFIX = "/aiserver.v1.DashboardService";
|
|
@@ -68,6 +69,8 @@ const mcpToolSchema = z.object({
|
|
|
68
69
|
inputSchema: z.unknown().optional(),
|
|
69
70
|
/** Flat JSON-string output schema (`output_schema_json` on the proto). */
|
|
70
71
|
outputSchemaJson: z.string().optional(),
|
|
72
|
+
/** Flat JSON-string MCP annotations (`annotations_json` on the proto). */
|
|
73
|
+
annotationsJson: z.string().optional(),
|
|
71
74
|
});
|
|
72
75
|
const getAvailableMcpServersResponseSchema = z.object({
|
|
73
76
|
servers: z
|
|
@@ -178,13 +181,16 @@ function parseRpcResponse(method, response) {
|
|
|
178
181
|
}
|
|
179
182
|
export class CursorBackendClient {
|
|
180
183
|
constructor(options) {
|
|
181
|
-
var _a, _b;
|
|
184
|
+
var _a, _b, _c;
|
|
182
185
|
this.backendUrl = options.backendUrl.endsWith("/")
|
|
183
186
|
? options.backendUrl.slice(0, -1)
|
|
184
187
|
: options.backendUrl;
|
|
185
|
-
this.
|
|
186
|
-
this.logger = (
|
|
187
|
-
this.fetchImpl = (
|
|
188
|
+
this.resolveApiKey = (_a = options.getApiKey) !== null && _a !== void 0 ? _a : (() => options.apiKey);
|
|
189
|
+
this.logger = (_b = options.logger) !== null && _b !== void 0 ? _b : (() => { });
|
|
190
|
+
this.fetchImpl = (_c = options.fetchImpl) !== null && _c !== void 0 ? _c : fetch;
|
|
191
|
+
}
|
|
192
|
+
currentApiKey() {
|
|
193
|
+
return this.resolveApiKey().trim();
|
|
188
194
|
}
|
|
189
195
|
/** Who this API key acts as. */
|
|
190
196
|
getMe() {
|
|
@@ -208,7 +214,8 @@ export class CursorBackendClient {
|
|
|
208
214
|
tools: ((_a = server.tools) !== null && _a !== void 0 ? _a : []).map((tool) => {
|
|
209
215
|
var _a;
|
|
210
216
|
const outputSchema = parseOutputSchemaJson(tool.outputSchemaJson);
|
|
211
|
-
|
|
217
|
+
const annotations = parseAnnotationsJson(tool.annotationsJson);
|
|
218
|
+
return Object.assign(Object.assign({ name: tool.name, description: (_a = tool.description) !== null && _a !== void 0 ? _a : "", inputSchema: normalizeInputSchema(tool.inputSchema) }, (outputSchema === undefined ? {} : { outputSchema })), (annotations === undefined ? {} : { annotations }));
|
|
212
219
|
}),
|
|
213
220
|
}); });
|
|
214
221
|
});
|
|
@@ -287,7 +294,7 @@ export class CursorBackendClient {
|
|
|
287
294
|
method: "POST",
|
|
288
295
|
headers: {
|
|
289
296
|
"content-type": "application/json",
|
|
290
|
-
authorization: `Bearer ${this.
|
|
297
|
+
authorization: `Bearer ${this.currentApiKey()}`,
|
|
291
298
|
},
|
|
292
299
|
body: JSON.stringify({ repos: [...repos], permissions }),
|
|
293
300
|
signal: AbortSignal.timeout(30000),
|
|
@@ -358,6 +365,14 @@ export class CursorBackendClient {
|
|
|
358
365
|
* when none is cached or it is near expiry.
|
|
359
366
|
*/
|
|
360
367
|
getAccessToken() {
|
|
368
|
+
const apiKey = this.currentApiKey();
|
|
369
|
+
if (apiKey === "") {
|
|
370
|
+
return Promise.reject(new CursorBackendError("The Cursor backend client has no API key yet. Bind CURSOR_API_KEY or CURSOR_API_KEY_FILE before authenticated calls."));
|
|
371
|
+
}
|
|
372
|
+
if (this.lastExchangedApiKey !== apiKey) {
|
|
373
|
+
this.token = undefined;
|
|
374
|
+
this.tokenExchange = undefined;
|
|
375
|
+
}
|
|
361
376
|
if (this.token !== undefined &&
|
|
362
377
|
Date.now() < this.token.expiresAtMs - TOKEN_EXPIRY_LEEWAY_MS) {
|
|
363
378
|
return Promise.resolve(this.token.value);
|
|
@@ -372,13 +387,14 @@ export class CursorBackendClient {
|
|
|
372
387
|
}
|
|
373
388
|
exchangeApiKey() {
|
|
374
389
|
return __awaiter(this, void 0, void 0, function* () {
|
|
390
|
+
const apiKey = this.currentApiKey();
|
|
375
391
|
let response;
|
|
376
392
|
try {
|
|
377
393
|
response = yield this.fetchImpl(`${this.backendUrl}${EXCHANGE_PATH}`, {
|
|
378
394
|
method: "POST",
|
|
379
395
|
headers: {
|
|
380
396
|
"content-type": "application/json",
|
|
381
|
-
authorization: `Bearer ${
|
|
397
|
+
authorization: `Bearer ${apiKey}`,
|
|
382
398
|
},
|
|
383
399
|
body: "{}",
|
|
384
400
|
signal: AbortSignal.timeout(30000),
|
|
@@ -401,6 +417,7 @@ export class CursorBackendClient {
|
|
|
401
417
|
value: body.data.accessToken,
|
|
402
418
|
expiresAtMs: jwtExpiryMs(body.data.accessToken),
|
|
403
419
|
};
|
|
420
|
+
this.lastExchangedApiKey = apiKey;
|
|
404
421
|
this.logger("[agent-sdk] cursor account: minted a fresh access token");
|
|
405
422
|
return body.data.accessToken;
|
|
406
423
|
});
|
|
@@ -521,6 +538,24 @@ function parseOutputSchemaJson(outputSchemaJson) {
|
|
|
521
538
|
? parsed
|
|
522
539
|
: undefined;
|
|
523
540
|
}
|
|
541
|
+
/**
|
|
542
|
+
* Parse the flat JSON-string annotations off the wire and bound them to the
|
|
543
|
+
* MCP-spec fields. Malformed or non-object payloads behave like absent ones,
|
|
544
|
+
* so readers fail closed.
|
|
545
|
+
*/
|
|
546
|
+
function parseAnnotationsJson(annotationsJson) {
|
|
547
|
+
if (annotationsJson === undefined) {
|
|
548
|
+
return undefined;
|
|
549
|
+
}
|
|
550
|
+
let parsed;
|
|
551
|
+
try {
|
|
552
|
+
parsed = JSON.parse(annotationsJson);
|
|
553
|
+
}
|
|
554
|
+
catch (_a) {
|
|
555
|
+
return undefined;
|
|
556
|
+
}
|
|
557
|
+
return boundedToolAnnotations(parsed);
|
|
558
|
+
}
|
|
524
559
|
function toCallResult(result) {
|
|
525
560
|
var _a;
|
|
526
561
|
if (result.success !== undefined) {
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
* dashboard-revocable user API key — only the key is stored.
|
|
10
10
|
* - `CURSOR_API_KEY` (or `serve({ apiKey })`) wins over the stored key, so
|
|
11
11
|
* CI and hosted deployments stay env-driven.
|
|
12
|
+
* - `CURSOR_API_KEY_FILE` (or the hosted default path) is next: freeze bind
|
|
13
|
+
* drops the key at task time without restarting July.
|
|
14
|
+
* - Stored `july login` is last. Same order for hosted and self-hosted:
|
|
15
|
+
* option → env → file → login.
|
|
12
16
|
*
|
|
13
17
|
* There is deliberately no session-token storage, refresh-token rotation, or
|
|
14
18
|
* cross-tool credential sharing here: short-lived access tokens are minted
|
|
@@ -27,10 +31,11 @@ export declare const DEFAULT_CURSOR_EXTERNAL_API_URL = "https://api.cursor.com";
|
|
|
27
31
|
export declare function cursorBackendUrl(): string;
|
|
28
32
|
/**
|
|
29
33
|
* External API base URL for routes served only by the external-api
|
|
30
|
-
* microlith (`/internal/agent-serve/*`, engine aliases).
|
|
31
|
-
* these are mounted on api.cursor.com and 404 on
|
|
32
|
-
* deploy surface needs its own default.
|
|
33
|
-
* overrides everything for local dev, where
|
|
34
|
+
* microlith (`/internal/agent-serve/*`, `/v0/grokbot/*`, engine aliases).
|
|
35
|
+
* In production these are mounted on api.cursor.com and 404 on
|
|
36
|
+
* api2.cursor.sh, so the deploy surface needs its own default.
|
|
37
|
+
* `CURSOR_API_BASE_URL` still overrides everything for local dev, where
|
|
38
|
+
* one server mounts all routes.
|
|
34
39
|
*/
|
|
35
40
|
export declare function cursorExternalApiUrl(): string;
|
|
36
41
|
/** Website base URL for the login deep link (`CURSOR_WEBSITE_URL` override). */
|
|
@@ -48,20 +53,41 @@ export type StoredCredentials = z.infer<typeof storedCredentialsSchema>;
|
|
|
48
53
|
export declare function configDirPath(): string;
|
|
49
54
|
/** `<configDir>/credentials.json` (0600). */
|
|
50
55
|
export declare function credentialsFilePath(): string;
|
|
56
|
+
export declare function readStoredCredentialsSync(): StoredCredentials | undefined;
|
|
51
57
|
export declare function readStoredCredentials(): Promise<StoredCredentials | undefined>;
|
|
52
58
|
export declare function writeStoredCredentials(credentials: StoredCredentials): Promise<void>;
|
|
53
59
|
export declare function clearStoredCredentials(): Promise<boolean>;
|
|
54
|
-
export type ApiKeySource = "option" | "env" | "login";
|
|
60
|
+
export type ApiKeySource = "option" | "env" | "file" | "login";
|
|
55
61
|
export interface ResolvedApiKey {
|
|
56
62
|
apiKey: string;
|
|
57
63
|
source: ApiKeySource;
|
|
58
64
|
backendUrl: string;
|
|
59
65
|
}
|
|
60
66
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
67
|
+
* Hosted task-bind path. Not a secret: the snapshot may name this path.
|
|
68
|
+
* The binder writes the key here after restore; July re-reads on each use.
|
|
69
|
+
* Override with `CURSOR_API_KEY_FILE`. A missing file is unsigned — self-hosted
|
|
70
|
+
* then uses `CURSOR_API_KEY` or stored login.
|
|
71
|
+
*/
|
|
72
|
+
export declare const DEFAULT_CURSOR_API_KEY_FILE: string;
|
|
73
|
+
/**
|
|
74
|
+
* Read `CURSOR_API_KEY_FILE` (or {@link DEFAULT_CURSOR_API_KEY_FILE} when
|
|
75
|
+
* unset). Missing/empty files are unsigned, not an error — freeze bake
|
|
76
|
+
* listens before the binder drops the key; self-hosted falls through to
|
|
77
|
+
* env or login.
|
|
78
|
+
*/
|
|
79
|
+
export declare function readApiKeyFromFile(filePath?: string): string | undefined;
|
|
80
|
+
/**
|
|
81
|
+
* First present source wins. We define the order; operators do not.
|
|
82
|
+
* `--api-key` / `serve({ apiKey })` → `CURSOR_API_KEY` → `CURSOR_API_KEY_FILE`
|
|
83
|
+
* (hosted default path if unset) → stored `july login`.
|
|
84
|
+
*/
|
|
85
|
+
export declare function resolveApiKeySync(options?: {
|
|
86
|
+
apiKey?: string;
|
|
87
|
+
backendUrl?: string;
|
|
88
|
+
}): ResolvedApiKey | undefined;
|
|
89
|
+
/**
|
|
90
|
+
* {@link resolveApiKeySync} as a Promise for call sites that already await.
|
|
65
91
|
*/
|
|
66
92
|
export declare function resolveApiKey(options?: {
|
|
67
93
|
apiKey?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../../src/internal/cursor/credentials.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../../src/internal/cursor/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
* dashboard-revocable user API key — only the key is stored.
|
|
10
10
|
* - `CURSOR_API_KEY` (or `serve({ apiKey })`) wins over the stored key, so
|
|
11
11
|
* CI and hosted deployments stay env-driven.
|
|
12
|
+
* - `CURSOR_API_KEY_FILE` (or the hosted default path) is next: freeze bind
|
|
13
|
+
* drops the key at task time without restarting July.
|
|
14
|
+
* - Stored `july login` is last. Same order for hosted and self-hosted:
|
|
15
|
+
* option → env → file → login.
|
|
12
16
|
*
|
|
13
17
|
* There is deliberately no session-token storage, refresh-token rotation, or
|
|
14
18
|
* cross-tool credential sharing here: short-lived access tokens are minted
|
|
@@ -24,6 +28,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
24
28
|
});
|
|
25
29
|
};
|
|
26
30
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
31
|
+
import { readFileSync } from "node:fs";
|
|
27
32
|
import { chmod, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
28
33
|
import { homedir } from "node:os";
|
|
29
34
|
import { dirname, join } from "node:path";
|
|
@@ -45,10 +50,11 @@ export function cursorBackendUrl() {
|
|
|
45
50
|
}
|
|
46
51
|
/**
|
|
47
52
|
* External API base URL for routes served only by the external-api
|
|
48
|
-
* microlith (`/internal/agent-serve/*`, engine aliases).
|
|
49
|
-
* these are mounted on api.cursor.com and 404 on
|
|
50
|
-
* deploy surface needs its own default.
|
|
51
|
-
* overrides everything for local dev, where
|
|
53
|
+
* microlith (`/internal/agent-serve/*`, `/v0/grokbot/*`, engine aliases).
|
|
54
|
+
* In production these are mounted on api.cursor.com and 404 on
|
|
55
|
+
* api2.cursor.sh, so the deploy surface needs its own default.
|
|
56
|
+
* `CURSOR_API_BASE_URL` still overrides everything for local dev, where
|
|
57
|
+
* one server mounts all routes.
|
|
52
58
|
*/
|
|
53
59
|
export function cursorExternalApiUrl() {
|
|
54
60
|
var _a;
|
|
@@ -83,6 +89,33 @@ export function configDirPath() {
|
|
|
83
89
|
export function credentialsFilePath() {
|
|
84
90
|
return join(configDirPath(), "credentials.json");
|
|
85
91
|
}
|
|
92
|
+
function parseStoredCredentialsJson(raw) {
|
|
93
|
+
let parsed;
|
|
94
|
+
try {
|
|
95
|
+
parsed = JSON.parse(raw);
|
|
96
|
+
}
|
|
97
|
+
catch (_a) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
const credentials = storedCredentialsSchema.safeParse(parsed);
|
|
101
|
+
if (!credentials.success) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
backendUrl: trimTrailingSlash(credentials.data.backendUrl),
|
|
106
|
+
apiKey: credentials.data.apiKey,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export function readStoredCredentialsSync() {
|
|
110
|
+
let raw;
|
|
111
|
+
try {
|
|
112
|
+
raw = readFileSync(credentialsFilePath(), "utf8");
|
|
113
|
+
}
|
|
114
|
+
catch (_a) {
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
return parseStoredCredentialsJson(raw);
|
|
118
|
+
}
|
|
86
119
|
export function readStoredCredentials() {
|
|
87
120
|
return __awaiter(this, void 0, void 0, function* () {
|
|
88
121
|
let raw;
|
|
@@ -92,22 +125,7 @@ export function readStoredCredentials() {
|
|
|
92
125
|
catch (_a) {
|
|
93
126
|
return undefined;
|
|
94
127
|
}
|
|
95
|
-
|
|
96
|
-
try {
|
|
97
|
-
parsed = JSON.parse(raw);
|
|
98
|
-
}
|
|
99
|
-
catch (_b) {
|
|
100
|
-
// Corrupt file — treat as signed out; login rewrites it.
|
|
101
|
-
return undefined;
|
|
102
|
-
}
|
|
103
|
-
const credentials = storedCredentialsSchema.safeParse(parsed);
|
|
104
|
-
if (!credentials.success) {
|
|
105
|
-
return undefined;
|
|
106
|
-
}
|
|
107
|
-
return {
|
|
108
|
-
backendUrl: trimTrailingSlash(credentials.data.backendUrl),
|
|
109
|
-
apiKey: credentials.data.apiKey,
|
|
110
|
-
};
|
|
128
|
+
return parseStoredCredentialsJson(raw);
|
|
111
129
|
});
|
|
112
130
|
}
|
|
113
131
|
export function writeStoredCredentials(credentials) {
|
|
@@ -133,31 +151,66 @@ export function clearStoredCredentials() {
|
|
|
133
151
|
});
|
|
134
152
|
}
|
|
135
153
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
154
|
+
* Hosted task-bind path. Not a secret: the snapshot may name this path.
|
|
155
|
+
* The binder writes the key here after restore; July re-reads on each use.
|
|
156
|
+
* Override with `CURSOR_API_KEY_FILE`. A missing file is unsigned — self-hosted
|
|
157
|
+
* then uses `CURSOR_API_KEY` or stored login.
|
|
158
|
+
*/
|
|
159
|
+
export const DEFAULT_CURSOR_API_KEY_FILE = "/run/cursor/secrets/CURSOR_API_KEY";
|
|
160
|
+
/**
|
|
161
|
+
* Read `CURSOR_API_KEY_FILE` (or {@link DEFAULT_CURSOR_API_KEY_FILE} when
|
|
162
|
+
* unset). Missing/empty files are unsigned, not an error — freeze bake
|
|
163
|
+
* listens before the binder drops the key; self-hosted falls through to
|
|
164
|
+
* env or login.
|
|
165
|
+
*/
|
|
166
|
+
export function readApiKeyFromFile(filePath) {
|
|
167
|
+
const configured = filePath !== null && filePath !== void 0 ? filePath : process.env.CURSOR_API_KEY_FILE;
|
|
168
|
+
const path = configured !== undefined && configured.trim() !== ""
|
|
169
|
+
? configured.trim()
|
|
170
|
+
: DEFAULT_CURSOR_API_KEY_FILE;
|
|
171
|
+
try {
|
|
172
|
+
const raw = readFileSync(path, "utf8").trim();
|
|
173
|
+
return raw === "" ? undefined : raw;
|
|
174
|
+
}
|
|
175
|
+
catch (_a) {
|
|
176
|
+
return undefined;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* First present source wins. We define the order; operators do not.
|
|
181
|
+
* `--api-key` / `serve({ apiKey })` → `CURSOR_API_KEY` → `CURSOR_API_KEY_FILE`
|
|
182
|
+
* (hosted default path if unset) → stored `july login`.
|
|
183
|
+
*/
|
|
184
|
+
export function resolveApiKeySync(options) {
|
|
185
|
+
var _a;
|
|
186
|
+
const backendUrl = (_a = options === null || options === void 0 ? void 0 : options.backendUrl) !== null && _a !== void 0 ? _a : cursorBackendUrl();
|
|
187
|
+
if ((options === null || options === void 0 ? void 0 : options.apiKey) !== undefined && options.apiKey.trim() !== "") {
|
|
188
|
+
return { apiKey: options.apiKey.trim(), source: "option", backendUrl };
|
|
189
|
+
}
|
|
190
|
+
const envKey = process.env.CURSOR_API_KEY;
|
|
191
|
+
if (envKey !== undefined && envKey.trim() !== "") {
|
|
192
|
+
return { apiKey: envKey.trim(), source: "env", backendUrl };
|
|
193
|
+
}
|
|
194
|
+
const fileKey = readApiKeyFromFile();
|
|
195
|
+
if (fileKey !== undefined) {
|
|
196
|
+
return { apiKey: fileKey, source: "file", backendUrl };
|
|
197
|
+
}
|
|
198
|
+
const stored = readStoredCredentialsSync();
|
|
199
|
+
if (stored !== undefined && stored.backendUrl === backendUrl) {
|
|
200
|
+
return { apiKey: stored.apiKey, source: "login", backendUrl };
|
|
201
|
+
}
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* {@link resolveApiKeySync} as a Promise for call sites that already await.
|
|
140
206
|
*/
|
|
141
207
|
export function resolveApiKey(options) {
|
|
142
208
|
return __awaiter(this, void 0, void 0, function* () {
|
|
143
|
-
|
|
144
|
-
const backendUrl = (_a = options === null || options === void 0 ? void 0 : options.backendUrl) !== null && _a !== void 0 ? _a : cursorBackendUrl();
|
|
145
|
-
if ((options === null || options === void 0 ? void 0 : options.apiKey) !== undefined && options.apiKey.trim() !== "") {
|
|
146
|
-
return { apiKey: options.apiKey.trim(), source: "option", backendUrl };
|
|
147
|
-
}
|
|
148
|
-
const envKey = process.env.CURSOR_API_KEY;
|
|
149
|
-
if (envKey !== undefined && envKey.trim() !== "") {
|
|
150
|
-
return { apiKey: envKey.trim(), source: "env", backendUrl };
|
|
151
|
-
}
|
|
152
|
-
const stored = yield readStoredCredentials();
|
|
153
|
-
if (stored !== undefined && stored.backendUrl === backendUrl) {
|
|
154
|
-
return { apiKey: stored.apiKey, source: "login", backendUrl };
|
|
155
|
-
}
|
|
156
|
-
return undefined;
|
|
209
|
+
return resolveApiKeySync(options);
|
|
157
210
|
});
|
|
158
211
|
}
|
|
159
212
|
/** One-line hint for "no credentials" errors, shared across surfaces. */
|
|
160
|
-
export const SIGN_IN_HINT = `Run \`${CLI_COMMAND_NAME} login\` (or set CURSOR_API_KEY / pass serve({ apiKey })).`;
|
|
213
|
+
export const SIGN_IN_HINT = `Run \`${CLI_COMMAND_NAME} login\` (or set CURSOR_API_KEY / CURSOR_API_KEY_FILE / pass serve({ apiKey })).`;
|
|
161
214
|
// ============================================================================
|
|
162
215
|
// PKCE browser login (mirrors cursor-agent / Sand)
|
|
163
216
|
// ============================================================================
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Thin client for the Agent Serve deployment management API
|
|
3
|
-
* (`/internal/agent-serve/deployments` on the Cursor backend)
|
|
3
|
+
* (`/internal/agent-serve/deployments` on the Cursor backend) and the v2
|
|
4
|
+
* AgentSDK accept path (`/internal/agentkit/deployments`). Pure
|
|
4
5
|
* request/response + error mapping — no console I/O, no polling loops;
|
|
5
6
|
* rendering lives in `cli-deploy.ts`.
|
|
6
7
|
*
|
|
@@ -131,6 +132,29 @@ export interface StopAccepted {
|
|
|
131
132
|
status: string;
|
|
132
133
|
}
|
|
133
134
|
export type DeleteAccepted = StopAccepted;
|
|
135
|
+
/**
|
|
136
|
+
* `POST /internal/agentkit/deployments` 202 body. Distinct from v1
|
|
137
|
+
* {@link DeployAccepted}: the v2 control plane returns catalog ids, not
|
|
138
|
+
* an engine alias or one-shot alias token.
|
|
139
|
+
*/
|
|
140
|
+
export interface AgentkitDeployAccepted {
|
|
141
|
+
applicationId: string;
|
|
142
|
+
releaseId: string;
|
|
143
|
+
status: string;
|
|
144
|
+
}
|
|
145
|
+
/** Customer-visible v2 deploy status (`GET /internal/agentkit/deployments/:slug`). */
|
|
146
|
+
export type AgentkitCustomerStatus = "pending" | "deploying" | "running" | "failed" | "stopped";
|
|
147
|
+
export type AgentkitDeployProgress = "queued" | "creating" | "building" | "starting" | "finalizing" | "running" | "failed" | "stopped";
|
|
148
|
+
export interface AgentkitDeployStatus {
|
|
149
|
+
applicationId: string;
|
|
150
|
+
releaseId: string;
|
|
151
|
+
slug: string;
|
|
152
|
+
teamId: number;
|
|
153
|
+
status: AgentkitCustomerStatus;
|
|
154
|
+
progress: AgentkitDeployProgress;
|
|
155
|
+
statusMessage: string | null;
|
|
156
|
+
}
|
|
157
|
+
export declare const TERMINAL_AGENTKIT_DEPLOY_STATUSES: ReadonlySet<AgentkitCustomerStatus>;
|
|
134
158
|
/** One secret's metadata from the list endpoint — names only, never values. */
|
|
135
159
|
export interface SecretInfo {
|
|
136
160
|
name: string;
|
|
@@ -176,6 +200,23 @@ export declare class AgentServeDeployClient {
|
|
|
176
200
|
source: DeploySource;
|
|
177
201
|
template?: string;
|
|
178
202
|
}): Promise<DeployAccepted>;
|
|
203
|
+
/**
|
|
204
|
+
* Create or redeploy onto the v2 control plane
|
|
205
|
+
* (`POST /internal/agentkit/deployments`). 202 means accepted; poll
|
|
206
|
+
* {@link getAgentkitDeploy} until a terminal status.
|
|
207
|
+
*/
|
|
208
|
+
deployAgentkit(args: {
|
|
209
|
+
teamId: number;
|
|
210
|
+
slug: string;
|
|
211
|
+
gitRepoUrl: string;
|
|
212
|
+
gitRef?: string;
|
|
213
|
+
agentPath?: string;
|
|
214
|
+
repositories?: string[];
|
|
215
|
+
}): Promise<AgentkitDeployAccepted>;
|
|
216
|
+
getAgentkitDeploy(args: {
|
|
217
|
+
teamId: number;
|
|
218
|
+
slug: string;
|
|
219
|
+
}): Promise<AgentkitDeployStatus>;
|
|
179
220
|
listDeployments(args: {
|
|
180
221
|
teamId: number;
|
|
181
222
|
}): Promise<Deployment[]>;
|