@stigmer/runner 3.11.1-dev.20260812192248 → 3.12.1

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.
Files changed (108) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/activities/execute-cursor/attachment-resolver.d.ts +11 -0
  3. package/dist/activities/execute-cursor/attachment-resolver.js +8 -0
  4. package/dist/activities/execute-cursor/attachment-resolver.js.map +1 -1
  5. package/dist/activities/execute-cursor/blueprint-resolver.d.ts +1 -9
  6. package/dist/activities/execute-cursor/blueprint-resolver.js +0 -1
  7. package/dist/activities/execute-cursor/blueprint-resolver.js.map +1 -1
  8. package/dist/activities/execute-cursor/index.d.ts +6 -2
  9. package/dist/activities/execute-cursor/index.js +16 -32
  10. package/dist/activities/execute-cursor/index.js.map +1 -1
  11. package/dist/activities/execute-cursor/prompt-builder.d.ts +15 -11
  12. package/dist/activities/execute-cursor/prompt-builder.js +20 -10
  13. package/dist/activities/execute-cursor/prompt-builder.js.map +1 -1
  14. package/dist/activities/execute-deep-agent/attachment-injector.d.ts +34 -8
  15. package/dist/activities/execute-deep-agent/attachment-injector.js +111 -106
  16. package/dist/activities/execute-deep-agent/attachment-injector.js.map +1 -1
  17. package/dist/activities/execute-deep-agent/index.js +0 -15
  18. package/dist/activities/execute-deep-agent/index.js.map +1 -1
  19. package/dist/activities/execute-deep-agent/mcp-gate.d.ts +0 -2
  20. package/dist/activities/execute-deep-agent/mcp-gate.js +0 -1
  21. package/dist/activities/execute-deep-agent/mcp-gate.js.map +1 -1
  22. package/dist/activities/execute-deep-agent/prompt-builder.d.ts +7 -8
  23. package/dist/activities/execute-deep-agent/prompt-builder.js +25 -8
  24. package/dist/activities/execute-deep-agent/prompt-builder.js.map +1 -1
  25. package/dist/activities/execute-deep-agent/setup.d.ts +0 -10
  26. package/dist/activities/execute-deep-agent/setup.js +13 -45
  27. package/dist/activities/execute-deep-agent/setup.js.map +1 -1
  28. package/dist/config.d.ts +6 -5
  29. package/dist/config.js.map +1 -1
  30. package/dist/middleware/path-normalization.d.ts +15 -2
  31. package/dist/middleware/path-normalization.js +39 -5
  32. package/dist/middleware/path-normalization.js.map +1 -1
  33. package/dist/shared/artifact-storage.d.ts +11 -0
  34. package/dist/shared/artifact-storage.js +2 -0
  35. package/dist/shared/artifact-storage.js.map +1 -1
  36. package/dist/shared/attachment-download-urls.d.ts +62 -0
  37. package/dist/shared/attachment-download-urls.js +79 -0
  38. package/dist/shared/attachment-download-urls.js.map +1 -0
  39. package/dist/shared/channel-attachment.d.ts +1 -1
  40. package/dist/shared/channel-attachment.js +1 -1
  41. package/dist/shared/conversation-attachment.d.ts +2 -3
  42. package/dist/shared/conversation-attachment.js +2 -3
  43. package/dist/shared/conversation-attachment.js.map +1 -1
  44. package/dist/shared/mcp-enabled-tools.d.ts +6 -2
  45. package/dist/shared/mcp-enabled-tools.js +6 -2
  46. package/dist/shared/mcp-enabled-tools.js.map +1 -1
  47. package/dist/shared/mcp-transport-guard.d.ts +2 -2
  48. package/dist/shared/mcp-transport-guard.js +2 -2
  49. package/dist/shared/plan-mode-permissions.d.ts +46 -10
  50. package/dist/shared/plan-mode-permissions.js +56 -12
  51. package/dist/shared/plan-mode-permissions.js.map +1 -1
  52. package/dist/shared/synthesized-attachment.d.ts +4 -4
  53. package/dist/shared/synthesized-attachment.js +4 -4
  54. package/dist/shared/zip-extract.d.ts +24 -6
  55. package/dist/shared/zip-extract.js +31 -90
  56. package/dist/shared/zip-extract.js.map +1 -1
  57. package/dist/shared/zip-structure.d.ts +61 -0
  58. package/dist/shared/zip-structure.js +128 -0
  59. package/dist/shared/zip-structure.js.map +1 -0
  60. package/package.json +2 -2
  61. package/src/__test-utils__/fake-artifact-storage.ts +10 -1
  62. package/src/__test-utils__/zip-fixtures.ts +206 -0
  63. package/src/activities/execute-cursor/__tests__/attachment-resolver.test.ts +63 -3
  64. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +62 -29
  65. package/src/activities/execute-cursor/__tests__/skill-resolver.test.ts +3 -42
  66. package/src/activities/execute-cursor/attachment-resolver.ts +24 -0
  67. package/src/activities/execute-cursor/blueprint-resolver.ts +1 -10
  68. package/src/activities/execute-cursor/index.ts +22 -37
  69. package/src/activities/execute-cursor/prompt-builder.ts +38 -22
  70. package/src/activities/execute-deep-agent/__tests__/attachment-injector.test.ts +270 -126
  71. package/src/activities/execute-deep-agent/__tests__/hitl-reject.test.ts +0 -2
  72. package/src/activities/execute-deep-agent/__tests__/hitl-resume-approve-all.test.ts +0 -1
  73. package/src/activities/execute-deep-agent/__tests__/hitl-resume-history.test.ts +0 -1
  74. package/src/activities/execute-deep-agent/__tests__/mcp-gate.test.ts +2 -7
  75. package/src/activities/execute-deep-agent/__tests__/plan-mode-path-normalization.test.ts +246 -37
  76. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +78 -2
  77. package/src/activities/execute-deep-agent/__tests__/sequential-gate-resume.test.ts +0 -1
  78. package/src/activities/execute-deep-agent/__tests__/subagent-plan-mode-permissions.test.ts +35 -4
  79. package/src/activities/execute-deep-agent/attachment-injector.ts +166 -143
  80. package/src/activities/execute-deep-agent/index.ts +0 -19
  81. package/src/activities/execute-deep-agent/mcp-gate.ts +0 -3
  82. package/src/activities/execute-deep-agent/prompt-builder.ts +38 -16
  83. package/src/activities/execute-deep-agent/setup.ts +13 -68
  84. package/src/config.ts +6 -5
  85. package/src/middleware/__tests__/path-normalization.test.ts +29 -3
  86. package/src/middleware/path-normalization.ts +42 -5
  87. package/src/shared/__tests__/artifact-storage.test.ts +9 -0
  88. package/src/shared/__tests__/attachment-download-urls.test.ts +70 -0
  89. package/src/shared/__tests__/channel-attachment.test.ts +2 -2
  90. package/src/shared/__tests__/plan-mode-permissions.test.ts +58 -0
  91. package/src/shared/__tests__/synthesized-attachment.test.ts +19 -41
  92. package/src/shared/__tests__/zip-extract.test.ts +106 -89
  93. package/src/shared/artifact-storage.ts +11 -0
  94. package/src/shared/attachment-download-urls.ts +98 -0
  95. package/src/shared/channel-attachment.ts +1 -1
  96. package/src/shared/conversation-attachment.ts +2 -3
  97. package/src/shared/mcp-enabled-tools.ts +6 -2
  98. package/src/shared/mcp-transport-guard.ts +2 -2
  99. package/src/shared/plan-mode-permissions.ts +59 -12
  100. package/src/shared/synthesized-attachment.ts +4 -4
  101. package/src/shared/zip-extract.ts +35 -117
  102. package/src/shared/zip-structure.ts +181 -0
  103. package/dist/shared/datastore-attachment.d.ts +0 -99
  104. package/dist/shared/datastore-attachment.js +0 -184
  105. package/dist/shared/datastore-attachment.js.map +0 -1
  106. package/src/activities/execute-deep-agent/__tests__/datastore-degradation.test.ts +0 -104
  107. package/src/shared/__tests__/datastore-attachment.test.ts +0 -293
  108. package/src/shared/datastore-attachment.ts +0 -209
@@ -72,7 +72,6 @@ import { StreamingUpdateScheduler, loadStreamingConfig } from "../../shared/stre
72
72
  import { createCursorEventRecorder } from "./cursor-event-recorder.js";
73
73
  import { resolveMcpServers, toCursorMcpConfig, validateMcpServerEnv } from "./mcp-resolver.js";
74
74
  import { resolveMcpTransportPosture } from "../../shared/mcp-transport-guard.js";
75
- import { synthesizeDatastoreAttachment } from "../../shared/datastore-attachment.js";
76
75
  import {
77
76
  discoverChannelMessaging,
78
77
  synthesizeChannelAttachment,
@@ -665,35 +664,16 @@ async function executeCursorInner(
665
664
  ?? config.stigmerTokenRef?.current
666
665
  ?? config.stigmerToken;
667
666
 
668
- // Phase 4a2: Synthesize the datastore records attachment (T05).
669
- // Deliberately AFTER resolve + backfill: the attachment has no
670
- // McpServerUsage and reports discovered capabilities, so the
671
- // backfill's destructiveHint tightener can never force-gate
672
- // delete_record (which on channels would be silently skipped).
673
- // Empty approval maps keep it approval-free by construction.
674
- if (blueprint.datastoreUsages.length > 0) {
675
- const attachment = synthesizeDatastoreAttachment(blueprint.datastoreUsages, {
676
- bridgeEndpoint: config.mcpBridgeEndpoint,
677
- credential: attachmentCredential,
678
- backendEndpoint: config.stigmerBackendEndpoint,
679
- });
680
- if (attachment) {
681
- const resolvedServers = injectSynthesizedAttachment(
682
- mcpResolution.resolvedServers, attachment, "datastore records",
683
- );
684
- mcpResolution = {
685
- resolvedServers,
686
- cursorConfig: toCursorMcpConfig(resolvedServers),
687
- };
688
- }
689
- }
690
-
691
- // Phase 4a3: Synthesize the channel messaging attachment (DD-006
692
- // D7/D8), the records attachment's twin. The discovery read is the
693
- // attachment decision — the control plane runs the SAME candidate
694
- // computation the send authorization uses — and every failure mode
695
- // (no channel, OSS, registry down, pre-3a control plane) degrades
696
- // to honest absence: no tool, no section, execution unharmed.
667
+ // Phase 4a2: Synthesize the channel messaging attachment (DD-006
668
+ // D7/D8). Deliberately AFTER resolve + backfill: the attachment has
669
+ // no McpServerUsage and reports discovered capabilities, so the
670
+ // backfill's destructiveHint tightener can never force-gate its
671
+ // tools; empty approval maps keep it approval-free by construction.
672
+ // The discovery read is the attachment decision — the control plane
673
+ // runs the SAME candidate computation the send authorization uses —
674
+ // and every failure mode (no channel, OSS, registry down, pre-3a
675
+ // control plane) degrades to honest absence: no tool, no section,
676
+ // execution unharmed.
697
677
  const channelMessaging = await discoverChannelMessaging(client, exchangedRunnerToken);
698
678
  if (channelMessaging.length > 0) {
699
679
  const attachment = synthesizeChannelAttachment(channelMessaging, {
@@ -802,6 +782,7 @@ async function executeCursorInner(
802
782
  const attachmentEntries = attachmentResults.map((a) => ({
803
783
  path: a.relativePath,
804
784
  ...(a.renamedFrom !== undefined ? { renamedFrom: a.renamedFrom } : {}),
785
+ ...(a.downloadUrl !== undefined ? { downloadUrl: a.downloadUrl } : {}),
805
786
  }));
806
787
  // Vision facts, derived once from the single resolution result: the
807
788
  // images the model will see inline (in attachment order) and the ones
@@ -1147,13 +1128,13 @@ async function executeCursorInner(
1147
1128
  instructions: blueprint.instructions,
1148
1129
  userMessage: spec.message,
1149
1130
  skills: skillMetadata,
1150
- datastoreUsages: blueprint.datastoreUsages,
1151
1131
  channelMessaging,
1152
1132
  subAgents: blueprint.subAgents,
1153
1133
  workspaceDirs: blueprint.workspaceDirs,
1154
1134
  workspaceFileRefs: spec.workspaceFileRefs ?? [],
1155
1135
  attachments: attachmentEntries,
1156
1136
  vision: visionPromptInfo,
1137
+ downloadUrlKind: artifactStorage?.downloadUrlKind,
1157
1138
  pendingApprovals: adjudicatedApprovals,
1158
1139
  appliedToolCallIds,
1159
1140
  interactionMode,
@@ -1821,13 +1802,13 @@ async function executeCursorInner(
1821
1802
  instructions: blueprint.instructions,
1822
1803
  userMessage: spec.message,
1823
1804
  skills: skillMetadata,
1824
- datastoreUsages: blueprint.datastoreUsages,
1825
1805
  channelMessaging,
1826
1806
  subAgents: blueprint.subAgents,
1827
1807
  workspaceDirs: blueprint.workspaceDirs,
1828
1808
  workspaceFileRefs: spec.workspaceFileRefs ?? [],
1829
1809
  attachments: attachmentEntries,
1830
1810
  vision: visionPromptInfo,
1811
+ downloadUrlKind: artifactStorage?.downloadUrlKind,
1831
1812
  pendingApprovals: adjudicatedApprovals,
1832
1813
  // Without the applied set, the HITL-recovery prompt would tell
1833
1814
  // the fresh agent to carry out writes the runner already
@@ -2367,8 +2348,6 @@ export interface BuildPromptInput {
2367
2348
  instructions: string;
2368
2349
  userMessage: string;
2369
2350
  skills: import("./prompt-builder.js").SkillMetadata[];
2370
- /** Datastores attached via `datastore_usages` — the `<available_datastores>` section. */
2371
- datastoreUsages?: import("@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb").DatastoreUsage[];
2372
2351
  /**
2373
2352
  * Serving proactive channels + their templates (the DD-006 D2
2374
2353
  * discovery read) — the `<available_channel_templates>` section.
@@ -2388,6 +2367,12 @@ export interface BuildPromptInput {
2388
2367
  * catchup — it rides both the enhanced prompt and a resumed turn's prefix.
2389
2368
  */
2390
2369
  vision?: import("./prompt-builder.js").VisionPromptInfo;
2370
+ /**
2371
+ * What kind of URL the turn's storage backend mints (issue #532) — keys
2372
+ * the input-files hand-off wording. Sourced from the resolved
2373
+ * artifactStorage's self-description; absent when no storage resolved.
2374
+ */
2375
+ downloadUrlKind?: import("../../shared/attachment-download-urls.js").DownloadUrlKind;
2391
2376
  pendingApprovals: import("@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb").PendingApproval[];
2392
2377
  /**
2393
2378
  * Approved whole-file writes the runner already applied itself (exact-apply).
@@ -2546,13 +2531,13 @@ export function buildPrompt(input: BuildPromptInput): string {
2546
2531
  instructions,
2547
2532
  userMessage,
2548
2533
  skills,
2549
- datastoreUsages: input.datastoreUsages ?? [],
2550
2534
  channelMessaging: input.channelMessaging ?? [],
2551
2535
  subAgents,
2552
2536
  workspaceDirs,
2553
2537
  workspaceFileRefs,
2554
2538
  attachments,
2555
2539
  vision: input.vision,
2540
+ downloadUrlKind: input.downloadUrlKind,
2556
2541
  interactionMode,
2557
2542
  buildFromPlan,
2558
2543
  contextBridge: input.contextBridge,
@@ -2594,7 +2579,7 @@ export function buildPrompt(input: BuildPromptInput): string {
2594
2579
  formatInteractionModePrefix(interactionMode),
2595
2580
  formatImplementPlanSection(buildFromPlan, attachments),
2596
2581
  attachments.length > 0
2597
- ? formatInputFiles(attachments, input.vision)
2582
+ ? formatInputFiles(attachments, input.vision, input.downloadUrlKind)
2598
2583
  : undefined,
2599
2584
  conversationCatchup !== undefined
2600
2585
  ? formatConversationCatchupSection(conversationCatchup)
@@ -2612,13 +2597,13 @@ export function buildPrompt(input: BuildPromptInput): string {
2612
2597
  instructions,
2613
2598
  userMessage,
2614
2599
  skills,
2615
- datastoreUsages: input.datastoreUsages ?? [],
2616
2600
  channelMessaging: input.channelMessaging ?? [],
2617
2601
  subAgents,
2618
2602
  workspaceDirs,
2619
2603
  workspaceFileRefs,
2620
2604
  attachments,
2621
2605
  vision: input.vision,
2606
+ downloadUrlKind: input.downloadUrlKind,
2622
2607
  interactionMode,
2623
2608
  buildFromPlan,
2624
2609
  contextBridge: input.contextBridge,
@@ -17,12 +17,11 @@
17
17
  */
18
18
 
19
19
  import { resolve } from "node:path";
20
- import type { DatastoreUsage, SubAgent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
20
+ import type { SubAgent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
21
21
  import type { PendingApproval } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/approval_pb";
22
22
  import { ApprovalAction, InteractionMode } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
23
23
  import { formatContextBridgeText } from "../../shared/context-bridge.js";
24
24
  import { formatConversationCatchupText } from "../../shared/conversation-catchup.js";
25
- import { formatDatastoresSection } from "../../shared/datastore-attachment.js";
26
25
  import {
27
26
  formatChannelTemplatesSection,
28
27
  type ChannelMessagingInfo,
@@ -36,6 +35,10 @@ import {
36
35
  visionDisclosureLines,
37
36
  type NotViewableEntry,
38
37
  } from "../../shared/attachment-vision.js";
38
+ import {
39
+ downloadUrlDisclosureLine,
40
+ type DownloadUrlKind,
41
+ } from "../../shared/attachment-download-urls.js";
39
42
  import { formatTurnRecoveryText } from "./turn-recovery.js";
40
43
  import { PLAN_MODE_DIRECTIVE } from "../../shared/plan-mode-prompt.js";
41
44
  import {
@@ -82,21 +85,18 @@ export interface AttachmentPromptEntry {
82
85
  path: string;
83
86
  /** Original filename, present only when a duplicate name was renamed. */
84
87
  renamedFrom?: string;
88
+ /**
89
+ * Download URL for the attachment's stored object, when one was minted
90
+ * (shared/attachment-download-urls.ts) — rendered beside the path so the
91
+ * agent can hand the file to tools that cannot read this filesystem.
92
+ */
93
+ downloadUrl?: string;
85
94
  }
86
95
 
87
96
  export interface EnhancedPromptOptions {
88
97
  instructions: string;
89
98
  userMessage: string;
90
99
  skills: SkillMetadata[];
91
- /**
92
- * Datastores attached via `datastore_usages` — rendered as the
93
- * `<available_datastores>` section (DD-005 SD-5, skills precedent)
94
- * pointing the model at the synthesized record tools. Always the healthy
95
- * rendering here: the Cursor SDK connects MCP itself, so this harness can
96
- * never observe the live roster — the section's standing
97
- * failure-disclosure instruction is its whole coverage (issue #325).
98
- */
99
- datastoreUsages?: DatastoreUsage[];
100
100
  /**
101
101
  * Serving proactive channels + their approved templates — rendered as
102
102
  * the `<available_channel_templates>` section (proactive-messaging
@@ -109,6 +109,12 @@ export interface EnhancedPromptOptions {
109
109
  attachments: AttachmentPromptEntry[];
110
110
  /** Inline/degraded image facts for the input-files section (T04 vision). */
111
111
  vision?: VisionPromptInfo;
112
+ /**
113
+ * What kind of URL the turn's storage backend mints — keys the input-files
114
+ * section's hand-off wording (attachment-download-urls.ts). One turn-level
115
+ * fact: all attachments ride the one configured storage.
116
+ */
117
+ downloadUrlKind?: DownloadUrlKind;
112
118
  interactionMode?: InteractionMode;
113
119
  /**
114
120
  * The execution is a Build-from-plan turn (spec.execution_config
@@ -183,10 +189,6 @@ export function buildEnhancedPrompt(options: EnhancedPromptOptions): string {
183
189
  sections.push(formatSkillsSection(options.skills));
184
190
  }
185
191
 
186
- if (options.datastoreUsages !== undefined && options.datastoreUsages.length > 0) {
187
- sections.push(formatDatastoresSection(options.datastoreUsages));
188
- }
189
-
190
192
  if (options.channelMessaging !== undefined && options.channelMessaging.length > 0) {
191
193
  // "" when nothing is sendable — the tool alone still serves text
192
194
  // sends inside a 24-hour window (DD-006 D6).
@@ -212,7 +214,7 @@ export function buildEnhancedPrompt(options: EnhancedPromptOptions): string {
212
214
  }
213
215
 
214
216
  if (options.attachments.length > 0) {
215
- sections.push(formatInputFiles(options.attachments, options.vision));
217
+ sections.push(formatInputFiles(options.attachments, options.vision, options.downloadUrlKind));
216
218
  }
217
219
 
218
220
  if (options.workspaceFileRefs.length > 0) {
@@ -548,15 +550,28 @@ export function formatWorkspaceContext(dirs: string[]): string {
548
550
  export function formatInputFiles(
549
551
  attachments: readonly AttachmentPromptEntry[],
550
552
  vision?: VisionPromptInfo,
553
+ downloadUrlKind?: DownloadUrlKind,
551
554
  ): string {
552
555
  // A duplicate-renamed file (attachment-naming.ts) discloses its original
553
556
  // name so the agent can connect "the two report.pdfs" in the user's
554
- // message to distinct files on disk.
555
- const entries = attachments.map((a) =>
556
- a.renamedFrom !== undefined
557
- ? `- \`${a.path}\` (renamed from duplicate '${a.renamedFrom}')`
558
- : `- \`${a.path}\``,
559
- );
557
+ // message to distinct files on disk. A file with a minted download URL
558
+ // (attachment-download-urls.ts) lists it beside the path for the remote
559
+ // hand-off story.
560
+ const entries = attachments.map((a) => {
561
+ const rename =
562
+ a.renamedFrom !== undefined
563
+ ? ` (renamed from duplicate '${a.renamedFrom}')`
564
+ : "";
565
+ const url = a.downloadUrl !== undefined ? ` — download URL: ${a.downloadUrl}` : "";
566
+ return `- \`${a.path}\`${rename}${url}`;
567
+ });
568
+ // The URL hand-off line (shared wording, attachment-download-urls.ts)
569
+ // renders only when some listed file actually carries a URL — its wording
570
+ // keys on what kind of URL the storage backend mints.
571
+ const urlDisclosure =
572
+ downloadUrlKind !== undefined && attachments.some((a) => a.downloadUrl !== undefined)
573
+ ? [downloadUrlDisclosureLine(downloadUrlKind)]
574
+ : [];
560
575
  // The vision lines (shared wording, attachment-vision.ts) tell the model
561
576
  // which of these files it can already SEE inline versus which degraded to
562
577
  // path-only — without them an agent silently ignores a photo the user
@@ -568,6 +583,7 @@ export function formatInputFiles(
568
583
  "<input_files>",
569
584
  "The following files have been provided as inputs. Read them when relevant to the task:",
570
585
  ...entries,
586
+ ...urlDisclosure,
571
587
  ...disclosure,
572
588
  "</input_files>",
573
589
  ].join("\n");