@wrongstack/acp 0.257.2 → 0.264.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/dist/agent.d.ts +60 -88
- package/dist/agent.js +402 -133
- package/dist/agent.js.map +1 -1
- package/dist/client.d.ts +2 -2
- package/dist/client.js +890 -114
- package/dist/client.js.map +1 -1
- package/dist/{index-DPMuJGqv.d.ts → index-BvPqJHhm.d.ts} +46 -14
- package/dist/index.d.ts +497 -3
- package/dist/index.js +1733 -326
- package/dist/index.js.map +1 -1
- package/dist/{stdio-transport-DoKRVjHz.d.ts → stdio-transport-CsFr8JzC.d.ts} +8 -1
- package/dist/tools-registry-BCf8evEG.d.ts +36 -0
- package/dist/wrongstack-acp-agent-Dv-A0bEm.d.ts +310 -0
- package/dist/wrongstack-acp-agent.d.ts +3 -0
- package/dist/wrongstack-acp-agent.js +492 -0
- package/dist/wrongstack-acp-agent.js.map +1 -0
- package/package.json +4 -3
package/dist/agent.js
CHANGED
|
@@ -205,182 +205,366 @@ function toolToPriority(tool) {
|
|
|
205
205
|
return "low";
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
+
// src/types/acp-v1.ts
|
|
209
|
+
var ACP_PROTOCOL_VERSION = 1;
|
|
210
|
+
|
|
208
211
|
// src/agent/protocol-handler.ts
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
function toWire(msg) {
|
|
213
|
+
return msg;
|
|
214
|
+
}
|
|
215
|
+
var WRONGSTACK_VERSION = "0.263.0";
|
|
216
|
+
var DEFAULT_MODE_ID = "code";
|
|
217
|
+
var DEFAULT_MODES = [
|
|
218
|
+
{
|
|
219
|
+
id: DEFAULT_MODE_ID,
|
|
220
|
+
name: "Code",
|
|
221
|
+
description: "Default agent mode for code-generation tasks."
|
|
222
|
+
}
|
|
215
223
|
];
|
|
216
224
|
var ACPProtocolHandler = class {
|
|
217
|
-
constructor(transport, registry, context) {
|
|
218
|
-
this.transport = transport;
|
|
219
|
-
this.registry = registry;
|
|
220
|
-
this.context = context;
|
|
221
|
-
}
|
|
222
225
|
transport;
|
|
223
|
-
|
|
224
|
-
|
|
226
|
+
defaultCwd;
|
|
227
|
+
runTurn;
|
|
228
|
+
onSessionNew;
|
|
229
|
+
modes;
|
|
230
|
+
configOptions;
|
|
231
|
+
agentName;
|
|
225
232
|
initialized = false;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}
|
|
233
|
+
sessions = /* @__PURE__ */ new Map();
|
|
234
|
+
nextId = 1;
|
|
235
|
+
constructor(opts) {
|
|
236
|
+
this.transport = opts.transport;
|
|
237
|
+
this.defaultCwd = opts.defaultCwd;
|
|
238
|
+
this.runTurn = opts.runTurn;
|
|
239
|
+
this.onSessionNew = opts.onSessionNew ?? (() => {
|
|
234
240
|
});
|
|
241
|
+
this.modes = opts.modes ?? DEFAULT_MODES;
|
|
242
|
+
this.configOptions = opts.configOptions ?? [];
|
|
243
|
+
this.agentName = opts.agentName ?? "wrongstack";
|
|
235
244
|
}
|
|
236
|
-
/**
|
|
245
|
+
/**
|
|
246
|
+
* Process one inbound message. Returns true if this was a terminal
|
|
247
|
+
* message (rare; reserved for future use by the server's own
|
|
248
|
+
* shutdown signal).
|
|
249
|
+
*/
|
|
237
250
|
async handleMessage(msg) {
|
|
238
|
-
if (msg
|
|
239
|
-
|
|
251
|
+
if (typeof msg !== "object" || msg === null) return false;
|
|
252
|
+
const m = msg;
|
|
253
|
+
if (m.id !== void 0 && (m.result !== void 0 || m.error !== void 0)) {
|
|
254
|
+
return false;
|
|
240
255
|
}
|
|
241
|
-
|
|
256
|
+
if (m.id !== void 0 && typeof m.method === "string") {
|
|
257
|
+
return this.handleRequest(m.id, m.method, m.params);
|
|
258
|
+
}
|
|
259
|
+
if (typeof m.method === "string") {
|
|
260
|
+
return this.handleNotification(m.method, m.params);
|
|
261
|
+
}
|
|
262
|
+
return false;
|
|
242
263
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
264
|
+
/** Abort all active turns and drop session state. */
|
|
265
|
+
close() {
|
|
266
|
+
for (const [, session] of this.sessions) {
|
|
267
|
+
session.abort.abort();
|
|
268
|
+
}
|
|
269
|
+
this.sessions.clear();
|
|
270
|
+
}
|
|
271
|
+
// ────────────────────────────────────────────────────────────────────
|
|
272
|
+
// Requests
|
|
273
|
+
// ────────────────────────────────────────────────────────────────────
|
|
274
|
+
async handleRequest(id, method, params) {
|
|
275
|
+
if (method !== "initialize" && !this.initialized) {
|
|
276
|
+
await this.sendError(id, -32e3, "Not initialized");
|
|
246
277
|
return false;
|
|
247
278
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
279
|
+
try {
|
|
280
|
+
switch (method) {
|
|
281
|
+
case "initialize":
|
|
282
|
+
return await this.handleInitialize(id, params);
|
|
283
|
+
case "authenticate":
|
|
284
|
+
return await this.handleAuthenticate(id, params);
|
|
285
|
+
case "session/new":
|
|
286
|
+
return await this.handleSessionNew(id, params);
|
|
287
|
+
case "session/load":
|
|
288
|
+
return await this.handleSessionLoad(id, params);
|
|
289
|
+
case "session/prompt":
|
|
290
|
+
return await this.handleSessionPrompt(id, params);
|
|
291
|
+
case "session/set_mode":
|
|
292
|
+
return await this.handleSetMode(id, params);
|
|
293
|
+
case "session/set_config_option":
|
|
294
|
+
return await this.handleSetConfigOption(id, params);
|
|
295
|
+
case "session/list":
|
|
296
|
+
return await this.handleSessionList(id);
|
|
297
|
+
default:
|
|
298
|
+
await this.sendError(id, -32601, `Unknown method: ${method}`);
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
} catch (err) {
|
|
302
|
+
const { code, message, data } = errorToJsonRpc(err);
|
|
303
|
+
await this.sendError(id, code, message, data);
|
|
304
|
+
return false;
|
|
269
305
|
}
|
|
270
306
|
}
|
|
271
|
-
async
|
|
272
|
-
|
|
273
|
-
|
|
307
|
+
async handleInitialize(id, params) {
|
|
308
|
+
const p = params ?? {};
|
|
309
|
+
const requested = typeof p.protocolVersion === "number" ? p.protocolVersion : 1;
|
|
310
|
+
if (requested !== ACP_PROTOCOL_VERSION) {
|
|
311
|
+
await this.sendError(
|
|
312
|
+
id,
|
|
313
|
+
-32e3,
|
|
314
|
+
`server speaks protocolVersion=${ACP_PROTOCOL_VERSION}, client requested ${requested}`
|
|
315
|
+
);
|
|
316
|
+
return false;
|
|
274
317
|
}
|
|
275
|
-
return false;
|
|
276
|
-
}
|
|
277
|
-
async handleInitialize(req, id) {
|
|
278
318
|
this.initialized = true;
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
319
|
+
await this.transport.send(toWire({
|
|
320
|
+
jsonrpc: "2.0",
|
|
321
|
+
id,
|
|
322
|
+
result: {
|
|
323
|
+
protocolVersion: ACP_PROTOCOL_VERSION,
|
|
324
|
+
agentCapabilities: {
|
|
325
|
+
loadSession: true,
|
|
326
|
+
promptCapabilities: {
|
|
327
|
+
image: false,
|
|
328
|
+
audio: false,
|
|
329
|
+
embeddedContext: true
|
|
330
|
+
}
|
|
331
|
+
},
|
|
332
|
+
agentInfo: {
|
|
333
|
+
name: this.agentName,
|
|
334
|
+
title: "WrongStack",
|
|
335
|
+
version: WRONGSTACK_VERSION
|
|
336
|
+
},
|
|
337
|
+
// Static options advertised at handshake. They are also
|
|
338
|
+
// re-sent on every `current_mode_update` / `config_option_update`
|
|
339
|
+
// notification so late-joining clients see them.
|
|
340
|
+
authMethods: [],
|
|
341
|
+
modes: this.modes,
|
|
342
|
+
configOptions: this.configOptions
|
|
343
|
+
}
|
|
344
|
+
}));
|
|
287
345
|
return false;
|
|
288
346
|
}
|
|
289
|
-
async
|
|
290
|
-
await this.transport.send({
|
|
347
|
+
async handleAuthenticate(id, _params) {
|
|
348
|
+
await this.transport.send(toWire({
|
|
349
|
+
jsonrpc: "2.0",
|
|
291
350
|
id,
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
});
|
|
351
|
+
result: { outcome: "unauthenticated" }
|
|
352
|
+
}));
|
|
295
353
|
return false;
|
|
296
354
|
}
|
|
297
|
-
async
|
|
298
|
-
const
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
355
|
+
async handleSessionNew(id, params) {
|
|
356
|
+
const p = params ?? {};
|
|
357
|
+
const cwd = typeof p.cwd === "string" ? p.cwd : this.defaultCwd;
|
|
358
|
+
const sessionId = `sess_${this.allocId()}`;
|
|
359
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
360
|
+
const state = {
|
|
361
|
+
id: sessionId,
|
|
362
|
+
cwd,
|
|
363
|
+
abort: new AbortController(),
|
|
364
|
+
modeId: DEFAULT_MODE_ID,
|
|
365
|
+
createdAt: now,
|
|
366
|
+
updatedAt: now
|
|
367
|
+
};
|
|
368
|
+
this.sessions.set(sessionId, state);
|
|
369
|
+
this.onSessionNew(state);
|
|
370
|
+
await this.sendNotification({
|
|
371
|
+
sessionId,
|
|
372
|
+
update: {
|
|
373
|
+
sessionUpdate: "current_mode_update",
|
|
374
|
+
modeId: this.modes[0]?.id ?? DEFAULT_MODE_ID
|
|
305
375
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
376
|
+
});
|
|
377
|
+
if (this.configOptions.length > 0) {
|
|
378
|
+
await this.sendNotification({
|
|
379
|
+
sessionId,
|
|
380
|
+
update: {
|
|
381
|
+
sessionUpdate: "config_option_update",
|
|
382
|
+
configOptions: [...this.configOptions]
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
await this.transport.send(toWire({
|
|
387
|
+
jsonrpc: "2.0",
|
|
388
|
+
id,
|
|
389
|
+
result: {
|
|
390
|
+
sessionId,
|
|
391
|
+
modes: this.modes,
|
|
392
|
+
configOptions: this.configOptions
|
|
393
|
+
}
|
|
394
|
+
}));
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
async handleSessionLoad(id, params) {
|
|
398
|
+
return this.handleSessionNew(id, params);
|
|
399
|
+
}
|
|
400
|
+
async handleSessionPrompt(id, params) {
|
|
401
|
+
const p = params ?? {};
|
|
402
|
+
const sessionId = typeof p.sessionId === "string" ? p.sessionId : null;
|
|
403
|
+
if (!sessionId || !this.sessions.has(sessionId)) {
|
|
404
|
+
await this.sendError(id, -32e3, "unknown or missing sessionId");
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
if (!Array.isArray(p.prompt)) {
|
|
408
|
+
await this.sendError(id, -32602, "prompt must be an array of content blocks");
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
const session = this.sessions.get(sessionId);
|
|
412
|
+
if (session.abort.signal.aborted) {
|
|
413
|
+
session.abort = new AbortController();
|
|
414
|
+
}
|
|
415
|
+
const turnSignal = new AbortController();
|
|
416
|
+
const onCancel = () => turnSignal.abort();
|
|
417
|
+
session.abort.signal.addEventListener("abort", onCancel, { once: true });
|
|
418
|
+
let result;
|
|
315
419
|
try {
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
420
|
+
result = await this.runTurn(
|
|
421
|
+
{ sessionId, prompt: p.prompt, signal: turnSignal.signal },
|
|
422
|
+
(update) => this.sendNotification({ sessionId, update })
|
|
423
|
+
);
|
|
320
424
|
} catch (err) {
|
|
321
|
-
|
|
322
|
-
const
|
|
323
|
-
await this.
|
|
324
|
-
|
|
325
|
-
method: "tools/call",
|
|
326
|
-
result: { content: [{ type: "text", text: msg }], isError: true }
|
|
327
|
-
});
|
|
425
|
+
session.abort.signal.removeEventListener("abort", onCancel);
|
|
426
|
+
const { code, message, data } = errorToJsonRpc(err);
|
|
427
|
+
await this.sendError(id, code, message, data);
|
|
428
|
+
return false;
|
|
328
429
|
}
|
|
430
|
+
session.abort.signal.removeEventListener("abort", onCancel);
|
|
431
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
432
|
+
await this.transport.send(toWire({
|
|
433
|
+
jsonrpc: "2.0",
|
|
434
|
+
id,
|
|
435
|
+
result: { stopReason: result.stopReason }
|
|
436
|
+
}));
|
|
329
437
|
return false;
|
|
330
438
|
}
|
|
331
|
-
async
|
|
332
|
-
|
|
333
|
-
|
|
439
|
+
async handleSetMode(id, params) {
|
|
440
|
+
const p = params ?? {};
|
|
441
|
+
const sessionId = typeof p.sessionId === "string" ? p.sessionId : null;
|
|
442
|
+
const modeId = typeof p.modeId === "string" ? p.modeId : null;
|
|
443
|
+
const session = sessionId ? this.sessions.get(sessionId) : void 0;
|
|
444
|
+
if (!session || !modeId || !this.modes.some((m) => m.id === modeId)) {
|
|
445
|
+
await this.sendError(id, -32602, "invalid sessionId or modeId");
|
|
446
|
+
return false;
|
|
447
|
+
}
|
|
448
|
+
session.modeId = modeId;
|
|
449
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
450
|
+
await this.sendNotification({
|
|
451
|
+
sessionId,
|
|
452
|
+
update: { sessionUpdate: "current_mode_update", modeId }
|
|
453
|
+
});
|
|
454
|
+
await this.transport.send(toWire({ jsonrpc: "2.0", id, result: {} }));
|
|
334
455
|
return false;
|
|
335
456
|
}
|
|
336
|
-
|
|
457
|
+
async handleSetConfigOption(id, params) {
|
|
458
|
+
const p = params ?? {};
|
|
459
|
+
const sessionId = typeof p.sessionId === "string" ? p.sessionId : null;
|
|
460
|
+
const optionId = typeof p.configOptionId === "string" ? p.configOptionId : null;
|
|
461
|
+
const value = typeof p.value === "string" ? p.value : null;
|
|
462
|
+
const session = sessionId ? this.sessions.get(sessionId) : void 0;
|
|
463
|
+
const option = optionId ? this.configOptions.find((o) => o.id === optionId) : void 0;
|
|
464
|
+
if (!session || !option || value === null || !option.options.some((o) => o.value === value)) {
|
|
465
|
+
await this.sendError(id, -32602, "invalid sessionId, configOptionId, or value");
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
option.currentValue = value;
|
|
469
|
+
session.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
470
|
+
await this.sendNotification({
|
|
471
|
+
sessionId,
|
|
472
|
+
update: {
|
|
473
|
+
sessionUpdate: "config_option_update",
|
|
474
|
+
configOptions: [...this.configOptions]
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
await this.transport.send(toWire({ jsonrpc: "2.0", id, result: {} }));
|
|
478
|
+
return false;
|
|
337
479
|
}
|
|
338
480
|
async handleSessionList(id) {
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
481
|
+
const sessions = Array.from(this.sessions.values()).map((s) => {
|
|
482
|
+
const out = {
|
|
483
|
+
sessionId: s.id,
|
|
484
|
+
cwd: s.cwd,
|
|
485
|
+
updatedAt: s.updatedAt
|
|
486
|
+
};
|
|
487
|
+
if (s.title !== void 0) out.title = s.title;
|
|
488
|
+
return out;
|
|
343
489
|
});
|
|
490
|
+
await this.transport.send(toWire({
|
|
491
|
+
jsonrpc: "2.0",
|
|
492
|
+
id,
|
|
493
|
+
result: { sessions }
|
|
494
|
+
}));
|
|
344
495
|
return false;
|
|
345
496
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
497
|
+
// ────────────────────────────────────────────────────────────────────
|
|
498
|
+
// Notifications
|
|
499
|
+
// ────────────────────────────────────────────────────────────────────
|
|
500
|
+
async handleNotification(method, params) {
|
|
501
|
+
switch (method) {
|
|
502
|
+
case "session/cancel": {
|
|
503
|
+
const p = params ?? {};
|
|
504
|
+
const sessionId = typeof p.sessionId === "string" ? p.sessionId : null;
|
|
505
|
+
const session = sessionId ? this.sessions.get(sessionId) : void 0;
|
|
506
|
+
if (session) {
|
|
507
|
+
session.abort.abort();
|
|
508
|
+
}
|
|
509
|
+
return false;
|
|
510
|
+
}
|
|
511
|
+
case "exit":
|
|
512
|
+
this.close();
|
|
513
|
+
return true;
|
|
514
|
+
default:
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
// ────────────────────────────────────────────────────────────────────
|
|
519
|
+
// Wire helpers
|
|
520
|
+
// ────────────────────────────────────────────────────────────────────
|
|
521
|
+
async sendNotification(params) {
|
|
522
|
+
await this.transport.send(toWire({ jsonrpc: "2.0", method: "session/update", params }));
|
|
523
|
+
}
|
|
524
|
+
async sendError(id, code, message, data) {
|
|
525
|
+
const error = { code, message };
|
|
526
|
+
if (data !== void 0) error.data = data;
|
|
527
|
+
await this.transport.send(toWire({ jsonrpc: "2.0", id, error }));
|
|
528
|
+
}
|
|
529
|
+
allocId() {
|
|
530
|
+
return this.nextId++;
|
|
349
531
|
}
|
|
350
532
|
};
|
|
533
|
+
function errorToJsonRpc(err) {
|
|
534
|
+
if (err && typeof err === "object") {
|
|
535
|
+
const e = err;
|
|
536
|
+
if (typeof e.code === "number" && typeof e.message === "string") {
|
|
537
|
+
const result = {
|
|
538
|
+
code: e.code,
|
|
539
|
+
message: e.message
|
|
540
|
+
};
|
|
541
|
+
if (e.data !== void 0) result.data = e.data;
|
|
542
|
+
return result;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
546
|
+
return { code: -32603, message };
|
|
547
|
+
}
|
|
351
548
|
var WrongStackACPServer = class {
|
|
352
549
|
transport;
|
|
353
|
-
registry;
|
|
354
550
|
handler;
|
|
355
551
|
running = false;
|
|
356
|
-
constructor(opts) {
|
|
552
|
+
constructor(opts = {}) {
|
|
357
553
|
this.transport = new StdioTransport();
|
|
358
|
-
|
|
359
|
-
this.
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
// project metadata so ACP tools can self-contextualise.
|
|
366
|
-
// Tracked in docs/notes/refactor-2026-06-05.md §5.1.
|
|
367
|
-
{}
|
|
368
|
-
);
|
|
554
|
+
const runTurn = opts.runTurn ?? defaultEchoRunTurn;
|
|
555
|
+
this.handler = new ACPProtocolHandler({
|
|
556
|
+
transport: this.transport,
|
|
557
|
+
defaultCwd: opts.defaultCwd ?? process.cwd(),
|
|
558
|
+
runTurn,
|
|
559
|
+
agentName: opts.agentName
|
|
560
|
+
});
|
|
369
561
|
}
|
|
370
562
|
/**
|
|
371
563
|
* Start the server. Blocks until the client disconnects.
|
|
372
564
|
*
|
|
373
|
-
* 1.
|
|
374
|
-
*
|
|
375
|
-
* 2. Loop: read messages, dispatch to handler, until EOF
|
|
376
|
-
*
|
|
377
|
-
* Single dispatch path: every inbound message is read exactly once
|
|
378
|
-
* from the transport and passed to the protocol handler exactly once.
|
|
379
|
-
* An earlier version combined a `transport.onMessage` callback with
|
|
380
|
-
* this read loop, which caused every message to be processed twice
|
|
381
|
-
* (once by the callback, once by the loop) — duplicate tool calls
|
|
382
|
-
* and duplicate responses to the client. See the ACP double-dispatch
|
|
383
|
-
* fix in the security audit (P1-001).
|
|
565
|
+
* 1. Print the legacy `[wstack-acp]\n` marker so the client knows the
|
|
566
|
+
* process is the ACP server (the old `StdioTransport` handshake).
|
|
567
|
+
* 2. Loop: read messages, dispatch to the handler, until EOF / error.
|
|
384
568
|
*/
|
|
385
569
|
async start() {
|
|
386
570
|
this.transport.sendStartupMarker();
|
|
@@ -399,8 +583,11 @@ var WrongStackACPServer = class {
|
|
|
399
583
|
this.transport.close();
|
|
400
584
|
}
|
|
401
585
|
};
|
|
586
|
+
var defaultEchoRunTurn = async (_input, _emit) => {
|
|
587
|
+
return { stopReason: "end_turn" };
|
|
588
|
+
};
|
|
402
589
|
async function main() {
|
|
403
|
-
const server = new WrongStackACPServer(
|
|
590
|
+
const server = new WrongStackACPServer();
|
|
404
591
|
await server.start();
|
|
405
592
|
}
|
|
406
593
|
var isEntrypoint = process.argv[1] !== void 0 && fileURLToPath(import.meta.url) === process.argv[1];
|
|
@@ -412,6 +599,88 @@ if (isEntrypoint) {
|
|
|
412
599
|
});
|
|
413
600
|
}
|
|
414
601
|
|
|
415
|
-
|
|
602
|
+
// src/agent/server-agent-turn.ts
|
|
603
|
+
function makeACPServerAgentTurn(opts) {
|
|
604
|
+
const agents = /* @__PURE__ */ new Map();
|
|
605
|
+
const timeouts = /* @__PURE__ */ new Map();
|
|
606
|
+
const timeoutMs = opts.timeoutMs ?? 5 * 6e4;
|
|
607
|
+
return async (input, emit) => {
|
|
608
|
+
let agent = agents.get(input.sessionId);
|
|
609
|
+
if (!agent) {
|
|
610
|
+
agent = await opts.agentFor(input.sessionId, process.cwd());
|
|
611
|
+
agents.set(input.sessionId, agent);
|
|
612
|
+
}
|
|
613
|
+
const timer = setTimeout(() => {
|
|
614
|
+
timeouts.delete(input.sessionId);
|
|
615
|
+
}, timeoutMs);
|
|
616
|
+
timeouts.set(input.sessionId, timer);
|
|
617
|
+
try {
|
|
618
|
+
const userMessage = promptToText(input.prompt);
|
|
619
|
+
const result = await agent.run(userMessage, { signal: input.signal });
|
|
620
|
+
const text = extractText(result);
|
|
621
|
+
if (text) {
|
|
622
|
+
emit({
|
|
623
|
+
sessionUpdate: "agent_message_chunk",
|
|
624
|
+
content: { type: "text", text }
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
const result_out = {
|
|
628
|
+
stopReason: pickStopReason(result, input.signal)
|
|
629
|
+
};
|
|
630
|
+
if (text) result_out.text = text;
|
|
631
|
+
return result_out;
|
|
632
|
+
} finally {
|
|
633
|
+
clearTimeout(timer);
|
|
634
|
+
timeouts.delete(input.sessionId);
|
|
635
|
+
}
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
function promptToText(blocks) {
|
|
639
|
+
const parts = [];
|
|
640
|
+
for (const b of blocks) {
|
|
641
|
+
if (b.type === "text") {
|
|
642
|
+
parts.push(b.text);
|
|
643
|
+
} else if (b.type === "image") {
|
|
644
|
+
parts.push(`[image: ${b.mimeType}]`);
|
|
645
|
+
} else if (b.type === "audio") {
|
|
646
|
+
parts.push(`[audio: ${b.mimeType}]`);
|
|
647
|
+
} else if (b.type === "resource") {
|
|
648
|
+
parts.push(`[embedded resource: ${b.resource.uri}]`);
|
|
649
|
+
} else if (b.type === "resource_link") {
|
|
650
|
+
parts.push(`[resource link: ${b.uri}]`);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return parts.join("\n").trim();
|
|
654
|
+
}
|
|
655
|
+
function extractText(result) {
|
|
656
|
+
if (typeof result !== "object" || result === null) return "";
|
|
657
|
+
const r = result;
|
|
658
|
+
if (typeof r.text === "string") return r.text;
|
|
659
|
+
if (Array.isArray(r.content)) {
|
|
660
|
+
const parts = [];
|
|
661
|
+
for (const c of r.content) {
|
|
662
|
+
if (typeof c === "object" && c !== null) {
|
|
663
|
+
const cb = c;
|
|
664
|
+
if (cb.type === "text" && typeof cb.text === "string") parts.push(cb.text);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
return parts.join("");
|
|
668
|
+
}
|
|
669
|
+
return "";
|
|
670
|
+
}
|
|
671
|
+
function pickStopReason(result, signal) {
|
|
672
|
+
if (signal.aborted) return "cancelled";
|
|
673
|
+
if (typeof result !== "object" || result === null) return "end_turn";
|
|
674
|
+
const r = result;
|
|
675
|
+
if (r.error) {
|
|
676
|
+
return "end_turn";
|
|
677
|
+
}
|
|
678
|
+
if (typeof r.stopReason === "string" && r.stopReason) {
|
|
679
|
+
return r.stopReason;
|
|
680
|
+
}
|
|
681
|
+
return "end_turn";
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
export { ACPProtocolHandler, ACPToolsRegistry, StdioTransport, WrongStackACPServer, makeACPServerAgentTurn };
|
|
416
685
|
//# sourceMappingURL=agent.js.map
|
|
417
686
|
//# sourceMappingURL=agent.js.map
|