@stigmer/runner 3.12.4 → 3.12.5
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/.build-fingerprint +1 -1
- package/dist/activities/execute-cursor/cursor-mcp-config.d.ts +45 -0
- package/dist/activities/execute-cursor/cursor-mcp-config.js +76 -0
- package/dist/activities/execute-cursor/cursor-mcp-config.js.map +1 -0
- package/dist/activities/execute-cursor/index.d.ts +10 -1
- package/dist/activities/execute-cursor/index.js +47 -29
- package/dist/activities/execute-cursor/index.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +13 -2
- package/dist/activities/execute-cursor/prompt-builder.js +11 -0
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/session-lifecycle.d.ts +1 -1
- package/dist/activities/execute-cursor/skill-resolver.d.ts +2 -21
- package/dist/activities/execute-cursor/skill-resolver.js +5 -108
- package/dist/activities/execute-cursor/skill-resolver.js.map +1 -1
- package/dist/activities/execute-deep-agent/approval-file-change.d.ts +9 -0
- package/dist/activities/execute-deep-agent/approval-file-change.js +2 -1
- package/dist/activities/execute-deep-agent/approval-file-change.js.map +1 -1
- package/dist/activities/execute-deep-agent/cas-capture-backend.d.ts +18 -1
- package/dist/activities/execute-deep-agent/cas-capture-backend.js +20 -3
- package/dist/activities/execute-deep-agent/cas-capture-backend.js.map +1 -1
- package/dist/activities/execute-deep-agent/index.js +57 -5
- package/dist/activities/execute-deep-agent/index.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +9 -0
- package/dist/activities/execute-deep-agent/prompt-builder.js +10 -0
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/setup.js +17 -16
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.js +17 -11
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/middleware/path-normalization.d.ts +49 -49
- package/dist/middleware/path-normalization.js +73 -84
- package/dist/middleware/path-normalization.js.map +1 -1
- package/dist/middleware/types.d.ts +3 -3
- package/dist/runner-manager.d.ts +1 -1
- package/dist/runner-manager.js +22 -15
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.js +11 -0
- package/dist/runner.js.map +1 -1
- package/dist/shared/args-preview.d.ts +8 -0
- package/dist/shared/args-preview.js +14 -3
- package/dist/shared/args-preview.js.map +1 -1
- package/dist/shared/artifact-storage.d.ts +11 -1
- package/dist/shared/artifact-storage.js +10 -1
- package/dist/shared/artifact-storage.js.map +1 -1
- package/dist/shared/declared-preferences.d.ts +47 -0
- package/dist/shared/declared-preferences.js +64 -0
- package/dist/shared/declared-preferences.js.map +1 -0
- package/dist/shared/mcp-enabled-tools.d.ts +2 -3
- package/dist/shared/mcp-enabled-tools.js +2 -3
- package/dist/shared/mcp-enabled-tools.js.map +1 -1
- package/dist/shared/mcp-resolver.d.ts +20 -15
- package/dist/shared/mcp-resolver.js +11 -12
- package/dist/shared/mcp-resolver.js.map +1 -1
- package/dist/shared/placeholder-resolver.d.ts +9 -2
- package/dist/shared/placeholder-resolver.js +9 -2
- package/dist/shared/placeholder-resolver.js.map +1 -1
- package/dist/shared/plan-mode-permissions.d.ts +26 -46
- package/dist/shared/plan-mode-permissions.js +27 -55
- package/dist/shared/plan-mode-permissions.js.map +1 -1
- package/dist/shared/skill-mount.d.ts +89 -0
- package/dist/shared/skill-mount.js +142 -0
- package/dist/shared/skill-mount.js.map +1 -0
- package/dist/shared/skill-writer.d.ts +28 -26
- package/dist/shared/skill-writer.js +79 -102
- package/dist/shared/skill-writer.js.map +1 -1
- package/dist/shared/worker-shutdown.d.ts +67 -0
- package/dist/shared/worker-shutdown.js +79 -0
- package/dist/shared/worker-shutdown.js.map +1 -0
- package/dist/shared/workspace/types.d.ts +3 -2
- package/dist/workflow-engine/loader.js +38 -1
- package/dist/workflow-engine/loader.js.map +1 -1
- package/dist/workflow-engine/tasks/human-input.js +23 -2
- package/dist/workflow-engine/tasks/human-input.js.map +1 -1
- package/package.json +15 -11
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +50 -0
- package/src/activities/execute-cursor/__tests__/cursor-mcp-config.test.ts +111 -0
- package/src/activities/execute-cursor/__tests__/skill-resolver.test.ts +3 -94
- package/src/activities/execute-cursor/cursor-mcp-config.ts +107 -0
- package/src/activities/execute-cursor/index.ts +63 -35
- package/src/activities/execute-cursor/prompt-builder.ts +29 -2
- package/src/activities/execute-cursor/session-lifecycle.ts +1 -1
- package/src/activities/execute-cursor/skill-resolver.ts +10 -137
- package/src/activities/execute-deep-agent/__tests__/approval-file-change.test.ts +15 -0
- package/src/activities/execute-deep-agent/__tests__/cas-capture-backend.test.ts +75 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/index.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +42 -29
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +52 -0
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +1 -0
- package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +11 -8
- package/src/activities/execute-deep-agent/approval-file-change.ts +11 -1
- package/src/activities/execute-deep-agent/cas-capture-backend.ts +20 -3
- package/src/activities/execute-deep-agent/index.ts +57 -5
- package/src/activities/execute-deep-agent/prompt-builder.ts +22 -0
- package/src/activities/execute-deep-agent/setup.ts +21 -19
- package/src/activities/execute-deep-agent/subagent-transformer.ts +19 -12
- package/src/activities/execute-deep-agent/subagent-wiring.ts +3 -3
- package/src/index.ts +1 -1
- package/src/middleware/__tests__/path-normalization.test.ts +32 -32
- package/src/middleware/path-normalization.ts +78 -90
- package/src/middleware/types.ts +3 -3
- package/src/runner-manager.ts +26 -16
- package/src/runner.ts +14 -0
- package/src/shared/__tests__/artifact-storage.test.ts +28 -0
- package/src/shared/__tests__/bedrock-seam.test.ts +5 -5
- package/src/shared/__tests__/declared-preferences.test.ts +109 -0
- package/src/shared/__tests__/foundry-seam.test.ts +5 -5
- package/src/shared/__tests__/plan-mode-permissions.test.ts +15 -44
- package/src/shared/__tests__/skill-mount.test.ts +238 -0
- package/src/shared/__tests__/skill-writer.test.ts +151 -128
- package/src/shared/__tests__/vertex-adapter.test.ts +30 -3
- package/src/shared/__tests__/vertex-seam.test.ts +5 -5
- package/src/shared/__tests__/worker-shutdown.test.ts +101 -0
- package/src/shared/args-preview.ts +17 -3
- package/src/shared/artifact-storage.ts +20 -1
- package/src/shared/declared-preferences.ts +84 -0
- package/src/shared/mcp-enabled-tools.ts +2 -3
- package/src/shared/mcp-resolver.ts +20 -20
- package/src/shared/placeholder-resolver.ts +9 -2
- package/src/shared/plan-mode-permissions.ts +27 -58
- package/src/shared/skill-mount.ts +179 -0
- package/src/shared/skill-writer.ts +96 -130
- package/src/shared/worker-shutdown.ts +99 -0
- package/src/shared/workspace/types.ts +3 -2
- package/src/workflow-engine/__tests__/loader.test.ts +51 -0
- package/src/workflow-engine/__tests__/tasks/human-input.test.ts +117 -0
- package/src/workflow-engine/loader.ts +46 -1
- package/src/workflow-engine/tasks/human-input.ts +33 -5
- package/dist/activities/execute-cursor/connect-backfill.d.ts +0 -19
- package/dist/activities/execute-cursor/connect-backfill.js +0 -27
- package/dist/activities/execute-cursor/connect-backfill.js.map +0 -1
- package/dist/activities/execute-cursor/mcp-resolver.d.ts +0 -120
- package/dist/activities/execute-cursor/mcp-resolver.js +0 -194
- package/dist/activities/execute-cursor/mcp-resolver.js.map +0 -1
- package/dist/activities/execute-cursor/placeholder-resolver.d.ts +0 -34
- package/dist/activities/execute-cursor/placeholder-resolver.js +0 -82
- package/dist/activities/execute-cursor/placeholder-resolver.js.map +0 -1
- package/src/activities/execute-cursor/__tests__/mcp-resolver.test.ts +0 -125
- package/src/activities/execute-cursor/connect-backfill.ts +0 -52
- package/src/activities/execute-cursor/mcp-resolver.ts +0 -324
- package/src/activities/execute-cursor/placeholder-resolver.ts +0 -109
package/dist/.build-fingerprint
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"hash":"
|
|
1
|
+
{"hash":"e77d58b2bc3277e6","builtAt":"2026-08-15T12:57:42.305Z","fileCount":298}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Cursor harness's MCP output adapter: maps the shared resolver's
|
|
3
|
+
* {@link ResolvedMcpServer} servers into the Cursor SDK's mcpServers config
|
|
4
|
+
* for Agent.create(), plus the harness's env pre-flight check.
|
|
5
|
+
*
|
|
6
|
+
* Resolution itself lives in shared/mcp-resolver.ts (oss#387 consolidated the
|
|
7
|
+
* near-duplicate resolver this file used to carry) — this module is the
|
|
8
|
+
* symmetric twin of the deep-agent harness's toMcpClientConfig in
|
|
9
|
+
* shared/mcp-manager.ts: both consume the identical intermediate, only the
|
|
10
|
+
* final SDK serialization differs.
|
|
11
|
+
*/
|
|
12
|
+
import type { McpServerUsage } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
|
|
13
|
+
import type { ResolvedMcpServer } from "../../shared/mcp-resolver.js";
|
|
14
|
+
/**
|
|
15
|
+
* Cursor SDK MCP server config shape (matches @cursor/sdk McpServerConfig).
|
|
16
|
+
* Defined here to avoid tight coupling to the SDK's internal types.
|
|
17
|
+
*/
|
|
18
|
+
export type CursorMcpServerConfig = {
|
|
19
|
+
type?: "stdio";
|
|
20
|
+
command: string;
|
|
21
|
+
args?: string[];
|
|
22
|
+
env?: Record<string, string>;
|
|
23
|
+
cwd?: string;
|
|
24
|
+
} | {
|
|
25
|
+
type?: "http" | "sse";
|
|
26
|
+
url: string;
|
|
27
|
+
headers?: Record<string, string>;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Transform resolved MCP servers into the Cursor SDK's mcpServers config
|
|
31
|
+
* for Agent.create().
|
|
32
|
+
*
|
|
33
|
+
* Call it ONCE, after the last mutation of the resolved-server list (backfill,
|
|
34
|
+
* synthesized-attachment injection): the config is a projection of that list,
|
|
35
|
+
* and building it early just creates a stale copy someone must remember to
|
|
36
|
+
* rebuild. The Cursor SDK config cannot hide tools, so enabledTools is NOT
|
|
37
|
+
* expressed here — the HITL hook enforces it (see ResolvedMcpServer.enabledTools).
|
|
38
|
+
*/
|
|
39
|
+
export declare function toCursorMcpConfig(servers: ResolvedMcpServer[]): Record<string, CursorMcpServerConfig>;
|
|
40
|
+
/**
|
|
41
|
+
* Validate that resolved MCP servers have their required env vars populated.
|
|
42
|
+
* Returns a list of warnings for servers with empty/missing env.
|
|
43
|
+
* Used as a pre-flight check before agent.send() to surface config issues early.
|
|
44
|
+
*/
|
|
45
|
+
export declare function validateMcpServerEnv(servers: ResolvedMcpServer[], usages: McpServerUsage[]): string[];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Cursor harness's MCP output adapter: maps the shared resolver's
|
|
3
|
+
* {@link ResolvedMcpServer} servers into the Cursor SDK's mcpServers config
|
|
4
|
+
* for Agent.create(), plus the harness's env pre-flight check.
|
|
5
|
+
*
|
|
6
|
+
* Resolution itself lives in shared/mcp-resolver.ts (oss#387 consolidated the
|
|
7
|
+
* near-duplicate resolver this file used to carry) — this module is the
|
|
8
|
+
* symmetric twin of the deep-agent harness's toMcpClientConfig in
|
|
9
|
+
* shared/mcp-manager.ts: both consume the identical intermediate, only the
|
|
10
|
+
* final SDK serialization differs.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Transform resolved MCP servers into the Cursor SDK's mcpServers config
|
|
14
|
+
* for Agent.create().
|
|
15
|
+
*
|
|
16
|
+
* Call it ONCE, after the last mutation of the resolved-server list (backfill,
|
|
17
|
+
* synthesized-attachment injection): the config is a projection of that list,
|
|
18
|
+
* and building it early just creates a stale copy someone must remember to
|
|
19
|
+
* rebuild. The Cursor SDK config cannot hide tools, so enabledTools is NOT
|
|
20
|
+
* expressed here — the HITL hook enforces it (see ResolvedMcpServer.enabledTools).
|
|
21
|
+
*/
|
|
22
|
+
export function toCursorMcpConfig(servers) {
|
|
23
|
+
const result = {};
|
|
24
|
+
for (const server of servers) {
|
|
25
|
+
if (server.connectionType === "stdio") {
|
|
26
|
+
if (!server.command)
|
|
27
|
+
continue;
|
|
28
|
+
result[server.slug] = {
|
|
29
|
+
type: "stdio",
|
|
30
|
+
command: server.command,
|
|
31
|
+
args: server.args,
|
|
32
|
+
env: server.env,
|
|
33
|
+
cwd: server.cwd,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
if (!server.url)
|
|
38
|
+
continue;
|
|
39
|
+
result[server.slug] = {
|
|
40
|
+
type: server.connectionType,
|
|
41
|
+
url: server.url,
|
|
42
|
+
headers: server.headers,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Validate that resolved MCP servers have their required env vars populated.
|
|
50
|
+
* Returns a list of warnings for servers with empty/missing env.
|
|
51
|
+
* Used as a pre-flight check before agent.send() to surface config issues early.
|
|
52
|
+
*/
|
|
53
|
+
export function validateMcpServerEnv(servers, usages) {
|
|
54
|
+
const warnings = [];
|
|
55
|
+
for (const usage of usages) {
|
|
56
|
+
const slug = usage.mcpServerRef?.slug;
|
|
57
|
+
if (!slug)
|
|
58
|
+
continue;
|
|
59
|
+
const resolved = servers.find((s) => s.slug === slug);
|
|
60
|
+
if (!resolved) {
|
|
61
|
+
warnings.push(`MCP server '${slug}': failed to resolve (server may not exist or is inaccessible)`);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (resolved.connectionType === "stdio" && resolved.env) {
|
|
65
|
+
const emptyKeys = Object.entries(resolved.env)
|
|
66
|
+
.filter(([, v]) => !v)
|
|
67
|
+
.map(([k]) => k);
|
|
68
|
+
if (emptyKeys.length > 0) {
|
|
69
|
+
warnings.push(`MCP server '${slug}': env vars [${emptyKeys.join(", ")}] are empty — ` +
|
|
70
|
+
`server subprocess will likely fail to connect`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return warnings;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=cursor-mcp-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-mcp-config.js","sourceRoot":"","sources":["../../../src/activities/execute-cursor/cursor-mcp-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAuBH;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAA4B;IAE5B,MAAM,MAAM,GAA0C,EAAE,CAAC;IAEzD,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,cAAc,KAAK,OAAO,EAAE,CAAC;YACtC,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,SAAS;YAC9B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;gBACpB,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,GAAG,EAAE,MAAM,CAAC,GAAG;aAChB,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,GAAG;gBAAE,SAAS;YAC1B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;gBACpB,IAAI,EAAE,MAAM,CAAC,cAAc;gBAC3B,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAA4B,EAC5B,MAAwB;IAExB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,EAAE,IAAI,CAAC;QACtC,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,CAAC,IAAI,CAAC,eAAe,IAAI,gEAAgE,CAAC,CAAC;YACnG,SAAS;QACX,CAAC;QAED,IAAI,QAAQ,CAAC,cAAc,KAAK,OAAO,IAAI,QAAQ,CAAC,GAAG,EAAE,CAAC;YACxD,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;iBAC3C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;iBACrB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;YACnB,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzB,QAAQ,CAAC,IAAI,CACX,eAAe,IAAI,gBAAgB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB;oBACvE,+CAA+C,CAChD,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -99,10 +99,19 @@ export interface BuildPromptInput {
|
|
|
99
99
|
* turn.
|
|
100
100
|
*/
|
|
101
101
|
sessionContext?: string;
|
|
102
|
+
/**
|
|
103
|
+
* Platform-declared standing preferences from the execution spec's
|
|
104
|
+
* `declared_preferences` (stigmer/stigmer#293). Like the bridge, only
|
|
105
|
+
* the enhanced-prompt path consumes it — deliberately frozen per Cursor
|
|
106
|
+
* session (DD-002 D3): the first turn delivers it into the agent's own
|
|
107
|
+
* conversation store, and repeating it on resumed turns would bloat the
|
|
108
|
+
* store with identical content.
|
|
109
|
+
*/
|
|
110
|
+
declaredPreferences?: import("../../shared/declared-preferences.js").DeclaredPreferencesContent;
|
|
102
111
|
/**
|
|
103
112
|
* Conversation catchup from the execution spec's `conversation_catchup`
|
|
104
113
|
* (cloud DD-006): what happened on the channel conversation that the
|
|
105
|
-
* agent has not seen. PER-TURN, so unlike the
|
|
114
|
+
* agent has not seen. PER-TURN, so unlike the standing values
|
|
106
115
|
* above it rides BOTH prompt paths — the enhanced prompt and a resumed
|
|
107
116
|
* turn's prefix (the `interaction_mode` shape). Handback lands
|
|
108
117
|
* mid-session on a resumed agent: the resumed path is the one that
|
|
@@ -45,6 +45,7 @@ import { readConversationCatchup } from "../../shared/conversation-catchup.js";
|
|
|
45
45
|
import { readSenderIdentity } from "../../shared/sender-identity.js";
|
|
46
46
|
import { injectCallerIdentityEnv, resolveCallerIdentity, } from "../../shared/caller-identity.js";
|
|
47
47
|
import { readSessionContext } from "../../shared/session-context.js";
|
|
48
|
+
import { readDeclaredPreferences } from "../../shared/declared-preferences.js";
|
|
48
49
|
import { withholdSecretContentFromMessages } from "../../shared/tool-row.js";
|
|
49
50
|
import { StallTimeoutError, formatStallFailure } from "../../shared/stall-watchdog.js";
|
|
50
51
|
import { resolveUsableArtifactStorage, loadArtifactStorageConfig } from "../../shared/artifact-storage.js";
|
|
@@ -55,7 +56,8 @@ import { DeltaEnricher } from "./delta-enricher.js";
|
|
|
55
56
|
import { TodoTracker } from "./todo-tracker.js";
|
|
56
57
|
import { StreamingUpdateScheduler, loadStreamingConfig } from "../../shared/streaming-scheduler.js";
|
|
57
58
|
import { createCursorEventRecorder } from "./cursor-event-recorder.js";
|
|
58
|
-
import { resolveMcpServers
|
|
59
|
+
import { resolveMcpServers } from "../../shared/mcp-resolver.js";
|
|
60
|
+
import { toCursorMcpConfig, validateMcpServerEnv } from "./cursor-mcp-config.js";
|
|
59
61
|
import { resolveMcpTransportPosture } from "../../shared/mcp-transport-guard.js";
|
|
60
62
|
import { discoverChannelMessaging, synthesizeChannelAttachment, } from "../../shared/channel-attachment.js";
|
|
61
63
|
import { readChannelConversationId, synthesizeConversationAttachment, } from "../../shared/conversation-attachment.js";
|
|
@@ -63,7 +65,7 @@ import { injectSynthesizedAttachment } from "../../shared/synthesized-attachment
|
|
|
63
65
|
import { mergeApprovalPolicies } from "./approval-policy.js";
|
|
64
66
|
import { deriveActiveLeases, isUnattendedApprovalMode } from "../../shared/approval-policy.js";
|
|
65
67
|
import { enabledToolsBySlug } from "../../shared/mcp-enabled-tools.js";
|
|
66
|
-
import { backfillMcpServersIfNeeded } from "
|
|
68
|
+
import { backfillMcpServersIfNeeded } from "../../shared/connect-backfill.js";
|
|
67
69
|
import { resolveExecutionEnv } from "./env-resolver.js";
|
|
68
70
|
import { resolveBlueprint } from "./blueprint-resolver.js";
|
|
69
71
|
import { buildCursorSubAgentDefinitions } from "./subagent-config.js";
|
|
@@ -103,7 +105,7 @@ import { synthesizeError, formatClassifiedError, shouldRetryWithFreshAgent, extr
|
|
|
103
105
|
import { createAgent, createCloudAgent } from "./session-lifecycle.js";
|
|
104
106
|
import { setMaxListeners } from "node:events";
|
|
105
107
|
import { startHeartbeat } from "../../shared/heartbeat.js";
|
|
106
|
-
import { getShutdownSignalForQueue } from "../../
|
|
108
|
+
import { classifyTurnInterruption, getShutdownSignalForQueue } from "../../shared/worker-shutdown.js";
|
|
107
109
|
/**
|
|
108
110
|
* Creates the activity functions bound to the runner config.
|
|
109
111
|
* Returned object is passed to Temporal Worker.create({ activities }).
|
|
@@ -526,12 +528,15 @@ turnSeq) {
|
|
|
526
528
|
await reportSetupProgress(client, executionId, "Resolving MCP servers");
|
|
527
529
|
const transportPosture = resolveMcpTransportPosture(config.mode);
|
|
528
530
|
const mcpEnvVars = injectCallerIdentityEnv(envVars, resolveCallerIdentity(blueprint.sessionSpec.metadata, session.status?.audit?.specAudit?.createdBy), sessionId);
|
|
529
|
-
|
|
531
|
+
// The resolved-server list mutates through backfill and attachment
|
|
532
|
+
// injection below; the Cursor SDK config is projected from it exactly
|
|
533
|
+
// once, after the last mutation (see toCursorMcpConfig).
|
|
534
|
+
let resolvedMcpServers = (await resolveMcpServers(client, blueprint.mergedMcpServerUsages, mcpEnvVars, transportPosture)).resolvedServers;
|
|
530
535
|
setupTiming.mark("resolve_mcp_servers");
|
|
531
536
|
// Phase 4a: Connect backfill for undiscovered MCP servers
|
|
532
537
|
heartbeatPhase = "resolving_mcp_servers";
|
|
533
538
|
const sessionOrg = session.metadata?.org ?? "";
|
|
534
|
-
|
|
539
|
+
resolvedMcpServers = await backfillMcpServersIfNeeded(client, resolvedMcpServers, blueprint.mergedMcpServerUsages, mcpEnvVars, sessionOrg, transportPosture, heartbeat, secretKeys);
|
|
535
540
|
setupTiming.mark("backfill_mcp");
|
|
536
541
|
// The synthesized attachments' credential story (DD-006 D4): the
|
|
537
542
|
// exchanged token authenticates the discovery reads per-call (a
|
|
@@ -574,11 +579,7 @@ turnSeq) {
|
|
|
574
579
|
backendEndpoint: config.stigmerBackendEndpoint,
|
|
575
580
|
});
|
|
576
581
|
if (attachment) {
|
|
577
|
-
|
|
578
|
-
mcpResolution = {
|
|
579
|
-
resolvedServers,
|
|
580
|
-
cursorConfig: toCursorMcpConfig(resolvedServers),
|
|
581
|
-
};
|
|
582
|
+
resolvedMcpServers = injectSynthesizedAttachment(resolvedMcpServers, attachment, "channel messaging");
|
|
582
583
|
}
|
|
583
584
|
}
|
|
584
585
|
// Phase 4a4: Synthesize the conversation participation attachment
|
|
@@ -594,13 +595,11 @@ turnSeq) {
|
|
|
594
595
|
backendEndpoint: config.stigmerBackendEndpoint,
|
|
595
596
|
});
|
|
596
597
|
if (conversationAttachment) {
|
|
597
|
-
|
|
598
|
-
mcpResolution = {
|
|
599
|
-
resolvedServers,
|
|
600
|
-
cursorConfig: toCursorMcpConfig(resolvedServers),
|
|
601
|
-
};
|
|
598
|
+
resolvedMcpServers = injectSynthesizedAttachment(resolvedMcpServers, conversationAttachment, "conversation participation");
|
|
602
599
|
}
|
|
603
|
-
|
|
600
|
+
// The one projection point: every mutation above is now visible in the
|
|
601
|
+
// Cursor SDK config by construction (no per-mutation rebuild to forget).
|
|
602
|
+
const mcpConfig = toCursorMcpConfig(resolvedMcpServers);
|
|
604
603
|
// Phase 4b: Merge approval policies from all layers.
|
|
605
604
|
//
|
|
606
605
|
// Two bypasses (see ActiveLeases, shared with the native harness): the
|
|
@@ -614,10 +613,10 @@ turnSeq) {
|
|
|
614
613
|
// Layer-3 overrides ride each resolved server from its merged usage —
|
|
615
614
|
// see ResolvedMcpServer.toolApprovalOverrides (issue #349) — so there
|
|
616
615
|
// is no separate override input to pass here.
|
|
617
|
-
const mergedPolicies = mergeApprovalPolicies(
|
|
616
|
+
const mergedPolicies = mergeApprovalPolicies(resolvedMcpServers, leases);
|
|
618
617
|
heartbeat();
|
|
619
618
|
// Phase 4c: Validate MCP server env health (diagnostic, non-blocking)
|
|
620
|
-
const mcpWarnings = validateMcpServerEnv(
|
|
619
|
+
const mcpWarnings = validateMcpServerEnv(resolvedMcpServers, blueprint.mergedMcpServerUsages);
|
|
621
620
|
if (mcpWarnings.length > 0) {
|
|
622
621
|
console.warn(`ExecuteCursor MCP pre-flight warnings: execution=${executionId}\n` +
|
|
623
622
|
mcpWarnings.map((w) => ` - ${w}`).join("\n"));
|
|
@@ -760,7 +759,7 @@ turnSeq) {
|
|
|
760
759
|
// servers' allow-lists, enforced by the hook's "disabled" arm ahead of
|
|
761
760
|
// every approval bypass. The Cursor SDK config cannot hide a server's
|
|
762
761
|
// tools, so this deny-at-call is the harness's enforcement.
|
|
763
|
-
enabledToolsBySlug(
|
|
762
|
+
enabledToolsBySlug(resolvedMcpServers));
|
|
764
763
|
const hitlGate = await installHitlGate({
|
|
765
764
|
workspaceRoot: primaryWorkspaceDir,
|
|
766
765
|
hitlDir,
|
|
@@ -989,6 +988,7 @@ turnSeq) {
|
|
|
989
988
|
contextBridge: readContextBridge(blueprint.sessionSpec.metadata),
|
|
990
989
|
senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
|
|
991
990
|
sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
|
|
991
|
+
declaredPreferences: readDeclaredPreferences(spec.declaredPreferences),
|
|
992
992
|
conversationCatchup: readConversationCatchup(spec.conversationCatchup),
|
|
993
993
|
// The turn's recorded transcript, seeded from the persisted execution
|
|
994
994
|
// on a reinvocation (Phase 3). Consumed only by the HITL-recovery
|
|
@@ -1188,14 +1188,22 @@ turnSeq) {
|
|
|
1188
1188
|
// classifies a shutdown from the shutdown signal directly (in
|
|
1189
1189
|
// resolvePreBoundaryTerminal). The heartbeat timer may set `cancelled` before
|
|
1190
1190
|
// the AbortSignal microtask propagates; the direct signal check catches that.
|
|
1191
|
-
|
|
1192
|
-
|
|
1191
|
+
// The decision table (including #776's grace-window guard: an aborted
|
|
1192
|
+
// shutdown signal with NO interruption evidence stays "none") lives in
|
|
1193
|
+
// classifyTurnInterruption — shared/worker-shutdown.ts.
|
|
1194
|
+
const interruption = classifyTurnInterruption({
|
|
1195
|
+
heartbeatCancelled: periodicHeartbeat.cancelled,
|
|
1196
|
+
heartbeatWorkerShutdown: periodicHeartbeat.workerShutdown,
|
|
1197
|
+
cancellationSignalAborted: Context.current().cancellationSignal.aborted,
|
|
1198
|
+
shutdownSignalAborted: shutdownSignal?.aborted ?? false,
|
|
1199
|
+
});
|
|
1200
|
+
if (interruption === "worker-shutdown") {
|
|
1193
1201
|
turnState.pauseDetected = false;
|
|
1194
1202
|
}
|
|
1195
|
-
else if (
|
|
1203
|
+
else if (interruption === "pause") {
|
|
1196
1204
|
turnState.pauseDetected = true;
|
|
1197
1205
|
}
|
|
1198
|
-
workerShutdownDetected =
|
|
1206
|
+
workerShutdownDetected = interruption === "worker-shutdown";
|
|
1199
1207
|
// Post-stream finalize, shared by the primary turn and both recovery retries:
|
|
1200
1208
|
// finalize the transcript + streaming flags, mark any in-flight sub-agent
|
|
1201
1209
|
// CANCELLED on an aborted turn, snapshot usage, flush the recorder, and
|
|
@@ -1270,10 +1278,14 @@ turnSeq) {
|
|
|
1270
1278
|
`estimatedCostUsd=${estimated.toFixed(4)}, maxCostUsd=${maxCostUsd.toFixed(2)}`);
|
|
1271
1279
|
return { kind: "return" };
|
|
1272
1280
|
}
|
|
1273
|
-
// Worker shutdown: the runner
|
|
1281
|
+
// Worker shutdown: the runner/manager aborted the shutdown signal. NOT a
|
|
1274
1282
|
// user pause. Checked via the shutdown signal directly so a retry (whose
|
|
1275
|
-
// periodic heartbeat is already stopped) still classifies it correctly
|
|
1276
|
-
|
|
1283
|
+
// periodic heartbeat is already stopped) still classifies it correctly —
|
|
1284
|
+
// but only alongside a delivered cancellation: a retry that completed
|
|
1285
|
+
// normally inside the drain grace window must stay a completion (#776's
|
|
1286
|
+
// grace-window guard, mirroring the primary's `interrupted` gate).
|
|
1287
|
+
if (workerShutdownDetected ||
|
|
1288
|
+
((shutdownSignal?.aborted ?? false) && Context.current().cancellationSignal.aborted)) {
|
|
1277
1289
|
status.phase = ExecutionPhase.EXECUTION_FAILED;
|
|
1278
1290
|
status.error = "Execution interrupted: runner worker was shut down. Retry or resume.";
|
|
1279
1291
|
status.completedAt = utcTimestamp();
|
|
@@ -1574,6 +1586,7 @@ turnSeq) {
|
|
|
1574
1586
|
contextBridge: readContextBridge(blueprint.sessionSpec.metadata),
|
|
1575
1587
|
senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
|
|
1576
1588
|
sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
|
|
1589
|
+
declaredPreferences: readDeclaredPreferences(spec.declaredPreferences),
|
|
1577
1590
|
conversationCatchup: readConversationCatchup(spec.conversationCatchup),
|
|
1578
1591
|
// Composed fresh (not reused from Phase 10): the failed primary
|
|
1579
1592
|
// stream may have appended partial work onto status.messages,
|
|
@@ -1805,9 +1818,12 @@ turnSeq) {
|
|
|
1805
1818
|
catch (err) {
|
|
1806
1819
|
periodicHeartbeat?.stop();
|
|
1807
1820
|
if (err instanceof CancelledFailure) {
|
|
1808
|
-
//
|
|
1809
|
-
//
|
|
1810
|
-
|
|
1821
|
+
// Worker shutdown is infrastructure failure, not pause. The direct
|
|
1822
|
+
// signal check covers a CancelledFailure thrown BEFORE the post-stream
|
|
1823
|
+
// classification ran (workerShutdownDetected still false); no extra
|
|
1824
|
+
// interruption-evidence gate is needed here — the caught
|
|
1825
|
+
// CancelledFailure IS the evidence (#776).
|
|
1826
|
+
if (workerShutdownDetected || (shutdownSignal?.aborted ?? false)) {
|
|
1811
1827
|
console.log(`ExecuteCursor cancelled (worker shutdown) for execution ${executionId}`);
|
|
1812
1828
|
status.phase = ExecutionPhase.EXECUTION_FAILED;
|
|
1813
1829
|
status.error = "Execution interrupted: runner worker was shut down. Retry or resume.";
|
|
@@ -2109,6 +2125,7 @@ export function buildPrompt(input) {
|
|
|
2109
2125
|
contextBridge: input.contextBridge,
|
|
2110
2126
|
senderIdentity: input.senderIdentity,
|
|
2111
2127
|
sessionContext: input.sessionContext,
|
|
2128
|
+
declaredPreferences: input.declaredPreferences,
|
|
2112
2129
|
conversationCatchup,
|
|
2113
2130
|
}, {
|
|
2114
2131
|
turnDigest: input.turnRecoveryDigest,
|
|
@@ -2167,6 +2184,7 @@ export function buildPrompt(input) {
|
|
|
2167
2184
|
contextBridge: input.contextBridge,
|
|
2168
2185
|
senderIdentity: input.senderIdentity,
|
|
2169
2186
|
sessionContext: input.sessionContext,
|
|
2187
|
+
declaredPreferences: input.declaredPreferences,
|
|
2170
2188
|
conversationCatchup,
|
|
2171
2189
|
});
|
|
2172
2190
|
}
|