@cuylabs/agent-core 0.9.0 → 0.10.0
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/README.md +33 -17
- package/dist/chunk-2O4MCSQS.js +780 -0
- package/dist/chunk-2TTOLHBT.js +198 -0
- package/dist/chunk-5FMSGQVX.js +281 -0
- package/dist/chunk-5NVVNXPQ.js +288 -0
- package/dist/{chunk-EKR6PKXU.js → chunk-6HZBHFOL.js} +3 -3
- package/dist/chunk-CJI7PVS2.js +58 -0
- package/dist/{chunk-WKHDSSXG.js → chunk-CMYN2RCB.js} +146 -46
- package/dist/chunk-FII65CN7.js +117 -0
- package/dist/{chunk-UHCJEM2E.js → chunk-ICZ66572.js} +13 -6
- package/dist/chunk-KYLPMBHD.js +316 -0
- package/dist/chunk-MXAP4UG6.js +2956 -0
- package/dist/{chunk-4QFNWPIF.js → chunk-N3VX7FEE.js} +35 -2
- package/dist/{chunk-MAZ5DY5B.js → chunk-NDZWXCBZ.js} +213 -78
- package/dist/{chunk-MHKK374K.js → chunk-Q742PSH3.js} +11 -27
- package/dist/{chunk-WGZAPU6N.js → chunk-QAL3OMI3.js} +15 -1
- package/dist/{chunk-UDCZ673N.js → chunk-RN6WZEUF.js} +27 -23
- package/dist/{chunk-ZXAKHMWH.js → chunk-ROTGCYDW.js} +22 -84
- package/dist/chunk-SPBFQXOT.js +0 -0
- package/dist/chunk-SSFBF3US.js +602 -0
- package/dist/chunk-SZ2XBPTW.js +8 -0
- package/dist/chunk-T4UIX5D7.js +115 -0
- package/dist/{chunk-IYWQOJMQ.js → chunk-TIHPYVAJ.js} +34 -34
- package/dist/{chunk-RKEW5WXI.js → chunk-TOTDGK3P.js} +1 -1
- package/dist/chunk-V4RFNEET.js +563 -0
- package/dist/chunk-VOUEJSW6.js +0 -0
- package/dist/{chunk-J4QDGZIA.js → chunk-WBPOZ7CL.js} +659 -275
- package/dist/chunk-X4VN4GIJ.js +185 -0
- package/dist/dispatch/index.d.ts +93 -0
- package/dist/dispatch/index.js +37 -0
- package/dist/events/index.d.ts +93 -0
- package/dist/events/index.js +6 -0
- package/dist/{runtime → execution}/index.d.ts +120 -35
- package/dist/{runtime → execution}/index.js +17 -11
- package/dist/index.d.ts +489 -115
- package/dist/index.js +1665 -462
- package/dist/inference/errors/index.js +1 -1
- package/dist/inference/index.d.ts +13 -21
- package/dist/inference/index.js +15 -12
- package/dist/instance-BqV2D5pc.d.ts +5723 -0
- package/dist/logger/index.d.ts +50 -0
- package/dist/logger/index.js +11 -0
- package/dist/mcp/index.d.ts +5 -9
- package/dist/mcp/index.js +2 -3
- package/dist/middleware/index.d.ts +10 -150
- package/dist/middleware/index.js +10 -2
- package/dist/model-messages-B4nK9D1-.d.ts +13 -0
- package/dist/models/index.d.ts +5 -2
- package/dist/models/index.js +2 -1
- package/dist/models/reasoning/index.js +2 -1
- package/dist/plugin/index.d.ts +55 -11
- package/dist/plugin/index.js +1 -1
- package/dist/profiles/index.d.ts +55 -0
- package/dist/{presets → profiles}/index.js +10 -10
- package/dist/prompt/index.d.ts +8 -13
- package/dist/safety/index.d.ts +109 -14
- package/dist/safety/index.js +59 -3
- package/dist/sandbox/index.d.ts +81 -0
- package/dist/sandbox/index.js +1 -0
- package/dist/skill/index.d.ts +10 -8
- package/dist/skill/index.js +2 -2
- package/dist/storage/index.d.ts +12 -4
- package/dist/storage/index.js +1 -1
- package/dist/subagents/index.d.ts +177 -0
- package/dist/subagents/index.js +78 -0
- package/dist/team/index.d.ts +544 -0
- package/dist/team/index.js +41 -0
- package/dist/tool/host/index.d.ts +41 -0
- package/dist/tool/host/index.js +10 -0
- package/dist/tool/index.d.ts +111 -21
- package/dist/tool/index.js +20 -13
- package/dist/{types-VQgymC1N.d.ts → types-Bj_J8u_W.d.ts} +44 -64
- package/dist/{types-CHiPh8U2.d.ts → types-C_LCeYNg.d.ts} +7 -7
- package/dist/types-RSCv7nQ4.d.ts +59 -0
- package/package.json +46 -47
- package/dist/builder-BgZ_j4Vs.d.ts +0 -35
- package/dist/chunk-5ARZJWD2.js +0 -259
- package/dist/chunk-DXFBQMXP.js +0 -53
- package/dist/chunk-H3FUYU52.js +0 -81
- package/dist/chunk-JLXG2SH7.js +0 -905
- package/dist/chunk-N7P4PN3O.js +0 -84
- package/dist/chunk-OFDKHNCX.js +0 -727
- package/dist/chunk-SDSBEQXG.js +0 -157
- package/dist/chunk-VEKUXUVF.js +0 -41
- package/dist/chunk-VNQBHPCT.js +0 -398
- package/dist/chunk-WWYYNWEW.js +0 -259
- package/dist/context/index.d.ts +0 -259
- package/dist/context/index.js +0 -26
- package/dist/events-CE72w8W4.d.ts +0 -149
- package/dist/host/index.d.ts +0 -45
- package/dist/host/index.js +0 -8
- package/dist/index-DQuTZ8xL.d.ts +0 -1335
- package/dist/messages-BYWGn8TY.d.ts +0 -110
- package/dist/presets/index.d.ts +0 -53
- package/dist/registry-DwYqsQkX.d.ts +0 -164
- package/dist/runner-CI-XeR16.d.ts +0 -91
- package/dist/scope/index.d.ts +0 -10
- package/dist/scope/index.js +0 -14
- package/dist/session-manager-KbYt2WUh.d.ts +0 -282
- package/dist/signal/index.d.ts +0 -28
- package/dist/signal/index.js +0 -6
- package/dist/sub-agent/index.d.ts +0 -24
- package/dist/sub-agent/index.js +0 -32
- package/dist/tool-CZWN3KbO.d.ts +0 -141
- package/dist/tool-DkhSCV2Y.d.ts +0 -145
- package/dist/tracker-DClqYqTj.d.ts +0 -96
- package/dist/tracking/index.d.ts +0 -111
- package/dist/tracking/index.js +0 -20
- package/dist/types-BfNpU8NS.d.ts +0 -270
- package/dist/types-BlOKk-Bb.d.ts +0 -330
- package/dist/types-BlZwmnuW.d.ts +0 -50
- package/dist/types-CQL-SvTn.d.ts +0 -29
- package/dist/types-CWm-7rvB.d.ts +0 -55
- package/dist/types-DTSkxakL.d.ts +0 -651
- package/dist/types-DmDwi2zI.d.ts +0 -339
- package/dist/types-YuWV4ag7.d.ts +0 -72
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// src/events/local.ts
|
|
2
|
+
function createEventBus(options = {}) {
|
|
3
|
+
const channels = /* @__PURE__ */ new Map();
|
|
4
|
+
const maxHistoryMessages = Math.max(1, options.maxHistoryMessages ?? 1024);
|
|
5
|
+
const maxBufferedMessages = Math.max(1, options.maxBufferedMessages ?? 512);
|
|
6
|
+
const channelRetentionMs = Math.max(
|
|
7
|
+
1e3,
|
|
8
|
+
options.channelRetentionMs ?? 10 * 60 * 1e3
|
|
9
|
+
);
|
|
10
|
+
function getOrCreateChannel(channel) {
|
|
11
|
+
let state = channels.get(channel);
|
|
12
|
+
if (!state) {
|
|
13
|
+
state = {
|
|
14
|
+
seq: 0,
|
|
15
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
16
|
+
closed: false,
|
|
17
|
+
history: []
|
|
18
|
+
};
|
|
19
|
+
channels.set(channel, state);
|
|
20
|
+
} else if (state.cleanupTimer) {
|
|
21
|
+
clearTimeout(state.cleanupTimer);
|
|
22
|
+
state.cleanupTimer = void 0;
|
|
23
|
+
}
|
|
24
|
+
return state;
|
|
25
|
+
}
|
|
26
|
+
function scheduleCleanup(channel, state) {
|
|
27
|
+
if (state.cleanupTimer) {
|
|
28
|
+
clearTimeout(state.cleanupTimer);
|
|
29
|
+
}
|
|
30
|
+
state.cleanupTimer = setTimeout(() => {
|
|
31
|
+
const current = channels.get(channel);
|
|
32
|
+
if (current !== state) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
if (current.subscribers.size === 0) {
|
|
36
|
+
channels.delete(channel);
|
|
37
|
+
}
|
|
38
|
+
}, channelRetentionMs);
|
|
39
|
+
}
|
|
40
|
+
function appendToHistory(state, message) {
|
|
41
|
+
state.history.push(message);
|
|
42
|
+
if (state.history.length > maxHistoryMessages) {
|
|
43
|
+
state.history.splice(0, state.history.length - maxHistoryMessages);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
get activeChannels() {
|
|
48
|
+
let count = 0;
|
|
49
|
+
for (const state of channels.values()) {
|
|
50
|
+
if (state.subscribers.size > 0) count++;
|
|
51
|
+
}
|
|
52
|
+
return count;
|
|
53
|
+
},
|
|
54
|
+
publish(channel, type, data) {
|
|
55
|
+
const state = getOrCreateChannel(channel);
|
|
56
|
+
if (state.closed) {
|
|
57
|
+
state.closed = false;
|
|
58
|
+
state.seq = 0;
|
|
59
|
+
state.history = [];
|
|
60
|
+
}
|
|
61
|
+
state.seq++;
|
|
62
|
+
const message = {
|
|
63
|
+
channel,
|
|
64
|
+
type,
|
|
65
|
+
data,
|
|
66
|
+
seq: state.seq
|
|
67
|
+
};
|
|
68
|
+
appendToHistory(state, message);
|
|
69
|
+
for (const sub of state.subscribers) {
|
|
70
|
+
sub.push(message);
|
|
71
|
+
}
|
|
72
|
+
if (state.subscribers.size === 0) {
|
|
73
|
+
scheduleCleanup(channel, state);
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
subscribe(channel, subscribeOptions = {}) {
|
|
77
|
+
const state = getOrCreateChannel(channel);
|
|
78
|
+
const afterSeq = typeof subscribeOptions.afterSeq === "number" && Number.isFinite(subscribeOptions.afterSeq) && subscribeOptions.afterSeq >= 0 ? subscribeOptions.afterSeq : void 0;
|
|
79
|
+
const initialBuffer = state.history.filter(
|
|
80
|
+
(message) => afterSeq === void 0 ? true : message.seq > afterSeq
|
|
81
|
+
);
|
|
82
|
+
const closedAtSubscribe = state.closed;
|
|
83
|
+
const buffer = [...initialBuffer];
|
|
84
|
+
let waiting = null;
|
|
85
|
+
let done = false;
|
|
86
|
+
let closedAfterBuffer = closedAtSubscribe;
|
|
87
|
+
let unsubscribe = () => {
|
|
88
|
+
};
|
|
89
|
+
const subscriber = {
|
|
90
|
+
push(message) {
|
|
91
|
+
if (done) return;
|
|
92
|
+
if (waiting) {
|
|
93
|
+
const resolve = waiting;
|
|
94
|
+
waiting = null;
|
|
95
|
+
resolve({ value: message, done: false });
|
|
96
|
+
} else {
|
|
97
|
+
if (buffer.length >= maxBufferedMessages) {
|
|
98
|
+
unsubscribe();
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
buffer.push(message);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
complete() {
|
|
105
|
+
if (done) return;
|
|
106
|
+
closedAfterBuffer = true;
|
|
107
|
+
if (waiting) {
|
|
108
|
+
const resolve = waiting;
|
|
109
|
+
waiting = null;
|
|
110
|
+
if (buffer.length > 0) {
|
|
111
|
+
resolve({ value: buffer.shift(), done: false });
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
done = true;
|
|
115
|
+
resolve({ value: void 0, done: true });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
if (!closedAtSubscribe) {
|
|
120
|
+
state.subscribers.add(subscriber);
|
|
121
|
+
} else {
|
|
122
|
+
scheduleCleanup(channel, state);
|
|
123
|
+
}
|
|
124
|
+
unsubscribe = function unsubscribeImpl() {
|
|
125
|
+
if (!done) {
|
|
126
|
+
done = true;
|
|
127
|
+
state.subscribers.delete(subscriber);
|
|
128
|
+
if (state.subscribers.size === 0) {
|
|
129
|
+
scheduleCleanup(channel, state);
|
|
130
|
+
}
|
|
131
|
+
if (waiting) {
|
|
132
|
+
const resolve = waiting;
|
|
133
|
+
waiting = null;
|
|
134
|
+
resolve({ value: void 0, done: true });
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
const iterator = {
|
|
139
|
+
next() {
|
|
140
|
+
if (buffer.length > 0) {
|
|
141
|
+
return Promise.resolve({
|
|
142
|
+
value: buffer.shift(),
|
|
143
|
+
done: false
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
if (done || closedAfterBuffer) {
|
|
147
|
+
return Promise.resolve({
|
|
148
|
+
value: void 0,
|
|
149
|
+
done: true
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
return new Promise((resolve) => {
|
|
153
|
+
waiting = resolve;
|
|
154
|
+
});
|
|
155
|
+
},
|
|
156
|
+
return() {
|
|
157
|
+
unsubscribe();
|
|
158
|
+
return Promise.resolve({ value: void 0, done: true });
|
|
159
|
+
},
|
|
160
|
+
[Symbol.asyncIterator]() {
|
|
161
|
+
return this;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
return {
|
|
165
|
+
[Symbol.asyncIterator]() {
|
|
166
|
+
return iterator;
|
|
167
|
+
},
|
|
168
|
+
unsubscribe
|
|
169
|
+
};
|
|
170
|
+
},
|
|
171
|
+
close(channel, finalEvent) {
|
|
172
|
+
const state = getOrCreateChannel(channel);
|
|
173
|
+
state.closed = true;
|
|
174
|
+
if (finalEvent) {
|
|
175
|
+
state.seq++;
|
|
176
|
+
const message = {
|
|
177
|
+
channel,
|
|
178
|
+
type: finalEvent.type,
|
|
179
|
+
data: finalEvent.data,
|
|
180
|
+
seq: state.seq
|
|
181
|
+
};
|
|
182
|
+
appendToHistory(state, message);
|
|
183
|
+
for (const sub of state.subscribers) {
|
|
184
|
+
sub.push(message);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
for (const sub of state.subscribers) {
|
|
188
|
+
sub.complete();
|
|
189
|
+
}
|
|
190
|
+
state.subscribers.clear();
|
|
191
|
+
scheduleCleanup(channel, state);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export {
|
|
197
|
+
createEventBus
|
|
198
|
+
};
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sleep
|
|
3
|
+
} from "./chunk-SZ2XBPTW.js";
|
|
4
|
+
|
|
5
|
+
// src/dispatch/executor.ts
|
|
6
|
+
function ensureNonEmpty(input, label) {
|
|
7
|
+
const trimmed = input.trim();
|
|
8
|
+
if (!trimmed) {
|
|
9
|
+
throw new Error(`${label} must not be empty`);
|
|
10
|
+
}
|
|
11
|
+
return trimmed;
|
|
12
|
+
}
|
|
13
|
+
function createTargetIndex(targets) {
|
|
14
|
+
return new Map(targets.map((target) => [target.name, target]));
|
|
15
|
+
}
|
|
16
|
+
function requireTarget(targets, name) {
|
|
17
|
+
const target = targets.get(name);
|
|
18
|
+
if (!target) {
|
|
19
|
+
throw new Error(
|
|
20
|
+
`Unknown dispatch target "${name}". Available: ${[...targets.keys()].join(", ")}`
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
return target;
|
|
24
|
+
}
|
|
25
|
+
function defaultTaskRecord(input, targetName, startedAt, dispatchId, startResult) {
|
|
26
|
+
return {
|
|
27
|
+
id: dispatchId,
|
|
28
|
+
targetType: targetName,
|
|
29
|
+
title: input.task.title,
|
|
30
|
+
brief: input.prompt,
|
|
31
|
+
status: "running",
|
|
32
|
+
createdAt: startedAt,
|
|
33
|
+
updatedAt: startedAt,
|
|
34
|
+
parentSessionId: input.parentSessionId,
|
|
35
|
+
sessionId: startResult.sessionId ?? input.runtime.member.sessionId,
|
|
36
|
+
executionId: startResult.executionId ?? input.task.runId ?? dispatchId,
|
|
37
|
+
redirectCount: 0
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function defaultExternalControlRecord(task, runtime, targetName, startedAt, dispatchId) {
|
|
41
|
+
return {
|
|
42
|
+
id: dispatchId,
|
|
43
|
+
targetType: targetName,
|
|
44
|
+
title: task.title,
|
|
45
|
+
brief: task.prompt,
|
|
46
|
+
status: "running",
|
|
47
|
+
createdAt: task.createdAt || startedAt,
|
|
48
|
+
updatedAt: task.updatedAt || startedAt,
|
|
49
|
+
parentSessionId: runtime.member.sessionId,
|
|
50
|
+
sessionId: runtime.member.sessionId,
|
|
51
|
+
executionId: task.runId ?? dispatchId,
|
|
52
|
+
redirectCount: 0
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function mergeInspection(record, inspection, fallbackNow) {
|
|
56
|
+
if (!inspection) {
|
|
57
|
+
return record;
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
...record,
|
|
61
|
+
...inspection.status ? { status: inspection.status } : {},
|
|
62
|
+
...inspection.sessionId ? { sessionId: inspection.sessionId } : {},
|
|
63
|
+
...inspection.executionId ? { executionId: inspection.executionId } : {},
|
|
64
|
+
updatedAt: inspection.updatedAt ?? fallbackNow,
|
|
65
|
+
...inspection.result ? { result: inspection.result } : {},
|
|
66
|
+
...inspection.error ? { error: inspection.error } : {}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function toTaskResult(result) {
|
|
70
|
+
return {
|
|
71
|
+
response: result?.response ?? "",
|
|
72
|
+
usage: result?.usage,
|
|
73
|
+
toolCalls: result?.toolCalls
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async function cancelBestEffort(target, record, reason) {
|
|
77
|
+
await target.cancel({ record, reason }).catch(() => {
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function toInspection(record) {
|
|
81
|
+
if (!record) {
|
|
82
|
+
return void 0;
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
status: record.status,
|
|
86
|
+
sessionId: record.sessionId,
|
|
87
|
+
executionId: record.executionId,
|
|
88
|
+
updatedAt: record.updatedAt,
|
|
89
|
+
result: record.result,
|
|
90
|
+
error: record.error
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function resolveRuntimeRecordId(record) {
|
|
94
|
+
return record.executionId ?? record.id;
|
|
95
|
+
}
|
|
96
|
+
function createRuntimeDispatchTargets(options) {
|
|
97
|
+
return options.runtime.describeTargets().filter((target) => options.filter?.(target) ?? true).map((target) => ({
|
|
98
|
+
name: target.name,
|
|
99
|
+
description: target.description,
|
|
100
|
+
async start(input) {
|
|
101
|
+
const record = await options.runtime.start({
|
|
102
|
+
targetType: target.name,
|
|
103
|
+
brief: input.brief,
|
|
104
|
+
title: input.title,
|
|
105
|
+
parentSessionId: input.parentSessionId
|
|
106
|
+
});
|
|
107
|
+
return {
|
|
108
|
+
sessionId: record.sessionId,
|
|
109
|
+
executionId: record.id
|
|
110
|
+
};
|
|
111
|
+
},
|
|
112
|
+
async redirect(input) {
|
|
113
|
+
await options.runtime.redirect(
|
|
114
|
+
resolveRuntimeRecordId(input.record),
|
|
115
|
+
input.message
|
|
116
|
+
);
|
|
117
|
+
},
|
|
118
|
+
async cancel(input) {
|
|
119
|
+
await options.runtime.cancel(
|
|
120
|
+
resolveRuntimeRecordId(input.record),
|
|
121
|
+
input.reason
|
|
122
|
+
);
|
|
123
|
+
},
|
|
124
|
+
async check(input) {
|
|
125
|
+
const record = await options.runtime.check(
|
|
126
|
+
resolveRuntimeRecordId(input.record),
|
|
127
|
+
{ waitMs: 0 }
|
|
128
|
+
);
|
|
129
|
+
return toInspection(record);
|
|
130
|
+
}
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
function createDispatchTaskExecutor(options) {
|
|
134
|
+
const targets = createTargetIndex(options.targets);
|
|
135
|
+
const timeoutMs = options.timeoutMs ?? 6e5;
|
|
136
|
+
const pollIntervalMs = options.pollIntervalMs ?? 1e3;
|
|
137
|
+
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
138
|
+
return async (input) => {
|
|
139
|
+
const targetName = options.resolveTargetName?.(input) ?? input.runtime.member.role;
|
|
140
|
+
const target = requireTarget(targets, ensureNonEmpty(targetName, "targetName"));
|
|
141
|
+
const startedAt = now();
|
|
142
|
+
const dispatchId = input.task.runId ?? input.task.id;
|
|
143
|
+
const startResult = await target.start({
|
|
144
|
+
id: dispatchId,
|
|
145
|
+
brief: input.prompt,
|
|
146
|
+
title: input.task.title,
|
|
147
|
+
parentSessionId: input.parentSessionId,
|
|
148
|
+
sessionId: input.runtime.member.sessionId
|
|
149
|
+
});
|
|
150
|
+
let record = options.createRecord?.({
|
|
151
|
+
taskInput: input,
|
|
152
|
+
target,
|
|
153
|
+
dispatchId,
|
|
154
|
+
startedAt,
|
|
155
|
+
startResult
|
|
156
|
+
}) ?? defaultTaskRecord(
|
|
157
|
+
input,
|
|
158
|
+
target.name,
|
|
159
|
+
startedAt,
|
|
160
|
+
dispatchId,
|
|
161
|
+
startResult
|
|
162
|
+
);
|
|
163
|
+
const deadline = Date.now() + timeoutMs;
|
|
164
|
+
while (Date.now() < deadline) {
|
|
165
|
+
if (input.abort?.aborted) {
|
|
166
|
+
await cancelBestEffort(
|
|
167
|
+
target,
|
|
168
|
+
record,
|
|
169
|
+
String(input.abort.reason ?? "Aborted by coordinator")
|
|
170
|
+
);
|
|
171
|
+
throw new Error(String(input.abort.reason ?? "Aborted by coordinator"));
|
|
172
|
+
}
|
|
173
|
+
if (!target.check) {
|
|
174
|
+
throw new Error(
|
|
175
|
+
`Dispatch target "${target.name}" does not support status checks.`
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
const inspection = await target.check({ record });
|
|
179
|
+
record = mergeInspection(record, inspection, now());
|
|
180
|
+
if (record.status === "completed") {
|
|
181
|
+
return toTaskResult(record.result);
|
|
182
|
+
}
|
|
183
|
+
if (record.status === "failed") {
|
|
184
|
+
throw new Error(
|
|
185
|
+
record.error ?? `Dispatch "${dispatchId}" failed on target "${target.name}".`
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
if (record.status === "cancelled") {
|
|
189
|
+
throw new Error(
|
|
190
|
+
record.error ?? `Dispatch "${dispatchId}" was cancelled on target "${target.name}".`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
await sleep(pollIntervalMs);
|
|
194
|
+
}
|
|
195
|
+
throw new Error(
|
|
196
|
+
`Dispatch "${dispatchId}" on target "${target.name}" timed out after ${timeoutMs}ms.`
|
|
197
|
+
);
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
function createCompositeDispatchTaskExecutor(options) {
|
|
201
|
+
return async (input) => {
|
|
202
|
+
const matched = options.routes.find((route) => route.matches(input));
|
|
203
|
+
if (matched) {
|
|
204
|
+
return matched.executor(input);
|
|
205
|
+
}
|
|
206
|
+
if (options.fallback) {
|
|
207
|
+
return options.fallback(input);
|
|
208
|
+
}
|
|
209
|
+
const result = await input.runtime.agent.run({
|
|
210
|
+
parentSessionId: input.parentSessionId,
|
|
211
|
+
message: input.prompt,
|
|
212
|
+
title: input.task.title,
|
|
213
|
+
abort: input.abort
|
|
214
|
+
});
|
|
215
|
+
return {
|
|
216
|
+
response: result.response,
|
|
217
|
+
usage: result.usage,
|
|
218
|
+
toolCalls: result.toolCalls
|
|
219
|
+
};
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function createRuntimeDispatchExecutor(options) {
|
|
223
|
+
return createDispatchTaskExecutor({
|
|
224
|
+
targets: createRuntimeDispatchTargets({
|
|
225
|
+
runtime: options.runtime,
|
|
226
|
+
filter: options.filter
|
|
227
|
+
}),
|
|
228
|
+
timeoutMs: options.timeoutMs,
|
|
229
|
+
pollIntervalMs: options.pollIntervalMs,
|
|
230
|
+
now: options.now,
|
|
231
|
+
resolveTargetName: options.resolveTargetName,
|
|
232
|
+
createRecord: options.createRecord
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
function createDispatchExternalTaskControl(options) {
|
|
236
|
+
const targets = createTargetIndex(options.targets);
|
|
237
|
+
const now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
238
|
+
function resolveRecord(task, runtime) {
|
|
239
|
+
const targetName = options.resolveTargetName?.({ task, runtime }) ?? runtime.role.name;
|
|
240
|
+
const target = requireTarget(targets, ensureNonEmpty(targetName, "targetName"));
|
|
241
|
+
const dispatchId = task.runId ?? task.id;
|
|
242
|
+
const startedAt = now();
|
|
243
|
+
const record = options.createRecord?.({
|
|
244
|
+
task,
|
|
245
|
+
runtime,
|
|
246
|
+
target,
|
|
247
|
+
dispatchId,
|
|
248
|
+
startedAt
|
|
249
|
+
}) ?? defaultExternalControlRecord(
|
|
250
|
+
task,
|
|
251
|
+
runtime,
|
|
252
|
+
target.name,
|
|
253
|
+
startedAt,
|
|
254
|
+
dispatchId
|
|
255
|
+
);
|
|
256
|
+
return { target, record };
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
async abortTask({ task, runtime, reason }) {
|
|
260
|
+
const { target, record } = resolveRecord(task, runtime);
|
|
261
|
+
await target.cancel({ record, reason });
|
|
262
|
+
},
|
|
263
|
+
async guideTask({ task, runtime, message }) {
|
|
264
|
+
const { target, record } = resolveRecord(task, runtime);
|
|
265
|
+
await target.redirect({
|
|
266
|
+
record,
|
|
267
|
+
message: ensureNonEmpty(message, "message")
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export {
|
|
274
|
+
ensureNonEmpty,
|
|
275
|
+
mergeInspection,
|
|
276
|
+
createRuntimeDispatchTargets,
|
|
277
|
+
createDispatchTaskExecutor,
|
|
278
|
+
createCompositeDispatchTaskExecutor,
|
|
279
|
+
createRuntimeDispatchExecutor,
|
|
280
|
+
createDispatchExternalTaskControl
|
|
281
|
+
};
|