@ycodium-ai/agent-kimi 0.2.2974 → 0.2.2978

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.
Files changed (2) hide show
  1. package/dist/index.js +862 -833
  2. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -24480,64 +24480,146 @@ function deriveToolActivityPresentation(input2) {
24480
24480
  };
24481
24481
  }
24482
24482
 
24483
- // ../../packages/ycodium-acp-executor/src/events.ts
24484
- function canonicalRequestTypeFromAcpKind(kind) {
24485
- switch (kind) {
24486
- case "execute":
24487
- return "exec_command_approval";
24488
- case "read":
24489
- return "file_read_approval";
24490
- case "edit":
24491
- case "delete":
24492
- case "move":
24493
- return "file_change_approval";
24494
- case "fetch":
24495
- return "web_fetch_approval";
24496
- case "search":
24497
- return "web_search_approval";
24498
- default:
24499
- return "dynamic_tool_call";
24483
+ // ../../packages/ycodium-acp-executor/src/runtime-model.ts
24484
+ function extractModelConfigId(sessionResponse) {
24485
+ const configOptions = sessionResponse.configOptions;
24486
+ if (!configOptions) return void 0;
24487
+ for (const opt of configOptions) {
24488
+ if (opt.category === "model" && opt.id.trim().length > 0) {
24489
+ return opt.id.trim();
24490
+ }
24500
24491
  }
24492
+ return configOptions.find((opt) => opt.id.trim() === "model" && opt.type === "select") ? "model" : void 0;
24501
24493
  }
24502
- function fileChangesFromAcpPermission(permissionRequest) {
24503
- const content = permissionRequest.toolCall?.data["content"];
24504
- const changes = Array.isArray(content) ? content.flatMap((entry) => {
24505
- if (entry === null || typeof entry !== "object") {
24506
- return [];
24494
+ function findSessionConfigOption(configOptions, configId) {
24495
+ if (!configOptions) {
24496
+ return void 0;
24497
+ }
24498
+ const normalizedConfigId = configId.trim();
24499
+ if (!normalizedConfigId) {
24500
+ return void 0;
24501
+ }
24502
+ return configOptions.find((option) => option.id.trim() === normalizedConfigId);
24503
+ }
24504
+ function collectSessionConfigOptionValues(configOption) {
24505
+ if (configOption.type !== "select" || !configOption.options) {
24506
+ return [];
24507
+ }
24508
+ return configOption.options.flatMap(
24509
+ (entry) => "value" in entry ? [entry.value] : entry.options.map((option) => option.value)
24510
+ );
24511
+ }
24512
+ function collectSessionModelIds(models) {
24513
+ if (!isRecord3(models) || !Array.isArray(models["availableModels"])) {
24514
+ return [];
24515
+ }
24516
+ return models["availableModels"].flatMap(
24517
+ (model) => isRecord3(model) && typeof model["modelId"] === "string" ? [model["modelId"]] : []
24518
+ );
24519
+ }
24520
+ function catalogModelLastSegment(value) {
24521
+ if (value.startsWith("[")) {
24522
+ let parsed;
24523
+ try {
24524
+ parsed = JSON.parse(value);
24525
+ } catch {
24526
+ return void 0;
24507
24527
  }
24508
- const block = entry;
24509
- if (block["type"] !== "diff" || typeof block["path"] !== "string" || typeof block["newText"] !== "string") {
24510
- return [];
24528
+ if (!Array.isArray(parsed) || parsed.length < 2) return void 0;
24529
+ const last = parsed[parsed.length - 1];
24530
+ return typeof last === "string" ? last : void 0;
24531
+ }
24532
+ const separator = value.indexOf("/");
24533
+ return separator > 0 && separator < value.length - 1 ? value.slice(separator + 1) : void 0;
24534
+ }
24535
+ function matchAdvertisedModelValue(requestedModelId, advertisedValues) {
24536
+ const wanted = requestedModelId.trim();
24537
+ if (!wanted) return void 0;
24538
+ if (advertisedValues.includes(wanted)) return wanted;
24539
+ const byLastSegment = advertisedValues.filter(
24540
+ (value) => catalogModelLastSegment(value) === wanted
24541
+ );
24542
+ return byLastSegment.length === 1 ? byLastSegment[0] : void 0;
24543
+ }
24544
+ function parseSessionModeState(sessionResponse) {
24545
+ const modes = sessionResponse.modes;
24546
+ if (!modes) return void 0;
24547
+ const currentModeId = modes.currentModeId.trim();
24548
+ if (!currentModeId) {
24549
+ return void 0;
24550
+ }
24551
+ const availableModes = [];
24552
+ for (const mode of modes.availableModes) {
24553
+ const id = mode.id.trim();
24554
+ const name = mode.name.trim();
24555
+ if (!id || !name) {
24556
+ continue;
24511
24557
  }
24512
- const oldText = typeof block["oldText"] === "string" ? block["oldText"] : void 0;
24513
- return [
24514
- {
24515
- path: block["path"],
24516
- changeKind: oldText === void 0 ? "add" : "modify",
24517
- content: {
24518
- kind: "replace",
24519
- ...oldText !== void 0 ? { oldText } : {},
24520
- newText: block["newText"]
24521
- }
24522
- }
24523
- ];
24524
- }) : [];
24525
- if (changes.length > 0) {
24526
- return changes;
24558
+ const description = mode.description?.trim() || void 0;
24559
+ availableModes.push(
24560
+ description !== void 0 ? { id, name, description } : { id, name }
24561
+ );
24527
24562
  }
24528
- if (canonicalRequestTypeFromAcpKind(permissionRequest.kind) !== "file_change_approval") {
24563
+ if (availableModes.length === 0) {
24529
24564
  return void 0;
24530
24565
  }
24531
- const locations = permissionRequest.toolCall?.data["locations"];
24532
- const paths = Array.isArray(locations) ? locations.flatMap((entry) => {
24533
- const path = entry?.["path"];
24534
- return typeof path === "string" && path.trim().length > 0 ? [path] : [];
24535
- }) : [];
24536
- return paths.length > 0 ? paths.map((path) => ({ path, omitted: "unavailable" })) : void 0;
24566
+ return {
24567
+ currentModeId,
24568
+ availableModes
24569
+ };
24537
24570
  }
24538
- function runtimeItemStatusFromAcpToolStatus(status) {
24539
- switch (status) {
24571
+ function acpCommandsToSlashCommands(commands) {
24572
+ return commands.map((command) => ({
24573
+ name: command.name,
24574
+ ...command.description === void 0 ? {} : { description: command.description },
24575
+ ...command.inputHint === void 0 ? {} : { input: { hint: command.inputHint } }
24576
+ }));
24577
+ }
24578
+ function parseAvailableCommandsUpdate(params) {
24579
+ const update = params.update;
24580
+ if (update["sessionUpdate"] !== "available_commands_update") {
24581
+ return void 0;
24582
+ }
24583
+ const availableCommands = update["availableCommands"];
24584
+ if (!Array.isArray(availableCommands)) {
24585
+ return [];
24586
+ }
24587
+ const commands = [];
24588
+ for (const command of availableCommands) {
24589
+ if (!isRecord3(command)) {
24590
+ continue;
24591
+ }
24592
+ const name = typeof command["name"] === "string" ? command["name"].trim() : "";
24593
+ if (!name) {
24594
+ continue;
24595
+ }
24596
+ const description = typeof command["description"] === "string" ? command["description"].trim() || void 0 : void 0;
24597
+ const input2 = isRecord3(command["input"]) ? command["input"] : void 0;
24598
+ const inputHint = typeof input2?.["hint"] === "string" ? input2["hint"].trim() || void 0 : void 0;
24599
+ commands.push({
24600
+ name,
24601
+ ...description ? { description } : {},
24602
+ ...inputHint ? { inputHint } : {}
24603
+ });
24604
+ }
24605
+ return commands;
24606
+ }
24607
+ function normalizePlanStepStatus(raw) {
24608
+ switch (raw) {
24609
+ case "completed":
24610
+ return "completed";
24611
+ case "in_progress":
24612
+ case "inProgress":
24613
+ return "inProgress";
24614
+ default:
24615
+ return "pending";
24616
+ }
24617
+ }
24618
+ function normalizeToolCallStatus(raw, fallback) {
24619
+ switch (raw) {
24540
24620
  case "pending":
24621
+ return "pending";
24622
+ case "in_progress":
24541
24623
  case "inProgress":
24542
24624
  return "inProgress";
24543
24625
  case "completed":
@@ -24545,466 +24627,453 @@ function runtimeItemStatusFromAcpToolStatus(status) {
24545
24627
  case "failed":
24546
24628
  return "failed";
24547
24629
  default:
24548
- return void 0;
24630
+ return fallback;
24549
24631
  }
24550
24632
  }
24551
- function makeAcpRequestOpenedEvent(input2) {
24552
- const requestType = canonicalRequestTypeFromAcpKind(input2.permissionRequest.kind);
24553
- const toolName = requestType === "dynamic_tool_call" ? input2.permissionRequest.toolCall?.title : void 0;
24554
- return {
24555
- type: "request.opened",
24556
- ...input2.stamp,
24557
- provider: input2.provider,
24558
- threadId: input2.threadId,
24559
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
24560
- requestId: input2.requestId,
24561
- payload: {
24562
- requestType,
24563
- detail: input2.detail,
24564
- ...toolName ? { toolName } : {},
24565
- args: input2.args,
24566
- ...input2.options ? { options: input2.options } : {},
24567
- ...input2.fileChanges ? { fileChanges: input2.fileChanges } : {},
24568
- declineReasonRelay: "queued"
24569
- },
24570
- raw: {
24571
- source: input2.source,
24572
- method: input2.method,
24573
- payload: input2.rawPayload
24633
+ function normalizeCommandValue2(value) {
24634
+ if (typeof value === "string" && value.trim().length > 0) {
24635
+ return value.trim();
24636
+ }
24637
+ if (!Array.isArray(value)) {
24638
+ return void 0;
24639
+ }
24640
+ const parts = [];
24641
+ for (const entry of value) {
24642
+ if (typeof entry === "string") {
24643
+ const part = entry.trim();
24644
+ if (part.length > 0) {
24645
+ parts.push(part);
24646
+ }
24574
24647
  }
24575
- };
24648
+ }
24649
+ return parts.length > 0 ? parts.join(" ") : void 0;
24576
24650
  }
24577
- function makeAcpRequestResolvedEvent(input2) {
24578
- return {
24579
- type: "request.resolved",
24580
- ...input2.stamp,
24581
- provider: input2.provider,
24582
- threadId: input2.threadId,
24583
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
24584
- requestId: input2.requestId,
24585
- payload: {
24586
- requestType: canonicalRequestTypeFromAcpKind(input2.permissionRequest.kind),
24587
- decision: input2.decision,
24588
- ...input2.reason ? { reason: input2.reason } : {}
24589
- }
24590
- };
24651
+ function extractCommandFromTitle2(title) {
24652
+ if (!title) {
24653
+ return void 0;
24654
+ }
24655
+ const match = /`([^`]+)`/.exec(title);
24656
+ return match?.[1]?.trim() || void 0;
24591
24657
  }
24592
- function makeAcpPlanUpdatedEvent(input2) {
24593
- return {
24594
- type: "turn.plan.updated",
24595
- ...input2.stamp,
24596
- provider: input2.provider,
24597
- threadId: input2.threadId,
24598
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
24599
- payload: input2.payload,
24600
- raw: {
24601
- source: input2.source,
24602
- method: input2.method,
24603
- payload: input2.rawPayload
24604
- }
24605
- };
24606
- }
24607
- function makeAcpToolCallEvent(input2) {
24608
- const runtimeStatus = runtimeItemStatusFromAcpToolStatus(input2.toolCall.status);
24609
- const { data } = input2.toolCall;
24610
- return {
24611
- type: input2.toolCall.status === "completed" || input2.toolCall.status === "failed" ? "item.completed" : "item.updated",
24612
- ...input2.stamp,
24613
- provider: input2.provider,
24614
- threadId: input2.threadId,
24615
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
24616
- itemId: input2.toolCall.toolCallId,
24617
- payload: {
24618
- itemType: canonicalItemTypeFromAcpToolKind(input2.toolCall.kind),
24619
- ...runtimeStatus ? { status: runtimeStatus } : {},
24620
- ...input2.toolCall.title ? { title: input2.toolCall.title } : {},
24621
- ...input2.toolCall.detail ? { detail: input2.toolCall.detail } : {},
24622
- ...Object.keys(data).length > 0 ? { data } : {}
24623
- },
24624
- raw: {
24625
- source: "acp.jsonrpc",
24626
- method: "session/update",
24627
- payload: input2.rawPayload
24658
+ function extractToolCallCommand(rawInput, title) {
24659
+ if (isRecord3(rawInput)) {
24660
+ const directCommand = normalizeCommandValue2(rawInput["command"]);
24661
+ if (directCommand) {
24662
+ return directCommand;
24628
24663
  }
24629
- };
24630
- }
24631
- function makeAcpAssistantItemEvent(input2) {
24632
- return {
24633
- type: input2.lifecycle,
24634
- ...input2.stamp,
24635
- provider: input2.provider,
24636
- threadId: input2.threadId,
24637
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
24638
- itemId: input2.itemId,
24639
- payload: {
24640
- itemType: "assistant_message",
24641
- status: input2.lifecycle === "item.completed" ? "completed" : "inProgress"
24664
+ const executable = typeof rawInput["executable"] === "string" ? rawInput["executable"].trim() : "";
24665
+ const args = normalizeCommandValue2(rawInput["args"]);
24666
+ if (executable && args) {
24667
+ return `${executable} ${args}`;
24642
24668
  }
24643
- };
24644
- }
24645
- function makeAcpContentDeltaEvent(input2) {
24646
- return {
24647
- type: "content.delta",
24648
- ...input2.stamp,
24649
- provider: input2.provider,
24650
- threadId: input2.threadId,
24651
- ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
24652
- ...input2.itemId ? { itemId: input2.itemId } : {},
24653
- payload: {
24654
- streamKind: input2.streamKind ?? "assistant_text",
24655
- delta: input2.text
24656
- },
24657
- raw: {
24658
- source: "acp.jsonrpc",
24659
- method: "session/update",
24660
- payload: input2.rawPayload
24669
+ if (executable) {
24670
+ return executable;
24661
24671
  }
24662
- };
24663
- }
24664
-
24665
- // ../../packages/ycodium-acp-executor/src/config-options.ts
24666
- function isRecord4(value) {
24667
- return typeof value === "object" && value !== null && !Array.isArray(value);
24668
- }
24669
- function asString(value) {
24670
- return typeof value === "string" ? value : void 0;
24671
- }
24672
- function normalizedField(option, key) {
24673
- return asString(option[key])?.trim().toLowerCase() ?? "";
24672
+ }
24673
+ return extractCommandFromTitle2(title);
24674
24674
  }
24675
- function looksLikeEffortOption(option) {
24676
- const id = normalizedField(option, "id");
24677
- const name = normalizedField(option, "name");
24678
- return id === "effort" || id === "reasoning" || name === "effort" || name === "reasoning" || name.includes("effort") || name.includes("reasoning") || normalizedField(option, "category") === "thought_level";
24675
+ var TOOL_CALL_CONTENT_MAX_CHARS = 8e3;
24676
+ var TOOL_CALL_CONTENT_TRUNCATION_MARKER = "[Earlier output truncated]\n\n";
24677
+ function boundToolCallOutputText(text) {
24678
+ if (text.length <= TOOL_CALL_CONTENT_MAX_CHARS) {
24679
+ return text;
24680
+ }
24681
+ const tail = text.slice(text.length - TOOL_CALL_CONTENT_MAX_CHARS);
24682
+ return `${TOOL_CALL_CONTENT_TRUNCATION_MARKER}${tail}`;
24679
24683
  }
24680
- function flattenChoices(rawOptions, currentValue) {
24681
- if (!Array.isArray(rawOptions)) return [];
24682
- const out = [];
24683
- const seen = /* @__PURE__ */ new Set();
24684
- const push = (entry) => {
24685
- if (!isRecord4(entry)) return;
24686
- const value = asString(entry["value"]);
24687
- if (value === void 0 || seen.has(value)) return;
24688
- seen.add(value);
24689
- const description = asString(entry["description"])?.trim();
24690
- const name = asString(entry["name"])?.trim();
24691
- out.push({
24692
- value,
24693
- ...name ? { name } : {},
24694
- label: name || value,
24695
- ...description ? { description } : {},
24696
- ...currentValue !== void 0 && currentValue === value ? { isDefault: true } : {}
24697
- });
24698
- };
24699
- for (const entry of rawOptions) {
24700
- if (isRecord4(entry) && Array.isArray(entry["options"])) {
24701
- for (const nested of entry["options"]) push(nested);
24702
- continue;
24684
+ var RAW_OUTPUT_TEXT_FIELDS = ["content", "stdout", "stderr", "output"];
24685
+ function boundToolCallRawOutput(rawOutput) {
24686
+ if (!isRecord3(rawOutput)) {
24687
+ return rawOutput;
24688
+ }
24689
+ let changed = false;
24690
+ const bounded = { ...rawOutput };
24691
+ for (const field of RAW_OUTPUT_TEXT_FIELDS) {
24692
+ const value = rawOutput[field];
24693
+ if (typeof value === "string" && value.length > TOOL_CALL_CONTENT_MAX_CHARS) {
24694
+ bounded[field] = boundToolCallOutputText(value);
24695
+ changed = true;
24703
24696
  }
24704
- push(entry);
24705
24697
  }
24706
- return out;
24707
- }
24708
- function findAcpEffortConfig(configOptions) {
24709
- if (!Array.isArray(configOptions)) return void 0;
24710
- const candidates = configOptions.filter(isRecord4).filter((option) => normalizedField(option, "type") === "select").filter(looksLikeEffortOption);
24711
- if (candidates.length === 0) return void 0;
24712
- const picked = candidates.find((option) => normalizedField(option, "category") === "model_option") ?? candidates.find((option) => normalizedField(option, "id") === "effort") ?? candidates.find((option) => normalizedField(option, "category") === "thought_level") ?? candidates[0];
24713
- if (picked === void 0) return void 0;
24714
- const configId = asString(picked["id"])?.trim();
24715
- if (!configId) return void 0;
24716
- const choices = flattenChoices(picked["options"], asString(picked["currentValue"])?.trim());
24717
- if (choices.length === 0) return void 0;
24718
- return {
24719
- configId,
24720
- label: asString(picked["name"])?.trim() ?? "",
24721
- choices
24722
- };
24723
- }
24724
-
24725
- // ../../packages/ycodium-acp-executor/src/runtime-mode.ts
24726
- function isRecord5(value) {
24727
- return typeof value === "object" && value !== null && !Array.isArray(value);
24728
- }
24729
- function asString2(value) {
24730
- return typeof value === "string" ? value : void 0;
24698
+ return changed ? bounded : rawOutput;
24731
24699
  }
24732
- function acpModeConfigId(setup) {
24733
- if (!isRecord5(setup)) return void 0;
24734
- const configOptions = setup["configOptions"];
24735
- if (!Array.isArray(configOptions)) return void 0;
24736
- for (const option of configOptions) {
24737
- if (!isRecord5(option)) continue;
24738
- if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
24739
- const id = asString2(option["id"])?.trim();
24740
- if (id) return id;
24700
+ function toolCallContentText(entry) {
24701
+ if (entry.type !== "content" || entry.content?.type !== "text") {
24702
+ return void 0;
24741
24703
  }
24742
- return void 0;
24704
+ return entry.content.text;
24743
24705
  }
24744
- function acpCurrentModeId(setup) {
24745
- if (!isRecord5(setup)) return void 0;
24746
- const modes = setup["modes"];
24747
- if (isRecord5(modes)) {
24748
- const current = asString2(modes["currentModeId"])?.trim();
24749
- if (current) return current;
24706
+ function extractTextContentFromToolCallContent(content) {
24707
+ if (!Array.isArray(content)) {
24708
+ return { text: void 0, content: void 0 };
24750
24709
  }
24751
- const configOptions = setup["configOptions"];
24752
- if (Array.isArray(configOptions)) {
24753
- for (const option of configOptions) {
24754
- if (!isRecord5(option)) continue;
24755
- if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
24756
- const current = asString2(option["currentValue"])?.trim();
24757
- if (current) return current;
24710
+ const typed = content;
24711
+ const chunks = [];
24712
+ for (const entry of typed) {
24713
+ const text = toolCallContentText(entry)?.trim();
24714
+ if (text) {
24715
+ chunks.push(text);
24758
24716
  }
24759
24717
  }
24760
- return void 0;
24718
+ if (chunks.length === 0) {
24719
+ return { text: void 0, content: typed };
24720
+ }
24721
+ const joined = chunks.join("\n");
24722
+ if (joined.length <= TOOL_CALL_CONTENT_MAX_CHARS) {
24723
+ return { text: joined, content: typed };
24724
+ }
24725
+ const bounded = boundToolCallOutputText(joined);
24726
+ const lastContributingTextIndex = typed.reduce(
24727
+ (lastIndex, entry, index) => toolCallContentText(entry)?.trim() ? index : lastIndex,
24728
+ -1
24729
+ );
24730
+ const boundedContent = typed.flatMap((entry, index) => {
24731
+ if (toolCallContentText(entry) === void 0) {
24732
+ return [entry];
24733
+ }
24734
+ if (index !== lastContributingTextIndex) {
24735
+ return [];
24736
+ }
24737
+ return [{ type: "content", content: { type: "text", text: bounded } }];
24738
+ });
24739
+ return { text: bounded, content: boundedContent };
24761
24740
  }
24762
-
24763
- // ../../packages/ycodium-acp-executor/src/handshake.ts
24764
- function acpInitializePayload(clientInfo, overrides) {
24765
- return {
24766
- protocolVersion: PROTOCOL_VERSION,
24767
- clientCapabilities: {
24768
- fs: {
24769
- readTextFile: false,
24770
- writeTextFile: false,
24771
- ...overrides?.fs
24772
- },
24773
- terminal: overrides?.terminal ?? false
24774
- },
24775
- clientInfo
24776
- };
24741
+ function normalizeToolKind(kind) {
24742
+ return typeof kind === "string" && kind.trim().length > 0 ? kind.trim() : void 0;
24777
24743
  }
24778
-
24779
- // ../../packages/ycodium-acp-executor/src/config-option-wiring.ts
24780
- var VENDOR_CATEGORY_PREFIX = "_";
24781
- var ACP_CONFIG_CATEGORY_HANDLING = {
24782
- mode: {
24783
- consumed: true,
24784
- via: "runtime-mode.ts\uFF1AacpAvailableModes / acpCurrentModeId / acpModeConfigId"
24785
- },
24786
- model: {
24787
- consumed: true,
24788
- via: "runtime-model.ts:extractModelConfigId \u2192 executor.ts:applyRequestedModel"
24789
- },
24790
- thought_level: {
24791
- consumed: true,
24792
- via: "config-options.ts:findAcpEffortConfig \u2192 executor.ts:applyRequestedEffort"
24793
- },
24794
- model_option: {
24795
- consumed: true,
24796
- // 精确说法:它不是**识别器**,是**优先级**。`looksLikeEffortOption` 先筛出候选,
24797
- // 标了 `model_option` 的在候选里排第一(厂商自己标的最准),排在 id 叫 `effort`
24798
- // 的和标 `thought_level` 的前面。光有这个 category 而 id/name 不像力度档的,
24799
- // 压根进不了候选。
24800
- via: "config-options.ts:findAcpEffortConfig\uFF08\u5019\u9009\u91CC\u7684\u6700\u9AD8\u4F18\u5148\u7EA7\uFF0C\u538B\u8FC7 thought_level\uFF09"
24801
- },
24802
- model_config: {
24803
- consumed: false,
24804
- note: "\u53EA\u6709\u5BBF\u4E3B\u7684 CursorProvider \u6D88\u8D39\u8FC7\uFF08context / fast / thinking \u4E09\u4E2A\u5F00\u5173\uFF09\u3002Cursor 2026-09-20 \u5E9F\u5F03\u5220\u9664\uFF0C\u8FD9\u4E00\u7C7B\u73B0\u5728\u6CA1\u6709\u6D88\u8D39\u70B9\uFF1B\u6CA1\u89C1\u8FC7\u522B\u5BB6\u7684\u771F\u5B9E\u8F7D\u8377\uFF0C\u5148\u8BB0\u8D26\u4E0D\u731C\u5F62\u72B6\u3002"
24744
+ function makeToolCallState(input2, options) {
24745
+ const toolCallId = typeof input2.toolCallId === "string" ? input2.toolCallId.trim() : "";
24746
+ if (!toolCallId) {
24747
+ return void 0;
24805
24748
  }
24806
- };
24807
- var KNOWN_CATEGORIES = new Set(Object.keys(ACP_CONFIG_CATEGORY_HANDLING));
24808
- function unhandledConfigCategories(configOptions) {
24809
- if (!configOptions) return [];
24810
- const seen = /* @__PURE__ */ new Set();
24811
- const out = [];
24812
- for (const option of configOptions) {
24813
- const category = option.category?.trim();
24814
- if (!category) continue;
24815
- if (KNOWN_CATEGORIES.has(category)) continue;
24816
- if (seen.has(category)) continue;
24817
- seen.add(category);
24818
- out.push({
24819
- category,
24820
- optionId: option.id.trim(),
24821
- vendorExtension: category.startsWith(VENDOR_CATEGORY_PREFIX)
24822
- });
24749
+ const title = typeof input2.title === "string" ? input2.title.trim() || void 0 : void 0;
24750
+ const command = extractToolCallCommand(input2.rawInput, title);
24751
+ const extractedContent = extractTextContentFromToolCallContent(input2.content);
24752
+ const textContent = extractedContent.text;
24753
+ const normalizedTitle = title && title.toLowerCase() !== "terminal" && title.toLowerCase() !== "tool call" ? title : void 0;
24754
+ const data = { toolCallId };
24755
+ const kind = normalizeToolKind(input2.kind);
24756
+ if (kind) {
24757
+ data["kind"] = kind;
24823
24758
  }
24824
- return out;
24825
- }
24826
-
24827
- // ../../packages/ycodium-acp-executor/src/mutex.ts
24828
- var Mutex = class {
24829
- locked = false;
24830
- waiters = [];
24831
- get isLocked() {
24832
- return this.locked;
24759
+ const name = readAcpText(input2, "name");
24760
+ if (name) {
24761
+ data["name"] = name;
24833
24762
  }
24834
- acquire() {
24835
- if (!this.locked) {
24836
- this.locked = true;
24837
- return Promise.resolve();
24838
- }
24839
- return new Promise((resolve3) => {
24840
- this.waiters.push(resolve3);
24841
- });
24763
+ if (command) {
24764
+ data["command"] = command;
24842
24765
  }
24843
- tryAcquire() {
24844
- if (this.locked) {
24845
- return false;
24846
- }
24847
- this.locked = true;
24848
- return true;
24766
+ if (input2.rawInput !== void 0) {
24767
+ data["rawInput"] = input2.rawInput;
24849
24768
  }
24850
- release() {
24851
- const next = this.waiters.shift();
24852
- if (next) {
24853
- next();
24854
- return;
24769
+ if (input2.rawOutput !== void 0) {
24770
+ data["rawOutput"] = boundToolCallRawOutput(input2.rawOutput);
24771
+ }
24772
+ if (input2.content !== void 0) {
24773
+ data["content"] = extractedContent.content ?? input2.content;
24774
+ }
24775
+ if (input2.locations !== void 0) {
24776
+ data["locations"] = input2.locations;
24777
+ }
24778
+ const fallbackDetail = command ?? normalizedTitle ?? textContent;
24779
+ const hasPresentationSeed = title !== void 0 || kind !== void 0 || command !== void 0 || normalizedTitle !== void 0 || textContent !== void 0;
24780
+ const presentation = hasPresentationSeed ? deriveToolActivityPresentation({
24781
+ itemType: canonicalItemTypeFromAcpToolKind(kind),
24782
+ title,
24783
+ detail: fallbackDetail,
24784
+ data,
24785
+ fallbackSummary: title ?? "Tool"
24786
+ }) : void 0;
24787
+ const status = normalizeToolCallStatus(input2.status, options?.fallbackStatus);
24788
+ return {
24789
+ toolCallId,
24790
+ ...kind ? { kind } : {},
24791
+ ...presentation?.summary ? { title: presentation.summary } : {},
24792
+ ...status ? { status } : {},
24793
+ ...command ? { command } : {},
24794
+ ...presentation?.detail ? { detail: presentation.detail } : {},
24795
+ data
24796
+ };
24797
+ }
24798
+ function mergeToolCallState(previous, next) {
24799
+ const nextKind = typeof next.data["kind"] === "string" ? next.data["kind"] : void 0;
24800
+ const kind = nextKind ?? previous?.kind;
24801
+ const title = next.title ?? previous?.title;
24802
+ const status = next.status ?? previous?.status;
24803
+ const command = next.command ?? previous?.command;
24804
+ const detail = next.detail ?? previous?.detail;
24805
+ return {
24806
+ toolCallId: next.toolCallId,
24807
+ ...kind ? { kind } : {},
24808
+ ...title ? { title } : {},
24809
+ ...status ? { status } : {},
24810
+ ...command ? { command } : {},
24811
+ ...detail ? { detail } : {},
24812
+ data: {
24813
+ ...previous?.data,
24814
+ ...next.data
24855
24815
  }
24856
- this.locked = false;
24816
+ };
24817
+ }
24818
+ var TOOL_CALL_UPDATE_MIN_DETAIL_GROWTH_CHARS = 256;
24819
+ var TOOL_CALL_UPDATE_COALESCE_LIMIT = 10;
24820
+ function decideToolCallUpdateEmission(input2) {
24821
+ const { previous, next, lastEmittedDetailLength, skippedSinceEmit } = input2;
24822
+ if (next.status === "completed" || next.status === "failed") {
24823
+ return { emit: true, skippedSinceEmit: 0 };
24857
24824
  }
24858
- async runExclusive(fn) {
24859
- await this.acquire();
24860
- try {
24861
- return await fn();
24862
- } finally {
24863
- this.release();
24864
- }
24825
+ if (!next.detail) {
24826
+ return { emit: false, skippedSinceEmit };
24865
24827
  }
24866
- };
24867
-
24868
- // ../../packages/ycodium-acp-executor/src/runtime-model.ts
24869
- function extractModelConfigId(sessionResponse) {
24870
- const configOptions = sessionResponse.configOptions;
24871
- if (!configOptions) return void 0;
24872
- for (const opt of configOptions) {
24873
- if (opt.category === "model" && opt.id.trim().length > 0) {
24874
- return opt.id.trim();
24875
- }
24828
+ if (previous === void 0 || previous.title !== next.title) {
24829
+ return { emit: true, skippedSinceEmit: 0 };
24876
24830
  }
24877
- return configOptions.find((opt) => opt.id.trim() === "model" && opt.type === "select") ? "model" : void 0;
24878
- }
24879
- function findSessionConfigOption(configOptions, configId) {
24880
- if (!configOptions) {
24881
- return void 0;
24831
+ if (previous.detail === next.detail) {
24832
+ return { emit: false, skippedSinceEmit };
24882
24833
  }
24883
- const normalizedConfigId = configId.trim();
24884
- if (!normalizedConfigId) {
24885
- return void 0;
24834
+ const grewMeaningfully = lastEmittedDetailLength === void 0 || Math.abs(next.detail.length - lastEmittedDetailLength) >= TOOL_CALL_UPDATE_MIN_DETAIL_GROWTH_CHARS;
24835
+ if (grewMeaningfully || skippedSinceEmit + 1 >= TOOL_CALL_UPDATE_COALESCE_LIMIT) {
24836
+ return { emit: true, skippedSinceEmit: 0 };
24886
24837
  }
24887
- return configOptions.find((option) => option.id.trim() === normalizedConfigId);
24838
+ return { emit: false, skippedSinceEmit: skippedSinceEmit + 1 };
24888
24839
  }
24889
- function collectSessionConfigOptionValues(configOption) {
24890
- if (configOption.type !== "select" || !configOption.options) {
24891
- return [];
24892
- }
24893
- return configOption.options.flatMap(
24894
- (entry) => "value" in entry ? [entry.value] : entry.options.map((option) => option.value)
24840
+ function parsePermissionRequest(params) {
24841
+ const toolCall = makeToolCallState(
24842
+ {
24843
+ toolCallId: params.toolCall.toolCallId,
24844
+ title: params.toolCall.title,
24845
+ kind: params.toolCall.kind,
24846
+ status: params.toolCall.status,
24847
+ rawInput: params.toolCall.rawInput,
24848
+ rawOutput: params.toolCall.rawOutput,
24849
+ content: params.toolCall.content,
24850
+ locations: params.toolCall.locations
24851
+ },
24852
+ { fallbackStatus: "pending" }
24895
24853
  );
24854
+ const kind = normalizeToolKind(params.toolCall.kind) ?? "unknown";
24855
+ const detail = toolCall?.command ?? toolCall?.title ?? toolCall?.detail ?? (typeof params.sessionId === "string" ? `Session ${params.sessionId}` : void 0);
24856
+ return {
24857
+ kind,
24858
+ ...detail ? { detail } : {},
24859
+ ...toolCall ? { toolCall } : {}
24860
+ };
24896
24861
  }
24897
- function collectSessionModelIds(models) {
24898
- if (!isRecord3(models) || !Array.isArray(models["availableModels"])) {
24899
- return [];
24862
+ function boundToolCallRawPayload(params, update, toolCall) {
24863
+ const boundedContent = toolCall.data["content"];
24864
+ const boundedRawOutput = toolCall.data["rawOutput"];
24865
+ const contentBounded = update["content"] !== void 0 && boundedContent !== update["content"];
24866
+ const rawOutputBounded = update["rawOutput"] !== void 0 && boundedRawOutput !== update["rawOutput"];
24867
+ if (!contentBounded && !rawOutputBounded) {
24868
+ return params;
24900
24869
  }
24901
- return models["availableModels"].flatMap(
24902
- (model) => isRecord3(model) && typeof model["modelId"] === "string" ? [model["modelId"]] : []
24903
- );
24904
- }
24905
- function catalogModelLastSegment(value) {
24906
- if (value.startsWith("[")) {
24907
- let parsed;
24908
- try {
24909
- parsed = JSON.parse(value);
24910
- } catch {
24911
- return void 0;
24870
+ return {
24871
+ ...params,
24872
+ update: {
24873
+ ...update,
24874
+ ...contentBounded ? { content: boundedContent } : {},
24875
+ ...rawOutputBounded ? { rawOutput: boundedRawOutput } : {}
24912
24876
  }
24913
- if (!Array.isArray(parsed) || parsed.length < 2) return void 0;
24914
- const last = parsed[parsed.length - 1];
24915
- return typeof last === "string" ? last : void 0;
24916
- }
24917
- const separator = value.indexOf("/");
24918
- return separator > 0 && separator < value.length - 1 ? value.slice(separator + 1) : void 0;
24877
+ };
24919
24878
  }
24920
- function matchAdvertisedModelValue(requestedModelId, advertisedValues) {
24921
- const wanted = requestedModelId.trim();
24922
- if (!wanted) return void 0;
24923
- if (advertisedValues.includes(wanted)) return wanted;
24924
- const byLastSegment = advertisedValues.filter(
24925
- (value) => catalogModelLastSegment(value) === wanted
24879
+ function readAcpText(source, key) {
24880
+ const value = source?.[key];
24881
+ if (typeof value !== "string") return void 0;
24882
+ const trimmed = value.trim();
24883
+ return trimmed.length > 0 ? trimmed : void 0;
24884
+ }
24885
+ function textFromContentBlocks(blocks) {
24886
+ const parts = blocks.flatMap(
24887
+ (block) => isRecord3(block) && block["type"] === "text" && typeof block["text"] === "string" ? [block["text"]] : []
24926
24888
  );
24927
- return byLastSegment.length === 1 ? byLastSegment[0] : void 0;
24889
+ const joined = parts.join("");
24890
+ return joined.trim().length > 0 ? joined : void 0;
24928
24891
  }
24929
- function parseSessionModeState(sessionResponse) {
24930
- const modes = sessionResponse.modes;
24931
- if (!modes) return void 0;
24932
- const currentModeId = modes.currentModeId.trim();
24933
- if (!currentModeId) {
24934
- return void 0;
24935
- }
24936
- const availableModes = [];
24937
- for (const mode of modes.availableModes) {
24938
- const id = mode.id.trim();
24939
- const name = mode.name.trim();
24940
- if (!id || !name) {
24941
- continue;
24892
+ function parseSessionUpdateEvent(params) {
24893
+ const upd = params.update;
24894
+ const events = [];
24895
+ let modeId;
24896
+ const kind = upd["sessionUpdate"];
24897
+ switch (kind) {
24898
+ case "current_mode_update": {
24899
+ modeId = readAcpText(upd, "currentModeId");
24900
+ if (modeId) {
24901
+ events.push({
24902
+ _tag: "ModeChanged",
24903
+ modeId
24904
+ });
24905
+ }
24906
+ break;
24942
24907
  }
24943
- const description = mode.description?.trim() || void 0;
24944
- availableModes.push(
24945
- description !== void 0 ? { id, name, description } : { id, name }
24946
- );
24947
- }
24948
- if (availableModes.length === 0) {
24949
- return void 0;
24950
- }
24951
- return {
24952
- currentModeId,
24953
- availableModes
24954
- };
24908
+ case "plan": {
24909
+ const entries = Array.isArray(upd["entries"]) ? upd["entries"] : [];
24910
+ const plan = entries.map((entry, index) => ({
24911
+ step: readAcpText(entry, "content") ?? `Step ${index + 1}`,
24912
+ status: normalizePlanStepStatus(isRecord3(entry) ? entry["status"] : void 0)
24913
+ }));
24914
+ if (plan.length > 0) {
24915
+ events.push({
24916
+ _tag: "PlanUpdated",
24917
+ payload: {
24918
+ plan
24919
+ },
24920
+ rawPayload: params
24921
+ });
24922
+ }
24923
+ break;
24924
+ }
24925
+ case "tool_call":
24926
+ case "tool_call_update": {
24927
+ const toolCall = makeToolCallState(
24928
+ {
24929
+ toolCallId: upd["toolCallId"],
24930
+ name: upd["name"],
24931
+ title: typeof upd["title"] === "string" ? upd["title"] : void 0,
24932
+ kind: upd["kind"],
24933
+ status: upd["status"],
24934
+ rawInput: upd["rawInput"],
24935
+ rawOutput: upd["rawOutput"],
24936
+ content: upd["content"],
24937
+ locations: upd["locations"]
24938
+ },
24939
+ kind === "tool_call" ? { fallbackStatus: "pending" } : void 0
24940
+ );
24941
+ if (toolCall) {
24942
+ events.push({
24943
+ _tag: "ToolCallUpdated",
24944
+ toolCall,
24945
+ rawPayload: boundToolCallRawPayload(params, upd, toolCall)
24946
+ });
24947
+ }
24948
+ break;
24949
+ }
24950
+ case "agent_message_chunk":
24951
+ case "agent_thought_chunk": {
24952
+ const content = isRecord3(upd["content"]) ? upd["content"] : void 0;
24953
+ const contentType = content?.["type"];
24954
+ const streamKind = kind === "agent_thought_chunk" ? "reasoning_text" : "assistant_text";
24955
+ if (contentType === "text") {
24956
+ const text = typeof content?.["text"] === "string" ? content["text"] : "";
24957
+ if (text.length > 0) {
24958
+ events.push({
24959
+ _tag: "ContentDelta",
24960
+ text,
24961
+ streamKind,
24962
+ rawPayload: params
24963
+ });
24964
+ }
24965
+ break;
24966
+ }
24967
+ if (streamKind === "assistant_text" && content && contentType !== "audio") {
24968
+ events.push({
24969
+ _tag: "AssistantContentBlock",
24970
+ content,
24971
+ rawPayload: params
24972
+ });
24973
+ }
24974
+ break;
24975
+ }
24976
+ case "compaction_update": {
24977
+ const compactionId = readAcpText(upd, "compactionId");
24978
+ const status = readAcpText(upd, "status");
24979
+ if (compactionId === void 0 || status === void 0) break;
24980
+ const rawSummary = upd["summary"];
24981
+ events.push({
24982
+ _tag: "CompactionUpdated",
24983
+ compactionId,
24984
+ status,
24985
+ summary: rawSummary === void 0 ? void 0 : Array.isArray(rawSummary) ? textFromContentBlocks(rawSummary) ?? null : null,
24986
+ error: readAcpText(upd, "error")
24987
+ });
24988
+ break;
24989
+ }
24990
+ case "compaction_summary_chunk": {
24991
+ const compactionId = readAcpText(upd, "compactionId");
24992
+ const content = isRecord3(upd["content"]) ? upd["content"] : void 0;
24993
+ const text = content?.["type"] === "text" ? content["text"] : void 0;
24994
+ if (compactionId === void 0 || typeof text !== "string" || text.length === 0) break;
24995
+ events.push({ _tag: "CompactionSummaryChunk", compactionId, text });
24996
+ break;
24997
+ }
24998
+ default:
24999
+ break;
25000
+ }
25001
+ return { ...modeId !== void 0 ? { modeId } : {}, events };
24955
25002
  }
24956
- function acpCommandsToSlashCommands(commands) {
24957
- return commands.map((command) => ({
24958
- name: command.name,
24959
- ...command.description === void 0 ? {} : { description: command.description },
24960
- ...command.inputHint === void 0 ? {} : { input: { hint: command.inputHint } }
24961
- }));
25003
+ function filterMcpServersByAgentCapabilities(mcpServers, agentCapabilities) {
25004
+ return mcpServers.filter((server) => {
25005
+ if (!("type" in server) || server.type === void 0) {
25006
+ return true;
25007
+ }
25008
+ switch (server.type) {
25009
+ case "http":
25010
+ return agentCapabilities?.mcpCapabilities?.http === true;
25011
+ case "sse":
25012
+ return agentCapabilities?.mcpCapabilities?.sse === true;
25013
+ default:
25014
+ return true;
25015
+ }
25016
+ });
24962
25017
  }
24963
- function parseAvailableCommandsUpdate(params) {
24964
- const update = params.update;
24965
- if (update["sessionUpdate"] !== "available_commands_update") {
24966
- return void 0;
24967
- }
24968
- const availableCommands = update["availableCommands"];
24969
- if (!Array.isArray(availableCommands)) {
24970
- return [];
25018
+
25019
+ // ../../packages/ycodium-acp-executor/src/events.ts
25020
+ function canonicalRequestTypeFromAcpKind(kind) {
25021
+ switch (kind) {
25022
+ case "execute":
25023
+ return "exec_command_approval";
25024
+ case "read":
25025
+ return "file_read_approval";
25026
+ case "edit":
25027
+ case "delete":
25028
+ case "move":
25029
+ return "file_change_approval";
25030
+ case "fetch":
25031
+ return "web_fetch_approval";
25032
+ case "search":
25033
+ return "web_search_approval";
25034
+ default:
25035
+ return "dynamic_tool_call";
24971
25036
  }
24972
- const commands = [];
24973
- for (const command of availableCommands) {
24974
- if (!isRecord3(command)) {
24975
- continue;
25037
+ }
25038
+ function fileChangesFromAcpPermission(permissionRequest) {
25039
+ const content = permissionRequest.toolCall?.data["content"];
25040
+ const changes = Array.isArray(content) ? content.flatMap((entry) => {
25041
+ if (entry === null || typeof entry !== "object") {
25042
+ return [];
24976
25043
  }
24977
- const name = typeof command["name"] === "string" ? command["name"].trim() : "";
24978
- if (!name) {
24979
- continue;
25044
+ const block = entry;
25045
+ if (block["type"] !== "diff" || typeof block["path"] !== "string" || typeof block["newText"] !== "string") {
25046
+ return [];
24980
25047
  }
24981
- const description = typeof command["description"] === "string" ? command["description"].trim() || void 0 : void 0;
24982
- const input2 = isRecord3(command["input"]) ? command["input"] : void 0;
24983
- const inputHint = typeof input2?.["hint"] === "string" ? input2["hint"].trim() || void 0 : void 0;
24984
- commands.push({
24985
- name,
24986
- ...description ? { description } : {},
24987
- ...inputHint ? { inputHint } : {}
24988
- });
25048
+ const oldText = typeof block["oldText"] === "string" ? block["oldText"] : void 0;
25049
+ return [
25050
+ {
25051
+ path: block["path"],
25052
+ changeKind: oldText === void 0 ? "add" : "modify",
25053
+ content: {
25054
+ kind: "replace",
25055
+ ...oldText !== void 0 ? { oldText } : {},
25056
+ newText: block["newText"]
25057
+ }
25058
+ }
25059
+ ];
25060
+ }) : [];
25061
+ if (changes.length > 0) {
25062
+ return changes;
24989
25063
  }
24990
- return commands;
24991
- }
24992
- function normalizePlanStepStatus(raw) {
24993
- switch (raw) {
24994
- case "completed":
24995
- return "completed";
24996
- case "in_progress":
24997
- case "inProgress":
24998
- return "inProgress";
24999
- default:
25000
- return "pending";
25064
+ if (canonicalRequestTypeFromAcpKind(permissionRequest.kind) !== "file_change_approval") {
25065
+ return void 0;
25001
25066
  }
25067
+ const locations = permissionRequest.toolCall?.data["locations"];
25068
+ const paths = Array.isArray(locations) ? locations.flatMap((entry) => {
25069
+ const path = entry?.["path"];
25070
+ return typeof path === "string" && path.trim().length > 0 ? [path] : [];
25071
+ }) : [];
25072
+ return paths.length > 0 ? paths.map((path) => ({ path, omitted: "unavailable" })) : void 0;
25002
25073
  }
25003
- function normalizeToolCallStatus(raw, fallback) {
25004
- switch (raw) {
25074
+ function runtimeItemStatusFromAcpToolStatus(status) {
25075
+ switch (status) {
25005
25076
  case "pending":
25006
- return "pending";
25007
- case "in_progress":
25008
25077
  case "inProgress":
25009
25078
  return "inProgress";
25010
25079
  case "completed":
@@ -25012,394 +25081,366 @@ function normalizeToolCallStatus(raw, fallback) {
25012
25081
  case "failed":
25013
25082
  return "failed";
25014
25083
  default:
25015
- return fallback;
25016
- }
25017
- }
25018
- function normalizeCommandValue2(value) {
25019
- if (typeof value === "string" && value.trim().length > 0) {
25020
- return value.trim();
25021
- }
25022
- if (!Array.isArray(value)) {
25023
- return void 0;
25024
- }
25025
- const parts = [];
25026
- for (const entry of value) {
25027
- if (typeof entry === "string") {
25028
- const part = entry.trim();
25029
- if (part.length > 0) {
25030
- parts.push(part);
25031
- }
25032
- }
25033
- }
25034
- return parts.length > 0 ? parts.join(" ") : void 0;
25035
- }
25036
- function extractCommandFromTitle2(title) {
25037
- if (!title) {
25038
- return void 0;
25084
+ return void 0;
25039
25085
  }
25040
- const match = /`([^`]+)`/.exec(title);
25041
- return match?.[1]?.trim() || void 0;
25042
25086
  }
25043
- function extractToolCallCommand(rawInput, title) {
25044
- if (isRecord3(rawInput)) {
25045
- const directCommand = normalizeCommandValue2(rawInput["command"]);
25046
- if (directCommand) {
25047
- return directCommand;
25048
- }
25049
- const executable = typeof rawInput["executable"] === "string" ? rawInput["executable"].trim() : "";
25050
- const args = normalizeCommandValue2(rawInput["args"]);
25051
- if (executable && args) {
25052
- return `${executable} ${args}`;
25053
- }
25054
- if (executable) {
25055
- return executable;
25087
+ function makeAcpRequestOpenedEvent(input2) {
25088
+ const requestType = canonicalRequestTypeFromAcpKind(input2.permissionRequest.kind);
25089
+ const toolName = requestType === "dynamic_tool_call" ? input2.permissionRequest.toolCall?.title : void 0;
25090
+ return {
25091
+ type: "request.opened",
25092
+ ...input2.stamp,
25093
+ provider: input2.provider,
25094
+ threadId: input2.threadId,
25095
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
25096
+ requestId: input2.requestId,
25097
+ payload: {
25098
+ requestType,
25099
+ detail: input2.detail,
25100
+ ...toolName ? { toolName } : {},
25101
+ args: input2.args,
25102
+ ...input2.options ? { options: input2.options } : {},
25103
+ ...input2.fileChanges ? { fileChanges: input2.fileChanges } : {},
25104
+ declineReasonRelay: "queued"
25105
+ },
25106
+ raw: {
25107
+ source: input2.source,
25108
+ method: input2.method,
25109
+ payload: input2.rawPayload
25056
25110
  }
25057
- }
25058
- return extractCommandFromTitle2(title);
25059
- }
25060
- var TOOL_CALL_CONTENT_MAX_CHARS = 8e3;
25061
- var TOOL_CALL_CONTENT_TRUNCATION_MARKER = "[Earlier output truncated]\n\n";
25062
- function boundToolCallOutputText(text) {
25063
- if (text.length <= TOOL_CALL_CONTENT_MAX_CHARS) {
25064
- return text;
25065
- }
25066
- const tail = text.slice(text.length - TOOL_CALL_CONTENT_MAX_CHARS);
25067
- return `${TOOL_CALL_CONTENT_TRUNCATION_MARKER}${tail}`;
25111
+ };
25068
25112
  }
25069
- var RAW_OUTPUT_TEXT_FIELDS = ["content", "stdout", "stderr", "output"];
25070
- function boundToolCallRawOutput(rawOutput) {
25071
- if (!isRecord3(rawOutput)) {
25072
- return rawOutput;
25073
- }
25074
- let changed = false;
25075
- const bounded = { ...rawOutput };
25076
- for (const field of RAW_OUTPUT_TEXT_FIELDS) {
25077
- const value = rawOutput[field];
25078
- if (typeof value === "string" && value.length > TOOL_CALL_CONTENT_MAX_CHARS) {
25079
- bounded[field] = boundToolCallOutputText(value);
25080
- changed = true;
25113
+ function makeAcpRequestResolvedEvent(input2) {
25114
+ return {
25115
+ type: "request.resolved",
25116
+ ...input2.stamp,
25117
+ provider: input2.provider,
25118
+ threadId: input2.threadId,
25119
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
25120
+ requestId: input2.requestId,
25121
+ payload: {
25122
+ requestType: canonicalRequestTypeFromAcpKind(input2.permissionRequest.kind),
25123
+ decision: input2.decision,
25124
+ ...input2.reason ? { reason: input2.reason } : {}
25081
25125
  }
25082
- }
25083
- return changed ? bounded : rawOutput;
25084
- }
25085
- function toolCallContentText(entry) {
25086
- if (entry.type !== "content" || entry.content?.type !== "text") {
25087
- return void 0;
25088
- }
25089
- return entry.content.text;
25126
+ };
25090
25127
  }
25091
- function extractTextContentFromToolCallContent(content) {
25092
- if (!Array.isArray(content)) {
25093
- return { text: void 0, content: void 0 };
25094
- }
25095
- const typed = content;
25096
- const chunks = [];
25097
- for (const entry of typed) {
25098
- const text = toolCallContentText(entry)?.trim();
25099
- if (text) {
25100
- chunks.push(text);
25101
- }
25102
- }
25103
- if (chunks.length === 0) {
25104
- return { text: void 0, content: typed };
25105
- }
25106
- const joined = chunks.join("\n");
25107
- if (joined.length <= TOOL_CALL_CONTENT_MAX_CHARS) {
25108
- return { text: joined, content: typed };
25109
- }
25110
- const bounded = boundToolCallOutputText(joined);
25111
- const lastContributingTextIndex = typed.reduce(
25112
- (lastIndex, entry, index) => toolCallContentText(entry)?.trim() ? index : lastIndex,
25113
- -1
25114
- );
25115
- const boundedContent = typed.flatMap((entry, index) => {
25116
- if (toolCallContentText(entry) === void 0) {
25117
- return [entry];
25118
- }
25119
- if (index !== lastContributingTextIndex) {
25120
- return [];
25128
+ function makeAcpPlanUpdatedEvent(input2) {
25129
+ return {
25130
+ type: "turn.plan.updated",
25131
+ ...input2.stamp,
25132
+ provider: input2.provider,
25133
+ threadId: input2.threadId,
25134
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
25135
+ payload: input2.payload,
25136
+ raw: {
25137
+ source: input2.source,
25138
+ method: input2.method,
25139
+ payload: input2.rawPayload
25121
25140
  }
25122
- return [{ type: "content", content: { type: "text", text: bounded } }];
25123
- });
25124
- return { text: bounded, content: boundedContent };
25141
+ };
25125
25142
  }
25126
- function normalizeToolKind(kind) {
25127
- return typeof kind === "string" && kind.trim().length > 0 ? kind.trim() : void 0;
25143
+ function makeAcpToolCallEvent(input2) {
25144
+ const runtimeStatus = runtimeItemStatusFromAcpToolStatus(input2.toolCall.status);
25145
+ const { data } = input2.toolCall;
25146
+ return {
25147
+ type: input2.toolCall.status === "completed" || input2.toolCall.status === "failed" ? "item.completed" : "item.updated",
25148
+ ...input2.stamp,
25149
+ provider: input2.provider,
25150
+ threadId: input2.threadId,
25151
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
25152
+ itemId: input2.toolCall.toolCallId,
25153
+ payload: {
25154
+ itemType: canonicalItemTypeFromAcpToolKind(input2.toolCall.kind),
25155
+ ...runtimeStatus ? { status: runtimeStatus } : {},
25156
+ ...input2.toolCall.title ? { title: input2.toolCall.title } : {},
25157
+ ...input2.toolCall.detail ? { detail: input2.toolCall.detail } : {},
25158
+ ...Object.keys(data).length > 0 ? { data } : {}
25159
+ },
25160
+ raw: {
25161
+ source: "acp.jsonrpc",
25162
+ method: "session/update",
25163
+ payload: input2.rawPayload
25164
+ }
25165
+ };
25128
25166
  }
25129
- function makeToolCallState(input2, options) {
25130
- const toolCallId = typeof input2.toolCallId === "string" ? input2.toolCallId.trim() : "";
25131
- if (!toolCallId) {
25132
- return void 0;
25133
- }
25134
- const title = typeof input2.title === "string" ? input2.title.trim() || void 0 : void 0;
25135
- const command = extractToolCallCommand(input2.rawInput, title);
25136
- const extractedContent = extractTextContentFromToolCallContent(input2.content);
25137
- const textContent = extractedContent.text;
25138
- const normalizedTitle = title && title.toLowerCase() !== "terminal" && title.toLowerCase() !== "tool call" ? title : void 0;
25139
- const data = { toolCallId };
25140
- const kind = normalizeToolKind(input2.kind);
25141
- if (kind) {
25142
- data["kind"] = kind;
25143
- }
25144
- const name = readAcpText(input2, "name");
25145
- if (name) {
25146
- data["name"] = name;
25147
- }
25148
- if (command) {
25149
- data["command"] = command;
25150
- }
25151
- if (input2.rawInput !== void 0) {
25152
- data["rawInput"] = input2.rawInput;
25153
- }
25154
- if (input2.rawOutput !== void 0) {
25155
- data["rawOutput"] = boundToolCallRawOutput(input2.rawOutput);
25156
- }
25157
- if (input2.content !== void 0) {
25158
- data["content"] = extractedContent.content ?? input2.content;
25159
- }
25160
- if (input2.locations !== void 0) {
25161
- data["locations"] = input2.locations;
25162
- }
25163
- const fallbackDetail = command ?? normalizedTitle ?? textContent;
25164
- const hasPresentationSeed = title !== void 0 || kind !== void 0 || command !== void 0 || normalizedTitle !== void 0 || textContent !== void 0;
25165
- const presentation = hasPresentationSeed ? deriveToolActivityPresentation({
25166
- itemType: canonicalItemTypeFromAcpToolKind(kind),
25167
- title,
25168
- detail: fallbackDetail,
25169
- data,
25170
- fallbackSummary: title ?? "Tool"
25171
- }) : void 0;
25172
- const status = normalizeToolCallStatus(input2.status, options?.fallbackStatus);
25167
+ function makeAcpAssistantItemEvent(input2) {
25173
25168
  return {
25174
- toolCallId,
25175
- ...kind ? { kind } : {},
25176
- ...presentation?.summary ? { title: presentation.summary } : {},
25177
- ...status ? { status } : {},
25178
- ...command ? { command } : {},
25179
- ...presentation?.detail ? { detail: presentation.detail } : {},
25180
- data
25169
+ type: input2.lifecycle,
25170
+ ...input2.stamp,
25171
+ provider: input2.provider,
25172
+ threadId: input2.threadId,
25173
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
25174
+ itemId: input2.itemId,
25175
+ payload: {
25176
+ itemType: "assistant_message",
25177
+ status: input2.lifecycle === "item.completed" ? "completed" : "inProgress"
25178
+ }
25181
25179
  };
25182
25180
  }
25183
- function mergeToolCallState(previous, next) {
25184
- const nextKind = typeof next.data["kind"] === "string" ? next.data["kind"] : void 0;
25185
- const kind = nextKind ?? previous?.kind;
25186
- const title = next.title ?? previous?.title;
25187
- const status = next.status ?? previous?.status;
25188
- const command = next.command ?? previous?.command;
25189
- const detail = next.detail ?? previous?.detail;
25181
+ function makeAcpContentDeltaEvent(input2) {
25190
25182
  return {
25191
- toolCallId: next.toolCallId,
25192
- ...kind ? { kind } : {},
25193
- ...title ? { title } : {},
25194
- ...status ? { status } : {},
25195
- ...command ? { command } : {},
25196
- ...detail ? { detail } : {},
25197
- data: {
25198
- ...previous?.data,
25199
- ...next.data
25183
+ type: "content.delta",
25184
+ ...input2.stamp,
25185
+ provider: input2.provider,
25186
+ threadId: input2.threadId,
25187
+ ...input2.turnId !== void 0 ? { turnId: input2.turnId } : {},
25188
+ ...input2.itemId ? { itemId: input2.itemId } : {},
25189
+ payload: {
25190
+ streamKind: input2.streamKind ?? "assistant_text",
25191
+ delta: input2.text
25192
+ },
25193
+ raw: {
25194
+ source: "acp.jsonrpc",
25195
+ method: "session/update",
25196
+ payload: input2.rawPayload
25200
25197
  }
25201
25198
  };
25202
25199
  }
25203
- var TOOL_CALL_UPDATE_MIN_DETAIL_GROWTH_CHARS = 256;
25204
- var TOOL_CALL_UPDATE_COALESCE_LIMIT = 10;
25205
- function decideToolCallUpdateEmission(input2) {
25206
- const { previous, next, lastEmittedDetailLength, skippedSinceEmit } = input2;
25207
- if (next.status === "completed" || next.status === "failed") {
25208
- return { emit: true, skippedSinceEmit: 0 };
25209
- }
25210
- if (!next.detail) {
25211
- return { emit: false, skippedSinceEmit };
25212
- }
25213
- if (previous === void 0 || previous.title !== next.title) {
25214
- return { emit: true, skippedSinceEmit: 0 };
25200
+ function retainToolCallUpdate(toolCalls, next, seen) {
25201
+ const tracked = toolCalls.get(next.toolCallId);
25202
+ const previous = tracked?.state;
25203
+ const nextToolCall = mergeToolCallState(previous, next);
25204
+ const decision = decideToolCallUpdateEmission({
25205
+ previous,
25206
+ next: nextToolCall,
25207
+ lastEmittedDetailLength: tracked?.lastEmittedDetailLength,
25208
+ skippedSinceEmit: tracked?.skippedSinceEmit ?? 0
25209
+ });
25210
+ if (nextToolCall.status === "completed" || nextToolCall.status === "failed") {
25211
+ toolCalls.delete(nextToolCall.toolCallId);
25212
+ } else {
25213
+ toolCalls.set(nextToolCall.toolCallId, {
25214
+ state: nextToolCall,
25215
+ lastEmittedDetailLength: decision.emit ? nextToolCall.detail?.length : tracked?.lastEmittedDetailLength,
25216
+ skippedSinceEmit: decision.skippedSinceEmit,
25217
+ turnId: tracked === void 0 ? seen.turnId : tracked.turnId,
25218
+ startedAtMs: tracked?.startedAtMs ?? (nextToolCall.status === "inProgress" ? seen.nowMs() : void 0),
25219
+ rawTitle: typeof seen.rawTitle === "string" ? seen.rawTitle : tracked?.rawTitle
25220
+ });
25215
25221
  }
25216
- if (previous.detail === next.detail) {
25217
- return { emit: false, skippedSinceEmit };
25222
+ return { nextToolCall, decision };
25223
+ }
25224
+
25225
+ // ../../packages/ycodium-acp-executor/src/openCommands.ts
25226
+ function readOpenToolCalls(toolCalls, turnId) {
25227
+ const running = [];
25228
+ for (const tracked of toolCalls.values()) {
25229
+ if (tracked.turnId !== turnId || tracked.startedAtMs === void 0) continue;
25230
+ running.push({
25231
+ toolCallId: tracked.state.toolCallId,
25232
+ turnId: tracked.turnId,
25233
+ startedAtMs: tracked.startedAtMs,
25234
+ kind: tracked.state.kind,
25235
+ title: tracked.rawTitle,
25236
+ rawInput: tracked.state.data["rawInput"]
25237
+ });
25218
25238
  }
25219
- const grewMeaningfully = lastEmittedDetailLength === void 0 || Math.abs(next.detail.length - lastEmittedDetailLength) >= TOOL_CALL_UPDATE_MIN_DETAIL_GROWTH_CHARS;
25220
- if (grewMeaningfully || skippedSinceEmit + 1 >= TOOL_CALL_UPDATE_COALESCE_LIMIT) {
25221
- return { emit: true, skippedSinceEmit: 0 };
25239
+ return running;
25240
+ }
25241
+
25242
+ // ../../packages/ycodium-acp-executor/src/config-options.ts
25243
+ function isRecord4(value) {
25244
+ return typeof value === "object" && value !== null && !Array.isArray(value);
25245
+ }
25246
+ function asString(value) {
25247
+ return typeof value === "string" ? value : void 0;
25248
+ }
25249
+ function normalizedField(option, key) {
25250
+ return asString(option[key])?.trim().toLowerCase() ?? "";
25251
+ }
25252
+ function looksLikeEffortOption(option) {
25253
+ const id = normalizedField(option, "id");
25254
+ const name = normalizedField(option, "name");
25255
+ return id === "effort" || id === "reasoning" || name === "effort" || name === "reasoning" || name.includes("effort") || name.includes("reasoning") || normalizedField(option, "category") === "thought_level";
25256
+ }
25257
+ function flattenChoices(rawOptions, currentValue) {
25258
+ if (!Array.isArray(rawOptions)) return [];
25259
+ const out = [];
25260
+ const seen = /* @__PURE__ */ new Set();
25261
+ const push = (entry) => {
25262
+ if (!isRecord4(entry)) return;
25263
+ const value = asString(entry["value"]);
25264
+ if (value === void 0 || seen.has(value)) return;
25265
+ seen.add(value);
25266
+ const description = asString(entry["description"])?.trim();
25267
+ const name = asString(entry["name"])?.trim();
25268
+ out.push({
25269
+ value,
25270
+ ...name ? { name } : {},
25271
+ label: name || value,
25272
+ ...description ? { description } : {},
25273
+ ...currentValue !== void 0 && currentValue === value ? { isDefault: true } : {}
25274
+ });
25275
+ };
25276
+ for (const entry of rawOptions) {
25277
+ if (isRecord4(entry) && Array.isArray(entry["options"])) {
25278
+ for (const nested of entry["options"]) push(nested);
25279
+ continue;
25280
+ }
25281
+ push(entry);
25222
25282
  }
25223
- return { emit: false, skippedSinceEmit: skippedSinceEmit + 1 };
25283
+ return out;
25224
25284
  }
25225
- function parsePermissionRequest(params) {
25226
- const toolCall = makeToolCallState(
25227
- {
25228
- toolCallId: params.toolCall.toolCallId,
25229
- title: params.toolCall.title,
25230
- kind: params.toolCall.kind,
25231
- status: params.toolCall.status,
25232
- rawInput: params.toolCall.rawInput,
25233
- rawOutput: params.toolCall.rawOutput,
25234
- content: params.toolCall.content,
25235
- locations: params.toolCall.locations
25236
- },
25237
- { fallbackStatus: "pending" }
25238
- );
25239
- const kind = normalizeToolKind(params.toolCall.kind) ?? "unknown";
25240
- const detail = toolCall?.command ?? toolCall?.title ?? toolCall?.detail ?? (typeof params.sessionId === "string" ? `Session ${params.sessionId}` : void 0);
25285
+ function findAcpEffortConfig(configOptions) {
25286
+ if (!Array.isArray(configOptions)) return void 0;
25287
+ const candidates = configOptions.filter(isRecord4).filter((option) => normalizedField(option, "type") === "select").filter(looksLikeEffortOption);
25288
+ if (candidates.length === 0) return void 0;
25289
+ const picked = candidates.find((option) => normalizedField(option, "category") === "model_option") ?? candidates.find((option) => normalizedField(option, "id") === "effort") ?? candidates.find((option) => normalizedField(option, "category") === "thought_level") ?? candidates[0];
25290
+ if (picked === void 0) return void 0;
25291
+ const configId = asString(picked["id"])?.trim();
25292
+ if (!configId) return void 0;
25293
+ const choices = flattenChoices(picked["options"], asString(picked["currentValue"])?.trim());
25294
+ if (choices.length === 0) return void 0;
25241
25295
  return {
25242
- kind,
25243
- ...detail ? { detail } : {},
25244
- ...toolCall ? { toolCall } : {}
25296
+ configId,
25297
+ label: asString(picked["name"])?.trim() ?? "",
25298
+ choices
25245
25299
  };
25246
25300
  }
25247
- function boundToolCallRawPayload(params, update, toolCall) {
25248
- const boundedContent = toolCall.data["content"];
25249
- const boundedRawOutput = toolCall.data["rawOutput"];
25250
- const contentBounded = update["content"] !== void 0 && boundedContent !== update["content"];
25251
- const rawOutputBounded = update["rawOutput"] !== void 0 && boundedRawOutput !== update["rawOutput"];
25252
- if (!contentBounded && !rawOutputBounded) {
25253
- return params;
25301
+
25302
+ // ../../packages/ycodium-acp-executor/src/runtime-mode.ts
25303
+ function isRecord5(value) {
25304
+ return typeof value === "object" && value !== null && !Array.isArray(value);
25305
+ }
25306
+ function asString2(value) {
25307
+ return typeof value === "string" ? value : void 0;
25308
+ }
25309
+ function acpModeConfigId(setup) {
25310
+ if (!isRecord5(setup)) return void 0;
25311
+ const configOptions = setup["configOptions"];
25312
+ if (!Array.isArray(configOptions)) return void 0;
25313
+ for (const option of configOptions) {
25314
+ if (!isRecord5(option)) continue;
25315
+ if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
25316
+ const id = asString2(option["id"])?.trim();
25317
+ if (id) return id;
25318
+ }
25319
+ return void 0;
25320
+ }
25321
+ function acpCurrentModeId(setup) {
25322
+ if (!isRecord5(setup)) return void 0;
25323
+ const modes = setup["modes"];
25324
+ if (isRecord5(modes)) {
25325
+ const current = asString2(modes["currentModeId"])?.trim();
25326
+ if (current) return current;
25254
25327
  }
25255
- return {
25256
- ...params,
25257
- update: {
25258
- ...update,
25259
- ...contentBounded ? { content: boundedContent } : {},
25260
- ...rawOutputBounded ? { rawOutput: boundedRawOutput } : {}
25328
+ const configOptions = setup["configOptions"];
25329
+ if (Array.isArray(configOptions)) {
25330
+ for (const option of configOptions) {
25331
+ if (!isRecord5(option)) continue;
25332
+ if (asString2(option["category"])?.trim().toLowerCase() !== "mode") continue;
25333
+ const current = asString2(option["currentValue"])?.trim();
25334
+ if (current) return current;
25261
25335
  }
25262
- };
25336
+ }
25337
+ return void 0;
25263
25338
  }
25264
- function readAcpText(source, key) {
25265
- const value = source?.[key];
25266
- if (typeof value !== "string") return void 0;
25267
- const trimmed = value.trim();
25268
- return trimmed.length > 0 ? trimmed : void 0;
25339
+
25340
+ // ../../packages/ycodium-acp-executor/src/handshake.ts
25341
+ function acpInitializePayload(clientInfo, overrides) {
25342
+ return {
25343
+ protocolVersion: PROTOCOL_VERSION,
25344
+ clientCapabilities: {
25345
+ fs: {
25346
+ readTextFile: false,
25347
+ writeTextFile: false,
25348
+ ...overrides?.fs
25349
+ },
25350
+ terminal: overrides?.terminal ?? false
25351
+ },
25352
+ clientInfo
25353
+ };
25269
25354
  }
25270
- function textFromContentBlocks(blocks) {
25271
- const parts = blocks.flatMap(
25272
- (block) => isRecord3(block) && block["type"] === "text" && typeof block["text"] === "string" ? [block["text"]] : []
25273
- );
25274
- const joined = parts.join("");
25275
- return joined.trim().length > 0 ? joined : void 0;
25355
+
25356
+ // ../../packages/ycodium-acp-executor/src/config-option-wiring.ts
25357
+ var VENDOR_CATEGORY_PREFIX = "_";
25358
+ var ACP_CONFIG_CATEGORY_HANDLING = {
25359
+ mode: {
25360
+ consumed: true,
25361
+ via: "runtime-mode.ts\uFF1AacpAvailableModes / acpCurrentModeId / acpModeConfigId"
25362
+ },
25363
+ model: {
25364
+ consumed: true,
25365
+ via: "runtime-model.ts:extractModelConfigId \u2192 executor.ts:applyRequestedModel"
25366
+ },
25367
+ thought_level: {
25368
+ consumed: true,
25369
+ via: "config-options.ts:findAcpEffortConfig \u2192 executor.ts:applyRequestedEffort"
25370
+ },
25371
+ model_option: {
25372
+ consumed: true,
25373
+ // 精确说法:它不是**识别器**,是**优先级**。`looksLikeEffortOption` 先筛出候选,
25374
+ // 标了 `model_option` 的在候选里排第一(厂商自己标的最准),排在 id 叫 `effort`
25375
+ // 的和标 `thought_level` 的前面。光有这个 category 而 id/name 不像力度档的,
25376
+ // 压根进不了候选。
25377
+ via: "config-options.ts:findAcpEffortConfig\uFF08\u5019\u9009\u91CC\u7684\u6700\u9AD8\u4F18\u5148\u7EA7\uFF0C\u538B\u8FC7 thought_level\uFF09"
25378
+ },
25379
+ model_config: {
25380
+ consumed: false,
25381
+ note: "\u53EA\u6709\u5BBF\u4E3B\u7684 CursorProvider \u6D88\u8D39\u8FC7\uFF08context / fast / thinking \u4E09\u4E2A\u5F00\u5173\uFF09\u3002Cursor 2026-09-20 \u5E9F\u5F03\u5220\u9664\uFF0C\u8FD9\u4E00\u7C7B\u73B0\u5728\u6CA1\u6709\u6D88\u8D39\u70B9\uFF1B\u6CA1\u89C1\u8FC7\u522B\u5BB6\u7684\u771F\u5B9E\u8F7D\u8377\uFF0C\u5148\u8BB0\u8D26\u4E0D\u731C\u5F62\u72B6\u3002"
25382
+ }
25383
+ };
25384
+ var KNOWN_CATEGORIES = new Set(Object.keys(ACP_CONFIG_CATEGORY_HANDLING));
25385
+ function unhandledConfigCategories(configOptions) {
25386
+ if (!configOptions) return [];
25387
+ const seen = /* @__PURE__ */ new Set();
25388
+ const out = [];
25389
+ for (const option of configOptions) {
25390
+ const category = option.category?.trim();
25391
+ if (!category) continue;
25392
+ if (KNOWN_CATEGORIES.has(category)) continue;
25393
+ if (seen.has(category)) continue;
25394
+ seen.add(category);
25395
+ out.push({
25396
+ category,
25397
+ optionId: option.id.trim(),
25398
+ vendorExtension: category.startsWith(VENDOR_CATEGORY_PREFIX)
25399
+ });
25400
+ }
25401
+ return out;
25276
25402
  }
25277
- function parseSessionUpdateEvent(params) {
25278
- const upd = params.update;
25279
- const events = [];
25280
- let modeId;
25281
- const kind = upd["sessionUpdate"];
25282
- switch (kind) {
25283
- case "current_mode_update": {
25284
- modeId = readAcpText(upd, "currentModeId");
25285
- if (modeId) {
25286
- events.push({
25287
- _tag: "ModeChanged",
25288
- modeId
25289
- });
25290
- }
25291
- break;
25292
- }
25293
- case "plan": {
25294
- const entries = Array.isArray(upd["entries"]) ? upd["entries"] : [];
25295
- const plan = entries.map((entry, index) => ({
25296
- step: readAcpText(entry, "content") ?? `Step ${index + 1}`,
25297
- status: normalizePlanStepStatus(isRecord3(entry) ? entry["status"] : void 0)
25298
- }));
25299
- if (plan.length > 0) {
25300
- events.push({
25301
- _tag: "PlanUpdated",
25302
- payload: {
25303
- plan
25304
- },
25305
- rawPayload: params
25306
- });
25307
- }
25308
- break;
25309
- }
25310
- case "tool_call":
25311
- case "tool_call_update": {
25312
- const toolCall = makeToolCallState(
25313
- {
25314
- toolCallId: upd["toolCallId"],
25315
- name: upd["name"],
25316
- title: typeof upd["title"] === "string" ? upd["title"] : void 0,
25317
- kind: upd["kind"],
25318
- status: upd["status"],
25319
- rawInput: upd["rawInput"],
25320
- rawOutput: upd["rawOutput"],
25321
- content: upd["content"],
25322
- locations: upd["locations"]
25323
- },
25324
- kind === "tool_call" ? { fallbackStatus: "pending" } : void 0
25325
- );
25326
- if (toolCall) {
25327
- events.push({
25328
- _tag: "ToolCallUpdated",
25329
- toolCall,
25330
- rawPayload: boundToolCallRawPayload(params, upd, toolCall)
25331
- });
25332
- }
25333
- break;
25334
- }
25335
- case "agent_message_chunk":
25336
- case "agent_thought_chunk": {
25337
- const content = isRecord3(upd["content"]) ? upd["content"] : void 0;
25338
- const contentType = content?.["type"];
25339
- const streamKind = kind === "agent_thought_chunk" ? "reasoning_text" : "assistant_text";
25340
- if (contentType === "text") {
25341
- const text = typeof content?.["text"] === "string" ? content["text"] : "";
25342
- if (text.length > 0) {
25343
- events.push({
25344
- _tag: "ContentDelta",
25345
- text,
25346
- streamKind,
25347
- rawPayload: params
25348
- });
25349
- }
25350
- break;
25351
- }
25352
- if (streamKind === "assistant_text" && content && contentType !== "audio") {
25353
- events.push({
25354
- _tag: "AssistantContentBlock",
25355
- content,
25356
- rawPayload: params
25357
- });
25358
- }
25359
- break;
25360
- }
25361
- case "compaction_update": {
25362
- const compactionId = readAcpText(upd, "compactionId");
25363
- const status = readAcpText(upd, "status");
25364
- if (compactionId === void 0 || status === void 0) break;
25365
- const rawSummary = upd["summary"];
25366
- events.push({
25367
- _tag: "CompactionUpdated",
25368
- compactionId,
25369
- status,
25370
- summary: rawSummary === void 0 ? void 0 : Array.isArray(rawSummary) ? textFromContentBlocks(rawSummary) ?? null : null,
25371
- error: readAcpText(upd, "error")
25372
- });
25373
- break;
25403
+
25404
+ // ../../packages/ycodium-acp-executor/src/mutex.ts
25405
+ var Mutex = class {
25406
+ locked = false;
25407
+ waiters = [];
25408
+ get isLocked() {
25409
+ return this.locked;
25410
+ }
25411
+ acquire() {
25412
+ if (!this.locked) {
25413
+ this.locked = true;
25414
+ return Promise.resolve();
25374
25415
  }
25375
- case "compaction_summary_chunk": {
25376
- const compactionId = readAcpText(upd, "compactionId");
25377
- const content = isRecord3(upd["content"]) ? upd["content"] : void 0;
25378
- const text = content?.["type"] === "text" ? content["text"] : void 0;
25379
- if (compactionId === void 0 || typeof text !== "string" || text.length === 0) break;
25380
- events.push({ _tag: "CompactionSummaryChunk", compactionId, text });
25381
- break;
25416
+ return new Promise((resolve3) => {
25417
+ this.waiters.push(resolve3);
25418
+ });
25419
+ }
25420
+ tryAcquire() {
25421
+ if (this.locked) {
25422
+ return false;
25382
25423
  }
25383
- default:
25384
- break;
25424
+ this.locked = true;
25425
+ return true;
25385
25426
  }
25386
- return { ...modeId !== void 0 ? { modeId } : {}, events };
25387
- }
25388
- function filterMcpServersByAgentCapabilities(mcpServers, agentCapabilities) {
25389
- return mcpServers.filter((server) => {
25390
- if (!("type" in server) || server.type === void 0) {
25391
- return true;
25427
+ release() {
25428
+ const next = this.waiters.shift();
25429
+ if (next) {
25430
+ next();
25431
+ return;
25392
25432
  }
25393
- switch (server.type) {
25394
- case "http":
25395
- return agentCapabilities?.mcpCapabilities?.http === true;
25396
- case "sse":
25397
- return agentCapabilities?.mcpCapabilities?.sse === true;
25398
- default:
25399
- return true;
25433
+ this.locked = false;
25434
+ }
25435
+ async runExclusive(fn) {
25436
+ await this.acquire();
25437
+ try {
25438
+ return await fn();
25439
+ } finally {
25440
+ this.release();
25400
25441
  }
25401
- });
25402
- }
25442
+ }
25443
+ };
25403
25444
 
25404
25445
  // ../../packages/ycodium-acp-executor/src/model-selection.ts
25405
25446
  function normalizeModelId(value) {
@@ -25658,24 +25699,11 @@ function createAcpExecutor(options) {
25658
25699
  }
25659
25700
  for (const event of parsed.events) {
25660
25701
  if (event._tag === "ToolCallUpdated") {
25661
- const tracked = toolCalls.get(event.toolCall.toolCallId);
25662
- const previous = tracked?.state;
25663
- const nextToolCall = mergeToolCallState(previous, event.toolCall);
25664
- const decision = decideToolCallUpdateEmission({
25665
- previous,
25666
- next: nextToolCall,
25667
- lastEmittedDetailLength: tracked?.lastEmittedDetailLength,
25668
- skippedSinceEmit: tracked?.skippedSinceEmit ?? 0
25702
+ const { nextToolCall, decision } = retainToolCallUpdate(toolCalls, event.toolCall, {
25703
+ turnId: activeTurnId,
25704
+ rawTitle: params.update.title,
25705
+ nowMs
25669
25706
  });
25670
- if (nextToolCall.status === "completed" || nextToolCall.status === "failed") {
25671
- toolCalls.delete(nextToolCall.toolCallId);
25672
- } else {
25673
- toolCalls.set(nextToolCall.toolCallId, {
25674
- state: nextToolCall,
25675
- lastEmittedDetailLength: decision.emit ? nextToolCall.detail?.length : tracked?.lastEmittedDetailLength,
25676
- skippedSinceEmit: decision.skippedSinceEmit
25677
- });
25678
- }
25679
25707
  const hookResult = hooks.onToolCallUpdated?.({
25680
25708
  toolCallId: nextToolCall.toolCallId,
25681
25709
  status: nextToolCall.status,
@@ -26703,6 +26731,7 @@ function createAcpExecutor(options) {
26703
26731
  respondToUserInput,
26704
26732
  setNativeMode,
26705
26733
  compact,
26734
+ openToolCalls: () => readOpenToolCalls(toolCalls, activeTurnId),
26706
26735
  dispose
26707
26736
  };
26708
26737
  }
@@ -28002,7 +28031,7 @@ var executors = [
28002
28031
  ];
28003
28032
  var index_default = definePlugin({
28004
28033
  id: "agent-kimi",
28005
- apiVersion: 3,
28034
+ apiVersion: 5,
28006
28035
  executors,
28007
28036
  activate(ctx) {
28008
28037
  ctx.log.info("Kimi Code executor ready");