@agentclientprotocol/claude-agent-acp 0.58.1 → 0.59.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/acp-agent.d.ts +277 -6
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +1376 -301
- package/dist/tools.d.ts +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +208 -8
- package/package.json +5 -5
package/dist/tools.d.ts
CHANGED
|
@@ -35,7 +35,7 @@ interface ToolUpdate {
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function toDisplayPath(filePath: string, cwd?: string): string;
|
|
37
37
|
export declare function toolInfoFromToolUse(toolUse: any, supportsTerminalOutput?: boolean, cwd?: string): ToolInfo;
|
|
38
|
-
export declare function toolUpdateFromToolResult(toolResult: ToolResultBlockParam | BetaToolResultBlockParam | BetaWebSearchToolResultBlockParam | BetaWebFetchToolResultBlockParam | WebSearchToolResultBlockParam | BetaCodeExecutionToolResultBlockParam | BetaBashCodeExecutionToolResultBlockParam | BetaTextEditorCodeExecutionToolResultBlockParam | BetaRequestMCPToolResultBlockParam | BetaToolSearchToolResultBlockParam, toolUse: any | undefined, supportsTerminalOutput?: boolean): ToolUpdate;
|
|
38
|
+
export declare function toolUpdateFromToolResult(toolResult: ToolResultBlockParam | BetaToolResultBlockParam | BetaWebSearchToolResultBlockParam | BetaWebFetchToolResultBlockParam | WebSearchToolResultBlockParam | BetaCodeExecutionToolResultBlockParam | BetaBashCodeExecutionToolResultBlockParam | BetaTextEditorCodeExecutionToolResultBlockParam | BetaRequestMCPToolResultBlockParam | BetaToolSearchToolResultBlockParam, toolUse: any | undefined, supportsTerminalOutput?: boolean, toolUseResult?: unknown): ToolUpdate;
|
|
39
39
|
export type ClaudePlanEntry = {
|
|
40
40
|
content: string;
|
|
41
41
|
status: "pending" | "in_progress" | "completed";
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,SAAS,EACT,eAAe,EACf,gBAAgB,EAChB,QAAQ,EACT,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAaL,eAAe,EACf,gBAAgB,EAChB,eAAe,EAKhB,MAAM,6CAA6C,CAAC;AACrD,OAAO,EAGL,oBAAoB,EAEpB,6BAA6B,EAE9B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAEL,yCAAyC,EAGzC,qCAAqC,EAGrC,kCAAkC,EAGlC,+CAA+C,EAI/C,wBAAwB,EACxB,kCAAkC,EAIlC,gCAAgC,EAEhC,iCAAiC,EAClC,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AA0BxC,UAAU,QAAQ;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAED,UAAU,UAAU;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;IAC/B,KAAK,CAAC,EAAE;QACN,aAAa,CAAC,EAAE;YACd,WAAW,EAAE,MAAM,CAAC;SACrB,CAAC;QACF,eAAe,CAAC,EAAE;YAChB,WAAW,EAAE,MAAM,CAAC;YACpB,IAAI,EAAE,MAAM,CAAC;SACd,CAAC;QACF,aAAa,CAAC,EAAE;YACd,WAAW,EAAE,MAAM,CAAC;YACpB,SAAS,EAAE,MAAM,CAAC;YAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;SACvB,CAAC;KACH,CAAC;CACH;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAQpE;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,GAAG,EACZ,sBAAsB,GAAE,OAAe,EACvC,GAAG,CAAC,EAAE,MAAM,GACX,QAAQ,CAqWV;AAmDD,wBAAgB,wBAAwB,CACtC,UAAU,EACN,oBAAoB,GACpB,wBAAwB,GACxB,iCAAiC,GACjC,gCAAgC,GAChC,6BAA6B,GAC7B,qCAAqC,GACrC,yCAAyC,GACzC,+CAA+C,GAC/C,kCAAkC,GAClC,kCAAkC,EACtC,OAAO,EAAE,GAAG,GAAG,SAAS,EACxB,sBAAsB,GAAE,OAAe,EACvC,aAAa,CAAC,EAAE,OAAO,GACtB,UAAU,CAgTZ;AAiHD,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,WAAW,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,eAAe,EAAE,CAAA;CAAE,GAAG,SAAS,GAAG,SAAS,EAAE,CAMxF;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,CAAC;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AACF,MAAM,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAE/C;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,gBAAgB,GAAG,SAAS,CAiCpF;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,SAAS,EAChB,KAAK,EAAE,eAAe,GAAG,SAAS,EAClC,MAAM,EAAE,gBAAgB,GAAG,SAAS,GACnC,IAAI,CASN;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,eAAe,GAAG,SAAS,GAAG,IAAI,CAiB1F;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE,CAMpE;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQnD;AAeD;;;;;;GAMG;AACH,wBAAgB,8BAA8B,CAAC,YAAY,EAAE,OAAO,GAAG;IACrE,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAChC,CAoCA;AAcD,eAAO,MAAM,oBAAoB,GAC/B,WAAW,MAAM,EACjB,wBAEG;IACD,iBAAiB,CAAC,EAAE,CAClB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,OAAO,EAClB,YAAY,EAAE,OAAO,KAClB,OAAO,CAAC,IAAI,CAAC,CAAC;CACpB,SAKF,CAAC;AAGF,eAAO,MAAM,qBAAqB,GAE9B,SAAQ,MAAgB,EACxB,UAAU;IACR,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,KACA,YAoBF,CAAC;AAEJ;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,GACxB,SAAS;IAAE,SAAS,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,KAAG,YAsBpE,CAAC"}
|
package/dist/tools.js
CHANGED
|
@@ -338,7 +338,51 @@ export function toolInfoFromToolUse(toolUse, supportsTerminalOutput = false, cwd
|
|
|
338
338
|
};
|
|
339
339
|
}
|
|
340
340
|
}
|
|
341
|
-
|
|
341
|
+
/**
|
|
342
|
+
* Narrow the untyped message-level `tool_use_result` toward a per-tool Output
|
|
343
|
+
* shape: rejects everything but a plain non-null object (arrays pass a bare
|
|
344
|
+
* `typeof === "object"` check, so they're excluded here). The returned value
|
|
345
|
+
* is only *nominally* typed — it arrives over the wire from arbitrary CLI
|
|
346
|
+
* versions, so each caller must still guard the specific fields it reads
|
|
347
|
+
* before trusting them.
|
|
348
|
+
*/
|
|
349
|
+
function structuredResult(toolUseResult) {
|
|
350
|
+
return toolUseResult !== null &&
|
|
351
|
+
typeof toolUseResult === "object" &&
|
|
352
|
+
!Array.isArray(toolUseResult)
|
|
353
|
+
? toolUseResult
|
|
354
|
+
: undefined;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Strip the model-directed trailer from a raw Agent/Task tool_result text:
|
|
358
|
+
* a `<usage>…</usage>` totals block and/or an
|
|
359
|
+
* `agentId: <id> (use SendMessage …)` continuation line at the end of the
|
|
360
|
+
* text. Both patterns are tail-anchored and independent (older CLIs emit
|
|
361
|
+
* variants with only one of them), so a format change makes them stop
|
|
362
|
+
* matching rather than mangle the report.
|
|
363
|
+
*/
|
|
364
|
+
function stripAgentTrailer(text) {
|
|
365
|
+
return text
|
|
366
|
+
.replace(/\n?<usage>[\s\S]*?<\/usage>\s*$/, "")
|
|
367
|
+
.replace(/\n?agentId: [\w-]+ \([^)]*\)\s*$/, "");
|
|
368
|
+
}
|
|
369
|
+
/** Apply {@link stripAgentTrailer} across a raw tool_result `content` (plain
|
|
370
|
+
* string or block array), leaving non-text blocks untouched. */
|
|
371
|
+
function stripAgentTrailerFromContent(content) {
|
|
372
|
+
if (typeof content === "string") {
|
|
373
|
+
return stripAgentTrailer(content);
|
|
374
|
+
}
|
|
375
|
+
if (Array.isArray(content)) {
|
|
376
|
+
return content.map((block) => block !== null &&
|
|
377
|
+
typeof block === "object" &&
|
|
378
|
+
block.type === "text" &&
|
|
379
|
+
typeof block.text === "string"
|
|
380
|
+
? { ...block, text: stripAgentTrailer(block.text) }
|
|
381
|
+
: block);
|
|
382
|
+
}
|
|
383
|
+
return content;
|
|
384
|
+
}
|
|
385
|
+
export function toolUpdateFromToolResult(toolResult, toolUse, supportsTerminalOutput = false, toolUseResult) {
|
|
342
386
|
if ("is_error" in toolResult &&
|
|
343
387
|
toolResult.is_error &&
|
|
344
388
|
toolResult.content &&
|
|
@@ -347,8 +391,57 @@ export function toolUpdateFromToolResult(toolResult, toolUse, supportsTerminalOu
|
|
|
347
391
|
// Only return errors
|
|
348
392
|
return toAcpContentUpdate(toolResult.content, true);
|
|
349
393
|
}
|
|
394
|
+
// Shared raw-text fallback: renders the tool_result content the model saw.
|
|
395
|
+
// The structured cases below fall back to this when `tool_use_result` is
|
|
396
|
+
// absent or fails its shape guard (older CLIs, replayed sessions).
|
|
397
|
+
const rawContentUpdate = () => toAcpContentUpdate(toolResult.content, "is_error" in toolResult ? toolResult.is_error : false);
|
|
350
398
|
switch (toolUse?.name) {
|
|
351
|
-
case "Read":
|
|
399
|
+
case "Read": {
|
|
400
|
+
// The raw tool_result text is the model-facing view: line-numbered
|
|
401
|
+
// content plus any appended <system-reminder> blocks (malicious-code
|
|
402
|
+
// checks, memory staleness notes, …) that clients shouldn't see. The
|
|
403
|
+
// structured FileReadOutput carries the clean content — rebuild the
|
|
404
|
+
// line-numbered view from it. Non-text variants (image/notebook/pdf)
|
|
405
|
+
// fall back to the raw content blocks, which already render fine.
|
|
406
|
+
const structuredRead = structuredResult(toolUseResult);
|
|
407
|
+
if (structuredRead?.type === "text" &&
|
|
408
|
+
typeof structuredRead.file?.content === "string" &&
|
|
409
|
+
// An empty file has nothing to line-number; keep the raw view (the
|
|
410
|
+
// model-facing "file is empty" note) rather than a phantom blank line.
|
|
411
|
+
structuredRead.file.content.length > 0) {
|
|
412
|
+
// startLine is typed non-optional but defended anyway; a Read's
|
|
413
|
+
// `offset` input is the same 1-based starting line, so it beats a
|
|
414
|
+
// blind 1 when an emitter omits the field.
|
|
415
|
+
const startLine = structuredRead.file.startLine ??
|
|
416
|
+
toolUse.input?.offset ??
|
|
417
|
+
1;
|
|
418
|
+
// A trailing newline is a line terminator, not an extra line — don't
|
|
419
|
+
// number a phantom empty line after it.
|
|
420
|
+
let numbered = structuredRead.file.content
|
|
421
|
+
.replace(/\n$/, "")
|
|
422
|
+
.split("\n")
|
|
423
|
+
.map((line, i) => `${startLine + i}\t${line}`)
|
|
424
|
+
.join("\n");
|
|
425
|
+
// The model-facing truncation banner doesn't survive reconstruction
|
|
426
|
+
// from file.content (the SDK flag exists for exactly this case) —
|
|
427
|
+
// re-establish it so a partial first page doesn't read as the whole
|
|
428
|
+
// file.
|
|
429
|
+
if (structuredRead.file.truncatedByTokenCap) {
|
|
430
|
+
const { numLines, totalLines } = structuredRead.file;
|
|
431
|
+
const detail = typeof numLines === "number" && typeof totalLines === "number"
|
|
432
|
+
? `: showing ${numLines} of ${totalLines} lines`
|
|
433
|
+
: "";
|
|
434
|
+
numbered += `\n[File truncated${detail}]`;
|
|
435
|
+
}
|
|
436
|
+
return {
|
|
437
|
+
content: [
|
|
438
|
+
{
|
|
439
|
+
type: "content",
|
|
440
|
+
content: { type: "text", text: markdownEscape(numbered) },
|
|
441
|
+
},
|
|
442
|
+
],
|
|
443
|
+
};
|
|
444
|
+
}
|
|
352
445
|
if (Array.isArray(toolResult.content) && toolResult.content.length > 0) {
|
|
353
446
|
return {
|
|
354
447
|
content: toolResult.content.map((content) => ({
|
|
@@ -376,19 +469,60 @@ export function toolUpdateFromToolResult(toolResult, toolUse, supportsTerminalOu
|
|
|
376
469
|
};
|
|
377
470
|
}
|
|
378
471
|
return {};
|
|
472
|
+
}
|
|
379
473
|
case "Bash": {
|
|
380
474
|
const result = toolResult.content;
|
|
381
475
|
const terminalId = "tool_use_id" in toolResult ? String(toolResult.tool_use_id) : "";
|
|
382
476
|
const isError = "is_error" in toolResult && toolResult.is_error;
|
|
383
477
|
// Extract output and exit code from either format:
|
|
384
|
-
// 1.
|
|
385
|
-
//
|
|
386
|
-
//
|
|
478
|
+
// 1. The structured BashOutput (message-level tool_use_result): its
|
|
479
|
+
// stdout/stderr exclude the model-directed suffixes the raw text
|
|
480
|
+
// carries (stale-read hints, gh rate-limit hints, the
|
|
481
|
+
// persisted-output wrapper for too-large outputs — the interruption
|
|
482
|
+
// and truncation facts those carried are re-established from the
|
|
483
|
+
// structured flags below). Skipped for image output (the raw content
|
|
484
|
+
// array carries the actual image blocks) and backgrounded commands
|
|
485
|
+
// (the raw text carries the background-task notice; structured
|
|
486
|
+
// stdout may be empty).
|
|
487
|
+
// 2. BetaBashCodeExecutionResultBlock: { type: "bash_code_execution_result", stdout, stderr, return_code }
|
|
488
|
+
// 3. Plain string content from a regular tool_result
|
|
489
|
+
// 4. Array content (e.g. [{ type: "text", text: "..." }] for stdout,
|
|
387
490
|
// or [{ type: "image", source: {...} }] when the local Bash tool
|
|
388
491
|
// produces an image, e.g. piping a base64 data URI)
|
|
389
492
|
let output = "";
|
|
390
493
|
let exitCode = isError ? 1 : 0;
|
|
391
|
-
|
|
494
|
+
const structuredBash = structuredResult(toolUseResult);
|
|
495
|
+
if (structuredBash &&
|
|
496
|
+
typeof structuredBash.stdout === "string" &&
|
|
497
|
+
typeof structuredBash.stderr === "string" &&
|
|
498
|
+
!structuredBash.isImage &&
|
|
499
|
+
structuredBash.backgroundTaskId === undefined) {
|
|
500
|
+
output = [structuredBash.stdout, structuredBash.stderr].filter(Boolean).join("\n");
|
|
501
|
+
// Two raw-text notices don't survive the structured stdout/stderr —
|
|
502
|
+
// re-establish them so the client isn't shown a clean-looking result:
|
|
503
|
+
// the CLI appends its abort marker only to the model-facing text, and
|
|
504
|
+
// an aborted command isn't a success, so synthesize a failing exit
|
|
505
|
+
// code when the result wasn't already an error.
|
|
506
|
+
if (structuredBash.interrupted) {
|
|
507
|
+
output = [output, "[Command was aborted before completion]"].filter(Boolean).join("\n");
|
|
508
|
+
exitCode = 1;
|
|
509
|
+
}
|
|
510
|
+
// Structured stdout is clipped (~30k chars) when the full output was
|
|
511
|
+
// persisted to disk; without this note the clip is silent and the
|
|
512
|
+
// path to the full output is lost.
|
|
513
|
+
if (typeof structuredBash.persistedOutputPath === "string") {
|
|
514
|
+
const size = typeof structuredBash.persistedOutputSize === "number"
|
|
515
|
+
? ` (${structuredBash.persistedOutputSize} bytes total)`
|
|
516
|
+
: "";
|
|
517
|
+
output = [
|
|
518
|
+
output,
|
|
519
|
+
`[Output truncated${size}: full output saved to ${structuredBash.persistedOutputPath}]`,
|
|
520
|
+
]
|
|
521
|
+
.filter(Boolean)
|
|
522
|
+
.join("\n");
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
else if (result &&
|
|
392
526
|
typeof result === "object" &&
|
|
393
527
|
"type" in result &&
|
|
394
528
|
result.type === "bash_code_execution_result") {
|
|
@@ -448,6 +582,36 @@ export function toolUpdateFromToolResult(toolResult, toolUse, supportsTerminalOu
|
|
|
448
582
|
}
|
|
449
583
|
return {};
|
|
450
584
|
}
|
|
585
|
+
case "Agent":
|
|
586
|
+
case "Task": {
|
|
587
|
+
// The raw tool_result text ends with a model-directed trailer (an
|
|
588
|
+
// `agentId: … (use SendMessage …)` line plus a `<usage>` totals block)
|
|
589
|
+
// that ACP clients shouldn't see. The message-level `tool_use_result`
|
|
590
|
+
// carries the structured AgentOutput whose `content` is the subagent's
|
|
591
|
+
// report without the trailer — render from it when present (per the SDK
|
|
592
|
+
// 0.3.207 guidance) and fall back to the raw text otherwise (older CLIs,
|
|
593
|
+
// replayed sessions).
|
|
594
|
+
// Narrowed to the full union, not the completed variant — the status
|
|
595
|
+
// check below is what discriminates it, and pre-narrowing would let
|
|
596
|
+
// future field reads typecheck against a variant the runtime value may
|
|
597
|
+
// not be.
|
|
598
|
+
const structured = structuredResult(toolUseResult);
|
|
599
|
+
if (structured?.status === "completed" &&
|
|
600
|
+
Array.isArray(structured.content) &&
|
|
601
|
+
// A completed subagent can end with zero text blocks; an empty
|
|
602
|
+
// structured render would beat the raw fallback for no benefit.
|
|
603
|
+
structured.content.length > 0) {
|
|
604
|
+
return toAcpContentUpdate(structured.content, "is_error" in toolResult ? toolResult.is_error : false);
|
|
605
|
+
}
|
|
606
|
+
// No structured report to render from (replayed sessions —
|
|
607
|
+
// getSessionMessages doesn't expose the transcript's toolUseResult —
|
|
608
|
+
// and older CLIs). The SDK advises rendering from tool_use_result
|
|
609
|
+
// instead of parsing the text, but with no structured value the
|
|
610
|
+
// tail-anchored strip is the only cleanup available; if the trailer
|
|
611
|
+
// format changes it simply stops matching and the full raw text
|
|
612
|
+
// renders, no worse than before.
|
|
613
|
+
return toAcpContentUpdate(stripAgentTrailerFromContent(toolResult.content), "is_error" in toolResult ? toolResult.is_error : false);
|
|
614
|
+
}
|
|
451
615
|
case "Edit": // Edit is handled in hooks
|
|
452
616
|
case "Write": {
|
|
453
617
|
return {};
|
|
@@ -455,11 +619,47 @@ export function toolUpdateFromToolResult(toolResult, toolUse, supportsTerminalOu
|
|
|
455
619
|
case "ExitPlanMode": {
|
|
456
620
|
return { title: "Exited Plan Mode" };
|
|
457
621
|
}
|
|
622
|
+
case "WebSearch": {
|
|
623
|
+
// The raw tool_result text is a model-directed dump ("Web search
|
|
624
|
+
// results for query: …\n\nLinks: [{…json…}]"). The structured
|
|
625
|
+
// WebSearchOutput carries the hits — render them the way server-side
|
|
626
|
+
// web_search_result blocks render ("Title (url)").
|
|
627
|
+
const structuredSearch = structuredResult(toolUseResult);
|
|
628
|
+
if (structuredSearch && Array.isArray(structuredSearch.results)) {
|
|
629
|
+
const lines = structuredSearch.results.flatMap((entry) => typeof entry === "string"
|
|
630
|
+
? [entry]
|
|
631
|
+
: Array.isArray(entry?.content)
|
|
632
|
+
? // tool_use_result arrives untyped across CLI version skew —
|
|
633
|
+
// skip off-spec hits rather than rendering
|
|
634
|
+
// "undefined (undefined)" lines.
|
|
635
|
+
entry.content.flatMap((hit) => typeof hit?.title === "string" && typeof hit?.url === "string"
|
|
636
|
+
? [formatWebSearchHit(hit)]
|
|
637
|
+
: [])
|
|
638
|
+
: []);
|
|
639
|
+
if (lines.length > 0) {
|
|
640
|
+
return {
|
|
641
|
+
content: [
|
|
642
|
+
{
|
|
643
|
+
type: "content",
|
|
644
|
+
content: { type: "text", text: lines.join("\n") },
|
|
645
|
+
},
|
|
646
|
+
],
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return rawContentUpdate();
|
|
651
|
+
}
|
|
458
652
|
default: {
|
|
459
|
-
return
|
|
653
|
+
return rawContentUpdate();
|
|
460
654
|
}
|
|
461
655
|
}
|
|
462
656
|
}
|
|
657
|
+
/** One display format for a web-search hit, shared by the structured
|
|
658
|
+
* WebSearchOutput render and the server-side `web_search_result` block so
|
|
659
|
+
* the two paths can't drift. */
|
|
660
|
+
function formatWebSearchHit(hit) {
|
|
661
|
+
return `${hit.title} (${hit.url})`;
|
|
662
|
+
}
|
|
463
663
|
function toAcpContentUpdate(content, isError = false) {
|
|
464
664
|
if (Array.isArray(content) && content.length > 0) {
|
|
465
665
|
return {
|
|
@@ -524,7 +724,7 @@ function toAcpContentBlock(content, isError) {
|
|
|
524
724
|
case "tool_search_tool_result_error":
|
|
525
725
|
return wrapText(`Error: ${content.error_code}${content.error_message ? ` - ${content.error_message}` : ""}`);
|
|
526
726
|
case "web_search_result":
|
|
527
|
-
return wrapText(
|
|
727
|
+
return wrapText(formatWebSearchHit(content));
|
|
528
728
|
case "web_search_tool_result_error":
|
|
529
729
|
return wrapText(`Error: ${content.error_code}`);
|
|
530
730
|
case "web_fetch_result":
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.59.0",
|
|
7
7
|
"description": "An ACP-compatible coding agent powered by the Claude Agent SDK (TypeScript)",
|
|
8
8
|
"main": "dist/lib.js",
|
|
9
9
|
"types": "dist/lib.d.ts",
|
|
@@ -64,20 +64,20 @@
|
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
66
|
"@agentclientprotocol/sdk": "1.2.1",
|
|
67
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.
|
|
67
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.207",
|
|
68
68
|
"zod": "^3.25.0 || ^4.0.0"
|
|
69
69
|
},
|
|
70
70
|
"devDependencies": {
|
|
71
|
-
"@anthropic-ai/sdk": "0.
|
|
71
|
+
"@anthropic-ai/sdk": "0.111.0",
|
|
72
72
|
"@eslint/js": "10.0.1",
|
|
73
73
|
"@tsconfig/node22": "22.0.5",
|
|
74
74
|
"@types/node": "26.1.1",
|
|
75
75
|
"@typescript-eslint/eslint-plugin": "8.63.0",
|
|
76
76
|
"@typescript-eslint/parser": "8.63.0",
|
|
77
|
-
"eslint": "10.
|
|
77
|
+
"eslint": "10.7.0",
|
|
78
78
|
"eslint-config-prettier": "10.1.8",
|
|
79
79
|
"globals": "17.7.0",
|
|
80
|
-
"prettier": "3.9.
|
|
80
|
+
"prettier": "3.9.5",
|
|
81
81
|
"ts-node": "10.9.2",
|
|
82
82
|
"typescript": "6.0.3",
|
|
83
83
|
"vitest": "4.1.10"
|