@agentclientprotocol/claude-agent-acp 0.66.0 → 0.68.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/tools.js CHANGED
@@ -96,7 +96,7 @@ export function toolInfoFromToolUse(toolUse, supportsTerminalOutput = false, cwd
96
96
  }
97
97
  const displayPath = input?.file_path ? toDisplayPath(input.file_path, cwd) : undefined;
98
98
  return {
99
- title: displayPath ? `Write ${displayPath}` : "Write",
99
+ title: displayPath ? `Write ${displayPath}` : "Preparing file…",
100
100
  kind: "edit",
101
101
  content,
102
102
  locations: input?.file_path ? [{ path: input.file_path }] : [],
@@ -291,6 +291,15 @@ export function toolInfoFromToolUse(toolUse, supportsTerminalOutput = false, cwd
291
291
  : [],
292
292
  };
293
293
  }
294
+ case "Skill": {
295
+ const input = toolUse.input;
296
+ const skillName = input?.skill;
297
+ return {
298
+ title: skillName ? `Load skill: ${skillName}` : "Load skill",
299
+ kind: "other",
300
+ content: [],
301
+ };
302
+ }
294
303
  case "AskUserQuestion": {
295
304
  const input = toolUse.input;
296
305
  const questions = Array.isArray(input?.questions) ? input.questions : [];
@@ -658,6 +667,9 @@ export function toolUpdateFromToolResult(toolResult, toolUse, supportsTerminalOu
658
667
  // renders, no worse than before.
659
668
  return toAcpContentUpdate(stripAgentTrailerFromContent(toolResult.content), "is_error" in toolResult ? toolResult.is_error : false);
660
669
  }
670
+ case "Skill": {
671
+ return {};
672
+ }
661
673
  case "Edit": // Edit is handled in hooks
662
674
  case "Write": {
663
675
  return {};
@@ -798,35 +810,32 @@ function toAcpContentBlock(content, isError) {
798
810
  }
799
811
  export function planEntries(input) {
800
812
  return (input?.todos ?? []).map((todo) => ({
801
- content: todo.content,
813
+ content: todo.status === "in_progress" && todo.activeForm ? todo.activeForm : todo.content,
802
814
  status: todo.status,
803
815
  priority: "medium",
804
816
  }));
805
817
  }
806
818
  /**
807
- * Best-effort parse of a TaskCreate tool_result content into the structured
808
- * TaskCreateOutput. The SDK delivers tool outputs either as a string or as
809
- * an array of TextBlockParam-like blocks containing JSON text; try both.
819
+ * Best-effort parse of a structured Task* tool_result. The SDK delivers tool
820
+ * outputs either as a string or as an array of TextBlockParam-like blocks
821
+ * containing JSON text; try both.
810
822
  */
811
- export function parseTaskCreateOutput(content) {
823
+ function parseJsonToolOutput(content, isExpectedOutput) {
812
824
  const tryParse = (text) => {
813
825
  try {
814
826
  const parsed = JSON.parse(text);
815
- if (parsed &&
816
- typeof parsed === "object" &&
817
- parsed.task &&
818
- typeof parsed.task.id === "string") {
819
- return parsed;
820
- }
827
+ return isExpectedOutput(parsed) ? parsed : undefined;
821
828
  }
822
829
  catch {
823
- // ignore
830
+ return undefined;
824
831
  }
825
- return undefined;
826
832
  };
827
833
  if (typeof content === "string") {
828
834
  return tryParse(content);
829
835
  }
836
+ if (content && typeof content === "object" && !Array.isArray(content)) {
837
+ return isExpectedOutput(content) ? content : undefined;
838
+ }
830
839
  if (Array.isArray(content)) {
831
840
  for (const block of content) {
832
841
  if (block && typeof block === "object" && "type" in block && block.type === "text") {
@@ -841,6 +850,96 @@ export function parseTaskCreateOutput(content) {
841
850
  }
842
851
  return undefined;
843
852
  }
853
+ function toolOutputTexts(content) {
854
+ if (typeof content === "string")
855
+ return [content];
856
+ if (!Array.isArray(content))
857
+ return [];
858
+ return content.flatMap((block) => block &&
859
+ typeof block === "object" &&
860
+ "type" in block &&
861
+ block.type === "text" &&
862
+ "text" in block &&
863
+ typeof block.text === "string"
864
+ ? [block.text]
865
+ : []);
866
+ }
867
+ export function parseTaskCreateOutput(content) {
868
+ const structured = parseJsonToolOutput(content, (parsed) => Boolean(parsed &&
869
+ typeof parsed === "object" &&
870
+ "task" in parsed &&
871
+ parsed.task &&
872
+ typeof parsed.task === "object" &&
873
+ "id" in parsed.task &&
874
+ typeof parsed.task.id === "string"));
875
+ if (structured)
876
+ return structured;
877
+ for (const text of toolOutputTexts(content)) {
878
+ const match = /^Task #(\S+) created successfully: (.+)$/.exec(text.trim());
879
+ if (match)
880
+ return { task: { id: match[1], subject: match[2] } };
881
+ }
882
+ return undefined;
883
+ }
884
+ export function parseTaskListOutput(content) {
885
+ const validStatuses = new Set(["pending", "in_progress", "completed"]);
886
+ const structured = parseJsonToolOutput(content, (parsed) => Boolean(parsed &&
887
+ typeof parsed === "object" &&
888
+ "tasks" in parsed &&
889
+ Array.isArray(parsed.tasks) &&
890
+ parsed.tasks.every((task) => task &&
891
+ typeof task === "object" &&
892
+ typeof task.id === "string" &&
893
+ typeof task.subject === "string" &&
894
+ typeof task.status === "string" &&
895
+ validStatuses.has(task.status))));
896
+ if (structured)
897
+ return structured;
898
+ for (const text of toolOutputTexts(content)) {
899
+ if (text.trim() === "No tasks found")
900
+ return { tasks: [] };
901
+ const tasks = [];
902
+ const lines = text.trim().split("\n");
903
+ for (const line of lines) {
904
+ const match = /^#(\S+) \[(pending|in_progress|completed)\] (.+?)(?: \(([^()]*)\))?(?: \[blocked by ((?:#[^,\]]+(?:, )?)+)\])?$/.exec(line);
905
+ if (!match) {
906
+ tasks.length = 0;
907
+ break;
908
+ }
909
+ tasks.push({
910
+ id: match[1],
911
+ subject: match[3],
912
+ status: match[2],
913
+ ...(match[4] ? { owner: match[4] } : {}),
914
+ blockedBy: match[5] ? match[5].split(", ").map((id) => id.slice(1)) : [],
915
+ });
916
+ }
917
+ if (tasks.length > 0)
918
+ return { tasks };
919
+ }
920
+ return undefined;
921
+ }
922
+ export function parseTaskUpdateOutput(content, expectedTaskId) {
923
+ const structured = parseJsonToolOutput(content, (parsed) => Boolean(parsed &&
924
+ typeof parsed === "object" &&
925
+ "success" in parsed &&
926
+ typeof parsed.success === "boolean" &&
927
+ "taskId" in parsed &&
928
+ typeof parsed.taskId === "string" &&
929
+ "updatedFields" in parsed &&
930
+ Array.isArray(parsed.updatedFields) &&
931
+ parsed.updatedFields.every((field) => typeof field === "string")));
932
+ if (structured)
933
+ return structured;
934
+ for (const text of toolOutputTexts(content)) {
935
+ const notFound = /^Task #(\S+) not found$/.exec(text.trim());
936
+ const taskId = notFound?.[1] ?? expectedTaskId;
937
+ if (taskId && (notFound || text.trim() === "Failed to delete task")) {
938
+ return { success: false, taskId, updatedFields: [], error: text.trim() };
939
+ }
940
+ }
941
+ return undefined;
942
+ }
844
943
  export function applyTaskCreate(state, input, output) {
845
944
  const taskId = output?.task?.id;
846
945
  if (!taskId || !input)
@@ -872,9 +971,22 @@ export function applyTaskUpdate(state, input) {
872
971
  description: input.description ?? existing?.description,
873
972
  });
874
973
  }
974
+ export function applyTaskList(state, output) {
975
+ const previous = new Map(state);
976
+ state.clear();
977
+ for (const task of output.tasks) {
978
+ const existing = previous.get(task.id);
979
+ state.set(task.id, {
980
+ subject: task.subject,
981
+ status: task.status,
982
+ activeForm: existing?.activeForm,
983
+ description: existing?.description,
984
+ });
985
+ }
986
+ }
875
987
  export function taskStateToPlanEntries(state) {
876
988
  return Array.from(state.values()).map((task) => ({
877
- content: task.subject,
989
+ content: task.status === "in_progress" && task.activeForm ? task.activeForm : task.subject,
878
990
  status: task.status,
879
991
  priority: "medium",
880
992
  }));
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.66.0",
6
+ "version": "0.68.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",
@@ -66,19 +66,19 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "@agentclientprotocol/sdk": "1.3.0",
69
- "@anthropic-ai/claude-agent-sdk": "0.3.220",
69
+ "@anthropic-ai/claude-agent-sdk": "0.3.232",
70
70
  "zod": "^3.25.0 || ^4.0.0"
71
71
  },
72
72
  "devDependencies": {
73
- "@anthropic-ai/sdk": "0.115.0",
73
+ "@anthropic-ai/sdk": "0.117.1",
74
74
  "@eslint/js": "10.0.1",
75
75
  "@tsconfig/node22": "22.0.5",
76
- "@types/node": "26.1.2",
77
- "@typescript-eslint/eslint-plugin": "8.65.0",
78
- "@typescript-eslint/parser": "8.65.0",
79
- "eslint": "10.8.0",
76
+ "@types/node": "26.2.0",
77
+ "@typescript-eslint/eslint-plugin": "8.67.0",
78
+ "@typescript-eslint/parser": "8.67.0",
79
+ "eslint": "10.8.1",
80
80
  "eslint-config-prettier": "10.1.8",
81
- "globals": "17.9.0",
81
+ "globals": "17.11.0",
82
82
  "prettier": "3.9.6",
83
83
  "ts-node": "10.9.2",
84
84
  "typescript": "6.0.3",