@cursor/july 0.1.99 → 0.1.100
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/AGENTS.md +4 -2
- package/dist/channels/github/defaults.d.ts.map +1 -1
- package/dist/channels/github/defaults.js +28 -3
- package/dist/channels/github/progress.d.ts +7 -0
- package/dist/channels/github/progress.d.ts.map +1 -1
- package/dist/channels/slack/api.d.ts +16 -7
- package/dist/channels/slack/api.d.ts.map +1 -1
- package/dist/channels/slack/api.js +29 -13
- package/dist/channels/slack/constants.d.ts +6 -0
- package/dist/channels/slack/constants.d.ts.map +1 -1
- package/dist/channels/slack/constants.js +6 -0
- package/dist/channels/slack/defaults.d.ts +9 -4
- package/dist/channels/slack/defaults.d.ts.map +1 -1
- package/dist/channels/slack/defaults.js +154 -76
- package/dist/channels/slack/dispatch.d.ts.map +1 -1
- package/dist/channels/slack/dispatch.js +3 -3
- package/dist/channels/slack/inbound.d.ts +9 -0
- package/dist/channels/slack/inbound.d.ts.map +1 -1
- package/dist/channels/slack/inbound.js +14 -0
- package/dist/channels/slack/index.d.ts +1 -0
- package/dist/channels/slack/index.d.ts.map +1 -1
- package/dist/channels/slack/index.js +1 -0
- package/dist/channels/slack/live-delivery.d.ts +5 -0
- package/dist/channels/slack/live-delivery.d.ts.map +1 -1
- package/dist/channels/slack/live-delivery.js +107 -19
- package/dist/channels/slack/reasoning-card.d.ts +38 -0
- package/dist/channels/slack/reasoning-card.d.ts.map +1 -0
- package/dist/channels/slack/reasoning-card.js +104 -0
- package/dist/channels/slack/redact.d.ts +2 -0
- package/dist/channels/slack/redact.d.ts.map +1 -0
- package/dist/channels/slack/redact.js +5 -0
- package/dist/channels/slack/reply-options.d.ts +40 -0
- package/dist/channels/slack/reply-options.d.ts.map +1 -0
- package/dist/channels/slack/reply-options.js +150 -0
- package/dist/channels/slack/slack-channel.d.ts.map +1 -1
- package/dist/channels/slack/slack-channel.js +8 -4
- package/dist/channels/slack/stream.d.ts +22 -10
- package/dist/channels/slack/stream.d.ts.map +1 -1
- package/dist/channels/slack/stream.js +9 -16
- package/dist/channels/slack/tool-cards.d.ts +22 -0
- package/dist/channels/slack/tool-cards.d.ts.map +1 -0
- package/dist/channels/slack/tool-cards.js +178 -0
- package/dist/channels/slack/types.d.ts +145 -6
- package/dist/channels/slack/types.d.ts.map +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +6 -6
- package/dist/docs/ab.md +1 -1
- package/dist/docs/assets/{ab.md.DJo5r4R-.js → ab.md.mlVgqvSk.js} +1 -1
- package/dist/docs/assets/{app.BplEAZ3S.js → app.DZ1e0Ycq.js} +1 -1
- package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.js → building-with-agents.md.CUSWxlP_.js} +2 -2
- package/dist/docs/assets/chunks/@localSearchIndexroot.j70vvPL4.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.CHXyv4wP.js → VPLocalSearchBox.l8omwc6D.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BTcsZmjQ.js → theme.JVcD6gel.js} +2 -2
- package/dist/docs/assets/{evals.md.lfJoEVc8.js → evals.md.CPzDAwoH.js} +1 -1
- package/dist/docs/assets/{guides_github.md.Cnh2mL4a.js → guides_github.md.BtPr9GaP.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.js → guides_mcp-oauth.md.Dp6cDP7f.js} +1 -1
- package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.js → guides_opentelemetry.md.BVTXDCRg.js} +2 -2
- package/dist/docs/assets/{guides_slack.md.VDXQV3ja.js → guides_slack.md.9oHPye9o.js} +19 -3
- package/dist/docs/assets/{guides_slack.md.VDXQV3ja.lean.js → guides_slack.md.9oHPye9o.lean.js} +1 -1
- package/dist/docs/assets/hillclimbing.md.CpTGTCle.js +4 -0
- package/dist/docs/assets/{index.md.CVeRUOeZ.js → index.md.Bb4k8kUm.js} +1 -1
- package/dist/docs/assets/{quickstart.md.Nj_LjW_a.js → quickstart.md.DdQOF7Y8.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.DxldvyIB.js → reference_connections.md.BiGoBAk2.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.em43xlY1.js +1 -0
- package/dist/docs/assets/skills_ab.md.CsFNatVx.js +26 -0
- package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +1 -0
- package/dist/docs/assets/skills_create-agent.md.BVoWPcan.js +8 -0
- package/dist/docs/assets/skills_create-agent.md.BVoWPcan.lean.js +1 -0
- package/dist/docs/assets/skills_debug.md.CDbPhHfg.js +1 -0
- package/dist/docs/assets/skills_debug.md.CDbPhHfg.lean.js +1 -0
- package/dist/docs/assets/skills_evals.md.723kpUmA.js +25 -0
- package/dist/docs/assets/skills_evals.md.723kpUmA.lean.js +1 -0
- package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +1 -0
- package/dist/docs/assets/skills_framework-map.md.BTi817yv.lean.js +1 -0
- package/dist/docs/assets/skills_github.md.D0JahM8c.js +16 -0
- package/dist/docs/assets/skills_github.md.D0JahM8c.lean.js +1 -0
- package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.js +7 -0
- package/dist/docs/assets/skills_hillclimb.md.B_zJerxA.lean.js +1 -0
- package/dist/docs/assets/skills_index.md.DKwIxzGg.js +1 -0
- package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +1 -0
- package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.js +18 -0
- package/dist/docs/assets/skills_mcp-auth.md.DGvFP3HE.lean.js +1 -0
- package/dist/docs/assets/skills_otel.md.CgiZryR3.js +8 -0
- package/dist/docs/assets/skills_otel.md.CgiZryR3.lean.js +1 -0
- package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.js +20 -0
- package/dist/docs/assets/skills_setup-slack.md.BBgx8lUz.lean.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.js → troubleshooting.md.Cus_YZga.js} +1 -1
- package/dist/docs/building-with-agents.html +6 -6
- package/dist/docs/building-with-agents.md +14 -11
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +4 -4
- package/dist/docs/evals.html +6 -6
- package/dist/docs/evals.md +1 -1
- 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 +5 -5
- package/dist/docs/guides/github.md +1 -1
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +5 -5
- package/dist/docs/guides/mcp-oauth.md +1 -1
- package/dist/docs/guides/opentelemetry.html +7 -7
- package/dist/docs/guides/opentelemetry.md +2 -2
- package/dist/docs/guides/slack.html +22 -6
- package/dist/docs/guides/slack.md +80 -1
- package/dist/docs/guides/webhooks.html +5 -5
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/hillclimbing.md +5 -5
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +1 -1
- package/dist/docs/llms-full.txt +1041 -30
- package/dist/docs/llms.txt +14 -0
- package/dist/docs/quickstart.html +5 -5
- package/dist/docs/quickstart.md +1 -1
- 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 +4 -4
- package/dist/docs/reference/connections.html +6 -6
- package/dist/docs/reference/connections.md +1 -1
- 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 +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/scaffolding-agents.md +3 -3
- package/dist/docs/skills/ab.html +52 -0
- package/dist/docs/skills/ab.md +50 -0
- package/dist/docs/skills/create-agent.html +34 -0
- package/dist/docs/skills/create-agent.md +160 -0
- package/dist/docs/skills/debug.html +27 -0
- package/dist/docs/skills/debug.md +36 -0
- package/dist/docs/skills/evals.html +51 -0
- package/dist/docs/skills/evals.md +99 -0
- package/dist/docs/skills/framework-map.html +27 -0
- package/dist/docs/skills/framework-map.md +95 -0
- package/dist/docs/skills/github.html +42 -0
- package/dist/docs/skills/github.md +93 -0
- package/dist/docs/skills/hillclimb.html +33 -0
- package/dist/docs/skills/hillclimb.md +55 -0
- package/dist/docs/skills/index.html +27 -0
- package/dist/docs/skills/index.md +21 -0
- package/dist/docs/skills/mcp-auth.html +44 -0
- package/dist/docs/skills/mcp-auth.md +76 -0
- package/dist/docs/skills/otel.html +34 -0
- package/dist/docs/skills/otel.md +48 -0
- package/dist/docs/skills/setup-slack.html +46 -0
- package/dist/docs/skills/setup-slack.md +141 -0
- package/dist/docs/storage.html +4 -4
- package/dist/docs/templates/agentic-owners.html +4 -4
- package/dist/docs/templates/agents-md.html +4 -4
- package/dist/docs/templates/code-wiki.html +4 -4
- package/dist/docs/templates/demo.html +4 -4
- package/dist/docs/templates/pr-autofixer.html +4 -4
- package/dist/docs/templates/security-help.html +4 -4
- package/dist/docs/templates/security-reviewer.html +4 -4
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +1 -1
- package/dist/files-backends/cursor-hosted.d.ts +6 -0
- package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/files-backends/cursor-hosted.js +6 -9
- package/dist/internal/cli-deploy.js +2 -2
- package/dist/internal/conversation-mirror.d.ts.map +1 -1
- package/dist/internal/conversation-mirror.js +3 -4
- package/dist/internal/cursor/hosted-store-secrets.d.ts +15 -0
- package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -0
- package/dist/internal/cursor/hosted-store-secrets.js +48 -0
- package/dist/internal/deploy-client.d.ts +6 -6
- package/dist/internal/deploy-client.js +7 -7
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +11 -1
- package/dist/internal/framework-file-storage.d.ts +12 -5
- package/dist/internal/framework-file-storage.d.ts.map +1 -1
- package/dist/internal/framework-file-storage.js +36 -5
- package/dist/internal/framework-storage-selection.d.ts +12 -12
- package/dist/internal/framework-storage-selection.d.ts.map +1 -1
- package/dist/internal/framework-storage-selection.js +33 -39
- package/dist/internal/session-run-log.d.ts +3 -3
- package/dist/internal/session-run-log.d.ts.map +1 -1
- package/dist/internal/session-run-log.js +6 -7
- package/dist/internal/storage-coordinator.d.ts +0 -6
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +1 -9
- package/dist/playground/assets/index-BszoQDc6.css +1 -0
- package/dist/playground/assets/{index-jzNbJENa.js → index-DVs98vPL.js} +1 -1
- package/dist/playground/index.html +2 -2
- package/dist/storage-backends/cursor-hosted-v2.d.ts +83 -0
- package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -0
- package/dist/storage-backends/cursor-hosted-v2.js +164 -0
- package/dist/storage-backends/cursor-hosted.d.ts +6 -0
- package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
- package/dist/storage-backends/cursor-hosted.js +6 -1
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +1 -1
- package/docs/ab.md +1 -1
- package/docs/building-with-agents.md +14 -11
- package/docs/evals.md +1 -1
- package/docs/guides/github.md +1 -1
- package/docs/guides/mcp-oauth.md +1 -1
- package/docs/guides/opentelemetry.md +2 -2
- package/docs/guides/slack.md +80 -1
- package/docs/hillclimbing.md +5 -5
- package/docs/quickstart.md +1 -1
- package/docs/reference/connections.md +1 -1
- package/docs/scaffolding-agents.md +3 -3
- package/docs/skills/index.md +26 -0
- package/docs/troubleshooting.md +1 -1
- package/package.json +1 -1
- package/src/channels/github/defaults.ts +36 -3
- package/src/channels/github/progress.ts +7 -0
- package/src/channels/slack/api.ts +35 -17
- package/src/channels/slack/constants.ts +6 -0
- package/src/channels/slack/defaults.ts +173 -92
- package/src/channels/slack/dispatch.ts +8 -1
- package/src/channels/slack/inbound.ts +17 -0
- package/src/channels/slack/index.ts +1 -0
- package/src/channels/slack/live-delivery.ts +131 -20
- package/src/channels/slack/reasoning-card.ts +140 -0
- package/src/channels/slack/redact.ts +6 -0
- package/src/channels/slack/reply-options.ts +229 -0
- package/src/channels/slack/slack-channel.ts +7 -2
- package/src/channels/slack/stream.ts +31 -24
- package/src/channels/slack/tool-cards.ts +221 -0
- package/src/channels/slack/types.ts +159 -6
- package/src/files-backends/cursor-hosted.ts +15 -5
- package/src/internal/cli-deploy.ts +2 -2
- package/src/internal/conversation-mirror.ts +3 -8
- package/src/internal/cursor/hosted-store-secrets.ts +72 -0
- package/src/internal/deploy-client.ts +10 -10
- package/src/internal/discovery.ts +9 -1
- package/src/internal/framework-file-storage.ts +41 -5
- package/src/internal/framework-storage-selection.ts +31 -44
- package/src/internal/session-run-log.ts +6 -11
- package/src/internal/storage-coordinator.ts +1 -11
- package/src/storage-backends/cursor-hosted-v2.ts +219 -0
- package/src/storage-backends/cursor-hosted.ts +6 -1
- package/src/types.ts +5 -0
- package/dist/docs/assets/chunks/@localSearchIndexroot.DpuI4i7Z.js +0 -1
- package/dist/docs/assets/hillclimbing.md.DhESf3OO.js +0 -4
- package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +0 -1
- package/dist/internal/null-kv-storage.d.ts +0 -48
- package/dist/internal/null-kv-storage.d.ts.map +0 -1
- package/dist/internal/null-kv-storage.js +0 -58
- package/dist/playground/assets/index-D7rGZNjy.css +0 -1
- package/src/internal/null-kv-storage.ts +0 -74
- /package/dist/docs/assets/{ab.md.DJo5r4R-.lean.js → ab.md.mlVgqvSk.lean.js} +0 -0
- /package/dist/docs/assets/{building-with-agents.md.DI4mEzlt.lean.js → building-with-agents.md.CUSWxlP_.lean.js} +0 -0
- /package/dist/docs/assets/{evals.md.lfJoEVc8.lean.js → evals.md.CPzDAwoH.lean.js} +0 -0
- /package/dist/docs/assets/{guides_github.md.Cnh2mL4a.lean.js → guides_github.md.BtPr9GaP.lean.js} +0 -0
- /package/dist/docs/assets/{guides_mcp-oauth.md.CN-6YmTJ.lean.js → guides_mcp-oauth.md.Dp6cDP7f.lean.js} +0 -0
- /package/dist/docs/assets/{guides_opentelemetry.md.bmPmkvJu.lean.js → guides_opentelemetry.md.BVTXDCRg.lean.js} +0 -0
- /package/dist/docs/assets/{hillclimbing.md.DhESf3OO.lean.js → hillclimbing.md.CpTGTCle.lean.js} +0 -0
- /package/dist/docs/assets/{index.md.CVeRUOeZ.lean.js → index.md.Bb4k8kUm.lean.js} +0 -0
- /package/dist/docs/assets/{quickstart.md.Nj_LjW_a.lean.js → quickstart.md.DdQOF7Y8.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.DxldvyIB.lean.js → reference_connections.md.BiGoBAk2.lean.js} +0 -0
- /package/dist/docs/assets/{scaffolding-agents.md.D7UUkWw0.lean.js → scaffolding-agents.md.em43xlY1.lean.js} +0 -0
- /package/dist/docs/assets/{troubleshooting.md.DCiPBhYs.lean.js → troubleshooting.md.Cus_YZga.lean.js} +0 -0
|
@@ -4,11 +4,36 @@
|
|
|
4
4
|
|
|
5
5
|
export type StreamTaskStatus = "pending" | "in_progress" | "complete" | "error";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* One update to a task card. Slack keeps one card per `id`: `title` and
|
|
9
|
+
* `status` replace the previous values, `details` and `output` are appended
|
|
10
|
+
* to what the card already shows.
|
|
11
|
+
*/
|
|
7
12
|
export interface StreamTaskChunk {
|
|
8
13
|
type: "task_update";
|
|
9
14
|
id: string;
|
|
10
15
|
title: string;
|
|
11
16
|
status: StreamTaskStatus;
|
|
17
|
+
details?: string;
|
|
18
|
+
output?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface StreamMarkdownChunk {
|
|
22
|
+
type: "markdown_text";
|
|
23
|
+
text: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* A `chat.*Stream` chunk. Slack fixes a stream's mode at `chat.startStream`:
|
|
28
|
+
* one opened with bare `markdown_text` rejects every later `chunks` append
|
|
29
|
+
* (`streaming_mode_mismatch`), and vice versa. The live-delivery strategy
|
|
30
|
+
* therefore always speaks chunks, wrapping text as `markdown_text` chunks so
|
|
31
|
+
* tool-step `task_update`s can share the same message.
|
|
32
|
+
*/
|
|
33
|
+
export type StreamChunk = StreamMarkdownChunk | StreamTaskChunk;
|
|
34
|
+
|
|
35
|
+
export function markdownChunk(text: string): StreamMarkdownChunk {
|
|
36
|
+
return { type: "markdown_text", text };
|
|
12
37
|
}
|
|
13
38
|
|
|
14
39
|
/**
|
|
@@ -36,28 +61,10 @@ export function computeStreamAppend(
|
|
|
36
61
|
return "";
|
|
37
62
|
}
|
|
38
63
|
|
|
39
|
-
/**
|
|
40
|
-
export function
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return
|
|
45
|
-
type: "task_update" as const,
|
|
46
|
-
id: call.callId,
|
|
47
|
-
title: call.toolName,
|
|
48
|
-
status,
|
|
49
|
-
}));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function buildTaskChunkForResult(args: {
|
|
53
|
-
callId: string;
|
|
54
|
-
toolName: string;
|
|
55
|
-
isError: boolean;
|
|
56
|
-
}): StreamTaskChunk {
|
|
57
|
-
return {
|
|
58
|
-
type: "task_update",
|
|
59
|
-
id: args.callId,
|
|
60
|
-
title: args.toolName,
|
|
61
|
-
status: args.isError ? "error" : "complete",
|
|
62
|
-
};
|
|
64
|
+
/** Clamp to `max` characters, ending in an ellipsis when cut. */
|
|
65
|
+
export function truncateCardText(text: string, max: number): string {
|
|
66
|
+
if (text.length <= max) {
|
|
67
|
+
return text;
|
|
68
|
+
}
|
|
69
|
+
return `${text.slice(0, max - 1)}…`;
|
|
63
70
|
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task cards for tool calls inside the streamed reply. One card per key:
|
|
3
|
+
* the call id for `per-call`, the tool name for `per-tool`. A card's title
|
|
4
|
+
* counts its calls and its status follows the whole group; with one call
|
|
5
|
+
* per key that reduces to the plain per-call card.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { redactSecretTokens } from "./redact.js";
|
|
9
|
+
import type { ResolvedSlackToolCards } from "./reply-options.js";
|
|
10
|
+
import { type StreamTaskChunk, truncateCardText } from "./stream.js";
|
|
11
|
+
import type {
|
|
12
|
+
SlackChannelState,
|
|
13
|
+
SlackToolCall,
|
|
14
|
+
SlackToolResult,
|
|
15
|
+
ToolCardCount,
|
|
16
|
+
} from "./types.js";
|
|
17
|
+
|
|
18
|
+
/** The argument the playground puts in a built-in tool's header. */
|
|
19
|
+
const TOOL_PRIMARY_ARGS: Readonly<Record<string, readonly string[]>> = {
|
|
20
|
+
grep: ["pattern"],
|
|
21
|
+
glob: ["glob_pattern", "globPattern"],
|
|
22
|
+
read: ["path", "file_path", "target_file"],
|
|
23
|
+
shell: ["command", "cmd"],
|
|
24
|
+
task: ["description", "prompt"],
|
|
25
|
+
};
|
|
26
|
+
/** For other tools: the telling key, if any. */
|
|
27
|
+
const GENERIC_PRIMARY_ARGS = [
|
|
28
|
+
"pattern",
|
|
29
|
+
"query",
|
|
30
|
+
"command",
|
|
31
|
+
"cmd",
|
|
32
|
+
"path",
|
|
33
|
+
"file",
|
|
34
|
+
"file_path",
|
|
35
|
+
"target_file",
|
|
36
|
+
"url",
|
|
37
|
+
"prompt",
|
|
38
|
+
"description",
|
|
39
|
+
"name",
|
|
40
|
+
"message",
|
|
41
|
+
];
|
|
42
|
+
const PATH_ARGS = new Set([
|
|
43
|
+
"path",
|
|
44
|
+
"file",
|
|
45
|
+
"file_path",
|
|
46
|
+
"target_file",
|
|
47
|
+
"target_directory",
|
|
48
|
+
"targetDirectory",
|
|
49
|
+
]);
|
|
50
|
+
const LINE_MAX = 80;
|
|
51
|
+
const JSON_MAX = 120;
|
|
52
|
+
|
|
53
|
+
function oneLine(text: string, max: number): string {
|
|
54
|
+
return truncateCardText(
|
|
55
|
+
redactSecretTokens(text).replace(/\s+/g, " ").trim(),
|
|
56
|
+
max
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Clamp the middle so both ends stay visible; tail-biased to keep filenames. */
|
|
61
|
+
function clampPath(text: string, max: number): string {
|
|
62
|
+
const one = redactSecretTokens(text).replace(/\s+/g, " ").trim();
|
|
63
|
+
if (one.length <= max) {
|
|
64
|
+
return one;
|
|
65
|
+
}
|
|
66
|
+
const budget = max - 1;
|
|
67
|
+
const head = Math.max(1, Math.floor(budget * 0.35));
|
|
68
|
+
const tail = Math.max(1, budget - head);
|
|
69
|
+
return `${one.slice(0, head)}…${one.slice(one.length - tail)}`;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Default tool-card line for a call, matching the playground's tool header:
|
|
74
|
+
* the grep pattern, the glob pattern, the file path, the shell command. Other
|
|
75
|
+
* tools show a lone string argument bare, else compact JSON. No key labels,
|
|
76
|
+
* no knobs like `headLimit`.
|
|
77
|
+
*/
|
|
78
|
+
export function defaultToolCardDetails(
|
|
79
|
+
call: SlackToolCall
|
|
80
|
+
): string | undefined {
|
|
81
|
+
const args = call.args;
|
|
82
|
+
if (args === undefined || args === null) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
if (typeof args === "string") {
|
|
86
|
+
const line = oneLine(args, LINE_MAX);
|
|
87
|
+
return line === "" ? undefined : line;
|
|
88
|
+
}
|
|
89
|
+
if (typeof args !== "object" || Array.isArray(args)) {
|
|
90
|
+
return oneLine(JSON.stringify(args), JSON_MAX);
|
|
91
|
+
}
|
|
92
|
+
const record = args as Record<string, unknown>;
|
|
93
|
+
for (const key of TOOL_PRIMARY_ARGS[call.toolName] ?? GENERIC_PRIMARY_ARGS) {
|
|
94
|
+
const value = record[key];
|
|
95
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
96
|
+
return PATH_ARGS.has(key)
|
|
97
|
+
? clampPath(value, LINE_MAX)
|
|
98
|
+
: oneLine(value, LINE_MAX);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const entries = Object.entries(record);
|
|
102
|
+
if (entries.length === 0) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
const lone = entries.length === 1 ? entries[0]?.[1] : undefined;
|
|
106
|
+
if (typeof lone === "string" && lone.trim() !== "") {
|
|
107
|
+
return oneLine(lone, LINE_MAX);
|
|
108
|
+
}
|
|
109
|
+
return oneLine(JSON.stringify(record), JSON_MAX);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface ToolCards {
|
|
113
|
+
forCalls(
|
|
114
|
+
state: SlackChannelState,
|
|
115
|
+
calls: readonly SlackToolCall[]
|
|
116
|
+
): StreamTaskChunk[];
|
|
117
|
+
forResult(state: SlackChannelState, result: SlackToolResult): StreamTaskChunk;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function tallyFor(state: SlackChannelState, key: string): ToolCardCount {
|
|
121
|
+
if (state.toolCardCounts === undefined) {
|
|
122
|
+
state.toolCardCounts = {};
|
|
123
|
+
}
|
|
124
|
+
const existing = state.toolCardCounts[key];
|
|
125
|
+
if (existing !== undefined) {
|
|
126
|
+
return existing;
|
|
127
|
+
}
|
|
128
|
+
const created: ToolCardCount = { started: 0, done: 0, errors: 0 };
|
|
129
|
+
state.toolCardCounts[key] = created;
|
|
130
|
+
return created;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Slack appends each update's text to the card verbatim, so a group's later
|
|
135
|
+
* batch of lines brings its own line break.
|
|
136
|
+
*/
|
|
137
|
+
function appendLines(
|
|
138
|
+
tally: ToolCardCount,
|
|
139
|
+
field: "details" | "output",
|
|
140
|
+
lines: readonly string[]
|
|
141
|
+
): string | undefined {
|
|
142
|
+
if (lines.length === 0) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
const already = tally[field] ?? 0;
|
|
146
|
+
tally[field] = already + lines.length;
|
|
147
|
+
return `${already > 0 ? "\n" : ""}${lines.join("\n")}`;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function present(line: string | undefined): line is string {
|
|
151
|
+
return line !== undefined && line !== "";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function createToolCards(
|
|
155
|
+
cards: ResolvedSlackToolCards,
|
|
156
|
+
toolLabel: (toolName: string) => string
|
|
157
|
+
): ToolCards {
|
|
158
|
+
const keyOf = (call: { callId: string; toolName: string }): string =>
|
|
159
|
+
cards.group === "per-call" ? call.callId : `tool:${call.toolName}`;
|
|
160
|
+
const title = (toolName: string, started: number): string => {
|
|
161
|
+
const label = toolLabel(toolName);
|
|
162
|
+
return started > 1 ? `${label} ×${started}` : label;
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
forCalls(state, calls) {
|
|
167
|
+
const groups = new Map<string, SlackToolCall[]>();
|
|
168
|
+
for (const call of calls) {
|
|
169
|
+
const key = keyOf(call);
|
|
170
|
+
groups.set(key, [...(groups.get(key) ?? []), call]);
|
|
171
|
+
}
|
|
172
|
+
return [...groups.entries()].map(([key, group]) => {
|
|
173
|
+
const tally = tallyFor(state, key);
|
|
174
|
+
tally.started += group.length;
|
|
175
|
+
const chunk: StreamTaskChunk = {
|
|
176
|
+
type: "task_update",
|
|
177
|
+
id: key,
|
|
178
|
+
title: title(group[0]!.toolName, tally.started),
|
|
179
|
+
status: "in_progress",
|
|
180
|
+
};
|
|
181
|
+
const details = appendLines(
|
|
182
|
+
tally,
|
|
183
|
+
"details",
|
|
184
|
+
group.map((call) => cards.details?.(call)).filter(present)
|
|
185
|
+
);
|
|
186
|
+
if (details !== undefined) {
|
|
187
|
+
chunk.details = details;
|
|
188
|
+
}
|
|
189
|
+
return chunk;
|
|
190
|
+
});
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
forResult(state, result) {
|
|
194
|
+
const tally = tallyFor(state, keyOf(result));
|
|
195
|
+
tally.done += 1;
|
|
196
|
+
if (result.isError) {
|
|
197
|
+
tally.errors += 1;
|
|
198
|
+
}
|
|
199
|
+
const chunk: StreamTaskChunk = {
|
|
200
|
+
type: "task_update",
|
|
201
|
+
id: keyOf(result),
|
|
202
|
+
title: title(result.toolName, tally.started),
|
|
203
|
+
status:
|
|
204
|
+
tally.done < tally.started
|
|
205
|
+
? "in_progress"
|
|
206
|
+
: tally.errors > 0
|
|
207
|
+
? "error"
|
|
208
|
+
: "complete",
|
|
209
|
+
};
|
|
210
|
+
const output = appendLines(
|
|
211
|
+
tally,
|
|
212
|
+
"output",
|
|
213
|
+
[cards.output?.(result)].filter(present)
|
|
214
|
+
);
|
|
215
|
+
if (output !== undefined) {
|
|
216
|
+
chunk.output = output;
|
|
217
|
+
}
|
|
218
|
+
return chunk;
|
|
219
|
+
},
|
|
220
|
+
};
|
|
221
|
+
}
|
|
@@ -79,6 +79,8 @@ export interface SlackChannelState {
|
|
|
79
79
|
* for the rest of the turn.
|
|
80
80
|
*/
|
|
81
81
|
streamingUnavailable?: boolean;
|
|
82
|
+
/** The open stream hit Slack's size cap; appends stop until it closes. */
|
|
83
|
+
streamFull?: boolean;
|
|
82
84
|
/** Editable progress message ts when `chat.startStream` is unavailable. */
|
|
83
85
|
progressTs: string | null;
|
|
84
86
|
/**
|
|
@@ -86,8 +88,151 @@ export interface SlackChannelState {
|
|
|
86
88
|
* replacing Approve/Deny buttons after a decision).
|
|
87
89
|
*/
|
|
88
90
|
approvalMessageByCallId?: Record<string, string>;
|
|
91
|
+
/** `reply.reasoningCard` bookkeeping for the current turn. */
|
|
92
|
+
reasoningCard?: ReasoningCardState;
|
|
93
|
+
/** `reply.toolCards` per-tool tallies for the current turn, keyed by tool name. */
|
|
94
|
+
toolCardCounts?: Record<string, ToolCardCount>;
|
|
89
95
|
}
|
|
90
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Slack appends a task card's `details` across updates, so the reasoning
|
|
99
|
+
* card is fed deltas: `blockSent` is how much of the current reasoning block
|
|
100
|
+
* is already on Slack, `pending` is buffered text awaiting a flush.
|
|
101
|
+
*/
|
|
102
|
+
export interface ReasoningCardState {
|
|
103
|
+
status: "in_progress" | "complete" | null;
|
|
104
|
+
blockSent: number | null;
|
|
105
|
+
pending: string;
|
|
106
|
+
lastFlushMs: number | null;
|
|
107
|
+
chars: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* `details` / `output` count the lines already on the card, so a later
|
|
112
|
+
* batch can start on a new line (Slack appends updates verbatim).
|
|
113
|
+
*/
|
|
114
|
+
export interface ToolCardCount {
|
|
115
|
+
started: number;
|
|
116
|
+
done: number;
|
|
117
|
+
errors: number;
|
|
118
|
+
details?: number;
|
|
119
|
+
output?: number;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/** A tool call as the model requested it (`actions.requested`). */
|
|
123
|
+
export interface SlackToolCall {
|
|
124
|
+
callId: string;
|
|
125
|
+
toolName: string;
|
|
126
|
+
args?: unknown;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** A finished tool call (`action.result`). */
|
|
130
|
+
export interface SlackToolResult {
|
|
131
|
+
callId: string;
|
|
132
|
+
toolName: string;
|
|
133
|
+
output?: unknown;
|
|
134
|
+
isError: boolean;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* What the status chip under the thread shows while a turn runs. Slack caps
|
|
139
|
+
* each line at 50 characters. While a `chat.startStream` is open Slack shows
|
|
140
|
+
* its own generic "is working…" instead, so in `"stream"` mode these lines
|
|
141
|
+
* are only visible until the first chunk goes out.
|
|
142
|
+
*/
|
|
143
|
+
export interface SlackStatusOptions {
|
|
144
|
+
/** First line of each reasoning block, throttled. Defaults to `true`. */
|
|
145
|
+
reasoning?: boolean;
|
|
146
|
+
/**
|
|
147
|
+
* Tool calls as they start: `"Running grep, glob…"` (tool names through
|
|
148
|
+
* {@link SlackChannelOptions.toolLabels}), or your own line. Defaults to
|
|
149
|
+
* `true`.
|
|
150
|
+
*/
|
|
151
|
+
tools?: boolean | ((calls: readonly SlackToolCall[]) => string);
|
|
152
|
+
/**
|
|
153
|
+
* Rotation Slack cycles through while nothing more specific is known
|
|
154
|
+
* (turn start, long silent stretches). Up to 5 entries. Defaults to
|
|
155
|
+
* Thinking… / Working on it… / Almost there….
|
|
156
|
+
*/
|
|
157
|
+
idle?: readonly string[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export type SlackToolCardGroup = "per-call" | "per-tool";
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Task cards for tool calls inside the streamed reply. Slack appends each
|
|
164
|
+
* update's `details` / `output` to the card, so the callbacks return the
|
|
165
|
+
* text to add, not the full card.
|
|
166
|
+
*/
|
|
167
|
+
export interface SlackToolCardOptions {
|
|
168
|
+
/**
|
|
169
|
+
* `"per-tool"` (default) keeps one card per tool name and counts calls in
|
|
170
|
+
* the title (`grep ×3`). `"per-call"` shows one card per call.
|
|
171
|
+
*/
|
|
172
|
+
group?: SlackToolCardGroup;
|
|
173
|
+
/**
|
|
174
|
+
* `true` (default): cards expand to show one line per call, the way the
|
|
175
|
+
* reasoning card does. `false`: cards are their titles only.
|
|
176
|
+
*/
|
|
177
|
+
collapsible?: boolean;
|
|
178
|
+
/**
|
|
179
|
+
* The line a collapsible card shows for a call. Defaults to what the
|
|
180
|
+
* playground shows in that tool's header: the grep pattern, the file
|
|
181
|
+
* path, the shell command.
|
|
182
|
+
*/
|
|
183
|
+
details?: (call: SlackToolCall) => string | undefined;
|
|
184
|
+
/** Text appended to a collapsible card when a call finishes. */
|
|
185
|
+
output?: (result: SlackToolResult) => string | undefined;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* One task card that receives the model's reasoning as it streams. Its
|
|
190
|
+
* status is `in_progress` while the model thinks and `complete` once the
|
|
191
|
+
* answer text starts.
|
|
192
|
+
*/
|
|
193
|
+
export interface SlackReasoningCardOptions {
|
|
194
|
+
/** Card title. Defaults to `"Thinking"`. */
|
|
195
|
+
title?: string;
|
|
196
|
+
/**
|
|
197
|
+
* Stop appending after this many characters. Defaults to 1500: Slack caps
|
|
198
|
+
* a streamed message (answer text plus cards) near 12k, so a long card
|
|
199
|
+
* shortens the answer that fits before the reply spills into a second
|
|
200
|
+
* message.
|
|
201
|
+
*/
|
|
202
|
+
maxChars?: number;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* How the reply reaches the thread while the turn runs.
|
|
207
|
+
*
|
|
208
|
+
* - `"post"` (default): live feedback is the status chip; the answer lands
|
|
209
|
+
* as one message when the turn finishes.
|
|
210
|
+
* - `"stream"`: the answer text streams into one message as it is written.
|
|
211
|
+
* Slack replaces the status chip with its generic "is working…" for the
|
|
212
|
+
* duration, so live feedback inside the message comes from cards.
|
|
213
|
+
*/
|
|
214
|
+
export type SlackReplyOptions =
|
|
215
|
+
| {
|
|
216
|
+
mode: "post";
|
|
217
|
+
status?: SlackStatusOptions;
|
|
218
|
+
}
|
|
219
|
+
| {
|
|
220
|
+
mode: "stream";
|
|
221
|
+
status?: SlackStatusOptions;
|
|
222
|
+
/** Defaults to `false`. `true` is `{ group: "per-tool" }`. */
|
|
223
|
+
toolCards?: boolean | SlackToolCardOptions;
|
|
224
|
+
/** Defaults to `false`. */
|
|
225
|
+
reasoningCard?: boolean | SlackReasoningCardOptions;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Human labels for tool names, shared by the status chip and the cards.
|
|
230
|
+
* A function may return `undefined` to keep the raw tool name.
|
|
231
|
+
*/
|
|
232
|
+
export type SlackToolLabels =
|
|
233
|
+
| Readonly<Record<string, string>>
|
|
234
|
+
| ((toolName: string) => string | undefined);
|
|
235
|
+
|
|
91
236
|
export interface SlackAuthor {
|
|
92
237
|
/** Slack user id. Empty string for bot posts with no `user` field. */
|
|
93
238
|
userId: string;
|
|
@@ -502,13 +647,21 @@ export interface SlackChannelOptions {
|
|
|
502
647
|
*/
|
|
503
648
|
deliverDefaults?: boolean;
|
|
504
649
|
/**
|
|
505
|
-
*
|
|
506
|
-
* `
|
|
650
|
+
* How the reply reaches the thread: status chip + one message at the end
|
|
651
|
+
* (`"post"`, default), or a live-streamed message with optional tool and
|
|
652
|
+
* reasoning cards (`"stream"`). See {@link SlackReplyOptions}.
|
|
653
|
+
*/
|
|
654
|
+
reply?: SlackReplyOptions;
|
|
655
|
+
/** Human labels for tool names in the status chip and cards. */
|
|
656
|
+
toolLabels?: SlackToolLabels;
|
|
657
|
+
/**
|
|
658
|
+
* @deprecated Use `reply: { mode: "stream" }` / `reply: { mode: "post" }`.
|
|
659
|
+
* Ignored when `reply` is set.
|
|
507
660
|
*/
|
|
508
661
|
streaming?: boolean;
|
|
509
662
|
/**
|
|
510
|
-
*
|
|
511
|
-
*
|
|
663
|
+
* @deprecated Use `reply: { mode: "stream", toolCards: true }`. Ignored
|
|
664
|
+
* when `reply` is set.
|
|
512
665
|
*/
|
|
513
666
|
thinkingSteps?: boolean;
|
|
514
667
|
/**
|
|
@@ -556,8 +709,8 @@ export interface SlackChannelOptions {
|
|
|
556
709
|
suggestedPrompts?: SlackSuggestedPrompt[];
|
|
557
710
|
suggestedPromptsTitle?: string;
|
|
558
711
|
/**
|
|
559
|
-
*
|
|
560
|
-
*
|
|
712
|
+
* @deprecated Use `reply: { mode, status: { idle: [...] } }`. Ignored when
|
|
713
|
+
* `reply` is set.
|
|
561
714
|
*/
|
|
562
715
|
loadingMessages?: string[];
|
|
563
716
|
/**
|
|
@@ -51,6 +51,10 @@ import {
|
|
|
51
51
|
type FileSinkEntry,
|
|
52
52
|
type FileSinkPutResult,
|
|
53
53
|
} from "../files.js";
|
|
54
|
+
import {
|
|
55
|
+
resolveDeploymentStoreSourceIdSync,
|
|
56
|
+
resolveFrameworkStoreSourceIdSync,
|
|
57
|
+
} from "../internal/cursor/hosted-store-secrets.js";
|
|
54
58
|
import { createAgentStorePresignedUrlValidatorForBackend } from "./agent-store-presigned-url.js";
|
|
55
59
|
|
|
56
60
|
/**
|
|
@@ -111,8 +115,7 @@ const MAX_LIST_WALK_PAGES = 1_000;
|
|
|
111
115
|
export function isCursorHostedFilesAvailable(
|
|
112
116
|
env: NodeJS.ProcessEnv = process.env
|
|
113
117
|
): boolean {
|
|
114
|
-
|
|
115
|
-
return sourceId !== undefined && sourceId !== "";
|
|
118
|
+
return resolveDeploymentStoreSourceIdSync(env) !== undefined;
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
/**
|
|
@@ -125,8 +128,7 @@ export function isCursorHostedFilesAvailable(
|
|
|
125
128
|
export function cursorFrameworkStoreSourceId(
|
|
126
129
|
env: NodeJS.ProcessEnv = process.env
|
|
127
130
|
): string | undefined {
|
|
128
|
-
|
|
129
|
-
return sourceId === undefined || sourceId === "" ? undefined : sourceId;
|
|
131
|
+
return resolveFrameworkStoreSourceIdSync(env);
|
|
130
132
|
}
|
|
131
133
|
|
|
132
134
|
/**
|
|
@@ -164,6 +166,12 @@ export interface CursorHostedFilesOptions {
|
|
|
164
166
|
resolveApiKey?: () => string | undefined;
|
|
165
167
|
/** File store to address (default: `AGENT_SERVE_STORE_SOURCE_ID`). */
|
|
166
168
|
storeSourceId?: string;
|
|
169
|
+
/**
|
|
170
|
+
* Lazy store source id, re-resolved on every call and preferred over
|
|
171
|
+
* {@link storeSourceId} — freeze bind drops ids into `/run/cursor/secrets`
|
|
172
|
+
* after serve start without restarting July.
|
|
173
|
+
*/
|
|
174
|
+
resolveStoreSourceId?: () => string | undefined;
|
|
167
175
|
/** Test seam; defaults to global fetch. */
|
|
168
176
|
fetch?: typeof fetch;
|
|
169
177
|
}
|
|
@@ -650,7 +658,9 @@ function fetchImpl(options: CursorHostedFilesOptions): typeof fetch {
|
|
|
650
658
|
*/
|
|
651
659
|
function resolveStoreSourceId(options: CursorHostedFilesOptions): string {
|
|
652
660
|
const id = (
|
|
653
|
-
options.
|
|
661
|
+
options.resolveStoreSourceId?.() ??
|
|
662
|
+
options.storeSourceId ??
|
|
663
|
+
resolveDeploymentStoreSourceIdSync(process.env)
|
|
654
664
|
)?.trim();
|
|
655
665
|
if (id === undefined || id === "") {
|
|
656
666
|
throw new Error(
|
|
@@ -958,7 +958,7 @@ async function deployAgentsdkApplication(
|
|
|
958
958
|
}
|
|
959
959
|
|
|
960
960
|
/**
|
|
961
|
-
* `architecture: "v2"` deploy: POST `/internal/
|
|
961
|
+
* `architecture: "v2"` deploy: POST `/internal/agentsdk/deployments` and
|
|
962
962
|
* poll the matching GET. The v2 accept path starts freeze bake; it does
|
|
963
963
|
* not mint an engine alias or alias token.
|
|
964
964
|
*/
|
|
@@ -1478,7 +1478,7 @@ export async function cmdStop(
|
|
|
1478
1478
|
// deploy). The v2 agentsdk control plane goes first: v1 endpoints refuse
|
|
1479
1479
|
// `architecture: "v2"` slugs with a 409 rather than a 404, so v1-first
|
|
1480
1480
|
// could not fall through. A v2 404 (including an older backend without
|
|
1481
|
-
// the `/internal/
|
|
1481
|
+
// the `/internal/agentsdk` mount) falls back to the v1 stop.
|
|
1482
1482
|
let architecture: "v1" | "v2" = "v2";
|
|
1483
1483
|
let accepted: StopAccepted | AgentkitStopAccepted;
|
|
1484
1484
|
try {
|
|
@@ -383,18 +383,13 @@ export function selectConversationMirror(input: {
|
|
|
383
383
|
return undefined;
|
|
384
384
|
}
|
|
385
385
|
const env = input.env ?? process.env;
|
|
386
|
-
|
|
387
|
-
env as NodeJS.ProcessEnv
|
|
388
|
-
);
|
|
389
|
-
if (
|
|
390
|
-
env[AGENT_SERVE_GENERATION_ENV_VAR] === undefined ||
|
|
391
|
-
frameworkStoreId === undefined
|
|
392
|
-
) {
|
|
386
|
+
if (env[AGENT_SERVE_GENERATION_ENV_VAR] === undefined) {
|
|
393
387
|
return undefined;
|
|
394
388
|
}
|
|
389
|
+
const envSnapshot = env as NodeJS.ProcessEnv;
|
|
395
390
|
return createConversationMirror({
|
|
396
391
|
sink: cursorHostedFiles({
|
|
397
|
-
|
|
392
|
+
resolveStoreSourceId: () => cursorFrameworkStoreSourceId(envSnapshot),
|
|
398
393
|
// Full chain (env → key file → stored login): frozen engines listen
|
|
399
394
|
// unsigned and bind CURSOR_API_KEY_FILE at task time, after this sink
|
|
400
395
|
// is constructed.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task-time bind paths for hosted deployment file-store source ids.
|
|
3
|
+
*
|
|
4
|
+
* Freeze v2 snapshots start `agent-serve serve` at bake time without a service
|
|
5
|
+
* account, so neither store id is in process env. Execute-from-freeze binds
|
|
6
|
+
* the deployment credential and store ids into `/run/cursor/secrets/` without
|
|
7
|
+
* restarting July — the same pattern as {@link DEFAULT_CURSOR_API_KEY_FILE}.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
|
|
12
|
+
export const DEFAULT_AGENT_SERVE_STORE_SOURCE_ID_FILE =
|
|
13
|
+
"/run/cursor/secrets/AGENT_SERVE_STORE_SOURCE_ID";
|
|
14
|
+
|
|
15
|
+
export const DEFAULT_AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID_FILE =
|
|
16
|
+
"/run/cursor/secrets/AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID";
|
|
17
|
+
|
|
18
|
+
const STORE_SOURCE_ID_ENV = "AGENT_SERVE_STORE_SOURCE_ID";
|
|
19
|
+
const FRAMEWORK_STORE_SOURCE_ID_ENV = "AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID";
|
|
20
|
+
const STORE_SOURCE_ID_FILE_ENV = "AGENT_SERVE_STORE_SOURCE_ID_FILE";
|
|
21
|
+
const FRAMEWORK_STORE_SOURCE_ID_FILE_ENV =
|
|
22
|
+
"AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID_FILE";
|
|
23
|
+
|
|
24
|
+
function readTrimmedFile(path: string): string | undefined {
|
|
25
|
+
try {
|
|
26
|
+
const raw = readFileSync(path, "utf8").trim();
|
|
27
|
+
return raw === "" ? undefined : raw;
|
|
28
|
+
} catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function readBoundSecretFile(
|
|
34
|
+
fileEnvVar: string,
|
|
35
|
+
defaultPath: string,
|
|
36
|
+
env: NodeJS.ProcessEnv
|
|
37
|
+
): string | undefined {
|
|
38
|
+
const configured = env[fileEnvVar]?.trim();
|
|
39
|
+
const path =
|
|
40
|
+
configured !== undefined && configured !== "" ? configured : defaultPath;
|
|
41
|
+
return readTrimmedFile(path);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Deployment user-land store: env, then task-bind file. */
|
|
45
|
+
export function resolveDeploymentStoreSourceIdSync(
|
|
46
|
+
env: NodeJS.ProcessEnv = process.env
|
|
47
|
+
): string | undefined {
|
|
48
|
+
const fromEnv = env[STORE_SOURCE_ID_ENV]?.trim();
|
|
49
|
+
if (fromEnv !== undefined && fromEnv !== "") {
|
|
50
|
+
return fromEnv;
|
|
51
|
+
}
|
|
52
|
+
return readBoundSecretFile(
|
|
53
|
+
STORE_SOURCE_ID_FILE_ENV,
|
|
54
|
+
DEFAULT_AGENT_SERVE_STORE_SOURCE_ID_FILE,
|
|
55
|
+
env
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Engine framework store: env, then task-bind file. */
|
|
60
|
+
export function resolveFrameworkStoreSourceIdSync(
|
|
61
|
+
env: NodeJS.ProcessEnv = process.env
|
|
62
|
+
): string | undefined {
|
|
63
|
+
const fromEnv = env[FRAMEWORK_STORE_SOURCE_ID_ENV]?.trim();
|
|
64
|
+
if (fromEnv !== undefined && fromEnv !== "") {
|
|
65
|
+
return fromEnv;
|
|
66
|
+
}
|
|
67
|
+
return readBoundSecretFile(
|
|
68
|
+
FRAMEWORK_STORE_SOURCE_ID_FILE_ENV,
|
|
69
|
+
DEFAULT_AGENT_SERVE_FRAMEWORK_STORE_SOURCE_ID_FILE,
|
|
70
|
+
env
|
|
71
|
+
);
|
|
72
|
+
}
|