@cursor/july 0.1.94 → 0.1.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +14 -2
- package/dist/channels/github/types.d.ts +18 -3
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.d.ts.map +1 -1
- package/dist/channels/origin/origin-channel.js +11 -3
- package/dist/channels/origin/origin-webhook.d.ts +11 -1
- package/dist/channels/origin/origin-webhook.d.ts.map +1 -1
- package/dist/channels/origin/origin-webhook.js +23 -3
- package/dist/channels/origin/types.d.ts +8 -0
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/pr-ref.d.ts +7 -1
- package/dist/channels/slack/pr-ref.d.ts.map +1 -1
- package/dist/channels/slack/pr-ref.js +42 -23
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.CFDEas4I.js → app.BBj0klBO.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.oqPawjiD.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.B1IIYpYS.js → VPLocalSearchBox.CUEXpL78.js} +1 -1
- package/dist/docs/assets/chunks/{theme.Ct4NSiLm.js → theme.DabmQnia.js} +2 -2
- package/dist/docs/assets/index.md.BoHaMdeZ.js +5 -0
- package/dist/docs/assets/{index.md.DRakGHFe.lean.js → index.md.BoHaMdeZ.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.js → reference_cli.md.BsMOxDvh.js} +3 -2
- package/dist/docs/assets/{reference_cli.md.Cw6_ICYG.lean.js → reference_cli.md.BsMOxDvh.lean.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.8son6Hjm.js → reference_skills.md.BFW9retM.js} +3 -3
- package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.js → templates_agentic-owners.md.BZSH4N9z.js} +1 -1
- package/dist/docs/assets/{templates_demo.md.DhFcWN6j.js → templates_demo.md.BeQX9V3H.js} +1 -1
- package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.js → templates_pr-autofixer.md.x5zl6-GT.js} +2 -2
- package/dist/docs/assets/{templates_pr-autofixer.md.DU7dQpor.lean.js → templates_pr-autofixer.md.x5zl6-GT.lean.js} +1 -1
- package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.js +4 -0
- package/dist/docs/assets/templates_security-help.md.C3Ny_Qr2.lean.js +1 -0
- package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.js → templates_security-reviewer.md.lshxbCLK.js} +2 -2
- package/dist/docs/assets/{templates_security-reviewer.md.CTa7u_l1.lean.js → templates_security-reviewer.md.lshxbCLK.lean.js} +1 -1
- package/dist/docs/assets/{templates_triage.md.CVlpctKS.js → templates_triage.md.Co4UNzkZ.js} +3 -3
- package/dist/docs/assets/{templates_triage.md.CVlpctKS.lean.js → templates_triage.md.Co4UNzkZ.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +4 -4
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +4 -4
- package/dist/docs/guides/convert-automation.html +4 -4
- package/dist/docs/guides/github.html +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +4 -4
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +4 -4
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +3 -1
- package/dist/docs/llms-full.txt +90 -26
- package/dist/docs/llms.txt +1 -0
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +7 -6
- package/dist/docs/reference/cli.md +3 -1
- package/dist/docs/reference/connections.html +4 -4
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +4 -4
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/prompt.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +7 -7
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +7 -7
- package/dist/docs/templates/agentic-owners.md +1 -1
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/demo.md +3 -2
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/pr-autofixer.md +7 -13
- package/dist/docs/templates/security-help.html +30 -0
- package/dist/docs/templates/security-help.md +65 -0
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/security-reviewer.md +1 -2
- package/dist/docs/templates/triage.html +7 -7
- package/dist/docs/templates/triage.md +2 -6
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/files-backends/cursor-hosted.d.ts +6 -2
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +2 -2
- package/dist/files.d.ts +2 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +5 -0
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +135 -6
- package/dist/internal/conversation-mirror.d.ts +82 -0
- package/dist/internal/conversation-mirror.d.ts.map +1 -0
- package/dist/internal/conversation-mirror.js +251 -0
- package/dist/internal/deferred-channel-session.d.ts +20 -0
- package/dist/internal/deferred-channel-session.d.ts.map +1 -0
- package/dist/internal/deferred-channel-session.js +62 -0
- package/dist/internal/deploy-client.d.ts +13 -1
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +11 -1
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +11 -5
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +22 -2
- package/dist/internal/framework-storage-selection.d.ts +32 -16
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +51 -17
- package/dist/internal/hosted-admission-context.d.ts +20 -0
- package/dist/internal/hosted-admission-context.d.ts.map +1 -0
- package/dist/internal/hosted-admission-context.js +31 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +5 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +33 -1
- package/dist/internal/hosted-delivery.d.ts +4 -2
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +75 -35
- package/dist/internal/hosted-managed-automation.d.ts +30 -0
- package/dist/internal/hosted-managed-automation.d.ts.map +1 -0
- package/dist/internal/hosted-managed-automation.js +58 -0
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +10 -98
- package/dist/internal/scm/pr-url.d.ts +14 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -0
- package/dist/internal/scm/pr-url.js +65 -0
- package/dist/internal/sdk-runner.d.ts +14 -0
- package/dist/internal/sdk-runner.d.ts.map +1 -1
- package/dist/internal/sdk-runner.js +41 -2
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +10 -2
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +9 -0
- package/dist/playground/assets/index-CF7hUDnQ.css +1 -0
- package/dist/playground/assets/{index-B3JCyigB.js → index-CZA1uEWA.js} +48 -48
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted.d.ts +7 -2
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +2 -2
- package/docs/README.md +3 -1
- package/docs/reference/cli.md +3 -1
- package/docs/templates/agentic-owners.md +1 -1
- package/docs/templates/demo.md +3 -2
- package/docs/templates/pr-autofixer.md +7 -13
- package/docs/templates/security-help.md +70 -0
- package/docs/templates/security-reviewer.md +1 -2
- package/docs/templates/triage.md +2 -6
- package/package.json +1 -1
- package/src/channels/github/github-channel.ts +23 -8
- package/src/channels/github/types.ts +19 -2
- package/src/channels/origin/origin-channel.ts +13 -1
- package/src/channels/origin/origin-webhook.ts +27 -3
- package/src/channels/origin/types.ts +8 -0
- package/src/channels/slack/pr-ref.ts +56 -25
- package/src/files-backends/cursor-hosted.ts +9 -3
- package/src/files.ts +11 -0
- package/src/internal/cli-deploy.ts +171 -7
- package/src/internal/conversation-mirror.ts +330 -0
- package/src/internal/deferred-channel-session.ts +61 -0
- package/src/internal/deploy-client.ts +24 -1
- package/src/internal/deploy-manifest.ts +10 -5
- package/src/internal/discovery.ts +25 -2
- package/src/internal/framework-storage-selection.ts +61 -19
- package/src/internal/hosted-admission-context.ts +37 -0
- package/src/internal/hosted-delivery-protocol.ts +44 -1
- package/src/internal/hosted-delivery.ts +95 -40
- package/src/internal/hosted-managed-automation.ts +72 -0
- package/src/internal/review-comments.ts +10 -113
- package/src/internal/scm/pr-url.ts +95 -0
- package/src/internal/sdk-runner.ts +57 -2
- package/src/internal/server.ts +10 -0
- package/src/internal/session-engine.ts +12 -0
- package/src/storage-backends/cursor-hosted.ts +10 -3
- package/templates/agentic-owners/README.md +1 -1
- package/templates/agentic-owners/agent/agent.ts +0 -10
- package/templates/agentic-owners/agent/channels/github.ts +5 -14
- package/templates/agentic-owners/agent/lib/config.ts +0 -8
- package/templates/agentic-owners/agent/lib/review.ts +2 -15
- package/templates/agentic-owners/agent/tools/record_review.ts +2 -4
- package/templates/demo/agent/agent.ts +0 -10
- package/templates/pr-autofixer/README.md +0 -2
- package/templates/pr-autofixer/agent/agent.ts +0 -11
- package/templates/pr-autofixer/agent/channels/slack.ts +0 -7
- package/templates/pr-autofixer/agent/lib/pr-state.ts +5 -17
- package/templates/pr-autofixer/agent/lib/repos.ts +0 -1
- package/templates/security-help/README.md +2 -2
- package/templates/security-help/agent/agent.ts +1 -2
- package/templates/security-help/agent/channels/slack.ts +0 -3
- package/templates/security-help/agent/instructions.md +9 -10
- package/templates/security-help/agent/skills/access-request.md +1 -1
- package/templates/security-help/agent/skills/faq.md +31 -0
- package/templates/security-help/agent/skills/security-playbooks.md +1 -1
- package/templates/security-help/package.json +1 -2
- package/templates/security-reviewer/agent/agent.ts +0 -10
- package/templates/triage/agent/agent.ts +0 -10
- package/templates/triage/agent/channels/queue.ts +1 -1
- package/templates/triage/agent/channels/webhook.ts +1 -3
- package/dist/docs/assets/chunks/@localSearchIndexroot.DU3U2Ij2.js +0 -1
- package/dist/docs/assets/index.md.DRakGHFe.js +0 -5
- package/dist/playground/assets/index-D9N7-q97.css +0 -1
- package/templates/security-help/agent/knowledge/faq/approvals.md +0 -5
- package/templates/security-help/agent/knowledge/faq/channels.md +0 -6
- package/templates/security-help/agent/knowledge/faq/phishing.md +0 -10
- package/templates/security-help/agent/skills/security-first-pass.md +0 -15
- /package/dist/docs/assets/{reference_skills.md.8son6Hjm.lean.js → reference_skills.md.BFW9retM.lean.js} +0 -0
- /package/dist/docs/assets/{templates_agentic-owners.md.DqtPdm6f.lean.js → templates_agentic-owners.md.BZSH4N9z.lean.js} +0 -0
- /package/dist/docs/assets/{templates_demo.md.DhFcWN6j.lean.js → templates_demo.md.BeQX9V3H.lean.js} +0 -0
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
/>
|
|
9
9
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
10
10
|
<title>agent-serve playground</title>
|
|
11
|
-
<script type="module" crossorigin src="./assets/index-
|
|
12
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
11
|
+
<script type="module" crossorigin src="./assets/index-CZA1uEWA.js"></script>
|
|
12
|
+
<link rel="stylesheet" crossorigin href="./assets/index-CF7hUDnQ.css">
|
|
13
13
|
</head>
|
|
14
14
|
<body>
|
|
15
15
|
<div id="root"></div>
|
|
@@ -47,8 +47,13 @@ export interface CursorHostedStorageOptions {
|
|
|
47
47
|
* `https://api.cursor.com`).
|
|
48
48
|
*/
|
|
49
49
|
baseUrl?: string;
|
|
50
|
-
/**
|
|
51
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Bearer credential (default: `CURSOR_API_KEY`). A function is
|
|
52
|
+
* re-resolved on every call: hosted freeze snapshots listen unsigned and
|
|
53
|
+
* bind the key file after serve start, so a value captured at construct
|
|
54
|
+
* time would be permanently absent.
|
|
55
|
+
*/
|
|
56
|
+
apiKey?: string | (() => string | undefined);
|
|
52
57
|
/** Injected for tests. */
|
|
53
58
|
fetch?: typeof fetch;
|
|
54
59
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-hosted.d.ts","sourceRoot":"","sources":["../../src/storage-backends/cursor-hosted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,aAAa,EAEb,iBAAiB,EAClB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAiC,MAAM,aAAa,CAAC;AAW5E;;;GAGG;AACH,eAAO,MAAM,+CAA+C,EAC1D,cAAuB,CAAC;AAE1B;;;GAGG;AACH,eAAO,MAAM,iCAAiC,EAC5C,2BAAoC,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,SAAS;IACpD,OAAO,+CAA+C;IACtD,OAAO,iCAAiC;CAIzC,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB
|
|
1
|
+
{"version":3,"file":"cursor-hosted.d.ts","sourceRoot":"","sources":["../../src/storage-backends/cursor-hosted.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,aAAa,EAEb,iBAAiB,EAClB,MAAM,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,SAAS,EAAiC,MAAM,aAAa,CAAC;AAW5E;;;GAGG;AACH,eAAO,MAAM,+CAA+C,EAC1D,cAAuB,CAAC;AAE1B;;;GAGG;AACH,eAAO,MAAM,iCAAiC,EAC5C,2BAAoC,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,8BAA8B,EAAE,SAAS;IACpD,OAAO,+CAA+C;IACtD,OAAO,iCAAiC;CAIzC,CAAC;AAEF,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,0BAA0B;IAC1B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,OAAO,MAE1C,CAAC;AAEF,4EAA4E;AAC5E,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAM7D;AAED,KAAK,0BAA0B,GAAG,QAAQ,CACxC,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC,CACvD,GAAG;IACF,QAAQ,CAAC,CAAC,qBAAqB,CAAC,EAAE,IAAI,CAAC;IACvC,GAAG,EAAE,eAAe,CAAC;IACrB,KAAK,EAAE,iBAAiB,CAAC;IACzB,GAAG,EAAE,cAAc,CAAC;CACrB,CAAC;AA4BF,6EAA6E;AAC7E,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,mEAAmE;AACnE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,OAAO,CAAC;IACZ,2CAA2C;IAC3C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,iEAAiE;IACjE,OAAO,EAAE;QAAE,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC9D;AAED,2CAA2C;AAC3C,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAmFD;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,OAAO,GAAE,0BAA+B,GACvC,0BAA0B,CA2I5B"}
|
|
@@ -87,8 +87,8 @@ function toCasResult(response) {
|
|
|
87
87
|
}
|
|
88
88
|
function resolveApiKey(options) {
|
|
89
89
|
var _a;
|
|
90
|
-
|
|
91
|
-
const key = (_a = (
|
|
90
|
+
const configured = typeof options.apiKey === "function" ? options.apiKey() : options.apiKey;
|
|
91
|
+
const key = (_a = (configured !== null && configured !== void 0 ? configured : process.env.CURSOR_API_KEY)) === null || _a === void 0 ? void 0 : _a.trim();
|
|
92
92
|
if (key === undefined || key === "") {
|
|
93
93
|
throw new Error("cursorHostedStorage requires CURSOR_API_KEY (deployment pod credential on Cursor hosting)");
|
|
94
94
|
}
|
package/docs/README.md
CHANGED
|
@@ -35,7 +35,7 @@ npx @cursor/july docs
|
|
|
35
35
|
| Building a new agent with Cursor | [Scaffold an agent with Cursor](./scaffolding-agents.md) |
|
|
36
36
|
| Turning a Cursor Automation into a project | [Convert a Cursor Automation](./guides/convert-automation.md) |
|
|
37
37
|
| Wiring an agent to Slack | [Slack guide](./guides/slack.md) |
|
|
38
|
-
| Starting from a packaged template | [Demo](./templates/demo.md), [Security reviewer](./templates/security-reviewer.md), [Triage](./templates/triage.md), or [Agentic Owners](./templates/agentic-owners.md) |
|
|
38
|
+
| Starting from a packaged template | [Demo](./templates/demo.md), [Security reviewer](./templates/security-reviewer.md), [Security help](./templates/security-help.md), [Triage](./templates/triage.md), or [Agentic Owners](./templates/agentic-owners.md) |
|
|
39
39
|
| Wiring an agent to GitHub webhooks | [GitHub guide](./guides/github.md) |
|
|
40
40
|
| Driving PRs from a cloud VM | [PR autofixer template](./templates/pr-autofixer.md) |
|
|
41
41
|
| Driving an agent from Linear (or another tracker) | [Webhooks guide: Linear example](./guides/webhooks.md#example-linear-as-the-control-plane) |
|
|
@@ -63,6 +63,8 @@ npx @cursor/july docs
|
|
|
63
63
|
collects the PR, the model records, then comments.
|
|
64
64
|
- [Security reviewer](./templates/security-reviewer.md): review pull
|
|
65
65
|
requests for exploitable bugs and post one comment.
|
|
66
|
+
- [Answer security questions in Slack](./templates/security-help.md):
|
|
67
|
+
answer from your skills, or take a first look at a pasted PR.
|
|
66
68
|
- [Triage Linear or Jira issues in place](./templates/triage.md): classify
|
|
67
69
|
existing tickets and comment on them.
|
|
68
70
|
- [Review pull requests with owners policies](./templates/agentic-owners.md):
|
package/docs/reference/cli.md
CHANGED
|
@@ -415,6 +415,7 @@ non-zero when the reconstructed trajectory failed.
|
|
|
415
415
|
agent-sdk init ./my-agent # scaffold package.json, tsconfig.json, agent/ + a demo tool
|
|
416
416
|
agent-sdk init ./my-demo --template demo # record a PR walkthrough
|
|
417
417
|
agent-sdk init ./my-reviewer --template security-reviewer # review PRs for security bugs
|
|
418
|
+
agent-sdk init ./security-help --template security-help # answer security questions in Slack
|
|
418
419
|
agent-sdk init ./my-triage --template triage-linear # comment on Linear issues
|
|
419
420
|
agent-sdk init ./my-triage --template triage-jira # comment on Jira issues
|
|
420
421
|
agent-sdk init ./my-owners --template agentic-owners # review PRs via owners policies
|
|
@@ -430,7 +431,8 @@ agent-sdk init # no directory: print the setup guide
|
|
|
430
431
|
`@cursor/july` resolves for `dev` and `run`.
|
|
431
432
|
|
|
432
433
|
Templates may ship `init.json`. On a TTY, `init` asks those questions
|
|
433
|
-
before writing files. `pr-autofixer`
|
|
434
|
+
before writing files. `pr-autofixer` and `security-help` ask for GitHub
|
|
435
|
+
repos. Repeat
|
|
434
436
|
`--var id=value` to answer without a prompt.
|
|
435
437
|
`--json` and non-TTY hosts skip the interview unless `--var` is set.
|
|
436
438
|
|
|
@@ -49,7 +49,7 @@ low risk approve, medium and above hold with a comment. Route reviews by
|
|
|
49
49
|
committing policies:
|
|
50
50
|
|
|
51
51
|
```yaml
|
|
52
|
-
# .agentic-owners/policy.yml
|
|
52
|
+
# .agentic-owners/policy.yml. Anywhere in the repo; closest wins.
|
|
53
53
|
# paths are repo-root-relative globs, wherever the policy file lives.
|
|
54
54
|
version: 1
|
|
55
55
|
policies:
|
package/docs/templates/demo.md
CHANGED
|
@@ -44,13 +44,14 @@ curl -X POST http://127.0.0.1:3000/demo-agent/v1/channels/queue/pr \
|
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
The host fetches title, body, and files, writes `pr.md` and `files.md`,
|
|
47
|
-
and starts the turn. Retries
|
|
47
|
+
and starts the turn. Retries for the same PR coalesce.
|
|
48
48
|
|
|
49
49
|
GitHub label `demo` or comment `/demo` when you terminate webhooks
|
|
50
50
|
yourself: self-host and set `GITHUB_WEBHOOK_SECRET`. Hosted Cursor
|
|
51
51
|
aliases require `X-Agent-Alias-Token`, which GitHub cannot send.
|
|
52
52
|
|
|
53
|
-
`record_demo` comments on that
|
|
53
|
+
`record_demo` comments on that pull request. Eval sessions skip the
|
|
54
|
+
comment.
|
|
54
55
|
|
|
55
56
|
## First walkthrough
|
|
56
57
|
|
|
@@ -83,17 +83,11 @@ with `git push origin HEAD:<headRef>`. Workflow actions run through
|
|
|
83
83
|
|
|
84
84
|
## GitHub wakes
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
not. The channel buffers about 3 seconds per PR. Payload details are
|
|
92
|
-
dropped on purpose. The follow-up says something changed.
|
|
93
|
-
|
|
94
|
-
Pending wakes and the PR-to-cloud-agent map persist in `host.kv` so
|
|
95
|
-
they survive restart. `cursorHostedStorage` keeps both across replace.
|
|
96
|
-
Without that plug-in, `host.kv` is local-only.
|
|
86
|
+
Cursor relays pull request, comment, review, check, and failing status
|
|
87
|
+
events for the repos you listed. A wake only starts or resumes a cloud
|
|
88
|
+
conversation after that PR has been driven. `pull_request.opened` is
|
|
89
|
+
ignored. A PR comment or review on an opted-in PR wakes the agent. A
|
|
90
|
+
comment on a plain GitHub issue does not.
|
|
97
91
|
|
|
98
92
|
Closing a PR cancels its merge-conflict reminder and drops buffered
|
|
99
93
|
wakes.
|
|
@@ -105,8 +99,8 @@ fixture replay.
|
|
|
105
99
|
|
|
106
100
|
`agent/channels/slack.ts` is a dedicated Socket Mode bot
|
|
107
101
|
(`PR_AUTOFIXER_SLACK_*`). Mint it with `agent-sdk slack create`, then
|
|
108
|
-
mention the bot or DM it with a PR URL.
|
|
109
|
-
|
|
102
|
+
mention the bot or DM it with a PR URL. Same `drive_pr` path as the
|
|
103
|
+
playground. See [Slack](../guides/slack.md).
|
|
110
104
|
|
|
111
105
|
## Evals
|
|
112
106
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Answer security questions in Slack"
|
|
3
|
+
description: "Scaffold the agent, connect Slack, and answer from your skills. Paste a GitHub pull request for a first look."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Answer security questions in Slack
|
|
7
|
+
|
|
8
|
+
This agent answers security questions in Slack from files you edit.
|
|
9
|
+
Paste a GitHub pull request URL for a first look. Access grants,
|
|
10
|
+
incident close-out, and GitHub writes stay with a person.
|
|
11
|
+
|
|
12
|
+
## Scaffold
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npx @cursor/july init ./security-help --template security-help
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`init` asks which GitHub repos it may read. Every repo must share one
|
|
19
|
+
owner. Pass `--var repos=acme/api,acme/web` to skip the prompt.
|
|
20
|
+
|
|
21
|
+
The list lands in `agent/lib/repos.ts`. Slack uses it when someone
|
|
22
|
+
pastes a PR URL.
|
|
23
|
+
|
|
24
|
+
## Connect Slack and GitHub
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
cd security-help
|
|
28
|
+
agent-sdk login
|
|
29
|
+
agent-sdk slack create --name "Security Help" --channel-posts
|
|
30
|
+
agent-sdk dev
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`--channel-posts` is required to watch channels. Mentions and DMs work
|
|
34
|
+
without it. Connect GitHub in Cursor for the watched repos. Slack
|
|
35
|
+
starts the session. See [Slack](../guides/slack.md) and
|
|
36
|
+
[GitHub](../guides/github.md).
|
|
37
|
+
|
|
38
|
+
## First answer
|
|
39
|
+
|
|
40
|
+
Mention the bot or DM it. Edit `agent/skills/faq.md` before you rely
|
|
41
|
+
on the answers; the shipped file is a placeholder.
|
|
42
|
+
|
|
43
|
+
Paste a watched PR URL for a first look. A repo outside the list is
|
|
44
|
+
refused.
|
|
45
|
+
|
|
46
|
+
## What to edit
|
|
47
|
+
|
|
48
|
+
- `agent/lib/repos.ts`: repos it may read
|
|
49
|
+
- `agent/channels/slack.ts`: channel ids to watch (`watch`)
|
|
50
|
+
- `agent/skills/faq.md`: answers for your company
|
|
51
|
+
- `agent/skills/`: how to look at a PR, a leak, or an access ask
|
|
52
|
+
- `agent/instructions.md`: routing
|
|
53
|
+
|
|
54
|
+
## Evals
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
agent-sdk eval
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Three smoke cases: phishing, SaaS access, and a seeded PR look. Eval
|
|
61
|
+
sessions skip Slack and GitHub writes.
|
|
62
|
+
|
|
63
|
+
## Deploy
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
agent-sdk deploy
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Run it from the agent's git checkout. Set Slack tokens on the
|
|
70
|
+
deployment after `slack create`. See [Deployment](../deployment.md).
|
|
@@ -9,8 +9,7 @@ This agent reads a pull request diff and posts one review comment. It
|
|
|
9
9
|
reports exploitable bugs: injection, authz bypass, secret leaks, SSRF,
|
|
10
10
|
RCE. Style nits stay out.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
parallel workers. This template is one model turn.
|
|
12
|
+
This template is one model turn: read the diff, then post one comment.
|
|
14
13
|
|
|
15
14
|
## Scaffold
|
|
16
15
|
|
package/docs/templates/triage.md
CHANGED
|
@@ -51,8 +51,7 @@ agent-sdk dev
|
|
|
51
51
|
|
|
52
52
|
Open the playground. Run `/queue/issue` and paste an existing issue.
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
also POST:
|
|
54
|
+
You can also POST:
|
|
56
55
|
|
|
57
56
|
```bash
|
|
58
57
|
curl -X POST http://127.0.0.1:3000/triage-agent/v1/channels/queue/issue \
|
|
@@ -64,14 +63,11 @@ curl -X POST http://127.0.0.1:3000/triage-agent/v1/channels/queue/issue \
|
|
|
64
63
|
}'
|
|
65
64
|
```
|
|
66
65
|
|
|
67
|
-
`POST /v1/channels/queue/issue` accepts
|
|
68
|
-
`{ identifier, title?, description? }` from the playground.
|
|
69
|
-
|
|
70
66
|
For create webhooks, set `LINEAR_WEBHOOK_SECRET` or
|
|
71
67
|
`JIRA_WEBHOOK_SECRET`. Point the provider at the deployed alias under
|
|
72
68
|
`/v1/channels/webhook`. Signed events start or resume triage for that issue.
|
|
73
69
|
|
|
74
|
-
`record_triage` comments on the issue
|
|
70
|
+
`record_triage` comments on the issue that started the session, not
|
|
75
71
|
whatever identifier the model copies out of the ticket body.
|
|
76
72
|
|
|
77
73
|
## Rubric
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cursor/july",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.95",
|
|
4
4
|
"description": "(early alpha) Filesystem-first framework for defining Cursor agents as markdown and TypeScript and serving them over channels with the Cursor SDK.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"repository": {
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
continuationSource,
|
|
12
12
|
normalizeIdentity,
|
|
13
13
|
} from "../../internal/continuation-identity.js";
|
|
14
|
+
import { isDeferredChannelSession } from "../../internal/deferred-channel-session.js";
|
|
14
15
|
import { isDevMode } from "../../internal/dev-mode.js";
|
|
15
16
|
import { bindLocalIngressSend } from "../../internal/local-ingress.js";
|
|
16
17
|
import type {
|
|
@@ -1622,16 +1623,15 @@ async function startTurn(input: {
|
|
|
1622
1623
|
scheduleAfterAck(input.args, async () => {
|
|
1623
1624
|
await sendTurn();
|
|
1624
1625
|
});
|
|
1625
|
-
return
|
|
1626
|
-
Response.json(
|
|
1627
|
-
{ ok: true, dispatched: true, mode: "turn" },
|
|
1628
|
-
{ status: 202 }
|
|
1629
|
-
),
|
|
1630
|
-
"send"
|
|
1631
|
-
);
|
|
1626
|
+
return acknowledgeTurn();
|
|
1632
1627
|
}
|
|
1633
1628
|
|
|
1634
1629
|
const session = await sendTurn();
|
|
1630
|
+
if (isDeferredChannelSession(session)) {
|
|
1631
|
+
// Hosted admission captured the send; the control plane allocates the
|
|
1632
|
+
// session after acknowledgement, so there is nothing to report yet.
|
|
1633
|
+
return acknowledgeTurn();
|
|
1634
|
+
}
|
|
1635
1635
|
return withDispatchOutcome(
|
|
1636
1636
|
Response.json({
|
|
1637
1637
|
ok: true,
|
|
@@ -1677,12 +1677,27 @@ function scheduleAfterAck(
|
|
|
1677
1677
|
);
|
|
1678
1678
|
}
|
|
1679
1679
|
|
|
1680
|
+
/** 202 ack for a turn whose send completes after the response flushes. */
|
|
1681
|
+
function acknowledgeTurn(): Response {
|
|
1682
|
+
return withDispatchOutcome(
|
|
1683
|
+
Response.json(
|
|
1684
|
+
{ ok: true, dispatched: true, mode: "turn" },
|
|
1685
|
+
{ status: 202 }
|
|
1686
|
+
),
|
|
1687
|
+
"send"
|
|
1688
|
+
);
|
|
1689
|
+
}
|
|
1690
|
+
|
|
1680
1691
|
function acknowledgeTask(
|
|
1681
1692
|
args: ChannelHandlerArgs,
|
|
1682
1693
|
dispatch: GitHubTaskDispatch,
|
|
1683
1694
|
extra: Record<string, unknown>
|
|
1684
1695
|
): Response {
|
|
1685
|
-
|
|
1696
|
+
// Hand the task the per-delivery send/waitUntil so hosted admission can
|
|
1697
|
+
// capture task-initiated sends; startup-captured sends bypass capture.
|
|
1698
|
+
scheduleAfterAck(args, () =>
|
|
1699
|
+
dispatch.task({ send: args.send, waitUntil: args.waitUntil })
|
|
1700
|
+
);
|
|
1686
1701
|
return withDispatchOutcome(
|
|
1687
1702
|
Response.json(
|
|
1688
1703
|
{ ok: true, dispatched: true, mode: "task", ...extra },
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
ChannelEventHandlers,
|
|
8
8
|
ChannelStartArgs,
|
|
9
9
|
HostContext,
|
|
10
|
+
SendMessageFn,
|
|
10
11
|
SendMessageOptions,
|
|
11
12
|
} from "../../types.js";
|
|
12
13
|
import type { GitHubApiOptions } from "./api.js";
|
|
@@ -370,13 +371,29 @@ export interface GitHubTurnDispatch {
|
|
|
370
371
|
| Promise<GitHubWorkspaceFiles | undefined>);
|
|
371
372
|
}
|
|
372
373
|
|
|
374
|
+
/** Bound per-delivery helpers passed to a {@link GitHubTaskDispatch.task}. */
|
|
375
|
+
export interface GitHubTaskArgs {
|
|
376
|
+
/**
|
|
377
|
+
* Start (or resume) a session for this delivery. Locally this runs a real
|
|
378
|
+
* turn and returns the live session. In hosted admission it captures the
|
|
379
|
+
* send for the control plane to execute after `ses_…` is allocated and
|
|
380
|
+
* returns an inert deferred handle, so the task body keeps running.
|
|
381
|
+
* Always use this over a send captured at `onStart` — a startup-captured
|
|
382
|
+
* send bypasses hosted capture and is rejected during hosted admission.
|
|
383
|
+
*/
|
|
384
|
+
send: SendMessageFn;
|
|
385
|
+
/** Extend the delivery's background window past the task promise. */
|
|
386
|
+
waitUntil: (promise: Promise<unknown>) => void;
|
|
387
|
+
}
|
|
388
|
+
|
|
373
389
|
/**
|
|
374
390
|
* Run a host-side handler for the event instead of a model turn. The task
|
|
375
391
|
* runs in the background (`waitUntil`) after the webhook is acknowledged
|
|
376
|
-
* with a 202, so it can outlive GitHub's ~10s delivery timeout.
|
|
392
|
+
* with a 202, so it can outlive GitHub's ~10s delivery timeout. The callback
|
|
393
|
+
* receives {@link GitHubTaskArgs}; zero-argument tasks remain valid.
|
|
377
394
|
*/
|
|
378
395
|
export interface GitHubTaskDispatch {
|
|
379
|
-
task: () => void | Promise<void>;
|
|
396
|
+
task: (args: GitHubTaskArgs) => void | Promise<void>;
|
|
380
397
|
}
|
|
381
398
|
|
|
382
399
|
export type GitHubDispatchResult =
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
import { deriveOriginWebhookEvents, ORIGIN_CHANNEL_KIND } from "./events.js";
|
|
27
27
|
import {
|
|
28
28
|
DEFAULT_ORIGIN_API_BASE_URL,
|
|
29
|
+
OriginJwksUnavailableError,
|
|
29
30
|
type OriginWebhookHeaders,
|
|
30
31
|
verifyOriginWebhook,
|
|
31
32
|
} from "./origin-webhook.js";
|
|
@@ -300,10 +301,12 @@ export function parseOriginPullRequestEvent(input: {
|
|
|
300
301
|
ctx: {
|
|
301
302
|
deliveryId: input.envelope.deliveryId,
|
|
302
303
|
eventType,
|
|
304
|
+
eventTime: input.envelope.event.eventTime,
|
|
303
305
|
installationId: input.envelope.installationId,
|
|
304
306
|
repository,
|
|
305
307
|
pullRequestNumber: number,
|
|
306
308
|
pullRequestUrl: url,
|
|
309
|
+
payload,
|
|
307
310
|
sender: originSender(input.envelope, payload),
|
|
308
311
|
},
|
|
309
312
|
pullRequest: {
|
|
@@ -687,7 +690,16 @@ export async function handleOriginWebhookRequest(input: {
|
|
|
687
690
|
await verifyOriginWebhook(bodyText, originHeaders(input.request), {
|
|
688
691
|
apiBaseUrl: resolveApiBaseUrl(input.options),
|
|
689
692
|
});
|
|
690
|
-
} catch {
|
|
693
|
+
} catch (error) {
|
|
694
|
+
// A JWKS outage means the delivery was never checked: answer 503 so
|
|
695
|
+
// Origin's delivery worker retries. Only a real signature mismatch
|
|
696
|
+
// is the terminal 401.
|
|
697
|
+
if (error instanceof OriginJwksUnavailableError) {
|
|
698
|
+
return Response.json(
|
|
699
|
+
{ ok: false, error: "signature_verification_unavailable" },
|
|
700
|
+
{ status: 503 }
|
|
701
|
+
);
|
|
702
|
+
}
|
|
691
703
|
return Response.json(
|
|
692
704
|
{ ok: false, error: "invalid_signature" },
|
|
693
705
|
{ status: 401 }
|
|
@@ -247,7 +247,31 @@ export interface VerifyOriginWebhookOptions {
|
|
|
247
247
|
}
|
|
248
248
|
|
|
249
249
|
/**
|
|
250
|
-
*
|
|
250
|
+
* The signing JWKS could not be fetched (and no cached copy applies), so
|
|
251
|
+
* the delivery was never actually checked. Callers must answer retryably
|
|
252
|
+
* (5xx) — a 401 would make Origin's delivery worker drop the wake as
|
|
253
|
+
* terminal on what is only a transient outage.
|
|
254
|
+
*/
|
|
255
|
+
export class OriginJwksUnavailableError extends Error {}
|
|
256
|
+
|
|
257
|
+
async function fetchJwksOrUnavailable(
|
|
258
|
+
apiBaseUrl: string,
|
|
259
|
+
fetchImpl: typeof fetch,
|
|
260
|
+
options?: FetchOriginJwksOptions
|
|
261
|
+
): Promise<readonly OriginJwk[]> {
|
|
262
|
+
try {
|
|
263
|
+
return await fetchOriginJwks(apiBaseUrl, fetchImpl, options);
|
|
264
|
+
} catch (error) {
|
|
265
|
+
throw new OriginJwksUnavailableError(
|
|
266
|
+
`Origin JWKS unavailable: ${error instanceof Error ? error.message : String(error)}`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Verify a Standard-Webhooks v1ed Origin payload. Throws
|
|
273
|
+
* {@link OriginJwksUnavailableError} when the keys cannot be fetched, and a
|
|
274
|
+
* plain error when the signature does not verify against them.
|
|
251
275
|
*/
|
|
252
276
|
export async function verifyOriginWebhook(
|
|
253
277
|
body: string | Buffer,
|
|
@@ -256,7 +280,7 @@ export async function verifyOriginWebhook(
|
|
|
256
280
|
): Promise<void> {
|
|
257
281
|
const apiBaseUrl = options?.apiBaseUrl ?? DEFAULT_ORIGIN_API_BASE_URL;
|
|
258
282
|
const fetchImpl = options?.fetchImpl ?? fetch;
|
|
259
|
-
const keys = await
|
|
283
|
+
const keys = await fetchJwksOrUnavailable(apiBaseUrl, fetchImpl);
|
|
260
284
|
if (
|
|
261
285
|
verifyV1edWebhookPayload({
|
|
262
286
|
publicJwks: keys,
|
|
@@ -267,7 +291,7 @@ export async function verifyOriginWebhook(
|
|
|
267
291
|
) {
|
|
268
292
|
return;
|
|
269
293
|
}
|
|
270
|
-
const refreshed = await
|
|
294
|
+
const refreshed = await fetchJwksOrUnavailable(apiBaseUrl, fetchImpl, {
|
|
271
295
|
force: true,
|
|
272
296
|
});
|
|
273
297
|
if (
|
|
@@ -51,11 +51,19 @@ export interface OriginReview {
|
|
|
51
51
|
export interface OriginEventContext {
|
|
52
52
|
deliveryId?: string;
|
|
53
53
|
eventType: string;
|
|
54
|
+
/** Delivery envelope `event.eventTime`, when present. */
|
|
55
|
+
eventTime?: string;
|
|
54
56
|
/** Origin app installation id from the delivery envelope, when present. */
|
|
55
57
|
installationId?: string;
|
|
56
58
|
repository: OriginRepositoryRef;
|
|
57
59
|
pullRequestNumber: number;
|
|
58
60
|
pullRequestUrl: string;
|
|
61
|
+
/**
|
|
62
|
+
* Raw parsed `event.payload` record (`{}` when absent), for consumers
|
|
63
|
+
* whose normalization needs more than the typed event — the GitHub
|
|
64
|
+
* channel's hook ctx exposes the same.
|
|
65
|
+
*/
|
|
66
|
+
payload: Record<string, unknown>;
|
|
59
67
|
sender?: OriginActor;
|
|
60
68
|
host: HostContext;
|
|
61
69
|
artifacts: ArtifactsApi;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Best-effort
|
|
2
|
+
* Best-effort PR references from free-form chat (Slack, etc.).
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import { type PrProvider, parsePrUrl } from "../../internal/scm/pr-url.js";
|
|
6
|
+
|
|
5
7
|
export interface GithubPrRef {
|
|
6
8
|
/** Normalized URL `https://github.com/owner/repo/pull/N`. */
|
|
7
9
|
url: string;
|
|
@@ -12,39 +14,68 @@ export interface GithubPrRef {
|
|
|
12
14
|
number: number;
|
|
13
15
|
}
|
|
14
16
|
|
|
17
|
+
export type OriginPrRef = GithubPrRef;
|
|
18
|
+
|
|
19
|
+
const URL_IN_TEXT = /https?:\/\/[^\s>|]+/gi;
|
|
20
|
+
|
|
21
|
+
function githubRef(owner: string, repo: string, number: number): GithubPrRef {
|
|
22
|
+
return {
|
|
23
|
+
owner,
|
|
24
|
+
repo,
|
|
25
|
+
number,
|
|
26
|
+
url: `https://github.com/${owner}/${repo}/pull/${number}`,
|
|
27
|
+
label: `${owner}/${repo}#${number}`,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function firstUrlRef(
|
|
32
|
+
text: string,
|
|
33
|
+
provider: PrProvider
|
|
34
|
+
): GithubPrRef | undefined {
|
|
35
|
+
const matches = text.match(URL_IN_TEXT);
|
|
36
|
+
if (matches === null) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
for (const raw of matches) {
|
|
40
|
+
const parsed = parsePrUrl(raw);
|
|
41
|
+
if (parsed?.provider === provider) {
|
|
42
|
+
return {
|
|
43
|
+
owner: parsed.owner,
|
|
44
|
+
repo: parsed.repo,
|
|
45
|
+
number: parsed.number,
|
|
46
|
+
url: parsed.url,
|
|
47
|
+
label: `${parsed.owner}/${parsed.repo}#${parsed.number}`,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Find the first Origin PR URL in `text`.
|
|
56
|
+
* Does not treat bare `owner/repo#N` as Origin.
|
|
57
|
+
*/
|
|
58
|
+
export function extractOriginPrRef(text: string): OriginPrRef | undefined {
|
|
59
|
+
return firstUrlRef(text, "origin");
|
|
60
|
+
}
|
|
61
|
+
|
|
15
62
|
/**
|
|
16
63
|
* Find the first GitHub PR URL or `owner/repo#N` in `text`.
|
|
17
64
|
* Returns `undefined` when none is present.
|
|
18
65
|
*/
|
|
19
66
|
export function extractGithubPrRef(text: string): GithubPrRef | undefined {
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (urlMatch !== null) {
|
|
24
|
-
const owner = urlMatch[1] as string;
|
|
25
|
-
const repo = urlMatch[2] as string;
|
|
26
|
-
const number = Number(urlMatch[3]);
|
|
27
|
-
return {
|
|
28
|
-
owner,
|
|
29
|
-
repo,
|
|
30
|
-
number,
|
|
31
|
-
url: `https://github.com/${owner}/${repo}/pull/${number}`,
|
|
32
|
-
label: `${owner}/${repo}#${number}`,
|
|
33
|
-
};
|
|
67
|
+
const fromUrl = firstUrlRef(text, "github");
|
|
68
|
+
if (fromUrl !== undefined) {
|
|
69
|
+
return fromUrl;
|
|
34
70
|
}
|
|
35
71
|
|
|
36
72
|
const hashMatch = text.match(/\b([\w.-]+)\/([\w.-]+)#(\d+)\b/);
|
|
37
73
|
if (hashMatch === null) {
|
|
38
74
|
return undefined;
|
|
39
75
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
repo,
|
|
46
|
-
number,
|
|
47
|
-
url: `https://github.com/${owner}/${repo}/pull/${number}`,
|
|
48
|
-
label: `${owner}/${repo}#${number}`,
|
|
49
|
-
};
|
|
76
|
+
return githubRef(
|
|
77
|
+
hashMatch[1] as string,
|
|
78
|
+
hashMatch[2] as string,
|
|
79
|
+
Number(hashMatch[3])
|
|
80
|
+
);
|
|
50
81
|
}
|
|
@@ -125,8 +125,12 @@ export function isCursorUserStoreFilesAvailable(
|
|
|
125
125
|
export interface CursorHostedFilesOptions {
|
|
126
126
|
/** Control-plane base URL (default: `CURSOR_API_BASE_URL`, else api.cursor.com). */
|
|
127
127
|
baseUrl?: string;
|
|
128
|
-
/**
|
|
129
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Bearer credential (default: `CURSOR_API_KEY`). A function is re-resolved
|
|
130
|
+
* on every call — hosted freeze snapshots listen unsigned and bind the key
|
|
131
|
+
* file after serve start.
|
|
132
|
+
*/
|
|
133
|
+
apiKey?: string | (() => string | undefined);
|
|
130
134
|
/** File store to address (default: `AGENT_SERVE_STORE_SOURCE_ID`). */
|
|
131
135
|
storeSourceId?: string;
|
|
132
136
|
/** Test seam; defaults to global fetch. */
|
|
@@ -622,7 +626,9 @@ function resolveStoreSourceId(options: CursorHostedFilesOptions): string {
|
|
|
622
626
|
}
|
|
623
627
|
|
|
624
628
|
function resolveApiKey(options: CursorHostedFilesOptions): string {
|
|
625
|
-
const
|
|
629
|
+
const configured =
|
|
630
|
+
typeof options.apiKey === "function" ? options.apiKey() : options.apiKey;
|
|
631
|
+
const key = (configured ?? process.env.CURSOR_API_KEY)?.trim();
|
|
626
632
|
if (key === undefined || key === "") {
|
|
627
633
|
throw new Error(
|
|
628
634
|
"cursorHostedFiles requires CURSOR_API_KEY (deployment pod credential on Cursor hosting)"
|
package/src/files.ts
CHANGED
|
@@ -184,6 +184,17 @@ export const agentStoreKeys = {
|
|
|
184
184
|
`${STORAGE_KEY_ROOT}/${agent}/memory/journal.jsonl`,
|
|
185
185
|
memoryJournalRotated: (agent: string, stamp: string): string =>
|
|
186
186
|
`${STORAGE_KEY_ROOT}/${agent}/memory/journal-${stamp}.jsonl`,
|
|
187
|
+
// SDK conversation mirror (the runner's SQLite store, exported through the
|
|
188
|
+
// store APIs): one manifest per SDK agent id plus its content-addressed
|
|
189
|
+
// checkpoint blobs. See internal/conversation-mirror.ts.
|
|
190
|
+
conversationManifest: (agent: string, sdkAgentId: string): string =>
|
|
191
|
+
`${STORAGE_KEY_ROOT}/${agent}/conversations/${encodeURIComponent(sdkAgentId)}/manifest.json`,
|
|
192
|
+
conversationBlob: (
|
|
193
|
+
agent: string,
|
|
194
|
+
sdkAgentId: string,
|
|
195
|
+
blobId: string
|
|
196
|
+
): string =>
|
|
197
|
+
`${STORAGE_KEY_ROOT}/${agent}/conversations/${encodeURIComponent(sdkAgentId)}/blobs/${encodeURIComponent(blobId)}`,
|
|
187
198
|
} as const;
|
|
188
199
|
|
|
189
200
|
/**
|