@sapiom/harness 0.1.6 → 0.2.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 (185) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/dist/cli/args.d.ts +16 -0
  3. package/dist/cli/args.d.ts.map +1 -0
  4. package/dist/cli/args.js +80 -0
  5. package/dist/cli/args.js.map +1 -0
  6. package/dist/cli/bin.js +12 -65
  7. package/dist/cli/bin.js.map +1 -1
  8. package/dist/cli/settings.d.ts.map +1 -1
  9. package/dist/cli/settings.js +33 -1
  10. package/dist/cli/settings.js.map +1 -1
  11. package/dist/core/adapters/claude-code.d.ts +60 -2
  12. package/dist/core/adapters/claude-code.d.ts.map +1 -1
  13. package/dist/core/adapters/claude-code.js +119 -32
  14. package/dist/core/adapters/claude-code.js.map +1 -1
  15. package/dist/core/adapters/codex.d.ts +21 -2
  16. package/dist/core/adapters/codex.d.ts.map +1 -1
  17. package/dist/core/adapters/codex.js +53 -2
  18. package/dist/core/adapters/codex.js.map +1 -1
  19. package/dist/core/adapters/detect.d.ts +9 -0
  20. package/dist/core/adapters/detect.d.ts.map +1 -1
  21. package/dist/core/adapters/detect.js +9 -0
  22. package/dist/core/adapters/detect.js.map +1 -1
  23. package/dist/core/canvas-body.d.ts +28 -28
  24. package/dist/core/canvas-body.d.ts.map +1 -1
  25. package/dist/core/canvas-body.js +117 -55
  26. package/dist/core/canvas-body.js.map +1 -1
  27. package/dist/core/canvas-derive.d.ts +43 -0
  28. package/dist/core/canvas-derive.d.ts.map +1 -0
  29. package/dist/core/canvas-derive.js +95 -0
  30. package/dist/core/canvas-derive.js.map +1 -0
  31. package/dist/core/canvas-enrichment.d.ts +52 -127
  32. package/dist/core/canvas-enrichment.d.ts.map +1 -1
  33. package/dist/core/canvas-enrichment.js +17 -178
  34. package/dist/core/canvas-enrichment.js.map +1 -1
  35. package/dist/core/canvas-graph.d.ts +40 -1
  36. package/dist/core/canvas-graph.d.ts.map +1 -1
  37. package/dist/core/canvas-graph.js +71 -9
  38. package/dist/core/canvas-graph.js.map +1 -1
  39. package/dist/core/canvas-interconnections.d.ts +26 -8
  40. package/dist/core/canvas-interconnections.d.ts.map +1 -1
  41. package/dist/core/canvas-interconnections.js +132 -24
  42. package/dist/core/canvas-interconnections.js.map +1 -1
  43. package/dist/core/canvas-manifest-check.d.ts.map +1 -1
  44. package/dist/core/canvas-manifest-check.js +15 -2
  45. package/dist/core/canvas-manifest-check.js.map +1 -1
  46. package/dist/core/canvas-render.d.ts +8 -15
  47. package/dist/core/canvas-render.d.ts.map +1 -1
  48. package/dist/core/canvas-render.js +29 -41
  49. package/dist/core/canvas-render.js.map +1 -1
  50. package/dist/core/canvas-run-state.d.ts +41 -0
  51. package/dist/core/canvas-run-state.d.ts.map +1 -1
  52. package/dist/core/canvas-run-state.js +136 -0
  53. package/dist/core/canvas-run-state.js.map +1 -1
  54. package/dist/core/canvas-svg.d.ts +9 -4
  55. package/dist/core/canvas-svg.d.ts.map +1 -1
  56. package/dist/core/canvas-svg.js +84 -13
  57. package/dist/core/canvas-svg.js.map +1 -1
  58. package/dist/core/canvas-template.d.ts +9 -10
  59. package/dist/core/canvas-template.d.ts.map +1 -1
  60. package/dist/core/canvas-template.js +57 -20
  61. package/dist/core/canvas-template.js.map +1 -1
  62. package/dist/core/canvas-watcher.d.ts +22 -1
  63. package/dist/core/canvas-watcher.d.ts.map +1 -1
  64. package/dist/core/canvas-watcher.js +111 -30
  65. package/dist/core/canvas-watcher.js.map +1 -1
  66. package/dist/core/collector/normalizer.d.ts +8 -0
  67. package/dist/core/collector/normalizer.d.ts.map +1 -1
  68. package/dist/core/collector/normalizer.js +8 -0
  69. package/dist/core/collector/normalizer.js.map +1 -1
  70. package/dist/core/collector/store.d.ts +75 -1
  71. package/dist/core/collector/store.d.ts.map +1 -1
  72. package/dist/core/collector/store.js +334 -2
  73. package/dist/core/collector/store.js.map +1 -1
  74. package/dist/core/errors.d.ts +10 -4
  75. package/dist/core/errors.d.ts.map +1 -1
  76. package/dist/core/errors.js +11 -5
  77. package/dist/core/errors.js.map +1 -1
  78. package/dist/core/example-seed.d.ts +8 -0
  79. package/dist/core/example-seed.d.ts.map +1 -1
  80. package/dist/core/example-seed.js +47 -10
  81. package/dist/core/example-seed.js.map +1 -1
  82. package/dist/core/inject/system-prompt.d.ts +8 -0
  83. package/dist/core/inject/system-prompt.d.ts.map +1 -1
  84. package/dist/core/inject/system-prompt.js +3 -1
  85. package/dist/core/inject/system-prompt.js.map +1 -1
  86. package/dist/core/macros.d.ts.map +1 -1
  87. package/dist/core/macros.js +5 -6
  88. package/dist/core/macros.js.map +1 -1
  89. package/dist/core/paths.d.ts +1 -0
  90. package/dist/core/paths.d.ts.map +1 -1
  91. package/dist/core/paths.js +1 -0
  92. package/dist/core/paths.js.map +1 -1
  93. package/dist/core/record-archive.d.ts +187 -0
  94. package/dist/core/record-archive.d.ts.map +1 -0
  95. package/dist/core/record-archive.js +465 -0
  96. package/dist/core/record-archive.js.map +1 -0
  97. package/dist/core/rehydration.d.ts +72 -0
  98. package/dist/core/rehydration.d.ts.map +1 -0
  99. package/dist/core/rehydration.js +72 -0
  100. package/dist/core/rehydration.js.map +1 -0
  101. package/dist/core/resume-brief.d.ts +130 -0
  102. package/dist/core/resume-brief.d.ts.map +1 -0
  103. package/dist/core/resume-brief.js +404 -0
  104. package/dist/core/resume-brief.js.map +1 -0
  105. package/dist/core/rolling-summary.d.ts +130 -0
  106. package/dist/core/rolling-summary.d.ts.map +1 -0
  107. package/dist/core/rolling-summary.js +227 -0
  108. package/dist/core/rolling-summary.js.map +1 -0
  109. package/dist/core/session-manager.d.ts +11 -3
  110. package/dist/core/session-manager.d.ts.map +1 -1
  111. package/dist/core/session-manager.js +56 -7
  112. package/dist/core/session-manager.js.map +1 -1
  113. package/dist/core/session-record.d.ts +165 -0
  114. package/dist/core/session-record.d.ts.map +1 -0
  115. package/dist/core/session-record.js +470 -0
  116. package/dist/core/session-record.js.map +1 -0
  117. package/dist/core/spawn-target.d.ts +12 -0
  118. package/dist/core/spawn-target.d.ts.map +1 -0
  119. package/dist/core/spawn-target.js +187 -0
  120. package/dist/core/spawn-target.js.map +1 -0
  121. package/dist/core/task-manager.d.ts.map +1 -1
  122. package/dist/core/task-manager.js +9 -1
  123. package/dist/core/task-manager.js.map +1 -1
  124. package/dist/core/template-catalog.d.ts +48 -0
  125. package/dist/core/template-catalog.d.ts.map +1 -0
  126. package/dist/core/template-catalog.js +338 -0
  127. package/dist/core/template-catalog.js.map +1 -0
  128. package/dist/core/workflow-registry.d.ts.map +1 -1
  129. package/dist/core/workflow-registry.js +2 -2
  130. package/dist/core/workflow-registry.js.map +1 -1
  131. package/dist/core/workspace-watcher.d.ts.map +1 -1
  132. package/dist/core/workspace-watcher.js +4 -3
  133. package/dist/core/workspace-watcher.js.map +1 -1
  134. package/dist/index.d.ts +12 -0
  135. package/dist/index.d.ts.map +1 -1
  136. package/dist/index.js +21 -0
  137. package/dist/index.js.map +1 -1
  138. package/dist/profiles/default.d.ts.map +1 -1
  139. package/dist/profiles/default.js +9 -14
  140. package/dist/profiles/default.js.map +1 -1
  141. package/dist/server/canvas.d.ts.map +1 -1
  142. package/dist/server/canvas.js +7 -7
  143. package/dist/server/canvas.js.map +1 -1
  144. package/dist/server/fs.d.ts.map +1 -1
  145. package/dist/server/fs.js +17 -1
  146. package/dist/server/fs.js.map +1 -1
  147. package/dist/server/index.d.ts +12 -3
  148. package/dist/server/index.d.ts.map +1 -1
  149. package/dist/server/index.js +321 -50
  150. package/dist/server/index.js.map +1 -1
  151. package/dist/server/ingest.d.ts +11 -0
  152. package/dist/server/ingest.d.ts.map +1 -1
  153. package/dist/server/ingest.js +1 -0
  154. package/dist/server/ingest.js.map +1 -1
  155. package/dist/server/macros.d.ts +4 -6
  156. package/dist/server/macros.d.ts.map +1 -1
  157. package/dist/server/macros.js.map +1 -1
  158. package/dist/server/rest.d.ts +18 -6
  159. package/dist/server/rest.d.ts.map +1 -1
  160. package/dist/server/rest.js +185 -48
  161. package/dist/server/rest.js.map +1 -1
  162. package/dist/server/templates.d.ts +24 -0
  163. package/dist/server/templates.d.ts.map +1 -0
  164. package/dist/server/templates.js +54 -0
  165. package/dist/server/templates.js.map +1 -0
  166. package/dist/shared/types.d.ts +477 -29
  167. package/dist/shared/types.d.ts.map +1 -1
  168. package/dist/shared/types.js +19 -11
  169. package/dist/shared/types.js.map +1 -1
  170. package/dist/web/assets/index-SYpugKQ1.css +32 -0
  171. package/dist/web/assets/index-vYYd44hZ.js +446 -0
  172. package/dist/web/index.html +2 -2
  173. package/package.json +5 -4
  174. package/dist/core/canvas-enrich.d.ts +0 -115
  175. package/dist/core/canvas-enrich.d.ts.map +0 -1
  176. package/dist/core/canvas-enrich.js +0 -186
  177. package/dist/core/canvas-enrich.js.map +0 -1
  178. package/dist/profiles/canvas-guidelines.d.ts +0 -20
  179. package/dist/profiles/canvas-guidelines.d.ts.map +0 -1
  180. package/dist/profiles/canvas-guidelines.js +0 -48
  181. package/dist/profiles/canvas-guidelines.js.map +0 -1
  182. package/dist/web/assets/index-DCtyI4VW.css +0 -32
  183. package/dist/web/assets/index-WSw5RvYR.js +0 -445
  184. package/dist/web/welcome-hero-dark.png +0 -0
  185. package/dist/web/welcome-hero-light.png +0 -0
@@ -9,11 +9,72 @@
9
9
  * never overlap with an in-flight append and no appended line can be lost
10
10
  * in a sweep's read window. Overhead is negligible — appends are low-frequency
11
11
  * (one per hook event), and the queue never holds more than O(sessions) entries.
12
+ *
13
+ * Reads (`read`, `index`) run deliberately OUTSIDE that queue: an append is a
14
+ * single `appendFile` of one line, so a reader can never be left waiting out a
15
+ * half-written record it would otherwise have to skip — the worst case is a
16
+ * torn final line from a crash, which the parser drops. Blocking writers
17
+ * behind a 50 MB scan to buy nothing would be the wrong trade.
18
+ *
19
+ * Index: reading one session's events must not rescan the whole file (capped
20
+ * at 50 MB — see store-retention.ts). The index maps each harnessSessionId to
21
+ * the byte spans its lines occupy. It is built lazily on the first read and
22
+ * maintained incrementally after that: each subsequent read scans only the
23
+ * bytes appended since the last one — by this process or by a second harness
24
+ * boot writing to the same file, which is why the trigger is the file's size
25
+ * rather than our own append path. A shrink or an inode change means the file
26
+ * was rewritten underneath us (a retention sweep), which invalidates every
27
+ * offset, so the index is rebuilt from scratch.
12
28
  */
29
+ import { createReadStream } from "node:fs";
13
30
  import * as fs from "node:fs/promises";
14
31
  import * as path from "node:path";
15
- import { HARNESS_PATHS } from "../../shared/types.js";
32
+ import * as readline from "node:readline";
33
+ import { StringDecoder } from "node:string_decoder";
34
+ import { HARNESS_PATHS, } from "../../shared/types.js";
16
35
  import { expandHome } from "../paths.js";
36
+ /** Bytes read per positioned read when walking a span (see readSpanLines). */
37
+ const SPAN_CHUNK_BYTES = 1024 * 1024;
38
+ /** Parse one ndjson line into an event, or null when it isn't one. */
39
+ function parseEventLine(line) {
40
+ if (!line.trim())
41
+ return null;
42
+ let parsed;
43
+ try {
44
+ parsed = JSON.parse(line);
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ if (typeof parsed !== "object" || parsed === null)
50
+ return null;
51
+ const candidate = parsed;
52
+ // harnessSessionId keys the index and ts orders the fold — a line missing
53
+ // either can't be placed in a record, so it isn't an event as far as
54
+ // readers are concerned.
55
+ if (typeof candidate.harnessSessionId !== "string")
56
+ return null;
57
+ if (typeof candidate.ts !== "string" || typeof candidate.type !== "string")
58
+ return null;
59
+ return candidate;
60
+ }
61
+ function matchesFilter(event, sessionIds, types) {
62
+ if (sessionIds && !sessionIds.has(event.harnessSessionId))
63
+ return false;
64
+ if (types && !types.has(event.type))
65
+ return false;
66
+ return true;
67
+ }
68
+ /** Append a span, merging into the previous one when contiguous — keeps a
69
+ * single-session file at one span instead of one per line. */
70
+ function pushSpan(spans, start, end) {
71
+ const last = spans[spans.length - 1];
72
+ if (last && last.end >= start) {
73
+ last.end = Math.max(last.end, end);
74
+ return;
75
+ }
76
+ spans.push({ start, end });
77
+ }
17
78
  /**
18
79
  * @param filePath Defaults to `HARNESS_PATHS.events`
19
80
  * (`~/.sapiom/harness/events.ndjson`). Override in tests.
@@ -36,15 +97,286 @@ export function createEventStore(filePath = HARNESS_PATHS.events) {
36
97
  queue = next.then(() => { }, () => { });
37
98
  return next;
38
99
  }
100
+ // ── Reading ─────────────────────────────────────────────────────────────
101
+ /** Line-by-line over `[start, end]` — inclusive `end`, as fs streams take it. */
102
+ async function* readLines(start, end) {
103
+ const stream = createReadStream(resolvedPath, { start, end });
104
+ const lines = readline.createInterface({ input: stream, crlfDelay: Infinity });
105
+ try {
106
+ for await (const line of lines)
107
+ yield line;
108
+ }
109
+ finally {
110
+ lines.close();
111
+ stream.destroy();
112
+ }
113
+ }
114
+ /**
115
+ * Line-by-line over a set of byte spans, through ONE file handle and
116
+ * positioned reads.
117
+ *
118
+ * Not `createReadStream` per span, deliberately: a session interleaved with
119
+ * others across the file has one span per contiguous run of its lines —
120
+ * hundreds of them for a busy machine — and standing up a stream plus a
121
+ * readline interface for each costs far more than the bytes do. A span is
122
+ * still read in bounded chunks (never all at once) so a session that owns the
123
+ * whole 50 MB file can't be pulled into memory in one buffer, and a
124
+ * StringDecoder carries multi-byte characters across chunk boundaries.
125
+ */
126
+ async function* readSpanLines(spans) {
127
+ if (spans.length === 0)
128
+ return;
129
+ let handle;
130
+ try {
131
+ handle = await fs.open(resolvedPath, "r");
132
+ }
133
+ catch (err) {
134
+ if (err.code === "ENOENT")
135
+ return;
136
+ throw err;
137
+ }
138
+ try {
139
+ for (const span of spans) {
140
+ const decoder = new StringDecoder("utf8");
141
+ let carry = "";
142
+ let position = span.start;
143
+ while (position < span.end) {
144
+ const length = Math.min(SPAN_CHUNK_BYTES, span.end - position);
145
+ const buffer = Buffer.allocUnsafe(length);
146
+ const { bytesRead } = await handle.read(buffer, 0, length, position);
147
+ // A short read means the file shrank under us (a sweep landed
148
+ // mid-read): stop this span rather than looping on a stale offset.
149
+ if (bytesRead <= 0)
150
+ break;
151
+ position += bytesRead;
152
+ const chunk = carry + decoder.write(buffer.subarray(0, bytesRead));
153
+ const lines = chunk.split("\n");
154
+ carry = lines.pop() ?? "";
155
+ for (const line of lines)
156
+ yield line;
157
+ }
158
+ // Whatever is left has no trailing newline — the file's last line, or
159
+ // a torn one. Either way it's the caller's parser that decides.
160
+ const tail = carry + decoder.end();
161
+ if (tail)
162
+ yield tail;
163
+ }
164
+ }
165
+ finally {
166
+ await handle.close().catch(() => { });
167
+ }
168
+ }
169
+ async function statFile() {
170
+ try {
171
+ const stat = await fs.stat(resolvedPath);
172
+ return { size: stat.size, ino: stat.ino };
173
+ }
174
+ catch (err) {
175
+ if (err.code === "ENOENT")
176
+ return null;
177
+ throw err;
178
+ }
179
+ }
180
+ // ── Index ───────────────────────────────────────────────────────────────
181
+ let state = null;
182
+ // Serializes index work so two concurrent reads never scan the same tail
183
+ // twice, nor interleave partial updates into the same maps.
184
+ let indexWork = Promise.resolve();
185
+ function entryFor(current, harnessSessionId) {
186
+ const existing = current.bySession.get(harnessSessionId);
187
+ if (existing)
188
+ return existing;
189
+ const created = {
190
+ harnessSessionId,
191
+ spans: [],
192
+ eventCount: 0,
193
+ turnCount: 0,
194
+ agentSessionIds: [],
195
+ harness: null,
196
+ firstTs: null,
197
+ lastTs: null,
198
+ };
199
+ current.bySession.set(harnessSessionId, created);
200
+ return created;
201
+ }
202
+ function recordEvent(current, event, start, end) {
203
+ const entry = entryFor(current, event.harnessSessionId);
204
+ pushSpan(entry.spans, start, end);
205
+ entry.eventCount += 1;
206
+ if (event.type === "prompt.submitted")
207
+ entry.turnCount += 1;
208
+ if (entry.harness === null && typeof event.harness === "string")
209
+ entry.harness = event.harness;
210
+ if (entry.firstTs === null)
211
+ entry.firstTs = event.ts;
212
+ entry.lastTs = event.ts;
213
+ if (typeof event.agentSessionId === "string" && event.agentSessionId) {
214
+ if (!entry.agentSessionIds.includes(event.agentSessionId)) {
215
+ entry.agentSessionIds.push(event.agentSessionId);
216
+ }
217
+ const siblings = current.byAgentSession.get(event.agentSessionId);
218
+ if (!siblings) {
219
+ current.byAgentSession.set(event.agentSessionId, [event.harnessSessionId]);
220
+ }
221
+ else if (!siblings.includes(event.harnessSessionId)) {
222
+ siblings.push(event.harnessSessionId);
223
+ }
224
+ }
225
+ }
226
+ /**
227
+ * Fold `[from, to)` of the file into `current`. Offsets advance by the BYTE
228
+ * length of each line, not its character count — a multi-byte prompt would
229
+ * otherwise skew every subsequent span.
230
+ *
231
+ * A final line with no trailing newline (a crash mid-append, or a read that
232
+ * caught an append in flight) rewinds `indexedBytes` to that line's start
233
+ * rather than claiming it as indexed: the next reconcile re-reads it, so a
234
+ * line that was merely incomplete at scan time still lands in the index once
235
+ * it's whole. A line that stays torn forever costs one re-parse per read.
236
+ */
237
+ async function scanInto(current, from, to) {
238
+ if (to <= from)
239
+ return;
240
+ let offset = from;
241
+ let lastLineStart = from;
242
+ let lastLineWasEvent = false;
243
+ for await (const line of readLines(from, to - 1)) {
244
+ lastLineStart = offset;
245
+ // +1 for the newline readline consumed.
246
+ offset += Buffer.byteLength(line, "utf8") + 1;
247
+ const event = parseEventLine(line);
248
+ lastLineWasEvent = event !== null;
249
+ // min(): the last line may have had no newline to count.
250
+ if (event)
251
+ recordEvent(current, event, lastLineStart, Math.min(offset, to));
252
+ }
253
+ // `offset > to` means the last line's counted newline wasn't there. Rewind
254
+ // only if that line also failed to parse — a complete final event without a
255
+ // trailing newline is indexed, and re-reading it would double-count it.
256
+ current.indexedBytes = offset > to && !lastLineWasEvent ? lastLineStart : to;
257
+ }
258
+ /**
259
+ * Bring the index in line with the file on disk, building it if needed.
260
+ * Grown file → scan only the new tail. Shrunk file or a new inode → the
261
+ * offsets we hold describe a file that no longer exists (retention sweep),
262
+ * so rebuild. Unchanged → no I/O beyond the stat.
263
+ */
264
+ async function reconcile() {
265
+ const stat = await statFile();
266
+ if (!stat) {
267
+ // No file yet: an empty index is the honest answer, and it must not be
268
+ // cached as "indexed" — the next call has to look again.
269
+ state = null;
270
+ return { bySession: new Map(), byAgentSession: new Map(), indexedBytes: 0, ino: -1 };
271
+ }
272
+ const current = state;
273
+ if (current && current.ino === stat.ino && stat.size >= current.indexedBytes) {
274
+ if (stat.size > current.indexedBytes)
275
+ await scanInto(current, current.indexedBytes, stat.size);
276
+ return current;
277
+ }
278
+ const fresh = {
279
+ bySession: new Map(),
280
+ byAgentSession: new Map(),
281
+ indexedBytes: 0,
282
+ ino: stat.ino,
283
+ };
284
+ await scanInto(fresh, 0, stat.size);
285
+ state = fresh;
286
+ return fresh;
287
+ }
288
+ /** Serialize reconciliation; concurrent readers queue behind one scan. */
289
+ function withIndex() {
290
+ const next = indexWork.then(reconcile, reconcile);
291
+ indexWork = next.catch(() => { });
292
+ return next;
293
+ }
39
294
  return {
40
295
  append(event) {
41
296
  return enqueue(async () => {
42
297
  await ensureDir();
43
298
  await fs.appendFile(resolvedPath, `${JSON.stringify(event)}\n`, "utf8");
299
+ // The index is deliberately NOT written to here. reconcile() is the one
300
+ // writer, and it absorbs this line by scanning from `indexedBytes` to
301
+ // the current size — the appended bytes only, never the whole file.
302
+ //
303
+ // Writing the entry from this side as well is the obvious optimization
304
+ // and it is wrong: a reader's reconcile() can stat a size that already
305
+ // includes this line while its scan is still in flight, so both paths
306
+ // record the same event and every offset after it shifts by a line. One
307
+ // writer, serialized, no window. The cost is a tail read on the next
308
+ // index() call, which is bounded by what was appended since the last
309
+ // one — a few hundred bytes in practice.
44
310
  });
45
311
  },
46
312
  runExclusive(fn) {
47
- return enqueue(fn);
313
+ return enqueue(() => {
314
+ // A sweep rewrites the file (temp + rename): every offset the index
315
+ // holds points into the old inode. Drop it and let the next read
316
+ // rebuild, rather than trying to predict what the sweep kept.
317
+ state = null;
318
+ return fn();
319
+ });
320
+ },
321
+ read(filter = {}) {
322
+ const requested = filter.harnessSessionId === undefined
323
+ ? null
324
+ : typeof filter.harnessSessionId === "string"
325
+ ? [filter.harnessSessionId]
326
+ : [...filter.harnessSessionId];
327
+ const sessionIds = requested ? new Set(requested) : null;
328
+ const types = filter.types ? new Set(filter.types) : null;
329
+ return {
330
+ async *[Symbol.asyncIterator]() {
331
+ if (!requested) {
332
+ // Unfiltered: a full scan IS the answer the caller asked for.
333
+ const stat = await statFile();
334
+ if (!stat || stat.size === 0)
335
+ return;
336
+ for await (const line of readLines(0, stat.size - 1)) {
337
+ const event = parseEventLine(line);
338
+ if (event && matchesFilter(event, null, types))
339
+ yield event;
340
+ }
341
+ return;
342
+ }
343
+ const index = await withIndex();
344
+ // Merge the requested sessions' spans and walk them in file order,
345
+ // so a record spanning several sessions still reads sequentially.
346
+ const collected = [];
347
+ for (const id of requested) {
348
+ const entry = index.bySession.get(id);
349
+ if (entry)
350
+ collected.push(...entry.spans.map((span) => ({ ...span })));
351
+ }
352
+ collected.sort((a, b) => a.start - b.start);
353
+ const spans = [];
354
+ for (const span of collected)
355
+ pushSpan(spans, span.start, span.end);
356
+ for await (const line of readSpanLines(spans)) {
357
+ const event = parseEventLine(line);
358
+ if (event && matchesFilter(event, sessionIds, types))
359
+ yield event;
360
+ }
361
+ },
362
+ };
363
+ },
364
+ async index() {
365
+ const current = await withIndex();
366
+ // A snapshot, not the live maps. reconcile() mutates entries IN PLACE as
367
+ // the file grows, so handing out the internals would let a caller's
368
+ // `turnCount` or `lastTs` change under it between two reads of the same
369
+ // object — and let a caller corrupt the index by writing to a span. The
370
+ // copy is one small object per session; the alternative is a data race
371
+ // dressed up as a `ReadonlyMap`.
372
+ const bySession = new Map();
373
+ for (const [id, entry] of current.bySession) {
374
+ bySession.set(id, { ...entry, spans: entry.spans.map((span) => ({ ...span })), agentSessionIds: [...entry.agentSessionIds] });
375
+ }
376
+ const byAgentSession = new Map();
377
+ for (const [id, sessionIds] of current.byAgentSession)
378
+ byAgentSession.set(id, [...sessionIds]);
379
+ return { bySession, byAgentSession };
48
380
  },
49
381
  };
50
382
  }
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/core/collector/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,aAAa,EAAuB,MAAM,uBAAuB,CAAC;AAC3E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAgBzC;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,WAAmB,aAAa,CAAC,MAAM;IACtE,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC1C,IAAI,QAAQ,GAAyB,IAAI,CAAC;IAE1C,SAAS,SAAS;QAChB,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC7F,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,gEAAgE;IAChE,gEAAgE;IAChE,oDAAoD;IACpD,IAAI,KAAK,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;IAE7C,SAAS,OAAO,CAAI,GAAqB;QACvC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC7C,KAAK,GAAG,IAAI,CAAC,IAAI,CACf,GAAG,EAAE,GAAE,CAAC,EACR,GAAG,EAAE,GAAE,CAAC,CACT,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,MAAM,CAAC,KAAqB;YAC1B,OAAO,OAAO,CAAC,KAAK,IAAI,EAAE;gBACxB,MAAM,SAAS,EAAE,CAAC;gBAClB,MAAM,EAAE,CAAC,UAAU,CAAC,YAAY,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YAC1E,CAAC,CAAC,CAAC;QACL,CAAC;QAED,YAAY,CAAI,EAAoB;YAClC,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC;QACrB,CAAC;KACF,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/core/collector/store.ts"],"names":[],"mappings":"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"}
@@ -34,12 +34,18 @@ export declare class SessionNotReadyError extends HarnessError {
34
34
  constructor(id: string);
35
35
  }
36
36
  /**
37
- * Thrown by `resume()` when the session record has no `agentSessionId` to
38
- * resume from (it was never fully started, or is history-only with no
39
- * recorded session). Maps to HTTP 409.
37
+ * Thrown by `resume()` when the session cannot be handed back to its agent.
38
+ * Two causes, both 409:
39
+ *
40
+ * 1. No `agentSessionId` at all — never fully started (the default message).
41
+ * 2. An `agentSessionId` the agent's own store no longer holds, caught by
42
+ * `resume()`'s `canResume` pre-flight. Pass `reason` for these: the
43
+ * message reaches the user as a toast, and "why" is the whole point —
44
+ * the old behaviour spawned a doomed pty and left them with a bare
45
+ * "exit code 1" and a Resume button that would fail again.
40
46
  */
41
47
  export declare class SessionNotResumeableError extends HarnessError {
42
- constructor(id: string);
48
+ constructor(id: string, reason?: string);
43
49
  }
44
50
  /**
45
51
  * Thrown by `resume()` when the session already has a live pty — double-resume
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+CAA+C;AAC/C,qBAAa,YAAa,SAAQ,KAAK;IACrC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;gBAEb,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAQ3D;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,YAAY;gBACvC,EAAE,EAAE,MAAM;CAGvB;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;gBACxC,EAAE,EAAE,MAAM;CAMvB;AAED;;;;GAIG;AACH,qBAAa,yBAA0B,SAAQ,YAAY;gBAC7C,EAAE,EAAE,MAAM;CAGvB;AAED;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,YAAY;gBAC3C,EAAE,EAAE,MAAM;CAGvB;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;gBACxC,OAAO,EAAE,MAAM;CAG5B;AAED;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAO3C"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+CAA+C;AAC/C,qBAAa,YAAa,SAAQ,KAAK;IACrC,mFAAmF;IACnF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uDAAuD;IACvD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;gBAEb,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAQ3D;AAED;;;GAGG;AACH,qBAAa,mBAAoB,SAAQ,YAAY;gBACvC,EAAE,EAAE,MAAM;CAGvB;AAED;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;gBACxC,EAAE,EAAE,MAAM;CAMvB;AAED;;;;;;;;;;GAUG;AACH,qBAAa,yBAA0B,SAAQ,YAAY;gBAC7C,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAGxC;AAED;;;GAGG;AACH,qBAAa,uBAAwB,SAAQ,YAAY;gBAC3C,EAAE,EAAE,MAAM;CAGvB;AAED;;;GAGG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;gBACxC,OAAO,EAAE,MAAM;CAG5B;AAED;;;;;;;;GAQG;AACH,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;gBAEb,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAO3C"}
@@ -41,13 +41,19 @@ export class SessionNotReadyError extends HarnessError {
41
41
  }
42
42
  }
43
43
  /**
44
- * Thrown by `resume()` when the session record has no `agentSessionId` to
45
- * resume from (it was never fully started, or is history-only with no
46
- * recorded session). Maps to HTTP 409.
44
+ * Thrown by `resume()` when the session cannot be handed back to its agent.
45
+ * Two causes, both 409:
46
+ *
47
+ * 1. No `agentSessionId` at all — never fully started (the default message).
48
+ * 2. An `agentSessionId` the agent's own store no longer holds, caught by
49
+ * `resume()`'s `canResume` pre-flight. Pass `reason` for these: the
50
+ * message reaches the user as a toast, and "why" is the whole point —
51
+ * the old behaviour spawned a doomed pty and left them with a bare
52
+ * "exit code 1" and a Resume button that would fail again.
47
53
  */
48
54
  export class SessionNotResumeableError extends HarnessError {
49
- constructor(id) {
50
- super("SESSION_NOT_RESUMEABLE", `Session "${id}" has no agentSessionId to resume from`);
55
+ constructor(id, reason) {
56
+ super("SESSION_NOT_RESUMEABLE", reason ?? `Session "${id}" has no agentSessionId to resume from`);
51
57
  }
52
58
  }
53
59
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+CAA+C;AAC/C,MAAM,OAAO,YAAa,SAAQ,KAAK;IAMrC,YAAY,IAAY,EAAE,OAAe,EAAE,KAAe;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,sEAAsE;QACtE,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,mBAAoB,SAAQ,YAAY;IACnD,YAAY,EAAU;QACpB,KAAK,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,GAAG,CAAC,CAAC;IACtD,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IACpD,YAAY,EAAU;QACpB,KAAK,CACH,mBAAmB,EACnB,YAAY,EAAE,gFAAgF,CAC/F,CAAC;IACJ,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,yBAA0B,SAAQ,YAAY;IACzD,YAAY,EAAU;QACpB,KAAK,CAAC,wBAAwB,EAAE,YAAY,EAAE,wCAAwC,CAAC,CAAC;IAC1F,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,uBAAwB,SAAQ,YAAY;IACvD,YAAY,EAAU;QACpB,KAAK,CAAC,sBAAsB,EAAE,YAAY,EAAE,0BAA0B,CAAC,CAAC;IAC1E,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IACpD,YAAY,OAAe;QACzB,KAAK,CAAC,mBAAmB,EAAE,sCAAsC,OAAO,GAAG,CAAC,CAAC;IAC/E,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IAGpD,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CACH,kBAAkB,EAClB,GAAG,KAAK,gCAAgC,KAAK,0CAA0C,CACxF,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF"}
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,+CAA+C;AAC/C,MAAM,OAAO,YAAa,SAAQ,KAAK;IAMrC,YAAY,IAAY,EAAE,OAAe,EAAE,KAAe;QACxD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,sEAAsE;QACtE,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC5B,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,mBAAoB,SAAQ,YAAY;IACnD,YAAY,EAAU;QACpB,KAAK,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,GAAG,CAAC,CAAC;IACtD,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IACpD,YAAY,EAAU;QACpB,KAAK,CACH,mBAAmB,EACnB,YAAY,EAAE,gFAAgF,CAC/F,CAAC;IACJ,CAAC;CACF;AAED;;;;;;;;;;GAUG;AACH,MAAM,OAAO,yBAA0B,SAAQ,YAAY;IACzD,YAAY,EAAU,EAAE,MAAe;QACrC,KAAK,CAAC,wBAAwB,EAAE,MAAM,IAAI,YAAY,EAAE,wCAAwC,CAAC,CAAC;IACpG,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,uBAAwB,SAAQ,YAAY;IACvD,YAAY,EAAU;QACpB,KAAK,CAAC,sBAAsB,EAAE,YAAY,EAAE,0BAA0B,CAAC,CAAC;IAC1E,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IACpD,YAAY,OAAe;QACzB,KAAK,CAAC,mBAAmB,EAAE,sCAAsC,OAAO,GAAG,CAAC,CAAC;IAC/E,CAAC;CACF;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,oBAAqB,SAAQ,YAAY;IAGpD,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CACH,kBAAkB,EAClB,GAAG,KAAK,gCAAgC,KAAK,0CAA0C,CACxF,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF"}
@@ -11,6 +11,10 @@ export interface SeedExampleProjectOptions {
11
11
  versions?: ResolvedVersions;
12
12
  /** Overrides where the scaffold templates live (tests). */
13
13
  templatesDir?: string;
14
+ /** Run `npm install` in the freshly-scaffolded project so the Canvas can
15
+ * bundle it on first render. Defaults to true; set false in tests to keep
16
+ * them offline/fast. Ignored on reuse (nothing is re-scaffolded). */
17
+ installDependencies?: boolean;
14
18
  }
15
19
  export interface SeedExampleProjectResult {
16
20
  /** == options.targetRoot, resolved — the directory to open a session in. */
@@ -21,6 +25,10 @@ export interface SeedExampleProjectResult {
21
25
  created: boolean;
22
26
  /** Whether a git repo with an initial commit was created (false on reuse or when `git` is unavailable). */
23
27
  gitInitialized: boolean;
28
+ /** Whether `npm install` succeeded for the freshly-scaffolded project (false
29
+ * on reuse, or when npm is missing/offline — the Canvas then degrades to its
30
+ * "ask your agent to fix it" prompt on first render). */
31
+ dependenciesInstalled: boolean;
24
32
  }
25
33
  /**
26
34
  * Seeds (or reuses) the example project under `options.targetRoot`.
@@ -1 +1 @@
1
- {"version":3,"file":"example-seed.d.ts","sourceRoot":"","sources":["../../src/core/example-seed.ts"],"names":[],"mappings":"AAqCA,OAAO,EAA0C,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMnG,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AA6LlD,MAAM,WAAW,yBAAyB;IACxC;sFACkF;IAClF,UAAU,EAAE,MAAM,CAAC;IACnB;mEAC+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,wBAAwB;IACvC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,2GAA2G;IAC3G,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAoD9G"}
1
+ {"version":3,"file":"example-seed.d.ts","sourceRoot":"","sources":["../../src/core/example-seed.ts"],"names":[],"mappings":"AAyCA,OAAO,EAA0C,KAAK,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMnG,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AA2NlD,MAAM,WAAW,yBAAyB;IACxC;sFACkF;IAClF,UAAU,EAAE,MAAM,CAAC;IACnB;mEAC+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,sEAAsE;IACtE,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAC5B,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;0EAEsE;IACtE,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,UAAU,EAAE,MAAM,CAAC;IACnB,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,2GAA2G;IAC3G,cAAc,EAAE,OAAO,CAAC;IACxB;;8DAE0D;IAC1D,qBAAqB,EAAE,OAAO,CAAC;CAChC;AAED;;;;;;;GAOG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,OAAO,CAAC,wBAAwB,CAAC,CA0D9G"}
@@ -1,13 +1,17 @@
1
1
  /**
2
2
  * Seeds the bundled example project — a directory the harness opens
3
- * beautifully on first run. Shared by two callers with different needs:
3
+ * beautifully on first run.
4
4
  *
5
- * - `POST /api/sample-project` (the welcome panel's "Run the sample
6
- * project" action)seeds `~/.sapiom/harness/sample-project` lazily and
7
- * idempotently: an already-seeded copy is reused as-is, including any
8
- * edits the user's agent has made to it since.
9
- * - `scripts/seed-example.mjs` (demo prep) same seeding with
10
- * `force: true`, which wipes and regenerates from scratch.
5
+ * ONE caller today: `scripts/seed-example.mjs` (demo prep), which seeds with
6
+ * `force: true` wipe and regenerate from scratch.
7
+ *
8
+ * There was a second: `POST /api/sample-project`, behind the welcome panel's
9
+ * "Sample project" action, which seeded `~/.sapiom/harness/sample-project`
10
+ * lazily and idempotently. Both the route and the action were removed because
11
+ * the in-app flow did not work; this module was kept because the demo script
12
+ * still needs it. So an existing `~/.sapiom/harness/sample-project/` on a
13
+ * machine is leftover output, not state the app maintains — nothing in the
14
+ * running Studio reads or writes it.
11
15
  *
12
16
  * Produces:
13
17
  * <targetRoot>/order-triage/ — a real scaffolded agent project
@@ -41,7 +45,12 @@ export const SAMPLE_PROJECT_NAME = "order-triage";
41
45
  /** Locate @sapiom/agent-core's bundled templates dir (no `__dirname` in ESM). */
42
46
  function agentCoreTemplatesDir() {
43
47
  const entry = nodeRequire.resolve("@sapiom/agent-core");
44
- return path.resolve(path.dirname(entry), "..", "..", "templates");
48
+ const dir = path.resolve(path.dirname(entry), "..", "..", "templates");
49
+ // Embedded in Electron, require.resolve reports the app.asar (virtual) path;
50
+ // scaffold()'s cpSync can't opendir inside the asar archive (ENOTDIR), so
51
+ // point at the unpacked twin. No-op under the CLI (real filesystem path).
52
+ // The desktop host must asarUnpack node_modules (it unpacks all of them).
53
+ return dir.replace(/([\\/])app\.asar([\\/])/, "$1app.asar.unpacked$2");
45
54
  }
46
55
  function tryGit(cwd, args) {
47
56
  try {
@@ -52,6 +61,31 @@ function tryGit(cwd, args) {
52
61
  return false;
53
62
  }
54
63
  }
64
+ /**
65
+ * Best-effort `npm install` in the freshly-scaffolded project. The Canvas
66
+ * step-graph extraction esbuild-bundles the project, so without its declared
67
+ * deps (`@sapiom/agent`, `zod`, …) installed the very first render fails with
68
+ * "Could not resolve …". Installing here means a freshly-seeded project opens
69
+ * with a working Canvas instead of an error the user has to ask the agent to
70
+ * fix. Non-fatal: if npm is missing or offline, seeding still succeeds and the
71
+ * Canvas falls back to its existing "ask your agent to fix it" prompt.
72
+ * `shell: true` lets Windows resolve the `npm.cmd` shim; cwd (which may contain
73
+ * spaces) is passed via options, not the command line, so it stays safe.
74
+ */
75
+ function tryInstallDependencies(projectDir) {
76
+ try {
77
+ execFileSync("npm", ["install", "--no-audit", "--no-fund", "--loglevel=error"], {
78
+ cwd: projectDir,
79
+ stdio: "ignore",
80
+ shell: process.platform === "win32",
81
+ timeout: 120000,
82
+ });
83
+ return true;
84
+ }
85
+ catch {
86
+ return false;
87
+ }
88
+ }
55
89
  /** Fold the demo customizations (index.ts, sapiom.json) into the scaffold's initial commit. */
56
90
  function commitCustomizations(projectDir) {
57
91
  if (!existsSync(path.join(projectDir, ".git")))
@@ -251,7 +285,7 @@ export async function seedExampleProject(options) {
251
285
  };
252
286
  if (alreadySeeded && !options.force) {
253
287
  await writeCanvasPair(false);
254
- return { root, projectDir, created: false, gitInitialized: false };
288
+ return { root, projectDir, created: false, gitInitialized: false, dependenciesInstalled: false };
255
289
  }
256
290
  // Wipe a stale copy before rescaffolding — scaffold() refuses a non-empty dir.
257
291
  await fs.rm(projectDir, { recursive: true, force: true });
@@ -270,8 +304,11 @@ export async function seedExampleProject(options) {
270
304
  });
271
305
  await fs.writeFile(path.join(projectDir, "index.ts"), ORDER_TRIAGE_INDEX_TS, "utf8");
272
306
  writeConfig(projectDir, { name: SAMPLE_PROJECT_NAME });
307
+ // Install deps BEFORE the initial commit so the (gitignored) node_modules is
308
+ // present for the Canvas's first bundle, while staying out of git history.
309
+ const dependenciesInstalled = (options.installDependencies ?? true) ? tryInstallDependencies(projectDir) : false;
273
310
  commitCustomizations(projectDir);
274
311
  await writeCanvasPair(true);
275
- return { root, projectDir, created: true, gitInitialized: result.gitInitialized };
312
+ return { root, projectDir, created: true, gitInitialized: result.gitInitialized, dependenciesInstalled };
276
313
  }
277
314
  //# sourceMappingURL=example-seed.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"example-seed.js","sourceRoot":"","sources":["../../src/core/example-seed.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"example-seed.js","sourceRoot":"","sources":["../../src/core/example-seed.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,14 @@ export interface GenerateSystemPromptFileOptions {
4
4
  generatedRoot?: string;
5
5
  /** Defaults to the harness's default profile (DEFAULT_SYSTEM_PROMPT). */
6
6
  prompt?: string;
7
+ /**
8
+ * Extra text appended after the prompt, separated by a blank line — today
9
+ * the portable-continue brief (core/rehydration.ts). Kept distinct from
10
+ * `prompt` so a caller that only wants to *add* context doesn't have to
11
+ * re-import and re-compose the default profile (and can't accidentally
12
+ * replace it). Empty/whitespace appendices are ignored.
13
+ */
14
+ appendix?: string;
7
15
  }
8
16
  /** Writes `<generated>/<harnessSessionId>/system-prompt.txt`. Returns its
9
17
  * absolute path (LaunchOpts.systemPromptFile). */
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../../src/core/inject/system-prompt.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,+BAA+B;IAC9C;iFAC6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;mDACmD;AACnD,wBAAsB,wBAAwB,CAC5C,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,MAAM,CAAC,CAQjB"}
1
+ {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../../src/core/inject/system-prompt.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,+BAA+B;IAC9C;iFAC6E;IAC7E,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;mDACmD;AACnD,wBAAsB,wBAAwB,CAC5C,gBAAgB,EAAE,MAAM,EACxB,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,MAAM,CAAC,CAUjB"}
@@ -15,8 +15,10 @@ export async function generateSystemPromptFile(harnessSessionId, options = {}) {
15
15
  const root = expandHome(options.generatedRoot ?? HARNESS_PATHS.generated);
16
16
  const dir = path.join(root, harnessSessionId);
17
17
  await fs.mkdir(dir, { recursive: true });
18
+ const base = options.prompt ?? DEFAULT_SYSTEM_PROMPT;
19
+ const appendix = options.appendix?.trim();
18
20
  const filePath = path.join(dir, "system-prompt.txt");
19
- await fs.writeFile(filePath, options.prompt ?? DEFAULT_SYSTEM_PROMPT, "utf8");
21
+ await fs.writeFile(filePath, appendix ? `${base}\n\n${appendix}\n` : base, "utf8");
20
22
  return filePath;
21
23
  }
22
24
  //# sourceMappingURL=system-prompt.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../../src/core/inject/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAUlE;mDACmD;AACnD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,gBAAwB,EACxB,UAA2C,EAAE;IAE7C,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,aAAa,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;IAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAC9C,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,IAAI,qBAAqB,EAAE,MAAM,CAAC,CAAC;IAC9E,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../../src/core/inject/system-prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAkBlE;mDACmD;AACnD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,gBAAwB,EACxB,UAA2C,EAAE;IAE7C,MAAM,IAAI,GAAG,UAAU,CAAC,OAAO,CAAC,aAAa,IAAI,aAAa,CAAC,SAAS,CAAC,CAAC;IAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAC;IAC9C,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,IAAI,qBAAqB,CAAC;IACrD,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,OAAO,QAAQ,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnF,OAAO,QAAQ,CAAC;AAClB,CAAC"}