@stigmer/runner 3.1.2 → 3.1.4

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 (127) hide show
  1. package/dist/.build-fingerprint +1 -1
  2. package/dist/activities/execute-cursor/attachment-resolver.d.ts +1 -1
  3. package/dist/activities/execute-cursor/attachment-resolver.js +1 -1
  4. package/dist/activities/execute-cursor/capture-flow.d.ts +29 -0
  5. package/dist/activities/execute-cursor/capture-flow.js +59 -0
  6. package/dist/activities/execute-cursor/capture-flow.js.map +1 -1
  7. package/dist/activities/execute-cursor/command-provenance.d.ts +11 -25
  8. package/dist/activities/execute-cursor/command-provenance.js +25 -115
  9. package/dist/activities/execute-cursor/command-provenance.js.map +1 -1
  10. package/dist/activities/execute-cursor/index.js +358 -557
  11. package/dist/activities/execute-cursor/index.js.map +1 -1
  12. package/dist/activities/execute-cursor/todo-tracker.d.ts +6 -1
  13. package/dist/activities/execute-cursor/todo-tracker.js +15 -43
  14. package/dist/activities/execute-cursor/todo-tracker.js.map +1 -1
  15. package/dist/activities/execute-cursor/turn-boundary.d.ts +108 -0
  16. package/dist/activities/execute-cursor/turn-boundary.js +163 -0
  17. package/dist/activities/execute-cursor/turn-boundary.js.map +1 -0
  18. package/dist/activities/execute-cursor/turn-stream.d.ts +141 -0
  19. package/dist/activities/execute-cursor/turn-stream.js +249 -0
  20. package/dist/activities/execute-cursor/turn-stream.js.map +1 -0
  21. package/dist/activities/execute-deep-agent/command-provenance.d.ts +61 -0
  22. package/dist/activities/execute-deep-agent/command-provenance.js +72 -0
  23. package/dist/activities/execute-deep-agent/command-provenance.js.map +1 -0
  24. package/dist/activities/execute-deep-agent/index.js +73 -4
  25. package/dist/activities/execute-deep-agent/index.js.map +1 -1
  26. package/dist/activities/execute-deep-agent/status-builder.js +8 -1
  27. package/dist/activities/execute-deep-agent/status-builder.js.map +1 -1
  28. package/dist/activities/execute-deep-agent/streaming-v3.js +6 -1
  29. package/dist/activities/execute-deep-agent/streaming-v3.js.map +1 -1
  30. package/dist/activities/execute-deep-agent/streaming.d.ts +7 -0
  31. package/dist/activities/execute-deep-agent/streaming.js +5 -1
  32. package/dist/activities/execute-deep-agent/streaming.js.map +1 -1
  33. package/dist/activities/execute-deep-agent/v3-status-builder.js +12 -1
  34. package/dist/activities/execute-deep-agent/v3-status-builder.js.map +1 -1
  35. package/dist/otel.js +10 -0
  36. package/dist/otel.js.map +1 -1
  37. package/dist/shared/filereview/capture.d.ts +18 -1
  38. package/dist/shared/filereview/capture.js +105 -28
  39. package/dist/shared/filereview/capture.js.map +1 -1
  40. package/dist/shared/filereview/cas-progress.d.ts +63 -0
  41. package/dist/shared/filereview/cas-progress.js +128 -0
  42. package/dist/shared/filereview/cas-progress.js.map +1 -0
  43. package/dist/shared/filereview/cas-substrate.d.ts +38 -0
  44. package/dist/shared/filereview/cas-substrate.js +48 -15
  45. package/dist/shared/filereview/cas-substrate.js.map +1 -1
  46. package/dist/shared/filereview/command-provenance.d.ts +93 -0
  47. package/dist/shared/filereview/command-provenance.js +132 -0
  48. package/dist/shared/filereview/command-provenance.js.map +1 -0
  49. package/dist/shared/filereview/events.d.ts +16 -0
  50. package/dist/shared/filereview/events.js +37 -0
  51. package/dist/shared/filereview/events.js.map +1 -1
  52. package/dist/shared/filereview/git-substrate.d.ts +48 -0
  53. package/dist/shared/filereview/git-substrate.js +78 -0
  54. package/dist/shared/filereview/git-substrate.js.map +1 -1
  55. package/dist/shared/filereview/index.d.ts +5 -2
  56. package/dist/shared/filereview/index.js +5 -2
  57. package/dist/shared/filereview/index.js.map +1 -1
  58. package/dist/shared/filereview/line-counts.d.ts +48 -0
  59. package/dist/shared/filereview/line-counts.js +72 -0
  60. package/dist/shared/filereview/line-counts.js.map +1 -0
  61. package/dist/shared/filereview/progress.d.ts +167 -0
  62. package/dist/shared/filereview/progress.js +196 -0
  63. package/dist/shared/filereview/progress.js.map +1 -0
  64. package/dist/shared/implement-plan-prompt.d.ts +6 -4
  65. package/dist/shared/implement-plan-prompt.js +38 -6
  66. package/dist/shared/implement-plan-prompt.js.map +1 -1
  67. package/dist/shared/plan-artifact.d.ts +59 -11
  68. package/dist/shared/plan-artifact.js +144 -16
  69. package/dist/shared/plan-artifact.js.map +1 -1
  70. package/dist/shared/plan-mode-prompt.d.ts +15 -4
  71. package/dist/shared/plan-mode-prompt.js +28 -5
  72. package/dist/shared/plan-mode-prompt.js.map +1 -1
  73. package/dist/shared/todos.d.ts +56 -0
  74. package/dist/shared/todos.js +98 -0
  75. package/dist/shared/todos.js.map +1 -0
  76. package/dist/shared/tool-row.d.ts +16 -0
  77. package/dist/shared/tool-row.js +31 -0
  78. package/dist/shared/tool-row.js.map +1 -1
  79. package/package.json +3 -2
  80. package/src/__tests__/otel-turn-span.test.ts +61 -0
  81. package/src/activities/execute-cursor/__tests__/build-prompt.test.ts +7 -0
  82. package/src/activities/execute-cursor/__tests__/delta-enricher.test.ts +68 -0
  83. package/src/activities/execute-cursor/__tests__/progress-substrate.test.ts +169 -0
  84. package/src/activities/execute-cursor/__tests__/turn-boundary.test.ts +280 -0
  85. package/src/activities/execute-cursor/__tests__/turn-stream.test.ts +349 -0
  86. package/src/activities/execute-cursor/attachment-resolver.ts +1 -1
  87. package/src/activities/execute-cursor/capture-flow.ts +78 -0
  88. package/src/activities/execute-cursor/command-provenance.ts +25 -120
  89. package/src/activities/execute-cursor/index.ts +419 -602
  90. package/src/activities/execute-cursor/todo-tracker.ts +17 -59
  91. package/src/activities/execute-cursor/turn-boundary.ts +274 -0
  92. package/src/activities/execute-cursor/turn-stream.ts +418 -0
  93. package/src/activities/execute-deep-agent/__tests__/command-provenance.test.ts +252 -0
  94. package/src/activities/execute-deep-agent/__tests__/prompt-builder.test.ts +11 -0
  95. package/src/activities/execute-deep-agent/__tests__/status-builder.test.ts +78 -0
  96. package/src/activities/execute-deep-agent/__tests__/v3-status-builder.test.ts +105 -1
  97. package/src/activities/execute-deep-agent/command-provenance.ts +102 -0
  98. package/src/activities/execute-deep-agent/index.ts +91 -4
  99. package/src/activities/execute-deep-agent/status-builder.ts +9 -0
  100. package/src/activities/execute-deep-agent/streaming-v3.ts +6 -1
  101. package/src/activities/execute-deep-agent/streaming.ts +12 -1
  102. package/src/activities/execute-deep-agent/v3-status-builder.ts +13 -0
  103. package/src/otel.ts +8 -0
  104. package/src/shared/__tests__/implement-plan-prompt.test.ts +40 -2
  105. package/src/shared/__tests__/plan-artifact.test.ts +142 -9
  106. package/src/shared/__tests__/todos.test.ts +216 -0
  107. package/src/shared/filereview/__tests__/capture.test.ts +182 -1
  108. package/src/shared/filereview/__tests__/cas-progress.test.ts +228 -0
  109. package/src/shared/filereview/__tests__/cas-substrate.test.ts +100 -0
  110. package/src/shared/filereview/__tests__/command-provenance.test.ts +252 -0
  111. package/src/shared/filereview/__tests__/events.test.ts +105 -0
  112. package/src/shared/filereview/__tests__/line-counts.test.ts +73 -0
  113. package/src/shared/filereview/__tests__/progress.test.ts +338 -0
  114. package/src/shared/filereview/capture.ts +134 -30
  115. package/src/shared/filereview/cas-progress.ts +170 -0
  116. package/src/shared/filereview/cas-substrate.ts +79 -18
  117. package/src/shared/filereview/command-provenance.ts +180 -0
  118. package/src/shared/filereview/events.ts +50 -0
  119. package/src/shared/filereview/git-substrate.ts +114 -0
  120. package/src/shared/filereview/index.ts +36 -1
  121. package/src/shared/filereview/line-counts.ts +83 -0
  122. package/src/shared/filereview/progress.ts +310 -0
  123. package/src/shared/implement-plan-prompt.ts +39 -8
  124. package/src/shared/plan-artifact.ts +152 -16
  125. package/src/shared/plan-mode-prompt.ts +28 -5
  126. package/src/shared/todos.ts +126 -0
  127. package/src/shared/tool-row.ts +34 -0
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Todo-list projection shared by every harness's status writer.
3
+ *
4
+ * All harnesses expose an agent to-do tool — the Cursor SDK emits `TodoWrite`
5
+ * (legacy) / `updateTodos` (current), the native deepagents harness emits
6
+ * `write_todos` — and each writes the SAME `AgentExecutionStatus.todos` proto
7
+ * map that the clients (React `TodoCard`, CLI) render. This module is the single
8
+ * place that maps a raw tool payload into that map, so the Cursor `TodoTracker`
9
+ * and the native v2/v3 status builders cannot drift in how they build todos.
10
+ *
11
+ * The mapping is a superset of what any one harness emits: the Cursor SDK sends
12
+ * per-item `id`/`created_at` and can send a `merge` flag and camelCase statuses;
13
+ * deepagents sends only `{ content, status }` (three statuses, no id, no merge).
14
+ * One helper handling the superset serves all three writers.
15
+ */
16
+
17
+ import { create } from "@bufbuild/protobuf";
18
+ import { TodoItemSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/todo_pb";
19
+ import type { TodoItem } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/todo_pb";
20
+ import { TodoStatus } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
21
+ import { utcTimestamp } from "./status.js";
22
+
23
+ /**
24
+ * A single raw todo as it arrives in a to-do tool call's arguments. Every field
25
+ * is optional and defensively typed: the Cursor `updateTodos` schema omits
26
+ * per-item `id`, deepagents omits `id`/`created_at`, and the values reach us as
27
+ * untyped JSON (a Cursor `args` string or a protobuf `JsonObject` value).
28
+ */
29
+ export interface RawTodoItem {
30
+ id?: string;
31
+ content?: string;
32
+ status?: string;
33
+ created_at?: string;
34
+ }
35
+
36
+ /**
37
+ * Raw status string -> proto `TodoStatus`. Keyed on the lowercased status so
38
+ * the current SDK's camelCase `inProgress` and the legacy snake_case
39
+ * `in_progress` both resolve. `cancelled` is only ever emitted by the Cursor
40
+ * SDK — deepagents' three-status schema never sends it — but it is kept here so
41
+ * the one shared mapping is faithful to every producer. Unknown values fall back
42
+ * to `TODO_PENDING` at the call site.
43
+ */
44
+ const STATUS_MAP: Record<string, TodoStatus> = {
45
+ pending: TodoStatus.TODO_PENDING,
46
+ in_progress: TodoStatus.TODO_IN_PROGRESS,
47
+ inprogress: TodoStatus.TODO_IN_PROGRESS,
48
+ completed: TodoStatus.TODO_COMPLETED,
49
+ cancelled: TodoStatus.TODO_CANCELLED,
50
+ };
51
+
52
+ /**
53
+ * Project a to-do tool call's payload into a `status.todos` map, in place.
54
+ * Returns whether the map changed — the caller's "dirty" / force-persist signal.
55
+ *
56
+ * Semantics (identical across all three harness writers):
57
+ * - Empty or non-array `rawTodos`: a full-replace (`!merge`) clears the map and
58
+ * is a change; a merge is a no-op (nothing to merge in) and is not.
59
+ * - Otherwise a full-replace clears first, then every item is (re)written.
60
+ * - `id` is the provided id or a stable index fallback (`todo-<i>`); order is
61
+ * the array order, so index ids are stable across full-replace updates.
62
+ * - `created_at` is preserved from the prior same-id entry ONLY on merge; a
63
+ * full-replace clears first, so it becomes `raw.created_at || now`. (The
64
+ * native harness is always full-replace and sends no `created_at`, so a
65
+ * native todo's `created_at` is `now` on each write — deliberately identical
66
+ * to the Cursor non-merge path.)
67
+ * - `updated_at` is always `now`.
68
+ *
69
+ * Note on clearing: an empty full-replace clears the in-memory map, but the Go
70
+ * `update_status` activity replaces persisted todos only when the incoming map
71
+ * is non-empty, so a settled list survives in history — the clear never reaches
72
+ * the record. This is intentional and relied upon by both harnesses.
73
+ */
74
+ export function applyTodoUpdate(
75
+ target: { [key: string]: TodoItem },
76
+ rawTodos: unknown,
77
+ opts: { merge: boolean; now?: string },
78
+ ): boolean {
79
+ const { merge } = opts;
80
+ const now = opts.now ?? utcTimestamp();
81
+
82
+ if (!Array.isArray(rawTodos) || rawTodos.length === 0) {
83
+ if (!merge) {
84
+ clearMap(target);
85
+ return true;
86
+ }
87
+ return false;
88
+ }
89
+
90
+ if (!merge) {
91
+ clearMap(target);
92
+ }
93
+
94
+ for (let i = 0; i < rawTodos.length; i++) {
95
+ const raw = coerceRawTodo(rawTodos[i]);
96
+ const id = raw.id || `todo-${i}`;
97
+ const statusStr = (raw.status ?? "pending").toLowerCase();
98
+ const status = STATUS_MAP[statusStr] ?? TodoStatus.TODO_PENDING;
99
+
100
+ // Preserve the original creation time only when merging into an existing
101
+ // entry; a full-replace cleared the map above, so `existing` is undefined.
102
+ const existing = merge ? target[id] : undefined;
103
+
104
+ target[id] = create(TodoItemSchema, {
105
+ id,
106
+ content: raw.content ?? "",
107
+ status,
108
+ createdAt: existing?.createdAt || raw.created_at || now,
109
+ updatedAt: now,
110
+ });
111
+ }
112
+
113
+ return true;
114
+ }
115
+
116
+ /** Narrow an untyped array element to a {@link RawTodoItem}; non-objects become empty. */
117
+ function coerceRawTodo(value: unknown): RawTodoItem {
118
+ return typeof value === "object" && value !== null ? (value as RawTodoItem) : {};
119
+ }
120
+
121
+ /** Delete every key from the map in place (proto map fields have no `.clear()`). */
122
+ function clearMap(target: { [key: string]: TodoItem }): void {
123
+ for (const key of Object.keys(target)) {
124
+ delete target[key];
125
+ }
126
+ }
@@ -186,3 +186,37 @@ export function collectSubAgentToolCallIds(
186
186
  }
187
187
  return ids;
188
188
  }
189
+
190
+ /** Terminal tool-call statuses — a row that has finished (however it finished). */
191
+ const TERMINAL_TOOL_CALL_STATUSES: ReadonlySet<ToolCallStatus> = new Set([
192
+ ToolCallStatus.TOOL_CALL_COMPLETED,
193
+ ToolCallStatus.TOOL_CALL_FAILED,
194
+ ToolCallStatus.TOOL_CALL_SKIPPED,
195
+ ]);
196
+
197
+ /**
198
+ * Collect the ids of tool-call rows that have already SETTLED (reached a terminal
199
+ * state: completed, failed, or skipped) in a transcript.
200
+ *
201
+ * The deep-agent turn-boundary provenance derivation (DD-28) snapshots this
202
+ * BEFORE a turn's stream to scope "this turn's tool calls" by identity: a call
203
+ * whose id is absent from the snapshot is this-turn's — either freshly streamed,
204
+ * or a prior gate that was WAITING_APPROVAL before the stream and executes now on
205
+ * resume (StatusBuilder updates the seeded row in place, so it keeps its id).
206
+ * Unlike the Cursor harness, the deep-agent cannot scope positionally — an
207
+ * approved command executes at its SEEDED position — so identity is the only
208
+ * correct scope, mirroring {@link collectSubAgentToolCallIds}. Terminal (not just
209
+ * completed) so a PRIOR turn's failed/skipped non-shell call is excluded and
210
+ * cannot spuriously disqualify this turn.
211
+ */
212
+ export function collectSettledToolCallIds(
213
+ messages: readonly AgentMessage[],
214
+ ): Set<string> {
215
+ const ids = new Set<string>();
216
+ for (const msg of messages) {
217
+ for (const tc of msg.toolCalls) {
218
+ if (TERMINAL_TOOL_CALL_STATUSES.has(tc.status)) ids.add(tc.id);
219
+ }
220
+ }
221
+ return ids;
222
+ }