@astralyn/pi 1.4.9 → 1.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +54 -0
- package/dist/bundle/chunks/{chunk-3PKXUKTB.js → chunk-6GTUUUCJ.js} +123 -123
- package/dist/bundle/chunks/{chunk-BAGHIP5J.js → chunk-MF3T3ETJ.js} +3 -3
- package/dist/bundle/chunks/{chunk-F66AY3WR.js → chunk-UCH27AVQ.js} +1 -1
- package/dist/bundle/chunks/{execute-P22VMM2H.js → execute-FQKRO4XJ.js} +1 -1
- package/dist/bundle/chunks/{virtual-modules-VKMBQTR2.js → virtual-modules-6IJ6V2CG.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/core/agent-session.d.ts +34 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +99 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/isolated-session.d.ts +7 -2
- package/dist/core/isolated-session.d.ts.map +1 -1
- package/dist/core/isolated-session.js +7 -3
- package/dist/core/isolated-session.js.map +1 -1
- package/dist/core/session-manager.d.ts +17 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +29 -0
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/tasks/delivery.d.ts +42 -7
- package/dist/core/tasks/delivery.d.ts.map +1 -1
- package/dist/core/tasks/delivery.js +129 -15
- package/dist/core/tasks/delivery.js.map +1 -1
- package/dist/core/tasks/execution.d.ts +27 -14
- package/dist/core/tasks/execution.d.ts.map +1 -1
- package/dist/core/tasks/execution.js +90 -86
- package/dist/core/tasks/execution.js.map +1 -1
- package/dist/core/tasks/limits.d.ts +13 -1
- package/dist/core/tasks/limits.d.ts.map +1 -1
- package/dist/core/tasks/limits.js +14 -1
- package/dist/core/tasks/limits.js.map +1 -1
- package/dist/core/tasks/output.d.ts +9 -1
- package/dist/core/tasks/output.d.ts.map +1 -1
- package/dist/core/tasks/output.js +23 -10
- package/dist/core/tasks/output.js.map +1 -1
- package/dist/core/tasks/presentation.d.ts +1 -1
- package/dist/core/tasks/presentation.d.ts.map +1 -1
- package/dist/core/tasks/presentation.js +6 -4
- package/dist/core/tasks/presentation.js.map +1 -1
- package/dist/core/tasks/record.d.ts +41 -29
- package/dist/core/tasks/record.d.ts.map +1 -1
- package/dist/core/tasks/record.js +82 -37
- package/dist/core/tasks/record.js.map +1 -1
- package/dist/core/tasks/reminder.js +2 -2
- package/dist/core/tasks/reminder.js.map +1 -1
- package/dist/core/tasks/runtime.d.ts +17 -14
- package/dist/core/tasks/runtime.d.ts.map +1 -1
- package/dist/core/tasks/runtime.js +68 -116
- package/dist/core/tasks/runtime.js.map +1 -1
- package/dist/core/tasks/scheduler.d.ts +3 -1
- package/dist/core/tasks/scheduler.d.ts.map +1 -1
- package/dist/core/tasks/scheduler.js +16 -12
- package/dist/core/tasks/scheduler.js.map +1 -1
- package/dist/core/tasks/session.d.ts +24 -3
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +73 -9
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tasks/store.d.ts +17 -4
- package/dist/core/tasks/store.d.ts.map +1 -1
- package/dist/core/tasks/store.js +45 -48
- package/dist/core/tasks/store.js.map +1 -1
- package/dist/core/tasks/types.d.ts +72 -29
- package/dist/core/tasks/types.d.ts.map +1 -1
- package/dist/core/tasks/types.js +7 -0
- package/dist/core/tasks/types.js.map +1 -1
- package/dist/core/tasks/wait.d.ts +19 -0
- package/dist/core/tasks/wait.d.ts.map +1 -0
- package/dist/core/tasks/wait.js +45 -0
- package/dist/core/tasks/wait.js.map +1 -0
- package/dist/core/tools/shell-execution.d.ts.map +1 -1
- package/dist/core/tools/shell-execution.js +2 -1
- package/dist/core/tools/shell-execution.js.map +1 -1
- package/dist/core/tools/shell-tool.d.ts.map +1 -1
- package/dist/core/tools/shell-tool.js +20 -13
- package/dist/core/tools/shell-tool.js.map +1 -1
- package/dist/extensions/agent/activity-lines.d.ts +10 -0
- package/dist/extensions/agent/activity-lines.d.ts.map +1 -0
- package/dist/extensions/agent/activity-lines.js +76 -0
- package/dist/extensions/agent/activity-lines.js.map +1 -0
- package/dist/extensions/agent/activity.d.ts +25 -4
- package/dist/extensions/agent/activity.d.ts.map +1 -1
- package/dist/extensions/agent/activity.js +76 -21
- package/dist/extensions/agent/activity.js.map +1 -1
- package/dist/extensions/agent/artifacts.d.ts +15 -0
- package/dist/extensions/agent/artifacts.d.ts.map +1 -0
- package/dist/extensions/agent/artifacts.js +44 -0
- package/dist/extensions/agent/artifacts.js.map +1 -0
- package/dist/extensions/agent/progress.d.ts +30 -4
- package/dist/extensions/agent/progress.d.ts.map +1 -1
- package/dist/extensions/agent/progress.js +84 -11
- package/dist/extensions/agent/progress.js.map +1 -1
- package/dist/extensions/agent/render.d.ts.map +1 -1
- package/dist/extensions/agent/render.js +8 -24
- package/dist/extensions/agent/render.js.map +1 -1
- package/dist/extensions/agent/report.d.ts +11 -3
- package/dist/extensions/agent/report.d.ts.map +1 -1
- package/dist/extensions/agent/report.js +32 -7
- package/dist/extensions/agent/report.js.map +1 -1
- package/dist/extensions/agent/tool.d.ts.map +1 -1
- package/dist/extensions/agent/tool.js +20 -5
- package/dist/extensions/agent/tool.js.map +1 -1
- package/dist/extensions/agent/types.d.ts +2 -0
- package/dist/extensions/agent/types.d.ts.map +1 -1
- package/dist/extensions/agent/types.js.map +1 -1
- package/dist/extensions/agent/worker.d.ts +7 -0
- package/dist/extensions/agent/worker.d.ts.map +1 -1
- package/dist/extensions/agent/worker.js +9 -3
- package/dist/extensions/agent/worker.js.map +1 -1
- package/dist/extensions/search/index.d.ts.map +1 -1
- package/dist/extensions/search/index.js +6 -7
- package/dist/extensions/search/index.js.map +1 -1
- package/dist/extensions/tasks/tool/actions.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/actions.js +15 -11
- package/dist/extensions/tasks/tool/actions.js.map +1 -1
- package/dist/extensions/tasks/tool/schema.d.ts +1 -1
- package/dist/extensions/tasks/tool/schema.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/schema.js +5 -5
- package/dist/extensions/tasks/tool/schema.js.map +1 -1
- package/dist/extensions/tasks/tool/types.d.ts +2 -0
- package/dist/extensions/tasks/tool/types.d.ts.map +1 -1
- package/dist/extensions/tasks/tool/types.js.map +1 -1
- package/dist/extensions/tasks/tool.d.ts.map +1 -1
- package/dist/extensions/tasks/tool.js +3 -2
- package/dist/extensions/tasks/tool.js.map +1 -1
- package/dist/extensions/tasks/ui/completion-render.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/completion-render.js +2 -2
- package/dist/extensions/tasks/ui/completion-render.js.map +1 -1
- package/dist/extensions/tasks/ui/footer.d.ts +37 -0
- package/dist/extensions/tasks/ui/footer.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/footer.js +129 -0
- package/dist/extensions/tasks/ui/footer.js.map +1 -0
- package/dist/extensions/tasks/ui/frame.d.ts +36 -0
- package/dist/extensions/tasks/ui/frame.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/frame.js +33 -0
- package/dist/extensions/tasks/ui/frame.js.map +1 -0
- package/dist/extensions/tasks/ui/help.d.ts +6 -0
- package/dist/extensions/tasks/ui/help.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/help.js +53 -0
- package/dist/extensions/tasks/ui/help.js.map +1 -0
- package/dist/extensions/tasks/ui/inspector.d.ts +4 -3
- package/dist/extensions/tasks/ui/inspector.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/inspector.js +25 -6
- package/dist/extensions/tasks/ui/inspector.js.map +1 -1
- package/dist/extensions/tasks/ui/layout.d.ts +15 -18
- package/dist/extensions/tasks/ui/layout.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/layout.js +162 -255
- package/dist/extensions/tasks/ui/layout.js.map +1 -1
- package/dist/extensions/tasks/ui/list.d.ts +3 -1
- package/dist/extensions/tasks/ui/list.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/list.js +19 -14
- package/dist/extensions/tasks/ui/list.js.map +1 -1
- package/dist/extensions/tasks/ui/manager.d.ts +17 -5
- package/dist/extensions/tasks/ui/manager.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/manager.js +147 -90
- package/dist/extensions/tasks/ui/manager.js.map +1 -1
- package/dist/extensions/tasks/ui/model.d.ts +32 -5
- package/dist/extensions/tasks/ui/model.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/model.js +7 -7
- package/dist/extensions/tasks/ui/model.js.map +1 -1
- package/dist/extensions/tasks/ui/panes.d.ts +40 -0
- package/dist/extensions/tasks/ui/panes.d.ts.map +1 -0
- package/dist/extensions/tasks/ui/panes.js +144 -0
- package/dist/extensions/tasks/ui/panes.js.map +1 -0
- package/dist/extensions/tasks/ui/render.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/render.js +11 -7
- package/dist/extensions/tasks/ui/render.js.map +1 -1
- package/dist/extensions/tasks/ui/viewport.d.ts +12 -4
- package/dist/extensions/tasks/ui/viewport.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/viewport.js +23 -7
- package/dist/extensions/tasks/ui/viewport.js.map +1 -1
- package/dist/extensions/tasks/ui/views.d.ts +12 -6
- package/dist/extensions/tasks/ui/views.d.ts.map +1 -1
- package/dist/extensions/tasks/ui/views.js +39 -32
- package/dist/extensions/tasks/ui/views.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +11 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +43 -17
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +37 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +11 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +48 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +2 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/docs/bundled/extensions/agent.md +39 -7
- package/docs/bundled/tasks.md +25 -21
- package/docs/extensions.md +14 -10
- package/docs/json.md +3 -0
- package/docs/rpc.md +14 -0
- package/docs/sdk.md +11 -1
- package/docs/session-format.md +10 -4
- package/docs/sessions.md +1 -1
- package/docs/usage.md +2 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { finiteLimit } from "../../utils/number.js";
|
|
3
3
|
import { Execution } from "./execution.js";
|
|
4
|
-
import {
|
|
4
|
+
import { defaultReadMode, TASKS_WAIT_DEFAULT_MS } from "./limits.js";
|
|
5
5
|
import { boundFacts, boundInput, boundText, errorText, readOutputSlice, sliceText, TASK_LABEL_BYTES, TASK_TITLE_BYTES, } from "./output.js";
|
|
6
6
|
import { TaskRecord } from "./record.js";
|
|
7
7
|
import { TaskScheduler } from "./scheduler.js";
|
|
8
8
|
import { TaskStore } from "./store.js";
|
|
9
|
-
import { TASK_BACKGROUND_REJECTION, TASK_KIND_PATTERN, TaskLookupError, } from "./types.js";
|
|
9
|
+
import { TASK_BACKGROUND_REJECTION, TASK_KIND_PATTERN, TASK_MANAGEMENT_REJECTION, TaskLookupError, } from "./types.js";
|
|
10
|
+
import { waitForFirst } from "./wait.js";
|
|
10
11
|
/** Session-local supervision. Executors own their processes, items and output files. */
|
|
11
12
|
export class TaskRuntime {
|
|
12
13
|
constructor(options = {}) {
|
|
13
14
|
this.executions = new Map();
|
|
14
15
|
this.scheduler = new TaskScheduler();
|
|
15
16
|
this.listeners = new Set();
|
|
17
|
+
this.closing = new AbortController();
|
|
16
18
|
this._closed = false;
|
|
17
19
|
this.options = options;
|
|
18
20
|
this.configuredEnabled = options.enabled ?? false;
|
|
@@ -59,12 +61,24 @@ export class TaskRuntime {
|
|
|
59
61
|
this.configuredEnabled = enabled;
|
|
60
62
|
this.emit();
|
|
61
63
|
}
|
|
62
|
-
/**
|
|
64
|
+
/** Tell subscribers that something the runtime reads from its host changed, such as `canManageBackground`. */
|
|
65
|
+
refresh() {
|
|
66
|
+
this.emit();
|
|
67
|
+
}
|
|
68
|
+
/** Whether new work may move to or start in the background: enabled, and the host can manage it. */
|
|
69
|
+
get admitsBackground() {
|
|
70
|
+
return this.enabled && (this.options.canManageBackground?.() ?? true);
|
|
71
|
+
}
|
|
72
|
+
/** Handed-off work that has not settled: the waitAny cohort and the statusline count. */
|
|
63
73
|
activeBackground() {
|
|
64
74
|
return this.store.unsettled().filter((record) => record.task.mode === "background");
|
|
65
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* Foreground work is bounded by its caller; only background work holds a slot, including work
|
|
78
|
+
* whose caller is still waiting for the executor to accept (a detaching task).
|
|
79
|
+
*/
|
|
66
80
|
backgroundActive() {
|
|
67
|
-
return this.
|
|
81
|
+
return [...this.executions.values()].filter((execution) => execution.holdsBackgroundSlot).length;
|
|
68
82
|
}
|
|
69
83
|
limitError() {
|
|
70
84
|
return new Error(`Background task limit reached (${this.maxBackground}); stop or wait for a background task, or run in the foreground.`);
|
|
@@ -78,10 +92,12 @@ export class TaskRuntime {
|
|
|
78
92
|
if (execution.background) {
|
|
79
93
|
if (!this.enabled)
|
|
80
94
|
throw new Error("Background execution is not available in this host");
|
|
95
|
+
if (!this.admitsBackground)
|
|
96
|
+
throw new Error(TASK_MANAGEMENT_REJECTION);
|
|
81
97
|
if (this.backgroundActive() >= this.maxBackground)
|
|
82
98
|
throw this.limitError();
|
|
83
99
|
if (this.store.retainedCount() >= this.maxRetained) {
|
|
84
|
-
throw new Error("Task history retention limit reached; deliver pending notifications or release
|
|
100
|
+
throw new Error("Task history retention limit reached; deliver pending notifications or release task pins and delivery leases");
|
|
85
101
|
}
|
|
86
102
|
}
|
|
87
103
|
if (execution.signal?.aborted)
|
|
@@ -104,18 +120,18 @@ export class TaskRuntime {
|
|
|
104
120
|
...(execution.facts?.length ? { facts: boundFacts(execution.facts) } : {}),
|
|
105
121
|
toolCallId: boundText(execution.toolCallId, 512),
|
|
106
122
|
anchorId,
|
|
107
|
-
mode:
|
|
123
|
+
mode: "foreground",
|
|
108
124
|
status: "queued",
|
|
109
125
|
startedAt: Date.now(),
|
|
110
126
|
};
|
|
111
127
|
const record = new TaskRecord(task);
|
|
128
|
+
record.setPresenter(execution.present);
|
|
112
129
|
const active = new Execution(this.host, record, execution);
|
|
113
130
|
this.store.add(record);
|
|
114
131
|
this.executions.set(task.id, active);
|
|
115
132
|
this.scheduler.schedule(active);
|
|
116
133
|
// Queued background work returns at once; started work hands off after its own accept().
|
|
117
|
-
|
|
118
|
-
active.handoff();
|
|
134
|
+
active.handOffIfQueued();
|
|
119
135
|
this.emit();
|
|
120
136
|
return active.caller;
|
|
121
137
|
}
|
|
@@ -123,7 +139,7 @@ export class TaskRuntime {
|
|
|
123
139
|
return this.executions.get(record.task.id)?.detachable ?? false;
|
|
124
140
|
}
|
|
125
141
|
detachForeground() {
|
|
126
|
-
if (!this.
|
|
142
|
+
if (!this.admitsBackground)
|
|
127
143
|
return 0;
|
|
128
144
|
const eligible = [...this.executions.values()]
|
|
129
145
|
.filter((execution) => execution.detachable)
|
|
@@ -133,30 +149,29 @@ export class TaskRuntime {
|
|
|
133
149
|
const free = this.maxBackground - this.backgroundActive();
|
|
134
150
|
if (free <= 0)
|
|
135
151
|
throw this.limitError();
|
|
136
|
-
|
|
137
|
-
for (const execution of executions)
|
|
138
|
-
execution.requestDetach();
|
|
139
|
-
for (const execution of executions)
|
|
140
|
-
execution.completeDetach();
|
|
141
|
-
this.emit();
|
|
142
|
-
return executions.length;
|
|
152
|
+
return this.detachAll(eligible.slice(0, free));
|
|
143
153
|
}
|
|
144
154
|
canDetach(id) {
|
|
145
155
|
const record = this.lookup(id);
|
|
146
|
-
return this.
|
|
156
|
+
return this.admitsBackground && this.backgroundActive() < this.maxBackground && this.detachable(record);
|
|
147
157
|
}
|
|
148
158
|
detach(id) {
|
|
149
159
|
const record = this.lookup(id);
|
|
150
|
-
if (!this.
|
|
160
|
+
if (!this.admitsBackground || !this.detachable(record))
|
|
151
161
|
return false;
|
|
152
162
|
if (this.backgroundActive() >= this.maxBackground)
|
|
153
163
|
throw this.limitError();
|
|
154
|
-
|
|
155
|
-
execution.requestDetach();
|
|
156
|
-
execution.completeDetach();
|
|
157
|
-
this.emit();
|
|
164
|
+
this.detachAll([this.executions.get(record.task.id)]);
|
|
158
165
|
return true;
|
|
159
166
|
}
|
|
167
|
+
/** Every placement changes before any listener hears about it. */
|
|
168
|
+
detachAll(executions) {
|
|
169
|
+
const notifications = executions.map((execution) => execution.detach());
|
|
170
|
+
for (const notify of notifications)
|
|
171
|
+
notify();
|
|
172
|
+
this.emit();
|
|
173
|
+
return executions.length;
|
|
174
|
+
}
|
|
160
175
|
list() {
|
|
161
176
|
return this.store.visible().map((record) => record.snapshot());
|
|
162
177
|
}
|
|
@@ -178,65 +193,38 @@ export class TaskRuntime {
|
|
|
178
193
|
const release = this.retain(record.task.id);
|
|
179
194
|
try {
|
|
180
195
|
const task = record.snapshot();
|
|
196
|
+
const window = { ...options, mode: options.mode ?? defaultReadMode(task) };
|
|
181
197
|
if (task.outputPath) {
|
|
182
198
|
try {
|
|
183
|
-
return { task, ...(await readOutputSlice(task.outputPath,
|
|
199
|
+
return { task, ...(await readOutputSlice(task.outputPath, window)) };
|
|
184
200
|
}
|
|
185
201
|
catch (error) {
|
|
186
202
|
return {
|
|
187
203
|
task,
|
|
188
204
|
readError: boundText(`Output could not be read: ${errorText(error)}`, 4096),
|
|
189
|
-
...sliceText(this.resultText(task),
|
|
205
|
+
...sliceText(this.resultText(task), window),
|
|
190
206
|
};
|
|
191
207
|
}
|
|
192
208
|
}
|
|
193
|
-
return { task, readError: record.readError, ...sliceText(this.resultText(task),
|
|
209
|
+
return { task, readError: record.readError, ...sliceText(this.resultText(task), window) };
|
|
194
210
|
}
|
|
195
211
|
finally {
|
|
196
212
|
release();
|
|
197
213
|
}
|
|
198
214
|
}
|
|
215
|
+
presentOutput(id, width, theme) {
|
|
216
|
+
let record;
|
|
217
|
+
try {
|
|
218
|
+
record = this.lookup(id);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return undefined;
|
|
222
|
+
}
|
|
223
|
+
return record.present(width, theme);
|
|
224
|
+
}
|
|
199
225
|
resultText(task) {
|
|
200
226
|
return task.result?.text || task.error || "No output yet.";
|
|
201
227
|
}
|
|
202
|
-
/** One event-driven waiter can observe a whole waitAny cohort without per-task timers. */
|
|
203
|
-
waitForRecords(records, timeoutMs, signal, interruptSignal) {
|
|
204
|
-
if (records.some((record) => record.settled) || interruptSignal?.aborted)
|
|
205
|
-
return Promise.resolve();
|
|
206
|
-
return new Promise((resolve, reject) => {
|
|
207
|
-
let finished = false;
|
|
208
|
-
let timer;
|
|
209
|
-
const complete = (aborted = false) => {
|
|
210
|
-
if (finished)
|
|
211
|
-
return;
|
|
212
|
-
finished = true;
|
|
213
|
-
if (timer !== undefined)
|
|
214
|
-
clearTimeout(timer);
|
|
215
|
-
signal?.removeEventListener("abort", abort);
|
|
216
|
-
interruptSignal?.removeEventListener("abort", interrupt);
|
|
217
|
-
for (const record of records)
|
|
218
|
-
record.waiters.delete(wake);
|
|
219
|
-
if (aborted)
|
|
220
|
-
reject(signal?.reason ?? new Error("Wait aborted"));
|
|
221
|
-
else
|
|
222
|
-
resolve();
|
|
223
|
-
this.store.trim();
|
|
224
|
-
this.emit();
|
|
225
|
-
};
|
|
226
|
-
const wake = () => complete();
|
|
227
|
-
const abort = () => complete(true);
|
|
228
|
-
const interrupt = () => complete();
|
|
229
|
-
for (const record of records)
|
|
230
|
-
record.waiters.add(wake);
|
|
231
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
232
|
-
interruptSignal?.addEventListener("abort", interrupt, { once: true });
|
|
233
|
-
timer = setTimeout(wake, boundWaitMs(timeoutMs));
|
|
234
|
-
if (this.closed || interruptSignal?.aborted)
|
|
235
|
-
wake();
|
|
236
|
-
if (signal?.aborted)
|
|
237
|
-
abort();
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
228
|
/**
|
|
241
229
|
* One observation: hold delivery for the observed records, wait, read, then register the
|
|
242
230
|
* receipt with the host, and only then release. Nothing the caller does between those steps
|
|
@@ -246,11 +234,20 @@ export class TaskRuntime {
|
|
|
246
234
|
/** Record to read when none settled; a cohort has none. */
|
|
247
235
|
fallback) {
|
|
248
236
|
const { signal } = options;
|
|
249
|
-
|
|
237
|
+
// Retention pins the records; the host keeps them out of automatic delivery until released.
|
|
238
|
+
const releases = records.map((record) => this.pin(record));
|
|
239
|
+
releases.push(this.options.waits?.hold(records.map((record) => record.task.id)) ?? (() => { }));
|
|
250
240
|
try {
|
|
251
241
|
const start = Date.now();
|
|
252
242
|
const interrupt = this.options.waits?.interruptSignal;
|
|
253
|
-
await
|
|
243
|
+
await waitForFirst({
|
|
244
|
+
hasSettled: () => records.some((record) => record.settled),
|
|
245
|
+
subscribe: (listener) => this.subscribe(listener),
|
|
246
|
+
timeoutMs: options.timeoutMs ?? TASKS_WAIT_DEFAULT_MS,
|
|
247
|
+
signal,
|
|
248
|
+
interrupt,
|
|
249
|
+
closed: this.closing.signal,
|
|
250
|
+
});
|
|
254
251
|
const waitedMs = Date.now() - start;
|
|
255
252
|
const settled = records
|
|
256
253
|
.filter((record) => record.settled)
|
|
@@ -315,62 +312,17 @@ export class TaskRuntime {
|
|
|
315
312
|
this.listeners.delete(listener);
|
|
316
313
|
};
|
|
317
314
|
}
|
|
318
|
-
/**
|
|
319
|
-
* Retention protects snapshots and logs only. Delivery has its own explicit hold.
|
|
320
|
-
*/
|
|
315
|
+
/** Retention protects snapshots and logs only; completion delivery never waits on it. */
|
|
321
316
|
retain(id) {
|
|
322
317
|
return this.pin(this.lookup(id));
|
|
323
318
|
}
|
|
324
319
|
pin(record) {
|
|
325
|
-
record.
|
|
326
|
-
let released = false;
|
|
320
|
+
const release = record.pin();
|
|
327
321
|
return () => {
|
|
328
|
-
|
|
329
|
-
return;
|
|
330
|
-
released = true;
|
|
331
|
-
record.pins--;
|
|
322
|
+
release();
|
|
332
323
|
this.store.trim();
|
|
333
|
-
// Listeners decide whether delivery may proceed; TaskDelivery owns pausing.
|
|
334
|
-
if (!this.closed && record.deliverable)
|
|
335
|
-
this.emit();
|
|
336
324
|
};
|
|
337
325
|
}
|
|
338
|
-
holdDelivery(id) {
|
|
339
|
-
return this.holdRecord(this.lookup(id));
|
|
340
|
-
}
|
|
341
|
-
holdRecord(record) {
|
|
342
|
-
const releasePin = this.pin(record);
|
|
343
|
-
record.deliveryHolds++;
|
|
344
|
-
let released = false;
|
|
345
|
-
return () => {
|
|
346
|
-
if (released)
|
|
347
|
-
return;
|
|
348
|
-
released = true;
|
|
349
|
-
record.deliveryHolds--;
|
|
350
|
-
releasePin();
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
pendingNotifications() {
|
|
354
|
-
if (this.closed)
|
|
355
|
-
return [];
|
|
356
|
-
return this.store.deliverable().map((record) => record.snapshot());
|
|
357
|
-
}
|
|
358
|
-
claimNotification(id) {
|
|
359
|
-
return !this.closed && (this.store.get(id)?.claim() ?? false);
|
|
360
|
-
}
|
|
361
|
-
markDelivered(id) {
|
|
362
|
-
const record = this.store.get(id);
|
|
363
|
-
if (!record)
|
|
364
|
-
return;
|
|
365
|
-
record.acknowledge();
|
|
366
|
-
this.store.trim();
|
|
367
|
-
}
|
|
368
|
-
releaseNotification(id) {
|
|
369
|
-
if (!this.store.get(id)?.unclaim())
|
|
370
|
-
return;
|
|
371
|
-
this.store.trim();
|
|
372
|
-
this.emit();
|
|
373
|
-
}
|
|
374
326
|
close() {
|
|
375
327
|
if (this.closed)
|
|
376
328
|
return;
|
|
@@ -379,9 +331,9 @@ export class TaskRuntime {
|
|
|
379
331
|
for (const record of this.store.all()) {
|
|
380
332
|
this.executions.get(record.task.id)?.releaseParent();
|
|
381
333
|
this.cancel(record);
|
|
382
|
-
for (const waiter of [...record.waiters])
|
|
383
|
-
waiter();
|
|
384
334
|
}
|
|
335
|
+
this.closing.abort();
|
|
336
|
+
this.options.onClosed?.();
|
|
385
337
|
this.store.trim();
|
|
386
338
|
}
|
|
387
339
|
async shutdown(graceMs = 2000) {
|
|
@@ -402,7 +354,7 @@ export class TaskRuntime {
|
|
|
402
354
|
async cancelOutsideBranch(ancestors) {
|
|
403
355
|
const records = this.store.all();
|
|
404
356
|
for (const record of records)
|
|
405
|
-
record.
|
|
357
|
+
record.setVisible(record.task.anchorId === null || ancestors.has(record.task.anchorId));
|
|
406
358
|
const outside = records.filter((record) => !record.visible);
|
|
407
359
|
for (const record of outside)
|
|
408
360
|
this.cancel(record);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/core/tasks/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport { finiteLimit } from \"../../utils/number.ts\";\nimport { Execution, type ExecutionHost } from \"./execution.ts\";\nimport { boundWaitMs, TASKS_WAIT_DEFAULT_MS } from \"./limits.ts\";\nimport {\n\tboundFacts,\n\tboundInput,\n\tboundText,\n\terrorText,\n\treadOutputSlice,\n\tsliceText,\n\tTASK_LABEL_BYTES,\n\tTASK_TITLE_BYTES,\n} from \"./output.ts\";\nimport { TaskRecord } from \"./record.ts\";\nimport { TaskScheduler } from \"./scheduler.ts\";\nimport { TaskStore } from \"./store.ts\";\nimport {\n\tTASK_BACKGROUND_REJECTION,\n\tTASK_KIND_PATTERN,\n\ttype TaskDeliveryLedger,\n\ttype TaskExecution,\n\tTaskLookupError,\n\ttype TaskRead,\n\ttype TaskReadOptions,\n\ttype TaskRuntimeOptions,\n\ttype TaskSnapshot,\n\ttype TasksContext,\n\ttype TaskToolOutcome,\n\ttype TaskWaitAnyOptions,\n\ttype TaskWaitAnyResult,\n\ttype TaskWaitOptions,\n\ttype TaskWaitOutcome,\n\ttype TaskWaitResult,\n} from \"./types.ts\";\n\n/** Session-local supervision. Executors own their processes, items and output files. */\nexport class TaskRuntime implements TasksContext, TaskDeliveryLedger {\n\tprivate readonly store: TaskStore;\n\tprivate readonly executions = new Map<string, Execution<unknown>>();\n\tprivate readonly scheduler = new TaskScheduler();\n\tprivate readonly listeners = new Set<() => void>();\n\tprivate readonly host: ExecutionHost;\n\tprivate readonly maxBackground: number;\n\tprivate readonly maxHistory: number;\n\tprivate readonly maxRetained: number;\n\tprivate readonly options: TaskRuntimeOptions;\n\tprivate configuredEnabled: boolean;\n\tprivate _closed = false;\n\n\tconstructor(options: TaskRuntimeOptions = {}) {\n\t\tthis.options = options;\n\t\tthis.configuredEnabled = options.enabled ?? false;\n\t\tthis.maxBackground = Math.max(1, finiteLimit(options.maxBackground, 8, 128));\n\t\tthis.maxHistory = finiteLimit(options.maxHistory, 32, 1024);\n\t\t// Separate foreground and background histories, plus the protected-record allowance.\n\t\tthis.maxRetained = this.maxBackground + 2 * Math.max(1, this.maxHistory) + this.maxHistory;\n\t\tthis.store = new TaskStore(this.maxHistory, this.maxRetained, () => this.closed, options.onCleanupError);\n\t\tconst runtime = this;\n\t\tthis.host = {\n\t\t\tget closed() {\n\t\t\t\treturn runtime.closed;\n\t\t\t},\n\t\t\temit: () => this.emit(),\n\t\t\tsettle: (task, usage) => this.options.onSettled?.(task, usage),\n\t\t\treleased: (execution) => {\n\t\t\t\tthis.executions.delete(execution.task.id);\n\t\t\t\tthis.scheduler.release(execution);\n\t\t\t\tthis.store.trim();\n\t\t\t\tthis.emit();\n\t\t\t},\n\t\t};\n\t}\n\n\tget closed(): boolean {\n\t\treturn this._closed;\n\t}\n\n\tget session(): TaskRuntimeOptions[\"session\"] {\n\t\treturn this.options.session;\n\t}\n\n\t/**\n\t * Rehydrate terminal snapshots only, newest endedAt in each history (later input wins\n\t * ties). Existing runtime records win ID collisions. No execution, accounting,\n\t * notification, or deletion ownership is restored. Foreground records take their output\n\t * from the branch's tool results. The host supplies the current branch; closed services\n\t * ignore restoration.\n\t */\n\trestoreHistory(\n\t\trecords: readonly unknown[],\n\t\ttoolResults?: ReadonlyMap<string, AgentToolResult<unknown>[\"content\"]>,\n\t): void {\n\t\tthis.store.restoreHistory(records, toolResults);\n\t}\n\n\tget enabled(): boolean {\n\t\treturn this.configuredEnabled && !this.closed && this.options.backgroundAllowed !== false;\n\t}\n\n\tsetEnabled(enabled: boolean): void {\n\t\tthis.configuredEnabled = enabled;\n\t\tthis.emit();\n\t}\n\n\t/** Foreground work is bounded by its caller; only background work, queued or running, holds a slot. */\n\tprivate activeBackground(): TaskRecord[] {\n\t\treturn this.store.unsettled().filter((record) => record.task.mode === \"background\");\n\t}\n\n\tprivate backgroundActive(): number {\n\t\treturn this.activeBackground().length;\n\t}\n\n\tprivate limitError(): Error {\n\t\treturn new Error(\n\t\t\t`Background task limit reached (${this.maxBackground}); stop or wait for a background task, or run in the foreground.`,\n\t\t);\n\t}\n\n\tasync execute<T>(execution: TaskExecution<T>): Promise<TaskToolOutcome<T>> {\n\t\t// Admission and registration happen synchronously, before invoking user code or awaiting anything.\n\t\tif (execution.background && this.options.backgroundAllowed === false) throw new Error(TASK_BACKGROUND_REJECTION);\n\t\tif (this.closed) throw new Error(\"Task service is closed\");\n\t\tif (execution.background) {\n\t\t\tif (!this.enabled) throw new Error(\"Background execution is not available in this host\");\n\t\t\tif (this.backgroundActive() >= this.maxBackground) throw this.limitError();\n\t\t\tif (this.store.retainedCount() >= this.maxRetained) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Task history retention limit reached; deliver pending notifications or release pinned or claimed records\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (execution.signal?.aborted) throw execution.signal.reason ?? new Error(\"Execution aborted\");\n\t\tif (!TASK_KIND_PATTERN.test(execution.kind)) throw new Error(\"Invalid task source\");\n\t\tconst concurrency = execution.concurrency;\n\t\tif (concurrency && (!concurrency.key || !Number.isSafeInteger(concurrency.limit) || concurrency.limit < 1))\n\t\t\tthrow new Error(\"Invalid task concurrency\");\n\t\tconst anchorId = this.options.anchor?.() ?? null;\n\t\tif (anchorId !== null && Buffer.byteLength(anchorId) > 8192) throw new Error(\"Task branch anchor is too large\");\n\t\tconst task: TaskSnapshot = {\n\t\t\tid: `${execution.kind}-${randomUUID()}`,\n\t\t\tkind: execution.kind,\n\t\t\tlabel: boundText(execution.label ?? execution.kind, TASK_LABEL_BYTES),\n\t\t\ttitle: boundText(execution.title, TASK_TITLE_BYTES),\n\t\t\toutput: execution.output ?? \"log\",\n\t\t\t...(execution.input ? { input: boundInput(execution.input) } : {}),\n\t\t\t...(execution.facts?.length ? { facts: boundFacts(execution.facts) } : {}),\n\t\t\ttoolCallId: boundText(execution.toolCallId, 512),\n\t\t\tanchorId,\n\t\t\tmode: execution.background ? \"background\" : \"foreground\",\n\t\t\tstatus: \"queued\",\n\t\t\tstartedAt: Date.now(),\n\t\t};\n\t\tconst record = new TaskRecord(task);\n\t\tconst active = new Execution(this.host, record, execution);\n\t\tthis.store.add(record);\n\t\tthis.executions.set(task.id, active as Execution<unknown>);\n\t\tthis.scheduler.schedule(active);\n\t\t// Queued background work returns at once; started work hands off after its own accept().\n\t\tif (active.queued) active.handoff();\n\t\tthis.emit();\n\t\treturn active.caller;\n\t}\n\n\tprivate detachable(record: TaskRecord): boolean {\n\t\treturn this.executions.get(record.task.id)?.detachable ?? false;\n\t}\n\n\tdetachForeground(): number {\n\t\tif (!this.enabled) return 0;\n\t\tconst eligible = [...this.executions.values()]\n\t\t\t.filter((execution) => execution.detachable)\n\t\t\t.sort((left, right) => left.task.startedAt - right.task.startedAt);\n\t\tif (!eligible.length) return 0;\n\t\tconst free = this.maxBackground - this.backgroundActive();\n\t\tif (free <= 0) throw this.limitError();\n\t\tconst executions = eligible.slice(0, free);\n\t\tfor (const execution of executions) execution.requestDetach();\n\t\tfor (const execution of executions) execution.completeDetach();\n\t\tthis.emit();\n\t\treturn executions.length;\n\t}\n\n\tcanDetach(id: string): boolean {\n\t\tconst record = this.lookup(id);\n\t\treturn this.enabled && this.backgroundActive() < this.maxBackground && this.detachable(record);\n\t}\n\n\tdetach(id: string): boolean {\n\t\tconst record = this.lookup(id);\n\t\tif (!this.enabled || !this.detachable(record)) return false;\n\t\tif (this.backgroundActive() >= this.maxBackground) throw this.limitError();\n\t\tconst execution = this.executions.get(record.task.id)!;\n\t\texecution.requestDetach();\n\t\texecution.completeDetach();\n\t\tthis.emit();\n\t\treturn true;\n\t}\n\n\tlist(): TaskSnapshot[] {\n\t\treturn this.store.visible().map((record) => record.snapshot());\n\t}\n\n\tprivate lookup(id: string): TaskRecord {\n\t\tconst exact = this.store.get(id);\n\t\tif (exact) return exact;\n\t\tconst matches = this.store.match(id);\n\t\tif (!id || matches.length !== 1) {\n\t\t\tthrow new TaskLookupError(\n\t\t\t\tmatches.length > 1 ? \"ambiguous\" : \"unknown\",\n\t\t\t\tmatches.map((record) => record.snapshot()),\n\t\t\t);\n\t\t}\n\t\treturn matches[0]!;\n\t}\n\n\tget(id: string): TaskSnapshot {\n\t\treturn this.lookup(id).snapshot();\n\t}\n\n\tasync read(id: string, options: TaskReadOptions = {}): Promise<TaskRead> {\n\t\tconst record = this.lookup(id);\n\t\tconst release = this.retain(record.task.id);\n\t\ttry {\n\t\t\tconst task = record.snapshot();\n\t\t\tif (task.outputPath) {\n\t\t\t\ttry {\n\t\t\t\t\treturn { task, ...(await readOutputSlice(task.outputPath, options)) };\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttask,\n\t\t\t\t\t\treadError: boundText(`Output could not be read: ${errorText(error)}`, 4096),\n\t\t\t\t\t\t...sliceText(this.resultText(task), options),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { task, readError: record.readError, ...sliceText(this.resultText(task), options) };\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t}\n\n\tprivate resultText(task: TaskSnapshot): string {\n\t\treturn task.result?.text || task.error || \"No output yet.\";\n\t}\n\n\t/** One event-driven waiter can observe a whole waitAny cohort without per-task timers. */\n\tprivate waitForRecords(\n\t\trecords: readonly TaskRecord[],\n\t\ttimeoutMs: number,\n\t\tsignal?: AbortSignal,\n\t\tinterruptSignal?: AbortSignal,\n\t): Promise<void> {\n\t\tif (records.some((record) => record.settled) || interruptSignal?.aborted) return Promise.resolve();\n\t\treturn new Promise<void>((resolve, reject) => {\n\t\t\tlet finished = false;\n\t\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\t\tconst complete = (aborted = false) => {\n\t\t\t\tif (finished) return;\n\t\t\t\tfinished = true;\n\t\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\t\tinterruptSignal?.removeEventListener(\"abort\", interrupt);\n\t\t\t\tfor (const record of records) record.waiters.delete(wake);\n\t\t\t\tif (aborted) reject(signal?.reason ?? new Error(\"Wait aborted\"));\n\t\t\t\telse resolve();\n\t\t\t\tthis.store.trim();\n\t\t\t\tthis.emit();\n\t\t\t};\n\t\t\tconst wake = () => complete();\n\t\t\tconst abort = () => complete(true);\n\t\t\tconst interrupt = () => complete();\n\t\t\tfor (const record of records) record.waiters.add(wake);\n\t\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t\t\tinterruptSignal?.addEventListener(\"abort\", interrupt, { once: true });\n\t\t\ttimer = setTimeout(wake, boundWaitMs(timeoutMs));\n\t\t\tif (this.closed || interruptSignal?.aborted) wake();\n\t\t\tif (signal?.aborted) abort();\n\t\t});\n\t}\n\n\t/**\n\t * One observation: hold delivery for the observed records, wait, read, then register the\n\t * receipt with the host, and only then release. Nothing the caller does between those steps\n\t * can leak a settled result into an automatic notification or lose it.\n\t */\n\tprivate async observe(\n\t\trecords: readonly TaskRecord[],\n\t\toptions: TaskWaitOptions,\n\t\t/** Record to read when none settled; a cohort has none. */\n\t\tfallback?: TaskRecord,\n\t): Promise<{\n\t\toutcome: TaskWaitOutcome;\n\t\twaitedMs: number;\n\t\tsettled?: TaskRecord;\n\t\trunning: TaskSnapshot[];\n\t\tread?: TaskRead;\n\t}> {\n\t\tconst { signal } = options;\n\t\tconst releases = records.map((record) => this.holdRecord(record));\n\t\ttry {\n\t\t\tconst start = Date.now();\n\t\t\tconst interrupt = this.options.waits?.interruptSignal;\n\t\t\tawait this.waitForRecords(records, options.timeoutMs ?? TASKS_WAIT_DEFAULT_MS, signal, interrupt);\n\t\t\tconst waitedMs = Date.now() - start;\n\t\t\tconst settled = records\n\t\t\t\t.filter((record) => record.settled)\n\t\t\t\t.sort((left, right) => (left.task.endedAt ?? 0) - (right.task.endedAt ?? 0))[0];\n\t\t\tconst outcome: TaskWaitOutcome = settled\n\t\t\t\t? \"settled\"\n\t\t\t\t: this.closed\n\t\t\t\t\t? \"closed\"\n\t\t\t\t\t: interrupt?.aborted\n\t\t\t\t\t\t? \"interrupted\"\n\t\t\t\t\t\t: \"timed_out\";\n\t\t\tconst running = records\n\t\t\t\t.filter((record) => record.visible && !record.settled)\n\t\t\t\t.map((record) => record.snapshot());\n\t\t\tconst observed = settled ?? fallback;\n\t\t\tconst read =\n\t\t\t\toptions.read && observed && outcome !== \"interrupted\"\n\t\t\t\t\t? await this.read(observed.task.id, options.read)\n\t\t\t\t\t: undefined;\n\t\t\tsignal?.throwIfAborted();\n\t\t\tif (settled && settled.task.mode === \"background\" && options.toolCallId)\n\t\t\t\tthis.options.waits?.bind(options.toolCallId, settled.task.id);\n\t\t\treturn { outcome, waitedMs, settled, running, read };\n\t\t} finally {\n\t\t\tfor (const release of releases) release();\n\t\t}\n\t}\n\n\tasync wait(id: string, options: TaskWaitOptions = {}): Promise<TaskWaitResult> {\n\t\tif (options.signal?.aborted) throw options.signal.reason ?? new Error(\"Wait aborted\");\n\t\tconst record = this.lookup(id);\n\t\tconst { outcome, waitedMs, read } = await this.observe([record], options, record);\n\t\treturn { outcome, waitedMs, task: record.snapshot(), ...(read ? { read } : {}) };\n\t}\n\n\tasync waitAny(options: TaskWaitAnyOptions = {}): Promise<TaskWaitAnyResult> {\n\t\tif (options.signal?.aborted) throw options.signal.reason ?? new Error(\"Wait aborted\");\n\t\tconst records = this.activeBackground().filter((record) => record.visible);\n\t\tif (records.length === 0) return { outcome: \"no_tasks\", waitedMs: 0, running: [] };\n\t\tconst { outcome, waitedMs, settled, running, read } = await this.observe(records, options);\n\t\treturn {\n\t\t\toutcome,\n\t\t\twaitedMs,\n\t\t\trunning,\n\t\t\t...(settled ? { task: settled.snapshot() } : {}),\n\t\t\t...(read ? { read } : {}),\n\t\t};\n\t}\n\n\tkill(id: string): boolean {\n\t\treturn this.cancel(this.lookup(id));\n\t}\n\n\tprivate cancel(record: TaskRecord): boolean {\n\t\treturn this.executions.get(record.task.id)?.cancel() ?? false;\n\t}\n\n\tsubscribe(listener: () => void): () => void {\n\t\tif (this.closed) return () => {};\n\t\tthis.listeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(listener);\n\t\t};\n\t}\n\n\t/**\n\t * Retention protects snapshots and logs only. Delivery has its own explicit hold.\n\t */\n\tretain(id: string): () => void {\n\t\treturn this.pin(this.lookup(id));\n\t}\n\n\tprivate pin(record: TaskRecord): () => void {\n\t\trecord.pins++;\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\trecord.pins--;\n\t\t\tthis.store.trim();\n\t\t\t// Listeners decide whether delivery may proceed; TaskDelivery owns pausing.\n\t\t\tif (!this.closed && record.deliverable) this.emit();\n\t\t};\n\t}\n\n\tholdDelivery(id: string): () => void {\n\t\treturn this.holdRecord(this.lookup(id));\n\t}\n\n\tprivate holdRecord(record: TaskRecord): () => void {\n\t\tconst releasePin = this.pin(record);\n\t\trecord.deliveryHolds++;\n\t\tlet released = false;\n\t\treturn () => {\n\t\t\tif (released) return;\n\t\t\treleased = true;\n\t\t\trecord.deliveryHolds--;\n\t\t\treleasePin();\n\t\t};\n\t}\n\n\tpendingNotifications(): TaskSnapshot[] {\n\t\tif (this.closed) return [];\n\t\treturn this.store.deliverable().map((record) => record.snapshot());\n\t}\n\n\tclaimNotification(id: string): boolean {\n\t\treturn !this.closed && (this.store.get(id)?.claim() ?? false);\n\t}\n\n\tmarkDelivered(id: string): void {\n\t\tconst record = this.store.get(id);\n\t\tif (!record) return;\n\t\trecord.acknowledge();\n\t\tthis.store.trim();\n\t}\n\n\treleaseNotification(id: string): void {\n\t\tif (!this.store.get(id)?.unclaim()) return;\n\t\tthis.store.trim();\n\t\tthis.emit();\n\t}\n\n\tclose(): void {\n\t\tif (this.closed) return;\n\t\tthis._closed = true;\n\t\tthis.listeners.clear();\n\t\tfor (const record of this.store.all()) {\n\t\t\tthis.executions.get(record.task.id)?.releaseParent();\n\t\t\tthis.cancel(record);\n\t\t\tfor (const waiter of [...record.waiters]) waiter();\n\t\t}\n\t\tthis.store.trim();\n\t}\n\n\tasync shutdown(graceMs = 2000): Promise<void> {\n\t\tthis.close();\n\t\tawait this.drain(this.store.all(), graceMs);\n\t}\n\n\t/** Running tasks whose launch anchor is outside the branch made of `ancestors`. */\n\tactiveOutsideBranch(ancestors: ReadonlySet<string>): TaskSnapshot[] {\n\t\treturn this.store\n\t\t\t.unsettled()\n\t\t\t.filter((record) => record.task.anchorId !== null && !ancestors.has(record.task.anchorId))\n\t\t\t.map((record) => record.snapshot());\n\t}\n\n\t/**\n\t * Hidden results stay pending: returning to their branch delivers them again.\n\t * Restored history is already delivered.\n\t */\n\tasync cancelOutsideBranch(ancestors: ReadonlySet<string>): Promise<void> {\n\t\tconst records = this.store.all();\n\t\tfor (const record of records)\n\t\t\trecord.visible = record.task.anchorId === null || ancestors.has(record.task.anchorId);\n\t\tconst outside = records.filter((record) => !record.visible);\n\t\tfor (const record of outside) this.cancel(record);\n\t\tthis.store.trim();\n\t\tthis.emit();\n\t\tawait this.drain(outside, 2000);\n\t}\n\n\tprivate async drain(records: TaskRecord[], graceMs: number): Promise<void> {\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\ttry {\n\t\t\tawait Promise.race([\n\t\t\t\tPromise.all(records.map((record) => this.executions.get(record.task.id)?.done)).then(() =>\n\t\t\t\t\tthis.store.cleanupsDone(),\n\t\t\t\t),\n\t\t\t\tnew Promise<void>((resolve) => {\n\t\t\t\t\ttimer = setTimeout(resolve, finiteLimit(graceMs, 2000, 60_000));\n\t\t\t\t}),\n\t\t\t]);\n\t\t} finally {\n\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t}\n\t}\n\n\tprivate emit(): void {\n\t\tif (this.closed) return;\n\t\tfor (const listener of [...this.listeners]) {\n\t\t\tif (this.closed) break;\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch {\n\t\t\t\t/* Observers do not own execution or delivery. */\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/core/tasks/runtime.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { AgentToolResult } from \"@earendil-works/pi-agent-core\";\nimport type { Theme } from \"../../modes/interactive/theme/theme.ts\";\nimport { finiteLimit } from \"../../utils/number.ts\";\nimport { Execution, type ExecutionHost } from \"./execution.ts\";\nimport { defaultReadMode, TASKS_WAIT_DEFAULT_MS } from \"./limits.ts\";\nimport {\n\tboundFacts,\n\tboundInput,\n\tboundText,\n\terrorText,\n\treadOutputSlice,\n\tsliceText,\n\tTASK_LABEL_BYTES,\n\tTASK_TITLE_BYTES,\n} from \"./output.ts\";\nimport { TaskRecord } from \"./record.ts\";\nimport { TaskScheduler } from \"./scheduler.ts\";\nimport { TaskStore } from \"./store.ts\";\nimport {\n\tTASK_BACKGROUND_REJECTION,\n\tTASK_KIND_PATTERN,\n\tTASK_MANAGEMENT_REJECTION,\n\ttype TaskExecution,\n\tTaskLookupError,\n\ttype TaskRead,\n\ttype TaskReadOptions,\n\ttype TaskRuntimeOptions,\n\ttype TaskSnapshot,\n\ttype TasksContext,\n\ttype TaskToolOutcome,\n\ttype TaskWaitAnyOptions,\n\ttype TaskWaitAnyResult,\n\ttype TaskWaitOptions,\n\ttype TaskWaitOutcome,\n\ttype TaskWaitResult,\n} from \"./types.ts\";\nimport { waitForFirst } from \"./wait.ts\";\n\n/** Session-local supervision. Executors own their processes, items and output files. */\nexport class TaskRuntime implements TasksContext {\n\tprivate readonly store: TaskStore;\n\tprivate readonly executions = new Map<string, Execution<unknown>>();\n\tprivate readonly scheduler = new TaskScheduler();\n\tprivate readonly listeners = new Set<() => void>();\n\tprivate readonly host: ExecutionHost;\n\tprivate readonly maxBackground: number;\n\tprivate readonly maxHistory: number;\n\tprivate readonly maxRetained: number;\n\tprivate readonly options: TaskRuntimeOptions;\n\tprivate readonly closing = new AbortController();\n\tprivate configuredEnabled: boolean;\n\tprivate _closed = false;\n\n\tconstructor(options: TaskRuntimeOptions = {}) {\n\t\tthis.options = options;\n\t\tthis.configuredEnabled = options.enabled ?? false;\n\t\tthis.maxBackground = Math.max(1, finiteLimit(options.maxBackground, 8, 128));\n\t\tthis.maxHistory = finiteLimit(options.maxHistory, 32, 1024);\n\t\t// Separate foreground and background histories, plus the protected-record allowance.\n\t\tthis.maxRetained = this.maxBackground + 2 * Math.max(1, this.maxHistory) + this.maxHistory;\n\t\tthis.store = new TaskStore(this.maxHistory, this.maxRetained, () => this.closed, options.onCleanupError);\n\t\tconst runtime = this;\n\t\tthis.host = {\n\t\t\tget closed() {\n\t\t\t\treturn runtime.closed;\n\t\t\t},\n\t\t\temit: () => this.emit(),\n\t\t\tsettle: (task, usage) => this.options.onSettled?.(task, usage),\n\t\t\treleased: (execution) => {\n\t\t\t\tthis.executions.delete(execution.task.id);\n\t\t\t\tthis.scheduler.release(execution);\n\t\t\t\tthis.store.trim();\n\t\t\t\tthis.emit();\n\t\t\t},\n\t\t};\n\t}\n\n\tget closed(): boolean {\n\t\treturn this._closed;\n\t}\n\n\tget session(): TaskRuntimeOptions[\"session\"] {\n\t\treturn this.options.session;\n\t}\n\n\t/**\n\t * Rehydrate terminal snapshots only, newest endedAt in each history (later input wins\n\t * ties). Existing runtime records win ID collisions. No execution, accounting,\n\t * notification, or deletion ownership is restored. Foreground records take their output\n\t * from the branch's tool results. The host supplies the current branch; closed services\n\t * ignore restoration.\n\t */\n\trestoreHistory(\n\t\trecords: readonly unknown[],\n\t\ttoolResults?: ReadonlyMap<string, AgentToolResult<unknown>[\"content\"]>,\n\t): void {\n\t\tthis.store.restoreHistory(records, toolResults);\n\t}\n\n\tget enabled(): boolean {\n\t\treturn this.configuredEnabled && !this.closed && this.options.backgroundAllowed !== false;\n\t}\n\n\tsetEnabled(enabled: boolean): void {\n\t\tthis.configuredEnabled = enabled;\n\t\tthis.emit();\n\t}\n\n\t/** Tell subscribers that something the runtime reads from its host changed, such as `canManageBackground`. */\n\trefresh(): void {\n\t\tthis.emit();\n\t}\n\n\t/** Whether new work may move to or start in the background: enabled, and the host can manage it. */\n\tprivate get admitsBackground(): boolean {\n\t\treturn this.enabled && (this.options.canManageBackground?.() ?? true);\n\t}\n\n\t/** Handed-off work that has not settled: the waitAny cohort and the statusline count. */\n\tprivate activeBackground(): TaskRecord[] {\n\t\treturn this.store.unsettled().filter((record) => record.task.mode === \"background\");\n\t}\n\n\t/**\n\t * Foreground work is bounded by its caller; only background work holds a slot, including work\n\t * whose caller is still waiting for the executor to accept (a detaching task).\n\t */\n\tprivate backgroundActive(): number {\n\t\treturn [...this.executions.values()].filter((execution) => execution.holdsBackgroundSlot).length;\n\t}\n\n\tprivate limitError(): Error {\n\t\treturn new Error(\n\t\t\t`Background task limit reached (${this.maxBackground}); stop or wait for a background task, or run in the foreground.`,\n\t\t);\n\t}\n\n\tasync execute<T>(execution: TaskExecution<T>): Promise<TaskToolOutcome<T>> {\n\t\t// Admission and registration happen synchronously, before invoking user code or awaiting anything.\n\t\tif (execution.background && this.options.backgroundAllowed === false) throw new Error(TASK_BACKGROUND_REJECTION);\n\t\tif (this.closed) throw new Error(\"Task service is closed\");\n\t\tif (execution.background) {\n\t\t\tif (!this.enabled) throw new Error(\"Background execution is not available in this host\");\n\t\t\tif (!this.admitsBackground) throw new Error(TASK_MANAGEMENT_REJECTION);\n\t\t\tif (this.backgroundActive() >= this.maxBackground) throw this.limitError();\n\t\t\tif (this.store.retainedCount() >= this.maxRetained) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"Task history retention limit reached; deliver pending notifications or release task pins and delivery leases\",\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (execution.signal?.aborted) throw execution.signal.reason ?? new Error(\"Execution aborted\");\n\t\tif (!TASK_KIND_PATTERN.test(execution.kind)) throw new Error(\"Invalid task source\");\n\t\tconst concurrency = execution.concurrency;\n\t\tif (concurrency && (!concurrency.key || !Number.isSafeInteger(concurrency.limit) || concurrency.limit < 1))\n\t\t\tthrow new Error(\"Invalid task concurrency\");\n\t\tconst anchorId = this.options.anchor?.() ?? null;\n\t\tif (anchorId !== null && Buffer.byteLength(anchorId) > 8192) throw new Error(\"Task branch anchor is too large\");\n\t\tconst task: TaskSnapshot = {\n\t\t\tid: `${execution.kind}-${randomUUID()}`,\n\t\t\tkind: execution.kind,\n\t\t\tlabel: boundText(execution.label ?? execution.kind, TASK_LABEL_BYTES),\n\t\t\ttitle: boundText(execution.title, TASK_TITLE_BYTES),\n\t\t\toutput: execution.output ?? \"log\",\n\t\t\t...(execution.input ? { input: boundInput(execution.input) } : {}),\n\t\t\t...(execution.facts?.length ? { facts: boundFacts(execution.facts) } : {}),\n\t\t\ttoolCallId: boundText(execution.toolCallId, 512),\n\t\t\tanchorId,\n\t\t\tmode: \"foreground\",\n\t\t\tstatus: \"queued\",\n\t\t\tstartedAt: Date.now(),\n\t\t};\n\t\tconst record = new TaskRecord(task);\n\t\trecord.setPresenter(execution.present);\n\t\tconst active = new Execution(this.host, record, execution);\n\t\tthis.store.add(record);\n\t\tthis.executions.set(task.id, active as Execution<unknown>);\n\t\tthis.scheduler.schedule(active);\n\t\t// Queued background work returns at once; started work hands off after its own accept().\n\t\tactive.handOffIfQueued();\n\t\tthis.emit();\n\t\treturn active.caller;\n\t}\n\n\tprivate detachable(record: TaskRecord): boolean {\n\t\treturn this.executions.get(record.task.id)?.detachable ?? false;\n\t}\n\n\tdetachForeground(): number {\n\t\tif (!this.admitsBackground) return 0;\n\t\tconst eligible = [...this.executions.values()]\n\t\t\t.filter((execution) => execution.detachable)\n\t\t\t.sort((left, right) => left.task.startedAt - right.task.startedAt);\n\t\tif (!eligible.length) return 0;\n\t\tconst free = this.maxBackground - this.backgroundActive();\n\t\tif (free <= 0) throw this.limitError();\n\t\treturn this.detachAll(eligible.slice(0, free));\n\t}\n\n\tcanDetach(id: string): boolean {\n\t\tconst record = this.lookup(id);\n\t\treturn this.admitsBackground && this.backgroundActive() < this.maxBackground && this.detachable(record);\n\t}\n\n\tdetach(id: string): boolean {\n\t\tconst record = this.lookup(id);\n\t\tif (!this.admitsBackground || !this.detachable(record)) return false;\n\t\tif (this.backgroundActive() >= this.maxBackground) throw this.limitError();\n\t\tthis.detachAll([this.executions.get(record.task.id)!]);\n\t\treturn true;\n\t}\n\n\t/** Every placement changes before any listener hears about it. */\n\tprivate detachAll(executions: Execution<unknown>[]): number {\n\t\tconst notifications = executions.map((execution) => execution.detach());\n\t\tfor (const notify of notifications) notify();\n\t\tthis.emit();\n\t\treturn executions.length;\n\t}\n\n\tlist(): TaskSnapshot[] {\n\t\treturn this.store.visible().map((record) => record.snapshot());\n\t}\n\n\tprivate lookup(id: string): TaskRecord {\n\t\tconst exact = this.store.get(id);\n\t\tif (exact) return exact;\n\t\tconst matches = this.store.match(id);\n\t\tif (!id || matches.length !== 1) {\n\t\t\tthrow new TaskLookupError(\n\t\t\t\tmatches.length > 1 ? \"ambiguous\" : \"unknown\",\n\t\t\t\tmatches.map((record) => record.snapshot()),\n\t\t\t);\n\t\t}\n\t\treturn matches[0]!;\n\t}\n\n\tget(id: string): TaskSnapshot {\n\t\treturn this.lookup(id).snapshot();\n\t}\n\n\tasync read(id: string, options: TaskReadOptions = {}): Promise<TaskRead> {\n\t\tconst record = this.lookup(id);\n\t\tconst release = this.retain(record.task.id);\n\t\ttry {\n\t\t\tconst task = record.snapshot();\n\t\t\tconst window = { ...options, mode: options.mode ?? defaultReadMode(task) };\n\t\t\tif (task.outputPath) {\n\t\t\t\ttry {\n\t\t\t\t\treturn { task, ...(await readOutputSlice(task.outputPath, window)) };\n\t\t\t\t} catch (error) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttask,\n\t\t\t\t\t\treadError: boundText(`Output could not be read: ${errorText(error)}`, 4096),\n\t\t\t\t\t\t...sliceText(this.resultText(task), window),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn { task, readError: record.readError, ...sliceText(this.resultText(task), window) };\n\t\t} finally {\n\t\t\trelease();\n\t\t}\n\t}\n\n\tpresentOutput(id: string, width: number, theme: Theme): string[] | undefined {\n\t\tlet record: TaskRecord;\n\t\ttry {\n\t\t\trecord = this.lookup(id);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn record.present(width, theme);\n\t}\n\n\tprivate resultText(task: TaskSnapshot): string {\n\t\treturn task.result?.text || task.error || \"No output yet.\";\n\t}\n\n\t/**\n\t * One observation: hold delivery for the observed records, wait, read, then register the\n\t * receipt with the host, and only then release. Nothing the caller does between those steps\n\t * can leak a settled result into an automatic notification or lose it.\n\t */\n\tprivate async observe(\n\t\trecords: readonly TaskRecord[],\n\t\toptions: TaskWaitOptions,\n\t\t/** Record to read when none settled; a cohort has none. */\n\t\tfallback?: TaskRecord,\n\t): Promise<{\n\t\toutcome: TaskWaitOutcome;\n\t\twaitedMs: number;\n\t\tsettled?: TaskRecord;\n\t\trunning: TaskSnapshot[];\n\t\tread?: TaskRead;\n\t}> {\n\t\tconst { signal } = options;\n\t\t// Retention pins the records; the host keeps them out of automatic delivery until released.\n\t\tconst releases = records.map((record) => this.pin(record));\n\t\treleases.push(this.options.waits?.hold(records.map((record) => record.task.id)) ?? (() => {}));\n\t\ttry {\n\t\t\tconst start = Date.now();\n\t\t\tconst interrupt = this.options.waits?.interruptSignal;\n\t\t\tawait waitForFirst({\n\t\t\t\thasSettled: () => records.some((record) => record.settled),\n\t\t\t\tsubscribe: (listener) => this.subscribe(listener),\n\t\t\t\ttimeoutMs: options.timeoutMs ?? TASKS_WAIT_DEFAULT_MS,\n\t\t\t\tsignal,\n\t\t\t\tinterrupt,\n\t\t\t\tclosed: this.closing.signal,\n\t\t\t});\n\t\t\tconst waitedMs = Date.now() - start;\n\t\t\tconst settled = records\n\t\t\t\t.filter((record) => record.settled)\n\t\t\t\t.sort((left, right) => (left.task.endedAt ?? 0) - (right.task.endedAt ?? 0))[0];\n\t\t\tconst outcome: TaskWaitOutcome = settled\n\t\t\t\t? \"settled\"\n\t\t\t\t: this.closed\n\t\t\t\t\t? \"closed\"\n\t\t\t\t\t: interrupt?.aborted\n\t\t\t\t\t\t? \"interrupted\"\n\t\t\t\t\t\t: \"timed_out\";\n\t\t\tconst running = records\n\t\t\t\t.filter((record) => record.visible && !record.settled)\n\t\t\t\t.map((record) => record.snapshot());\n\t\t\tconst observed = settled ?? fallback;\n\t\t\tconst read =\n\t\t\t\toptions.read && observed && outcome !== \"interrupted\"\n\t\t\t\t\t? await this.read(observed.task.id, options.read)\n\t\t\t\t\t: undefined;\n\t\t\tsignal?.throwIfAborted();\n\t\t\tif (settled && settled.task.mode === \"background\" && options.toolCallId)\n\t\t\t\tthis.options.waits?.bind(options.toolCallId, settled.task.id);\n\t\t\treturn { outcome, waitedMs, settled, running, read };\n\t\t} finally {\n\t\t\tfor (const release of releases) release();\n\t\t}\n\t}\n\n\tasync wait(id: string, options: TaskWaitOptions = {}): Promise<TaskWaitResult> {\n\t\tif (options.signal?.aborted) throw options.signal.reason ?? new Error(\"Wait aborted\");\n\t\tconst record = this.lookup(id);\n\t\tconst { outcome, waitedMs, read } = await this.observe([record], options, record);\n\t\treturn { outcome, waitedMs, task: record.snapshot(), ...(read ? { read } : {}) };\n\t}\n\n\tasync waitAny(options: TaskWaitAnyOptions = {}): Promise<TaskWaitAnyResult> {\n\t\tif (options.signal?.aborted) throw options.signal.reason ?? new Error(\"Wait aborted\");\n\t\tconst records = this.activeBackground().filter((record) => record.visible);\n\t\tif (records.length === 0) return { outcome: \"no_tasks\", waitedMs: 0, running: [] };\n\t\tconst { outcome, waitedMs, settled, running, read } = await this.observe(records, options);\n\t\treturn {\n\t\t\toutcome,\n\t\t\twaitedMs,\n\t\t\trunning,\n\t\t\t...(settled ? { task: settled.snapshot() } : {}),\n\t\t\t...(read ? { read } : {}),\n\t\t};\n\t}\n\n\tkill(id: string): boolean {\n\t\treturn this.cancel(this.lookup(id));\n\t}\n\n\tprivate cancel(record: TaskRecord): boolean {\n\t\treturn this.executions.get(record.task.id)?.cancel() ?? false;\n\t}\n\n\tsubscribe(listener: () => void): () => void {\n\t\tif (this.closed) return () => {};\n\t\tthis.listeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(listener);\n\t\t};\n\t}\n\n\t/** Retention protects snapshots and logs only; completion delivery never waits on it. */\n\tretain(id: string): () => void {\n\t\treturn this.pin(this.lookup(id));\n\t}\n\n\tprivate pin(record: TaskRecord): () => void {\n\t\tconst release = record.pin();\n\t\treturn () => {\n\t\t\trelease();\n\t\t\tthis.store.trim();\n\t\t};\n\t}\n\n\tclose(): void {\n\t\tif (this.closed) return;\n\t\tthis._closed = true;\n\t\tthis.listeners.clear();\n\t\tfor (const record of this.store.all()) {\n\t\t\tthis.executions.get(record.task.id)?.releaseParent();\n\t\t\tthis.cancel(record);\n\t\t}\n\t\tthis.closing.abort();\n\t\tthis.options.onClosed?.();\n\t\tthis.store.trim();\n\t}\n\n\tasync shutdown(graceMs = 2000): Promise<void> {\n\t\tthis.close();\n\t\tawait this.drain(this.store.all(), graceMs);\n\t}\n\n\t/** Running tasks whose launch anchor is outside the branch made of `ancestors`. */\n\tactiveOutsideBranch(ancestors: ReadonlySet<string>): TaskSnapshot[] {\n\t\treturn this.store\n\t\t\t.unsettled()\n\t\t\t.filter((record) => record.task.anchorId !== null && !ancestors.has(record.task.anchorId))\n\t\t\t.map((record) => record.snapshot());\n\t}\n\n\t/**\n\t * Hidden results stay pending: returning to their branch delivers them again.\n\t * Restored history is already delivered.\n\t */\n\tasync cancelOutsideBranch(ancestors: ReadonlySet<string>): Promise<void> {\n\t\tconst records = this.store.all();\n\t\tfor (const record of records)\n\t\t\trecord.setVisible(record.task.anchorId === null || ancestors.has(record.task.anchorId));\n\t\tconst outside = records.filter((record) => !record.visible);\n\t\tfor (const record of outside) this.cancel(record);\n\t\tthis.store.trim();\n\t\tthis.emit();\n\t\tawait this.drain(outside, 2000);\n\t}\n\n\tprivate async drain(records: TaskRecord[], graceMs: number): Promise<void> {\n\t\tlet timer: ReturnType<typeof setTimeout> | undefined;\n\t\ttry {\n\t\t\tawait Promise.race([\n\t\t\t\tPromise.all(records.map((record) => this.executions.get(record.task.id)?.done)).then(() =>\n\t\t\t\t\tthis.store.cleanupsDone(),\n\t\t\t\t),\n\t\t\t\tnew Promise<void>((resolve) => {\n\t\t\t\t\ttimer = setTimeout(resolve, finiteLimit(graceMs, 2000, 60_000));\n\t\t\t\t}),\n\t\t\t]);\n\t\t} finally {\n\t\t\tif (timer !== undefined) clearTimeout(timer);\n\t\t}\n\t}\n\n\tprivate emit(): void {\n\t\tif (this.closed) return;\n\t\tfor (const listener of [...this.listeners]) {\n\t\t\tif (this.closed) break;\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch {\n\t\t\t\t/* Observers do not own execution or delivery. */\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
/** Per-
|
|
1
|
+
/** Per-executor concurrency lanes. Executions without a concurrency key start immediately. */
|
|
2
2
|
export interface Schedulable {
|
|
3
|
+
/** The executor kind, which namespaces its lane keys. */
|
|
4
|
+
readonly kind: string;
|
|
3
5
|
readonly concurrency?: {
|
|
4
6
|
key: string;
|
|
5
7
|
limit: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/scheduler.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../../../src/core/tasks/scheduler.ts"],"names":[],"mappings":"AAAA,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC3B,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,CAAC,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,KAAK,IAAI,IAAI,CAAC;CACd;AAYD,qBAAa,aAAa;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2B;IAEjD,QAAQ,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI;IAetC,2FAA2F;IAC3F,OAAO,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI;IAUrC,OAAO,CAAC,IAAI;CASZ"}
|
|
@@ -1,42 +1,46 @@
|
|
|
1
|
+
/** A lane belongs to one executor kind, so two executors can never collide on a chosen key. */
|
|
2
|
+
function laneId(execution) {
|
|
3
|
+
return execution.concurrency ? `${execution.kind}:${execution.concurrency.key}` : undefined;
|
|
4
|
+
}
|
|
1
5
|
export class TaskScheduler {
|
|
2
6
|
constructor() {
|
|
3
7
|
this.lanes = new Map();
|
|
4
8
|
}
|
|
5
9
|
schedule(execution) {
|
|
6
|
-
const
|
|
7
|
-
if (
|
|
10
|
+
const id = laneId(execution);
|
|
11
|
+
if (id === undefined) {
|
|
8
12
|
execution.start();
|
|
9
13
|
return;
|
|
10
14
|
}
|
|
11
|
-
let lane = this.lanes.get(
|
|
15
|
+
let lane = this.lanes.get(id);
|
|
12
16
|
if (!lane) {
|
|
13
17
|
lane = { running: new Set(), waiting: [] };
|
|
14
|
-
this.lanes.set(
|
|
18
|
+
this.lanes.set(id, lane);
|
|
15
19
|
}
|
|
16
20
|
lane.waiting.push(execution);
|
|
17
|
-
this.pump(
|
|
21
|
+
this.pump(id, lane);
|
|
18
22
|
}
|
|
19
23
|
/** A settled execution frees its slot or leaves the queue; the next waiting one starts. */
|
|
20
24
|
release(execution) {
|
|
21
|
-
const
|
|
22
|
-
const lane =
|
|
23
|
-
if (!lane ||
|
|
25
|
+
const id = laneId(execution);
|
|
26
|
+
const lane = id === undefined ? undefined : this.lanes.get(id);
|
|
27
|
+
if (!lane || id === undefined)
|
|
24
28
|
return;
|
|
25
29
|
lane.running.delete(execution);
|
|
26
30
|
const index = lane.waiting.indexOf(execution);
|
|
27
31
|
if (index >= 0)
|
|
28
32
|
lane.waiting.splice(index, 1);
|
|
29
|
-
this.pump(
|
|
33
|
+
this.pump(id, lane);
|
|
30
34
|
}
|
|
31
|
-
pump(
|
|
35
|
+
pump(id, lane) {
|
|
32
36
|
// Starting can settle synchronously and re-enter release(); the loop rereads lane state.
|
|
33
37
|
while (lane.waiting.length > 0 && lane.running.size < lane.waiting[0].concurrency.limit) {
|
|
34
38
|
const next = lane.waiting.shift();
|
|
35
39
|
lane.running.add(next);
|
|
36
40
|
next.start();
|
|
37
41
|
}
|
|
38
|
-
if (lane.running.size === 0 && lane.waiting.length === 0 && this.lanes.get(
|
|
39
|
-
this.lanes.delete(
|
|
42
|
+
if (lane.running.size === 0 && lane.waiting.length === 0 && this.lanes.get(id) === lane)
|
|
43
|
+
this.lanes.delete(id);
|
|
40
44
|
}
|
|
41
45
|
}
|
|
42
46
|
//# sourceMappingURL=scheduler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/core/tasks/scheduler.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../../../src/core/tasks/scheduler.ts"],"names":[],"mappings":"AAaA,+FAA+F;AAC/F,SAAS,MAAM,CAAC,SAAsB;IACrC,OAAO,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7F,CAAC;AAED,MAAM,OAAO,aAAa;IAA1B;QACkB,UAAK,GAAG,IAAI,GAAG,EAAgB,CAAC;IAqClD,CAAC;IAnCA,QAAQ,CAAC,SAAsB;QAC9B,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,EAAE,KAAK,SAAS,EAAE,CAAC;YACtB,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,OAAO;QACR,CAAC;QACD,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,IAAI,GAAG,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;YAC3C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC1B,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACrB,CAAC;IAED,2FAA2F;IAC3F,OAAO,CAAC,SAAsB;QAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7B,MAAM,IAAI,GAAG,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,IAAI,IAAI,EAAE,KAAK,SAAS;YAAE,OAAO;QACtC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,KAAK,IAAI,CAAC;YAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACrB,CAAC;IAEO,IAAI,CAAC,EAAU,EAAE,IAAU;QAClC,yFAAyF;QACzF,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,WAAY,CAAC,KAAK,EAAE,CAAC;YAC3F,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAG,CAAC;YACnC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACvB,IAAI,CAAC,KAAK,EAAE,CAAC;QACd,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,IAAI;YAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAChH,CAAC;CACD","sourcesContent":["/** Per-executor concurrency lanes. Executions without a concurrency key start immediately. */\nexport interface Schedulable {\n\t/** The executor kind, which namespaces its lane keys. */\n\treadonly kind: string;\n\treadonly concurrency?: { key: string; limit: number };\n\tstart(): void;\n}\n\ninterface Lane {\n\trunning: Set<Schedulable>;\n\twaiting: Schedulable[];\n}\n\n/** A lane belongs to one executor kind, so two executors can never collide on a chosen key. */\nfunction laneId(execution: Schedulable): string | undefined {\n\treturn execution.concurrency ? `${execution.kind}:${execution.concurrency.key}` : undefined;\n}\n\nexport class TaskScheduler {\n\tprivate readonly lanes = new Map<string, Lane>();\n\n\tschedule(execution: Schedulable): void {\n\t\tconst id = laneId(execution);\n\t\tif (id === undefined) {\n\t\t\texecution.start();\n\t\t\treturn;\n\t\t}\n\t\tlet lane = this.lanes.get(id);\n\t\tif (!lane) {\n\t\t\tlane = { running: new Set(), waiting: [] };\n\t\t\tthis.lanes.set(id, lane);\n\t\t}\n\t\tlane.waiting.push(execution);\n\t\tthis.pump(id, lane);\n\t}\n\n\t/** A settled execution frees its slot or leaves the queue; the next waiting one starts. */\n\trelease(execution: Schedulable): void {\n\t\tconst id = laneId(execution);\n\t\tconst lane = id === undefined ? undefined : this.lanes.get(id);\n\t\tif (!lane || id === undefined) return;\n\t\tlane.running.delete(execution);\n\t\tconst index = lane.waiting.indexOf(execution);\n\t\tif (index >= 0) lane.waiting.splice(index, 1);\n\t\tthis.pump(id, lane);\n\t}\n\n\tprivate pump(id: string, lane: Lane): void {\n\t\t// Starting can settle synchronously and re-enter release(); the loop rereads lane state.\n\t\twhile (lane.waiting.length > 0 && lane.running.size < lane.waiting[0]!.concurrency!.limit) {\n\t\t\tconst next = lane.waiting.shift()!;\n\t\t\tlane.running.add(next);\n\t\t\tnext.start();\n\t\t}\n\t\tif (lane.running.size === 0 && lane.waiting.length === 0 && this.lanes.get(id) === lane) this.lanes.delete(id);\n\t}\n}\n"]}
|