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