@townco/agent 0.1.74 → 0.1.76
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/acp-server/http.js
CHANGED
|
@@ -609,12 +609,10 @@ export function makeHttpTransport(agent, agentDir, agentName) {
|
|
|
609
609
|
});
|
|
610
610
|
const port = Number.parseInt(process.env.PORT || "3100", 10);
|
|
611
611
|
logger.info("Starting HTTP server", { port });
|
|
612
|
-
Bun.
|
|
613
|
-
|
|
614
|
-
port,
|
|
615
|
-
});
|
|
612
|
+
const hostname = Bun.env.BIND_HOST || "localhost";
|
|
613
|
+
Bun.serve({ fetch: app.fetch, hostname, port });
|
|
616
614
|
logger.info("HTTP server listening", {
|
|
617
|
-
url: `http
|
|
615
|
+
url: `http://${hostname}:${port}`,
|
|
618
616
|
port,
|
|
619
617
|
});
|
|
620
618
|
}
|
|
@@ -863,7 +863,9 @@ export class LangchainAgent {
|
|
|
863
863
|
toolUseBlock.name &&
|
|
864
864
|
!preliminaryToolCallIds.has(toolUseBlock.id)) {
|
|
865
865
|
preliminaryToolCallIds.add(toolUseBlock.id);
|
|
866
|
-
|
|
866
|
+
// Yield the preliminary notification immediately (don't buffer)
|
|
867
|
+
// This allows the UI to show the "selecting" state before params arrive
|
|
868
|
+
yield {
|
|
867
869
|
sessionUpdate: "tool_call",
|
|
868
870
|
toolCallId: toolUseBlock.id,
|
|
869
871
|
title: toolUseBlock.name,
|
|
@@ -871,7 +873,7 @@ export class LangchainAgent {
|
|
|
871
873
|
status: "pending",
|
|
872
874
|
rawInput: {}, // Args not available yet
|
|
873
875
|
_meta: { messageId: req.messageId },
|
|
874
|
-
}
|
|
876
|
+
};
|
|
875
877
|
}
|
|
876
878
|
}
|
|
877
879
|
else if (part.type === "input_json_delta") {
|
|
@@ -881,8 +883,8 @@ export class LangchainAgent {
|
|
|
881
883
|
throw new Error(`Unhandled AIMessageChunk content block type: ${part.type}\n${JSON.stringify(part)}`);
|
|
882
884
|
}
|
|
883
885
|
}
|
|
884
|
-
//
|
|
885
|
-
//
|
|
886
|
+
// Preliminary tool_use blocks are yielded immediately above
|
|
887
|
+
// Full tool calls with params will come later in "updates" mode
|
|
886
888
|
}
|
|
887
889
|
else {
|
|
888
890
|
throw new Error(`Unhandled AIMessageChunk content type: ${typeof aiMessage.content}`);
|
|
@@ -327,95 +327,105 @@ async function querySubagent(agentName, agentPath, agentWorkingDirectory, query)
|
|
|
327
327
|
// Map of tool call IDs to their indices in toolCalls array
|
|
328
328
|
const toolCallMap = new Map();
|
|
329
329
|
const ssePromise = (async () => {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
try {
|
|
353
|
-
const message = JSON.parse(data);
|
|
354
|
-
const update = message.params?.update;
|
|
355
|
-
if (message.method !== "session/update" || !update)
|
|
330
|
+
try {
|
|
331
|
+
const sseResponse = await fetch(`${baseUrl}/events`, {
|
|
332
|
+
headers: { "X-Session-ID": sessionId },
|
|
333
|
+
signal: sseAbortController.signal,
|
|
334
|
+
});
|
|
335
|
+
if (!sseResponse.ok || !sseResponse.body) {
|
|
336
|
+
throw new Error(`SSE connection failed: HTTP ${sseResponse.status}`);
|
|
337
|
+
}
|
|
338
|
+
const reader = sseResponse.body.getReader();
|
|
339
|
+
const decoder = new TextDecoder();
|
|
340
|
+
let buffer = "";
|
|
341
|
+
while (true) {
|
|
342
|
+
const { done, value } = await reader.read();
|
|
343
|
+
if (done)
|
|
344
|
+
break;
|
|
345
|
+
buffer += decoder.decode(value, { stream: true });
|
|
346
|
+
const lines = buffer.split("\n");
|
|
347
|
+
buffer = lines.pop() || "";
|
|
348
|
+
for (const line of lines) {
|
|
349
|
+
if (line.startsWith("data:")) {
|
|
350
|
+
const data = line.substring(5).trim();
|
|
351
|
+
if (!data)
|
|
356
352
|
continue;
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const
|
|
360
|
-
if (
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
currentMessage.contentBlocks.
|
|
371
|
-
|
|
372
|
-
text
|
|
373
|
-
}
|
|
353
|
+
try {
|
|
354
|
+
const message = JSON.parse(data);
|
|
355
|
+
const update = message.params?.update;
|
|
356
|
+
if (message.method !== "session/update" || !update)
|
|
357
|
+
continue;
|
|
358
|
+
// Handle agent_message_chunk - accumulate text
|
|
359
|
+
if (update.sessionUpdate === "agent_message_chunk") {
|
|
360
|
+
const content = update.content;
|
|
361
|
+
if (content?.type === "text" &&
|
|
362
|
+
typeof content.text === "string") {
|
|
363
|
+
responseText += content.text;
|
|
364
|
+
currentMessage.content += content.text;
|
|
365
|
+
// Add to contentBlocks - append to last text block or create new one
|
|
366
|
+
const lastBlock = currentMessage.contentBlocks[currentMessage.contentBlocks.length - 1];
|
|
367
|
+
if (lastBlock && lastBlock.type === "text") {
|
|
368
|
+
lastBlock.text += content.text;
|
|
369
|
+
}
|
|
370
|
+
else {
|
|
371
|
+
currentMessage.contentBlocks.push({
|
|
372
|
+
type: "text",
|
|
373
|
+
text: content.text,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
374
376
|
}
|
|
375
377
|
}
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
378
|
+
// Handle tool_call - track new tool calls
|
|
379
|
+
if (update.sessionUpdate === "tool_call" && update.toolCallId) {
|
|
380
|
+
const toolCall = {
|
|
381
|
+
id: update.toolCallId,
|
|
382
|
+
title: update.title || "Tool call",
|
|
383
|
+
prettyName: update._meta?.prettyName,
|
|
384
|
+
icon: update._meta?.icon,
|
|
385
|
+
status: update.status ||
|
|
386
|
+
"pending",
|
|
387
|
+
};
|
|
388
|
+
currentMessage.toolCalls.push(toolCall);
|
|
389
|
+
toolCallMap.set(update.toolCallId, currentMessage.toolCalls.length - 1);
|
|
390
|
+
// Add to contentBlocks for interleaved display
|
|
391
|
+
currentMessage.contentBlocks.push({
|
|
392
|
+
type: "tool_call",
|
|
393
|
+
toolCall,
|
|
394
|
+
});
|
|
395
|
+
}
|
|
396
|
+
// Handle tool_call_update - update existing tool call status
|
|
397
|
+
if (update.sessionUpdate === "tool_call_update" &&
|
|
398
|
+
update.toolCallId) {
|
|
399
|
+
const idx = toolCallMap.get(update.toolCallId);
|
|
400
|
+
if (idx !== undefined && currentMessage.toolCalls[idx]) {
|
|
401
|
+
if (update.status) {
|
|
402
|
+
currentMessage.toolCalls[idx].status =
|
|
403
|
+
update.status;
|
|
404
|
+
}
|
|
405
|
+
// Also update in contentBlocks
|
|
406
|
+
const block = currentMessage.contentBlocks.find((b) => b.type === "tool_call" &&
|
|
407
|
+
b.toolCall.id === update.toolCallId);
|
|
408
|
+
if (block && update.status) {
|
|
409
|
+
block.toolCall.status =
|
|
410
|
+
update.status;
|
|
411
|
+
}
|
|
409
412
|
}
|
|
410
413
|
}
|
|
411
414
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
+
catch {
|
|
416
|
+
// Ignore malformed SSE data
|
|
417
|
+
}
|
|
415
418
|
}
|
|
416
419
|
}
|
|
417
420
|
}
|
|
418
421
|
}
|
|
422
|
+
catch (error) {
|
|
423
|
+
// Ignore AbortError - this is expected when we abort the SSE connection
|
|
424
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
throw error;
|
|
428
|
+
}
|
|
419
429
|
})();
|
|
420
430
|
// Step 4: Send the prompt with timeout
|
|
421
431
|
const timeoutMs = 5 * 60 * 1000; // 5 minutes
|