@cursor/july 0.1.105 → 0.1.107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agent-serve.js +1 -8
- package/dist/channels/bitbucket/types.d.ts +2 -4
- package/dist/channels/bitbucket/types.d.ts.map +1 -1
- package/dist/channels/deployments/types.d.ts +5 -8
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/types.d.ts +2 -4
- package/dist/channels/github/types.d.ts.map +1 -1
- package/dist/channels/gitlab/types.d.ts +2 -5
- package/dist/channels/gitlab/types.d.ts.map +1 -1
- package/dist/channels/origin/types.d.ts +2 -3
- package/dist/channels/origin/types.d.ts.map +1 -1
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +3 -0
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +1 -1
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +48 -11
- package/dist/channels/slack/types.d.ts +4 -3
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +3 -3
- package/dist/docs/ab.html +6 -6
- package/dist/docs/assets/{app.BVwaffdK.js → app.CtuckIiL.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.DXXZxiMv.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.WuWTZ1x8.js → VPLocalSearchBox.Bkkhnu8K.js} +2 -2
- package/dist/docs/assets/chunks/{theme.BYdI_6sF.js → theme.DhpIe0Pa.js} +2 -2
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.js → guides_opentelemetry.md.SCRMskno.js} +3 -3
- package/dist/docs/assets/{guides_opentelemetry.md.COh9jFVg.lean.js → guides_opentelemetry.md.SCRMskno.lean.js} +1 -1
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.js → reference_channels.md.D-qTqwcq.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.DBGcaB7m.lean.js → reference_channels.md.D-qTqwcq.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.C6Lo8SEd.js → reference_cli.md.Dm67hd2D.js} +1 -1
- package/dist/docs/assets/{skills_otel.md.CqhobH3B.js → skills_otel.md.B5Ddv1xH.js} +1 -1
- package/dist/docs/assets/{style.BRuM8477.css → style.DCD_zyg3.css} +1 -1
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/concepts.html +5 -5
- package/dist/docs/deployment.html +6 -6
- package/dist/docs/evals.html +6 -6
- package/dist/docs/guides/agent-to-agent.html +6 -6
- package/dist/docs/guides/cloud-agents.html +6 -6
- package/dist/docs/guides/convert-automation.html +6 -6
- package/dist/docs/guides/github.html +6 -6
- package/dist/docs/guides/grokbot-agents.html +6 -6
- package/dist/docs/guides/human-in-the-loop.html +6 -6
- package/dist/docs/guides/mcp-oauth.html +6 -6
- package/dist/docs/guides/opentelemetry.html +8 -8
- package/dist/docs/guides/opentelemetry.md +3 -4
- package/dist/docs/guides/slack.html +6 -6
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/index.html +6 -6
- package/dist/docs/llms-full.txt +22 -28
- package/dist/docs/quickstart.html +6 -6
- package/dist/docs/reference/agent-config.html +6 -6
- package/dist/docs/reference/artifacts.html +6 -6
- package/dist/docs/reference/channels.html +7 -7
- package/dist/docs/reference/channels.md +11 -19
- package/dist/docs/reference/cli.html +8 -8
- package/dist/docs/reference/cli.md +5 -2
- package/dist/docs/reference/connections.html +6 -6
- package/dist/docs/reference/extensions.html +6 -6
- package/dist/docs/reference/hooks.html +6 -6
- package/dist/docs/reference/http-api.html +6 -6
- package/dist/docs/reference/instructions.html +6 -6
- package/dist/docs/reference/playground.html +5 -5
- package/dist/docs/reference/project-layout.html +6 -6
- package/dist/docs/reference/prompt.html +6 -6
- package/dist/docs/reference/result.html +6 -6
- package/dist/docs/reference/schedules.html +6 -6
- package/dist/docs/reference/sessions.html +5 -5
- package/dist/docs/reference/skills.html +6 -6
- package/dist/docs/reference/subagents.html +6 -6
- package/dist/docs/reference/tools.html +6 -6
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/skills/ab.html +6 -6
- package/dist/docs/skills/create-agent.html +6 -6
- package/dist/docs/skills/debug.html +5 -5
- package/dist/docs/skills/evals.html +6 -6
- package/dist/docs/skills/framework-map.html +5 -5
- package/dist/docs/skills/github.html +6 -6
- package/dist/docs/skills/hillclimb.html +6 -6
- package/dist/docs/skills/index.html +5 -5
- package/dist/docs/skills/mcp-auth.html +6 -6
- package/dist/docs/skills/otel.html +8 -8
- package/dist/docs/skills/otel.md +3 -3
- package/dist/docs/skills/setup-slack.html +6 -6
- package/dist/docs/storage.html +6 -6
- package/dist/docs/templates/agentic-owners.html +6 -6
- package/dist/docs/templates/agents-md.html +6 -6
- package/dist/docs/templates/code-wiki.html +6 -6
- package/dist/docs/templates/demo.html +6 -6
- package/dist/docs/templates/grokbot-agents.html +6 -6
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/security-help.html +6 -6
- package/dist/docs/templates/security-reviewer.html +6 -6
- package/dist/docs/templates/triage.html +6 -6
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +23 -11
- package/dist/internal/cursor/backend-client.d.ts +25 -0
- package/dist/internal/cursor/backend-client.d.ts.map +1 -1
- package/dist/internal/cursor/backend-client.js +57 -2
- package/dist/internal/deploy-client.d.ts +8 -0
- package/dist/internal/deploy-client.d.ts.map +1 -1
- package/dist/internal/deploy-client.js +14 -0
- package/dist/internal/deploy-manifest.d.ts +3 -0
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +15 -12
- package/dist/internal/discovery/agent.d.ts.map +1 -1
- package/dist/internal/discovery/agent.js +1 -0
- package/dist/internal/discovery/info.d.ts.map +1 -1
- package/dist/internal/discovery/info.js +7 -3
- package/dist/internal/discovery/modules.d.ts +1 -1
- package/dist/internal/discovery/modules.d.ts.map +1 -1
- package/dist/internal/discovery/modules.js +1 -0
- package/dist/internal/discovery/project.d.ts.map +1 -1
- package/dist/internal/discovery/project.js +3 -0
- package/dist/internal/discovery/reminders.d.ts +7 -0
- package/dist/internal/discovery/reminders.d.ts.map +1 -0
- package/dist/internal/discovery/reminders.js +65 -0
- package/dist/internal/discovery/subagent.js +1 -0
- package/dist/internal/distribution.d.ts +5 -0
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +17 -0
- package/dist/internal/framework-storage-selection.d.ts +14 -3
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +36 -6
- package/dist/internal/guest-network.d.ts.map +1 -1
- package/dist/internal/guest-network.js +2 -0
- package/dist/internal/hosted-delivery-protocol.d.ts +48 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
- package/dist/internal/hosted-delivery-protocol.js +60 -0
- package/dist/internal/hosted-delivery.d.ts +10 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -1
- package/dist/internal/hosted-delivery.js +83 -18
- package/dist/internal/local-control-plane.d.ts +18 -2
- package/dist/internal/local-control-plane.d.ts.map +1 -1
- package/dist/internal/local-control-plane.js +199 -17
- package/dist/internal/reminder-control-plane-protocol.d.ts +187 -0
- package/dist/internal/reminder-control-plane-protocol.d.ts.map +1 -0
- package/dist/internal/reminder-control-plane-protocol.js +244 -0
- package/dist/internal/reminder-runner.d.ts +48 -6
- package/dist/internal/reminder-runner.d.ts.map +1 -1
- package/dist/internal/reminder-runner.js +336 -48
- package/dist/internal/reminder-schedule.d.ts +5 -2
- package/dist/internal/reminder-schedule.d.ts.map +1 -1
- package/dist/internal/reminder-schedule.js +8 -6
- package/dist/internal/reminder-store.d.ts +24 -7
- package/dist/internal/reminder-store.d.ts.map +1 -1
- package/dist/internal/reminder-store.js +6 -5
- package/dist/internal/request-error-status.d.ts +2 -0
- package/dist/internal/request-error-status.d.ts.map +1 -1
- package/dist/internal/request-error-status.js +22 -3
- package/dist/internal/scm/pr-url.d.ts +40 -0
- package/dist/internal/scm/pr-url.d.ts.map +1 -1
- package/dist/internal/scm/pr-url.js +93 -14
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +67 -27
- package/dist/internal/session-engine.d.ts +4 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +5 -0
- package/dist/playground/assets/{index-BaQzjaNK.js → index-Bq2HpEQB.js} +23 -23
- package/dist/playground/assets/index-CZKKNlmb.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/reminders.d.ts +24 -5
- package/dist/reminders.d.ts.map +1 -1
- package/dist/reminders.js +28 -5
- package/dist/types.d.ts +89 -20
- package/dist/types.d.ts.map +1 -1
- package/docs/guides/opentelemetry.md +3 -4
- package/docs/reference/channels.md +11 -19
- package/docs/reference/cli.md +5 -2
- package/package.json +3 -3
- package/skills/otel/SKILL.md +3 -3
- package/src/bin/agent-serve.ts +1 -9
- package/src/channels/bitbucket/types.ts +2 -4
- package/src/channels/deployments/types.ts +5 -8
- package/src/channels/github/types.ts +2 -4
- package/src/channels/gitlab/types.ts +2 -5
- package/src/channels/origin/types.ts +2 -3
- package/src/channels/slack/defaults.ts +3 -0
- package/src/channels/slack/dispatch.ts +1 -0
- package/src/channels/slack/live-delivery.ts +53 -12
- package/src/channels/slack/types.ts +4 -3
- package/src/index.ts +6 -3
- package/src/internal/cli-deploy.ts +30 -12
- package/src/internal/cursor/backend-client.ts +90 -2
- package/src/internal/deploy-client.ts +16 -0
- package/src/internal/deploy-manifest.ts +16 -11
- package/src/internal/discovery/agent.ts +1 -0
- package/src/internal/discovery/info.ts +6 -0
- package/src/internal/discovery/modules.ts +2 -4
- package/src/internal/discovery/project.ts +3 -0
- package/src/internal/discovery/reminders.ts +65 -0
- package/src/internal/discovery/subagent.ts +1 -0
- package/src/internal/distribution.ts +20 -0
- package/src/internal/framework-storage-selection.ts +43 -6
- package/src/internal/guest-network.ts +3 -0
- package/src/internal/hosted-delivery-protocol.ts +96 -0
- package/src/internal/hosted-delivery.ts +154 -27
- package/src/internal/local-control-plane.ts +281 -22
- package/src/internal/reminder-control-plane-protocol.ts +499 -0
- package/src/internal/reminder-runner.ts +421 -48
- package/src/internal/reminder-schedule.ts +11 -6
- package/src/internal/reminder-store.ts +27 -7
- package/src/internal/request-error-status.ts +27 -3
- package/src/internal/scm/pr-url.ts +167 -20
- package/src/internal/server.ts +69 -16
- package/src/internal/session-engine.ts +5 -0
- package/src/reminders.ts +35 -4
- package/src/types.ts +95 -20
- package/dist/docs/assets/chunks/@localSearchIndexroot.CJxMklAy.js +0 -1
- package/dist/playground/assets/index-CceqnLTX.css +0 -1
- /package/dist/docs/assets/{reference_cli.md.C6Lo8SEd.lean.js → reference_cli.md.Dm67hd2D.lean.js} +0 -0
- /package/dist/docs/assets/{skills_otel.md.CqhobH3B.lean.js → skills_otel.md.B5Ddv1xH.lean.js} +0 -0
package/docs/reference/cli.md
CHANGED
|
@@ -674,14 +674,17 @@ The command polls for up to ten minutes until the status reaches
|
|
|
674
674
|
|
|
675
675
|
## delete
|
|
676
676
|
|
|
677
|
-
`delete` removes a deployment.
|
|
677
|
+
`delete` removes a hosted deployment. You can delete a deployment that
|
|
678
|
+
still runs. The command frees the slug. A later deploy can use the same
|
|
679
|
+
name. Spend stays on the archived service account.
|
|
678
680
|
|
|
679
681
|
```bash
|
|
680
682
|
agent-sdk delete <slug> [--team <id>] [--no-wait] [--json]
|
|
681
683
|
```
|
|
682
684
|
|
|
683
685
|
The command waits until the deployment is gone. `--no-wait` returns after
|
|
684
|
-
the delete request is accepted.
|
|
686
|
+
the delete request is accepted. Architecture v2 slugs use the Agent SDK
|
|
687
|
+
control plane. Architecture v1 slugs use the Agent Serve control plane.
|
|
685
688
|
|
|
686
689
|
## rotate-token
|
|
687
690
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cursor/july",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.107",
|
|
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": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"!dist/internal/tenant-mcp/**",
|
|
25
25
|
"!dist/internal/grokbot/**",
|
|
26
26
|
"!dist/extensions/cursor-grokbot-agents/**",
|
|
27
|
-
"!dist/internal/review-comments
|
|
27
|
+
"!dist/internal/review-comments*",
|
|
28
28
|
"!dist/internal/shallow-clone.*",
|
|
29
29
|
"!dist/internal/managed-delivery.*",
|
|
30
30
|
"src/**/*",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"!src/internal/tenant-mcp/**",
|
|
33
33
|
"!src/internal/grokbot/**",
|
|
34
34
|
"!src/extensions/cursor-grokbot-agents/**",
|
|
35
|
-
"!src/internal/review-comments
|
|
35
|
+
"!src/internal/review-comments*",
|
|
36
36
|
"!src/internal/shallow-clone.ts",
|
|
37
37
|
"!src/internal/managed-delivery.ts",
|
|
38
38
|
"skills/**/*",
|
package/skills/otel/SKILL.md
CHANGED
|
@@ -33,9 +33,9 @@ export default defineOtel({
|
|
|
33
33
|
3. `serve(dir, { otel: { … } })`. `otel: false` disables env and
|
|
34
34
|
authored config.
|
|
35
35
|
|
|
36
|
-
Hosted
|
|
37
|
-
re-resolves exporters. Authored `agent/otel.ts` records from
|
|
38
|
-
start even when the factory returns no exporters yet.
|
|
36
|
+
Hosted secrets can arrive after startup. Use `defineOtel(() => …)` so
|
|
37
|
+
flush re-resolves exporters. Authored `agent/otel.ts` records from
|
|
38
|
+
process start even when the factory returns no exporters yet.
|
|
39
39
|
|
|
40
40
|
| Signal | Default |
|
|
41
41
|
| --- | --- |
|
package/src/bin/agent-serve.ts
CHANGED
|
@@ -341,9 +341,6 @@ Options:
|
|
|
341
341
|
the Cursor backend's per-forge forwarder instead of
|
|
342
342
|
minting raw tokens into this process
|
|
343
343
|
(AGENT_SERVE_<FORGE>_PROXY_URL overrides a base URL).
|
|
344
|
-
--cursor-github-proxy
|
|
345
|
-
serve: deprecated alias for --cursor-scm-proxy; removed
|
|
346
|
-
one release after --cursor-scm-proxy ships.
|
|
347
344
|
--public-url serve: base URL where this host is reachable from outside
|
|
348
345
|
(e.g. https://agent-serve.example.com). Required for peer
|
|
349
346
|
connections (defineConnection({ agent })) on cloud-runtime
|
|
@@ -519,7 +516,6 @@ async function main(argv: string[]): Promise<number> {
|
|
|
519
516
|
"allow-anonymous-cursor-account-mcp": { type: "boolean", default: false },
|
|
520
517
|
"allow-anonymous-grokbot": { type: "boolean", default: false },
|
|
521
518
|
"cursor-scm-proxy": { type: "boolean", default: false },
|
|
522
|
-
"cursor-github-proxy": { type: "boolean", default: false },
|
|
523
519
|
"no-schedules": { type: "boolean", default: false },
|
|
524
520
|
"no-control-plane": { type: "boolean", default: false },
|
|
525
521
|
"no-playground": { type: "boolean", default: false },
|
|
@@ -1353,11 +1349,7 @@ async function main(argv: string[]): Promise<number> {
|
|
|
1353
1349
|
: undefined,
|
|
1354
1350
|
allowAnonymousGrokbot:
|
|
1355
1351
|
values["allow-anonymous-grokbot"] === true ? true : undefined,
|
|
1356
|
-
cursorScmProxy:
|
|
1357
|
-
values["cursor-scm-proxy"] === true ||
|
|
1358
|
-
values["cursor-github-proxy"] === true
|
|
1359
|
-
? true
|
|
1360
|
-
: undefined,
|
|
1352
|
+
cursorScmProxy: values["cursor-scm-proxy"] === true ? true : undefined,
|
|
1361
1353
|
schedules: values["no-schedules"] === true ? false : undefined,
|
|
1362
1354
|
noControlPlane: values["no-control-plane"] === true ? true : undefined,
|
|
1363
1355
|
playground: values["no-playground"] === true ? false : undefined,
|
|
@@ -229,10 +229,8 @@ export interface BitbucketChannelOptions {
|
|
|
229
229
|
*/
|
|
230
230
|
webhookEvents?: readonly string[];
|
|
231
231
|
/**
|
|
232
|
-
* Continuation selector.
|
|
233
|
-
*
|
|
234
|
-
* `architecture: "v2"` (then `bitbucket.pr/v2`, or `bitbucket.none/v2`
|
|
235
|
-
* when a non-PR event is declared).
|
|
232
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
233
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
236
234
|
*/
|
|
237
235
|
continuation?: ContinuationIdentity;
|
|
238
236
|
/**
|
|
@@ -56,10 +56,9 @@ export interface DeploymentsChannelOptions {
|
|
|
56
56
|
* and then receives nothing. A bare string takes the default environment and
|
|
57
57
|
* event filters.
|
|
58
58
|
*
|
|
59
|
-
* Omit on
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* sources for a tenant it has never seen.
|
|
59
|
+
* Omit on Cursor-managed hosting. The control plane binds sources from the
|
|
60
|
+
* deployment's watched repositories, and the channel admits only what it
|
|
61
|
+
* receives. An agent cannot enumerate sources for an unseen tenant.
|
|
63
62
|
*
|
|
64
63
|
* Name sources to narrow below that scope, or to drive the self-hosted
|
|
65
64
|
* relay, which has no deploy scope to inherit. On that wire `[]` means
|
|
@@ -89,10 +88,8 @@ export interface DeploymentsChannelOptions {
|
|
|
89
88
|
onStart?: ChannelDefinition["onStart"];
|
|
90
89
|
onStop?: ChannelDefinition["onStop"];
|
|
91
90
|
/**
|
|
92
|
-
* Continuation selector.
|
|
93
|
-
*
|
|
94
|
-
* `"deployments.deployment/v2"`). Override with `"deployments.none/v2"`
|
|
95
|
-
* for one-shot events.
|
|
91
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
92
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
96
93
|
*/
|
|
97
94
|
continuation?: ContinuationIdentity;
|
|
98
95
|
}
|
|
@@ -480,10 +480,8 @@ export interface GitHubChannelOptions {
|
|
|
480
480
|
*/
|
|
481
481
|
botName?: string;
|
|
482
482
|
/**
|
|
483
|
-
* Continuation selector.
|
|
484
|
-
*
|
|
485
|
-
* `"github.pr/v2"`). Override type with `"github.issue/v2"` or
|
|
486
|
-
* `"github.none/v2"` for events outside PR membership.
|
|
483
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
484
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
487
485
|
*/
|
|
488
486
|
continuation?: ContinuationIdentity;
|
|
489
487
|
/**
|
|
@@ -219,11 +219,8 @@ export interface GitLabChannelOptions {
|
|
|
219
219
|
*/
|
|
220
220
|
webhookEvents?: readonly string[];
|
|
221
221
|
/**
|
|
222
|
-
* Continuation selector.
|
|
223
|
-
*
|
|
224
|
-
* `architecture: "v2"` (then `gitlab.mr/v2`, or `gitlab.none/v2` when a
|
|
225
|
-
* non-MR event is declared). Override with `"gitlab.none/v2"` for one-shot
|
|
226
|
-
* events.
|
|
222
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
223
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
227
224
|
*/
|
|
228
225
|
continuation?: ContinuationIdentity;
|
|
229
226
|
/**
|
|
@@ -246,9 +246,8 @@ export interface OriginChannelOptions {
|
|
|
246
246
|
*/
|
|
247
247
|
webhookEvents?: readonly string[];
|
|
248
248
|
/**
|
|
249
|
-
* Continuation selector.
|
|
250
|
-
*
|
|
251
|
-
* `"origin.pr/v2"`). Override with `"origin.none/v2"` for one-shot events.
|
|
249
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
250
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
252
251
|
*/
|
|
253
252
|
continuation?: ContinuationIdentity;
|
|
254
253
|
/**
|
|
@@ -362,6 +362,9 @@ export function buildDefaultEvents(
|
|
|
362
362
|
channel.state.streamTs = null;
|
|
363
363
|
channel.state.streamChannelId = null;
|
|
364
364
|
channel.state.streamFull = false;
|
|
365
|
+
// A stream failure downgrades the rest of its own turn, not the thread.
|
|
366
|
+
channel.state.streamingUnavailable = false;
|
|
367
|
+
channel.state.streamAppendedChunks = 0;
|
|
365
368
|
channel.state.lastPostedText = null;
|
|
366
369
|
channel.state.streamBlockText = null;
|
|
367
370
|
channel.state.reasoningCard = undefined;
|
|
@@ -147,6 +147,7 @@ export function createStreamDeliveryStrategy(
|
|
|
147
147
|
channel.state.streamTs = started.ts;
|
|
148
148
|
channel.state.streamChannelId = started.channel;
|
|
149
149
|
channel.state.streamFull = false;
|
|
150
|
+
channel.state.streamAppendedChunks = 0;
|
|
150
151
|
channel.state.lastPostedText = openingText;
|
|
151
152
|
channel.state.streamBlockText = openingText;
|
|
152
153
|
log.info("chat.startStream ok", {
|
|
@@ -193,6 +194,21 @@ export function createStreamDeliveryStrategy(
|
|
|
193
194
|
highlightCodeFences(text)
|
|
194
195
|
);
|
|
195
196
|
|
|
197
|
+
/**
|
|
198
|
+
* The reply does not extend what the stream already holds, so there is no
|
|
199
|
+
* delta to append and the text on Slack is not the reply.
|
|
200
|
+
*/
|
|
201
|
+
const rewound = (channel: SlackChannel, text: string): boolean =>
|
|
202
|
+
streamDelta(channel, text) === "" &&
|
|
203
|
+
!highlightCodeFences(text).startsWith(
|
|
204
|
+
highlightCodeFences(channel.state.streamBlockText ?? "")
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
const countAppended = (channel: SlackChannel, chunks: number): void => {
|
|
208
|
+
channel.state.streamAppendedChunks =
|
|
209
|
+
(channel.state.streamAppendedChunks ?? 0) + chunks;
|
|
210
|
+
};
|
|
211
|
+
|
|
196
212
|
const stopWithSuffix = async (args: {
|
|
197
213
|
channel: SlackChannel;
|
|
198
214
|
channelId: string;
|
|
@@ -246,25 +262,25 @@ export function createStreamDeliveryStrategy(
|
|
|
246
262
|
};
|
|
247
263
|
|
|
248
264
|
/**
|
|
249
|
-
* The
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
* duplicate would be worse than a lost tail.
|
|
265
|
+
* The open stream cannot carry the rest of the reply — it is full, or the
|
|
266
|
+
* reply no longer extends what it holds. Close it as it stands so it stops
|
|
267
|
+
* spinning and post the remainder as a new thread message.
|
|
253
268
|
*/
|
|
254
|
-
const
|
|
269
|
+
const continueInNewMessage = async (args: {
|
|
255
270
|
channel: SlackChannel;
|
|
256
271
|
channelId: string;
|
|
257
272
|
ts: string;
|
|
258
273
|
remainder: string;
|
|
274
|
+
reason: string;
|
|
259
275
|
sessionId: string;
|
|
260
|
-
}): Promise<
|
|
261
|
-
const { channel, channelId, ts, remainder, sessionId } = args;
|
|
276
|
+
}): Promise<boolean> => {
|
|
277
|
+
const { channel, channelId, ts, remainder, reason, sessionId } = args;
|
|
262
278
|
const log = getLog();
|
|
263
279
|
await stopChatStream({ botToken, channel: channelId, ts });
|
|
264
280
|
channel.state.streamTs = null;
|
|
265
281
|
const threadTs = channel.state.threadTs;
|
|
266
282
|
if (remainder === "" || threadTs === null || threadTs === "") {
|
|
267
|
-
return;
|
|
283
|
+
return true;
|
|
268
284
|
}
|
|
269
285
|
try {
|
|
270
286
|
const posted = await postMessage({
|
|
@@ -275,19 +291,23 @@ export function createStreamDeliveryStrategy(
|
|
|
275
291
|
plainText: remainder.length >= SLACK_MARKDOWN_TEXT_MAX_LEN,
|
|
276
292
|
});
|
|
277
293
|
channel.state.lastBotMessageTs = posted.ts;
|
|
278
|
-
log.info("reply
|
|
294
|
+
log.info("reply continued in a new message", {
|
|
295
|
+
reason,
|
|
279
296
|
channel: channelId,
|
|
280
297
|
stream_ts: ts,
|
|
281
298
|
session: sessionId,
|
|
282
299
|
continued_chars: remainder.length,
|
|
283
300
|
});
|
|
301
|
+
return true;
|
|
284
302
|
} catch (error) {
|
|
285
|
-
log.warn("stream
|
|
303
|
+
log.warn("stream continuation failed", {
|
|
304
|
+
reason,
|
|
286
305
|
error: error instanceof Error ? error.message : String(error),
|
|
287
306
|
channel: channelId,
|
|
288
307
|
stream_ts: ts,
|
|
289
308
|
session: sessionId,
|
|
290
309
|
});
|
|
310
|
+
return false;
|
|
291
311
|
}
|
|
292
312
|
};
|
|
293
313
|
|
|
@@ -328,6 +348,7 @@ export function createStreamDeliveryStrategy(
|
|
|
328
348
|
noteAppendFailure(channel, result);
|
|
329
349
|
return;
|
|
330
350
|
}
|
|
351
|
+
countAppended(channel, 1);
|
|
331
352
|
channel.state.lastPostedText = text;
|
|
332
353
|
channel.state.streamBlockText = text;
|
|
333
354
|
},
|
|
@@ -364,8 +385,10 @@ export function createStreamDeliveryStrategy(
|
|
|
364
385
|
chunks: chunks.length,
|
|
365
386
|
});
|
|
366
387
|
noteAppendFailure(channel, result);
|
|
388
|
+
return false;
|
|
367
389
|
}
|
|
368
|
-
|
|
390
|
+
countAppended(channel, chunks.length);
|
|
391
|
+
return true;
|
|
369
392
|
},
|
|
370
393
|
|
|
371
394
|
async finalize({ channel, channelId, text, sessionId }) {
|
|
@@ -381,6 +404,22 @@ export function createStreamDeliveryStrategy(
|
|
|
381
404
|
}
|
|
382
405
|
// Measured before the stop attempt mutates stream state.
|
|
383
406
|
const remainder = streamDelta(channel, text);
|
|
407
|
+
// Nothing to append and the stream does not hold the reply: closing it
|
|
408
|
+
// here would leave the answer nowhere and report it as delivered.
|
|
409
|
+
if (rewound(channel, text)) {
|
|
410
|
+
const posted = await continueInNewMessage({
|
|
411
|
+
channel,
|
|
412
|
+
channelId,
|
|
413
|
+
ts,
|
|
414
|
+
remainder: text,
|
|
415
|
+
reason: "rewound",
|
|
416
|
+
sessionId,
|
|
417
|
+
});
|
|
418
|
+
if (posted) {
|
|
419
|
+
channel.state.lastPostedText = text;
|
|
420
|
+
}
|
|
421
|
+
return { delivered: posted };
|
|
422
|
+
}
|
|
384
423
|
const stopped =
|
|
385
424
|
channel.state.streamFull === true
|
|
386
425
|
? { ok: false, error: "msg_too_long" }
|
|
@@ -391,15 +430,17 @@ export function createStreamDeliveryStrategy(
|
|
|
391
430
|
stream_ts: ts,
|
|
392
431
|
session: sessionId,
|
|
393
432
|
chars: text.length,
|
|
433
|
+
appends: channel.state.streamAppendedChunks ?? 0,
|
|
394
434
|
});
|
|
395
435
|
return { delivered: true };
|
|
396
436
|
}
|
|
397
437
|
if (stopped.error === "msg_too_long") {
|
|
398
|
-
await
|
|
438
|
+
await continueInNewMessage({
|
|
399
439
|
channel,
|
|
400
440
|
channelId,
|
|
401
441
|
ts,
|
|
402
442
|
remainder,
|
|
443
|
+
reason: "msg_too_long",
|
|
403
444
|
sessionId,
|
|
404
445
|
});
|
|
405
446
|
channel.state.lastPostedText = text;
|
|
@@ -81,6 +81,8 @@ export interface SlackChannelState {
|
|
|
81
81
|
streamingUnavailable?: boolean;
|
|
82
82
|
/** The open stream hit Slack's size cap; appends stop until it closes. */
|
|
83
83
|
streamFull?: boolean;
|
|
84
|
+
/** Chunks Slack accepted on the open stream, reported when it closes. */
|
|
85
|
+
streamAppendedChunks?: number;
|
|
84
86
|
/** Editable progress message ts when `chat.startStream` is unavailable. */
|
|
85
87
|
progressTs: string | null;
|
|
86
88
|
/**
|
|
@@ -597,9 +599,8 @@ export interface SlackAccessPolicy {
|
|
|
597
599
|
export interface SlackChannelOptions {
|
|
598
600
|
credentials?: SlackCredentials;
|
|
599
601
|
/**
|
|
600
|
-
* Continuation selector.
|
|
601
|
-
*
|
|
602
|
-
* `"slack.thread/v2"`). Override with `"slack.none/v2"` for one-shot events.
|
|
602
|
+
* Continuation selector. Omit this to inherit the agent architecture's
|
|
603
|
+
* default. Set it explicitly only when migrating persisted identities.
|
|
603
604
|
*/
|
|
604
605
|
continuation?: ContinuationIdentity;
|
|
605
606
|
/** Defaults to `{ respondTo: "thread", blockExternals: true }`. */
|
package/src/index.ts
CHANGED
|
@@ -139,7 +139,9 @@ export {
|
|
|
139
139
|
TOOL_MCP_ENDPOINT_PATH,
|
|
140
140
|
} from "./internal/mcp-endpoint.js";
|
|
141
141
|
export {
|
|
142
|
+
REMINDER_ARGS_MAX_BYTES,
|
|
142
143
|
ReminderValidationError,
|
|
144
|
+
rejectAnonymousReminderHandlers,
|
|
143
145
|
UnknownReminderError,
|
|
144
146
|
} from "./internal/reminder-runner.js";
|
|
145
147
|
export type { AgentMount } from "./internal/server.js";
|
|
@@ -169,8 +171,10 @@ export { prompt } from "./prompt.js";
|
|
|
169
171
|
export type {
|
|
170
172
|
ReminderBusyPolicy,
|
|
171
173
|
ReminderCreateInput,
|
|
174
|
+
ReminderDefinition,
|
|
172
175
|
ReminderFireContext,
|
|
173
176
|
ReminderFireResult,
|
|
177
|
+
ReminderHandlerConfig,
|
|
174
178
|
ReminderHostApi,
|
|
175
179
|
ReminderInfo,
|
|
176
180
|
ReminderReschedule,
|
|
@@ -179,6 +183,7 @@ export type {
|
|
|
179
183
|
ReminderTarget,
|
|
180
184
|
ReminderUntilContext,
|
|
181
185
|
} from "./reminders.js";
|
|
186
|
+
export { defineReminder } from "./reminders.js";
|
|
182
187
|
export { defineResult } from "./result.js";
|
|
183
188
|
export { defineSchedule } from "./schedules.js";
|
|
184
189
|
export { defineSkill } from "./skills.js";
|
|
@@ -226,9 +231,7 @@ export {
|
|
|
226
231
|
|
|
227
232
|
/**
|
|
228
233
|
* Runtime config for an agent — authored at `agent/agent.ts` (the root
|
|
229
|
-
* agent) or `agent/subagents/<id>/agent.ts` (a subagent).
|
|
230
|
-
* `architecture: "v2"` to deploy onto the v2 control plane; omitted
|
|
231
|
-
* channel continuation then inherits kind `/v2` defaults.
|
|
234
|
+
* agent) or `agent/subagents/<id>/agent.ts` (a subagent).
|
|
232
235
|
*/
|
|
233
236
|
export function defineAgent(config: AgentConfig): AgentConfigDefinition {
|
|
234
237
|
return brandDefinition("agent", config);
|
|
@@ -1570,14 +1570,26 @@ export async function cmdDelete(
|
|
|
1570
1570
|
if (typeof ctx === "number") {
|
|
1571
1571
|
return ctx;
|
|
1572
1572
|
}
|
|
1573
|
-
|
|
1573
|
+
// Same dispatch as `stop`: v1 409s architecture-v2 slugs, so the v2
|
|
1574
|
+
// DELETE goes first. A v2 404 (missing slug, or an older backend)
|
|
1575
|
+
// falls through to the v1 agent-serve delete.
|
|
1576
|
+
let architecture: "v1" | "v2" = "v2";
|
|
1577
|
+
let accepted: DeleteAccepted | AgentkitStopAccepted;
|
|
1574
1578
|
try {
|
|
1575
|
-
accepted = await ctx.client.
|
|
1576
|
-
teamId: ctx.teamId,
|
|
1577
|
-
slug,
|
|
1578
|
-
});
|
|
1579
|
+
accepted = await ctx.client.deleteAgentkit({ teamId: ctx.teamId, slug });
|
|
1579
1580
|
} catch (error) {
|
|
1580
|
-
|
|
1581
|
+
if (!(error instanceof DeployApiError) || error.status !== 404) {
|
|
1582
|
+
return renderApiError(error, ctx.err);
|
|
1583
|
+
}
|
|
1584
|
+
try {
|
|
1585
|
+
accepted = await ctx.client.deleteDeployment({
|
|
1586
|
+
teamId: ctx.teamId,
|
|
1587
|
+
slug,
|
|
1588
|
+
});
|
|
1589
|
+
architecture = "v1";
|
|
1590
|
+
} catch (v1Error) {
|
|
1591
|
+
return renderApiError(v1Error, ctx.err);
|
|
1592
|
+
}
|
|
1581
1593
|
}
|
|
1582
1594
|
if (ctx.noWait) {
|
|
1583
1595
|
if (ctx.json) {
|
|
@@ -1588,7 +1600,11 @@ export async function cmdDelete(
|
|
|
1588
1600
|
return 0;
|
|
1589
1601
|
}
|
|
1590
1602
|
try {
|
|
1591
|
-
await pollUntilGone(ctx, slug)
|
|
1603
|
+
await pollUntilGone(ctx, slug, () =>
|
|
1604
|
+
architecture === "v2"
|
|
1605
|
+
? ctx.client.getAgentkitDeploy({ teamId: ctx.teamId, slug })
|
|
1606
|
+
: ctx.client.getDeployment({ teamId: ctx.teamId, slug })
|
|
1607
|
+
);
|
|
1592
1608
|
} catch (error) {
|
|
1593
1609
|
return renderApiError(error, ctx.err);
|
|
1594
1610
|
}
|
|
@@ -2103,7 +2119,12 @@ function transientDeployStatusWaitMs(
|
|
|
2103
2119
|
*/
|
|
2104
2120
|
async function pollUntilGone(
|
|
2105
2121
|
ctx: DeployCliContext,
|
|
2106
|
-
slug: string
|
|
2122
|
+
slug: string,
|
|
2123
|
+
getDetail: () => Promise<{
|
|
2124
|
+
status: string;
|
|
2125
|
+
progress?: DeploymentProgress;
|
|
2126
|
+
statusMessage?: string | null;
|
|
2127
|
+
}>
|
|
2107
2128
|
): Promise<void> {
|
|
2108
2129
|
const startedAt = Date.now();
|
|
2109
2130
|
const tty = process.stderr.isTTY === true;
|
|
@@ -2126,10 +2147,7 @@ async function pollUntilGone(
|
|
|
2126
2147
|
|
|
2127
2148
|
for (;;) {
|
|
2128
2149
|
try {
|
|
2129
|
-
const detail = await
|
|
2130
|
-
teamId: ctx.teamId,
|
|
2131
|
-
slug,
|
|
2132
|
-
});
|
|
2150
|
+
const detail = await getDetail();
|
|
2133
2151
|
report(deployProgressLabel(detail));
|
|
2134
2152
|
} catch (error: unknown) {
|
|
2135
2153
|
if (error instanceof DeployApiError && error.status === 404) {
|
|
@@ -82,6 +82,37 @@ const githubTokenResponseSchema: z.ZodType<CursorGithubToken> = z.object({
|
|
|
82
82
|
expiresAt: z.string().datetime(),
|
|
83
83
|
});
|
|
84
84
|
|
|
85
|
+
/** SCMs whose git fetches ride the backend's `/v0/scm-events/<provider>-git-proxy` routes. */
|
|
86
|
+
export type CursorScmCloneProvider = "gitlab" | "bitbucket";
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Proxied clone target for a GitLab / Bitbucket repository. The backend
|
|
90
|
+
* never hands out the provider credential: git fetches go to `remoteUrl`
|
|
91
|
+
* on the backend with the caller's own Cursor API key as a bearer token,
|
|
92
|
+
* and the backend adds the tenant credential per request.
|
|
93
|
+
*/
|
|
94
|
+
export interface CursorScmCloneTarget {
|
|
95
|
+
/** Absolute `<backend>/v0/scm-events/<provider>-git-proxy/<repo>.git`. */
|
|
96
|
+
remoteUrl: string;
|
|
97
|
+
/** Bearer credential git presents to the backend (the caller's API key). */
|
|
98
|
+
token: string;
|
|
99
|
+
/** ISO timestamp after which the caller re-resolves the target. */
|
|
100
|
+
expiresAt: string;
|
|
101
|
+
username: string;
|
|
102
|
+
authMode: "bearer";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const scmCloneTargetResponseSchema = z.object({
|
|
106
|
+
expiresAt: z.string().datetime(),
|
|
107
|
+
clone: z.object({
|
|
108
|
+
remotePath: z
|
|
109
|
+
.string()
|
|
110
|
+
.regex(/^\/v0\/scm-events\/[a-z]+-git-proxy\/.+\.git$/),
|
|
111
|
+
username: z.string().min(1),
|
|
112
|
+
authMode: z.literal("bearer"),
|
|
113
|
+
}),
|
|
114
|
+
});
|
|
115
|
+
|
|
85
116
|
const mcpToolSchema = z.object({
|
|
86
117
|
name: z.string(),
|
|
87
118
|
providerIdentifier: z.string().optional(),
|
|
@@ -490,6 +521,62 @@ export class CursorBackendClient {
|
|
|
490
521
|
return githubTokenResponseSchema.parse(parsed);
|
|
491
522
|
}
|
|
492
523
|
|
|
524
|
+
/**
|
|
525
|
+
* Resolve the proxied clone target for a GitLab / Bitbucket repository
|
|
526
|
+
* (`owner/name`; GitLab `path_with_namespace`). Same authorization as the
|
|
527
|
+
* provider proxy this host already calls; the returned remote lives on
|
|
528
|
+
* the backend and takes this client's API key, never a provider token.
|
|
529
|
+
*/
|
|
530
|
+
async getScmCloneTarget(
|
|
531
|
+
provider: CursorScmCloneProvider,
|
|
532
|
+
repo: string
|
|
533
|
+
): Promise<CursorScmCloneTarget> {
|
|
534
|
+
const label = provider === "gitlab" ? "GitLab" : "Bitbucket";
|
|
535
|
+
let response: Response;
|
|
536
|
+
try {
|
|
537
|
+
response = await this.fetchImpl(
|
|
538
|
+
`${this.backendUrl}/v0/scm-events/${provider}-clone-target`,
|
|
539
|
+
{
|
|
540
|
+
method: "POST",
|
|
541
|
+
headers: {
|
|
542
|
+
"content-type": "application/json",
|
|
543
|
+
authorization: `Bearer ${this.currentApiKey()}`,
|
|
544
|
+
},
|
|
545
|
+
body: JSON.stringify({ repo }),
|
|
546
|
+
signal: AbortSignal.timeout(30_000),
|
|
547
|
+
}
|
|
548
|
+
);
|
|
549
|
+
} catch (error) {
|
|
550
|
+
throw new CursorBackendError(
|
|
551
|
+
`Cursor ${label} clone target request failed: ${describeError(error)}`
|
|
552
|
+
);
|
|
553
|
+
}
|
|
554
|
+
const text = await response.text();
|
|
555
|
+
if (!response.ok) {
|
|
556
|
+
throw new CursorBackendError(
|
|
557
|
+
describeGithubTokenHttpFailure(response.status, text, label),
|
|
558
|
+
response.status,
|
|
559
|
+
retryAfterMsFromResponse(response)
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
let parsed: unknown;
|
|
563
|
+
try {
|
|
564
|
+
parsed = JSON.parse(text) as unknown;
|
|
565
|
+
} catch {
|
|
566
|
+
throw new CursorBackendError(
|
|
567
|
+
`Cursor backend returned a non-JSON ${label} clone target response.`
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
const body = scmCloneTargetResponseSchema.parse(parsed);
|
|
571
|
+
return {
|
|
572
|
+
remoteUrl: `${this.backendUrl}${body.clone.remotePath}`,
|
|
573
|
+
token: this.currentApiKey(),
|
|
574
|
+
expiresAt: body.expiresAt,
|
|
575
|
+
username: body.clone.username,
|
|
576
|
+
authMode: body.clone.authMode,
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
|
|
493
580
|
/**
|
|
494
581
|
* One unary Connect-JSON call on `aiserver.v1.<service>` with the same
|
|
495
582
|
* token exchange and 401 retry as the dashboard RPCs. Callers parse the
|
|
@@ -864,7 +951,8 @@ const MAX_GITHUB_TOKEN_RETRY_AFTER_MS = 60 * 60_000;
|
|
|
864
951
|
*/
|
|
865
952
|
function describeGithubTokenHttpFailure(
|
|
866
953
|
status: number,
|
|
867
|
-
bodyText: string
|
|
954
|
+
bodyText: string,
|
|
955
|
+
label = "GitHub"
|
|
868
956
|
): string {
|
|
869
957
|
const detail = githubTokenErrorFromBody(bodyText);
|
|
870
958
|
if (status === 401) {
|
|
@@ -875,7 +963,7 @@ function describeGithubTokenHttpFailure(
|
|
|
875
963
|
if (detail !== undefined) {
|
|
876
964
|
return detail;
|
|
877
965
|
}
|
|
878
|
-
return `Cursor
|
|
966
|
+
return `Cursor ${label} credential request failed (${status}).`;
|
|
879
967
|
}
|
|
880
968
|
|
|
881
969
|
function githubTokenErrorFromBody(bodyText: string): string | undefined {
|
|
@@ -675,6 +675,22 @@ export class AgentServeDeployClient {
|
|
|
675
675
|
return agentkitStopAcceptedSchema.parse(raw);
|
|
676
676
|
}
|
|
677
677
|
|
|
678
|
+
/**
|
|
679
|
+
* Delete a v2 deployment (`DELETE /internal/agentsdk/deployments/:slug`).
|
|
680
|
+
* 202 means accepted; poll {@link getAgentkitDeploy} until 404.
|
|
681
|
+
*/
|
|
682
|
+
async deleteAgentkit(args: {
|
|
683
|
+
teamId: number;
|
|
684
|
+
slug: string;
|
|
685
|
+
}): Promise<AgentkitStopAccepted> {
|
|
686
|
+
const raw = await this.request({
|
|
687
|
+
method: "DELETE",
|
|
688
|
+
path: `/internal/agentsdk/deployments/${encodeURIComponent(args.slug)}?teamId=${args.teamId}`,
|
|
689
|
+
context: { verb: "delete", slug: args.slug },
|
|
690
|
+
});
|
|
691
|
+
return agentkitStopAcceptedSchema.parse(raw);
|
|
692
|
+
}
|
|
693
|
+
|
|
678
694
|
async listDeployments(args: { teamId: number }): Promise<Deployment[]> {
|
|
679
695
|
const raw = await this.request({
|
|
680
696
|
method: "GET",
|