clay-server 3.3.2-beta.3 → 3.4.0-beta.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.
- package/lib/project-file-watch.js +77 -16
- package/lib/public/css/input.css +4 -0
- package/lib/public/css/mates.css +1 -0
- package/lib/public/gemini-avatar.svg +11 -0
- package/lib/public/index.html +8 -0
- package/lib/public/modules/app-panels.js +13 -1
- package/lib/public/modules/app-rendering.js +7 -1
- package/lib/public/modules/mate-sidebar.js +9 -3
- package/lib/public/modules/sidebar-mates.js +7 -1
- package/lib/public/modules/tools.js +7 -1
- package/lib/public/opencode-avatar.svg +4 -0
- package/lib/sdk-bridge.js +18 -2
- package/lib/yoke/acp-agent-profiles.js +188 -0
- package/lib/yoke/acp-driver-runtime.js +50 -0
- package/lib/yoke/acp-event-normalizer.js +179 -0
- package/lib/yoke/acp-process-manager.js +264 -0
- package/lib/yoke/acp-query-handle.js +487 -0
- package/lib/yoke/adapters/acp.js +317 -0
- package/lib/yoke/adapters/gemini.js +7 -0
- package/lib/yoke/adapters/kiro.js +4 -4
- package/lib/yoke/adapters/opencode.js +7 -0
- package/lib/yoke/index.js +45 -11
- package/lib/yoke/interface.js +2 -0
- package/lib/yoke/kiro-acp-server.js +30 -276
- package/lib/yoke/vendor-registry.js +22 -0
- package/package.json +1 -1
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
// Shared ACP Query Handle
|
|
2
|
+
// -----------------------
|
|
3
|
+
// Implements the YOKE QueryHandle contract with standard ACP session methods.
|
|
4
|
+
|
|
5
|
+
var normalizer = require("./acp-event-normalizer");
|
|
6
|
+
var driverRuntime = require("./acp-driver-runtime");
|
|
7
|
+
|
|
8
|
+
var uuidCounter = 0;
|
|
9
|
+
function generateUuid(vendor) {
|
|
10
|
+
uuidCounter++;
|
|
11
|
+
return (vendor || "acp") + "-" + Date.now().toString(36) + "-" + uuidCounter.toString(36);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function isAuthError(value) {
|
|
15
|
+
return /not logged in|sign in|log ?in|authenticate|authentication|credentials|unauthorized|forbidden|\b401\b/i.test(String(value || ""));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isApproved(decision) {
|
|
19
|
+
return decision === true || (decision && decision.behavior === "allow");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function createAcpQueryHandle(acp, queryOpts) {
|
|
23
|
+
queryOpts = queryOpts || {};
|
|
24
|
+
var vendor = queryOpts.vendor || "acp";
|
|
25
|
+
var driver = queryOpts.driver || null;
|
|
26
|
+
var abortController = queryOpts.abortController;
|
|
27
|
+
var canUseTool = queryOpts.canUseTool || null;
|
|
28
|
+
var state = normalizer.createEventState({ vendor: vendor, contextWindow: queryOpts.contextWindow });
|
|
29
|
+
state.sessionId = queryOpts.resumeSessionId || null;
|
|
30
|
+
state.model = queryOpts.model || "auto";
|
|
31
|
+
state.done = false;
|
|
32
|
+
state.aborted = false;
|
|
33
|
+
state.loadingSession = false;
|
|
34
|
+
state.toolPolicy = "ask";
|
|
35
|
+
|
|
36
|
+
var eventBuffer = [];
|
|
37
|
+
var eventWaiting = null;
|
|
38
|
+
var iteratorDone = false;
|
|
39
|
+
var messageQueue = [];
|
|
40
|
+
var messageWaiting = null;
|
|
41
|
+
var messageQueueEnded = false;
|
|
42
|
+
var loopStarted = false;
|
|
43
|
+
var finishedNotified = false;
|
|
44
|
+
|
|
45
|
+
function driverContext(extra) {
|
|
46
|
+
return Object.assign({
|
|
47
|
+
vendor: vendor,
|
|
48
|
+
driver: driver,
|
|
49
|
+
acp: acp,
|
|
50
|
+
state: state,
|
|
51
|
+
queryOpts: queryOpts,
|
|
52
|
+
}, extra || {});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function notifyFinished() {
|
|
56
|
+
if (finishedNotified) return;
|
|
57
|
+
finishedNotified = true;
|
|
58
|
+
if (typeof queryOpts.onFinished === "function") {
|
|
59
|
+
try { queryOpts.onFinished(); } catch (e) {
|
|
60
|
+
console.error("[yoke/" + vendor + "] onFinished error:", e.message || e);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function pushEvent(event) {
|
|
66
|
+
if (iteratorDone) return;
|
|
67
|
+
if (eventWaiting) {
|
|
68
|
+
var resolve = eventWaiting;
|
|
69
|
+
eventWaiting = null;
|
|
70
|
+
resolve({ value: event, done: false });
|
|
71
|
+
} else {
|
|
72
|
+
eventBuffer.push(event);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function endIterator() {
|
|
77
|
+
if (iteratorDone) return;
|
|
78
|
+
iteratorDone = true;
|
|
79
|
+
if (eventWaiting) {
|
|
80
|
+
var resolve = eventWaiting;
|
|
81
|
+
eventWaiting = null;
|
|
82
|
+
resolve({ value: undefined, done: true });
|
|
83
|
+
}
|
|
84
|
+
notifyFinished();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function isCancelled() {
|
|
88
|
+
return state.aborted || !!(abortController && abortController.signal && abortController.signal.aborted);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function queueMessage(message) {
|
|
92
|
+
if (messageQueueEnded) return false;
|
|
93
|
+
if (messageWaiting) {
|
|
94
|
+
var resolve = messageWaiting;
|
|
95
|
+
messageWaiting = null;
|
|
96
|
+
resolve(message);
|
|
97
|
+
} else {
|
|
98
|
+
messageQueue.push(message);
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function waitForMessage() {
|
|
104
|
+
if (messageQueue.length) return Promise.resolve(messageQueue.shift());
|
|
105
|
+
if (messageQueueEnded) return Promise.resolve(null);
|
|
106
|
+
return new Promise(function(resolve) { messageWaiting = resolve; });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function findPermissionOption(options, kinds) {
|
|
110
|
+
for (var i = 0; i < kinds.length; i++) {
|
|
111
|
+
for (var j = 0; j < options.length; j++) {
|
|
112
|
+
if (options[j].kind === kinds[i]) return options[j].optionId;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function handlePermission(msg) {
|
|
119
|
+
var params = msg.params || {};
|
|
120
|
+
var toolCall = params.toolCall || {};
|
|
121
|
+
var options = params.options || [];
|
|
122
|
+
var allowId = findPermissionOption(options, ["allow_once", "allow_always"]);
|
|
123
|
+
var rejectId = findPermissionOption(options, ["reject_once", "reject_always"]);
|
|
124
|
+
var meta = (toolCall.toolCallId && state.toolMeta[toolCall.toolCallId]) || {};
|
|
125
|
+
|
|
126
|
+
if (isCancelled()) {
|
|
127
|
+
acp.respond(msg.id, { outcome: { outcome: "cancelled" } });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function respond(allowed) {
|
|
132
|
+
var optionId = allowed ? allowId : rejectId;
|
|
133
|
+
if (!optionId) {
|
|
134
|
+
acp.respond(msg.id, { outcome: { outcome: "cancelled" } });
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
var defaultResult = { outcome: { outcome: "selected", optionId: optionId } };
|
|
138
|
+
var result = driverRuntime.call(driver, "buildPermissionResponse", driverContext({
|
|
139
|
+
message: msg,
|
|
140
|
+
allowed: allowed,
|
|
141
|
+
optionId: optionId,
|
|
142
|
+
}), function() { return defaultResult; });
|
|
143
|
+
acp.respond(msg.id, result || defaultResult);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (state.toolPolicy === "allow-all") {
|
|
147
|
+
respond(true);
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
if (!canUseTool) {
|
|
151
|
+
respond(false);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
var toolName = normalizer.toolNameForKind(toolCall.kind || meta.kind, toolCall.title || meta.title);
|
|
156
|
+
var input = toolCall.rawInput || meta.rawInput || { title: toolCall.title || meta.title };
|
|
157
|
+
var permission = driverRuntime.call(driver, "mapPermissionRequest", driverContext({
|
|
158
|
+
message: msg,
|
|
159
|
+
toolName: toolName,
|
|
160
|
+
input: input,
|
|
161
|
+
options: options,
|
|
162
|
+
}), function() { return { toolName: toolName, input: input }; }) || { toolName: toolName, input: input };
|
|
163
|
+
Promise.resolve(canUseTool(permission.toolName || toolName, permission.input || input, {})).then(function(decision) {
|
|
164
|
+
respond(isApproved(decision));
|
|
165
|
+
}).catch(function(err) {
|
|
166
|
+
console.error("[yoke/" + vendor + "] canUseTool error:", err.message || err);
|
|
167
|
+
respond(false);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function handleServerEvent(msg) {
|
|
172
|
+
if (msg.method === "session/request_permission") {
|
|
173
|
+
handlePermission(msg);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
if (msg.method !== "session/update" || isCancelled() || state.loadingSession) return;
|
|
177
|
+
var update = msg.params && msg.params.update;
|
|
178
|
+
var events = driverRuntime.normalizeEvents(driver, driverContext({ message: msg, update: update }), function() {
|
|
179
|
+
return normalizer.normalizeAcpUpdate(update, state);
|
|
180
|
+
});
|
|
181
|
+
for (var i = 0; i < events.length; i++) pushEvent(events[i]);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function configOptionFor(category, fallbackId) {
|
|
185
|
+
for (var i = 0; i < state.configOptions.length; i++) {
|
|
186
|
+
var option = state.configOptions[i];
|
|
187
|
+
if (option.category === category || option.id === fallbackId) return option;
|
|
188
|
+
}
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function setConfig(category, fallbackId, value) {
|
|
193
|
+
if (!state.sessionId || !acp.started || value === undefined || value === null) return Promise.resolve();
|
|
194
|
+
var option = configOptionFor(category, fallbackId);
|
|
195
|
+
if (option) {
|
|
196
|
+
return acp.send("session/set_config_option", {
|
|
197
|
+
sessionId: state.sessionId,
|
|
198
|
+
configId: option.id,
|
|
199
|
+
value: value,
|
|
200
|
+
}, 15000).then(function(result) {
|
|
201
|
+
if (result && Array.isArray(result.configOptions)) state.configOptions = result.configOptions;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
if (category === "mode") {
|
|
205
|
+
return acp.send("session/set_mode", { sessionId: state.sessionId, modeId: value }, 15000);
|
|
206
|
+
}
|
|
207
|
+
return Promise.reject(new Error("ACP session does not expose configuration option: " + fallbackId));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function safeModeValue(values) {
|
|
211
|
+
var preferred = /^(ask|default|manual|supervised|plan|read.?only)$/i;
|
|
212
|
+
for (var i = 0; i < values.length; i++) {
|
|
213
|
+
var value = typeof values[i] === "string" ? values[i] : values[i] && (values[i].value || values[i].id);
|
|
214
|
+
if (value && preferred.test(value)) return value;
|
|
215
|
+
}
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function ensureDefaultSafePermissionMode() {
|
|
220
|
+
var option = configOptionFor("mode", "mode");
|
|
221
|
+
if (option) {
|
|
222
|
+
if (safeModeValue([option.currentValue])) return Promise.resolve();
|
|
223
|
+
var safeValue = safeModeValue(option.options || []);
|
|
224
|
+
if (!safeValue) return Promise.reject(new Error("ACP agent started in an unsafe permission mode and exposed no supervised mode"));
|
|
225
|
+
return setConfig("mode", option.id, safeValue);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
var modes = state.modes;
|
|
229
|
+
if (modes) {
|
|
230
|
+
if (safeModeValue([modes.currentModeId])) return Promise.resolve();
|
|
231
|
+
var safeMode = safeModeValue(modes.availableModes || []);
|
|
232
|
+
if (!safeMode) return Promise.reject(new Error("ACP agent started in an unsafe permission mode and exposed no supervised mode"));
|
|
233
|
+
return acp.send("session/set_mode", { sessionId: state.sessionId, modeId: safeMode }, 15000);
|
|
234
|
+
}
|
|
235
|
+
if (driver && driver.permissionModeGuaranteed === true) return Promise.resolve();
|
|
236
|
+
return Promise.reject(new Error("ACP agent did not expose a verifiable supervised permission mode"));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function ensureSafePermissionMode() {
|
|
240
|
+
return driverRuntime.callAsync(driver, "ensureSafePermissionMode", driverContext(), ensureDefaultSafePermissionMode);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function prependSystemPrompt(message) {
|
|
244
|
+
var parts = [queryOpts.systemPrompt, queryOpts.appendSystemPrompt].filter(function(part) { return !!part; });
|
|
245
|
+
var systemPrompt = parts.join("\n\n");
|
|
246
|
+
if (!systemPrompt) return message;
|
|
247
|
+
if (typeof message === "string") return systemPrompt + "\n\n" + message;
|
|
248
|
+
if (!Array.isArray(message)) return message;
|
|
249
|
+
var cloned = message.slice();
|
|
250
|
+
for (var i = 0; i < cloned.length; i++) {
|
|
251
|
+
if (cloned[i] && cloned[i].type === "text") {
|
|
252
|
+
cloned[i] = Object.assign({}, cloned[i], { text: systemPrompt + "\n\n" + (cloned[i].text || "") });
|
|
253
|
+
return cloned;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
cloned.unshift({ type: "text", text: systemPrompt });
|
|
257
|
+
return cloned;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function asPrompt(message) {
|
|
261
|
+
if (typeof message === "string") return [{ type: "text", text: message }];
|
|
262
|
+
return Array.isArray(message) ? message : [];
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function emitResult() {
|
|
266
|
+
var modelUsage = {};
|
|
267
|
+
modelUsage[state.model] = { contextWindow: state.contextWindow || null };
|
|
268
|
+
var resultEvent = {
|
|
269
|
+
yokeType: "result",
|
|
270
|
+
uuid: generateUuid(vendor),
|
|
271
|
+
messageType: "assistant",
|
|
272
|
+
cost: null,
|
|
273
|
+
duration: null,
|
|
274
|
+
usage: state.lastInputTokens == null ? null : {
|
|
275
|
+
input_tokens: state.lastInputTokens,
|
|
276
|
+
output_tokens: 0,
|
|
277
|
+
cache_read_input_tokens: 0,
|
|
278
|
+
cache_creation_input_tokens: 0,
|
|
279
|
+
},
|
|
280
|
+
modelUsage: modelUsage,
|
|
281
|
+
sessionId: state.sessionId,
|
|
282
|
+
lastStreamInputTokens: state.lastInputTokens,
|
|
283
|
+
};
|
|
284
|
+
resultEvent = driverRuntime.call(driver, "buildResult", driverContext({ event: resultEvent }), function() { return resultEvent; }) || resultEvent;
|
|
285
|
+
pushEvent(resultEvent);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function buildSessionParams(operation, base) {
|
|
289
|
+
return driverRuntime.buildParams(driver, "buildSessionParams", driverContext({ operation: operation }), base);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function setModel(model) {
|
|
293
|
+
return driverRuntime.callAsync(driver, "setModel", driverContext({ model: model }), function() {
|
|
294
|
+
return setConfig("model", "model", model);
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function setEffort(effort) {
|
|
299
|
+
return driverRuntime.callAsync(driver, "setEffort", driverContext({ effort: effort }), function() {
|
|
300
|
+
return setConfig("thought_level", "thought_level", effort);
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function applySessionResult(result) {
|
|
305
|
+
result = result || {};
|
|
306
|
+
if (result.sessionId) state.sessionId = result.sessionId;
|
|
307
|
+
if (Array.isArray(result.configOptions)) state.configOptions = result.configOptions;
|
|
308
|
+
if (result.modes) state.modes = result.modes;
|
|
309
|
+
if (typeof queryOpts.onSessionReady === "function") queryOpts.onSessionReady(result);
|
|
310
|
+
return result;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async function openDefaultSession(handlerEntry) {
|
|
314
|
+
if (state.sessionId && queryOpts.canResumeSession) {
|
|
315
|
+
handlerEntry.sessionId = state.sessionId;
|
|
316
|
+
var resumed = await acp.send("session/resume", buildSessionParams("resume", {
|
|
317
|
+
sessionId: state.sessionId,
|
|
318
|
+
cwd: queryOpts.cwd,
|
|
319
|
+
mcpServers: queryOpts.mcpServers || [],
|
|
320
|
+
}), 60000);
|
|
321
|
+
return resumed;
|
|
322
|
+
}
|
|
323
|
+
if (state.sessionId && queryOpts.canLoadSession) {
|
|
324
|
+
handlerEntry.sessionId = state.sessionId;
|
|
325
|
+
state.loadingSession = true;
|
|
326
|
+
try {
|
|
327
|
+
var loaded = await acp.send("session/load", buildSessionParams("load", {
|
|
328
|
+
sessionId: state.sessionId,
|
|
329
|
+
cwd: queryOpts.cwd,
|
|
330
|
+
mcpServers: queryOpts.mcpServers || [],
|
|
331
|
+
}), 60000);
|
|
332
|
+
return loaded;
|
|
333
|
+
} finally {
|
|
334
|
+
state.loadingSession = false;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
state.sessionId = null;
|
|
339
|
+
var result = await acp.send("session/new", buildSessionParams("new", {
|
|
340
|
+
cwd: queryOpts.cwd,
|
|
341
|
+
mcpServers: queryOpts.mcpServers || [],
|
|
342
|
+
}), 60000);
|
|
343
|
+
return result;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function openSession(handlerEntry) {
|
|
347
|
+
return driverRuntime.callAsync(driver, "openSession", driverContext({ handlerEntry: handlerEntry }), function() {
|
|
348
|
+
return openDefaultSession(handlerEntry);
|
|
349
|
+
}).then(applySessionResult);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function prompt(message) {
|
|
353
|
+
return driverRuntime.callAsync(driver, "prompt", driverContext({ message: message }), function() {
|
|
354
|
+
var params = driverRuntime.buildParams(driver, "buildPromptParams", driverContext({ message: message }), {
|
|
355
|
+
sessionId: state.sessionId,
|
|
356
|
+
prompt: asPrompt(message),
|
|
357
|
+
});
|
|
358
|
+
return acp.send("session/prompt", params, 30 * 60 * 1000);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async function runQueryLoop(initialMessage) {
|
|
363
|
+
var currentMessage = prependSystemPrompt(initialMessage);
|
|
364
|
+
var handlerEntry = acp.addHandler(handleServerEvent);
|
|
365
|
+
try {
|
|
366
|
+
var sessionResult = await openSession(handlerEntry);
|
|
367
|
+
handlerEntry.sessionId = state.sessionId;
|
|
368
|
+
await driverRuntime.callAsync(driver, "afterSessionOpen", driverContext({ sessionResult: sessionResult }), function() {});
|
|
369
|
+
await ensureSafePermissionMode();
|
|
370
|
+
if (state.model && state.model !== "auto") await setModel(state.model);
|
|
371
|
+
if (queryOpts.mode) await setConfig("mode", "mode", queryOpts.mode);
|
|
372
|
+
|
|
373
|
+
while (!isCancelled()) {
|
|
374
|
+
normalizer.resetTurnState(state);
|
|
375
|
+
pushEvent({ yokeType: "turn_start", uuid: generateUuid(vendor), messageType: "user" });
|
|
376
|
+
var result = await prompt(currentMessage);
|
|
377
|
+
var closing = normalizer.closeOpenBlocks(state);
|
|
378
|
+
for (var i = 0; i < closing.length; i++) pushEvent(closing[i]);
|
|
379
|
+
if (isCancelled() || (result && result.stopReason === "cancelled")) {
|
|
380
|
+
pushEvent({ yokeType: "interrupted" });
|
|
381
|
+
emitResult();
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
384
|
+
emitResult();
|
|
385
|
+
var next = await waitForMessage();
|
|
386
|
+
if (next === null) break;
|
|
387
|
+
currentMessage = next;
|
|
388
|
+
}
|
|
389
|
+
} catch (e) {
|
|
390
|
+
if (!isCancelled() && e.name !== "AbortError") {
|
|
391
|
+
var message = e.message || String(e);
|
|
392
|
+
var authError = driverRuntime.call(driver, "isAuthError", driverContext({ error: e, message: message }), function() { return isAuthError(message); });
|
|
393
|
+
pushEvent(authError
|
|
394
|
+
? { yokeType: "auth_required", vendor: vendor }
|
|
395
|
+
: { yokeType: "error", text: message });
|
|
396
|
+
}
|
|
397
|
+
} finally {
|
|
398
|
+
acp.removeHandler(handlerEntry);
|
|
399
|
+
state.done = true;
|
|
400
|
+
endIterator();
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
var handle = {
|
|
405
|
+
[Symbol.asyncIterator]: function() {
|
|
406
|
+
return {
|
|
407
|
+
next: function() {
|
|
408
|
+
if (eventBuffer.length) return Promise.resolve({ value: eventBuffer.shift(), done: false });
|
|
409
|
+
if (iteratorDone) return Promise.resolve({ value: undefined, done: true });
|
|
410
|
+
return new Promise(function(resolve) { eventWaiting = resolve; });
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
},
|
|
414
|
+
pushMessage: function(text, images) {
|
|
415
|
+
if (iteratorDone || state.done || messageQueueEnded) return false;
|
|
416
|
+
var content = [];
|
|
417
|
+
for (var i = 0; images && i < images.length; i++) {
|
|
418
|
+
if (images[i] && images[i].base64 && images[i].mimeType) {
|
|
419
|
+
content.push({ type: "image", data: images[i].base64, mimeType: images[i].mimeType });
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
content.push({ type: "text", text: text || "" });
|
|
423
|
+
var message = content.length === 1 ? content[0].text : content;
|
|
424
|
+
if (!loopStarted) {
|
|
425
|
+
loopStarted = true;
|
|
426
|
+
runQueryLoop(message);
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
return queueMessage(message);
|
|
430
|
+
},
|
|
431
|
+
setModel: function(model) {
|
|
432
|
+
return setModel(model).then(function() { state.model = model; });
|
|
433
|
+
},
|
|
434
|
+
setEffort: function(effort) {
|
|
435
|
+
return setEffort(effort);
|
|
436
|
+
},
|
|
437
|
+
setToolPolicy: function(policy) {
|
|
438
|
+
state.toolPolicy = policy === "allow-all" ? "allow-all" : "ask";
|
|
439
|
+
return Promise.resolve();
|
|
440
|
+
},
|
|
441
|
+
stopTask: function(taskId) {
|
|
442
|
+
return driverRuntime.callAsync(driver, "stopTask", driverContext({ taskId: taskId }), function() {});
|
|
443
|
+
},
|
|
444
|
+
getContextUsage: function() {
|
|
445
|
+
return driverRuntime.callAsync(driver, "getContextUsage", driverContext(), function() { return state.lastInputTokens == null ? null : {
|
|
446
|
+
input_tokens: state.lastInputTokens,
|
|
447
|
+
contextWindow: state.contextWindow,
|
|
448
|
+
}; });
|
|
449
|
+
},
|
|
450
|
+
abort: function() {
|
|
451
|
+
state.aborted = true;
|
|
452
|
+
driverRuntime.call(driver, "cancel", driverContext(), function() {
|
|
453
|
+
if (state.sessionId && acp.started) acp.notify("session/cancel", { sessionId: state.sessionId });
|
|
454
|
+
});
|
|
455
|
+
endIterator();
|
|
456
|
+
},
|
|
457
|
+
close: function() {
|
|
458
|
+
messageQueueEnded = true;
|
|
459
|
+
if (messageWaiting) {
|
|
460
|
+
var resolve = messageWaiting;
|
|
461
|
+
messageWaiting = null;
|
|
462
|
+
resolve(null);
|
|
463
|
+
}
|
|
464
|
+
endIterator();
|
|
465
|
+
},
|
|
466
|
+
endInput: function() {
|
|
467
|
+
messageQueueEnded = true;
|
|
468
|
+
if (messageWaiting) {
|
|
469
|
+
var resolve = messageWaiting;
|
|
470
|
+
messageWaiting = null;
|
|
471
|
+
resolve(null);
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
if (abortController && abortController.signal) {
|
|
477
|
+
abortController.signal.addEventListener("abort", function() {
|
|
478
|
+
if (!state.aborted) handle.abort();
|
|
479
|
+
}, { once: true });
|
|
480
|
+
}
|
|
481
|
+
return handle;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
module.exports = {
|
|
485
|
+
createAcpQueryHandle: createAcpQueryHandle,
|
|
486
|
+
isAuthError: isAuthError,
|
|
487
|
+
};
|