@stigmer/runner 3.11.0 → 3.12.0
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/README.md +2 -0
- package/dist/.build-fingerprint +1 -1
- package/dist/activities/discover-mcp-server.d.ts +7 -0
- package/dist/activities/discover-mcp-server.js +6 -4
- package/dist/activities/discover-mcp-server.js.map +1 -1
- package/dist/activities/emit-event.d.ts +14 -2
- package/dist/activities/emit-event.js +52 -17
- package/dist/activities/emit-event.js.map +1 -1
- package/dist/activities/execute-cursor/attachment-resolver.d.ts +11 -0
- package/dist/activities/execute-cursor/attachment-resolver.js +8 -0
- package/dist/activities/execute-cursor/attachment-resolver.js.map +1 -1
- package/dist/activities/execute-cursor/blueprint-resolver.d.ts +1 -9
- package/dist/activities/execute-cursor/blueprint-resolver.js +0 -1
- package/dist/activities/execute-cursor/blueprint-resolver.js.map +1 -1
- package/dist/activities/execute-cursor/error-classifier.d.ts +19 -0
- package/dist/activities/execute-cursor/error-classifier.js +34 -3
- package/dist/activities/execute-cursor/error-classifier.js.map +1 -1
- package/dist/activities/execute-cursor/index.d.ts +52 -12
- package/dist/activities/execute-cursor/index.js +141 -67
- package/dist/activities/execute-cursor/index.js.map +1 -1
- package/dist/activities/execute-cursor/model-pricing-data.d.ts +2 -0
- package/dist/activities/execute-cursor/model-pricing-data.js +13 -3
- package/dist/activities/execute-cursor/model-pricing-data.js.map +1 -1
- package/dist/activities/execute-cursor/prompt-builder.d.ts +48 -11
- package/dist/activities/execute-cursor/prompt-builder.js +57 -10
- package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
- package/dist/activities/execute-cursor/turn-recovery.d.ts +52 -0
- package/dist/activities/execute-cursor/turn-recovery.js +193 -0
- package/dist/activities/execute-cursor/turn-recovery.js.map +1 -0
- package/dist/activities/execute-deep-agent/attachment-injector.d.ts +11 -0
- package/dist/activities/execute-deep-agent/attachment-injector.js +7 -1
- package/dist/activities/execute-deep-agent/attachment-injector.js.map +1 -1
- package/dist/activities/execute-deep-agent/index.js +0 -15
- package/dist/activities/execute-deep-agent/index.js.map +1 -1
- package/dist/activities/execute-deep-agent/mcp-gate.d.ts +0 -2
- package/dist/activities/execute-deep-agent/mcp-gate.js +0 -1
- package/dist/activities/execute-deep-agent/mcp-gate.js.map +1 -1
- package/dist/activities/execute-deep-agent/prompt-builder.d.ts +7 -8
- package/dist/activities/execute-deep-agent/prompt-builder.js +14 -7
- package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
- package/dist/activities/execute-deep-agent/setup.d.ts +0 -10
- package/dist/activities/execute-deep-agent/setup.js +22 -49
- package/dist/activities/execute-deep-agent/setup.js.map +1 -1
- package/dist/activities/execute-deep-agent/shell-env.d.ts +5 -1
- package/dist/activities/execute-deep-agent/shell-env.js +7 -9
- package/dist/activities/execute-deep-agent/shell-env.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.js +7 -1
- package/dist/activities/execute-deep-agent/subagent-transformer.js.map +1 -1
- package/dist/activities/execute-deep-agent/subagent-wiring.d.ts +17 -3
- package/dist/activities/execute-deep-agent/subagent-wiring.js +14 -2
- package/dist/activities/execute-deep-agent/subagent-wiring.js.map +1 -1
- package/dist/activities/hydrate-workflow-execution.js +8 -5
- package/dist/activities/hydrate-workflow-execution.js.map +1 -1
- package/dist/activities/run-command.d.ts +5 -2
- package/dist/activities/run-command.js +22 -10
- package/dist/activities/run-command.js.map +1 -1
- package/dist/activities/run-env.d.ts +40 -0
- package/dist/activities/run-env.js +66 -0
- package/dist/activities/run-env.js.map +1 -0
- package/dist/bootstrap.js +5 -0
- package/dist/bootstrap.js.map +1 -1
- package/dist/client/stigmer-client.d.ts +83 -26
- package/dist/client/stigmer-client.js +88 -24
- package/dist/client/stigmer-client.js.map +1 -1
- package/dist/config.d.ts +6 -5
- package/dist/config.js.map +1 -1
- package/dist/encryption/config.d.ts +41 -9
- package/dist/encryption/config.js +63 -23
- package/dist/encryption/config.js.map +1 -1
- package/dist/middleware/index.d.ts +3 -0
- package/dist/middleware/index.js +7 -0
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/path-normalization.d.ts +57 -0
- package/dist/middleware/path-normalization.js +109 -0
- package/dist/middleware/path-normalization.js.map +1 -0
- package/dist/middleware/types.d.ts +8 -0
- package/dist/payload-codecs.d.ts +2 -1
- package/dist/payload-codecs.js +7 -3
- package/dist/payload-codecs.js.map +1 -1
- package/dist/runner-manager.js +17 -3
- package/dist/runner-manager.js.map +1 -1
- package/dist/runner.js +7 -3
- package/dist/runner.js.map +1 -1
- package/dist/shared/artifact-storage.d.ts +34 -1
- package/dist/shared/artifact-storage.js +53 -10
- package/dist/shared/artifact-storage.js.map +1 -1
- package/dist/shared/attachment-download-urls.d.ts +62 -0
- package/dist/shared/attachment-download-urls.js +79 -0
- package/dist/shared/attachment-download-urls.js.map +1 -0
- package/dist/shared/channel-attachment.d.ts +1 -1
- package/dist/shared/channel-attachment.js +1 -1
- package/dist/shared/checkpointer/http-saver.d.ts +4 -20
- package/dist/shared/checkpointer/http-saver.js +15 -57
- package/dist/shared/checkpointer/http-saver.js.map +1 -1
- package/dist/shared/conversation-attachment.d.ts +2 -3
- package/dist/shared/conversation-attachment.js +2 -3
- package/dist/shared/conversation-attachment.js.map +1 -1
- package/dist/shared/conversation-catchup.d.ts +9 -2
- package/dist/shared/conversation-catchup.js +39 -6
- package/dist/shared/conversation-catchup.js.map +1 -1
- package/dist/shared/grpc-retry.d.ts +5 -1
- package/dist/shared/grpc-retry.js +5 -1
- package/dist/shared/grpc-retry.js.map +1 -1
- package/dist/shared/http-retry.d.ts +51 -9
- package/dist/shared/http-retry.js +60 -9
- package/dist/shared/http-retry.js.map +1 -1
- package/dist/shared/mcp-manager.d.ts +8 -4
- package/dist/shared/mcp-manager.js +30 -4
- package/dist/shared/mcp-manager.js.map +1 -1
- package/dist/shared/mcp-schema-sanitizer.d.ts +70 -0
- package/dist/shared/mcp-schema-sanitizer.js +197 -0
- package/dist/shared/mcp-schema-sanitizer.js.map +1 -0
- package/dist/shared/mcp-transport-guard.d.ts +2 -2
- package/dist/shared/mcp-transport-guard.js +2 -2
- package/dist/shared/model-client.d.ts +6 -0
- package/dist/shared/model-client.js +14 -3
- package/dist/shared/model-client.js.map +1 -1
- package/dist/shared/model-pricing-data.d.ts +2 -0
- package/dist/shared/model-pricing-data.js +13 -3
- package/dist/shared/model-pricing-data.js.map +1 -1
- package/dist/shared/model-registry.js +3 -2
- package/dist/shared/model-registry.js.map +1 -1
- package/dist/shared/plan-mode-permissions.d.ts +7 -0
- package/dist/shared/plan-mode-permissions.js +7 -0
- package/dist/shared/plan-mode-permissions.js.map +1 -1
- package/dist/shared/registry-endpoint.d.ts +20 -0
- package/dist/shared/registry-endpoint.js +25 -0
- package/dist/shared/registry-endpoint.js.map +1 -1
- package/dist/shared/runner-credential-keys.d.ts +24 -0
- package/dist/shared/runner-credential-keys.js +47 -0
- package/dist/shared/runner-credential-keys.js.map +1 -0
- package/dist/shared/synthesized-attachment.d.ts +4 -4
- package/dist/shared/synthesized-attachment.js +4 -4
- package/dist/workflow-engine/resolve.d.ts +19 -1
- package/dist/workflow-engine/resolve.js +37 -2
- package/dist/workflow-engine/resolve.js.map +1 -1
- package/dist/workflows/connect-mcp-server.js +2 -0
- package/dist/workflows/connect-mcp-server.js.map +1 -1
- package/dist/workflows/types.d.ts +8 -0
- package/package.json +3 -4
- package/src/__test-utils__/__tests__/vitest-global-setup.test.ts +37 -0
- package/src/__test-utils__/fake-artifact-storage.ts +10 -1
- package/src/__test-utils__/vitest-global-setup.ts +50 -0
- package/src/__tests__/bootstrap.test.ts +43 -0
- package/src/__tests__/encryption-codec.test.ts +53 -0
- package/src/__tests__/preflight.test.ts +15 -0
- package/src/activities/__tests__/discover-mcp-server.test.ts +39 -1
- package/src/activities/__tests__/error-classifier.test.ts +94 -2
- package/src/activities/__tests__/run-command.test.ts +221 -0
- package/src/activities/discover-mcp-server.ts +16 -2
- package/src/activities/emit-event.ts +65 -21
- package/src/activities/execute-cursor/__tests__/attachment-resolver.test.ts +63 -3
- package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +173 -31
- package/src/activities/execute-cursor/__tests__/model-pricing.test.ts +62 -1
- package/src/activities/execute-cursor/__tests__/turn-recovery.test.ts +160 -0
- package/src/activities/execute-cursor/attachment-resolver.ts +24 -0
- package/src/activities/execute-cursor/blueprint-resolver.ts +1 -10
- package/src/activities/execute-cursor/error-classifier.ts +40 -3
- package/src/activities/execute-cursor/index.ts +175 -74
- package/src/activities/execute-cursor/model-pricing-data.ts +22 -3
- package/src/activities/execute-cursor/prompt-builder.ts +89 -22
- package/src/activities/execute-cursor/turn-recovery.ts +208 -0
- package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +105 -0
- package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +0 -2
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +0 -1
- package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +0 -1
- package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +2 -7
- package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +174 -0
- package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +71 -0
- package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +0 -1
- package/src/activities/execute-deep-agent/__tests__/shell-env.test.ts +24 -10
- package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +22 -17
- package/src/activities/execute-deep-agent/attachment-injector.ts +20 -1
- package/src/activities/execute-deep-agent/index.ts +0 -19
- package/src/activities/execute-deep-agent/mcp-gate.ts +0 -3
- package/src/activities/execute-deep-agent/prompt-builder.ts +27 -15
- package/src/activities/execute-deep-agent/setup.ts +22 -73
- package/src/activities/execute-deep-agent/shell-env.ts +8 -9
- package/src/activities/execute-deep-agent/subagent-transformer.ts +7 -1
- package/src/activities/execute-deep-agent/subagent-wiring.ts +26 -3
- package/src/activities/hydrate-workflow-execution.ts +8 -5
- package/src/activities/run-command.ts +25 -12
- package/src/activities/run-env.ts +79 -0
- package/src/bootstrap.ts +5 -0
- package/src/client/__tests__/stigmer-client.test.ts +104 -5
- package/src/client/stigmer-client.ts +128 -29
- package/src/config.ts +6 -5
- package/src/encryption/config.ts +87 -23
- package/src/middleware/__tests__/path-normalization.test.ts +140 -0
- package/src/middleware/index.ts +8 -0
- package/src/middleware/path-normalization.ts +125 -0
- package/src/middleware/types.ts +11 -0
- package/src/payload-codecs.ts +8 -2
- package/src/runner-manager.ts +21 -3
- package/src/runner.ts +7 -3
- package/src/shared/__tests__/artifact-storage.test.ts +154 -2
- package/src/shared/__tests__/attachment-download-urls.test.ts +70 -0
- package/src/shared/__tests__/channel-attachment.test.ts +2 -2
- package/src/shared/__tests__/conversation-catchup.test.ts +24 -0
- package/src/shared/__tests__/http-retry.test.ts +5 -4
- package/src/shared/__tests__/mcp-manager.test.ts +53 -13
- package/src/shared/__tests__/mcp-schema-sanitizer.test.ts +267 -0
- package/src/shared/__tests__/model-client.test.ts +46 -0
- package/src/shared/__tests__/model-pricing.test.ts +62 -2
- package/src/shared/__tests__/model-registry.test.ts +22 -0
- package/src/shared/__tests__/synthesized-attachment.test.ts +19 -41
- package/src/shared/artifact-storage.ts +86 -10
- package/src/shared/attachment-download-urls.ts +98 -0
- package/src/shared/channel-attachment.ts +1 -1
- package/src/shared/checkpointer/http-saver.ts +15 -60
- package/src/shared/conversation-attachment.ts +2 -3
- package/src/shared/conversation-catchup.ts +39 -6
- package/src/shared/grpc-retry.ts +5 -1
- package/src/shared/http-retry.ts +98 -9
- package/src/shared/mcp-manager.ts +35 -4
- package/src/shared/mcp-schema-sanitizer.ts +224 -0
- package/src/shared/mcp-transport-guard.ts +2 -2
- package/src/shared/model-client.ts +21 -3
- package/src/shared/model-pricing-data.ts +22 -3
- package/src/shared/model-registry.ts +7 -2
- package/src/shared/plan-mode-permissions.ts +7 -0
- package/src/shared/registry-endpoint.ts +27 -0
- package/src/shared/runner-credential-keys.ts +46 -0
- package/src/shared/synthesized-attachment.ts +4 -4
- package/src/workflow-engine/__tests__/tasks/emit-event.test.ts +127 -49
- package/src/workflow-engine/resolve.ts +48 -2
- package/src/workflows/__tests__/connect-mcp-server.test.ts +25 -0
- package/src/workflows/connect-mcp-server.ts +2 -0
- package/src/workflows/types.ts +8 -0
- package/dist/activities/execute-cursor/mcp-config.d.ts +0 -30
- package/dist/activities/execute-cursor/mcp-config.js +0 -39
- package/dist/activities/execute-cursor/mcp-config.js.map +0 -1
- package/dist/shared/datastore-attachment.d.ts +0 -99
- package/dist/shared/datastore-attachment.js +0 -184
- package/dist/shared/datastore-attachment.js.map +0 -1
- package/src/activities/execute-cursor/mcp-config.ts +0 -66
- package/src/activities/execute-deep-agent/__tests__/datastore-degradation.test.ts +0 -104
- package/src/shared/__tests__/datastore-attachment.test.ts +0 -293
- package/src/shared/datastore-attachment.ts +0 -209
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
*/
|
|
28
28
|
import { InteractionMode, ApprovalAction } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
|
|
29
29
|
import type { Config } from "../../config.js";
|
|
30
|
-
import type { AgentResolution } from "./session-lifecycle.js";
|
|
30
|
+
import type { AgentResolution, AgentResolutionReason } from "./session-lifecycle.js";
|
|
31
31
|
import { type ExecuteActivityInput } from "../../shared/activity-input.js";
|
|
32
32
|
/**
|
|
33
33
|
* Creates the activity functions bound to the runner config.
|
|
@@ -42,8 +42,6 @@ export interface BuildPromptInput {
|
|
|
42
42
|
instructions: string;
|
|
43
43
|
userMessage: string;
|
|
44
44
|
skills: import("./prompt-builder.js").SkillMetadata[];
|
|
45
|
-
/** Datastores attached via `datastore_usages` — the `<available_datastores>` section. */
|
|
46
|
-
datastoreUsages?: import("@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb").DatastoreUsage[];
|
|
47
45
|
/**
|
|
48
46
|
* Serving proactive channels + their templates (the DD-006 D2
|
|
49
47
|
* discovery read) — the `<available_channel_templates>` section.
|
|
@@ -63,6 +61,12 @@ export interface BuildPromptInput {
|
|
|
63
61
|
* catchup — it rides both the enhanced prompt and a resumed turn's prefix.
|
|
64
62
|
*/
|
|
65
63
|
vision?: import("./prompt-builder.js").VisionPromptInfo;
|
|
64
|
+
/**
|
|
65
|
+
* What kind of URL the turn's storage backend mints (issue #532) — keys
|
|
66
|
+
* the input-files hand-off wording. Sourced from the resolved
|
|
67
|
+
* artifactStorage's self-description; absent when no storage resolved.
|
|
68
|
+
*/
|
|
69
|
+
downloadUrlKind?: import("../../shared/attachment-download-urls.js").DownloadUrlKind;
|
|
66
70
|
pendingApprovals: import("@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb").PendingApproval[];
|
|
67
71
|
/**
|
|
68
72
|
* Approved whole-file writes the runner already applied itself (exact-apply).
|
|
@@ -107,6 +111,15 @@ export interface BuildPromptInput {
|
|
|
107
111
|
* usually blank.
|
|
108
112
|
*/
|
|
109
113
|
conversationCatchup?: string;
|
|
114
|
+
/**
|
|
115
|
+
* The turn's recorded transcript rendered as digest lines
|
|
116
|
+
* (turn-recovery.ts), composed from `status.messages` at the call site.
|
|
117
|
+
* Consumed ONLY by the HITL-recovery shape — a fresh agent that replaced
|
|
118
|
+
* a lost one mid-HITL needs the story of the work it no longer remembers
|
|
119
|
+
* (issue #366); every other shape either has native context or no prior
|
|
120
|
+
* work to tell.
|
|
121
|
+
*/
|
|
122
|
+
turnRecoveryDigest?: string;
|
|
110
123
|
}
|
|
111
124
|
/**
|
|
112
125
|
* Select and build the appropriate prompt based on resolution reason and
|
|
@@ -117,20 +130,47 @@ export interface BuildPromptInput {
|
|
|
117
130
|
* volume, or cloud server-side state) — there is no separate continuation
|
|
118
131
|
* store. The prompt therefore depends only on how the agent was resolved:
|
|
119
132
|
*
|
|
120
|
-
* 1. HITL reinvocation -> buildReinvocationPrompt (approval decisions
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
* 2.
|
|
124
|
-
*
|
|
133
|
+
* 1. HITL reinvocation, -> buildReinvocationPrompt (approval decisions
|
|
134
|
+
* resumed agent only; the resumed agent's native context
|
|
135
|
+
* carries the prior conversation)
|
|
136
|
+
* 2. HITL reinvocation, -> buildHitlRecoveryPrompt (full context +
|
|
137
|
+
* fresh agent after the turn's recorded transcript + decisions;
|
|
138
|
+
* resume failure the replacement agent's conversation is
|
|
139
|
+
* empty, and both fresh-agent crossings —
|
|
140
|
+
* resolution-time resume failure and mid-send
|
|
141
|
+
* poisoned-handle recovery — land here by
|
|
142
|
+
* keying on the reason, issue #366)
|
|
143
|
+
* 3. resumed_successfully -> raw userMessage (native context carries it)
|
|
144
|
+
* 4. first execution / fresh -> buildEnhancedPrompt (full instructions +
|
|
125
145
|
* agent after resume failure skills; no prior conversation to inherit)
|
|
126
146
|
*/
|
|
127
147
|
/**
|
|
128
148
|
* Whether this activity invocation is a HITL re-invocation — the turn resumes
|
|
129
149
|
* an agent purely to convey approval decisions, carrying NO user message.
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* vision payload
|
|
133
|
-
*
|
|
150
|
+
* Discriminates the two surfaces that depend on the agent already holding
|
|
151
|
+
* this turn's content natively — the prompt shape (below) and the primary
|
|
152
|
+
* send's vision payload — but never alone: both pair it with
|
|
153
|
+
* `resolution.reason`, because a FRESH agent mid-HITL holds nothing and
|
|
154
|
+
* needs the full re-delivery (issue #366).
|
|
134
155
|
*/
|
|
135
156
|
export declare function isHitlReinvocation(approvalDecisions: Map<string, ApprovalAction> | undefined): approvalDecisions is Map<string, ApprovalAction>;
|
|
157
|
+
/**
|
|
158
|
+
* Whether the PRIMARY send delivers the turn's vision payload. The invariant
|
|
159
|
+
* is "images accompany the user's turn message, wherever the conversation
|
|
160
|
+
* does not already hold them" — so the only send that skips them is a HITL
|
|
161
|
+
* re-invocation of a successfully RESUMED agent, whose native conversation
|
|
162
|
+
* carries the images from the original send. A fresh agent mid-HITL
|
|
163
|
+
* (resolution-time resume failure — issue #366's vision corollary) holds
|
|
164
|
+
* nothing and needs the re-delivery. The mid-send recovery retries always
|
|
165
|
+
* run on a fresh agent, so their send sites carry the payload
|
|
166
|
+
* unconditionally rather than consulting this.
|
|
167
|
+
*/
|
|
168
|
+
export declare function primarySendCarriesImages(approvalDecisions: Map<string, ApprovalAction> | undefined, reason: AgentResolutionReason): boolean;
|
|
169
|
+
/**
|
|
170
|
+
* Append the structured-output contract to a prompt when the execution
|
|
171
|
+
* requests one. A per-turn directive (the buildFromPlan rule): it must ride
|
|
172
|
+
* every prompt this turn sends — the primary send AND the poisoned-handle
|
|
173
|
+
* recovery rebuild, which previously lost it (issue #366 ride-along).
|
|
174
|
+
*/
|
|
175
|
+
export declare function appendStructuredOutputDirective(basePrompt: string, schema: Record<string, unknown> | undefined): string;
|
|
136
176
|
export declare function buildPrompt(input: BuildPromptInput): string;
|
|
@@ -56,7 +56,6 @@ import { StreamingUpdateScheduler, loadStreamingConfig } from "../../shared/stre
|
|
|
56
56
|
import { createCursorEventRecorder } from "./cursor-event-recorder.js";
|
|
57
57
|
import { resolveMcpServers, toCursorMcpConfig, validateMcpServerEnv } from "./mcp-resolver.js";
|
|
58
58
|
import { resolveMcpTransportPosture } from "../../shared/mcp-transport-guard.js";
|
|
59
|
-
import { synthesizeDatastoreAttachment } from "../../shared/datastore-attachment.js";
|
|
60
59
|
import { discoverChannelMessaging, synthesizeChannelAttachment, } from "../../shared/channel-attachment.js";
|
|
61
60
|
import { readChannelConversationId, synthesizeConversationAttachment, } from "../../shared/conversation-attachment.js";
|
|
62
61
|
import { injectSynthesizedAttachment } from "../../shared/synthesized-attachment.js";
|
|
@@ -70,7 +69,8 @@ import { buildCursorSubAgentDefinitions } from "./subagent-config.js";
|
|
|
70
69
|
import { resolveSkills } from "./skill-resolver.js";
|
|
71
70
|
import { removeStigmerSymlink } from "../../shared/workspace/stigmer-link.js";
|
|
72
71
|
import { resolveAttachments } from "./attachment-resolver.js";
|
|
73
|
-
import { buildEnhancedPrompt, buildReinvocationPrompt, formatConversationCatchupSection, formatInputFiles, formatInteractionModePrefix, formatImplementPlanSection } from "./prompt-builder.js";
|
|
72
|
+
import { buildEnhancedPrompt, buildHitlRecoveryPrompt, buildReinvocationPrompt, formatConversationCatchupSection, formatInputFiles, formatInteractionModePrefix, formatImplementPlanSection } from "./prompt-builder.js";
|
|
73
|
+
import { composeTurnRecoveryDigest } from "./turn-recovery.js";
|
|
74
74
|
import { installHitlGate, removeHitlGate } from "./workspace-setup.js";
|
|
75
75
|
import { ensureHitlDir } from "../../shared/workspace/platform-dir.js";
|
|
76
76
|
import { acquireWorkspaceLock, WorkspaceLockCancelledError, WorkspaceLockTimeoutError, } from "../../shared/workspace/workspace-lock.js";
|
|
@@ -554,32 +554,16 @@ turnSeq) {
|
|
|
554
554
|
const attachmentCredential = exchangedRunnerToken
|
|
555
555
|
?? config.stigmerTokenRef?.current
|
|
556
556
|
?? config.stigmerToken;
|
|
557
|
-
// Phase 4a2: Synthesize the
|
|
558
|
-
// Deliberately AFTER resolve + backfill: the attachment has
|
|
559
|
-
// McpServerUsage and reports discovered capabilities, so the
|
|
560
|
-
// backfill's destructiveHint tightener can never force-gate
|
|
561
|
-
//
|
|
562
|
-
//
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
backendEndpoint: config.stigmerBackendEndpoint,
|
|
568
|
-
});
|
|
569
|
-
if (attachment) {
|
|
570
|
-
const resolvedServers = injectSynthesizedAttachment(mcpResolution.resolvedServers, attachment, "datastore records");
|
|
571
|
-
mcpResolution = {
|
|
572
|
-
resolvedServers,
|
|
573
|
-
cursorConfig: toCursorMcpConfig(resolvedServers),
|
|
574
|
-
};
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
// Phase 4a3: Synthesize the channel messaging attachment (DD-006
|
|
578
|
-
// D7/D8), the records attachment's twin. The discovery read is the
|
|
579
|
-
// attachment decision — the control plane runs the SAME candidate
|
|
580
|
-
// computation the send authorization uses — and every failure mode
|
|
581
|
-
// (no channel, OSS, registry down, pre-3a control plane) degrades
|
|
582
|
-
// to honest absence: no tool, no section, execution unharmed.
|
|
557
|
+
// Phase 4a2: Synthesize the channel messaging attachment (DD-006
|
|
558
|
+
// D7/D8). Deliberately AFTER resolve + backfill: the attachment has
|
|
559
|
+
// no McpServerUsage and reports discovered capabilities, so the
|
|
560
|
+
// backfill's destructiveHint tightener can never force-gate its
|
|
561
|
+
// tools; empty approval maps keep it approval-free by construction.
|
|
562
|
+
// The discovery read is the attachment decision — the control plane
|
|
563
|
+
// runs the SAME candidate computation the send authorization uses —
|
|
564
|
+
// and every failure mode (no channel, OSS, registry down, pre-3a
|
|
565
|
+
// control plane) degrades to honest absence: no tool, no section,
|
|
566
|
+
// execution unharmed.
|
|
583
567
|
const channelMessaging = await discoverChannelMessaging(client, exchangedRunnerToken);
|
|
584
568
|
if (channelMessaging.length > 0) {
|
|
585
569
|
const attachment = synthesizeChannelAttachment(channelMessaging, {
|
|
@@ -667,6 +651,7 @@ turnSeq) {
|
|
|
667
651
|
const attachmentEntries = attachmentResults.map((a) => ({
|
|
668
652
|
path: a.relativePath,
|
|
669
653
|
...(a.renamedFrom !== undefined ? { renamedFrom: a.renamedFrom } : {}),
|
|
654
|
+
...(a.downloadUrl !== undefined ? { downloadUrl: a.downloadUrl } : {}),
|
|
670
655
|
}));
|
|
671
656
|
// Vision facts, derived once from the single resolution result: the
|
|
672
657
|
// images the model will see inline (in attachment order) and the ones
|
|
@@ -961,13 +946,13 @@ turnSeq) {
|
|
|
961
946
|
instructions: blueprint.instructions,
|
|
962
947
|
userMessage: spec.message,
|
|
963
948
|
skills: skillMetadata,
|
|
964
|
-
datastoreUsages: blueprint.datastoreUsages,
|
|
965
949
|
channelMessaging,
|
|
966
950
|
subAgents: blueprint.subAgents,
|
|
967
951
|
workspaceDirs: blueprint.workspaceDirs,
|
|
968
952
|
workspaceFileRefs: spec.workspaceFileRefs ?? [],
|
|
969
953
|
attachments: attachmentEntries,
|
|
970
954
|
vision: visionPromptInfo,
|
|
955
|
+
downloadUrlKind: artifactStorage?.downloadUrlKind,
|
|
971
956
|
pendingApprovals: adjudicatedApprovals,
|
|
972
957
|
appliedToolCallIds,
|
|
973
958
|
interactionMode,
|
|
@@ -976,25 +961,36 @@ turnSeq) {
|
|
|
976
961
|
senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
|
|
977
962
|
sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
|
|
978
963
|
conversationCatchup: readConversationCatchup(spec.conversationCatchup),
|
|
964
|
+
// The turn's recorded transcript, seeded from the persisted execution
|
|
965
|
+
// on a reinvocation (Phase 3). Consumed only by the HITL-recovery
|
|
966
|
+
// shape — reached from HERE when the stored handle failed to resume
|
|
967
|
+
// at resolution time (issue #366 crossing 2).
|
|
968
|
+
turnRecoveryDigest: isReinvocation
|
|
969
|
+
? composeTurnRecoveryDigest(status.messages)
|
|
970
|
+
: undefined,
|
|
979
971
|
});
|
|
980
|
-
// Phase 10a: Inject structured output instruction for Cursor
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
972
|
+
// Phase 10a: Inject the structured output instruction for the Cursor
|
|
973
|
+
// harness. A per-turn directive, so like buildFromPlan it must ride every
|
|
974
|
+
// prompt this turn sends — the primary AND the poisoned-handle recovery
|
|
975
|
+
// rebuild (the transport retry re-sends effectivePrompt and inherits it).
|
|
976
|
+
const withStructuredOutputDirective = (basePrompt) => appendStructuredOutputDirective(basePrompt, structuredOutputSchema);
|
|
977
|
+
const effectivePrompt = withStructuredOutputDirective(prompt);
|
|
986
978
|
// Phase 10a1: The turn's vision payload. The invariant is "images
|
|
987
|
-
// accompany the user's turn message
|
|
988
|
-
//
|
|
989
|
-
//
|
|
990
|
-
//
|
|
991
|
-
//
|
|
992
|
-
//
|
|
993
|
-
//
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
const
|
|
979
|
+
// accompany the user's turn message, wherever the conversation does not
|
|
980
|
+
// already hold them" (primarySendCarriesImages): the ONLY send that
|
|
981
|
+
// skips them is a HITL re-invocation of a successfully RESUMED agent,
|
|
982
|
+
// whose native conversation carries the images from the original send.
|
|
983
|
+
// Every send that starts an empty conversation re-delivers them — the
|
|
984
|
+
// ordinary first/fresh-agent primary send, the HITL primary send after a
|
|
985
|
+
// resolution-time resume failure, and both mid-send recovery retries
|
|
986
|
+
// (which always run on a fresh agent, so their sites pass turnImages
|
|
987
|
+
// unconditionally). Attachments re-resolve on every invocation
|
|
988
|
+
// (Phase 5b), so the bytes are in hand even on a re-invocation.
|
|
989
|
+
const turnImages = toCursorImages(visionImages);
|
|
990
|
+
const primarySendImages = primarySendCarriesImages(approvalDecisions, resolution.reason)
|
|
991
|
+
? turnImages
|
|
992
|
+
: [];
|
|
993
|
+
const toSendMessage = (sendPrompt, images) => images.length > 0 ? { text: sendPrompt, images } : sendPrompt;
|
|
998
994
|
// Phase 10a2: Log Stigmer preamble size for context trimming diagnostics
|
|
999
995
|
const promptChars = effectivePrompt.length;
|
|
1000
996
|
const promptEstimatedTokens = Math.ceil(promptChars / 4);
|
|
@@ -1095,7 +1091,7 @@ turnSeq) {
|
|
|
1095
1091
|
// The stall watchdog is armed inside consumeCursorTurnStream (it needs the
|
|
1096
1092
|
// run to cancel), stored on turnState.stallWatchdog so this shared onDelta can
|
|
1097
1093
|
// reset it and the activity's finally can stop it as a backstop.
|
|
1098
|
-
const run = await resolution.agent.send(toSendMessage(effectivePrompt), {
|
|
1094
|
+
const run = await resolution.agent.send(toSendMessage(effectivePrompt, primarySendImages), {
|
|
1099
1095
|
onDelta: (event) => {
|
|
1100
1096
|
if (!turnFirstEventEmitted) {
|
|
1101
1097
|
turnFirstEventEmitted = true;
|
|
@@ -1412,10 +1408,11 @@ turnSeq) {
|
|
|
1412
1408
|
// poisoned-handle path leaked the fresh agent — it closed the stale one.)
|
|
1413
1409
|
resolution = { ...resolution, agent: freshAgent, agentId: freshAgent.agentId, isNew: true };
|
|
1414
1410
|
turnState.streamErrorMessage = undefined;
|
|
1415
|
-
// The retry carries the turn's
|
|
1416
|
-
//
|
|
1417
|
-
// silently lose the user's photo on
|
|
1418
|
-
|
|
1411
|
+
// The retry always carries the turn's full image payload — never the
|
|
1412
|
+
// primary send's HITL-trimmed set: the fresh agent's conversation is
|
|
1413
|
+
// empty, so skipping them here would silently lose the user's photo on
|
|
1414
|
+
// a recovered turn (issue #366's vision corollary).
|
|
1415
|
+
const retryRun = await freshAgent.send(toSendMessage(retryPrompt, turnImages), {
|
|
1419
1416
|
onDelta: makeCursorTurnOnDelta(onDeltaDeps),
|
|
1420
1417
|
});
|
|
1421
1418
|
await consumeCursorTurnStream(retryRun, streamDeps);
|
|
@@ -1524,14 +1521,18 @@ turnSeq) {
|
|
|
1524
1521
|
instructions: blueprint.instructions,
|
|
1525
1522
|
userMessage: spec.message,
|
|
1526
1523
|
skills: skillMetadata,
|
|
1527
|
-
datastoreUsages: blueprint.datastoreUsages,
|
|
1528
1524
|
channelMessaging,
|
|
1529
1525
|
subAgents: blueprint.subAgents,
|
|
1530
1526
|
workspaceDirs: blueprint.workspaceDirs,
|
|
1531
1527
|
workspaceFileRefs: spec.workspaceFileRefs ?? [],
|
|
1532
1528
|
attachments: attachmentEntries,
|
|
1533
1529
|
vision: visionPromptInfo,
|
|
1530
|
+
downloadUrlKind: artifactStorage?.downloadUrlKind,
|
|
1534
1531
|
pendingApprovals: adjudicatedApprovals,
|
|
1532
|
+
// Without the applied set, the HITL-recovery prompt would tell
|
|
1533
|
+
// the fresh agent to carry out writes the runner already
|
|
1534
|
+
// exact-applied (the primary call at Phase 10 passes it too).
|
|
1535
|
+
appliedToolCallIds,
|
|
1535
1536
|
interactionMode,
|
|
1536
1537
|
// buildFromPlan was silently dropped here until T03 Sitting 3 —
|
|
1537
1538
|
// a build turn that hit handle recovery lost its directive. The
|
|
@@ -1542,6 +1543,10 @@ turnSeq) {
|
|
|
1542
1543
|
senderIdentity: readSenderIdentity(blueprint.sessionSpec.metadata),
|
|
1543
1544
|
sessionContext: readSessionContext(blueprint.sessionSpec.metadata),
|
|
1544
1545
|
conversationCatchup: readConversationCatchup(spec.conversationCatchup),
|
|
1546
|
+
// Composed fresh (not reused from Phase 10): the failed primary
|
|
1547
|
+
// stream may have appended partial work onto status.messages,
|
|
1548
|
+
// and the replacement agent should know about that too.
|
|
1549
|
+
turnRecoveryDigest: composeTurnRecoveryDigest(status.messages),
|
|
1545
1550
|
});
|
|
1546
1551
|
console.log(`ExecuteCursor retry with fresh agent: execution=${executionId}, ` +
|
|
1547
1552
|
`newAgentId=${freshAgent.agentId}`);
|
|
@@ -1554,7 +1559,11 @@ turnSeq) {
|
|
|
1554
1559
|
catch (updateErr) {
|
|
1555
1560
|
console.warn("Failed to update session with fresh agentId (non-fatal):", updateErr);
|
|
1556
1561
|
}
|
|
1557
|
-
|
|
1562
|
+
// Same per-turn directive rule as buildFromPlan above: a
|
|
1563
|
+
// structured-output turn keeps its output contract on the rebuilt
|
|
1564
|
+
// prompt (the transport retry re-sends effectivePrompt and
|
|
1565
|
+
// inherits it without help).
|
|
1566
|
+
const outcome = await runRecoveryStream(freshAgent, withStructuredOutputDirective(freshPrompt));
|
|
1558
1567
|
if (!outcome.proceeded) {
|
|
1559
1568
|
if (outcome.terminal.kind === "return")
|
|
1560
1569
|
return slimStatus(status);
|
|
@@ -1986,30 +1995,95 @@ function seedCursorTranscriptFromExecution(status, execution) {
|
|
|
1986
1995
|
* volume, or cloud server-side state) — there is no separate continuation
|
|
1987
1996
|
* store. The prompt therefore depends only on how the agent was resolved:
|
|
1988
1997
|
*
|
|
1989
|
-
* 1. HITL reinvocation -> buildReinvocationPrompt (approval decisions
|
|
1990
|
-
*
|
|
1991
|
-
*
|
|
1992
|
-
* 2.
|
|
1993
|
-
*
|
|
1998
|
+
* 1. HITL reinvocation, -> buildReinvocationPrompt (approval decisions
|
|
1999
|
+
* resumed agent only; the resumed agent's native context
|
|
2000
|
+
* carries the prior conversation)
|
|
2001
|
+
* 2. HITL reinvocation, -> buildHitlRecoveryPrompt (full context +
|
|
2002
|
+
* fresh agent after the turn's recorded transcript + decisions;
|
|
2003
|
+
* resume failure the replacement agent's conversation is
|
|
2004
|
+
* empty, and both fresh-agent crossings —
|
|
2005
|
+
* resolution-time resume failure and mid-send
|
|
2006
|
+
* poisoned-handle recovery — land here by
|
|
2007
|
+
* keying on the reason, issue #366)
|
|
2008
|
+
* 3. resumed_successfully -> raw userMessage (native context carries it)
|
|
2009
|
+
* 4. first execution / fresh -> buildEnhancedPrompt (full instructions +
|
|
1994
2010
|
* agent after resume failure skills; no prior conversation to inherit)
|
|
1995
2011
|
*/
|
|
1996
2012
|
/**
|
|
1997
2013
|
* Whether this activity invocation is a HITL re-invocation — the turn resumes
|
|
1998
2014
|
* an agent purely to convey approval decisions, carrying NO user message.
|
|
1999
|
-
*
|
|
2000
|
-
*
|
|
2001
|
-
* vision payload
|
|
2002
|
-
*
|
|
2015
|
+
* Discriminates the two surfaces that depend on the agent already holding
|
|
2016
|
+
* this turn's content natively — the prompt shape (below) and the primary
|
|
2017
|
+
* send's vision payload — but never alone: both pair it with
|
|
2018
|
+
* `resolution.reason`, because a FRESH agent mid-HITL holds nothing and
|
|
2019
|
+
* needs the full re-delivery (issue #366).
|
|
2003
2020
|
*/
|
|
2004
2021
|
export function isHitlReinvocation(approvalDecisions) {
|
|
2005
2022
|
return approvalDecisions !== undefined && approvalDecisions.size > 0;
|
|
2006
2023
|
}
|
|
2024
|
+
/**
|
|
2025
|
+
* Whether the PRIMARY send delivers the turn's vision payload. The invariant
|
|
2026
|
+
* is "images accompany the user's turn message, wherever the conversation
|
|
2027
|
+
* does not already hold them" — so the only send that skips them is a HITL
|
|
2028
|
+
* re-invocation of a successfully RESUMED agent, whose native conversation
|
|
2029
|
+
* carries the images from the original send. A fresh agent mid-HITL
|
|
2030
|
+
* (resolution-time resume failure — issue #366's vision corollary) holds
|
|
2031
|
+
* nothing and needs the re-delivery. The mid-send recovery retries always
|
|
2032
|
+
* run on a fresh agent, so their send sites carry the payload
|
|
2033
|
+
* unconditionally rather than consulting this.
|
|
2034
|
+
*/
|
|
2035
|
+
export function primarySendCarriesImages(approvalDecisions, reason) {
|
|
2036
|
+
return !(isHitlReinvocation(approvalDecisions) && reason === "resumed_successfully");
|
|
2037
|
+
}
|
|
2038
|
+
/**
|
|
2039
|
+
* Append the structured-output contract to a prompt when the execution
|
|
2040
|
+
* requests one. A per-turn directive (the buildFromPlan rule): it must ride
|
|
2041
|
+
* every prompt this turn sends — the primary send AND the poisoned-handle
|
|
2042
|
+
* recovery rebuild, which previously lost it (issue #366 ride-along).
|
|
2043
|
+
*/
|
|
2044
|
+
export function appendStructuredOutputDirective(basePrompt, schema) {
|
|
2045
|
+
if (!schema)
|
|
2046
|
+
return basePrompt;
|
|
2047
|
+
const schemaStr = JSON.stringify(schema, null, 2);
|
|
2048
|
+
return basePrompt + `\n\n---\nCRITICAL OUTPUT REQUIREMENT:\nYour final response MUST be a single valid JSON object (no markdown, no commentary, no code fences) that matches this schema:\n${schemaStr}\n\nRespond with ONLY the JSON object. Nothing else.`;
|
|
2049
|
+
}
|
|
2007
2050
|
export function buildPrompt(input) {
|
|
2008
2051
|
const { resolution, approvalDecisions, instructions, userMessage, skills, subAgents, workspaceDirs, workspaceFileRefs, attachments, interactionMode, buildFromPlan, conversationCatchup, } = input;
|
|
2009
|
-
// HITL reinvocation: the
|
|
2010
|
-
//
|
|
2011
|
-
//
|
|
2052
|
+
// HITL reinvocation: the decisions-only prompt is correct ONLY while the
|
|
2053
|
+
// agent's native context still carries the prior conversation — which only
|
|
2054
|
+
// resumed_successfully guarantees. Any other reason means a fresh agent
|
|
2055
|
+
// mid-HITL (in practice created_after_resume_failure: the stored handle
|
|
2056
|
+
// failed to resume, or a poisoned handle was replaced mid-send), which
|
|
2057
|
+
// gets the full recovery shape instead — enhanced context + the turn's
|
|
2058
|
+
// recorded transcript + the same decisions — because the bare decisions on
|
|
2059
|
+
// an empty conversation strand the agent with instructions and no story,
|
|
2060
|
+
// and the session inherits that amnesia permanently (issue #366).
|
|
2012
2061
|
if (isHitlReinvocation(approvalDecisions)) {
|
|
2062
|
+
if (resolution.reason !== "resumed_successfully") {
|
|
2063
|
+
return buildHitlRecoveryPrompt({
|
|
2064
|
+
instructions,
|
|
2065
|
+
userMessage,
|
|
2066
|
+
skills,
|
|
2067
|
+
channelMessaging: input.channelMessaging ?? [],
|
|
2068
|
+
subAgents,
|
|
2069
|
+
workspaceDirs,
|
|
2070
|
+
workspaceFileRefs,
|
|
2071
|
+
attachments,
|
|
2072
|
+
vision: input.vision,
|
|
2073
|
+
downloadUrlKind: input.downloadUrlKind,
|
|
2074
|
+
interactionMode,
|
|
2075
|
+
buildFromPlan,
|
|
2076
|
+
contextBridge: input.contextBridge,
|
|
2077
|
+
senderIdentity: input.senderIdentity,
|
|
2078
|
+
sessionContext: input.sessionContext,
|
|
2079
|
+
conversationCatchup,
|
|
2080
|
+
}, {
|
|
2081
|
+
turnDigest: input.turnRecoveryDigest,
|
|
2082
|
+
pendingApprovals: input.pendingApprovals,
|
|
2083
|
+
approvalDecisions,
|
|
2084
|
+
appliedToolCallIds: input.appliedToolCallIds,
|
|
2085
|
+
});
|
|
2086
|
+
}
|
|
2013
2087
|
return buildReinvocationPrompt(input.pendingApprovals, approvalDecisions, input.appliedToolCallIds);
|
|
2014
2088
|
}
|
|
2015
2089
|
// A successfully resumed agent carries its own conversation context via the
|
|
@@ -2031,7 +2105,7 @@ export function buildPrompt(input) {
|
|
|
2031
2105
|
formatInteractionModePrefix(interactionMode),
|
|
2032
2106
|
formatImplementPlanSection(buildFromPlan, attachments),
|
|
2033
2107
|
attachments.length > 0
|
|
2034
|
-
? formatInputFiles(attachments, input.vision)
|
|
2108
|
+
? formatInputFiles(attachments, input.vision, input.downloadUrlKind)
|
|
2035
2109
|
: undefined,
|
|
2036
2110
|
conversationCatchup !== undefined
|
|
2037
2111
|
? formatConversationCatchupSection(conversationCatchup)
|
|
@@ -2048,13 +2122,13 @@ export function buildPrompt(input) {
|
|
|
2048
2122
|
instructions,
|
|
2049
2123
|
userMessage,
|
|
2050
2124
|
skills,
|
|
2051
|
-
datastoreUsages: input.datastoreUsages ?? [],
|
|
2052
2125
|
channelMessaging: input.channelMessaging ?? [],
|
|
2053
2126
|
subAgents,
|
|
2054
2127
|
workspaceDirs,
|
|
2055
2128
|
workspaceFileRefs,
|
|
2056
2129
|
attachments,
|
|
2057
2130
|
vision: input.vision,
|
|
2131
|
+
downloadUrlKind: input.downloadUrlKind,
|
|
2058
2132
|
interactionMode,
|
|
2059
2133
|
buildFromPlan,
|
|
2060
2134
|
contextBridge: input.contextBridge,
|