@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
|
@@ -41,6 +41,7 @@ import type { Config } from "../../config.js";
|
|
|
41
41
|
import { StigmerClient } from "../../client/stigmer-client.js";
|
|
42
42
|
import { describeExecutionError } from "../../shared/model-error.js";
|
|
43
43
|
import { resolveAgentWithTransportRecovery } from "./session-lifecycle.js";
|
|
44
|
+
import { cacheSessionAgent, computeAgentFingerprint, takeCachedAgent } from "./agent-session-cache.js";
|
|
44
45
|
import type { AgentResolution, AgentResolutionReason, CreateAgentOptions, CreateCloudAgentOptions } from "./session-lifecycle.js";
|
|
45
46
|
import { CursorMode } from "@stigmer/protos/ai/stigmer/agentic/session/v1/enum_pb";
|
|
46
47
|
import { determineCursorMode, isCloudMode } from "./cursor-mode.js";
|
|
@@ -55,6 +56,7 @@ import {
|
|
|
55
56
|
resolveCallerIdentity,
|
|
56
57
|
} from "../../shared/caller-identity.js";
|
|
57
58
|
import { readSessionContext } from "../../shared/session-context.js";
|
|
59
|
+
import { readDeclaredPreferences } from "../../shared/declared-preferences.js";
|
|
58
60
|
import { withholdSecretContentFromMessages } from "../../shared/tool-row.js";
|
|
59
61
|
import { StallTimeoutError, formatStallFailure } from "../../shared/stall-watchdog.js";
|
|
60
62
|
import { resolveUsableArtifactStorage, loadArtifactStorageConfig, type ArtifactStorage } from "../../shared/artifact-storage.js";
|
|
@@ -70,7 +72,8 @@ import { DeltaEnricher } from "./delta-enricher.js";
|
|
|
70
72
|
import { TodoTracker } from "./todo-tracker.js";
|
|
71
73
|
import { StreamingUpdateScheduler, loadStreamingConfig } from "../../shared/streaming-scheduler.js";
|
|
72
74
|
import { createCursorEventRecorder } from "./cursor-event-recorder.js";
|
|
73
|
-
import { resolveMcpServers
|
|
75
|
+
import { resolveMcpServers } from "../../shared/mcp-resolver.js";
|
|
76
|
+
import { toCursorMcpConfig, validateMcpServerEnv } from "./cursor-mcp-config.js";
|
|
74
77
|
import { resolveMcpTransportPosture } from "../../shared/mcp-transport-guard.js";
|
|
75
78
|
import {
|
|
76
79
|
discoverChannelMessaging,
|
|
@@ -84,7 +87,7 @@ import { injectSynthesizedAttachment } from "../../shared/synthesized-attachment
|
|
|
84
87
|
import { mergeApprovalPolicies } from "./approval-policy.js";
|
|
85
88
|
import { deriveActiveLeases, isUnattendedApprovalMode } from "../../shared/approval-policy.js";
|
|
86
89
|
import { enabledToolsBySlug } from "../../shared/mcp-enabled-tools.js";
|
|
87
|
-
import { backfillMcpServersIfNeeded } from "
|
|
90
|
+
import { backfillMcpServersIfNeeded } from "../../shared/connect-backfill.js";
|
|
88
91
|
import { resolveExecutionEnv } from "./env-resolver.js";
|
|
89
92
|
import { resolveBlueprint } from "./blueprint-resolver.js";
|
|
90
93
|
import { buildCursorSubAgentDefinitions } from "./subagent-config.js";
|
|
@@ -134,7 +137,8 @@ import { statusProtoWriter } from "../../shared/execution-status-writer.js";
|
|
|
134
137
|
import { setInterceptorExecutionId, runWithExecutionContext } from "./fetch-interceptor.js";
|
|
135
138
|
import { closeProxySessions } from "./http2-interceptor.js";
|
|
136
139
|
import { resolveModelId, ensureLoaded as ensurePricingLoaded } from "./model-pricing.js";
|
|
137
|
-
import { resolveEffectiveServiceTier
|
|
140
|
+
import { resolveEffectiveServiceTier } from "../../shared/service-tier.js";
|
|
141
|
+
import { resolveServiceTierParams } from "./service-tier.js";
|
|
138
142
|
import { UsageAccumulator } from "./usage-accumulator.js";
|
|
139
143
|
import { StreamingUsageSummarySchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/usage_pb";
|
|
140
144
|
import { activityStarted, activityFinished } from "../../idle-watchdog.js";
|
|
@@ -145,7 +149,7 @@ import type { ClassifiedError } from "./error-classifier.js";
|
|
|
145
149
|
import { createAgent, createCloudAgent } from "./session-lifecycle.js";
|
|
146
150
|
import { setMaxListeners } from "node:events";
|
|
147
151
|
import { startHeartbeat } from "../../shared/heartbeat.js";
|
|
148
|
-
import { getShutdownSignalForQueue } from "../../
|
|
152
|
+
import { classifyTurnInterruption, getShutdownSignalForQueue } from "../../shared/worker-shutdown.js";
|
|
149
153
|
|
|
150
154
|
/**
|
|
151
155
|
* Creates the activity functions bound to the runner config.
|
|
@@ -625,16 +629,19 @@ async function executeCursorInner(
|
|
|
625
629
|
),
|
|
626
630
|
sessionId,
|
|
627
631
|
);
|
|
628
|
-
|
|
632
|
+
// The resolved-server list mutates through backfill and attachment
|
|
633
|
+
// injection below; the Cursor SDK config is projected from it exactly
|
|
634
|
+
// once, after the last mutation (see toCursorMcpConfig).
|
|
635
|
+
let resolvedMcpServers = (await resolveMcpServers(
|
|
629
636
|
client, blueprint.mergedMcpServerUsages, mcpEnvVars, transportPosture,
|
|
630
|
-
);
|
|
637
|
+
)).resolvedServers;
|
|
631
638
|
setupTiming.mark("resolve_mcp_servers");
|
|
632
639
|
|
|
633
640
|
// Phase 4a: Connect backfill for undiscovered MCP servers
|
|
634
641
|
heartbeatPhase = "resolving_mcp_servers";
|
|
635
642
|
const sessionOrg = session.metadata?.org ?? "";
|
|
636
|
-
|
|
637
|
-
client,
|
|
643
|
+
resolvedMcpServers = await backfillMcpServersIfNeeded(
|
|
644
|
+
client, resolvedMcpServers, blueprint.mergedMcpServerUsages, mcpEnvVars, sessionOrg,
|
|
638
645
|
transportPosture, heartbeat, secretKeys,
|
|
639
646
|
);
|
|
640
647
|
setupTiming.mark("backfill_mcp");
|
|
@@ -682,13 +689,9 @@ async function executeCursorInner(
|
|
|
682
689
|
backendEndpoint: config.stigmerBackendEndpoint,
|
|
683
690
|
});
|
|
684
691
|
if (attachment) {
|
|
685
|
-
|
|
686
|
-
|
|
692
|
+
resolvedMcpServers = injectSynthesizedAttachment(
|
|
693
|
+
resolvedMcpServers, attachment, "channel messaging",
|
|
687
694
|
);
|
|
688
|
-
mcpResolution = {
|
|
689
|
-
resolvedServers,
|
|
690
|
-
cursorConfig: toCursorMcpConfig(resolvedServers),
|
|
691
|
-
};
|
|
692
695
|
}
|
|
693
696
|
}
|
|
694
697
|
|
|
@@ -708,15 +711,13 @@ async function executeCursorInner(
|
|
|
708
711
|
},
|
|
709
712
|
);
|
|
710
713
|
if (conversationAttachment) {
|
|
711
|
-
|
|
712
|
-
|
|
714
|
+
resolvedMcpServers = injectSynthesizedAttachment(
|
|
715
|
+
resolvedMcpServers, conversationAttachment, "conversation participation",
|
|
713
716
|
);
|
|
714
|
-
mcpResolution = {
|
|
715
|
-
resolvedServers,
|
|
716
|
-
cursorConfig: toCursorMcpConfig(resolvedServers),
|
|
717
|
-
};
|
|
718
717
|
}
|
|
719
|
-
|
|
718
|
+
// The one projection point: every mutation above is now visible in the
|
|
719
|
+
// Cursor SDK config by construction (no per-mutation rebuild to forget).
|
|
720
|
+
const mcpConfig = toCursorMcpConfig(resolvedMcpServers);
|
|
720
721
|
|
|
721
722
|
// Phase 4b: Merge approval policies from all layers.
|
|
722
723
|
//
|
|
@@ -732,16 +733,15 @@ async function executeCursorInner(
|
|
|
732
733
|
// see ResolvedMcpServer.toolApprovalOverrides (issue #349) — so there
|
|
733
734
|
// is no separate override input to pass here.
|
|
734
735
|
const mergedPolicies = mergeApprovalPolicies(
|
|
735
|
-
|
|
736
|
+
resolvedMcpServers,
|
|
736
737
|
leases,
|
|
737
738
|
);
|
|
738
739
|
heartbeat();
|
|
739
740
|
|
|
740
741
|
// Phase 4c: Validate MCP server env health (diagnostic, non-blocking)
|
|
741
742
|
const mcpWarnings = validateMcpServerEnv(
|
|
742
|
-
|
|
743
|
+
resolvedMcpServers,
|
|
743
744
|
blueprint.mergedMcpServerUsages,
|
|
744
|
-
envVars,
|
|
745
745
|
);
|
|
746
746
|
if (mcpWarnings.length > 0) {
|
|
747
747
|
console.warn(
|
|
@@ -908,7 +908,7 @@ async function executeCursorInner(
|
|
|
908
908
|
// servers' allow-lists, enforced by the hook's "disabled" arm ahead of
|
|
909
909
|
// every approval bypass. The Cursor SDK config cannot hide a server's
|
|
910
910
|
// tools, so this deny-at-call is the harness's enforcement.
|
|
911
|
-
enabledToolsBySlug(
|
|
911
|
+
enabledToolsBySlug(resolvedMcpServers),
|
|
912
912
|
);
|
|
913
913
|
const hitlGate = await installHitlGate({
|
|
914
914
|
workspaceRoot: primaryWorkspaceDir,
|
|
@@ -1052,21 +1052,52 @@ async function executeCursorInner(
|
|
|
1052
1052
|
// is the largest user-visible setup segment; this split keeps its
|
|
1053
1053
|
// historical meaning — the SDK call was already 98%+ of it).
|
|
1054
1054
|
setupTiming.mark("prepare_agent");
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1055
|
+
|
|
1056
|
+
// Phase 8a: Reuse the previous turn's agent when this session parked one
|
|
1057
|
+
// (#215). A checkout hit skips Agent.resume() AND — the real win — keeps
|
|
1058
|
+
// the SDK executor lease alive, so agent.send() below re-acquires the
|
|
1059
|
+
// warm executor instead of re-spawning every stdio MCP server (the
|
|
1060
|
+
// measured 2.2–3.2s `send_returned` tax). The fingerprint covers the
|
|
1061
|
+
// full acquisition config, so any drift (rotated credential, edited MCP
|
|
1062
|
+
// servers, model change) falls through to a fresh resolve.
|
|
1063
|
+
const agentFingerprint = computeAgentFingerprint(
|
|
1064
|
+
createOptions as unknown as Record<string, unknown>,
|
|
1065
|
+
);
|
|
1066
|
+
const parkedAgent = takeCachedAgent(sessionId, agentFingerprint, threadId ?? "");
|
|
1067
|
+
let resolution: AgentResolution;
|
|
1068
|
+
if (parkedAgent) {
|
|
1069
|
+
console.log(
|
|
1070
|
+
`ExecuteCursor reusing parked session agent: execution=${executionId}, ` +
|
|
1071
|
+
`session=${sessionId}, agentId=${parkedAgent.agentId}`,
|
|
1072
|
+
);
|
|
1073
|
+
resolution = {
|
|
1074
|
+
agent: parkedAgent as AgentResolution["agent"],
|
|
1075
|
+
agentId: parkedAgent.agentId,
|
|
1076
|
+
isNew: false,
|
|
1077
|
+
resumed: true,
|
|
1078
|
+
mode: agentMode,
|
|
1079
|
+
// The parked handle IS the live conversation — every consumer of
|
|
1080
|
+
// "resumed_successfully" (prompt selection, poisoned-handle
|
|
1081
|
+
// recovery eligibility) wants exactly those semantics.
|
|
1082
|
+
reason: "resumed_successfully",
|
|
1083
|
+
};
|
|
1084
|
+
} else {
|
|
1085
|
+
resolution = await resolveAgentWithTransportRecovery({
|
|
1086
|
+
harnessStateId: threadId,
|
|
1087
|
+
createOptions,
|
|
1088
|
+
mode: agentMode,
|
|
1089
|
+
timeoutMs: config.agentResolveTimeoutMs,
|
|
1090
|
+
buildTimeoutMessage: (finalAttempt) =>
|
|
1091
|
+
`Cursor agent ${threadId ? "resume" : "create"} timed out after ${resolveTimeoutSeconds}s ` +
|
|
1092
|
+
`(${config.proxyEndpoint ? `via proxy ${config.proxyEndpoint}` : "direct Cursor API connection"}). ` +
|
|
1093
|
+
`The transport connection is likely dead. ` +
|
|
1094
|
+
(finalAttempt
|
|
1095
|
+
? `An automatic retry on a fresh transport connection also timed out. ` +
|
|
1096
|
+
`Retry the message later; if this persists, check proxy and network health.`
|
|
1097
|
+
: `Resetting the transport and retrying automatically.`),
|
|
1098
|
+
resetTransport: closeProxySessions,
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1070
1101
|
|
|
1071
1102
|
console.log(
|
|
1072
1103
|
`ExecuteCursor agent resolved: execution=${executionId}, ` +
|
|
@@ -1142,6 +1173,7 @@ async function executeCursorInner(
|
|
|
1142
1173
|
contextBridge: readContextBridge(blueprint.sessionSpec.metadata),
|
|
1143
1174
|
senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
|
|
1144
1175
|
sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
|
|
1176
|
+
declaredPreferences: readDeclaredPreferences(spec.declaredPreferences),
|
|
1145
1177
|
conversationCatchup: readConversationCatchup(spec.conversationCatchup),
|
|
1146
1178
|
// The turn's recorded transcript, seeded from the persisted execution
|
|
1147
1179
|
// on a reinvocation (Phase 3). Consumed only by the HITL-recovery
|
|
@@ -1368,13 +1400,21 @@ async function executeCursorInner(
|
|
|
1368
1400
|
// classifies a shutdown from the shutdown signal directly (in
|
|
1369
1401
|
// resolvePreBoundaryTerminal). The heartbeat timer may set `cancelled` before
|
|
1370
1402
|
// the AbortSignal microtask propagates; the direct signal check catches that.
|
|
1371
|
-
|
|
1372
|
-
|
|
1403
|
+
// The decision table (including #776's grace-window guard: an aborted
|
|
1404
|
+
// shutdown signal with NO interruption evidence stays "none") lives in
|
|
1405
|
+
// classifyTurnInterruption — shared/worker-shutdown.ts.
|
|
1406
|
+
const interruption = classifyTurnInterruption({
|
|
1407
|
+
heartbeatCancelled: periodicHeartbeat.cancelled,
|
|
1408
|
+
heartbeatWorkerShutdown: periodicHeartbeat.workerShutdown,
|
|
1409
|
+
cancellationSignalAborted: Context.current().cancellationSignal.aborted,
|
|
1410
|
+
shutdownSignalAborted: shutdownSignal?.aborted ?? false,
|
|
1411
|
+
});
|
|
1412
|
+
if (interruption === "worker-shutdown") {
|
|
1373
1413
|
turnState.pauseDetected = false;
|
|
1374
|
-
} else if (
|
|
1414
|
+
} else if (interruption === "pause") {
|
|
1375
1415
|
turnState.pauseDetected = true;
|
|
1376
1416
|
}
|
|
1377
|
-
workerShutdownDetected =
|
|
1417
|
+
workerShutdownDetected = interruption === "worker-shutdown";
|
|
1378
1418
|
|
|
1379
1419
|
// Post-stream finalize, shared by the primary turn and both recovery retries:
|
|
1380
1420
|
// finalize the transcript + streaming flags, mark any in-flight sub-agent
|
|
@@ -1462,7 +1502,9 @@ async function executeCursorInner(
|
|
|
1462
1502
|
timestamp: utcTimestamp(),
|
|
1463
1503
|
}));
|
|
1464
1504
|
await persist(status);
|
|
1465
|
-
|
|
1505
|
+
// Clean terminal: the conversation continues on the next message,
|
|
1506
|
+
// so park the healthy agent for that turn (#215).
|
|
1507
|
+
cacheSessionAgent(sessionId ?? "", resolution.agent, agentFingerprint);
|
|
1466
1508
|
console.warn(
|
|
1467
1509
|
`ExecuteCursor terminated (cost cap): execution=${executionId}, ` +
|
|
1468
1510
|
`estimatedCostUsd=${estimated.toFixed(4)}, maxCostUsd=${maxCostUsd.toFixed(2)}`,
|
|
@@ -1470,10 +1512,16 @@ async function executeCursorInner(
|
|
|
1470
1512
|
return { kind: "return" };
|
|
1471
1513
|
}
|
|
1472
1514
|
|
|
1473
|
-
// Worker shutdown: the runner
|
|
1515
|
+
// Worker shutdown: the runner/manager aborted the shutdown signal. NOT a
|
|
1474
1516
|
// user pause. Checked via the shutdown signal directly so a retry (whose
|
|
1475
|
-
// periodic heartbeat is already stopped) still classifies it correctly
|
|
1476
|
-
|
|
1517
|
+
// periodic heartbeat is already stopped) still classifies it correctly —
|
|
1518
|
+
// but only alongside a delivered cancellation: a retry that completed
|
|
1519
|
+
// normally inside the drain grace window must stay a completion (#776's
|
|
1520
|
+
// grace-window guard, mirroring the primary's `interrupted` gate).
|
|
1521
|
+
if (
|
|
1522
|
+
workerShutdownDetected ||
|
|
1523
|
+
((shutdownSignal?.aborted ?? false) && Context.current().cancellationSignal.aborted)
|
|
1524
|
+
) {
|
|
1477
1525
|
status.phase = ExecutionPhase.EXECUTION_FAILED;
|
|
1478
1526
|
status.error = "Execution interrupted: runner worker was shut down. Retry or resume.";
|
|
1479
1527
|
status.completedAt = utcTimestamp();
|
|
@@ -1527,7 +1575,8 @@ async function executeCursorInner(
|
|
|
1527
1575
|
timestamp: utcTimestamp(),
|
|
1528
1576
|
}));
|
|
1529
1577
|
await persist(status);
|
|
1530
|
-
|
|
1578
|
+
// Clean terminal — park for the session's next turn (#215).
|
|
1579
|
+
cacheSessionAgent(sessionId ?? "", resolution.agent, agentFingerprint);
|
|
1531
1580
|
console.log(`ExecuteCursor completed (platform stop): execution=${executionId}`);
|
|
1532
1581
|
return { kind: "return" };
|
|
1533
1582
|
}
|
|
@@ -1573,6 +1622,12 @@ async function executeCursorInner(
|
|
|
1573
1622
|
const enterApprovalPause = async (boundary: TurnBoundaryResult) => {
|
|
1574
1623
|
status.phase = ExecutionPhase.EXECUTION_WAITING_FOR_APPROVAL;
|
|
1575
1624
|
await persist(status);
|
|
1625
|
+
// The approval-resume reinvocation is the cache's best case: park the
|
|
1626
|
+
// agent so the resumed turn skips the full executor rebuild (#215).
|
|
1627
|
+
// (This path previously dropped the handle without close() — the
|
|
1628
|
+
// lease leaked; parking makes the lifetime explicit.) An absent
|
|
1629
|
+
// sessionId falls back to "" — the cache closes the lease immediately.
|
|
1630
|
+
cacheSessionAgent(sessionId ?? "", resolution.agent, agentFingerprint);
|
|
1576
1631
|
console.log(
|
|
1577
1632
|
`ExecuteCursor returning WAITING_FOR_APPROVAL: ${boundary.deniedToolCallCount} gated tool(s), ` +
|
|
1578
1633
|
`${boundary.capturedChangeCount} file card(s) pending`,
|
|
@@ -1823,6 +1878,7 @@ async function executeCursorInner(
|
|
|
1823
1878
|
contextBridge: readContextBridge(blueprint.sessionSpec.metadata),
|
|
1824
1879
|
senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
|
|
1825
1880
|
sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
|
|
1881
|
+
declaredPreferences: readDeclaredPreferences(spec.declaredPreferences),
|
|
1826
1882
|
conversationCatchup: readConversationCatchup(spec.conversationCatchup),
|
|
1827
1883
|
// Composed fresh (not reused from Phase 10): the failed primary
|
|
1828
1884
|
// stream may have appended partial work onto status.messages,
|
|
@@ -2088,8 +2144,12 @@ async function executeCursorInner(
|
|
|
2088
2144
|
(status.error ? `, error=${status.error}` : ""),
|
|
2089
2145
|
);
|
|
2090
2146
|
|
|
2091
|
-
//
|
|
2092
|
-
|
|
2147
|
+
// Park the agent (with its executor lease) for the session's next turn
|
|
2148
|
+
// instead of closing it — the idle TTL / shutdown hooks in
|
|
2149
|
+
// agent-session-cache own the eventual release, so cache buildup across
|
|
2150
|
+
// sessions stays bounded while turns of ONE session stop paying the
|
|
2151
|
+
// executor + MCP re-spawn tax (#215).
|
|
2152
|
+
cacheSessionAgent(sessionId ?? "", resolution.agent, agentFingerprint);
|
|
2093
2153
|
|
|
2094
2154
|
const slim = slimStatus(status) as Record<string, unknown>;
|
|
2095
2155
|
if (finalText !== undefined) {
|
|
@@ -2104,9 +2164,12 @@ async function executeCursorInner(
|
|
|
2104
2164
|
periodicHeartbeat?.stop();
|
|
2105
2165
|
|
|
2106
2166
|
if (err instanceof CancelledFailure) {
|
|
2107
|
-
//
|
|
2108
|
-
//
|
|
2109
|
-
|
|
2167
|
+
// Worker shutdown is infrastructure failure, not pause. The direct
|
|
2168
|
+
// signal check covers a CancelledFailure thrown BEFORE the post-stream
|
|
2169
|
+
// classification ran (workerShutdownDetected still false); no extra
|
|
2170
|
+
// interruption-evidence gate is needed here — the caught
|
|
2171
|
+
// CancelledFailure IS the evidence (#776).
|
|
2172
|
+
if (workerShutdownDetected || (shutdownSignal?.aborted ?? false)) {
|
|
2110
2173
|
console.log(`ExecuteCursor cancelled (worker shutdown) for execution ${executionId}`);
|
|
2111
2174
|
status.phase = ExecutionPhase.EXECUTION_FAILED;
|
|
2112
2175
|
status.error = "Execution interrupted: runner worker was shut down. Retry or resume.";
|
|
@@ -2405,10 +2468,19 @@ export interface BuildPromptInput {
|
|
|
2405
2468
|
* turn.
|
|
2406
2469
|
*/
|
|
2407
2470
|
sessionContext?: string;
|
|
2471
|
+
/**
|
|
2472
|
+
* Platform-declared standing preferences from the execution spec's
|
|
2473
|
+
* `declared_preferences` (stigmer/stigmer#293). Like the bridge, only
|
|
2474
|
+
* the enhanced-prompt path consumes it — deliberately frozen per Cursor
|
|
2475
|
+
* session (DD-002 D3): the first turn delivers it into the agent's own
|
|
2476
|
+
* conversation store, and repeating it on resumed turns would bloat the
|
|
2477
|
+
* store with identical content.
|
|
2478
|
+
*/
|
|
2479
|
+
declaredPreferences?: import("../../shared/declared-preferences.js").DeclaredPreferencesContent;
|
|
2408
2480
|
/**
|
|
2409
2481
|
* Conversation catchup from the execution spec's `conversation_catchup`
|
|
2410
2482
|
* (cloud DD-006): what happened on the channel conversation that the
|
|
2411
|
-
* agent has not seen. PER-TURN, so unlike the
|
|
2483
|
+
* agent has not seen. PER-TURN, so unlike the standing values
|
|
2412
2484
|
* above it rides BOTH prompt paths — the enhanced prompt and a resumed
|
|
2413
2485
|
* turn's prefix (the `interaction_mode` shape). Handback lands
|
|
2414
2486
|
* mid-session on a resumed agent: the resumed path is the one that
|
|
@@ -2543,6 +2615,7 @@ export function buildPrompt(input: BuildPromptInput): string {
|
|
|
2543
2615
|
contextBridge: input.contextBridge,
|
|
2544
2616
|
senderIdentity: input.senderIdentity,
|
|
2545
2617
|
sessionContext: input.sessionContext,
|
|
2618
|
+
declaredPreferences: input.declaredPreferences,
|
|
2546
2619
|
conversationCatchup,
|
|
2547
2620
|
},
|
|
2548
2621
|
{
|
|
@@ -2609,6 +2682,7 @@ export function buildPrompt(input: BuildPromptInput): string {
|
|
|
2609
2682
|
contextBridge: input.contextBridge,
|
|
2610
2683
|
senderIdentity: input.senderIdentity,
|
|
2611
2684
|
sessionContext: input.sessionContext,
|
|
2685
|
+
declaredPreferences: input.declaredPreferences,
|
|
2612
2686
|
conversationCatchup,
|
|
2613
2687
|
});
|
|
2614
2688
|
}
|
|
@@ -31,6 +31,10 @@ import {
|
|
|
31
31
|
type SenderIdentity,
|
|
32
32
|
} from "../../shared/sender-identity.js";
|
|
33
33
|
import { formatSessionContextText } from "../../shared/session-context.js";
|
|
34
|
+
import {
|
|
35
|
+
formatDeclaredPreferencesText,
|
|
36
|
+
type DeclaredPreferencesContent,
|
|
37
|
+
} from "../../shared/declared-preferences.js";
|
|
34
38
|
import {
|
|
35
39
|
visionDisclosureLines,
|
|
36
40
|
type NotViewableEntry,
|
|
@@ -147,11 +151,20 @@ export interface EnhancedPromptOptions {
|
|
|
147
151
|
* store — the context is constant for the session's lifetime.
|
|
148
152
|
*/
|
|
149
153
|
sessionContext?: string;
|
|
154
|
+
/**
|
|
155
|
+
* Platform-declared standing preferences (stigmer/stigmer#293): the org's
|
|
156
|
+
* and user's standing context, server-snapshotted onto the execution
|
|
157
|
+
* spec's `declared_preferences` at create. Like the bridge, it lands in
|
|
158
|
+
* the first message and persists in the cursor agent's own conversation
|
|
159
|
+
* store — deliberately frozen per Cursor session (DD-002 D3): repeating
|
|
160
|
+
* it every resumed turn would bloat the store with identical content.
|
|
161
|
+
*/
|
|
162
|
+
declaredPreferences?: DeclaredPreferencesContent;
|
|
150
163
|
/**
|
|
151
164
|
* Conversation catchup (cloud DD-006): what happened on the channel
|
|
152
165
|
* conversation that the agent has not seen, read from the execution
|
|
153
|
-
* spec's `conversation_catchup`. PER-TURN, unlike the
|
|
154
|
-
*
|
|
166
|
+
* spec's `conversation_catchup`. PER-TURN, unlike the standing siblings
|
|
167
|
+
* above: it rides BOTH prompt paths — this enhanced prompt and
|
|
155
168
|
* a resumed turn's prefix (the `interaction_mode` shape) — because
|
|
156
169
|
* handback lands mid-session on a resumed agent, the exact case the
|
|
157
170
|
* metadata lane cannot reach.
|
|
@@ -232,6 +245,14 @@ export function buildEnhancedPrompt(options: EnhancedPromptOptions): string {
|
|
|
232
245
|
sections.push(formatSenderIdentitySection(options.senderIdentity));
|
|
233
246
|
}
|
|
234
247
|
|
|
248
|
+
// Platform-declared standing facts precede embedder-supplied context
|
|
249
|
+
// (DD-002 D3): both are standing background, but the declared preferences
|
|
250
|
+
// are platform-authored while session context is the embedder's overlay —
|
|
251
|
+
// the more specific overlay reads later and naturally refines.
|
|
252
|
+
if (options.declaredPreferences) {
|
|
253
|
+
sections.push(formatDeclaredPreferencesSection(options.declaredPreferences));
|
|
254
|
+
}
|
|
255
|
+
|
|
235
256
|
// Standing facts about the user (session context) come before the
|
|
236
257
|
// carried conversation (bridge): the bridge may refer back to them.
|
|
237
258
|
if (options.sessionContext) {
|
|
@@ -445,6 +466,12 @@ export function formatSenderIdentitySection(identity: SenderIdentity): string {
|
|
|
445
466
|
return `<conversation_sender>\n${formatSenderIdentityText(identity)}\n</conversation_sender>`;
|
|
446
467
|
}
|
|
447
468
|
|
|
469
|
+
export function formatDeclaredPreferencesSection(
|
|
470
|
+
preferences: DeclaredPreferencesContent,
|
|
471
|
+
): string {
|
|
472
|
+
return `<declared_preferences>\n${formatDeclaredPreferencesText(preferences)}\n</declared_preferences>`;
|
|
473
|
+
}
|
|
474
|
+
|
|
448
475
|
export function formatSessionContextSection(context: string): string {
|
|
449
476
|
return `<session_context>\n${formatSessionContextText(context)}\n</session_context>`;
|
|
450
477
|
}
|
|
@@ -20,19 +20,17 @@
|
|
|
20
20
|
* rides the same proxy fetch-interceptor as every other SDK call, so it
|
|
21
21
|
* works identically in proxy and direct modes.
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
23
|
+
* The harness-neutral halves — the tier enum semantics, and the single
|
|
24
|
+
* UNSPECIFIED→STANDARD resolution point — live in
|
|
25
|
+
* `shared/service-tier.ts` since #361 extended tiers to the native
|
|
26
|
+
* harness; this module keeps only the Cursor-catalog translation.
|
|
26
27
|
*/
|
|
27
28
|
|
|
28
29
|
import { Cursor } from "@cursor/sdk";
|
|
29
30
|
import type { ModelListItem, ModelParameterValue } from "@cursor/sdk";
|
|
30
31
|
import { ServiceTier } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
* The effective tier after platform-default resolution: never UNSPECIFIED.
|
|
34
|
-
*/
|
|
35
|
-
export type EffectiveServiceTier = ServiceTier.STANDARD | ServiceTier.FAST;
|
|
33
|
+
import { serviceTierLabel, type EffectiveServiceTier } from "../../shared/service-tier.js";
|
|
36
34
|
|
|
37
35
|
/**
|
|
38
36
|
* Catalog ids that mean "Cursor picks the model" (Auto). Auto's single
|
|
@@ -72,28 +70,6 @@ export function resetCatalogCacheForTests(): void {
|
|
|
72
70
|
inflightCatalogFetch = null;
|
|
73
71
|
}
|
|
74
72
|
|
|
75
|
-
/**
|
|
76
|
-
* Resolve the configured tier to its effective value. The single place in
|
|
77
|
-
* the platform where UNSPECIFIED becomes STANDARD.
|
|
78
|
-
*/
|
|
79
|
-
export function resolveEffectiveServiceTier(
|
|
80
|
-
configured: ServiceTier | undefined,
|
|
81
|
-
): EffectiveServiceTier {
|
|
82
|
-
return configured === ServiceTier.FAST ? ServiceTier.FAST : ServiceTier.STANDARD;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/** Human-readable tier label for logs and error messages. */
|
|
86
|
-
export function serviceTierLabel(tier: ServiceTier): string {
|
|
87
|
-
switch (tier) {
|
|
88
|
-
case ServiceTier.FAST:
|
|
89
|
-
return "fast";
|
|
90
|
-
case ServiceTier.STANDARD:
|
|
91
|
-
return "standard";
|
|
92
|
-
default:
|
|
93
|
-
return "unspecified";
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
73
|
async function listCatalogModels(apiKey: string): Promise<readonly ModelListItem[]> {
|
|
98
74
|
const now = Date.now();
|
|
99
75
|
if (catalogCache && catalogCache.apiKey === apiKey && catalogCache.expiresAt > now) {
|
|
@@ -47,7 +47,7 @@ import type {
|
|
|
47
47
|
ModelParameterValue,
|
|
48
48
|
} from "@cursor/sdk";
|
|
49
49
|
import { withTimeout, TimeoutError } from "../../shared/with-timeout.js";
|
|
50
|
-
import type { CursorMcpServerConfig } from "./mcp-
|
|
50
|
+
import type { CursorMcpServerConfig } from "./cursor-mcp-config.js";
|
|
51
51
|
|
|
52
52
|
// ---------------------------------------------------------------------------
|
|
53
53
|
// Constants
|