@stigmer/runner 3.12.3 → 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/call-http.js +12 -0
- package/dist/activities/call-http.js.map +1 -1
- package/dist/activities/call-llm.d.ts +18 -0
- package/dist/activities/call-llm.js +56 -2
- package/dist/activities/call-llm.js.map +1 -1
- package/dist/activities/execute-cursor/agent-session-cache.d.ts +72 -0
- package/dist/activities/execute-cursor/agent-session-cache.js +186 -0
- package/dist/activities/execute-cursor/agent-session-cache.js.map +1 -0
- 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 +108 -57
- 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/service-tier.d.ts +5 -15
- package/dist/activities/execute-cursor/service-tier.js +5 -21
- package/dist/activities/execute-cursor/service-tier.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 +31 -16
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/shell-env.d.ts +8 -5
- package/dist/activities/execute-deep-agent/shell-env.js +10 -7
- package/dist/activities/execute-deep-agent/shell-env.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/config.js +10 -5
- package/dist/config.js.map +1 -1
- package/dist/encryption/config.js +7 -2
- package/dist/encryption/config.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/main.js +12 -6
- package/dist/main.js.map +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/payload-codecs.js +2 -1
- package/dist/payload-codecs.js.map +1 -1
- package/dist/runner-manager.d.ts +1 -1
- package/dist/runner-manager.js +42 -22
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.js +30 -6
- 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/fingerprint-secret.d.ts +3 -2
- package/dist/shared/fingerprint-secret.js +5 -3
- package/dist/shared/fingerprint-secret.js.map +1 -1
- package/dist/shared/llm-backend.js +8 -1
- package/dist/shared/llm-backend.js.map +1 -1
- 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/model-client.d.ts +15 -0
- package/dist/shared/model-client.js +57 -13
- package/dist/shared/model-client.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/registry-endpoint.d.ts +5 -0
- package/dist/shared/registry-endpoint.js +7 -1
- package/dist/shared/registry-endpoint.js.map +1 -1
- package/dist/shared/runner-credential-keys.d.ts +26 -1
- package/dist/shared/runner-credential-keys.js +34 -1
- package/dist/shared/runner-credential-keys.js.map +1 -1
- package/dist/shared/runner-credential-store.d.ts +77 -0
- package/dist/shared/runner-credential-store.js +111 -0
- package/dist/shared/runner-credential-store.js.map +1 -0
- package/dist/shared/service-tier.d.ts +55 -0
- package/dist/shared/service-tier.js +67 -0
- package/dist/shared/service-tier.js.map +1 -0
- 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/shared/zip-extract.d.ts +10 -3
- package/dist/shared/zip-extract.js +10 -3
- package/dist/shared/zip-extract.js.map +1 -1
- package/dist/workflow-engine/loader.js +38 -1
- package/dist/workflow-engine/loader.js.map +1 -1
- package/dist/workflow-engine/tasks/call-function.d.ts +14 -0
- package/dist/workflow-engine/tasks/call-function.js +49 -5
- package/dist/workflow-engine/tasks/call-function.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/dist/workflow-engine/types.d.ts +6 -0
- package/dist/workflow-engine/types.js.map +1 -1
- package/dist/workflows/engine-core.js +36 -8
- package/dist/workflows/engine-core.js.map +1 -1
- package/package.json +15 -11
- package/src/activities/__tests__/call-http.test.ts +36 -0
- package/src/activities/__tests__/call-llm.test.ts +77 -0
- package/src/activities/call-http.ts +17 -0
- package/src/activities/call-llm.ts +78 -2
- package/src/activities/execute-cursor/__tests__/agent-session-cache.test.ts +220 -0
- 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__/service-tier.test.ts +1 -1
- package/src/activities/execute-cursor/__tests__/skill-resolver.test.ts +3 -94
- package/src/activities/execute-cursor/agent-session-cache.ts +229 -0
- package/src/activities/execute-cursor/cursor-mcp-config.ts +107 -0
- package/src/activities/execute-cursor/index.ts +129 -55
- package/src/activities/execute-cursor/prompt-builder.ts +29 -2
- package/src/activities/execute-cursor/service-tier.ts +5 -29
- 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 +36 -19
- package/src/activities/execute-deep-agent/shell-env.ts +10 -7
- package/src/activities/execute-deep-agent/subagent-transformer.ts +19 -12
- package/src/activities/execute-deep-agent/subagent-wiring.ts +3 -3
- package/src/config.ts +10 -5
- package/src/encryption/config.ts +8 -2
- package/src/index.ts +1 -1
- package/src/main.ts +16 -6
- 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/payload-codecs.ts +2 -1
- package/src/runner-manager.ts +55 -22
- package/src/runner.ts +39 -6
- 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__/model-client.test.ts +99 -0
- package/src/shared/__tests__/plan-mode-permissions.test.ts +15 -44
- package/src/shared/__tests__/runner-credential-store.test.ts +155 -0
- 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/__tests__/zip-extract.test.ts +46 -11
- 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/fingerprint-secret.ts +5 -3
- package/src/shared/llm-backend.ts +7 -1
- package/src/shared/mcp-enabled-tools.ts +2 -3
- package/src/shared/mcp-resolver.ts +20 -20
- package/src/shared/model-client.ts +76 -13
- package/src/shared/placeholder-resolver.ts +9 -2
- package/src/shared/plan-mode-permissions.ts +27 -58
- package/src/shared/registry-endpoint.ts +9 -1
- package/src/shared/runner-credential-keys.ts +36 -1
- package/src/shared/runner-credential-store.ts +115 -0
- package/src/shared/service-tier.ts +78 -0
- 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/shared/zip-extract.ts +14 -7
- package/src/workflow-engine/__tests__/golden-execution.test.ts +20 -1
- package/src/workflow-engine/__tests__/loader.test.ts +51 -0
- package/src/workflow-engine/__tests__/tasks/call-function.test.ts +105 -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/call-function.ts +74 -13
- package/src/workflow-engine/tasks/human-input.ts +33 -5
- package/src/workflow-engine/types.ts +6 -0
- package/src/workflows/engine-core.ts +39 -8
- 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
|
@@ -34,6 +34,7 @@ import { ExecutionPhase, FileChangeSetStatus, InteractionMode, MessageType, Appr
|
|
|
34
34
|
import { StigmerClient } from "../../client/stigmer-client.js";
|
|
35
35
|
import { describeExecutionError } from "../../shared/model-error.js";
|
|
36
36
|
import { resolveAgentWithTransportRecovery } from "./session-lifecycle.js";
|
|
37
|
+
import { cacheSessionAgent, computeAgentFingerprint, takeCachedAgent } from "./agent-session-cache.js";
|
|
37
38
|
import { CursorMode } from "@stigmer/protos/ai/stigmer/agentic/session/v1/enum_pb";
|
|
38
39
|
import { determineCursorMode, isCloudMode } from "./cursor-mode.js";
|
|
39
40
|
import { MessageAccumulator, cancelInProgressSubAgentProtos, collapseRedundantToolCallTwins } from "./message-translator.js";
|
|
@@ -44,6 +45,7 @@ import { readConversationCatchup } from "../../shared/conversation-catchup.js";
|
|
|
44
45
|
import { readSenderIdentity } from "../../shared/sender-identity.js";
|
|
45
46
|
import { injectCallerIdentityEnv, resolveCallerIdentity, } from "../../shared/caller-identity.js";
|
|
46
47
|
import { readSessionContext } from "../../shared/session-context.js";
|
|
48
|
+
import { readDeclaredPreferences } from "../../shared/declared-preferences.js";
|
|
47
49
|
import { withholdSecretContentFromMessages } from "../../shared/tool-row.js";
|
|
48
50
|
import { StallTimeoutError, formatStallFailure } from "../../shared/stall-watchdog.js";
|
|
49
51
|
import { resolveUsableArtifactStorage, loadArtifactStorageConfig } from "../../shared/artifact-storage.js";
|
|
@@ -54,7 +56,8 @@ import { DeltaEnricher } from "./delta-enricher.js";
|
|
|
54
56
|
import { TodoTracker } from "./todo-tracker.js";
|
|
55
57
|
import { StreamingUpdateScheduler, loadStreamingConfig } from "../../shared/streaming-scheduler.js";
|
|
56
58
|
import { createCursorEventRecorder } from "./cursor-event-recorder.js";
|
|
57
|
-
import { resolveMcpServers
|
|
59
|
+
import { resolveMcpServers } from "../../shared/mcp-resolver.js";
|
|
60
|
+
import { toCursorMcpConfig, validateMcpServerEnv } from "./cursor-mcp-config.js";
|
|
58
61
|
import { resolveMcpTransportPosture } from "../../shared/mcp-transport-guard.js";
|
|
59
62
|
import { discoverChannelMessaging, synthesizeChannelAttachment, } from "../../shared/channel-attachment.js";
|
|
60
63
|
import { readChannelConversationId, synthesizeConversationAttachment, } from "../../shared/conversation-attachment.js";
|
|
@@ -62,7 +65,7 @@ import { injectSynthesizedAttachment } from "../../shared/synthesized-attachment
|
|
|
62
65
|
import { mergeApprovalPolicies } from "./approval-policy.js";
|
|
63
66
|
import { deriveActiveLeases, isUnattendedApprovalMode } from "../../shared/approval-policy.js";
|
|
64
67
|
import { enabledToolsBySlug } from "../../shared/mcp-enabled-tools.js";
|
|
65
|
-
import { backfillMcpServersIfNeeded } from "
|
|
68
|
+
import { backfillMcpServersIfNeeded } from "../../shared/connect-backfill.js";
|
|
66
69
|
import { resolveExecutionEnv } from "./env-resolver.js";
|
|
67
70
|
import { resolveBlueprint } from "./blueprint-resolver.js";
|
|
68
71
|
import { buildCursorSubAgentDefinitions } from "./subagent-config.js";
|
|
@@ -91,7 +94,8 @@ import { statusProtoWriter } from "../../shared/execution-status-writer.js";
|
|
|
91
94
|
import { setInterceptorExecutionId, runWithExecutionContext } from "./fetch-interceptor.js";
|
|
92
95
|
import { closeProxySessions } from "./http2-interceptor.js";
|
|
93
96
|
import { resolveModelId, ensureLoaded as ensurePricingLoaded } from "./model-pricing.js";
|
|
94
|
-
import { resolveEffectiveServiceTier
|
|
97
|
+
import { resolveEffectiveServiceTier } from "../../shared/service-tier.js";
|
|
98
|
+
import { resolveServiceTierParams } from "./service-tier.js";
|
|
95
99
|
import { UsageAccumulator } from "./usage-accumulator.js";
|
|
96
100
|
import { StreamingUsageSummarySchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/usage_pb";
|
|
97
101
|
import { activityStarted, activityFinished } from "../../idle-watchdog.js";
|
|
@@ -101,7 +105,7 @@ import { synthesizeError, formatClassifiedError, shouldRetryWithFreshAgent, extr
|
|
|
101
105
|
import { createAgent, createCloudAgent } from "./session-lifecycle.js";
|
|
102
106
|
import { setMaxListeners } from "node:events";
|
|
103
107
|
import { startHeartbeat } from "../../shared/heartbeat.js";
|
|
104
|
-
import { getShutdownSignalForQueue } from "../../
|
|
108
|
+
import { classifyTurnInterruption, getShutdownSignalForQueue } from "../../shared/worker-shutdown.js";
|
|
105
109
|
/**
|
|
106
110
|
* Creates the activity functions bound to the runner config.
|
|
107
111
|
* Returned object is passed to Temporal Worker.create({ activities }).
|
|
@@ -524,12 +528,15 @@ turnSeq) {
|
|
|
524
528
|
await reportSetupProgress(client, executionId, "Resolving MCP servers");
|
|
525
529
|
const transportPosture = resolveMcpTransportPosture(config.mode);
|
|
526
530
|
const mcpEnvVars = injectCallerIdentityEnv(envVars, resolveCallerIdentity(blueprint.sessionSpec.metadata, session.status?.audit?.specAudit?.createdBy), sessionId);
|
|
527
|
-
|
|
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;
|
|
528
535
|
setupTiming.mark("resolve_mcp_servers");
|
|
529
536
|
// Phase 4a: Connect backfill for undiscovered MCP servers
|
|
530
537
|
heartbeatPhase = "resolving_mcp_servers";
|
|
531
538
|
const sessionOrg = session.metadata?.org ?? "";
|
|
532
|
-
|
|
539
|
+
resolvedMcpServers = await backfillMcpServersIfNeeded(client, resolvedMcpServers, blueprint.mergedMcpServerUsages, mcpEnvVars, sessionOrg, transportPosture, heartbeat, secretKeys);
|
|
533
540
|
setupTiming.mark("backfill_mcp");
|
|
534
541
|
// The synthesized attachments' credential story (DD-006 D4): the
|
|
535
542
|
// exchanged token authenticates the discovery reads per-call (a
|
|
@@ -572,11 +579,7 @@ turnSeq) {
|
|
|
572
579
|
backendEndpoint: config.stigmerBackendEndpoint,
|
|
573
580
|
});
|
|
574
581
|
if (attachment) {
|
|
575
|
-
|
|
576
|
-
mcpResolution = {
|
|
577
|
-
resolvedServers,
|
|
578
|
-
cursorConfig: toCursorMcpConfig(resolvedServers),
|
|
579
|
-
};
|
|
582
|
+
resolvedMcpServers = injectSynthesizedAttachment(resolvedMcpServers, attachment, "channel messaging");
|
|
580
583
|
}
|
|
581
584
|
}
|
|
582
585
|
// Phase 4a4: Synthesize the conversation participation attachment
|
|
@@ -592,13 +595,11 @@ turnSeq) {
|
|
|
592
595
|
backendEndpoint: config.stigmerBackendEndpoint,
|
|
593
596
|
});
|
|
594
597
|
if (conversationAttachment) {
|
|
595
|
-
|
|
596
|
-
mcpResolution = {
|
|
597
|
-
resolvedServers,
|
|
598
|
-
cursorConfig: toCursorMcpConfig(resolvedServers),
|
|
599
|
-
};
|
|
598
|
+
resolvedMcpServers = injectSynthesizedAttachment(resolvedMcpServers, conversationAttachment, "conversation participation");
|
|
600
599
|
}
|
|
601
|
-
|
|
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);
|
|
602
603
|
// Phase 4b: Merge approval policies from all layers.
|
|
603
604
|
//
|
|
604
605
|
// Two bypasses (see ActiveLeases, shared with the native harness): the
|
|
@@ -612,10 +613,10 @@ turnSeq) {
|
|
|
612
613
|
// Layer-3 overrides ride each resolved server from its merged usage —
|
|
613
614
|
// see ResolvedMcpServer.toolApprovalOverrides (issue #349) — so there
|
|
614
615
|
// is no separate override input to pass here.
|
|
615
|
-
const mergedPolicies = mergeApprovalPolicies(
|
|
616
|
+
const mergedPolicies = mergeApprovalPolicies(resolvedMcpServers, leases);
|
|
616
617
|
heartbeat();
|
|
617
618
|
// Phase 4c: Validate MCP server env health (diagnostic, non-blocking)
|
|
618
|
-
const mcpWarnings = validateMcpServerEnv(
|
|
619
|
+
const mcpWarnings = validateMcpServerEnv(resolvedMcpServers, blueprint.mergedMcpServerUsages);
|
|
619
620
|
if (mcpWarnings.length > 0) {
|
|
620
621
|
console.warn(`ExecuteCursor MCP pre-flight warnings: execution=${executionId}\n` +
|
|
621
622
|
mcpWarnings.map((w) => ` - ${w}`).join("\n"));
|
|
@@ -758,7 +759,7 @@ turnSeq) {
|
|
|
758
759
|
// servers' allow-lists, enforced by the hook's "disabled" arm ahead of
|
|
759
760
|
// every approval bypass. The Cursor SDK config cannot hide a server's
|
|
760
761
|
// tools, so this deny-at-call is the harness's enforcement.
|
|
761
|
-
enabledToolsBySlug(
|
|
762
|
+
enabledToolsBySlug(resolvedMcpServers));
|
|
762
763
|
const hitlGate = await installHitlGate({
|
|
763
764
|
workspaceRoot: primaryWorkspaceDir,
|
|
764
765
|
hitlDir,
|
|
@@ -882,20 +883,47 @@ turnSeq) {
|
|
|
882
883
|
// is the largest user-visible setup segment; this split keeps its
|
|
883
884
|
// historical meaning — the SDK call was already 98%+ of it).
|
|
884
885
|
setupTiming.mark("prepare_agent");
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
886
|
+
// Phase 8a: Reuse the previous turn's agent when this session parked one
|
|
887
|
+
// (#215). A checkout hit skips Agent.resume() AND — the real win — keeps
|
|
888
|
+
// the SDK executor lease alive, so agent.send() below re-acquires the
|
|
889
|
+
// warm executor instead of re-spawning every stdio MCP server (the
|
|
890
|
+
// measured 2.2–3.2s `send_returned` tax). The fingerprint covers the
|
|
891
|
+
// full acquisition config, so any drift (rotated credential, edited MCP
|
|
892
|
+
// servers, model change) falls through to a fresh resolve.
|
|
893
|
+
const agentFingerprint = computeAgentFingerprint(createOptions);
|
|
894
|
+
const parkedAgent = takeCachedAgent(sessionId, agentFingerprint, threadId ?? "");
|
|
895
|
+
let resolution;
|
|
896
|
+
if (parkedAgent) {
|
|
897
|
+
console.log(`ExecuteCursor reusing parked session agent: execution=${executionId}, ` +
|
|
898
|
+
`session=${sessionId}, agentId=${parkedAgent.agentId}`);
|
|
899
|
+
resolution = {
|
|
900
|
+
agent: parkedAgent,
|
|
901
|
+
agentId: parkedAgent.agentId,
|
|
902
|
+
isNew: false,
|
|
903
|
+
resumed: true,
|
|
904
|
+
mode: agentMode,
|
|
905
|
+
// The parked handle IS the live conversation — every consumer of
|
|
906
|
+
// "resumed_successfully" (prompt selection, poisoned-handle
|
|
907
|
+
// recovery eligibility) wants exactly those semantics.
|
|
908
|
+
reason: "resumed_successfully",
|
|
909
|
+
};
|
|
910
|
+
}
|
|
911
|
+
else {
|
|
912
|
+
resolution = await resolveAgentWithTransportRecovery({
|
|
913
|
+
harnessStateId: threadId,
|
|
914
|
+
createOptions,
|
|
915
|
+
mode: agentMode,
|
|
916
|
+
timeoutMs: config.agentResolveTimeoutMs,
|
|
917
|
+
buildTimeoutMessage: (finalAttempt) => `Cursor agent ${threadId ? "resume" : "create"} timed out after ${resolveTimeoutSeconds}s ` +
|
|
918
|
+
`(${config.proxyEndpoint ? `via proxy ${config.proxyEndpoint}` : "direct Cursor API connection"}). ` +
|
|
919
|
+
`The transport connection is likely dead. ` +
|
|
920
|
+
(finalAttempt
|
|
921
|
+
? `An automatic retry on a fresh transport connection also timed out. ` +
|
|
922
|
+
`Retry the message later; if this persists, check proxy and network health.`
|
|
923
|
+
: `Resetting the transport and retrying automatically.`),
|
|
924
|
+
resetTransport: closeProxySessions,
|
|
925
|
+
});
|
|
926
|
+
}
|
|
899
927
|
console.log(`ExecuteCursor agent resolved: execution=${executionId}, ` +
|
|
900
928
|
`reason=${resolution.reason}, mode=${resolution.mode}, ` +
|
|
901
929
|
`agentId=${resolution.agentId}, resumed=${resolution.resumed}` +
|
|
@@ -960,6 +988,7 @@ turnSeq) {
|
|
|
960
988
|
contextBridge: readContextBridge(blueprint.sessionSpec.metadata),
|
|
961
989
|
senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
|
|
962
990
|
sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
|
|
991
|
+
declaredPreferences: readDeclaredPreferences(spec.declaredPreferences),
|
|
963
992
|
conversationCatchup: readConversationCatchup(spec.conversationCatchup),
|
|
964
993
|
// The turn's recorded transcript, seeded from the persisted execution
|
|
965
994
|
// on a reinvocation (Phase 3). Consumed only by the HITL-recovery
|
|
@@ -1159,14 +1188,22 @@ turnSeq) {
|
|
|
1159
1188
|
// classifies a shutdown from the shutdown signal directly (in
|
|
1160
1189
|
// resolvePreBoundaryTerminal). The heartbeat timer may set `cancelled` before
|
|
1161
1190
|
// the AbortSignal microtask propagates; the direct signal check catches that.
|
|
1162
|
-
|
|
1163
|
-
|
|
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") {
|
|
1164
1201
|
turnState.pauseDetected = false;
|
|
1165
1202
|
}
|
|
1166
|
-
else if (
|
|
1203
|
+
else if (interruption === "pause") {
|
|
1167
1204
|
turnState.pauseDetected = true;
|
|
1168
1205
|
}
|
|
1169
|
-
workerShutdownDetected =
|
|
1206
|
+
workerShutdownDetected = interruption === "worker-shutdown";
|
|
1170
1207
|
// Post-stream finalize, shared by the primary turn and both recovery retries:
|
|
1171
1208
|
// finalize the transcript + streaming flags, mark any in-flight sub-agent
|
|
1172
1209
|
// CANCELLED on an aborted turn, snapshot usage, flush the recorder, and
|
|
@@ -1234,18 +1271,21 @@ turnSeq) {
|
|
|
1234
1271
|
timestamp: utcTimestamp(),
|
|
1235
1272
|
}));
|
|
1236
1273
|
await persist(status);
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
catch { /* best effort */ }
|
|
1274
|
+
// Clean terminal: the conversation continues on the next message,
|
|
1275
|
+
// so park the healthy agent for that turn (#215).
|
|
1276
|
+
cacheSessionAgent(sessionId ?? "", resolution.agent, agentFingerprint);
|
|
1241
1277
|
console.warn(`ExecuteCursor terminated (cost cap): execution=${executionId}, ` +
|
|
1242
1278
|
`estimatedCostUsd=${estimated.toFixed(4)}, maxCostUsd=${maxCostUsd.toFixed(2)}`);
|
|
1243
1279
|
return { kind: "return" };
|
|
1244
1280
|
}
|
|
1245
|
-
// Worker shutdown: the runner
|
|
1281
|
+
// Worker shutdown: the runner/manager aborted the shutdown signal. NOT a
|
|
1246
1282
|
// user pause. Checked via the shutdown signal directly so a retry (whose
|
|
1247
|
-
// periodic heartbeat is already stopped) still classifies it correctly
|
|
1248
|
-
|
|
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)) {
|
|
1249
1289
|
status.phase = ExecutionPhase.EXECUTION_FAILED;
|
|
1250
1290
|
status.error = "Execution interrupted: runner worker was shut down. Retry or resume.";
|
|
1251
1291
|
status.completedAt = utcTimestamp();
|
|
@@ -1296,10 +1336,8 @@ turnSeq) {
|
|
|
1296
1336
|
timestamp: utcTimestamp(),
|
|
1297
1337
|
}));
|
|
1298
1338
|
await persist(status);
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
}
|
|
1302
|
-
catch { /* best effort */ }
|
|
1339
|
+
// Clean terminal — park for the session's next turn (#215).
|
|
1340
|
+
cacheSessionAgent(sessionId ?? "", resolution.agent, agentFingerprint);
|
|
1303
1341
|
console.log(`ExecuteCursor completed (platform stop): execution=${executionId}`);
|
|
1304
1342
|
return { kind: "return" };
|
|
1305
1343
|
}
|
|
@@ -1343,6 +1381,12 @@ turnSeq) {
|
|
|
1343
1381
|
const enterApprovalPause = async (boundary) => {
|
|
1344
1382
|
status.phase = ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL;
|
|
1345
1383
|
await persist(status);
|
|
1384
|
+
// The approval-resume reinvocation is the cache's best case: park the
|
|
1385
|
+
// agent so the resumed turn skips the full executor rebuild (#215).
|
|
1386
|
+
// (This path previously dropped the handle without close() — the
|
|
1387
|
+
// lease leaked; parking makes the lifetime explicit.) An absent
|
|
1388
|
+
// sessionId falls back to "" — the cache closes the lease immediately.
|
|
1389
|
+
cacheSessionAgent(sessionId ?? "", resolution.agent, agentFingerprint);
|
|
1346
1390
|
console.log(`ExecuteCursor returning WAITING_FOR_APPROVAL: ${boundary.deniedToolCallCount} gated tool(s), ` +
|
|
1347
1391
|
`${boundary.capturedChangeCount} file card(s) pending`);
|
|
1348
1392
|
return slimStatus(status);
|
|
@@ -1542,6 +1586,7 @@ turnSeq) {
|
|
|
1542
1586
|
contextBridge: readContextBridge(blueprint.sessionSpec.metadata),
|
|
1543
1587
|
senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
|
|
1544
1588
|
sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
|
|
1589
|
+
declaredPreferences: readDeclaredPreferences(spec.declaredPreferences),
|
|
1545
1590
|
conversationCatchup: readConversationCatchup(spec.conversationCatchup),
|
|
1546
1591
|
// Composed fresh (not reused from Phase 10): the failed primary
|
|
1547
1592
|
// stream may have appended partial work onto status.messages,
|
|
@@ -1755,11 +1800,12 @@ turnSeq) {
|
|
|
1755
1800
|
console.log(`ExecuteCursor completed: execution=${executionId}, phase=${ExecutionPhase[status.phase]}, ` +
|
|
1756
1801
|
`hasStructuredOutput=${structuredOutput !== undefined}` +
|
|
1757
1802
|
(status.error ? `, error=${status.error}` : ""));
|
|
1758
|
-
//
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1803
|
+
// Park the agent (with its executor lease) for the session's next turn
|
|
1804
|
+
// instead of closing it — the idle TTL / shutdown hooks in
|
|
1805
|
+
// agent-session-cache own the eventual release, so cache buildup across
|
|
1806
|
+
// sessions stays bounded while turns of ONE session stop paying the
|
|
1807
|
+
// executor + MCP re-spawn tax (#215).
|
|
1808
|
+
cacheSessionAgent(sessionId ?? "", resolution.agent, agentFingerprint);
|
|
1763
1809
|
const slim = slimStatus(status);
|
|
1764
1810
|
if (finalText !== undefined) {
|
|
1765
1811
|
slim.final_text = finalText;
|
|
@@ -1772,9 +1818,12 @@ turnSeq) {
|
|
|
1772
1818
|
catch (err) {
|
|
1773
1819
|
periodicHeartbeat?.stop();
|
|
1774
1820
|
if (err instanceof CancelledFailure) {
|
|
1775
|
-
//
|
|
1776
|
-
//
|
|
1777
|
-
|
|
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)) {
|
|
1778
1827
|
console.log(`ExecuteCursor cancelled (worker shutdown) for execution ${executionId}`);
|
|
1779
1828
|
status.phase = ExecutionPhase.EXECUTION_FAILED;
|
|
1780
1829
|
status.error = "Execution interrupted: runner worker was shut down. Retry or resume.";
|
|
@@ -2076,6 +2125,7 @@ export function buildPrompt(input) {
|
|
|
2076
2125
|
contextBridge: input.contextBridge,
|
|
2077
2126
|
senderIdentity: input.senderIdentity,
|
|
2078
2127
|
sessionContext: input.sessionContext,
|
|
2128
|
+
declaredPreferences: input.declaredPreferences,
|
|
2079
2129
|
conversationCatchup,
|
|
2080
2130
|
}, {
|
|
2081
2131
|
turnDigest: input.turnRecoveryDigest,
|
|
@@ -2134,6 +2184,7 @@ export function buildPrompt(input) {
|
|
|
2134
2184
|
contextBridge: input.contextBridge,
|
|
2135
2185
|
senderIdentity: input.senderIdentity,
|
|
2136
2186
|
sessionContext: input.sessionContext,
|
|
2187
|
+
declaredPreferences: input.declaredPreferences,
|
|
2137
2188
|
conversationCatchup,
|
|
2138
2189
|
});
|
|
2139
2190
|
}
|