@ganglion/xacpx 0.20.1 → 0.20.2

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.
@@ -3260,6 +3260,7 @@ function createStreamingPromptState(formatToolCalls = false, options) {
3260
3260
  emittedToolCallIds: new Set,
3261
3261
  positionedToolCallIds: new Set,
3262
3262
  toolCalls: new Map,
3263
+ cursorPlanEntries: new Map,
3263
3264
  toolEventMode,
3264
3265
  driver,
3265
3266
  rawStream,
@@ -3318,13 +3319,17 @@ function parseStreamingChunks(state, line) {
3318
3319
  }
3319
3320
  const wantsStructured = state.toolEventMode === "structured" || state.toolEventMode === "both";
3320
3321
  const wantsText = (state.toolEventMode === "text" || state.toolEventMode === "both") && state.formatToolCalls;
3321
- if (wantsStructured && state.onToolEvent) {
3322
- const merged = update.toolCallId ? mergeToolCallUpdate(state, update.toolCallId, update) : update;
3322
+ const merged = update.toolCallId && (state.onToolEvent || state.onPlan) ? mergeToolCallUpdate(state, update.toolCallId, update) : update;
3323
+ const cursorPlan = normalizeCursorPlanUpdate(state, merged);
3324
+ const consumedAsPlan = cursorPlan !== undefined && state.onPlan !== undefined;
3325
+ if (consumedAsPlan) {
3326
+ state.onPlan?.(cursorPlan);
3327
+ } else if (wantsStructured && state.onToolEvent) {
3323
3328
  const toolEvent = buildToolUseEvent(merged, state.driver);
3324
3329
  if (toolEvent)
3325
3330
  state.onToolEvent(toolEvent);
3326
3331
  }
3327
- if (wantsText) {
3332
+ if (wantsText && !consumedAsPlan) {
3328
3333
  const formatted = formatToolCallEvent(update, update.sessionUpdate);
3329
3334
  if (formatted) {
3330
3335
  const toolCallId = update.toolCallId;
@@ -3340,7 +3345,7 @@ function parseStreamingChunks(state, line) {
3340
3345
  }
3341
3346
  if (update.sessionUpdate === "plan") {
3342
3347
  const entries = Array.isArray(update.entries) ? update.entries.filter((x) => !!x && typeof x === "object" && typeof x.content === "string" && typeof x.status === "string") : [];
3343
- if (entries.length > 0)
3348
+ if (Array.isArray(update.entries))
3344
3349
  state.onPlan?.(entries);
3345
3350
  return;
3346
3351
  }
@@ -3452,7 +3457,7 @@ function isEmptyToolField(v) {
3452
3457
  function mergeToolCallUpdate(state, toolCallId, update) {
3453
3458
  const prev = state.toolCalls.get(toolCallId) ?? { toolCallId };
3454
3459
  const merged = { ...prev };
3455
- for (const key of ["kind", "title", "rawInput", "content", "rawOutput", "locations", "status"]) {
3460
+ for (const key of ["kind", "title", "toolCallId", "parentToolCallId", "rawInput", "content", "rawOutput", "locations", "status"]) {
3456
3461
  const next = update[key];
3457
3462
  if (!isEmptyToolField(next))
3458
3463
  merged[key] = next;
@@ -3484,19 +3489,7 @@ function buildToolUseEvent(update, driver) {
3484
3489
  const toolCallId = update.toolCallId;
3485
3490
  if (!toolCallId)
3486
3491
  return null;
3487
- const kindRaw = update.kind ?? "";
3488
- const kind = (() => {
3489
- switch (kindRaw) {
3490
- case "read":
3491
- case "search":
3492
- case "execute":
3493
- case "edit":
3494
- case "think":
3495
- return kindRaw;
3496
- default:
3497
- return "other";
3498
- }
3499
- })();
3492
+ const kind = normalizeToolKind(update, driver);
3500
3493
  const title = (update.title ?? "").trim();
3501
3494
  const toolName = title || "Tool";
3502
3495
  const summaryRaw = summarizeToolInput(update.rawInput, title) || summarizeToolInput(update.rawOutput, title);
@@ -3512,8 +3505,8 @@ function buildToolUseEvent(update, driver) {
3512
3505
  const content = update.content;
3513
3506
  const rawOutput = update.rawOutput ?? claudeToolResponse;
3514
3507
  const locations = update.locations;
3515
- const parentToolCallId = claudeMeta?.parentToolUseId?.trim();
3516
- const isSubagent = claudeMeta?.toolName === "Agent" || driver === "qoder" && update._meta?.qoder?.toolName === "Agent" || driver === "kimi" && isKimiSubagentInput(rawInput) || driver === "codex" && isCodexSubagentMeta(update._meta?.codex?.subagent);
3508
+ const parentToolCallId = claudeMeta?.parentToolUseId?.trim() || update.parentToolCallId?.trim();
3509
+ const isSubagent = claudeMeta?.toolName === "Agent" || driver === "qoder" && update._meta?.qoder?.toolName === "Agent" || driver === "kimi" && isKimiSubagentInput(rawInput) || driver === "codex" && isCodexSubagentMeta(update._meta?.codex?.subagent) || driver === "cursor" && isCursorSubagentInput(rawInput, title);
3517
3510
  return {
3518
3511
  toolCallId,
3519
3512
  ...parentToolCallId ? { parentToolCallId } : {},
@@ -3528,6 +3521,147 @@ function buildToolUseEvent(update, driver) {
3528
3521
  status
3529
3522
  };
3530
3523
  }
3524
+ function normalizeCursorPlanUpdate(state, update) {
3525
+ if (state.driver !== "cursor")
3526
+ return;
3527
+ const title = normalizeCursorToolName(update.title);
3528
+ if (!CURSOR_PLAN_TOOL_NAMES.has(title))
3529
+ return;
3530
+ const input = cursorToolInput(update.rawInput);
3531
+ if (!Array.isArray(input?.todos))
3532
+ return;
3533
+ const merge = input.merge === true;
3534
+ if (input.todos.length === 0) {
3535
+ state.cursorPlanEntries.clear();
3536
+ return [];
3537
+ }
3538
+ const patches = input.todos.map((todo, index) => parseCursorPlanTodo(todo, index)).filter((todo) => todo !== undefined);
3539
+ if (patches.length === 0)
3540
+ return;
3541
+ if (!merge)
3542
+ state.cursorPlanEntries.clear();
3543
+ for (const patch of patches) {
3544
+ const previous = state.cursorPlanEntries.get(patch.key);
3545
+ const content = patch.content ?? previous?.content;
3546
+ if (!content)
3547
+ continue;
3548
+ const status = patch.status ?? previous?.status ?? "pending";
3549
+ const priority = patch.priority ?? previous?.priority;
3550
+ state.cursorPlanEntries.set(patch.key, {
3551
+ content,
3552
+ status,
3553
+ ...priority ? { priority } : {}
3554
+ });
3555
+ }
3556
+ return [...state.cursorPlanEntries.values()];
3557
+ }
3558
+ function parseCursorPlanTodo(value, index) {
3559
+ if (!isRecord2(value))
3560
+ return;
3561
+ const id = readFirstString(value, ["id", "todoId", "taskId"]);
3562
+ const content = readFirstString(value, ["content", "task", "description", "title", "text"]);
3563
+ const key = id ? `id:${id}` : content ? `content:${content}` : `index:${index}`;
3564
+ const status = normalizeCursorPlanStatus(value.status ?? value.state);
3565
+ const priority = normalizePlanPriority(value.priority);
3566
+ if (!content && !status && !priority && !id)
3567
+ return;
3568
+ return {
3569
+ key,
3570
+ ...content ? { content } : {},
3571
+ ...status ? { status } : {},
3572
+ ...priority ? { priority } : {}
3573
+ };
3574
+ }
3575
+ function normalizeCursorPlanStatus(value) {
3576
+ if (typeof value !== "string")
3577
+ return;
3578
+ const normalized = value.trim().toLowerCase().replace(/[\s-]+/g, "_").replace(/^todo_status_/, "");
3579
+ switch (normalized) {
3580
+ case "pending":
3581
+ case "todo":
3582
+ case "not_started":
3583
+ case "notstarted":
3584
+ case "incomplete":
3585
+ return "pending";
3586
+ case "in_progress":
3587
+ case "inprogress":
3588
+ case "active":
3589
+ case "working":
3590
+ return "in_progress";
3591
+ case "completed":
3592
+ case "complete":
3593
+ case "done":
3594
+ case "finished":
3595
+ return "completed";
3596
+ default:
3597
+ return;
3598
+ }
3599
+ }
3600
+ function normalizePlanPriority(value) {
3601
+ if (value !== "high" && value !== "medium" && value !== "low")
3602
+ return;
3603
+ return value;
3604
+ }
3605
+ function cursorToolInput(rawInput) {
3606
+ if (!isRecord2(rawInput))
3607
+ return;
3608
+ if (isRecord2(rawInput.args))
3609
+ return rawInput.args;
3610
+ return rawInput;
3611
+ }
3612
+ function normalizeCursorToolName(title) {
3613
+ return (title ?? "").trim().toLowerCase().replace(/[\s_-]+/g, "");
3614
+ }
3615
+ function normalizeToolKind(update, driver) {
3616
+ const kindRaw = update?.kind?.trim().toLowerCase() ?? "";
3617
+ switch (kindRaw) {
3618
+ case "read":
3619
+ case "search":
3620
+ case "execute":
3621
+ case "edit":
3622
+ case "think":
3623
+ return kindRaw;
3624
+ }
3625
+ if (driver !== "cursor")
3626
+ return "other";
3627
+ switch (normalizeCursorToolName(update?.title)) {
3628
+ case "read":
3629
+ case "readfile":
3630
+ return "read";
3631
+ case "grep":
3632
+ case "glob":
3633
+ case "search":
3634
+ return "search";
3635
+ case "shell":
3636
+ case "bash":
3637
+ case "terminal":
3638
+ return "execute";
3639
+ case "strreplace":
3640
+ case "replace":
3641
+ case "edit":
3642
+ case "write":
3643
+ case "delete":
3644
+ return "edit";
3645
+ case "task":
3646
+ case "delegate":
3647
+ case "runsubagent":
3648
+ case "switchmode":
3649
+ case "todowrite":
3650
+ case "createplan":
3651
+ case "updateplan":
3652
+ case "plan":
3653
+ return "think";
3654
+ default:
3655
+ return "other";
3656
+ }
3657
+ }
3658
+ function isCursorSubagentInput(rawInput, title) {
3659
+ const normalizedTitle = normalizeCursorToolName(title);
3660
+ if (!CURSOR_SUBAGENT_TOOL_NAMES.has(normalizedTitle))
3661
+ return false;
3662
+ const input = cursorToolInput(rawInput);
3663
+ return input !== undefined && readFirstString(input, ["subagent_type", "subagentType", "agent", "agentType", "prompt", "instructions"]) !== undefined;
3664
+ }
3531
3665
  function isKimiSubagentInput(rawInput) {
3532
3666
  return isRecord2(rawInput) && readFirstString(rawInput, ["prompt"]) !== undefined && readFirstString(rawInput, ["subagent_type", "subagentType"]) !== undefined;
3533
3667
  }
@@ -3542,6 +3676,12 @@ function summarizeToolInput(rawInput, title = "") {
3542
3676
  }
3543
3677
  if (!isRecord2(rawInput))
3544
3678
  return;
3679
+ const nestedInput = cursorToolInput(rawInput);
3680
+ if (nestedInput !== rawInput) {
3681
+ const nestedSummary = summarizeToolInput(nestedInput, title);
3682
+ if (nestedSummary)
3683
+ return nestedSummary;
3684
+ }
3545
3685
  const taskSummary = summarizeTaskInput(rawInput, title);
3546
3686
  if (taskSummary)
3547
3687
  return taskSummary;
@@ -3562,6 +3702,16 @@ function summarizeToolInput(rawInput, title = "") {
3562
3702
  return parts.join(" ");
3563
3703
  }
3564
3704
  }
3705
+ const globPattern = readFirstString(rawInput, ["glob_pattern"]);
3706
+ if (globPattern) {
3707
+ const targetDirectory = readFirstString(rawInput, ["target_directory"]);
3708
+ return targetDirectory ? `${globPattern} in ${targetDirectory}` : globPattern;
3709
+ }
3710
+ const mode = readFirstString(rawInput, ["target_mode_id", "mode_id"]);
3711
+ const explanation = readFirstString(rawInput, ["explanation"]);
3712
+ if (mode || explanation) {
3713
+ return mode && explanation ? `${mode}: ${explanation}` : mode ?? explanation;
3714
+ }
3565
3715
  return readFirstString(rawInput, [
3566
3716
  "path",
3567
3717
  "file",
@@ -3575,6 +3725,7 @@ function summarizeToolInput(rawInput, title = "") {
3575
3725
  "pattern",
3576
3726
  "text",
3577
3727
  "search",
3728
+ "working_directory",
3578
3729
  "name",
3579
3730
  "description"
3580
3731
  ]);
@@ -3681,7 +3832,7 @@ function isGenericToolTitle(kind, title) {
3681
3832
  }
3682
3833
  return false;
3683
3834
  }
3684
- var SENTENCE_TERMINAL_AT_END, PARAGRAPH_BOUNDARY_AT_END, PARAGRAPH_BOUNDARY_AT_START, LINE_BREAK_AT_END, LINE_BREAK_AT_START, PARTIAL_CRLF_PARAGRAPH_BOUNDARY_AT_END, USAGE_BREAKDOWN_FIELDS;
3835
+ var SENTENCE_TERMINAL_AT_END, PARAGRAPH_BOUNDARY_AT_END, PARAGRAPH_BOUNDARY_AT_START, LINE_BREAK_AT_END, LINE_BREAK_AT_START, PARTIAL_CRLF_PARAGRAPH_BOUNDARY_AT_END, CURSOR_PLAN_TOOL_NAMES, CURSOR_SUBAGENT_TOOL_NAMES, USAGE_BREAKDOWN_FIELDS;
3685
3836
  var init_streaming_prompt = __esm(() => {
3686
3837
  init_background_followup();
3687
3838
  init_tool_kind_emoji();
@@ -3691,6 +3842,8 @@ var init_streaming_prompt = __esm(() => {
3691
3842
  LINE_BREAK_AT_END = /\r?\n[\t ]*$/;
3692
3843
  LINE_BREAK_AT_START = /^[\t ]*\r?\n/;
3693
3844
  PARTIAL_CRLF_PARAGRAPH_BOUNDARY_AT_END = /\r?\n[\t ]*\r$/;
3845
+ CURSOR_PLAN_TOOL_NAMES = new Set(["todowrite", "createplan", "updateplan", "plan"]);
3846
+ CURSOR_SUBAGENT_TOOL_NAMES = new Set(["task", "delegate", "runsubagent", "subagent"]);
3694
3847
  USAGE_BREAKDOWN_FIELDS = [
3695
3848
  ["inputTokens", ["inputTokens", "input_tokens"]],
3696
3849
  ["outputTokens", ["outputTokens", "output_tokens"]],
package/dist/cli.js CHANGED
@@ -52653,6 +52653,7 @@ function createStreamingPromptState(formatToolCalls = false, options) {
52653
52653
  emittedToolCallIds: new Set,
52654
52654
  positionedToolCallIds: new Set,
52655
52655
  toolCalls: new Map,
52656
+ cursorPlanEntries: new Map,
52656
52657
  toolEventMode,
52657
52658
  driver,
52658
52659
  rawStream,
@@ -52711,13 +52712,17 @@ function parseStreamingChunks(state, line) {
52711
52712
  }
52712
52713
  const wantsStructured = state.toolEventMode === "structured" || state.toolEventMode === "both";
52713
52714
  const wantsText = (state.toolEventMode === "text" || state.toolEventMode === "both") && state.formatToolCalls;
52714
- if (wantsStructured && state.onToolEvent) {
52715
- const merged = update.toolCallId ? mergeToolCallUpdate(state, update.toolCallId, update) : update;
52715
+ const merged = update.toolCallId && (state.onToolEvent || state.onPlan) ? mergeToolCallUpdate(state, update.toolCallId, update) : update;
52716
+ const cursorPlan = normalizeCursorPlanUpdate(state, merged);
52717
+ const consumedAsPlan = cursorPlan !== undefined && state.onPlan !== undefined;
52718
+ if (consumedAsPlan) {
52719
+ state.onPlan?.(cursorPlan);
52720
+ } else if (wantsStructured && state.onToolEvent) {
52716
52721
  const toolEvent = buildToolUseEvent(merged, state.driver);
52717
52722
  if (toolEvent)
52718
52723
  state.onToolEvent(toolEvent);
52719
52724
  }
52720
- if (wantsText) {
52725
+ if (wantsText && !consumedAsPlan) {
52721
52726
  const formatted = formatToolCallEvent(update, update.sessionUpdate);
52722
52727
  if (formatted) {
52723
52728
  const toolCallId = update.toolCallId;
@@ -52733,7 +52738,7 @@ function parseStreamingChunks(state, line) {
52733
52738
  }
52734
52739
  if (update.sessionUpdate === "plan") {
52735
52740
  const entries = Array.isArray(update.entries) ? update.entries.filter((x) => !!x && typeof x === "object" && typeof x.content === "string" && typeof x.status === "string") : [];
52736
- if (entries.length > 0)
52741
+ if (Array.isArray(update.entries))
52737
52742
  state.onPlan?.(entries);
52738
52743
  return;
52739
52744
  }
@@ -52845,7 +52850,7 @@ function isEmptyToolField(v) {
52845
52850
  function mergeToolCallUpdate(state, toolCallId, update) {
52846
52851
  const prev = state.toolCalls.get(toolCallId) ?? { toolCallId };
52847
52852
  const merged = { ...prev };
52848
- for (const key of ["kind", "title", "rawInput", "content", "rawOutput", "locations", "status"]) {
52853
+ for (const key of ["kind", "title", "toolCallId", "parentToolCallId", "rawInput", "content", "rawOutput", "locations", "status"]) {
52849
52854
  const next = update[key];
52850
52855
  if (!isEmptyToolField(next))
52851
52856
  merged[key] = next;
@@ -52877,19 +52882,7 @@ function buildToolUseEvent(update, driver) {
52877
52882
  const toolCallId = update.toolCallId;
52878
52883
  if (!toolCallId)
52879
52884
  return null;
52880
- const kindRaw = update.kind ?? "";
52881
- const kind = (() => {
52882
- switch (kindRaw) {
52883
- case "read":
52884
- case "search":
52885
- case "execute":
52886
- case "edit":
52887
- case "think":
52888
- return kindRaw;
52889
- default:
52890
- return "other";
52891
- }
52892
- })();
52885
+ const kind = normalizeToolKind(update, driver);
52893
52886
  const title = (update.title ?? "").trim();
52894
52887
  const toolName = title || "Tool";
52895
52888
  const summaryRaw = summarizeToolInput(update.rawInput, title) || summarizeToolInput(update.rawOutput, title);
@@ -52905,8 +52898,8 @@ function buildToolUseEvent(update, driver) {
52905
52898
  const content = update.content;
52906
52899
  const rawOutput = update.rawOutput ?? claudeToolResponse;
52907
52900
  const locations = update.locations;
52908
- const parentToolCallId = claudeMeta?.parentToolUseId?.trim();
52909
- const isSubagent = claudeMeta?.toolName === "Agent" || driver === "qoder" && update._meta?.qoder?.toolName === "Agent" || driver === "kimi" && isKimiSubagentInput(rawInput) || driver === "codex" && isCodexSubagentMeta(update._meta?.codex?.subagent);
52901
+ const parentToolCallId = claudeMeta?.parentToolUseId?.trim() || update.parentToolCallId?.trim();
52902
+ const isSubagent = claudeMeta?.toolName === "Agent" || driver === "qoder" && update._meta?.qoder?.toolName === "Agent" || driver === "kimi" && isKimiSubagentInput(rawInput) || driver === "codex" && isCodexSubagentMeta(update._meta?.codex?.subagent) || driver === "cursor" && isCursorSubagentInput(rawInput, title);
52910
52903
  return {
52911
52904
  toolCallId,
52912
52905
  ...parentToolCallId ? { parentToolCallId } : {},
@@ -52921,6 +52914,147 @@ function buildToolUseEvent(update, driver) {
52921
52914
  status
52922
52915
  };
52923
52916
  }
52917
+ function normalizeCursorPlanUpdate(state, update) {
52918
+ if (state.driver !== "cursor")
52919
+ return;
52920
+ const title = normalizeCursorToolName(update.title);
52921
+ if (!CURSOR_PLAN_TOOL_NAMES.has(title))
52922
+ return;
52923
+ const input = cursorToolInput(update.rawInput);
52924
+ if (!Array.isArray(input?.todos))
52925
+ return;
52926
+ const merge2 = input.merge === true;
52927
+ if (input.todos.length === 0) {
52928
+ state.cursorPlanEntries.clear();
52929
+ return [];
52930
+ }
52931
+ const patches = input.todos.map((todo, index) => parseCursorPlanTodo(todo, index)).filter((todo) => todo !== undefined);
52932
+ if (patches.length === 0)
52933
+ return;
52934
+ if (!merge2)
52935
+ state.cursorPlanEntries.clear();
52936
+ for (const patch of patches) {
52937
+ const previous = state.cursorPlanEntries.get(patch.key);
52938
+ const content = patch.content ?? previous?.content;
52939
+ if (!content)
52940
+ continue;
52941
+ const status = patch.status ?? previous?.status ?? "pending";
52942
+ const priority = patch.priority ?? previous?.priority;
52943
+ state.cursorPlanEntries.set(patch.key, {
52944
+ content,
52945
+ status,
52946
+ ...priority ? { priority } : {}
52947
+ });
52948
+ }
52949
+ return [...state.cursorPlanEntries.values()];
52950
+ }
52951
+ function parseCursorPlanTodo(value, index) {
52952
+ if (!isRecord4(value))
52953
+ return;
52954
+ const id = readFirstString(value, ["id", "todoId", "taskId"]);
52955
+ const content = readFirstString(value, ["content", "task", "description", "title", "text"]);
52956
+ const key = id ? `id:${id}` : content ? `content:${content}` : `index:${index}`;
52957
+ const status = normalizeCursorPlanStatus(value.status ?? value.state);
52958
+ const priority = normalizePlanPriority(value.priority);
52959
+ if (!content && !status && !priority && !id)
52960
+ return;
52961
+ return {
52962
+ key,
52963
+ ...content ? { content } : {},
52964
+ ...status ? { status } : {},
52965
+ ...priority ? { priority } : {}
52966
+ };
52967
+ }
52968
+ function normalizeCursorPlanStatus(value) {
52969
+ if (typeof value !== "string")
52970
+ return;
52971
+ const normalized = value.trim().toLowerCase().replace(/[\s-]+/g, "_").replace(/^todo_status_/, "");
52972
+ switch (normalized) {
52973
+ case "pending":
52974
+ case "todo":
52975
+ case "not_started":
52976
+ case "notstarted":
52977
+ case "incomplete":
52978
+ return "pending";
52979
+ case "in_progress":
52980
+ case "inprogress":
52981
+ case "active":
52982
+ case "working":
52983
+ return "in_progress";
52984
+ case "completed":
52985
+ case "complete":
52986
+ case "done":
52987
+ case "finished":
52988
+ return "completed";
52989
+ default:
52990
+ return;
52991
+ }
52992
+ }
52993
+ function normalizePlanPriority(value) {
52994
+ if (value !== "high" && value !== "medium" && value !== "low")
52995
+ return;
52996
+ return value;
52997
+ }
52998
+ function cursorToolInput(rawInput) {
52999
+ if (!isRecord4(rawInput))
53000
+ return;
53001
+ if (isRecord4(rawInput.args))
53002
+ return rawInput.args;
53003
+ return rawInput;
53004
+ }
53005
+ function normalizeCursorToolName(title) {
53006
+ return (title ?? "").trim().toLowerCase().replace(/[\s_-]+/g, "");
53007
+ }
53008
+ function normalizeToolKind(update, driver) {
53009
+ const kindRaw = update?.kind?.trim().toLowerCase() ?? "";
53010
+ switch (kindRaw) {
53011
+ case "read":
53012
+ case "search":
53013
+ case "execute":
53014
+ case "edit":
53015
+ case "think":
53016
+ return kindRaw;
53017
+ }
53018
+ if (driver !== "cursor")
53019
+ return "other";
53020
+ switch (normalizeCursorToolName(update?.title)) {
53021
+ case "read":
53022
+ case "readfile":
53023
+ return "read";
53024
+ case "grep":
53025
+ case "glob":
53026
+ case "search":
53027
+ return "search";
53028
+ case "shell":
53029
+ case "bash":
53030
+ case "terminal":
53031
+ return "execute";
53032
+ case "strreplace":
53033
+ case "replace":
53034
+ case "edit":
53035
+ case "write":
53036
+ case "delete":
53037
+ return "edit";
53038
+ case "task":
53039
+ case "delegate":
53040
+ case "runsubagent":
53041
+ case "switchmode":
53042
+ case "todowrite":
53043
+ case "createplan":
53044
+ case "updateplan":
53045
+ case "plan":
53046
+ return "think";
53047
+ default:
53048
+ return "other";
53049
+ }
53050
+ }
53051
+ function isCursorSubagentInput(rawInput, title) {
53052
+ const normalizedTitle = normalizeCursorToolName(title);
53053
+ if (!CURSOR_SUBAGENT_TOOL_NAMES.has(normalizedTitle))
53054
+ return false;
53055
+ const input = cursorToolInput(rawInput);
53056
+ return input !== undefined && readFirstString(input, ["subagent_type", "subagentType", "agent", "agentType", "prompt", "instructions"]) !== undefined;
53057
+ }
52924
53058
  function isKimiSubagentInput(rawInput) {
52925
53059
  return isRecord4(rawInput) && readFirstString(rawInput, ["prompt"]) !== undefined && readFirstString(rawInput, ["subagent_type", "subagentType"]) !== undefined;
52926
53060
  }
@@ -52935,6 +53069,12 @@ function summarizeToolInput(rawInput, title = "") {
52935
53069
  }
52936
53070
  if (!isRecord4(rawInput))
52937
53071
  return;
53072
+ const nestedInput = cursorToolInput(rawInput);
53073
+ if (nestedInput !== rawInput) {
53074
+ const nestedSummary = summarizeToolInput(nestedInput, title);
53075
+ if (nestedSummary)
53076
+ return nestedSummary;
53077
+ }
52938
53078
  const taskSummary = summarizeTaskInput(rawInput, title);
52939
53079
  if (taskSummary)
52940
53080
  return taskSummary;
@@ -52955,6 +53095,16 @@ function summarizeToolInput(rawInput, title = "") {
52955
53095
  return parts.join(" ");
52956
53096
  }
52957
53097
  }
53098
+ const globPattern = readFirstString(rawInput, ["glob_pattern"]);
53099
+ if (globPattern) {
53100
+ const targetDirectory = readFirstString(rawInput, ["target_directory"]);
53101
+ return targetDirectory ? `${globPattern} in ${targetDirectory}` : globPattern;
53102
+ }
53103
+ const mode = readFirstString(rawInput, ["target_mode_id", "mode_id"]);
53104
+ const explanation = readFirstString(rawInput, ["explanation"]);
53105
+ if (mode || explanation) {
53106
+ return mode && explanation ? `${mode}: ${explanation}` : mode ?? explanation;
53107
+ }
52958
53108
  return readFirstString(rawInput, [
52959
53109
  "path",
52960
53110
  "file",
@@ -52968,6 +53118,7 @@ function summarizeToolInput(rawInput, title = "") {
52968
53118
  "pattern",
52969
53119
  "text",
52970
53120
  "search",
53121
+ "working_directory",
52971
53122
  "name",
52972
53123
  "description"
52973
53124
  ]);
@@ -53074,7 +53225,7 @@ function isGenericToolTitle(kind, title) {
53074
53225
  }
53075
53226
  return false;
53076
53227
  }
53077
- var SENTENCE_TERMINAL_AT_END, PARAGRAPH_BOUNDARY_AT_END, PARAGRAPH_BOUNDARY_AT_START, LINE_BREAK_AT_END, LINE_BREAK_AT_START, PARTIAL_CRLF_PARAGRAPH_BOUNDARY_AT_END, USAGE_BREAKDOWN_FIELDS;
53228
+ var SENTENCE_TERMINAL_AT_END, PARAGRAPH_BOUNDARY_AT_END, PARAGRAPH_BOUNDARY_AT_START, LINE_BREAK_AT_END, LINE_BREAK_AT_START, PARTIAL_CRLF_PARAGRAPH_BOUNDARY_AT_END, CURSOR_PLAN_TOOL_NAMES, CURSOR_SUBAGENT_TOOL_NAMES, USAGE_BREAKDOWN_FIELDS;
53078
53229
  var init_streaming_prompt = __esm(() => {
53079
53230
  init_background_followup();
53080
53231
  init_tool_kind_emoji();
@@ -53084,6 +53235,8 @@ var init_streaming_prompt = __esm(() => {
53084
53235
  LINE_BREAK_AT_END = /\r?\n[\t ]*$/;
53085
53236
  LINE_BREAK_AT_START = /^[\t ]*\r?\n/;
53086
53237
  PARTIAL_CRLF_PARAGRAPH_BOUNDARY_AT_END = /\r?\n[\t ]*\r$/;
53238
+ CURSOR_PLAN_TOOL_NAMES = new Set(["todowrite", "createplan", "updateplan", "plan"]);
53239
+ CURSOR_SUBAGENT_TOOL_NAMES = new Set(["task", "delegate", "runsubagent", "subagent"]);
53087
53240
  USAGE_BREAKDOWN_FIELDS = [
53088
53241
  ["inputTokens", ["inputTokens", "input_tokens"]],
53089
53242
  ["outputTokens", ["outputTokens", "output_tokens"]],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ganglion/xacpx",
3
- "version": "0.20.1",
3
+ "version": "0.20.2",
4
4
  "description": "随时随地通过聊天频道(微信 / 飞书 / 元宝等)远程控制 `acpx` 上的 Claude Code、Codex 等 Agents。",
5
5
  "keywords": [
6
6
  "acpx",