@bastani/atomic 0.9.57 → 0.9.58-alpha.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 (117) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/builtin/intercom/package.json +1 -1
  3. package/dist/builtin/mcp/package.json +1 -1
  4. package/dist/builtin/subagents/CHANGELOG.md +12 -0
  5. package/dist/builtin/subagents/package.json +1 -1
  6. package/dist/builtin/subagents/src/extension/index.bundle.mjs +39 -5
  7. package/dist/builtin/web-access/CHANGELOG.md +12 -0
  8. package/dist/builtin/web-access/index.bundle.mjs +2 -2
  9. package/dist/builtin/web-access/package.json +1 -1
  10. package/dist/builtin/workflows/CHANGELOG.md +42 -0
  11. package/dist/builtin/workflows/package.json +1 -1
  12. package/dist/builtin/workflows/src/extension/index.bundle.mjs +885 -228
  13. package/dist/builtin/workflows/src/extension/local-worker-entry.mjs +933 -175
  14. package/dist/builtin/workflows/src/index.js +630 -162
  15. package/dist/builtin/workflows/src/local-worker-entry.mjs +933 -175
  16. package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +1 -1
  17. package/dist/builtin/workflows/src/shared/workflow-infrastructure-error.d.ts +13 -0
  18. package/dist/builtin/workflows/src/workers/public-options.d.ts +10 -0
  19. package/dist/core/agent-session-persistent-custom-messages.d.ts +5 -0
  20. package/dist/core/agent-session-persistent-custom-messages.d.ts.map +1 -1
  21. package/dist/core/agent-session-persistent-custom-messages.js +16 -0
  22. package/dist/core/agent-session-persistent-custom-messages.js.map +1 -1
  23. package/dist/core/agent-session-tasks.d.ts.map +1 -1
  24. package/dist/core/agent-session-tasks.js +20 -0
  25. package/dist/core/agent-session-tasks.js.map +1 -1
  26. package/dist/core/settings-defaults.d.ts +4 -0
  27. package/dist/core/settings-defaults.d.ts.map +1 -1
  28. package/dist/core/settings-defaults.js +4 -0
  29. package/dist/core/settings-defaults.js.map +1 -1
  30. package/dist/core/settings-manager-resource-accessors.d.ts +2 -0
  31. package/dist/core/settings-manager-resource-accessors.d.ts.map +1 -1
  32. package/dist/core/settings-manager-resource-accessors.js +6 -0
  33. package/dist/core/settings-manager-resource-accessors.js.map +1 -1
  34. package/dist/core/settings-schema.d.ts +9 -0
  35. package/dist/core/settings-schema.d.ts.map +1 -1
  36. package/dist/core/settings-schema.js +11 -0
  37. package/dist/core/settings-schema.js.map +1 -1
  38. package/dist/core/settings-types.d.ts +1 -1
  39. package/dist/core/settings-types.d.ts.map +1 -1
  40. package/dist/core/settings-types.js.map +1 -1
  41. package/dist/core/tasks/agent-adapter.d.ts +10 -1
  42. package/dist/core/tasks/agent-adapter.d.ts.map +1 -1
  43. package/dist/core/tasks/agent-adapter.js +20 -0
  44. package/dist/core/tasks/agent-adapter.js.map +1 -1
  45. package/dist/core/tasks/contracts.d.ts +6 -0
  46. package/dist/core/tasks/contracts.d.ts.map +1 -1
  47. package/dist/core/tasks/contracts.js.map +1 -1
  48. package/dist/core/tasks/heartbeat-notice.d.ts +64 -0
  49. package/dist/core/tasks/heartbeat-notice.d.ts.map +1 -0
  50. package/dist/core/tasks/heartbeat-notice.js +98 -0
  51. package/dist/core/tasks/heartbeat-notice.js.map +1 -0
  52. package/dist/core/tasks/heartbeat.d.ts +75 -0
  53. package/dist/core/tasks/heartbeat.d.ts.map +1 -0
  54. package/dist/core/tasks/heartbeat.js +440 -0
  55. package/dist/core/tasks/heartbeat.js.map +1 -0
  56. package/dist/core/tasks/supervisor.d.ts +2 -0
  57. package/dist/core/tasks/supervisor.d.ts.map +1 -1
  58. package/dist/core/tasks/supervisor.js +32 -4
  59. package/dist/core/tasks/supervisor.js.map +1 -1
  60. package/dist/core/tasks/task-view-source.d.ts +72 -0
  61. package/dist/core/tasks/task-view-source.d.ts.map +1 -0
  62. package/dist/core/tasks/task-view-source.js +155 -0
  63. package/dist/core/tasks/task-view-source.js.map +1 -0
  64. package/dist/core/tools/bash-pty-native.d.ts +2 -0
  65. package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
  66. package/dist/core/tools/bash-pty-native.js +1 -0
  67. package/dist/core/tools/bash-pty-native.js.map +1 -1
  68. package/dist/core/tools/bash.d.ts +3 -0
  69. package/dist/core/tools/bash.d.ts.map +1 -1
  70. package/dist/core/tools/bash.js +20 -2
  71. package/dist/core/tools/bash.js.map +1 -1
  72. package/dist/core/tools/powershell.d.ts +16 -8
  73. package/dist/core/tools/powershell.d.ts.map +1 -1
  74. package/dist/index.d.ts +5 -3
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +4 -2
  77. package/dist/index.js.map +1 -1
  78. package/dist/modes/interactive/components/chat-session-host-events.d.ts.map +1 -1
  79. package/dist/modes/interactive/components/chat-session-host-events.js +7 -0
  80. package/dist/modes/interactive/components/chat-session-host-events.js.map +1 -1
  81. package/dist/modes/interactive/components/chat-session-host-state.d.ts +3 -0
  82. package/dist/modes/interactive/components/chat-session-host-state.d.ts.map +1 -1
  83. package/dist/modes/interactive/components/chat-session-host-state.js +4 -0
  84. package/dist/modes/interactive/components/chat-session-host-state.js.map +1 -1
  85. package/dist/modes/interactive/components/chat-session-host-types.d.ts +11 -0
  86. package/dist/modes/interactive/components/chat-session-host-types.d.ts.map +1 -1
  87. package/dist/modes/interactive/components/chat-session-host-types.js.map +1 -1
  88. package/dist/modes/interactive/components/chat-session-host.d.ts +2 -0
  89. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  90. package/dist/modes/interactive/components/chat-session-host.js +15 -8
  91. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  92. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  93. package/dist/modes/interactive/components/custom-message.js +12 -0
  94. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  95. package/dist/modes/interactive/components/task-detail.d.ts.map +1 -1
  96. package/dist/modes/interactive/components/task-detail.js +5 -0
  97. package/dist/modes/interactive/components/task-detail.js.map +1 -1
  98. package/dist/modes/interactive/components/task-heartbeat-message.d.ts +14 -0
  99. package/dist/modes/interactive/components/task-heartbeat-message.d.ts.map +1 -0
  100. package/dist/modes/interactive/components/task-heartbeat-message.js +76 -0
  101. package/dist/modes/interactive/components/task-heartbeat-message.js.map +1 -0
  102. package/dist/modes/interactive/components/task-inspector.d.ts +6 -3
  103. package/dist/modes/interactive/components/task-inspector.d.ts.map +1 -1
  104. package/dist/modes/interactive/components/task-inspector.js +53 -100
  105. package/dist/modes/interactive/components/task-inspector.js.map +1 -1
  106. package/dist/modes/interactive/skill-command-autocomplete.d.ts +22 -2
  107. package/dist/modes/interactive/skill-command-autocomplete.d.ts.map +1 -1
  108. package/dist/modes/interactive/skill-command-autocomplete.js +28 -9
  109. package/dist/modes/interactive/skill-command-autocomplete.js.map +1 -1
  110. package/docs/background-tasks.md +65 -1
  111. package/docs/settings.md +12 -0
  112. package/docs/subagents.md +2 -0
  113. package/docs/tools.md +2 -1
  114. package/docs/workflows/operations.md +5 -3
  115. package/npm-shrinkwrap.json +32 -32
  116. package/package.json +3 -3
  117. package/schemas/settings.schema.json +24 -0
@@ -0,0 +1,440 @@
1
+ import { taskOutputText } from "./command-output.js";
2
+ import { DEFAULT_TASK_HEARTBEAT_MS, formatTaskHeartbeat, isValidTaskHeartbeatMs, singleLine, TASK_HEARTBEAT_MESSAGE_TYPE, } from "./heartbeat-notice.js";
3
+ import { taskOwnTranscriptEntries, } from "./supervisor.js";
4
+ export * from "./heartbeat-notice.js";
5
+ /** Tasks described in full by one notice; further due tasks are only listed. */
6
+ export const TASK_HEARTBEAT_DETAIL_LIMIT = 8;
7
+ /** Further due tasks listed by name in one notice; the rest are counted. */
8
+ export const TASK_HEARTBEAT_LIST_LIMIT = 20;
9
+ /** Boundaries due within this window (capped at a quarter cadence) join the notice that is going out. */
10
+ export const TASK_HEARTBEAT_COALESCE_MS = 60_000;
11
+ /** While the owner has not read the previous notice, due tasks wait and are rechecked this often. */
12
+ export const TASK_HEARTBEAT_RECHECK_MS = 30_000;
13
+ /** How often a running shell's output is sampled to date its last output. */
14
+ export const TASK_HEARTBEAT_OUTPUT_SAMPLE_MS = 30_000;
15
+ const OUTPUT_TAIL_BYTES = 2048;
16
+ const OUTPUT_TAIL_LINES = 6;
17
+ const LINE_CHARS = 160;
18
+ const TITLE_CHARS = 120;
19
+ /** Longest delay a host timer accepts before it overflows to an immediate fire. */
20
+ const MAX_TIMER_DELAY_MS = 2_147_483_647;
21
+ /** The owner's default cadence, or the built-in one when its setting cannot be read or is out of range. */
22
+ export function defaultTaskHeartbeatMs(delivery) {
23
+ try {
24
+ const configured = delivery.defaultIntervalMs();
25
+ return isValidTaskHeartbeatMs(configured) ? configured : DEFAULT_TASK_HEARTBEAT_MS;
26
+ }
27
+ catch {
28
+ return DEFAULT_TASK_HEARTBEAT_MS;
29
+ }
30
+ }
31
+ const systemClock = {
32
+ now: () => Date.now(),
33
+ setTimeout: (run, delayMs) => {
34
+ const handle = setTimeout(run, delayMs);
35
+ handle.unref();
36
+ return handle;
37
+ },
38
+ clearTimeout: (handle) => clearTimeout(handle),
39
+ };
40
+ function activityKey(task) {
41
+ return JSON.stringify([task.currentAction, task.metrics, task.attention, task.model]);
42
+ }
43
+ /** Whether the newest message in a child's history is an assistant turn whose tool calls have not returned yet. */
44
+ function endsInToolCall(entries) {
45
+ for (let index = entries.length - 1; index >= 0; index--) {
46
+ const entry = entries[index];
47
+ if (entry?.type !== "message")
48
+ continue;
49
+ const message = entry.message;
50
+ return message.role === "assistant" && message.content.some((block) => block.type === "toolCall");
51
+ }
52
+ return false;
53
+ }
54
+ /** First boundary on the `startedAt + n × intervalMs` series strictly after `after`. */
55
+ function nextBoundary(startedAt, intervalMs, after) {
56
+ const n = Math.max(1, Math.floor((after - startedAt) / intervalMs) + 1);
57
+ const boundary = startedAt + n * intervalMs;
58
+ return boundary > after ? boundary : startedAt + (n + 1) * intervalMs;
59
+ }
60
+ function byBoundary(a, b) {
61
+ const left = a.nextAt ?? Number.POSITIVE_INFINITY;
62
+ const right = b.nextAt ?? Number.POSITIVE_INFINITY;
63
+ if (left !== right)
64
+ return left - right;
65
+ return a.taskId < b.taskId ? -1 : a.taskId > b.taskId ? 1 : 0;
66
+ }
67
+ /**
68
+ * Periodic "is this still making progress?" notices for one task owner's running shells and subagents.
69
+ *
70
+ * It follows the workflow heartbeat rules: boundaries are anchored at the task's start and never at the previous
71
+ * delivery, missed boundaries are skipped rather than replayed, and only one notice per owner is outstanding. Unlike
72
+ * a workflow run, an owner can have many tasks, so tasks due together share one bounded notice, and a task due while
73
+ * the owner has not read the previous notice waits for it rather than losing its turn.
74
+ */
75
+ export class TaskHeartbeatMonitor {
76
+ options;
77
+ clock;
78
+ tracked = new Map();
79
+ subscription;
80
+ timer;
81
+ /** The time the current timer wakes for, so an unchanged schedule keeps its timer. */
82
+ timerAt;
83
+ busy = false;
84
+ disposed = false;
85
+ recheckAt;
86
+ nextSampleAt;
87
+ constructor(options) {
88
+ this.options = options;
89
+ this.clock = options.clock ?? systemClock;
90
+ }
91
+ /** Begin watching the owner. Idempotent. */
92
+ start() {
93
+ if (this.subscription || this.disposed)
94
+ return;
95
+ const watched = this.options.supervisor.watchOwnerTasks(this.options.owner);
96
+ if (!watched.ok)
97
+ return;
98
+ this.subscription = watched.value;
99
+ this.subscription.onReconcile = (snapshot, events) => this.reconcile(snapshot, events);
100
+ this.reconcile(this.subscription.snapshot, []);
101
+ }
102
+ dispose() {
103
+ if (this.disposed)
104
+ return;
105
+ this.disposed = true;
106
+ this.subscription?.dispose();
107
+ this.subscription = undefined;
108
+ this.tracked.clear();
109
+ this.disarm();
110
+ }
111
+ reconcile(snapshot, events) {
112
+ if (this.disposed)
113
+ return;
114
+ if (snapshot.state !== "open") {
115
+ if (snapshot.state === "closed")
116
+ this.dispose();
117
+ else {
118
+ this.tracked.clear();
119
+ this.disarm();
120
+ }
121
+ return;
122
+ }
123
+ const at = this.clock.now();
124
+ const reported = new Set();
125
+ for (const event of events)
126
+ if (event.payload.kind === "task-activity")
127
+ reported.add(event.payload.ref.taskId);
128
+ const running = new Set();
129
+ for (const task of snapshot.tasks) {
130
+ // Queued, stopping, paused and finished tasks do not heartbeat.
131
+ if (task.execution.kind !== "running")
132
+ continue;
133
+ const id = task.ref.taskId;
134
+ running.add(id);
135
+ const key = activityKey(task);
136
+ const entry = this.tracked.get(id);
137
+ if (entry) {
138
+ entry.record = task;
139
+ if (key !== entry.activityKey || reported.has(id)) {
140
+ entry.activityKey = key;
141
+ entry.lastActivityAt = at;
142
+ }
143
+ continue;
144
+ }
145
+ const intervalMs = this.resolveInterval(task);
146
+ this.tracked.set(id, {
147
+ taskId: id,
148
+ record: task,
149
+ startedAt: at,
150
+ intervalMs,
151
+ ...(intervalMs > 0 ? { nextAt: at + intervalMs } : {}),
152
+ ...(reported.has(id) ? { lastActivityAt: at } : {}),
153
+ activityKey: key,
154
+ outputEnd: 0n,
155
+ });
156
+ }
157
+ for (const id of [...this.tracked.keys()])
158
+ if (!running.has(id))
159
+ this.tracked.delete(id);
160
+ if (!this.hasSampledShells())
161
+ this.nextSampleAt = undefined;
162
+ else
163
+ this.nextSampleAt ??= at + TASK_HEARTBEAT_OUTPUT_SAMPLE_MS;
164
+ this.arm();
165
+ }
166
+ resolveInterval(task) {
167
+ // Owners with a heartbeat binding fix each task's cadence on its record at admission.
168
+ if (task.heartbeatMs !== undefined)
169
+ return isValidTaskHeartbeatMs(task.heartbeatMs) ? task.heartbeatMs : 0;
170
+ const delivery = this.options.delivery();
171
+ return delivery ? defaultTaskHeartbeatMs(delivery) : DEFAULT_TASK_HEARTBEAT_MS;
172
+ }
173
+ hasSampledShells() {
174
+ for (const entry of this.tracked.values())
175
+ if (entry.record.kind === "command" && entry.intervalMs > 0)
176
+ return true;
177
+ return false;
178
+ }
179
+ disarm() {
180
+ if (this.timer === undefined)
181
+ return;
182
+ this.clock.clearTimeout(this.timer);
183
+ this.timer = undefined;
184
+ this.timerAt = undefined;
185
+ }
186
+ arm() {
187
+ if (this.disposed || this.busy) {
188
+ this.disarm();
189
+ return;
190
+ }
191
+ // A blocked owner cannot receive anything before its recheck, however many tasks come due meanwhile.
192
+ let wakeAt = this.recheckAt ?? Number.POSITIVE_INFINITY;
193
+ if (this.recheckAt === undefined)
194
+ for (const entry of this.tracked.values())
195
+ if (entry.nextAt !== undefined && entry.nextAt < wakeAt)
196
+ wakeAt = entry.nextAt;
197
+ if (this.nextSampleAt !== undefined && this.nextSampleAt < wakeAt)
198
+ wakeAt = this.nextSampleAt;
199
+ // Activity reconciles many times a second; it rarely moves the next wake-up.
200
+ if (this.timer !== undefined && this.timerAt === wakeAt)
201
+ return;
202
+ this.disarm();
203
+ if (!Number.isFinite(wakeAt))
204
+ return;
205
+ const delay = Math.min(Math.max(1, Math.ceil(wakeAt - this.clock.now())), MAX_TIMER_DELAY_MS);
206
+ this.timerAt = wakeAt;
207
+ this.timer = this.clock.setTimeout(() => {
208
+ this.timer = undefined;
209
+ this.timerAt = undefined;
210
+ void this.wake();
211
+ }, delay);
212
+ }
213
+ async wake() {
214
+ if (this.disposed || this.busy)
215
+ return;
216
+ this.busy = true;
217
+ try {
218
+ const at = this.clock.now();
219
+ if (this.nextSampleAt !== undefined && this.nextSampleAt <= at) {
220
+ await this.sampleShellOutput(at);
221
+ this.nextSampleAt = this.hasSampledShells() ? at + TASK_HEARTBEAT_OUTPUT_SAMPLE_MS : undefined;
222
+ }
223
+ await this.beat(at);
224
+ }
225
+ catch {
226
+ // A failed check skips this boundary; the next one is already scheduled.
227
+ }
228
+ finally {
229
+ this.busy = false;
230
+ this.arm();
231
+ }
232
+ }
233
+ async beat(at) {
234
+ if (this.recheckAt !== undefined && this.recheckAt > at)
235
+ return;
236
+ this.recheckAt = undefined;
237
+ const entries = [...this.tracked.values()];
238
+ if (!entries.some((entry) => entry.nextAt !== undefined && entry.nextAt <= at))
239
+ return;
240
+ const delivery = this.options.delivery();
241
+ let unread = false;
242
+ try {
243
+ unread = delivery?.hasUnreadHeartbeat() === true;
244
+ }
245
+ catch {
246
+ unread = false;
247
+ }
248
+ if (unread) {
249
+ // One outstanding notice per owner: due tasks stay owed and join the next notice instead of stacking.
250
+ this.recheckAt = at + TASK_HEARTBEAT_RECHECK_MS;
251
+ return;
252
+ }
253
+ const batch = entries
254
+ .filter((entry) => entry.nextAt !== undefined &&
255
+ entry.nextAt <= at + Math.min(TASK_HEARTBEAT_COALESCE_MS, entry.intervalMs / 4))
256
+ .sort(byBoundary);
257
+ for (const entry of batch)
258
+ entry.nextAt = nextBoundary(entry.startedAt, entry.intervalMs, Math.max(at, entry.nextAt ?? at));
259
+ if (!delivery)
260
+ return;
261
+ const details = await this.describe(batch, at);
262
+ // A task that finished while its notice was being prepared is no longer mentioned.
263
+ const live = (taskId) => this.tracked.has(taskId);
264
+ details.tasks = details.tasks.filter((task) => live(task.taskId));
265
+ details.more = details.more.filter((task) => live(task.taskId));
266
+ details.moreCount = batch.slice(TASK_HEARTBEAT_DETAIL_LIMIT).filter((entry) => live(entry.taskId)).length;
267
+ if (details.tasks.length === 0 || this.disposed)
268
+ return;
269
+ await delivery.deliver({
270
+ customType: TASK_HEARTBEAT_MESSAGE_TYPE,
271
+ content: formatTaskHeartbeat(details),
272
+ display: true,
273
+ details,
274
+ });
275
+ }
276
+ async describe(batch, at) {
277
+ const detailed = batch.slice(0, TASK_HEARTBEAT_DETAIL_LIMIT);
278
+ const rest = batch.slice(TASK_HEARTBEAT_DETAIL_LIMIT);
279
+ const tasks = [];
280
+ for (const entry of detailed)
281
+ tasks.push(await this.describeTask(entry, at));
282
+ return {
283
+ scheduledAt: at,
284
+ tasks,
285
+ more: rest.slice(0, TASK_HEARTBEAT_LIST_LIMIT).map((entry) => ({
286
+ taskId: entry.taskId,
287
+ kind: entry.record.kind,
288
+ title: singleLine(entry.record.title, TITLE_CHARS),
289
+ })),
290
+ moreCount: rest.length,
291
+ };
292
+ }
293
+ async describeTask(entry, at) {
294
+ const task = entry.record;
295
+ const lease = this.lease(entry.taskId);
296
+ const described = {
297
+ taskId: entry.taskId,
298
+ kind: task.kind,
299
+ title: singleLine(task.title, TITLE_CHARS),
300
+ ...(task.agentName === undefined ? {} : { agentName: singleLine(task.agentName, TITLE_CHARS) }),
301
+ ...(task.kind === "agent" && task.model !== undefined ? { model: task.model } : {}),
302
+ elapsedMs: Math.max(0, at - entry.startedAt),
303
+ intervalMs: entry.intervalMs,
304
+ };
305
+ if (task.kind === "command" && lease) {
306
+ const end = await this.observeOutput(entry, lease, at);
307
+ if (end !== undefined)
308
+ described.output = { bytes: Number(end), tail: await this.outputTail(lease, end) };
309
+ }
310
+ if (entry.lastActivityAt !== undefined)
311
+ described.lastActivityAgoMs = Math.max(0, at - entry.lastActivityAt);
312
+ if (task.kind === "agent") {
313
+ const entries = lease ? taskOwnTranscriptEntries(lease) : undefined;
314
+ if (task.currentAction)
315
+ described.currentAction = {
316
+ tool: singleLine(task.currentAction.tool, 60),
317
+ text: singleLine(task.currentAction.text, LINE_CHARS),
318
+ // The record keeps the last reported action after its tool returns. The child's own history says
319
+ // whether a call is still outstanding: its last message is an assistant turn that called tools.
320
+ running: entries !== undefined && endsInToolCall(entries),
321
+ };
322
+ if (task.metrics?.toolCount !== undefined)
323
+ described.toolCount = task.metrics.toolCount;
324
+ if (task.metrics?.tokenCount !== undefined)
325
+ described.tokenCount = task.metrics.tokenCount;
326
+ if (entries)
327
+ described.turnCount = entries.filter((item) => item.type === "message" && item.message.role === "assistant").length;
328
+ }
329
+ if (task.attention.kind === "input-needed")
330
+ described.attention = `waiting for input: ${singleLine(task.attention.prompt, LINE_CHARS)}`;
331
+ else if (task.attention.kind === "no-recent-activity")
332
+ described.attention = "no recent activity";
333
+ return described;
334
+ }
335
+ lease(taskId) {
336
+ const found = this.options.supervisor.lookupTask(this.options.owner, taskId);
337
+ return found.ok ? found.value : undefined;
338
+ }
339
+ async sampleShellOutput(at) {
340
+ for (const entry of [...this.tracked.values()]) {
341
+ if (entry.record.kind !== "command" || entry.intervalMs === 0)
342
+ continue;
343
+ const lease = this.lease(entry.taskId);
344
+ if (lease)
345
+ await this.observeOutput(entry, lease, at);
346
+ }
347
+ }
348
+ /** Current retained output size; growth since the last look dates the shell's last output. */
349
+ async observeOutput(entry, lease, at) {
350
+ const end = await findOutputEnd(this.options.supervisor, lease, entry.outputEnd);
351
+ if (end === undefined)
352
+ return undefined;
353
+ if (end > entry.outputEnd) {
354
+ entry.outputEnd = end;
355
+ entry.lastActivityAt = at;
356
+ }
357
+ return end;
358
+ }
359
+ async outputTail(lease, end) {
360
+ if (end === 0n)
361
+ return [];
362
+ const start = end > BigInt(OUTPUT_TAIL_BYTES) ? end - BigInt(OUTPUT_TAIL_BYTES) : 0n;
363
+ const page = await this.options.supervisor.readTaskOutput(lease, {
364
+ start: String(start),
365
+ maximumBytes: OUTPUT_TAIL_BYTES,
366
+ });
367
+ if (!page.ok)
368
+ return [];
369
+ const lines = taskOutputText(page.value).split("\n");
370
+ // The window can open mid-line; that fragment is not a line of output.
371
+ if (start > 0n)
372
+ lines.shift();
373
+ return lines
374
+ .map((line) => {
375
+ // A CRLF ending is not a redraw; a carriage return inside a line redraws it, so its last state counts.
376
+ const ended = line.replace(/\r+$/, "");
377
+ return singleLine(ended.slice(ended.lastIndexOf("\r") + 1), LINE_CHARS).trimEnd();
378
+ })
379
+ .filter((line) => line.trim().length > 0)
380
+ .slice(-OUTPUT_TAIL_LINES);
381
+ }
382
+ }
383
+ /**
384
+ * Retained output size of a running shell, found with one-byte reads: a read past the end returns nothing. Gallops
385
+ * from the last known size, then bisects, so a large burst of output costs a few dozen tiny reads, not a full scan.
386
+ */
387
+ async function findOutputEnd(supervisor, lease, from) {
388
+ const probe = async (offset) => {
389
+ const page = await supervisor.readTaskOutput(lease, { start: String(offset), maximumBytes: 1 });
390
+ if (!page.ok)
391
+ return undefined;
392
+ if (page.value.nextOffset !== undefined)
393
+ return { before: true, end: BigInt(page.value.nextOffset) };
394
+ let end = offset;
395
+ for (const chunk of page.value.chunks)
396
+ if (BigInt(chunk.offsets.end) > end)
397
+ end = BigInt(chunk.offsets.end);
398
+ for (const range of page.value.omittedRanges)
399
+ if (BigInt(range.end) > end)
400
+ end = BigInt(range.end);
401
+ // No byte beyond this page: the output ends at its last byte, or at or before `offset` when it is empty.
402
+ return { before: end > offset, end };
403
+ };
404
+ let low = from;
405
+ const first = await probe(low);
406
+ if (!first)
407
+ return undefined;
408
+ if (!first.before)
409
+ return first.end > from ? first.end : from;
410
+ let step = 65536n;
411
+ let high = low + step;
412
+ for (;;) {
413
+ const result = await probe(high);
414
+ if (!result)
415
+ return undefined;
416
+ if (!result.before) {
417
+ if (result.end > high)
418
+ return result.end;
419
+ break;
420
+ }
421
+ low = high;
422
+ step *= 2n;
423
+ high = low + step;
424
+ }
425
+ // The output ends after `low` and at or before `high`.
426
+ while (high - low > 1n) {
427
+ const middle = low + (high - low) / 2n;
428
+ const result = await probe(middle);
429
+ if (!result)
430
+ return undefined;
431
+ if (result.before)
432
+ low = middle;
433
+ else if (result.end > middle)
434
+ return result.end;
435
+ else
436
+ high = middle;
437
+ }
438
+ return high;
439
+ }
440
+ //# sourceMappingURL=heartbeat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../../src/core/tasks/heartbeat.ts"],"names":[],"mappings":"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","sourcesContent":["import { taskOutputText } from \"./command-output.js\";\nimport type { NativeEvent, OwnerSnapshot, TaskId, TaskRecord } from \"./contracts.js\";\nimport {\n\tDEFAULT_TASK_HEARTBEAT_MS,\n\tformatTaskHeartbeat,\n\tisValidTaskHeartbeatMs,\n\tsingleLine,\n\tTASK_HEARTBEAT_MESSAGE_TYPE,\n\ttype TaskHeartbeatDetails,\n\ttype TaskHeartbeatMessage,\n\ttype TaskHeartbeatTask,\n} from \"./heartbeat-notice.js\";\nimport {\n\ttype OwnerLease,\n\ttype TaskLease,\n\ttype TaskSubscription,\n\ttype TaskSupervisor,\n\ttaskOwnTranscriptEntries,\n} from \"./supervisor.js\";\n\nexport * from \"./heartbeat-notice.js\";\n\n/** Tasks described in full by one notice; further due tasks are only listed. */\nexport const TASK_HEARTBEAT_DETAIL_LIMIT = 8;\n/** Further due tasks listed by name in one notice; the rest are counted. */\nexport const TASK_HEARTBEAT_LIST_LIMIT = 20;\n/** Boundaries due within this window (capped at a quarter cadence) join the notice that is going out. */\nexport const TASK_HEARTBEAT_COALESCE_MS = 60_000;\n/** While the owner has not read the previous notice, due tasks wait and are rechecked this often. */\nexport const TASK_HEARTBEAT_RECHECK_MS = 30_000;\n/** How often a running shell's output is sampled to date its last output. */\nexport const TASK_HEARTBEAT_OUTPUT_SAMPLE_MS = 30_000;\nconst OUTPUT_TAIL_BYTES = 2048;\nconst OUTPUT_TAIL_LINES = 6;\nconst LINE_CHARS = 160;\nconst TITLE_CHARS = 120;\n/** Longest delay a host timer accepts before it overflows to an immediate fire. */\nconst MAX_TIMER_DELAY_MS = 2_147_483_647;\n\n/** Where an owner's heartbeats go. The host binds its own chat; nothing here is model-provided. */\nexport interface TaskHeartbeatDelivery {\n\t/** Cadence for tasks launched without their own `heartbeatMs`; `0` disables. */\n\tdefaultIntervalMs(): number;\n\t/** Whether a heartbeat this owner already sent is still waiting, unread, in its chat. */\n\thasUnreadHeartbeat(): boolean;\n\tdeliver(message: TaskHeartbeatMessage): Promise<void>;\n}\n\n/** The owner's default cadence, or the built-in one when its setting cannot be read or is out of range. */\nexport function defaultTaskHeartbeatMs(delivery: Pick<TaskHeartbeatDelivery, \"defaultIntervalMs\">): number {\n\ttry {\n\t\tconst configured = delivery.defaultIntervalMs();\n\t\treturn isValidTaskHeartbeatMs(configured) ? configured : DEFAULT_TASK_HEARTBEAT_MS;\n\t} catch {\n\t\treturn DEFAULT_TASK_HEARTBEAT_MS;\n\t}\n}\n\nexport interface TaskHeartbeatClock {\n\tnow(): number;\n\tsetTimeout(run: () => void, delayMs: number): object;\n\tclearTimeout(handle: object): void;\n}\n\nconst systemClock: TaskHeartbeatClock = {\n\tnow: () => Date.now(),\n\tsetTimeout: (run, delayMs) => {\n\t\tconst handle = setTimeout(run, delayMs);\n\t\thandle.unref();\n\t\treturn handle;\n\t},\n\tclearTimeout: (handle) => clearTimeout(handle as ReturnType<typeof setTimeout>),\n};\n\nexport interface TaskHeartbeatMonitorOptions {\n\tsupervisor: TaskSupervisor;\n\towner: OwnerLease;\n\t/** Read on every use, so a replaced session's binding takes over the same owner. */\n\tdelivery: () => TaskHeartbeatDelivery | undefined;\n\tclock?: TaskHeartbeatClock;\n}\n\ntype Tracked = {\n\ttaskId: TaskId;\n\trecord: TaskRecord;\n\t/** First observed running: the anchor of the cadence. */\n\tstartedAt: number;\n\t/** Frozen when the task is first observed; `0` disables. */\n\tintervalMs: number;\n\t/** Next boundary `startedAt + n × intervalMs`; absent when disabled. */\n\tnextAt?: number;\n\tlastActivityAt?: number;\n\tactivityKey: string;\n\t/** Shells: retained output bytes observed so far. */\n\toutputEnd: bigint;\n};\n\nfunction activityKey(task: TaskRecord): string {\n\treturn JSON.stringify([task.currentAction, task.metrics, task.attention, task.model]);\n}\n\n/** Whether the newest message in a child's history is an assistant turn whose tool calls have not returned yet. */\nfunction endsInToolCall(entries: NonNullable<ReturnType<typeof taskOwnTranscriptEntries>>): boolean {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type !== \"message\") continue;\n\t\tconst message = entry.message;\n\t\treturn message.role === \"assistant\" && message.content.some((block) => block.type === \"toolCall\");\n\t}\n\treturn false;\n}\n\n/** First boundary on the `startedAt + n × intervalMs` series strictly after `after`. */\nfunction nextBoundary(startedAt: number, intervalMs: number, after: number): number {\n\tconst n = Math.max(1, Math.floor((after - startedAt) / intervalMs) + 1);\n\tconst boundary = startedAt + n * intervalMs;\n\treturn boundary > after ? boundary : startedAt + (n + 1) * intervalMs;\n}\n\nfunction byBoundary(a: Tracked, b: Tracked): number {\n\tconst left = a.nextAt ?? Number.POSITIVE_INFINITY;\n\tconst right = b.nextAt ?? Number.POSITIVE_INFINITY;\n\tif (left !== right) return left - right;\n\treturn a.taskId < b.taskId ? -1 : a.taskId > b.taskId ? 1 : 0;\n}\n\n/**\n * Periodic \"is this still making progress?\" notices for one task owner's running shells and subagents.\n *\n * It follows the workflow heartbeat rules: boundaries are anchored at the task's start and never at the previous\n * delivery, missed boundaries are skipped rather than replayed, and only one notice per owner is outstanding. Unlike\n * a workflow run, an owner can have many tasks, so tasks due together share one bounded notice, and a task due while\n * the owner has not read the previous notice waits for it rather than losing its turn.\n */\nexport class TaskHeartbeatMonitor {\n\tprivate readonly options: TaskHeartbeatMonitorOptions;\n\tprivate readonly clock: TaskHeartbeatClock;\n\tprivate readonly tracked = new Map<TaskId, Tracked>();\n\tprivate subscription?: TaskSubscription;\n\tprivate timer?: object;\n\t/** The time the current timer wakes for, so an unchanged schedule keeps its timer. */\n\tprivate timerAt?: number;\n\tprivate busy = false;\n\tprivate disposed = false;\n\tprivate recheckAt?: number;\n\tprivate nextSampleAt?: number;\n\n\tconstructor(options: TaskHeartbeatMonitorOptions) {\n\t\tthis.options = options;\n\t\tthis.clock = options.clock ?? systemClock;\n\t}\n\n\t/** Begin watching the owner. Idempotent. */\n\tstart(): void {\n\t\tif (this.subscription || this.disposed) return;\n\t\tconst watched = this.options.supervisor.watchOwnerTasks(this.options.owner);\n\t\tif (!watched.ok) return;\n\t\tthis.subscription = watched.value;\n\t\tthis.subscription.onReconcile = (snapshot, events) => this.reconcile(snapshot, events);\n\t\tthis.reconcile(this.subscription.snapshot, []);\n\t}\n\n\tdispose(): void {\n\t\tif (this.disposed) return;\n\t\tthis.disposed = true;\n\t\tthis.subscription?.dispose();\n\t\tthis.subscription = undefined;\n\t\tthis.tracked.clear();\n\t\tthis.disarm();\n\t}\n\n\tprivate reconcile(snapshot: OwnerSnapshot, events: readonly NativeEvent[]): void {\n\t\tif (this.disposed) return;\n\t\tif (snapshot.state !== \"open\") {\n\t\t\tif (snapshot.state === \"closed\") this.dispose();\n\t\t\telse {\n\t\t\t\tthis.tracked.clear();\n\t\t\t\tthis.disarm();\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tconst at = this.clock.now();\n\t\tconst reported = new Set<TaskId>();\n\t\tfor (const event of events) if (event.payload.kind === \"task-activity\") reported.add(event.payload.ref.taskId);\n\t\tconst running = new Set<TaskId>();\n\t\tfor (const task of snapshot.tasks) {\n\t\t\t// Queued, stopping, paused and finished tasks do not heartbeat.\n\t\t\tif (task.execution.kind !== \"running\") continue;\n\t\t\tconst id = task.ref.taskId;\n\t\t\trunning.add(id);\n\t\t\tconst key = activityKey(task);\n\t\t\tconst entry = this.tracked.get(id);\n\t\t\tif (entry) {\n\t\t\t\tentry.record = task;\n\t\t\t\tif (key !== entry.activityKey || reported.has(id)) {\n\t\t\t\t\tentry.activityKey = key;\n\t\t\t\t\tentry.lastActivityAt = at;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst intervalMs = this.resolveInterval(task);\n\t\t\tthis.tracked.set(id, {\n\t\t\t\ttaskId: id,\n\t\t\t\trecord: task,\n\t\t\t\tstartedAt: at,\n\t\t\t\tintervalMs,\n\t\t\t\t...(intervalMs > 0 ? { nextAt: at + intervalMs } : {}),\n\t\t\t\t...(reported.has(id) ? { lastActivityAt: at } : {}),\n\t\t\t\tactivityKey: key,\n\t\t\t\toutputEnd: 0n,\n\t\t\t});\n\t\t}\n\t\tfor (const id of [...this.tracked.keys()]) if (!running.has(id)) this.tracked.delete(id);\n\t\tif (!this.hasSampledShells()) this.nextSampleAt = undefined;\n\t\telse this.nextSampleAt ??= at + TASK_HEARTBEAT_OUTPUT_SAMPLE_MS;\n\t\tthis.arm();\n\t}\n\n\tprivate resolveInterval(task: TaskRecord): number {\n\t\t// Owners with a heartbeat binding fix each task's cadence on its record at admission.\n\t\tif (task.heartbeatMs !== undefined) return isValidTaskHeartbeatMs(task.heartbeatMs) ? task.heartbeatMs : 0;\n\t\tconst delivery = this.options.delivery();\n\t\treturn delivery ? defaultTaskHeartbeatMs(delivery) : DEFAULT_TASK_HEARTBEAT_MS;\n\t}\n\n\tprivate hasSampledShells(): boolean {\n\t\tfor (const entry of this.tracked.values())\n\t\t\tif (entry.record.kind === \"command\" && entry.intervalMs > 0) return true;\n\t\treturn false;\n\t}\n\n\tprivate disarm(): void {\n\t\tif (this.timer === undefined) return;\n\t\tthis.clock.clearTimeout(this.timer);\n\t\tthis.timer = undefined;\n\t\tthis.timerAt = undefined;\n\t}\n\n\tprivate arm(): void {\n\t\tif (this.disposed || this.busy) {\n\t\t\tthis.disarm();\n\t\t\treturn;\n\t\t}\n\t\t// A blocked owner cannot receive anything before its recheck, however many tasks come due meanwhile.\n\t\tlet wakeAt = this.recheckAt ?? Number.POSITIVE_INFINITY;\n\t\tif (this.recheckAt === undefined)\n\t\t\tfor (const entry of this.tracked.values())\n\t\t\t\tif (entry.nextAt !== undefined && entry.nextAt < wakeAt) wakeAt = entry.nextAt;\n\t\tif (this.nextSampleAt !== undefined && this.nextSampleAt < wakeAt) wakeAt = this.nextSampleAt;\n\t\t// Activity reconciles many times a second; it rarely moves the next wake-up.\n\t\tif (this.timer !== undefined && this.timerAt === wakeAt) return;\n\t\tthis.disarm();\n\t\tif (!Number.isFinite(wakeAt)) return;\n\t\tconst delay = Math.min(Math.max(1, Math.ceil(wakeAt - this.clock.now())), MAX_TIMER_DELAY_MS);\n\t\tthis.timerAt = wakeAt;\n\t\tthis.timer = this.clock.setTimeout(() => {\n\t\t\tthis.timer = undefined;\n\t\t\tthis.timerAt = undefined;\n\t\t\tvoid this.wake();\n\t\t}, delay);\n\t}\n\n\tprivate async wake(): Promise<void> {\n\t\tif (this.disposed || this.busy) return;\n\t\tthis.busy = true;\n\t\ttry {\n\t\t\tconst at = this.clock.now();\n\t\t\tif (this.nextSampleAt !== undefined && this.nextSampleAt <= at) {\n\t\t\t\tawait this.sampleShellOutput(at);\n\t\t\t\tthis.nextSampleAt = this.hasSampledShells() ? at + TASK_HEARTBEAT_OUTPUT_SAMPLE_MS : undefined;\n\t\t\t}\n\t\t\tawait this.beat(at);\n\t\t} catch {\n\t\t\t// A failed check skips this boundary; the next one is already scheduled.\n\t\t} finally {\n\t\t\tthis.busy = false;\n\t\t\tthis.arm();\n\t\t}\n\t}\n\n\tprivate async beat(at: number): Promise<void> {\n\t\tif (this.recheckAt !== undefined && this.recheckAt > at) return;\n\t\tthis.recheckAt = undefined;\n\t\tconst entries = [...this.tracked.values()];\n\t\tif (!entries.some((entry) => entry.nextAt !== undefined && entry.nextAt <= at)) return;\n\t\tconst delivery = this.options.delivery();\n\t\tlet unread = false;\n\t\ttry {\n\t\t\tunread = delivery?.hasUnreadHeartbeat() === true;\n\t\t} catch {\n\t\t\tunread = false;\n\t\t}\n\t\tif (unread) {\n\t\t\t// One outstanding notice per owner: due tasks stay owed and join the next notice instead of stacking.\n\t\t\tthis.recheckAt = at + TASK_HEARTBEAT_RECHECK_MS;\n\t\t\treturn;\n\t\t}\n\t\tconst batch = entries\n\t\t\t.filter(\n\t\t\t\t(entry) =>\n\t\t\t\t\tentry.nextAt !== undefined &&\n\t\t\t\t\tentry.nextAt <= at + Math.min(TASK_HEARTBEAT_COALESCE_MS, entry.intervalMs / 4),\n\t\t\t)\n\t\t\t.sort(byBoundary);\n\t\tfor (const entry of batch)\n\t\t\tentry.nextAt = nextBoundary(entry.startedAt, entry.intervalMs, Math.max(at, entry.nextAt ?? at));\n\t\tif (!delivery) return;\n\t\tconst details = await this.describe(batch, at);\n\t\t// A task that finished while its notice was being prepared is no longer mentioned.\n\t\tconst live = (taskId: string) => this.tracked.has(taskId as TaskId);\n\t\tdetails.tasks = details.tasks.filter((task) => live(task.taskId));\n\t\tdetails.more = details.more.filter((task) => live(task.taskId));\n\t\tdetails.moreCount = batch.slice(TASK_HEARTBEAT_DETAIL_LIMIT).filter((entry) => live(entry.taskId)).length;\n\t\tif (details.tasks.length === 0 || this.disposed) return;\n\t\tawait delivery.deliver({\n\t\t\tcustomType: TASK_HEARTBEAT_MESSAGE_TYPE,\n\t\t\tcontent: formatTaskHeartbeat(details),\n\t\t\tdisplay: true,\n\t\t\tdetails,\n\t\t});\n\t}\n\n\tprivate async describe(batch: readonly Tracked[], at: number): Promise<TaskHeartbeatDetails> {\n\t\tconst detailed = batch.slice(0, TASK_HEARTBEAT_DETAIL_LIMIT);\n\t\tconst rest = batch.slice(TASK_HEARTBEAT_DETAIL_LIMIT);\n\t\tconst tasks: TaskHeartbeatTask[] = [];\n\t\tfor (const entry of detailed) tasks.push(await this.describeTask(entry, at));\n\t\treturn {\n\t\t\tscheduledAt: at,\n\t\t\ttasks,\n\t\t\tmore: rest.slice(0, TASK_HEARTBEAT_LIST_LIMIT).map((entry) => ({\n\t\t\t\ttaskId: entry.taskId,\n\t\t\t\tkind: entry.record.kind,\n\t\t\t\ttitle: singleLine(entry.record.title, TITLE_CHARS),\n\t\t\t})),\n\t\t\tmoreCount: rest.length,\n\t\t};\n\t}\n\n\tprivate async describeTask(entry: Tracked, at: number): Promise<TaskHeartbeatTask> {\n\t\tconst task = entry.record;\n\t\tconst lease = this.lease(entry.taskId);\n\t\tconst described: TaskHeartbeatTask = {\n\t\t\ttaskId: entry.taskId,\n\t\t\tkind: task.kind,\n\t\t\ttitle: singleLine(task.title, TITLE_CHARS),\n\t\t\t...(task.agentName === undefined ? {} : { agentName: singleLine(task.agentName, TITLE_CHARS) }),\n\t\t\t...(task.kind === \"agent\" && task.model !== undefined ? { model: task.model } : {}),\n\t\t\telapsedMs: Math.max(0, at - entry.startedAt),\n\t\t\tintervalMs: entry.intervalMs,\n\t\t};\n\t\tif (task.kind === \"command\" && lease) {\n\t\t\tconst end = await this.observeOutput(entry, lease, at);\n\t\t\tif (end !== undefined) described.output = { bytes: Number(end), tail: await this.outputTail(lease, end) };\n\t\t}\n\t\tif (entry.lastActivityAt !== undefined) described.lastActivityAgoMs = Math.max(0, at - entry.lastActivityAt);\n\t\tif (task.kind === \"agent\") {\n\t\t\tconst entries = lease ? taskOwnTranscriptEntries(lease) : undefined;\n\t\t\tif (task.currentAction)\n\t\t\t\tdescribed.currentAction = {\n\t\t\t\t\ttool: singleLine(task.currentAction.tool, 60),\n\t\t\t\t\ttext: singleLine(task.currentAction.text, LINE_CHARS),\n\t\t\t\t\t// The record keeps the last reported action after its tool returns. The child's own history says\n\t\t\t\t\t// whether a call is still outstanding: its last message is an assistant turn that called tools.\n\t\t\t\t\trunning: entries !== undefined && endsInToolCall(entries),\n\t\t\t\t};\n\t\t\tif (task.metrics?.toolCount !== undefined) described.toolCount = task.metrics.toolCount;\n\t\t\tif (task.metrics?.tokenCount !== undefined) described.tokenCount = task.metrics.tokenCount;\n\t\t\tif (entries)\n\t\t\t\tdescribed.turnCount = entries.filter(\n\t\t\t\t\t(item) => item.type === \"message\" && item.message.role === \"assistant\",\n\t\t\t\t).length;\n\t\t}\n\t\tif (task.attention.kind === \"input-needed\")\n\t\t\tdescribed.attention = `waiting for input: ${singleLine(task.attention.prompt, LINE_CHARS)}`;\n\t\telse if (task.attention.kind === \"no-recent-activity\") described.attention = \"no recent activity\";\n\t\treturn described;\n\t}\n\n\tprivate lease(taskId: TaskId): TaskLease | undefined {\n\t\tconst found = this.options.supervisor.lookupTask(this.options.owner, taskId);\n\t\treturn found.ok ? found.value : undefined;\n\t}\n\n\tprivate async sampleShellOutput(at: number): Promise<void> {\n\t\tfor (const entry of [...this.tracked.values()]) {\n\t\t\tif (entry.record.kind !== \"command\" || entry.intervalMs === 0) continue;\n\t\t\tconst lease = this.lease(entry.taskId);\n\t\t\tif (lease) await this.observeOutput(entry, lease, at);\n\t\t}\n\t}\n\n\t/** Current retained output size; growth since the last look dates the shell's last output. */\n\tprivate async observeOutput(entry: Tracked, lease: TaskLease, at: number): Promise<bigint | undefined> {\n\t\tconst end = await findOutputEnd(this.options.supervisor, lease, entry.outputEnd);\n\t\tif (end === undefined) return undefined;\n\t\tif (end > entry.outputEnd) {\n\t\t\tentry.outputEnd = end;\n\t\t\tentry.lastActivityAt = at;\n\t\t}\n\t\treturn end;\n\t}\n\n\tprivate async outputTail(lease: TaskLease, end: bigint): Promise<string[]> {\n\t\tif (end === 0n) return [];\n\t\tconst start = end > BigInt(OUTPUT_TAIL_BYTES) ? end - BigInt(OUTPUT_TAIL_BYTES) : 0n;\n\t\tconst page = await this.options.supervisor.readTaskOutput(lease, {\n\t\t\tstart: String(start),\n\t\t\tmaximumBytes: OUTPUT_TAIL_BYTES,\n\t\t});\n\t\tif (!page.ok) return [];\n\t\tconst lines = taskOutputText(page.value).split(\"\\n\");\n\t\t// The window can open mid-line; that fragment is not a line of output.\n\t\tif (start > 0n) lines.shift();\n\t\treturn lines\n\t\t\t.map((line) => {\n\t\t\t\t// A CRLF ending is not a redraw; a carriage return inside a line redraws it, so its last state counts.\n\t\t\t\tconst ended = line.replace(/\\r+$/, \"\");\n\t\t\t\treturn singleLine(ended.slice(ended.lastIndexOf(\"\\r\") + 1), LINE_CHARS).trimEnd();\n\t\t\t})\n\t\t\t.filter((line) => line.trim().length > 0)\n\t\t\t.slice(-OUTPUT_TAIL_LINES);\n\t}\n}\n\n/**\n * Retained output size of a running shell, found with one-byte reads: a read past the end returns nothing. Gallops\n * from the last known size, then bisects, so a large burst of output costs a few dozen tiny reads, not a full scan.\n */\nasync function findOutputEnd(supervisor: TaskSupervisor, lease: TaskLease, from: bigint): Promise<bigint | undefined> {\n\tconst probe = async (offset: bigint): Promise<{ before: boolean; end: bigint } | undefined> => {\n\t\tconst page = await supervisor.readTaskOutput(lease, { start: String(offset), maximumBytes: 1 });\n\t\tif (!page.ok) return undefined;\n\t\tif (page.value.nextOffset !== undefined) return { before: true, end: BigInt(page.value.nextOffset) };\n\t\tlet end = offset;\n\t\tfor (const chunk of page.value.chunks) if (BigInt(chunk.offsets.end) > end) end = BigInt(chunk.offsets.end);\n\t\tfor (const range of page.value.omittedRanges) if (BigInt(range.end) > end) end = BigInt(range.end);\n\t\t// No byte beyond this page: the output ends at its last byte, or at or before `offset` when it is empty.\n\t\treturn { before: end > offset, end };\n\t};\n\tlet low = from;\n\tconst first = await probe(low);\n\tif (!first) return undefined;\n\tif (!first.before) return first.end > from ? first.end : from;\n\tlet step = 65_536n;\n\tlet high = low + step;\n\tfor (;;) {\n\t\tconst result = await probe(high);\n\t\tif (!result) return undefined;\n\t\tif (!result.before) {\n\t\t\tif (result.end > high) return result.end;\n\t\t\tbreak;\n\t\t}\n\t\tlow = high;\n\t\tstep *= 2n;\n\t\thigh = low + step;\n\t}\n\t// The output ends after `low` and at or before `high`.\n\twhile (high - low > 1n) {\n\t\tconst middle = low + (high - low) / 2n;\n\t\tconst result = await probe(middle);\n\t\tif (!result) return undefined;\n\t\tif (result.before) low = middle;\n\t\telse if (result.end > middle) return result.end;\n\t\telse high = middle;\n\t}\n\treturn high;\n}\n"]}
@@ -67,6 +67,8 @@ export type TrustedTaskHost = {
67
67
  authorizeLaunch(intent: C.AgentIntent): void;
68
68
  resourceAdmission?: import("../sdk-types.ts").ResourceAdmission;
69
69
  onTaskSettled?(ref: C.NativeTaskRef, receipt: C.SettlementReceipt): void;
70
+ /** Heartbeat cadence for a launch that names none, fixed on its record at admission; omitted, none is recorded. */
71
+ defaultHeartbeatMs?(): number | undefined;
70
72
  createRunner(context: FakeRunnerContext, intent: C.AgentIntent): FakeExecution;
71
73
  };
72
74
  /** Reads only history bound by the admitted runner, never a caller-selected session. */
@@ -1 +1 @@
1
- {"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/supervisor.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"supervisor.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/supervisor.ts"],"names":[],"mappings":"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"}
@@ -197,10 +197,26 @@ function observation(value) {
197
197
  // Native records own lifecycle and mutable execution metadata. Routing provenance is
198
198
  // immutable host metadata, retained for the same environment lifetime as task records.
199
199
  const routerSelections = new Map();
200
+ // Launch heartbeat cadences, keyed by owner and launch operation rather than task id: a command's
201
+ // record can be observed before its native start resolves, and it must already carry its cadence.
202
+ const launchHeartbeats = new Map();
203
+ function launchKey(ownerId, operation) {
204
+ return `${ownerId}\0${operation}`;
205
+ }
206
+ /** Record a launch's cadence before native admission; returns the key to forget if admission fails. */
207
+ function rememberLaunchHeartbeat(ownerId, operation, heartbeatMs) {
208
+ const key = launchKey(ownerId, operation);
209
+ // A replayed operation keeps the cadence of the launch that admitted it.
210
+ if (heartbeatMs === undefined || launchHeartbeats.has(key))
211
+ return undefined;
212
+ launchHeartbeats.set(key, heartbeatMs);
213
+ return key;
214
+ }
200
215
  function record(value) {
201
216
  if (value.kind !== "agent" && value.kind !== "command")
202
217
  throw new Error(`Invalid native task kind: ${value.kind}`);
203
218
  const routerSelection = routerSelections.get(value.ref.taskId);
219
+ const heartbeatMs = launchHeartbeats.get(launchKey(value.ref.ownerId, value.launchOperationId));
204
220
  return {
205
221
  ref: reference(value.ref),
206
222
  launchOperationId: value.launchOperationId,
@@ -213,6 +229,7 @@ function record(value) {
213
229
  ...(value.model === undefined ? {} : { model: value.model }),
214
230
  ...(value.thinking === undefined ? {} : { thinking: value.thinking }),
215
231
  ...(routerSelection ? { routerSelection } : {}),
232
+ ...(heartbeatMs === undefined ? {} : { heartbeatMs }),
216
233
  execution: execution(value.execution),
217
234
  observation: observation(value.observation),
218
235
  ...(value.wasBackground === undefined ? {} : { wasBackground: value.wasBackground }),
@@ -580,6 +597,7 @@ export class TaskSupervisor {
580
597
  const owner = new OwnerCapability();
581
598
  Object.freeze(owner);
582
599
  const ownerState = {
600
+ id,
583
601
  native: lease,
584
602
  host: state,
585
603
  tasks: new Map(),
@@ -701,9 +719,11 @@ export class TaskSupervisor {
701
719
  let release;
702
720
  try {
703
721
  release = await (currentResourceAdmission() ?? state.host.binding.resourceAdmission)?.acquire("process", signal ? AbortSignal.any([signal, state.closing.signal]) : state.closing.signal);
722
+ const { heartbeatMs, ...nativeIntent } = intent;
723
+ const heartbeatKey = rememberLaunchHeartbeat(state.id, operation, heartbeatMs ?? state.host.binding.defaultHeartbeatMs?.());
704
724
  let started;
705
725
  try {
706
- started = await this.#native.startCommandTask(state.native, intent, operation);
726
+ started = await this.#native.startCommandTask(state.native, nativeIntent, operation);
707
727
  }
708
728
  catch (error) {
709
729
  release = undefined;
@@ -716,8 +736,11 @@ export class TaskSupervisor {
716
736
  throw new Error(`Command cleanup unconfirmed; process permit retained: ${started.error.code}: ${started.error.message}`);
717
737
  }
718
738
  const admitted = mapped(started, (lease) => lease, startErrors);
719
- if (!admitted.ok)
739
+ if (!admitted.ok) {
740
+ if (heartbeatKey !== undefined)
741
+ launchHeartbeats.delete(heartbeatKey);
720
742
  return admitted;
743
+ }
721
744
  const ref = this.#native.taskReference(admitted.value);
722
745
  if (!ref.ok)
723
746
  throw new Error(ref.error.message);
@@ -808,9 +831,14 @@ export class TaskSupervisor {
808
831
  async startAgentTask(owner, intent, operation, schedule) {
809
832
  const state = this.#owner(owner);
810
833
  state.host.binding.authorizeLaunch(intent);
811
- const admitted = mapped(this.#native.startAgentTask(state.native, intent, operation), (lease) => lease, startErrors);
812
- if (!admitted.ok)
834
+ const { heartbeatMs, ...nativeIntent } = intent;
835
+ const heartbeatKey = rememberLaunchHeartbeat(state.id, operation, heartbeatMs ?? state.host.binding.defaultHeartbeatMs?.());
836
+ const admitted = mapped(this.#native.startAgentTask(state.native, nativeIntent, operation), (lease) => lease, startErrors);
837
+ if (!admitted.ok) {
838
+ if (heartbeatKey !== undefined)
839
+ launchHeartbeats.delete(heartbeatKey);
813
840
  return admitted;
841
+ }
814
842
  const ref = this.#native.taskReference(admitted.value);
815
843
  if (!ref.ok)
816
844
  throw new Error(ref.error.message);