@adhdev/daemon-core 0.9.76-rc.60 → 0.9.76-rc.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -431,10 +431,10 @@ function getMeshConfigPath() {
431
431
  return join4(getConfigDir(), "meshes.json");
432
432
  }
433
433
  function loadMeshConfig() {
434
- const path27 = getMeshConfigPath();
435
- if (!existsSync4(path27)) return { meshes: [] };
434
+ const path28 = getMeshConfigPath();
435
+ if (!existsSync4(path28)) return { meshes: [] };
436
436
  try {
437
- const raw = JSON.parse(readFileSync2(path27, "utf-8"));
437
+ const raw = JSON.parse(readFileSync2(path28, "utf-8"));
438
438
  if (!raw || !Array.isArray(raw.meshes)) return { meshes: [] };
439
439
  return raw;
440
440
  } catch {
@@ -442,16 +442,16 @@ function loadMeshConfig() {
442
442
  }
443
443
  }
444
444
  function saveMeshConfig(config) {
445
- const path27 = getMeshConfigPath();
446
- writeFileSync2(path27, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
445
+ const path28 = getMeshConfigPath();
446
+ writeFileSync2(path28, JSON.stringify(config, null, 2), { encoding: "utf-8", mode: 384 });
447
447
  }
448
448
  function normalizeRepoIdentity(remoteUrl) {
449
449
  let identity = remoteUrl.trim();
450
450
  if (identity.startsWith("http://") || identity.startsWith("https://")) {
451
451
  try {
452
452
  const url = new URL(identity);
453
- const path27 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
454
- return `${url.hostname}/${path27}`;
453
+ const path28 = url.pathname.replace(/^\//, "").replace(/\.git$/, "");
454
+ return `${url.hostname}/${path28}`;
455
455
  } catch {
456
456
  }
457
457
  }
@@ -605,6 +605,7 @@ Default branch: \`${mesh.defaultBranch}\`` : ""}`);
605
605
  }
606
606
  sections.push(buildPolicySection({ ...DEFAULT_MESH_POLICY, ...mesh.policy || {} }));
607
607
  sections.push(TOOLS_SECTION);
608
+ sections.push(TOOL_EXPOSURE_PREFLIGHT_SECTION);
608
609
  sections.push(WORKFLOW_SECTION);
609
610
  sections.push(buildRulesSection(coordinatorCliType));
610
611
  if (userInstruction) {
@@ -674,7 +675,7 @@ function buildRulesSection(coordinatorCliType) {
674
675
  - **Clean up worktree nodes.** After a worktree task completes and its changes are merged or checkpointed, call \`mesh_remove_node\` to free resources.
675
676
  - **Name worktree branches meaningfully.** Use descriptive names like \`feat/auth-refactor\` or \`fix/build-123\`.${coordinatorNote}`;
676
677
  }
677
- var TOOLS_SECTION, WORKFLOW_SECTION;
678
+ var TOOLS_SECTION, TOOL_EXPOSURE_PREFLIGHT_SECTION, WORKFLOW_SECTION;
678
679
  var init_coordinator_prompt = __esm({
679
680
  "src/mesh/coordinator-prompt.ts"() {
680
681
  "use strict";
@@ -693,6 +694,9 @@ var init_coordinator_prompt = __esm({
693
694
  | \`mesh_approve\` | Approve/reject a pending agent action |
694
695
  | \`mesh_clone_node\` | Create a worktree node for isolated parallel branch work |
695
696
  | \`mesh_remove_node\` | Remove a node (cleans up worktree if applicable) |`;
697
+ TOOL_EXPOSURE_PREFLIGHT_SECTION = `## Tool Exposure Preflight
698
+
699
+ Before doing any coordinator work, confirm that the actual callable tool list includes \`mesh_status\` and the other \`mesh_*\` tools from the table above. If this Repo Mesh coordinator prompt is present but the callable \`mesh_*\` tools are missing, the MCP server/tool manifest is stale or not injected yet. Do not substitute terminal/file/git tools, do not inspect or edit the repository directly, and do not continue as a non-mesh local coding agent. Stop immediately and tell the user to run \`/reload-mcp\` or start a fresh coordinator session so ADHDev can reconnect \`adhdev-mesh\`.`;
696
700
  WORKFLOW_SECTION = `## Orchestration Workflow
697
701
 
698
702
  1. **Assess** \u2014 Call \`mesh_status\` to see which nodes are healthy and available.
@@ -7522,6 +7526,10 @@ function flattenMessageParts(parts) {
7522
7526
  return parts.map((part) => {
7523
7527
  if (part.type === "text") return part.text;
7524
7528
  if (part.type === "resource") return part.resource.text || "";
7529
+ if (part.type === "image") return part.alt || (part.data ? `[image: ${part.mimeType}]` : "");
7530
+ if (part.type === "audio") return part.transcript || (part.data ? `[audio: ${part.mimeType}]` : "");
7531
+ if (part.type === "video") return part.transcript || (part.data ? `[video: ${part.mimeType}]` : "");
7532
+ if (part.type === "resource_link") return [part.name, part.description].filter(Boolean).join("\n");
7525
7533
  return "";
7526
7534
  }).filter((value) => value.length > 0).join("\n");
7527
7535
  }
@@ -7608,6 +7616,7 @@ function normalizeInputPartObject(raw) {
7608
7616
  mimeType: raw.mimeType,
7609
7617
  ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
7610
7618
  ...typeof raw.data === "string" ? { data: raw.data } : {},
7619
+ ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {},
7611
7620
  ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
7612
7621
  };
7613
7622
  }
@@ -7623,10 +7632,14 @@ function normalizeInputPartObject(raw) {
7623
7632
  }
7624
7633
  if (type === "resource_link" && typeof raw.uri === "string") {
7625
7634
  return {
7626
- type: "resource",
7635
+ type,
7627
7636
  uri: raw.uri,
7637
+ name: typeof raw.name === "string" ? raw.name : getUriDisplayName(raw.uri, "resource"),
7638
+ ...typeof raw.title === "string" ? { title: raw.title } : {},
7639
+ ...typeof raw.description === "string" ? { description: raw.description } : {},
7628
7640
  ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
7629
- ...typeof raw.name === "string" ? { name: raw.name } : {}
7641
+ ...typeof raw.size === "number" && Number.isFinite(raw.size) ? { size: raw.size } : {},
7642
+ ...normalizeAnnotationsProperty(raw.annotations)
7630
7643
  };
7631
7644
  }
7632
7645
  return null;
@@ -7641,7 +7654,8 @@ function normalizeMessagePartObject(raw) {
7641
7654
  type,
7642
7655
  mimeType: raw.mimeType,
7643
7656
  ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
7644
- ...typeof raw.data === "string" ? { data: raw.data } : {}
7657
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
7658
+ ...typeof raw.alt === "string" ? { alt: raw.alt } : {}
7645
7659
  };
7646
7660
  }
7647
7661
  if (type === "audio" && typeof raw.mimeType === "string") {
@@ -7659,6 +7673,7 @@ function normalizeMessagePartObject(raw) {
7659
7673
  mimeType: raw.mimeType,
7660
7674
  ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
7661
7675
  ...typeof raw.data === "string" ? { data: raw.data } : {},
7676
+ ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {},
7662
7677
  ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
7663
7678
  };
7664
7679
  }
@@ -7667,8 +7682,11 @@ function normalizeMessagePartObject(raw) {
7667
7682
  type,
7668
7683
  uri: raw.uri,
7669
7684
  name: raw.name,
7685
+ ...typeof raw.title === "string" ? { title: raw.title } : {},
7686
+ ...typeof raw.description === "string" ? { description: raw.description } : {},
7670
7687
  ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
7671
- ...typeof raw.size === "number" ? { size: raw.size } : {}
7688
+ ...typeof raw.size === "number" && Number.isFinite(raw.size) ? { size: raw.size } : {},
7689
+ ...normalizeAnnotationsProperty(raw.annotations)
7672
7690
  };
7673
7691
  }
7674
7692
  if (type === "resource" && raw.resource && typeof raw.resource === "object") {
@@ -7689,11 +7707,35 @@ function normalizeMessagePartObject(raw) {
7689
7707
  function flattenInputParts(parts) {
7690
7708
  return parts.map((part) => {
7691
7709
  if (part.type === "text") return part.text;
7692
- if (part.type === "audio") return part.transcript || "";
7693
- if (part.type === "resource") return part.text || "";
7710
+ if (part.type === "image") return part.alt || (part.data ? `[image: ${part.mimeType}]` : "");
7711
+ if (part.type === "audio") return part.transcript || (part.data ? `[audio: ${part.mimeType}]` : "");
7712
+ if (part.type === "video") return part.transcript || (part.data ? `[video: ${part.mimeType}]` : "");
7713
+ if (part.type === "resource_link") return [part.title, part.name, part.description, part.uri].filter(Boolean).join("\n");
7714
+ if (part.type === "resource") return part.text || part.name || part.uri;
7694
7715
  return "";
7695
7716
  }).filter((value) => value.length > 0).join("\n");
7696
7717
  }
7718
+ function getUriDisplayName(uri, fallback) {
7719
+ try {
7720
+ const pathname = uri.startsWith("file://") ? new URL(uri).pathname : uri;
7721
+ return pathname.split(/[\\/]/).filter(Boolean).pop() || fallback;
7722
+ } catch {
7723
+ return uri.split(/[\\/]/).filter(Boolean).pop() || fallback;
7724
+ }
7725
+ }
7726
+ function normalizeAnnotationsProperty(value) {
7727
+ if (!value || typeof value !== "object") return {};
7728
+ const record = value;
7729
+ const annotations = {};
7730
+ if (Array.isArray(record.audience)) {
7731
+ const audience = record.audience.filter((item) => item === "user" || item === "assistant");
7732
+ if (audience.length > 0) annotations.audience = audience;
7733
+ }
7734
+ if (typeof record.priority === "number" && Number.isFinite(record.priority)) {
7735
+ annotations.priority = record.priority;
7736
+ }
7737
+ return Object.keys(annotations).length > 0 ? { annotations } : {};
7738
+ }
7697
7739
 
7698
7740
  // src/providers/contracts.ts
7699
7741
  function flattenContent(content) {
@@ -7815,6 +7857,20 @@ var StatusMonitor = class {
7815
7857
 
7816
7858
  // src/providers/chat-message-normalization.ts
7817
7859
  var BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
7860
+ var CHAT_MESSAGE_VISIBILITIES = ["user", "debug", "internal", "hidden"];
7861
+ var CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES = ["visible", "chat", "user", "debug", "internal", "hidden"];
7862
+ var CHAT_MESSAGE_AUDIENCES = ["chat", "debug", "trace", "internal"];
7863
+ var CHAT_MESSAGE_SOURCES = [
7864
+ "assistant_text",
7865
+ "tool_call",
7866
+ "terminal_command",
7867
+ "runtime_activity",
7868
+ "runtime_status",
7869
+ "provider_chrome",
7870
+ "control"
7871
+ ];
7872
+ var CHAT_MESSAGE_ACTIVITY_SOURCES = ["tool_call", "terminal_command", "runtime_activity"];
7873
+ var CHAT_MESSAGE_INTERNAL_SOURCES = ["runtime_status", "provider_chrome", "control"];
7818
7874
  var KNOWN_CHAT_MESSAGE_KINDS = new Set(BUILTIN_CHAT_MESSAGE_KINDS);
7819
7875
  var CHAT_MESSAGE_KIND_ALIASES = {
7820
7876
  text: "standard",
@@ -7963,37 +8019,162 @@ function readMessageMeta(message) {
7963
8019
  function readStringField(value) {
7964
8020
  return typeof value === "string" ? value.trim().toLowerCase() : "";
7965
8021
  }
7966
- function readVisibilityField(message, meta) {
8022
+ function readRecordField(message, meta, key) {
7967
8023
  const record = message;
7968
- return readStringField(record.visibility ?? record.transcriptVisibility ?? meta?.visibility ?? meta?.transcriptVisibility);
8024
+ return record[key] ?? meta?.[key];
7969
8025
  }
7970
- function isExplicitlyHiddenFromTranscript(message, meta) {
7971
- const record = message;
7972
- const visibility = readVisibilityField(message, meta);
7973
- const audience = readStringField(record.audience ?? meta?.audience);
7974
- const source = readStringField(record.source ?? meta?.source);
7975
- return visibility === "hidden" || visibility === "debug" || visibility === "internal" || audience === "debug" || audience === "trace" || audience === "internal" || source === "runtime_status" || source === "runtime_activity" || source === "provider_chrome" || source === "control" || record.internal === true || record.isInternal === true || record.debug === true || meta?.internal === true || meta?.isInternal === true || meta?.debug === true || meta?.statusOnly === true || meta?.controlOnly === true;
8026
+ function readVisibilityField(message, meta) {
8027
+ return readStringField(readRecordField(message, meta, "visibility"));
7976
8028
  }
7977
- function isExplicitlyVisibleInTranscript(message, meta) {
8029
+ function readTranscriptVisibilityField(message, meta) {
7978
8030
  const record = message;
7979
- const visibility = readVisibilityField(message, meta);
7980
- const audience = readStringField(record.audience ?? meta?.audience);
7981
- return visibility === "visible" || visibility === "user" || visibility === "chat" || audience === "chat" || record.userFacing === true || meta?.userFacing === true;
8031
+ return readStringField(record.transcriptVisibility ?? meta?.transcriptVisibility ?? record.visibility ?? meta?.visibility);
8032
+ }
8033
+ var EXPLICIT_HIDDEN_VISIBILITIES = /* @__PURE__ */ new Set(["hidden", "debug", "internal"]);
8034
+ var EXPLICIT_VISIBLE_VISIBILITIES = /* @__PURE__ */ new Set(["visible", "user", "chat"]);
8035
+ var HIDDEN_AUDIENCES = /* @__PURE__ */ new Set(["debug", "trace", "internal"]);
8036
+ var ACTIVITY_SOURCE_SET = new Set(CHAT_MESSAGE_ACTIVITY_SOURCES);
8037
+ var INTERNAL_SOURCE_SET = new Set(CHAT_MESSAGE_INTERNAL_SOURCES);
8038
+ function hasBooleanMarker(message, meta, keys) {
8039
+ const record = message;
8040
+ return keys.some((key) => record[key] === true || meta?.[key] === true);
7982
8041
  }
7983
- function isUserFacingChatMessage(message) {
7984
- if (!message) return false;
7985
- const meta = readMessageMeta(message);
7986
- if (isExplicitlyHiddenFromTranscript(message, meta)) return false;
7987
- if (isExplicitlyVisibleInTranscript(message, meta)) return true;
7988
- const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
7989
- const kind = resolveChatMessageKind(message);
8042
+ function isActivityKind(kind) {
8043
+ return kind === "thought" || kind === "tool" || kind === "terminal";
8044
+ }
8045
+ function isOrdinaryVisibleTurn(message, role, kind) {
7990
8046
  if (role === "user" || role === "human") return kind === "standard" || kind === "";
7991
8047
  if (role === "assistant") return kind === "standard" || kind === "";
7992
8048
  return false;
7993
8049
  }
8050
+ function classifyChatMessageVisibility(message) {
8051
+ if (!message) {
8052
+ return {
8053
+ surface: "internal",
8054
+ isUserFacing: false,
8055
+ isActivityFacing: false,
8056
+ isInternal: true,
8057
+ explicitUserFacing: false,
8058
+ explicitHidden: true,
8059
+ role: "",
8060
+ kind: "standard",
8061
+ visibility: "",
8062
+ transcriptVisibility: "",
8063
+ audience: "",
8064
+ source: ""
8065
+ };
8066
+ }
8067
+ const meta = readMessageMeta(message);
8068
+ const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
8069
+ const kind = resolveChatMessageKind(message);
8070
+ const visibility = readVisibilityField(message, meta);
8071
+ const transcriptVisibility = readTranscriptVisibilityField(message, meta);
8072
+ const audience = readStringField(readRecordField(message, meta, "audience"));
8073
+ const source = readStringField(readRecordField(message, meta, "source"));
8074
+ const explicitHidden = EXPLICIT_HIDDEN_VISIBILITIES.has(visibility) || EXPLICIT_HIDDEN_VISIBILITIES.has(transcriptVisibility) || HIDDEN_AUDIENCES.has(audience) || hasBooleanMarker(message, meta, ["internal", "isInternal", "debug", "statusOnly", "controlOnly"]);
8075
+ const explicitUserFacing = EXPLICIT_VISIBLE_VISIBILITIES.has(visibility) || EXPLICIT_VISIBLE_VISIBILITIES.has(transcriptVisibility) || audience === "chat" || hasBooleanMarker(message, meta, ["userFacing"]);
8076
+ if (explicitHidden) {
8077
+ const activityLike = isActivityKind(kind) || ACTIVITY_SOURCE_SET.has(source);
8078
+ return {
8079
+ surface: activityLike ? "activity" : "internal",
8080
+ isUserFacing: false,
8081
+ isActivityFacing: activityLike,
8082
+ isInternal: !activityLike,
8083
+ explicitUserFacing,
8084
+ explicitHidden,
8085
+ role,
8086
+ kind,
8087
+ visibility,
8088
+ transcriptVisibility,
8089
+ audience,
8090
+ source
8091
+ };
8092
+ }
8093
+ if (explicitUserFacing) {
8094
+ return {
8095
+ surface: "chat",
8096
+ isUserFacing: true,
8097
+ isActivityFacing: false,
8098
+ isInternal: false,
8099
+ explicitUserFacing,
8100
+ explicitHidden,
8101
+ role,
8102
+ kind,
8103
+ visibility,
8104
+ transcriptVisibility,
8105
+ audience,
8106
+ source
8107
+ };
8108
+ }
8109
+ if (INTERNAL_SOURCE_SET.has(source) || role === "system" || kind === "system") {
8110
+ return {
8111
+ surface: "internal",
8112
+ isUserFacing: false,
8113
+ isActivityFacing: false,
8114
+ isInternal: true,
8115
+ explicitUserFacing,
8116
+ explicitHidden,
8117
+ role,
8118
+ kind,
8119
+ visibility,
8120
+ transcriptVisibility,
8121
+ audience,
8122
+ source
8123
+ };
8124
+ }
8125
+ if (ACTIVITY_SOURCE_SET.has(source) || isActivityKind(kind)) {
8126
+ return {
8127
+ surface: "activity",
8128
+ isUserFacing: false,
8129
+ isActivityFacing: true,
8130
+ isInternal: false,
8131
+ explicitUserFacing,
8132
+ explicitHidden,
8133
+ role,
8134
+ kind,
8135
+ visibility,
8136
+ transcriptVisibility,
8137
+ audience,
8138
+ source
8139
+ };
8140
+ }
8141
+ const isUserFacing = isOrdinaryVisibleTurn(message, role, kind);
8142
+ return {
8143
+ surface: isUserFacing ? "chat" : "internal",
8144
+ isUserFacing,
8145
+ isActivityFacing: false,
8146
+ isInternal: !isUserFacing,
8147
+ explicitUserFacing,
8148
+ explicitHidden,
8149
+ role,
8150
+ kind,
8151
+ visibility,
8152
+ transcriptVisibility,
8153
+ audience,
8154
+ source
8155
+ };
8156
+ }
8157
+ function isUserFacingChatMessage(message) {
8158
+ return classifyChatMessageVisibility(message).isUserFacing;
8159
+ }
8160
+ function isActivityChatMessage(message) {
8161
+ return classifyChatMessageVisibility(message).isActivityFacing;
8162
+ }
8163
+ function isInternalChatMessage(message) {
8164
+ return classifyChatMessageVisibility(message).isInternal;
8165
+ }
7994
8166
  function filterUserFacingChatMessages(messages) {
7995
8167
  return (Array.isArray(messages) ? messages : []).filter((message) => isUserFacingChatMessage(message));
7996
8168
  }
8169
+ function filterActivityChatMessages(messages) {
8170
+ return (Array.isArray(messages) ? messages : []).filter((message) => isActivityChatMessage(message));
8171
+ }
8172
+ function filterInternalChatMessages(messages) {
8173
+ return (Array.isArray(messages) ? messages : []).filter((message) => isInternalChatMessage(message));
8174
+ }
8175
+ function filterChatMessagesByVisibility(messages, surface) {
8176
+ return (Array.isArray(messages) ? messages : []).filter((message) => classifyChatMessageVisibility(message).surface === surface);
8177
+ }
7997
8178
 
7998
8179
  // src/providers/control-effects.ts
7999
8180
  function extractProviderControlValues(controls, data) {
@@ -11214,6 +11395,147 @@ function normalizeActiveChatData(activeChat, options = FULL_STATUS_ACTIVE_CHAT_O
11214
11395
  return normalized;
11215
11396
  }
11216
11397
 
11398
+ // src/providers/provider-input-support.ts
11399
+ var VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
11400
+ var VALID_INPUT_STRATEGIES = /* @__PURE__ */ new Set(["native", "native_acp", "resource_link", "text_fallback", "paste", "upload"]);
11401
+ var TEXT_ONLY_MESSAGE_INPUT_SUPPORT = Object.freeze({
11402
+ text: true,
11403
+ multipart: false,
11404
+ mediaTypes: ["text"],
11405
+ strategies: []
11406
+ });
11407
+ function getProviderLabel(provider) {
11408
+ return provider?.name || provider?.type || "This provider";
11409
+ }
11410
+ function hasNonEmptyFallbackText(input) {
11411
+ return typeof input.textFallback === "string" && input.textFallback.trim().length > 0;
11412
+ }
11413
+ function getRequestedInputMediaTypes(input) {
11414
+ const types = /* @__PURE__ */ new Set();
11415
+ if (hasNonEmptyFallbackText(input) && !input.parts.some((part) => part.type === "text")) {
11416
+ types.add("text");
11417
+ }
11418
+ for (const part of input.parts) {
11419
+ if (VALID_INPUT_MEDIA_TYPES.has(part.type)) {
11420
+ types.add(part.type);
11421
+ }
11422
+ }
11423
+ return Array.from(types);
11424
+ }
11425
+ function getEffectiveSemanticPartCount(input) {
11426
+ let count = input.parts.length;
11427
+ if (hasNonEmptyFallbackText(input) && !input.parts.some((part) => part.type === "text")) {
11428
+ count += 1;
11429
+ }
11430
+ return count;
11431
+ }
11432
+ function assertTextOnlyInput(provider, input) {
11433
+ const unsupported = getRequestedInputMediaTypes(input).filter((type) => type !== "text");
11434
+ if (unsupported.length === 0) return;
11435
+ const label = getProviderLabel(provider);
11436
+ const suffix = unsupported.length === 1 ? "" : "s";
11437
+ throw new Error(`${label} only supports text input; unsupported input type${suffix}: ${unsupported.join(", ")}`);
11438
+ }
11439
+ function getDeclaredProviderInputSupport(provider) {
11440
+ const rawMediaTypes = Array.isArray(provider?.capabilities?.input?.mediaTypes) ? provider?.capabilities?.input?.mediaTypes.filter((type) => VALID_INPUT_MEDIA_TYPES.has(type)) : [];
11441
+ const strategies = normalizeInputStrategyDescriptors(provider?.capabilities?.input?.strategies);
11442
+ return {
11443
+ multipart: provider?.capabilities?.input?.multipart === true,
11444
+ mediaTypes: new Set(rawMediaTypes.length > 0 ? rawMediaTypes : ["text"]),
11445
+ strategies
11446
+ };
11447
+ }
11448
+ function normalizeInputStrategyDescriptors(raw) {
11449
+ if (!Array.isArray(raw)) return [];
11450
+ const result = [];
11451
+ for (const entry of raw) {
11452
+ if (!entry || typeof entry !== "object") continue;
11453
+ const record = entry;
11454
+ const mediaType = record.mediaType;
11455
+ if (typeof mediaType !== "string" || !VALID_INPUT_MEDIA_TYPES.has(mediaType)) continue;
11456
+ const strategies = Array.isArray(record.strategies) ? record.strategies.filter((value) => typeof value === "string" && VALID_INPUT_STRATEGIES.has(value)) : [];
11457
+ const degradation = Array.isArray(record.degradation) ? record.degradation.filter((value) => typeof value === "string" && VALID_INPUT_STRATEGIES.has(value)) : [];
11458
+ if (strategies.length === 0 && degradation.length === 0) continue;
11459
+ result.push({
11460
+ mediaType,
11461
+ strategies,
11462
+ ...typeof record.native === "boolean" ? { native: record.native } : {},
11463
+ ...degradation.length > 0 ? { degradation } : {}
11464
+ });
11465
+ }
11466
+ return result;
11467
+ }
11468
+ function promptCapabilityFlags(runtimeCapabilities) {
11469
+ const prompt = runtimeCapabilities?.promptCapabilities || {};
11470
+ return {
11471
+ image: prompt.image === true,
11472
+ audio: prompt.audio === true,
11473
+ embeddedContext: prompt.embeddedContext === true
11474
+ };
11475
+ }
11476
+ function supportFromDeclared(provider) {
11477
+ const declared = getDeclaredProviderInputSupport(provider);
11478
+ return {
11479
+ text: true,
11480
+ multipart: declared.multipart,
11481
+ mediaTypes: Array.from(declared.mediaTypes),
11482
+ strategies: declared.strategies
11483
+ };
11484
+ }
11485
+ function getEffectiveMessageInputSupport(provider, runtimeCapabilities) {
11486
+ if (provider?.category !== "acp") {
11487
+ const declared2 = supportFromDeclared(provider);
11488
+ return {
11489
+ ...declared2,
11490
+ mediaTypes: [...declared2.mediaTypes],
11491
+ strategies: declared2.strategies.map((strategy) => ({
11492
+ ...strategy,
11493
+ strategies: [...strategy.strategies],
11494
+ ...strategy.degradation ? { degradation: [...strategy.degradation] } : {}
11495
+ }))
11496
+ };
11497
+ }
11498
+ const declared = supportFromDeclared(provider);
11499
+ const caps = promptCapabilityFlags(runtimeCapabilities);
11500
+ const mediaTypes = /* @__PURE__ */ new Set(["text"]);
11501
+ const strategies = [];
11502
+ if (declared.mediaTypes.includes("resource")) {
11503
+ mediaTypes.add("resource");
11504
+ strategies.push({ mediaType: "resource", strategies: caps.embeddedContext ? ["native_acp", "resource_link", "text_fallback"] : ["resource_link", "text_fallback"], native: caps.embeddedContext, degradation: ["resource_link", "text_fallback"] });
11505
+ }
11506
+ if (declared.mediaTypes.includes("video")) {
11507
+ mediaTypes.add("video");
11508
+ strategies.push({ mediaType: "video", strategies: ["resource_link", "text_fallback"], native: false, degradation: ["resource_link", "text_fallback"] });
11509
+ }
11510
+ if (declared.mediaTypes.includes("image")) {
11511
+ mediaTypes.add("image");
11512
+ strategies.push({ mediaType: "image", strategies: caps.image ? ["native_acp", "resource_link", "text_fallback"] : ["resource_link", "text_fallback"], native: caps.image, degradation: ["resource_link", "text_fallback"] });
11513
+ }
11514
+ if (declared.mediaTypes.includes("audio")) {
11515
+ mediaTypes.add("audio");
11516
+ strategies.push({ mediaType: "audio", strategies: caps.audio ? ["native_acp", "resource_link", "text_fallback"] : ["resource_link", "text_fallback"], native: caps.audio, degradation: ["resource_link", "text_fallback"] });
11517
+ }
11518
+ return {
11519
+ text: true,
11520
+ multipart: declared.multipart && mediaTypes.size > 1,
11521
+ mediaTypes: Array.from(mediaTypes),
11522
+ strategies
11523
+ };
11524
+ }
11525
+ function assertProviderSupportsDeclaredInput(provider, input) {
11526
+ const label = getProviderLabel(provider);
11527
+ const support = getDeclaredProviderInputSupport(provider);
11528
+ const requestedTypes = getRequestedInputMediaTypes(input);
11529
+ const unsupported = requestedTypes.filter((type) => !support.mediaTypes.has(type));
11530
+ if (unsupported.length > 0) {
11531
+ const suffix = unsupported.length === 1 ? "" : "s";
11532
+ throw new Error(`${label} does not support input type${suffix}: ${unsupported.join(", ")}`);
11533
+ }
11534
+ if (getEffectiveSemanticPartCount(input) > 1 && !support.multipart) {
11535
+ throw new Error(`${label} does not support multipart input`);
11536
+ }
11537
+ }
11538
+
11217
11539
  // src/status/builders.ts
11218
11540
  function getActiveChatOptions(profile) {
11219
11541
  if (profile === "full") return {};
@@ -11311,7 +11633,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
11311
11633
  ...git && { git },
11312
11634
  activeChat,
11313
11635
  ...summaryMetadata && { summaryMetadata },
11314
- ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES },
11636
+ ...includeSessionMetadata && { capabilities: state.sessionCapabilities || IDE_SESSION_CAPABILITIES, messageInput: state.messageInput || TEXT_ONLY_MESSAGE_INPUT_SUPPORT },
11315
11637
  cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
11316
11638
  ...includeSessionControls && {
11317
11639
  ...controlValues && { controlValues },
@@ -11346,7 +11668,7 @@ function buildExtensionAgentSession(parent, ext, options) {
11346
11668
  ...git && { git },
11347
11669
  activeChat,
11348
11670
  ...summaryMetadata && { summaryMetadata },
11349
- ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES },
11671
+ ...includeSessionMetadata && { capabilities: ext.sessionCapabilities || EXTENSION_SESSION_CAPABILITIES, messageInput: ext.messageInput || TEXT_ONLY_MESSAGE_INPUT_SUPPORT },
11350
11672
  ...includeSessionControls && {
11351
11673
  ...controlValues && { controlValues },
11352
11674
  providerControls: ext.providerControls
@@ -11410,7 +11732,8 @@ function buildCliSession(state, options) {
11410
11732
  activeChat,
11411
11733
  ...summaryMetadata && { summaryMetadata },
11412
11734
  ...includeSessionMetadata && {
11413
- capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES
11735
+ capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES,
11736
+ messageInput: state.messageInput || TEXT_ONLY_MESSAGE_INPUT_SUPPORT
11414
11737
  },
11415
11738
  ...includeSessionControls && {
11416
11739
  ...controlValues && { controlValues },
@@ -11444,7 +11767,7 @@ function buildAcpSession(state, options) {
11444
11767
  ...git && { git },
11445
11768
  activeChat,
11446
11769
  ...summaryMetadata && { summaryMetadata },
11447
- ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
11770
+ ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES, messageInput: state.messageInput || TEXT_ONLY_MESSAGE_INPUT_SUPPORT },
11448
11771
  ...includeSessionControls && {
11449
11772
  ...controlValues && { controlValues },
11450
11773
  providerControls: state.providerControls
@@ -11563,63 +11886,6 @@ import * as fs4 from "fs";
11563
11886
  import * as os6 from "os";
11564
11887
  import * as path12 from "path";
11565
11888
  import { randomUUID as randomUUID5 } from "crypto";
11566
-
11567
- // src/providers/provider-input-support.ts
11568
- var VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
11569
- function getProviderLabel(provider) {
11570
- return provider?.name || provider?.type || "This provider";
11571
- }
11572
- function hasNonEmptyFallbackText(input) {
11573
- return typeof input.textFallback === "string" && input.textFallback.trim().length > 0;
11574
- }
11575
- function getRequestedInputMediaTypes(input) {
11576
- const types = /* @__PURE__ */ new Set();
11577
- if (hasNonEmptyFallbackText(input) && !input.parts.some((part) => part.type === "text")) {
11578
- types.add("text");
11579
- }
11580
- for (const part of input.parts) {
11581
- if (VALID_INPUT_MEDIA_TYPES.has(part.type)) {
11582
- types.add(part.type);
11583
- }
11584
- }
11585
- return Array.from(types);
11586
- }
11587
- function getEffectiveSemanticPartCount(input) {
11588
- let count = input.parts.length;
11589
- if (hasNonEmptyFallbackText(input) && !input.parts.some((part) => part.type === "text")) {
11590
- count += 1;
11591
- }
11592
- return count;
11593
- }
11594
- function assertTextOnlyInput(provider, input) {
11595
- const unsupported = getRequestedInputMediaTypes(input).filter((type) => type !== "text");
11596
- if (unsupported.length === 0) return;
11597
- const label = getProviderLabel(provider);
11598
- const suffix = unsupported.length === 1 ? "" : "s";
11599
- throw new Error(`${label} only supports text input; unsupported input type${suffix}: ${unsupported.join(", ")}`);
11600
- }
11601
- function getDeclaredProviderInputSupport(provider) {
11602
- const rawMediaTypes = Array.isArray(provider?.capabilities?.input?.mediaTypes) ? provider?.capabilities?.input?.mediaTypes.filter((type) => VALID_INPUT_MEDIA_TYPES.has(type)) : [];
11603
- return {
11604
- multipart: provider?.capabilities?.input?.multipart === true,
11605
- mediaTypes: new Set(rawMediaTypes.length > 0 ? rawMediaTypes : ["text"])
11606
- };
11607
- }
11608
- function assertProviderSupportsDeclaredInput(provider, input) {
11609
- const label = getProviderLabel(provider);
11610
- const support = getDeclaredProviderInputSupport(provider);
11611
- const requestedTypes = getRequestedInputMediaTypes(input);
11612
- const unsupported = requestedTypes.filter((type) => !support.mediaTypes.has(type));
11613
- if (unsupported.length > 0) {
11614
- const suffix = unsupported.length === 1 ? "" : "s";
11615
- throw new Error(`${label} does not support input type${suffix}: ${unsupported.join(", ")}`);
11616
- }
11617
- if (getEffectiveSemanticPartCount(input) > 1 && !support.multipart) {
11618
- throw new Error(`${label} does not support multipart input`);
11619
- }
11620
- }
11621
-
11622
- // src/commands/chat-commands.ts
11623
11889
  init_logger();
11624
11890
 
11625
11891
  // src/logging/debug-trace.ts
@@ -11809,10 +12075,25 @@ function buildRecentSendKey(h, args, provider, signature) {
11809
12075
  const target = args?.targetSessionId || args?.agentType || h.currentSession?.providerType || h.currentProviderType || h.currentManagerKey || "unknown";
11810
12076
  return `${transport}:${target}:${signature.trim()}`;
11811
12077
  }
12078
+ function summarizeSendInputPart(part) {
12079
+ if (!part || typeof part !== "object") return String(part ?? "");
12080
+ if (part.type === "text") return `text:${String(part.text || "").trim()}`;
12081
+ const fields = [
12082
+ `type=${String(part.type || "")}`,
12083
+ `mime=${String(part.mimeType || "")}`,
12084
+ `uri=${String(part.uri || "")}`,
12085
+ `name=${String(part.name || "")}`
12086
+ ];
12087
+ const data = typeof part.data === "string" ? part.data : typeof part.resource?.blob === "string" ? part.resource.blob : "";
12088
+ if (data) fields.push(`dataLen=${data.length}`, `dataHash=${hashSignatureParts([data]).slice(0, 12)}`);
12089
+ const textish = [part.alt, part.transcript, part.description, part.title, part.resource?.uri].filter((value) => typeof value === "string" && value.trim()).join("");
12090
+ if (textish) fields.push(`meta=${hashSignatureParts([textish]).slice(0, 12)}`);
12091
+ return fields.join(";");
12092
+ }
11812
12093
  function buildSendInputSignature(input) {
11813
12094
  const text = typeof input.textFallback === "string" ? input.textFallback.trim() : "";
11814
- if (text) return text;
11815
- return JSON.stringify(input.parts || []);
12095
+ const partSummaries = (input.parts || []).map(summarizeSendInputPart);
12096
+ return hashSignatureParts([text, ...partSummaries]);
11816
12097
  }
11817
12098
  function getSendChatInputEnvelope(args) {
11818
12099
  return normalizeInputEnvelope(args?.input ? { input: args.input } : args);
@@ -12693,6 +12974,17 @@ async function handleSendChat(h, args) {
12693
12974
  if (adapter) {
12694
12975
  _log(`${transport} adapter: ${adapter.cliType}`);
12695
12976
  try {
12977
+ const hasStructuredParts = input.parts.some((part) => part.type !== "text");
12978
+ if (hasStructuredParts) {
12979
+ const target = getTargetInstance(h, args);
12980
+ if (!target || target.category !== "cli") {
12981
+ return { success: false, error: `CLI instance not found for ${provider?.type || args?.agentType || "unknown"}` };
12982
+ }
12983
+ assertProviderSupportsDeclaredInput(provider, input);
12984
+ await waitOnceForFreshHermesCliStart(adapter, _log);
12985
+ target.onEvent("send_message", { input });
12986
+ return _logSendSuccess(`${transport}-instance`, target.type);
12987
+ }
12696
12988
  assertTextOnlyInput(provider, input);
12697
12989
  if (!text) return { success: false, error: "text required for PTY send" };
12698
12990
  await waitOnceForFreshHermesCliStart(adapter, _log);
@@ -14783,9 +15075,9 @@ var DaemonCommandHandler = class {
14783
15075
  // src/commands/cli-manager.ts
14784
15076
  init_provider_cli_adapter();
14785
15077
  import * as os13 from "os";
14786
- import * as path17 from "path";
15078
+ import * as path18 from "path";
14787
15079
  import * as crypto4 from "crypto";
14788
- import { existsSync as existsSync12, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "fs";
15080
+ import { existsSync as existsSync12, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
14789
15081
  import { execFileSync } from "child_process";
14790
15082
  import chalk from "chalk";
14791
15083
  init_config();
@@ -14817,6 +15109,79 @@ function normalizeProviderSessionId(provider, providerSessionId) {
14817
15109
  }
14818
15110
 
14819
15111
  // src/providers/cli-provider-instance.ts
15112
+ var IMAGE_MIME_EXTENSIONS = {
15113
+ "image/png": ".png",
15114
+ "image/jpeg": ".jpg",
15115
+ "image/jpg": ".jpg",
15116
+ "image/gif": ".gif",
15117
+ "image/webp": ".webp",
15118
+ "image/bmp": ".bmp",
15119
+ "image/tiff": ".tiff",
15120
+ "image/svg+xml": ".svg"
15121
+ };
15122
+ function filePathFromUri(uri) {
15123
+ if (!uri) return null;
15124
+ if (uri.startsWith("file://")) {
15125
+ try {
15126
+ return decodeURIComponent(new URL(uri).pathname);
15127
+ } catch {
15128
+ return uri.slice("file://".length);
15129
+ }
15130
+ }
15131
+ if (path16.isAbsolute(uri)) return uri;
15132
+ return null;
15133
+ }
15134
+ function extensionForImageMime(mimeType) {
15135
+ return IMAGE_MIME_EXTENSIONS[mimeType.toLowerCase()] || ".img";
15136
+ }
15137
+ function safeInputImageBasename(index, mimeType) {
15138
+ const extension = extensionForImageMime(mimeType);
15139
+ const suffix = crypto3.randomBytes(6).toString("hex");
15140
+ return `adhdev-input-image-${Date.now()}-${index}-${suffix}${extension}`;
15141
+ }
15142
+ function materializeImageDataPart(part, index, dir) {
15143
+ if (!part.data) return null;
15144
+ const rawData = part.data.includes(",") ? part.data.split(",").pop() || "" : part.data;
15145
+ if (!rawData) return null;
15146
+ fs6.mkdirSync(dir, { recursive: true });
15147
+ const filePath = path16.join(dir, safeInputImageBasename(index, part.mimeType));
15148
+ fs6.writeFileSync(filePath, Buffer.from(rawData, "base64"));
15149
+ return filePath;
15150
+ }
15151
+ function buildCliStructuredInputPrompt(input, options = {}) {
15152
+ const promptParts = [];
15153
+ const imageRefs = [];
15154
+ const resourceRefs = [];
15155
+ const materializeDir = options.materializeDir || path16.join(os12.tmpdir(), "adhdev-input-media");
15156
+ input.parts.forEach((part, index) => {
15157
+ if (part.type === "text" && part.text.trim()) {
15158
+ promptParts.push(part.text.trim());
15159
+ return;
15160
+ }
15161
+ if (part.type === "image") {
15162
+ const localPath = typeof part.uri === "string" ? filePathFromUri(part.uri) : null;
15163
+ const materializedPath = !localPath && part.data ? materializeImageDataPart(part, index, materializeDir) : null;
15164
+ const ref = localPath || materializedPath || part.uri || "";
15165
+ if (ref) imageRefs.push(ref);
15166
+ if (part.alt?.trim()) promptParts.push(part.alt.trim());
15167
+ return;
15168
+ }
15169
+ if (part.type === "resource_link") {
15170
+ resourceRefs.push([part.title, part.name, part.description, part.uri].filter(Boolean).join("\n"));
15171
+ return;
15172
+ }
15173
+ if (part.type === "resource") {
15174
+ resourceRefs.push([part.name, part.text, part.uri].filter(Boolean).join("\n"));
15175
+ }
15176
+ });
15177
+ if (input.textFallback.trim()) promptParts.push(input.textFallback.trim());
15178
+ const ordered = [
15179
+ ...imageRefs,
15180
+ ...promptParts,
15181
+ ...resourceRefs
15182
+ ].filter((value, index, values) => value.trim().length > 0 && values.indexOf(value) === index);
15183
+ return ordered.join("\n");
15184
+ }
14820
15185
  function normalizePersistableCliHistoryContent(content) {
14821
15186
  return flattenContent(content).replace(/\s+/g, " ").trim();
14822
15187
  }
@@ -15136,6 +15501,7 @@ var CliProviderInstance = class {
15136
15501
  resume: this.provider.resume,
15137
15502
  controlValues: surface.controlValues,
15138
15503
  providerControls: this.provider.controls,
15504
+ messageInput: getEffectiveMessageInputSupport(this.provider),
15139
15505
  summaryMetadata: surface.summaryMetadata,
15140
15506
  errorMessage: this.errorMessage,
15141
15507
  errorReason: this.errorReason
@@ -15186,9 +15552,10 @@ var CliProviderInstance = class {
15186
15552
  onEvent(event, data) {
15187
15553
  if (event === "send_message") {
15188
15554
  const input = normalizeInputEnvelope(data);
15189
- assertTextOnlyInput(this.provider, input);
15190
- if (input.textFallback) {
15191
- void this.adapter.sendMessage(input.textFallback).catch((e) => {
15555
+ assertProviderSupportsDeclaredInput(this.provider, input);
15556
+ const promptText = buildCliStructuredInputPrompt(input);
15557
+ if (promptText) {
15558
+ void this.adapter.sendMessage(promptText).catch((e) => {
15192
15559
  LOG.warn("CLI", `[${this.type}] send_message failed: ${e?.message || e}`);
15193
15560
  });
15194
15561
  }
@@ -15817,6 +16184,7 @@ ${effect.notification.body || ""}`.trim();
15817
16184
  };
15818
16185
 
15819
16186
  // src/providers/acp-provider-instance.ts
16187
+ import * as path17 from "path";
15820
16188
  import { Readable, Writable } from "stream";
15821
16189
  import { spawn } from "child_process";
15822
16190
  import {
@@ -15841,6 +16209,31 @@ function appendPromptText(promptParts, text) {
15841
16209
  if (last?.type === "text" && last.text === normalized) return;
15842
16210
  promptParts.push({ type: "text", text: normalized });
15843
16211
  }
16212
+ function getUriDisplayName2(uri, fallback) {
16213
+ if (!uri) return fallback;
16214
+ try {
16215
+ const pathname = uri.startsWith("file://") ? new URL(uri).pathname : uri;
16216
+ return pathname.split(/[\\/]/).filter(Boolean).pop() || fallback;
16217
+ } catch {
16218
+ return uri.split(/[\\/]/).filter(Boolean).pop() || fallback;
16219
+ }
16220
+ }
16221
+ function appendResourceLink(promptParts, uri, fallbackName, mimeType, description, metadata) {
16222
+ promptParts.push({
16223
+ type: "resource_link",
16224
+ uri,
16225
+ name: metadata?.name || getUriDisplayName2(uri, fallbackName),
16226
+ ...metadata?.title ? { title: metadata.title } : {},
16227
+ ...mimeType ? { mimeType } : {},
16228
+ ...description ? { description } : {},
16229
+ ...typeof metadata?.size === "number" ? { size: metadata.size } : {},
16230
+ ...metadata?.annotations ? { annotations: metadata.annotations } : {}
16231
+ });
16232
+ }
16233
+ function appendMediaFallbackText(promptParts, label, details) {
16234
+ const normalizedDetails = details.map((value) => typeof value === "string" ? value.trim() : "").filter(Boolean);
16235
+ appendPromptText(promptParts, `[${[label, ...normalizedDetails].join(": ")}]`);
16236
+ }
15844
16237
  function buildAcpPromptParts(input, agentCapabilities) {
15845
16238
  const caps = getPromptCapabilityFlags(agentCapabilities);
15846
16239
  const promptParts = [];
@@ -15850,56 +16243,76 @@ function buildAcpPromptParts(input, agentCapabilities) {
15850
16243
  continue;
15851
16244
  }
15852
16245
  if (part.type === "image") {
15853
- if (!caps.image) {
15854
- throw new Error("ACP agent does not support input type: image");
15855
- }
15856
- if (!part.data) {
15857
- throw new Error("ACP image input requires inline image data");
16246
+ if (caps.image && part.data) {
16247
+ promptParts.push({
16248
+ type: "image",
16249
+ data: part.data,
16250
+ mimeType: part.mimeType,
16251
+ ...part.uri ? { uri: part.uri } : {},
16252
+ ...part.alt ? { alt: part.alt } : {}
16253
+ });
16254
+ if (part.alt) appendPromptText(promptParts, part.alt);
16255
+ } else if (part.uri) {
16256
+ appendResourceLink(promptParts, part.uri, "image", part.mimeType, part.alt);
16257
+ if (part.alt) appendPromptText(promptParts, part.alt);
16258
+ } else {
16259
+ appendMediaFallbackText(promptParts, "Image attachment", [part.alt, part.mimeType]);
15858
16260
  }
15859
- promptParts.push({
15860
- type: "image",
15861
- data: part.data,
15862
- mimeType: part.mimeType,
15863
- ...part.uri ? { uri: part.uri } : {}
15864
- });
15865
16261
  continue;
15866
16262
  }
15867
16263
  if (part.type === "audio") {
15868
- if (!caps.audio) {
15869
- throw new Error("ACP agent does not support input type: audio");
15870
- }
15871
- if (!part.data) {
15872
- throw new Error("ACP audio input requires inline audio data");
16264
+ if (caps.audio && part.data) {
16265
+ promptParts.push({
16266
+ type: "audio",
16267
+ data: part.data,
16268
+ mimeType: part.mimeType,
16269
+ ...part.uri ? { uri: part.uri } : {},
16270
+ ...part.transcript ? { transcript: part.transcript } : {}
16271
+ });
16272
+ if (part.transcript) appendPromptText(promptParts, part.transcript);
16273
+ } else if (part.uri) {
16274
+ appendResourceLink(promptParts, part.uri, "audio", part.mimeType, part.transcript);
16275
+ if (part.transcript) appendPromptText(promptParts, part.transcript);
16276
+ } else {
16277
+ appendMediaFallbackText(promptParts, "Audio attachment", [part.transcript, part.mimeType]);
15873
16278
  }
15874
- promptParts.push({
15875
- type: "audio",
15876
- data: part.data,
15877
- mimeType: part.mimeType
15878
- });
15879
16279
  continue;
15880
16280
  }
15881
16281
  if (part.type === "resource") {
15882
- if (!caps.embeddedContext) {
15883
- throw new Error("ACP agent does not support input type: resource");
15884
- }
15885
- if (part.text) {
16282
+ if (caps.embeddedContext && part.text) {
15886
16283
  promptParts.push({
15887
16284
  type: "resource",
15888
16285
  resource: { uri: part.uri, text: part.text, mimeType: part.mimeType ?? null }
15889
16286
  });
15890
16287
  continue;
15891
16288
  }
15892
- if (part.data) {
16289
+ if (caps.embeddedContext && part.data) {
15893
16290
  promptParts.push({
15894
16291
  type: "resource",
15895
16292
  resource: { uri: part.uri, blob: part.data, mimeType: part.mimeType ?? null }
15896
16293
  });
15897
16294
  continue;
15898
16295
  }
15899
- throw new Error("ACP resource input requires embedded text or binary data");
16296
+ appendResourceLink(promptParts, part.uri, part.name || "resource", part.mimeType, part.text);
16297
+ if (part.text) appendPromptText(promptParts, part.text);
16298
+ continue;
16299
+ }
16300
+ if (part.type === "resource_link") {
16301
+ appendResourceLink(promptParts, part.uri, part.name, part.mimeType, part.description, {
16302
+ name: part.name,
16303
+ ...part.title ? { title: part.title } : {},
16304
+ ...typeof part.size === "number" ? { size: part.size } : {},
16305
+ ...part.annotations ? { annotations: part.annotations } : {}
16306
+ });
16307
+ continue;
15900
16308
  }
15901
16309
  if (part.type === "video") {
15902
- throw new Error("ACP agent does not support input type: video");
16310
+ if (part.uri) {
16311
+ appendResourceLink(promptParts, part.uri, "video", part.mimeType, part.transcript);
16312
+ if (part.transcript) appendPromptText(promptParts, part.transcript);
16313
+ } else {
16314
+ appendMediaFallbackText(promptParts, "Video attachment", [part.transcript, part.mimeType]);
16315
+ }
15903
16316
  }
15904
16317
  }
15905
16318
  if (!promptParts.some((part) => part.type === "text") && input.textFallback) {
@@ -16032,6 +16445,7 @@ var AcpProviderInstance = class {
16032
16445
  lastUpdated: Date.now(),
16033
16446
  settings: this.settings,
16034
16447
  pendingEvents: this.flushEvents(),
16448
+ messageInput: getEffectiveMessageInputSupport(this.provider, this.agentCapabilities),
16035
16449
  // ACP-specific: expose available models/modes for dashboard
16036
16450
  acpConfigOptions: this.configOptions,
16037
16451
  acpModes: this.availableModes,
@@ -16533,22 +16947,38 @@ var AcpProviderInstance = class {
16533
16947
  type: "image",
16534
16948
  data: b.data,
16535
16949
  mimeType: b.mimeType,
16536
- ...b.uri ? { uri: b.uri } : {}
16950
+ ...b.uri ? { uri: b.uri } : {},
16951
+ ...b.alt ? { alt: b.alt } : {}
16537
16952
  };
16538
16953
  }
16539
16954
  if (b.type === "audio") {
16540
16955
  return {
16541
16956
  type: "audio",
16542
16957
  data: b.data,
16543
- mimeType: b.mimeType
16958
+ mimeType: b.mimeType,
16959
+ ...b.uri ? { uri: b.uri } : {},
16960
+ ...b.transcript ? { transcript: b.transcript } : {}
16544
16961
  };
16545
16962
  }
16963
+ if (b.type === "video") {
16964
+ return b.uri ? {
16965
+ type: "resource_link",
16966
+ uri: b.uri,
16967
+ name: path17.basename(b.uri),
16968
+ mimeType: b.mimeType,
16969
+ ...b.transcript ? { description: b.transcript } : {}
16970
+ } : { type: "text", text: b.transcript || `[Video attachment: ${b.mimeType}]` };
16971
+ }
16546
16972
  if (b.type === "resource_link") {
16547
16973
  return {
16548
16974
  type: "resource_link",
16549
16975
  uri: b.uri,
16550
16976
  name: b.name,
16551
- ...b.mimeType ? { mimeType: b.mimeType } : {}
16977
+ ...b.title ? { title: b.title } : {},
16978
+ ...b.description ? { description: b.description } : {},
16979
+ ...b.mimeType ? { mimeType: b.mimeType } : {},
16980
+ ...typeof b.size === "number" ? { size: b.size } : {},
16981
+ ...b.annotations ? { annotations: b.annotations } : {}
16552
16982
  };
16553
16983
  }
16554
16984
  if (b.type === "resource") return { type: "resource", resource: b.resource };
@@ -16624,7 +17054,18 @@ var AcpProviderInstance = class {
16624
17054
  this.partialBlocks.push({
16625
17055
  type: "audio",
16626
17056
  data: content.data,
16627
- mimeType: content.mimeType
17057
+ mimeType: content.mimeType,
17058
+ ...content.uri ? { uri: content.uri } : {},
17059
+ ...content.transcript ? { transcript: content.transcript } : {}
17060
+ });
17061
+ } else if (content.type === "video") {
17062
+ this.partialBlocks.push({
17063
+ type: "video",
17064
+ data: content.data,
17065
+ mimeType: content.mimeType,
17066
+ ...content.uri ? { uri: content.uri } : {},
17067
+ ...content.transcript ? { transcript: content.transcript } : {},
17068
+ ...content.posterUri ? { posterUri: content.posterUri } : {}
16628
17069
  });
16629
17070
  } else if (content.type === "resource_link") {
16630
17071
  this.partialBlocks.push({
@@ -16981,11 +17422,11 @@ function shouldRestoreHostedRuntime(record, managerTag) {
16981
17422
  // src/commands/cli-manager.ts
16982
17423
  function isExplicitCommand(command) {
16983
17424
  const trimmed = command.trim();
16984
- return path17.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
17425
+ return path18.isAbsolute(trimmed) || trimmed.includes("/") || trimmed.includes("\\") || trimmed.startsWith("~");
16985
17426
  }
16986
17427
  function expandExecutable(command) {
16987
17428
  const trimmed = command.trim();
16988
- return trimmed.startsWith("~") ? path17.join(os13.homedir(), trimmed.slice(1)) : trimmed;
17429
+ return trimmed.startsWith("~") ? path18.join(os13.homedir(), trimmed.slice(1)) : trimmed;
16989
17430
  }
16990
17431
  function commandExists(command) {
16991
17432
  const trimmed = command.trim();
@@ -17019,11 +17460,11 @@ function hasCliArg(args, flag) {
17019
17460
  return args.some((arg) => arg === flag || arg.startsWith(`${flag}=`));
17020
17461
  }
17021
17462
  function ensureEmptyDelegatedMcpConfig(workspace) {
17022
- const baseDir = path17.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
17023
- mkdirSync7(baseDir, { recursive: true });
17024
- const workspaceHash = crypto4.createHash("sha256").update(path17.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
17025
- const filePath = path17.join(baseDir, `${workspaceHash}.json`);
17026
- writeFileSync7(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
17463
+ const baseDir = path18.join(os13.tmpdir(), "adhdev-delegated-agent-empty-mcp");
17464
+ mkdirSync8(baseDir, { recursive: true });
17465
+ const workspaceHash = crypto4.createHash("sha256").update(path18.resolve(workspace || os13.tmpdir())).digest("hex").slice(0, 16);
17466
+ const filePath = path18.join(baseDir, `${workspaceHash}.json`);
17467
+ writeFileSync8(filePath, JSON.stringify({ mcpServers: {} }, null, 2), "utf-8");
17027
17468
  return filePath;
17028
17469
  }
17029
17470
  function buildCoordinatorDelegatedCliLaunchOptions(input) {
@@ -17295,7 +17736,7 @@ var DaemonCliManager = class {
17295
17736
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
17296
17737
  const trimmed = (workingDir || "").trim();
17297
17738
  if (!trimmed) throw new Error("working directory required");
17298
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path17.resolve(trimmed);
17739
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os13.homedir()) : path18.resolve(trimmed);
17299
17740
  const normalizedType = this.providerLoader.resolveAlias(cliType);
17300
17741
  const rawProvider = this.providerLoader.getByAlias(cliType);
17301
17742
  const provider = rawProvider ? this.providerLoader.resolve(normalizedType) || rawProvider : void 0;
@@ -17809,17 +18250,18 @@ Run 'adhdev doctor' for detailed diagnostics.`
17809
18250
  import { execSync as execSync4, spawn as spawn2 } from "child_process";
17810
18251
  import * as net from "net";
17811
18252
  import * as os15 from "os";
17812
- import * as path19 from "path";
18253
+ import * as path20 from "path";
17813
18254
 
17814
18255
  // src/providers/provider-loader.ts
17815
18256
  import * as fs7 from "fs";
17816
- import * as path18 from "path";
18257
+ import * as path19 from "path";
17817
18258
  import * as os14 from "os";
17818
18259
  import * as chokidar from "chokidar";
17819
18260
  init_logger();
17820
18261
 
17821
18262
  // src/providers/provider-schema.ts
17822
18263
  var VALID_CAPABILITY_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
18264
+ var VALID_INPUT_STRATEGIES2 = /* @__PURE__ */ new Set(["native", "native_acp", "resource_link", "text_fallback", "paste", "upload"]);
17823
18265
  var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
17824
18266
  "type",
17825
18267
  "name",
@@ -17949,16 +18391,45 @@ function validateCapabilities(provider, controls, errors) {
17949
18391
  return;
17950
18392
  }
17951
18393
  const input = capabilities.input;
17952
- if (!input || typeof input !== "object") {
17953
- errors.push("capabilities.input is required");
17954
- } else {
17955
- if (typeof input.multipart !== "boolean") {
18394
+ if (input !== void 0) {
18395
+ if (!input || typeof input !== "object") {
18396
+ errors.push("capabilities.input must be an object when provided");
18397
+ } else if (typeof input.multipart !== "boolean") {
17956
18398
  errors.push("capabilities.input.multipart must be boolean");
17957
18399
  }
17958
- if (!Array.isArray(input.mediaTypes) || input.mediaTypes.length === 0) {
17959
- errors.push("capabilities.input.mediaTypes must be a non-empty array");
17960
- } else if (input.mediaTypes.some((type) => typeof type !== "string" || !VALID_CAPABILITY_MEDIA_TYPES.has(type))) {
17961
- errors.push(`capabilities.input.mediaTypes must only include: ${Array.from(VALID_CAPABILITY_MEDIA_TYPES).join(", ")}`);
18400
+ if (input && typeof input === "object") {
18401
+ const mediaTypes = Array.isArray(input.mediaTypes) ? input.mediaTypes : void 0;
18402
+ if (!mediaTypes || mediaTypes.length === 0) {
18403
+ errors.push("capabilities.input.mediaTypes must be a non-empty array");
18404
+ } else if (mediaTypes.some((type) => typeof type !== "string" || !VALID_CAPABILITY_MEDIA_TYPES.has(type))) {
18405
+ errors.push(`capabilities.input.mediaTypes must only include: ${Array.from(VALID_CAPABILITY_MEDIA_TYPES).join(", ")}`);
18406
+ }
18407
+ }
18408
+ if (input && typeof input === "object" && input.strategies !== void 0) {
18409
+ if (!Array.isArray(input.strategies)) {
18410
+ errors.push("capabilities.input.strategies must be an array when provided");
18411
+ } else {
18412
+ for (const strategy of input.strategies) {
18413
+ if (!strategy || typeof strategy !== "object" || Array.isArray(strategy)) {
18414
+ errors.push("capabilities.input.strategies entries must be objects");
18415
+ continue;
18416
+ }
18417
+ const entry = strategy;
18418
+ if (typeof entry.mediaType !== "string" || !VALID_CAPABILITY_MEDIA_TYPES.has(entry.mediaType)) {
18419
+ errors.push(`capabilities.input.strategies.mediaType must only include: ${Array.from(VALID_CAPABILITY_MEDIA_TYPES).join(", ")}`);
18420
+ }
18421
+ for (const field of ["strategies", "degradation"]) {
18422
+ const values = entry[field];
18423
+ if (values === void 0) continue;
18424
+ if (!Array.isArray(values) || values.some((value) => typeof value !== "string" || !VALID_INPUT_STRATEGIES2.has(value))) {
18425
+ errors.push(`capabilities.input.strategies.${field} must only include: ${Array.from(VALID_INPUT_STRATEGIES2).join(", ")}`);
18426
+ }
18427
+ }
18428
+ if (entry.native !== void 0 && typeof entry.native !== "boolean") {
18429
+ errors.push("capabilities.input.strategies.native must be boolean when provided");
18430
+ }
18431
+ }
18432
+ }
17962
18433
  }
17963
18434
  }
17964
18435
  const output = capabilities.output;
@@ -18137,7 +18608,7 @@ var ProviderLoader = class _ProviderLoader {
18137
18608
  try {
18138
18609
  if (!fs7.existsSync(candidate) || !fs7.statSync(candidate).isDirectory()) return false;
18139
18610
  return ["ide", "extension", "cli", "acp"].some(
18140
- (category) => fs7.existsSync(path18.join(candidate, category))
18611
+ (category) => fs7.existsSync(path19.join(candidate, category))
18141
18612
  );
18142
18613
  } catch {
18143
18614
  return false;
@@ -18145,20 +18616,20 @@ var ProviderLoader = class _ProviderLoader {
18145
18616
  }
18146
18617
  static hasProviderRootMarker(candidate) {
18147
18618
  try {
18148
- return fs7.existsSync(path18.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18619
+ return fs7.existsSync(path19.join(candidate, _ProviderLoader.SIBLING_MARKER_FILE));
18149
18620
  } catch {
18150
18621
  return false;
18151
18622
  }
18152
18623
  }
18153
18624
  detectDefaultUserDir() {
18154
- const fallback = path18.join(os14.homedir(), ".adhdev", "providers");
18625
+ const fallback = path19.join(os14.homedir(), ".adhdev", "providers");
18155
18626
  const envOptIn = process.env[_ProviderLoader.SIBLING_ENV_VAR] === "1";
18156
18627
  const visited = /* @__PURE__ */ new Set();
18157
18628
  for (const start of this.probeStarts) {
18158
- let current = path18.resolve(start);
18629
+ let current = path19.resolve(start);
18159
18630
  while (!visited.has(current)) {
18160
18631
  visited.add(current);
18161
- const siblingCandidate = path18.join(path18.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18632
+ const siblingCandidate = path19.join(path19.dirname(current), _ProviderLoader.REPO_PROVIDER_DIRNAME);
18162
18633
  if (_ProviderLoader.looksLikeProviderRoot(siblingCandidate)) {
18163
18634
  const hasMarker = _ProviderLoader.hasProviderRootMarker(siblingCandidate);
18164
18635
  if (envOptIn || hasMarker) {
@@ -18180,7 +18651,7 @@ var ProviderLoader = class _ProviderLoader {
18180
18651
  return { path: siblingCandidate, source };
18181
18652
  }
18182
18653
  }
18183
- const parent = path18.dirname(current);
18654
+ const parent = path19.dirname(current);
18184
18655
  if (parent === current) break;
18185
18656
  current = parent;
18186
18657
  }
@@ -18190,11 +18661,11 @@ var ProviderLoader = class _ProviderLoader {
18190
18661
  constructor(options) {
18191
18662
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
18192
18663
  this.probeStarts = options?.probeStarts ?? [process.cwd(), __dirname];
18193
- this.defaultProvidersDir = path18.join(os14.homedir(), ".adhdev", "providers");
18664
+ this.defaultProvidersDir = path19.join(os14.homedir(), ".adhdev", "providers");
18194
18665
  const detected = this.detectDefaultUserDir();
18195
18666
  this.userDir = detected.path;
18196
18667
  this.userDirSource = detected.source;
18197
- this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
18668
+ this.upstreamDir = path19.join(this.defaultProvidersDir, ".upstream");
18198
18669
  this.disableUpstream = false;
18199
18670
  this.applySourceConfig({
18200
18671
  userDir: options?.userDir,
@@ -18253,7 +18724,7 @@ var ProviderLoader = class _ProviderLoader {
18253
18724
  this.userDir = detected.path;
18254
18725
  this.userDirSource = detected.source;
18255
18726
  }
18256
- this.upstreamDir = path18.join(this.defaultProvidersDir, ".upstream");
18727
+ this.upstreamDir = path19.join(this.defaultProvidersDir, ".upstream");
18257
18728
  this.disableUpstream = this.sourceMode === "no-upstream";
18258
18729
  if (this.explicitProviderDir) {
18259
18730
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
@@ -18267,7 +18738,7 @@ var ProviderLoader = class _ProviderLoader {
18267
18738
  * Canonical provider directory shape for a given root.
18268
18739
  */
18269
18740
  getProviderDir(root, category, type) {
18270
- return path18.join(root, category, type);
18741
+ return path19.join(root, category, type);
18271
18742
  }
18272
18743
  /**
18273
18744
  * Canonical user override directory for a provider.
@@ -18294,7 +18765,7 @@ var ProviderLoader = class _ProviderLoader {
18294
18765
  resolveProviderFile(type, ...segments) {
18295
18766
  const dir = this.findProviderDirInternal(type);
18296
18767
  if (!dir) return null;
18297
- return path18.join(dir, ...segments);
18768
+ return path19.join(dir, ...segments);
18298
18769
  }
18299
18770
  /**
18300
18771
  * Load all providers (3-tier priority)
@@ -18333,7 +18804,7 @@ var ProviderLoader = class _ProviderLoader {
18333
18804
  if (!fs7.existsSync(this.upstreamDir)) return false;
18334
18805
  try {
18335
18806
  return fs7.readdirSync(this.upstreamDir).some(
18336
- (d) => fs7.statSync(path18.join(this.upstreamDir, d)).isDirectory()
18807
+ (d) => fs7.statSync(path19.join(this.upstreamDir, d)).isDirectory()
18337
18808
  );
18338
18809
  } catch {
18339
18810
  return false;
@@ -18830,8 +19301,8 @@ var ProviderLoader = class _ProviderLoader {
18830
19301
  resolved._resolvedScriptDir = entry.scriptDir;
18831
19302
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
18832
19303
  if (providerDir) {
18833
- const fullDir = path18.join(providerDir, entry.scriptDir);
18834
- resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
19304
+ const fullDir = path19.join(providerDir, entry.scriptDir);
19305
+ resolved._resolvedScriptsPath = fs7.existsSync(path19.join(fullDir, "scripts.js")) ? path19.join(fullDir, "scripts.js") : fullDir;
18835
19306
  }
18836
19307
  matched = true;
18837
19308
  }
@@ -18846,8 +19317,8 @@ var ProviderLoader = class _ProviderLoader {
18846
19317
  resolved._resolvedScriptDir = base.defaultScriptDir;
18847
19318
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
18848
19319
  if (providerDir) {
18849
- const fullDir = path18.join(providerDir, base.defaultScriptDir);
18850
- resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
19320
+ const fullDir = path19.join(providerDir, base.defaultScriptDir);
19321
+ resolved._resolvedScriptsPath = fs7.existsSync(path19.join(fullDir, "scripts.js")) ? path19.join(fullDir, "scripts.js") : fullDir;
18851
19322
  }
18852
19323
  }
18853
19324
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -18864,8 +19335,8 @@ var ProviderLoader = class _ProviderLoader {
18864
19335
  resolved._resolvedScriptDir = dirOverride;
18865
19336
  resolved._resolvedScriptsSource = `versions:${range}`;
18866
19337
  if (providerDir) {
18867
- const fullDir = path18.join(providerDir, dirOverride);
18868
- resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
19338
+ const fullDir = path19.join(providerDir, dirOverride);
19339
+ resolved._resolvedScriptsPath = fs7.existsSync(path19.join(fullDir, "scripts.js")) ? path19.join(fullDir, "scripts.js") : fullDir;
18869
19340
  }
18870
19341
  }
18871
19342
  } else if (override.scripts) {
@@ -18881,8 +19352,8 @@ var ProviderLoader = class _ProviderLoader {
18881
19352
  resolved._resolvedScriptDir = base.defaultScriptDir;
18882
19353
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
18883
19354
  if (providerDir) {
18884
- const fullDir = path18.join(providerDir, base.defaultScriptDir);
18885
- resolved._resolvedScriptsPath = fs7.existsSync(path18.join(fullDir, "scripts.js")) ? path18.join(fullDir, "scripts.js") : fullDir;
19355
+ const fullDir = path19.join(providerDir, base.defaultScriptDir);
19356
+ resolved._resolvedScriptsPath = fs7.existsSync(path19.join(fullDir, "scripts.js")) ? path19.join(fullDir, "scripts.js") : fullDir;
18886
19357
  }
18887
19358
  }
18888
19359
  }
@@ -18914,14 +19385,14 @@ var ProviderLoader = class _ProviderLoader {
18914
19385
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
18915
19386
  return null;
18916
19387
  }
18917
- const dir = path18.join(providerDir, scriptDir);
19388
+ const dir = path19.join(providerDir, scriptDir);
18918
19389
  if (!fs7.existsSync(dir)) {
18919
19390
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
18920
19391
  return null;
18921
19392
  }
18922
19393
  const cached = this.scriptsCache.get(dir);
18923
19394
  if (cached) return cached;
18924
- const scriptsJs = path18.join(dir, "scripts.js");
19395
+ const scriptsJs = path19.join(dir, "scripts.js");
18925
19396
  if (fs7.existsSync(scriptsJs)) {
18926
19397
  try {
18927
19398
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -18963,7 +19434,7 @@ var ProviderLoader = class _ProviderLoader {
18963
19434
  return;
18964
19435
  }
18965
19436
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
18966
- this.log(`File changed: ${path18.basename(filePath)}, reloading...`);
19437
+ this.log(`File changed: ${path19.basename(filePath)}, reloading...`);
18967
19438
  this.reload();
18968
19439
  }
18969
19440
  };
@@ -19018,7 +19489,7 @@ var ProviderLoader = class _ProviderLoader {
19018
19489
  }
19019
19490
  const https = __require("https");
19020
19491
  const { execSync: execSync7 } = __require("child_process");
19021
- const metaPath = path18.join(this.upstreamDir, _ProviderLoader.META_FILE);
19492
+ const metaPath = path19.join(this.upstreamDir, _ProviderLoader.META_FILE);
19022
19493
  let prevEtag = "";
19023
19494
  let prevTimestamp = 0;
19024
19495
  try {
@@ -19078,17 +19549,17 @@ var ProviderLoader = class _ProviderLoader {
19078
19549
  return { updated: false };
19079
19550
  }
19080
19551
  this.log("Downloading latest providers from GitHub...");
19081
- const tmpTar = path18.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
19082
- const tmpExtract = path18.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
19552
+ const tmpTar = path19.join(os14.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
19553
+ const tmpExtract = path19.join(os14.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
19083
19554
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
19084
19555
  fs7.mkdirSync(tmpExtract, { recursive: true });
19085
19556
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
19086
19557
  const extracted = fs7.readdirSync(tmpExtract);
19087
19558
  const rootDir = extracted.find(
19088
- (d) => fs7.statSync(path18.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
19559
+ (d) => fs7.statSync(path19.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
19089
19560
  );
19090
19561
  if (!rootDir) throw new Error("Unexpected tarball structure");
19091
- const sourceDir = path18.join(tmpExtract, rootDir);
19562
+ const sourceDir = path19.join(tmpExtract, rootDir);
19092
19563
  const backupDir = this.upstreamDir + ".bak";
19093
19564
  if (fs7.existsSync(this.upstreamDir)) {
19094
19565
  if (fs7.existsSync(backupDir)) fs7.rmSync(backupDir, { recursive: true, force: true });
@@ -19163,8 +19634,8 @@ var ProviderLoader = class _ProviderLoader {
19163
19634
  copyDirRecursive(src, dest) {
19164
19635
  fs7.mkdirSync(dest, { recursive: true });
19165
19636
  for (const entry of fs7.readdirSync(src, { withFileTypes: true })) {
19166
- const srcPath = path18.join(src, entry.name);
19167
- const destPath = path18.join(dest, entry.name);
19637
+ const srcPath = path19.join(src, entry.name);
19638
+ const destPath = path19.join(dest, entry.name);
19168
19639
  if (entry.isDirectory()) {
19169
19640
  this.copyDirRecursive(srcPath, destPath);
19170
19641
  } else {
@@ -19175,7 +19646,7 @@ var ProviderLoader = class _ProviderLoader {
19175
19646
  /** .meta.json save */
19176
19647
  writeMeta(metaPath, etag, timestamp) {
19177
19648
  try {
19178
- fs7.mkdirSync(path18.dirname(metaPath), { recursive: true });
19649
+ fs7.mkdirSync(path19.dirname(metaPath), { recursive: true });
19179
19650
  fs7.writeFileSync(metaPath, JSON.stringify({
19180
19651
  etag,
19181
19652
  timestamp,
@@ -19192,7 +19663,7 @@ var ProviderLoader = class _ProviderLoader {
19192
19663
  const scan = (d) => {
19193
19664
  try {
19194
19665
  for (const entry of fs7.readdirSync(d, { withFileTypes: true })) {
19195
- if (entry.isDirectory()) scan(path18.join(d, entry.name));
19666
+ if (entry.isDirectory()) scan(path19.join(d, entry.name));
19196
19667
  else if (entry.name === "provider.json") count++;
19197
19668
  }
19198
19669
  } catch {
@@ -19420,17 +19891,17 @@ var ProviderLoader = class _ProviderLoader {
19420
19891
  for (const root of searchRoots) {
19421
19892
  if (!fs7.existsSync(root)) continue;
19422
19893
  const candidate = this.getProviderDir(root, cat, type);
19423
- if (fs7.existsSync(path18.join(candidate, "provider.json"))) return candidate;
19424
- const catDir = path18.join(root, cat);
19894
+ if (fs7.existsSync(path19.join(candidate, "provider.json"))) return candidate;
19895
+ const catDir = path19.join(root, cat);
19425
19896
  if (fs7.existsSync(catDir)) {
19426
19897
  try {
19427
19898
  for (const entry of fs7.readdirSync(catDir, { withFileTypes: true })) {
19428
19899
  if (!entry.isDirectory()) continue;
19429
- const jsonPath = path18.join(catDir, entry.name, "provider.json");
19900
+ const jsonPath = path19.join(catDir, entry.name, "provider.json");
19430
19901
  if (fs7.existsSync(jsonPath)) {
19431
19902
  try {
19432
19903
  const data = JSON.parse(fs7.readFileSync(jsonPath, "utf-8"));
19433
- if (data.type === type) return path18.join(catDir, entry.name);
19904
+ if (data.type === type) return path19.join(catDir, entry.name);
19434
19905
  } catch {
19435
19906
  }
19436
19907
  }
@@ -19447,7 +19918,7 @@ var ProviderLoader = class _ProviderLoader {
19447
19918
  * (template substitution is NOT applied here — scripts.js handles that)
19448
19919
  */
19449
19920
  buildScriptWrappersFromDir(dir) {
19450
- const scriptsJs = path18.join(dir, "scripts.js");
19921
+ const scriptsJs = path19.join(dir, "scripts.js");
19451
19922
  if (fs7.existsSync(scriptsJs)) {
19452
19923
  try {
19453
19924
  delete __require.cache[__require.resolve(scriptsJs)];
@@ -19461,7 +19932,7 @@ var ProviderLoader = class _ProviderLoader {
19461
19932
  for (const file of fs7.readdirSync(dir)) {
19462
19933
  if (!file.endsWith(".js")) continue;
19463
19934
  const scriptName = toCamel(file.replace(".js", ""));
19464
- const filePath = path18.join(dir, file);
19935
+ const filePath = path19.join(dir, file);
19465
19936
  result[scriptName] = (...args) => {
19466
19937
  try {
19467
19938
  let content = fs7.readFileSync(filePath, "utf-8");
@@ -19521,7 +19992,7 @@ var ProviderLoader = class _ProviderLoader {
19521
19992
  }
19522
19993
  const hasJson = entries.some((e) => e.name === "provider.json");
19523
19994
  if (hasJson) {
19524
- const jsonPath = path18.join(d, "provider.json");
19995
+ const jsonPath = path19.join(d, "provider.json");
19525
19996
  try {
19526
19997
  const raw = fs7.readFileSync(jsonPath, "utf-8");
19527
19998
  const mod = JSON.parse(raw);
@@ -19542,7 +20013,7 @@ var ProviderLoader = class _ProviderLoader {
19542
20013
  this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
19543
20014
  } else {
19544
20015
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
19545
- const scriptsPath = path18.join(d, "scripts.js");
20016
+ const scriptsPath = path19.join(d, "scripts.js");
19546
20017
  if (!hasCompatibility && fs7.existsSync(scriptsPath)) {
19547
20018
  try {
19548
20019
  delete __require.cache[__require.resolve(scriptsPath)];
@@ -19568,7 +20039,7 @@ var ProviderLoader = class _ProviderLoader {
19568
20039
  if (!entry.isDirectory()) continue;
19569
20040
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
19570
20041
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
19571
- scan(path18.join(d, entry.name));
20042
+ scan(path19.join(d, entry.name));
19572
20043
  }
19573
20044
  }
19574
20045
  };
@@ -19893,8 +20364,8 @@ function detectCurrentWorkspace(ideId) {
19893
20364
  const appNameMap = getMacAppIdentifiers();
19894
20365
  const appName = appNameMap[ideId];
19895
20366
  if (appName) {
19896
- const storagePath = path19.join(
19897
- process.env.APPDATA || path19.join(os15.homedir(), "AppData", "Roaming"),
20367
+ const storagePath = path20.join(
20368
+ process.env.APPDATA || path20.join(os15.homedir(), "AppData", "Roaming"),
19898
20369
  appName,
19899
20370
  "storage.json"
19900
20371
  );
@@ -20083,9 +20554,9 @@ init_logger();
20083
20554
 
20084
20555
  // src/logging/command-log.ts
20085
20556
  import * as fs8 from "fs";
20086
- import * as path20 from "path";
20557
+ import * as path21 from "path";
20087
20558
  import * as os16 from "os";
20088
- var LOG_DIR2 = process.platform === "win32" ? path20.join(process.env.LOCALAPPDATA || process.env.APPDATA || path20.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path20.join(os16.homedir(), "Library", "Logs", "adhdev") : path20.join(os16.homedir(), ".local", "share", "adhdev", "logs");
20559
+ var LOG_DIR2 = process.platform === "win32" ? path21.join(process.env.LOCALAPPDATA || process.env.APPDATA || path21.join(os16.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path21.join(os16.homedir(), "Library", "Logs", "adhdev") : path21.join(os16.homedir(), ".local", "share", "adhdev", "logs");
20089
20560
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
20090
20561
  var MAX_DAYS = 7;
20091
20562
  try {
@@ -20123,13 +20594,13 @@ function getDateStr2() {
20123
20594
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
20124
20595
  }
20125
20596
  var currentDate2 = getDateStr2();
20126
- var currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20597
+ var currentFile = path21.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20127
20598
  var writeCount2 = 0;
20128
20599
  function checkRotation() {
20129
20600
  const today = getDateStr2();
20130
20601
  if (today !== currentDate2) {
20131
20602
  currentDate2 = today;
20132
- currentFile = path20.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20603
+ currentFile = path21.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
20133
20604
  cleanOldFiles();
20134
20605
  }
20135
20606
  }
@@ -20143,7 +20614,7 @@ function cleanOldFiles() {
20143
20614
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
20144
20615
  if (dateMatch && dateMatch[1] < cutoffStr) {
20145
20616
  try {
20146
- fs8.unlinkSync(path20.join(LOG_DIR2, file));
20617
+ fs8.unlinkSync(path21.join(LOG_DIR2, file));
20147
20618
  } catch {
20148
20619
  }
20149
20620
  }
@@ -20231,10 +20702,11 @@ import * as yaml from "js-yaml";
20231
20702
 
20232
20703
  // src/commands/mesh-coordinator.ts
20233
20704
  import { execFileSync as execFileSync2 } from "child_process";
20705
+ import { createHash as createHash2 } from "crypto";
20234
20706
  import { existsSync as existsSync15, readdirSync as readdirSync6, realpathSync as realpathSync2 } from "fs";
20235
20707
  import { createRequire as createRequire2 } from "module";
20236
20708
  import * as os17 from "os";
20237
- import { dirname as dirname4, isAbsolute as isAbsolute10, join as join18, resolve as resolve13 } from "path";
20709
+ import { dirname as dirname4, isAbsolute as isAbsolute11, join as join18, resolve as resolve13 } from "path";
20238
20710
  var DEFAULT_SERVER_NAME = "adhdev-mesh";
20239
20711
  var DEFAULT_ADHDEV_MCP_COMMAND = "adhdev-mcp";
20240
20712
  var HERMES_CLI_TYPE = "hermes-cli";
@@ -20255,7 +20727,7 @@ function resolveHermesMeshCoordinatorSetup(options) {
20255
20727
  reason: "Could not resolve the ADHDev MCP server entrypoint and a Node runtime with WebSocket support for daemon IPC mode"
20256
20728
  };
20257
20729
  }
20258
- const configPath = resolveMcpConfigPath(HERMES_MCP_CONFIG_PATH, options.workspace);
20730
+ const configPath = join18(resolveHermesCoordinatorHome(options.meshId, options.workspace), "config.yaml");
20259
20731
  if (!configPath.trim()) {
20260
20732
  return createHermesManualMeshCoordinatorSetup(options.meshId, options.workspace);
20261
20733
  }
@@ -20307,8 +20779,8 @@ function resolveMeshCoordinatorSetup(options) {
20307
20779
  }
20308
20780
  const serverName = mcpConfig.serverName?.trim() || DEFAULT_SERVER_NAME;
20309
20781
  if (mcpConfig.mode === "auto_import") {
20310
- const path27 = mcpConfig.path?.trim();
20311
- if (!path27) {
20782
+ const path28 = mcpConfig.path?.trim();
20783
+ if (!path28) {
20312
20784
  return { kind: "unsupported", reason: "Provider auto-import MCP config is missing a config path" };
20313
20785
  }
20314
20786
  const mcpServer = resolveAdhdevMcpServerLaunch({
@@ -20325,7 +20797,7 @@ function resolveMeshCoordinatorSetup(options) {
20325
20797
  return {
20326
20798
  kind: "auto_import",
20327
20799
  serverName,
20328
- configPath: resolveMcpConfigPath(path27, workspace),
20800
+ configPath: resolveMcpConfigPath(path28, workspace),
20329
20801
  configFormat: mcpConfig.format,
20330
20802
  mcpServer
20331
20803
  };
@@ -20359,11 +20831,17 @@ function resolveMeshCoordinatorSetup(options) {
20359
20831
  function renderMeshCoordinatorTemplate(template, values) {
20360
20832
  return template.replace(/\{\{\s*(meshId|workspace|serverName|adhdevMcpCommand)\s*\}\}/g, (_, key) => values[key] || "");
20361
20833
  }
20834
+ function resolveHermesCoordinatorHome(meshId, workspace) {
20835
+ const key = `${meshId || "mesh"}
20836
+ ${resolve13(workspace || os17.tmpdir())}`;
20837
+ const hash = createHash2("sha256").update(key).digest("hex").slice(0, 16);
20838
+ return join18(os17.tmpdir(), `adhdev-hermes-mesh-coordinator-${hash}`);
20839
+ }
20362
20840
  function resolveMcpConfigPath(configPath, workspace) {
20363
20841
  const trimmed = configPath.trim();
20364
20842
  if (trimmed === "~") return os17.homedir();
20365
20843
  if (trimmed.startsWith("~/")) return join18(os17.homedir(), trimmed.slice(2));
20366
- if (isAbsolute10(trimmed)) return trimmed;
20844
+ if (isAbsolute11(trimmed)) return trimmed;
20367
20845
  return join18(workspace, trimmed);
20368
20846
  }
20369
20847
  function resolveAdhdevMcpServerLaunch(options) {
@@ -20892,13 +21370,13 @@ import { execFileSync as execFileSync3 } from "child_process";
20892
21370
  import { spawn as spawn3 } from "child_process";
20893
21371
  import * as fs9 from "fs";
20894
21372
  import * as os19 from "os";
20895
- import * as path21 from "path";
21373
+ import * as path22 from "path";
20896
21374
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
20897
21375
  function getUpgradeLogPath() {
20898
21376
  const home = os19.homedir();
20899
- const dir = path21.join(home, ".adhdev");
21377
+ const dir = path22.join(home, ".adhdev");
20900
21378
  fs9.mkdirSync(dir, { recursive: true });
20901
- return path21.join(dir, "daemon-upgrade.log");
21379
+ return path22.join(dir, "daemon-upgrade.log");
20902
21380
  }
20903
21381
  function appendUpgradeLog(message) {
20904
21382
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -20909,14 +21387,14 @@ function appendUpgradeLog(message) {
20909
21387
  }
20910
21388
  }
20911
21389
  function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platform) {
20912
- const binDir = path21.dirname(nodeExecutable);
21390
+ const binDir = path22.dirname(nodeExecutable);
20913
21391
  if (platform10 === "win32") {
20914
- const npmCliPath = path21.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
21392
+ const npmCliPath = path22.join(binDir, "node_modules", "npm", "bin", "npm-cli.js");
20915
21393
  if (fs9.existsSync(npmCliPath)) {
20916
21394
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20917
21395
  }
20918
21396
  for (const candidate of ["npm.exe", "npm"]) {
20919
- const candidatePath = path21.join(binDir, candidate);
21397
+ const candidatePath = path22.join(binDir, candidate);
20920
21398
  if (fs9.existsSync(candidatePath)) {
20921
21399
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20922
21400
  }
@@ -20924,7 +21402,7 @@ function resolveSiblingNpmInvocation(nodeExecutable, platform10 = process.platfo
20924
21402
  return { executable: nodeExecutable, argsPrefix: [npmCliPath], execOptions: getNpmExecOptions(platform10) };
20925
21403
  }
20926
21404
  for (const candidate of ["npm"]) {
20927
- const candidatePath = path21.join(binDir, candidate);
21405
+ const candidatePath = path22.join(binDir, candidate);
20928
21406
  if (fs9.existsSync(candidatePath)) {
20929
21407
  return { executable: candidatePath, argsPrefix: [], execOptions: getNpmExecOptions(platform10) };
20930
21408
  }
@@ -20941,13 +21419,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20941
21419
  let currentDir = resolvedPath;
20942
21420
  try {
20943
21421
  if (fs9.statSync(resolvedPath).isFile()) {
20944
- currentDir = path21.dirname(resolvedPath);
21422
+ currentDir = path22.dirname(resolvedPath);
20945
21423
  }
20946
21424
  } catch {
20947
- currentDir = path21.dirname(resolvedPath);
21425
+ currentDir = path22.dirname(resolvedPath);
20948
21426
  }
20949
21427
  while (true) {
20950
- const packageJsonPath = path21.join(currentDir, "package.json");
21428
+ const packageJsonPath = path22.join(currentDir, "package.json");
20951
21429
  try {
20952
21430
  if (fs9.existsSync(packageJsonPath)) {
20953
21431
  const parsed = JSON.parse(fs9.readFileSync(packageJsonPath, "utf8"));
@@ -20958,7 +21436,7 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20958
21436
  }
20959
21437
  } catch {
20960
21438
  }
20961
- const parentDir = path21.dirname(currentDir);
21439
+ const parentDir = path22.dirname(currentDir);
20962
21440
  if (parentDir === currentDir) {
20963
21441
  return null;
20964
21442
  }
@@ -20966,13 +21444,13 @@ function findCurrentPackageRoot(currentCliPath, packageName) {
20966
21444
  }
20967
21445
  }
20968
21446
  function resolveInstallPrefixFromPackageRoot(packageRoot, packageName) {
20969
- const nodeModulesDir = packageName.startsWith("@") ? path21.dirname(path21.dirname(packageRoot)) : path21.dirname(packageRoot);
20970
- if (path21.basename(nodeModulesDir) !== "node_modules") {
21447
+ const nodeModulesDir = packageName.startsWith("@") ? path22.dirname(path22.dirname(packageRoot)) : path22.dirname(packageRoot);
21448
+ if (path22.basename(nodeModulesDir) !== "node_modules") {
20971
21449
  return null;
20972
21450
  }
20973
- const maybeLibDir = path21.dirname(nodeModulesDir);
20974
- if (path21.basename(maybeLibDir) === "lib") {
20975
- return path21.dirname(maybeLibDir);
21451
+ const maybeLibDir = path22.dirname(nodeModulesDir);
21452
+ if (path22.basename(maybeLibDir) === "lib") {
21453
+ return path22.dirname(maybeLibDir);
20976
21454
  }
20977
21455
  return maybeLibDir;
20978
21456
  }
@@ -21087,7 +21565,7 @@ async function waitForPidExit(pid, timeoutMs) {
21087
21565
  }
21088
21566
  }
21089
21567
  function stopSessionHostProcesses(appName) {
21090
- const pidFile = path21.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
21568
+ const pidFile = path22.join(os19.homedir(), ".adhdev", `${appName}-session-host.pid`);
21091
21569
  try {
21092
21570
  if (fs9.existsSync(pidFile)) {
21093
21571
  const pid = Number.parseInt(fs9.readFileSync(pidFile, "utf8").trim(), 10);
@@ -21104,7 +21582,7 @@ function stopSessionHostProcesses(appName) {
21104
21582
  }
21105
21583
  }
21106
21584
  function removeDaemonPidFile() {
21107
- const pidFile = path21.join(os19.homedir(), ".adhdev", "daemon.pid");
21585
+ const pidFile = path22.join(os19.homedir(), ".adhdev", "daemon.pid");
21108
21586
  try {
21109
21587
  fs9.unlinkSync(pidFile);
21110
21588
  } catch {
@@ -21115,7 +21593,7 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
21115
21593
  const npmRoot = String(execNpmCommandSync(["root", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
21116
21594
  if (!npmRoot) return;
21117
21595
  const npmPrefix = surface.installPrefix || String(execNpmCommandSync(["prefix", "-g", ...prefixArgs], { encoding: "utf8" }, surface)).trim();
21118
- const binDir = process.platform === "win32" ? npmPrefix : path21.join(npmPrefix, "bin");
21596
+ const binDir = process.platform === "win32" ? npmPrefix : path22.join(npmPrefix, "bin");
21119
21597
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
21120
21598
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
21121
21599
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -21123,25 +21601,25 @@ function cleanupStaleGlobalInstallDirs(pkgName, surface) {
21123
21601
  }
21124
21602
  if (pkgName.startsWith("@")) {
21125
21603
  const [scope, name] = pkgName.split("/");
21126
- const scopeDir = path21.join(npmRoot, scope);
21604
+ const scopeDir = path22.join(npmRoot, scope);
21127
21605
  if (!fs9.existsSync(scopeDir)) return;
21128
21606
  for (const entry of fs9.readdirSync(scopeDir)) {
21129
21607
  if (!entry.startsWith(`.${name}-`)) continue;
21130
- fs9.rmSync(path21.join(scopeDir, entry), { recursive: true, force: true });
21131
- appendUpgradeLog(`Removed stale scoped staging dir: ${path21.join(scopeDir, entry)}`);
21608
+ fs9.rmSync(path22.join(scopeDir, entry), { recursive: true, force: true });
21609
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path22.join(scopeDir, entry)}`);
21132
21610
  }
21133
21611
  } else {
21134
21612
  for (const entry of fs9.readdirSync(npmRoot)) {
21135
21613
  if (!entry.startsWith(`.${pkgName}-`)) continue;
21136
- fs9.rmSync(path21.join(npmRoot, entry), { recursive: true, force: true });
21137
- appendUpgradeLog(`Removed stale staging dir: ${path21.join(npmRoot, entry)}`);
21614
+ fs9.rmSync(path22.join(npmRoot, entry), { recursive: true, force: true });
21615
+ appendUpgradeLog(`Removed stale staging dir: ${path22.join(npmRoot, entry)}`);
21138
21616
  }
21139
21617
  }
21140
21618
  if (fs9.existsSync(binDir)) {
21141
21619
  for (const entry of fs9.readdirSync(binDir)) {
21142
21620
  if (!Array.from(binNames).some((name) => entry.startsWith(`.${name}-`))) continue;
21143
- fs9.rmSync(path21.join(binDir, entry), { recursive: true, force: true });
21144
- appendUpgradeLog(`Removed stale bin staging entry: ${path21.join(binDir, entry)}`);
21621
+ fs9.rmSync(path22.join(binDir, entry), { recursive: true, force: true });
21622
+ appendUpgradeLog(`Removed stale bin staging entry: ${path22.join(binDir, entry)}`);
21145
21623
  }
21146
21624
  }
21147
21625
  }
@@ -22513,7 +22991,7 @@ var DaemonCommandRouter = class {
22513
22991
  workspace
22514
22992
  };
22515
22993
  }
22516
- const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync13, copyFileSync: copyFileSync3, mkdirSync: mkdirSync15 } = await import("fs");
22994
+ const { existsSync: existsSync23, readFileSync: readFileSync15, writeFileSync: writeFileSync14, copyFileSync: copyFileSync3, mkdirSync: mkdirSync16 } = await import("fs");
22517
22995
  const { dirname: dirname9 } = await import("path");
22518
22996
  const mcpConfigPath = coordinatorSetup.configPath;
22519
22997
  const hermesManualFallback = cliType === "hermes-cli" && configFormat === "hermes_config_yaml" ? createHermesManualMeshCoordinatorSetup(meshId, workspace) : null;
@@ -22537,7 +23015,7 @@ var DaemonCommandRouter = class {
22537
23015
  };
22538
23016
  }
22539
23017
  try {
22540
- mkdirSync15(dirname9(mcpConfigPath), { recursive: true });
23018
+ mkdirSync16(dirname9(mcpConfigPath), { recursive: true });
22541
23019
  } catch (error) {
22542
23020
  const message = `Could not prepare MCP config path for automatic setup: ${error?.message || error}`;
22543
23021
  LOG.error("MeshCoordinator", message);
@@ -22569,7 +23047,7 @@ var DaemonCommandRouter = class {
22569
23047
  }
22570
23048
  };
22571
23049
  try {
22572
- writeFileSync13(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
23050
+ writeFileSync14(mcpConfigPath, serializeMeshCoordinatorMcpConfig(mcpConfig, configFormat), "utf-8");
22573
23051
  } catch (error) {
22574
23052
  const message = `Could not write MCP config for automatic setup: ${error?.message || error}`;
22575
23053
  LOG.error("MeshCoordinator", message);
@@ -22579,6 +23057,10 @@ var DaemonCommandRouter = class {
22579
23057
  LOG.info("MeshCoordinator", `Wrote ${mcpConfigPath} with ${coordinatorSetup.serverName} server`);
22580
23058
  const cliArgs = [];
22581
23059
  const launchEnv = {};
23060
+ if (configFormat === "hermes_config_yaml") {
23061
+ launchEnv.HERMES_HOME = dirname9(mcpConfigPath);
23062
+ launchEnv.HERMES_IGNORE_USER_CONFIG = "";
23063
+ }
22582
23064
  if (systemPrompt) {
22583
23065
  if (configFormat === "hermes_config_yaml") {
22584
23066
  launchEnv.HERMES_EPHEMERAL_SYSTEM_PROMPT = systemPrompt;
@@ -23000,7 +23482,8 @@ function prepareSessionChatTailUpdate(input) {
23000
23482
  update: null
23001
23483
  };
23002
23484
  }
23003
- const messages = Array.isArray(result.messages) ? result.messages : [];
23485
+ const fullMessages = normalizeChatMessages(Array.isArray(result.messages) ? result.messages : []);
23486
+ const messages = filterUserFacingChatMessages(fullMessages);
23004
23487
  const title = typeof result.title === "string" ? result.title : void 0;
23005
23488
  const activeModal = normalizeChatTailActiveModal(result.activeModal);
23006
23489
  const status = typeof result.status === "string" ? result.status : "idle";
@@ -24274,11 +24757,11 @@ var ProviderInstanceManager = class {
24274
24757
 
24275
24758
  // src/providers/version-archive.ts
24276
24759
  import * as fs11 from "fs";
24277
- import * as path22 from "path";
24760
+ import * as path23 from "path";
24278
24761
  import * as os20 from "os";
24279
24762
  import { execSync as execSync5 } from "child_process";
24280
24763
  import { platform as platform8 } from "os";
24281
- var ARCHIVE_PATH = path22.join(os20.homedir(), ".adhdev", "version-history.json");
24764
+ var ARCHIVE_PATH = path23.join(os20.homedir(), ".adhdev", "version-history.json");
24282
24765
  var MAX_ENTRIES_PER_PROVIDER = 20;
24283
24766
  var VersionArchive = class {
24284
24767
  history = {};
@@ -24325,7 +24808,7 @@ var VersionArchive = class {
24325
24808
  }
24326
24809
  save() {
24327
24810
  try {
24328
- fs11.mkdirSync(path22.dirname(ARCHIVE_PATH), { recursive: true });
24811
+ fs11.mkdirSync(path23.dirname(ARCHIVE_PATH), { recursive: true });
24329
24812
  fs11.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
24330
24813
  } catch {
24331
24814
  }
@@ -24382,7 +24865,7 @@ function checkPathExists2(paths) {
24382
24865
  for (const p of paths) {
24383
24866
  if (p.includes("*")) {
24384
24867
  const home = os20.homedir();
24385
- const resolved = p.replace(/\*/g, home.split(path22.sep).pop() || "");
24868
+ const resolved = p.replace(/\*/g, home.split(path23.sep).pop() || "");
24386
24869
  if (fs11.existsSync(resolved)) return resolved;
24387
24870
  } else {
24388
24871
  if (fs11.existsSync(p)) return p;
@@ -24392,7 +24875,7 @@ function checkPathExists2(paths) {
24392
24875
  }
24393
24876
  function getMacAppVersion(appPath) {
24394
24877
  if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
24395
- const plistPath = path22.join(appPath, "Contents", "Info.plist");
24878
+ const plistPath = path23.join(appPath, "Contents", "Info.plist");
24396
24879
  if (!fs11.existsSync(plistPath)) return null;
24397
24880
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
24398
24881
  return raw || null;
@@ -24418,7 +24901,7 @@ async function detectAllVersions(loader, archive) {
24418
24901
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
24419
24902
  let resolvedBin = cliBin;
24420
24903
  if (!resolvedBin && appPath && currentOs === "darwin") {
24421
- const bundled = path22.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
24904
+ const bundled = path23.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
24422
24905
  if (provider.cli && fs11.existsSync(bundled)) resolvedBin = bundled;
24423
24906
  }
24424
24907
  info.installed = !!(appPath || resolvedBin);
@@ -24459,7 +24942,7 @@ async function detectAllVersions(loader, archive) {
24459
24942
  // src/daemon/dev-server.ts
24460
24943
  import * as http2 from "http";
24461
24944
  import * as fs15 from "fs";
24462
- import * as path26 from "path";
24945
+ import * as path27 from "path";
24463
24946
  init_config();
24464
24947
 
24465
24948
  // src/daemon/scaffold-template.ts
@@ -24811,7 +25294,7 @@ init_logger();
24811
25294
  // src/daemon/dev-cdp-handlers.ts
24812
25295
  init_logger();
24813
25296
  import * as fs12 from "fs";
24814
- import * as path23 from "path";
25297
+ import * as path24 from "path";
24815
25298
  async function handleCdpEvaluate(ctx, req, res) {
24816
25299
  const body = await ctx.readBody(req);
24817
25300
  const { expression, timeout, ideType } = body;
@@ -24989,17 +25472,17 @@ async function handleScriptHints(ctx, type, _req, res) {
24989
25472
  return;
24990
25473
  }
24991
25474
  let scriptsPath = "";
24992
- const directScripts = path23.join(dir, "scripts.js");
25475
+ const directScripts = path24.join(dir, "scripts.js");
24993
25476
  if (fs12.existsSync(directScripts)) {
24994
25477
  scriptsPath = directScripts;
24995
25478
  } else {
24996
- const scriptsDir = path23.join(dir, "scripts");
25479
+ const scriptsDir = path24.join(dir, "scripts");
24997
25480
  if (fs12.existsSync(scriptsDir)) {
24998
25481
  const versions = fs12.readdirSync(scriptsDir).filter((d) => {
24999
- return fs12.statSync(path23.join(scriptsDir, d)).isDirectory();
25482
+ return fs12.statSync(path24.join(scriptsDir, d)).isDirectory();
25000
25483
  }).sort().reverse();
25001
25484
  for (const ver of versions) {
25002
- const p = path23.join(scriptsDir, ver, "scripts.js");
25485
+ const p = path24.join(scriptsDir, ver, "scripts.js");
25003
25486
  if (fs12.existsSync(p)) {
25004
25487
  scriptsPath = p;
25005
25488
  break;
@@ -25828,7 +26311,7 @@ async function handleDomContext(ctx, type, req, res) {
25828
26311
 
25829
26312
  // src/daemon/dev-cli-debug.ts
25830
26313
  import * as fs13 from "fs";
25831
- import * as path24 from "path";
26314
+ import * as path25 from "path";
25832
26315
  function slugifyFixtureName(value) {
25833
26316
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
25834
26317
  return normalized || `fixture-${Date.now()}`;
@@ -25838,11 +26321,11 @@ function getCliFixtureDir(ctx, type) {
25838
26321
  if (!providerDir) {
25839
26322
  throw new Error(`Provider directory not found for '${type}'`);
25840
26323
  }
25841
- return path24.join(providerDir, "fixtures");
26324
+ return path25.join(providerDir, "fixtures");
25842
26325
  }
25843
26326
  function readCliFixture(ctx, type, name) {
25844
26327
  const fixtureDir = getCliFixtureDir(ctx, type);
25845
- const filePath = path24.join(fixtureDir, `${name}.json`);
26328
+ const filePath = path25.join(fixtureDir, `${name}.json`);
25846
26329
  if (!fs13.existsSync(filePath)) {
25847
26330
  throw new Error(`Fixture not found: ${filePath}`);
25848
26331
  }
@@ -26609,7 +27092,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
26609
27092
  },
26610
27093
  notes: typeof body?.notes === "string" ? body.notes : void 0
26611
27094
  };
26612
- const filePath = path24.join(fixtureDir, `${name}.json`);
27095
+ const filePath = path25.join(fixtureDir, `${name}.json`);
26613
27096
  fs13.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
26614
27097
  ctx.json(res, 200, {
26615
27098
  saved: true,
@@ -26633,7 +27116,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
26633
27116
  return;
26634
27117
  }
26635
27118
  const fixtures = fs13.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
26636
- const fullPath = path24.join(fixtureDir, file);
27119
+ const fullPath = path25.join(fixtureDir, file);
26637
27120
  try {
26638
27121
  const raw = JSON.parse(fs13.readFileSync(fullPath, "utf-8"));
26639
27122
  return {
@@ -26769,7 +27252,7 @@ async function handleCliRaw(ctx, req, res) {
26769
27252
 
26770
27253
  // src/daemon/dev-auto-implement.ts
26771
27254
  import * as fs14 from "fs";
26772
- import * as path25 from "path";
27255
+ import * as path26 from "path";
26773
27256
  import * as os21 from "os";
26774
27257
  function getAutoImplPid(ctx) {
26775
27258
  const pid = ctx.autoImplProcess?.pid;
@@ -26819,22 +27302,22 @@ function getLatestScriptVersionDir(scriptsDir) {
26819
27302
  if (!fs14.existsSync(scriptsDir)) return null;
26820
27303
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
26821
27304
  try {
26822
- return fs14.statSync(path25.join(scriptsDir, d)).isDirectory();
27305
+ return fs14.statSync(path26.join(scriptsDir, d)).isDirectory();
26823
27306
  } catch {
26824
27307
  return false;
26825
27308
  }
26826
27309
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
26827
27310
  if (versions.length === 0) return null;
26828
- return path25.join(scriptsDir, versions[0]);
27311
+ return path26.join(scriptsDir, versions[0]);
26829
27312
  }
26830
27313
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
26831
- const canonicalUserDir = path25.resolve(ctx.providerLoader.getUserProviderDir(category, type));
26832
- const desiredDir = requestedDir ? path25.resolve(requestedDir) : canonicalUserDir;
26833
- const upstreamRoot = path25.resolve(ctx.providerLoader.getUpstreamDir());
26834
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path25.sep}`)) {
27314
+ const canonicalUserDir = path26.resolve(ctx.providerLoader.getUserProviderDir(category, type));
27315
+ const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
27316
+ const upstreamRoot = path26.resolve(ctx.providerLoader.getUpstreamDir());
27317
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
26835
27318
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
26836
27319
  }
26837
- if (path25.basename(desiredDir) !== type) {
27320
+ if (path26.basename(desiredDir) !== type) {
26838
27321
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
26839
27322
  }
26840
27323
  const sourceDir = ctx.findProviderDir(type);
@@ -26842,11 +27325,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
26842
27325
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
26843
27326
  }
26844
27327
  if (!fs14.existsSync(desiredDir)) {
26845
- fs14.mkdirSync(path25.dirname(desiredDir), { recursive: true });
27328
+ fs14.mkdirSync(path26.dirname(desiredDir), { recursive: true });
26846
27329
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
26847
27330
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
26848
27331
  }
26849
- const providerJson = path25.join(desiredDir, "provider.json");
27332
+ const providerJson = path26.join(desiredDir, "provider.json");
26850
27333
  if (!fs14.existsSync(providerJson)) {
26851
27334
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
26852
27335
  }
@@ -26857,13 +27340,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
26857
27340
  const refDir = ctx.findProviderDir(referenceType);
26858
27341
  if (!refDir || !fs14.existsSync(refDir)) return {};
26859
27342
  const referenceScripts = {};
26860
- const scriptsDir = path25.join(refDir, "scripts");
27343
+ const scriptsDir = path26.join(refDir, "scripts");
26861
27344
  const latestDir = getLatestScriptVersionDir(scriptsDir);
26862
27345
  if (!latestDir) return referenceScripts;
26863
27346
  for (const file of fs14.readdirSync(latestDir)) {
26864
27347
  if (!file.endsWith(".js")) continue;
26865
27348
  try {
26866
- referenceScripts[file] = fs14.readFileSync(path25.join(latestDir, file), "utf-8");
27349
+ referenceScripts[file] = fs14.readFileSync(path26.join(latestDir, file), "utf-8");
26867
27350
  } catch {
26868
27351
  }
26869
27352
  }
@@ -26971,9 +27454,9 @@ async function handleAutoImplement(ctx, type, req, res) {
26971
27454
  });
26972
27455
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
26973
27456
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
26974
- const tmpDir = path25.join(os21.tmpdir(), "adhdev-autoimpl");
27457
+ const tmpDir = path26.join(os21.tmpdir(), "adhdev-autoimpl");
26975
27458
  if (!fs14.existsSync(tmpDir)) fs14.mkdirSync(tmpDir, { recursive: true });
26976
- const promptFile = path25.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
27459
+ const promptFile = path26.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
26977
27460
  fs14.writeFileSync(promptFile, prompt, "utf-8");
26978
27461
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
26979
27462
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -27405,7 +27888,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
27405
27888
  setMode: "set_mode.js"
27406
27889
  };
27407
27890
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
27408
- const scriptsDir = path25.join(providerDir, "scripts");
27891
+ const scriptsDir = path26.join(providerDir, "scripts");
27409
27892
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
27410
27893
  if (latestScriptsDir) {
27411
27894
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -27416,7 +27899,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
27416
27899
  for (const file of fs14.readdirSync(latestScriptsDir)) {
27417
27900
  if (file.endsWith(".js") && targetFileNames.has(file)) {
27418
27901
  try {
27419
- const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
27902
+ const content = fs14.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27420
27903
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
27421
27904
  lines.push("```javascript");
27422
27905
  lines.push(content);
@@ -27433,7 +27916,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
27433
27916
  lines.push("");
27434
27917
  for (const file of refFiles) {
27435
27918
  try {
27436
- const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
27919
+ const content = fs14.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27437
27920
  lines.push(`### \`${file}\` \u{1F512}`);
27438
27921
  lines.push("```javascript");
27439
27922
  lines.push(content);
@@ -27474,10 +27957,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
27474
27957
  lines.push("");
27475
27958
  }
27476
27959
  }
27477
- const docsDir = path25.join(providerDir, "../../docs");
27960
+ const docsDir = path26.join(providerDir, "../../docs");
27478
27961
  const loadGuide = (name) => {
27479
27962
  try {
27480
- const p = path25.join(docsDir, name);
27963
+ const p = path26.join(docsDir, name);
27481
27964
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
27482
27965
  } catch {
27483
27966
  }
@@ -27714,7 +28197,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
27714
28197
  parseApproval: "parse_approval.js"
27715
28198
  };
27716
28199
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
27717
- const scriptsDir = path25.join(providerDir, "scripts");
28200
+ const scriptsDir = path26.join(providerDir, "scripts");
27718
28201
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
27719
28202
  if (latestScriptsDir) {
27720
28203
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -27726,7 +28209,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
27726
28209
  if (!file.endsWith(".js")) continue;
27727
28210
  if (!targetFileNames.has(file)) continue;
27728
28211
  try {
27729
- const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28212
+ const content = fs14.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27730
28213
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
27731
28214
  lines.push("```javascript");
27732
28215
  lines.push(content);
@@ -27742,7 +28225,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
27742
28225
  lines.push("");
27743
28226
  for (const file of refFiles) {
27744
28227
  try {
27745
- const content = fs14.readFileSync(path25.join(latestScriptsDir, file), "utf-8");
28228
+ const content = fs14.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
27746
28229
  lines.push(`### \`${file}\` \u{1F512}`);
27747
28230
  lines.push("```javascript");
27748
28231
  lines.push(content);
@@ -27775,10 +28258,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
27775
28258
  lines.push("");
27776
28259
  }
27777
28260
  }
27778
- const docsDir = path25.join(providerDir, "../../docs");
28261
+ const docsDir = path26.join(providerDir, "../../docs");
27779
28262
  const loadGuide = (name) => {
27780
28263
  try {
27781
- const p = path25.join(docsDir, name);
28264
+ const p = path26.join(docsDir, name);
27782
28265
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
27783
28266
  } catch {
27784
28267
  }
@@ -28225,8 +28708,8 @@ var DevServer = class _DevServer {
28225
28708
  }
28226
28709
  getEndpointList() {
28227
28710
  return this.routes.map((r) => {
28228
- const path27 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
28229
- return `${r.method.padEnd(5)} ${path27}`;
28711
+ const path28 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
28712
+ return `${r.method.padEnd(5)} ${path28}`;
28230
28713
  });
28231
28714
  }
28232
28715
  async start(port = DEV_SERVER_PORT) {
@@ -28514,12 +28997,12 @@ var DevServer = class _DevServer {
28514
28997
  // ─── DevConsole SPA ───
28515
28998
  getConsoleDistDir() {
28516
28999
  const candidates = [
28517
- path26.resolve(__dirname, "../../web-devconsole/dist"),
28518
- path26.resolve(__dirname, "../../../web-devconsole/dist"),
28519
- path26.join(process.cwd(), "packages/web-devconsole/dist")
29000
+ path27.resolve(__dirname, "../../web-devconsole/dist"),
29001
+ path27.resolve(__dirname, "../../../web-devconsole/dist"),
29002
+ path27.join(process.cwd(), "packages/web-devconsole/dist")
28520
29003
  ];
28521
29004
  for (const dir of candidates) {
28522
- if (fs15.existsSync(path26.join(dir, "index.html"))) return dir;
29005
+ if (fs15.existsSync(path27.join(dir, "index.html"))) return dir;
28523
29006
  }
28524
29007
  return null;
28525
29008
  }
@@ -28529,7 +29012,7 @@ var DevServer = class _DevServer {
28529
29012
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
28530
29013
  return;
28531
29014
  }
28532
- const htmlPath = path26.join(distDir, "index.html");
29015
+ const htmlPath = path27.join(distDir, "index.html");
28533
29016
  try {
28534
29017
  const html = fs15.readFileSync(htmlPath, "utf-8");
28535
29018
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -28554,15 +29037,15 @@ var DevServer = class _DevServer {
28554
29037
  this.json(res, 404, { error: "Not found" });
28555
29038
  return;
28556
29039
  }
28557
- const safePath = path26.normalize(pathname).replace(/^\.\.\//, "");
28558
- const filePath = path26.join(distDir, safePath);
29040
+ const safePath = path27.normalize(pathname).replace(/^\.\.\//, "");
29041
+ const filePath = path27.join(distDir, safePath);
28559
29042
  if (!filePath.startsWith(distDir)) {
28560
29043
  this.json(res, 403, { error: "Forbidden" });
28561
29044
  return;
28562
29045
  }
28563
29046
  try {
28564
29047
  const content = fs15.readFileSync(filePath);
28565
- const ext = path26.extname(filePath);
29048
+ const ext = path27.extname(filePath);
28566
29049
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
28567
29050
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
28568
29051
  res.end(content);
@@ -28675,9 +29158,9 @@ var DevServer = class _DevServer {
28675
29158
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
28676
29159
  if (entry.isDirectory()) {
28677
29160
  files.push({ path: rel, size: 0, type: "dir" });
28678
- scan(path26.join(d, entry.name), rel);
29161
+ scan(path27.join(d, entry.name), rel);
28679
29162
  } else {
28680
- const stat2 = fs15.statSync(path26.join(d, entry.name));
29163
+ const stat2 = fs15.statSync(path27.join(d, entry.name));
28681
29164
  files.push({ path: rel, size: stat2.size, type: "file" });
28682
29165
  }
28683
29166
  }
@@ -28700,7 +29183,7 @@ var DevServer = class _DevServer {
28700
29183
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
28701
29184
  return;
28702
29185
  }
28703
- const fullPath = path26.resolve(dir, path26.normalize(filePath));
29186
+ const fullPath = path27.resolve(dir, path27.normalize(filePath));
28704
29187
  if (!fullPath.startsWith(dir)) {
28705
29188
  this.json(res, 403, { error: "Forbidden" });
28706
29189
  return;
@@ -28725,14 +29208,14 @@ var DevServer = class _DevServer {
28725
29208
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
28726
29209
  return;
28727
29210
  }
28728
- const fullPath = path26.resolve(dir, path26.normalize(filePath));
29211
+ const fullPath = path27.resolve(dir, path27.normalize(filePath));
28729
29212
  if (!fullPath.startsWith(dir)) {
28730
29213
  this.json(res, 403, { error: "Forbidden" });
28731
29214
  return;
28732
29215
  }
28733
29216
  try {
28734
29217
  if (fs15.existsSync(fullPath)) fs15.copyFileSync(fullPath, fullPath + ".bak");
28735
- fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
29218
+ fs15.mkdirSync(path27.dirname(fullPath), { recursive: true });
28736
29219
  fs15.writeFileSync(fullPath, content, "utf-8");
28737
29220
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
28738
29221
  this.providerLoader.reload();
@@ -28749,7 +29232,7 @@ var DevServer = class _DevServer {
28749
29232
  return;
28750
29233
  }
28751
29234
  for (const name of ["scripts.js", "provider.json"]) {
28752
- const p = path26.join(dir, name);
29235
+ const p = path27.join(dir, name);
28753
29236
  if (fs15.existsSync(p)) {
28754
29237
  const source = fs15.readFileSync(p, "utf-8");
28755
29238
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -28770,8 +29253,8 @@ var DevServer = class _DevServer {
28770
29253
  this.json(res, 404, { error: `Provider not found: ${type}` });
28771
29254
  return;
28772
29255
  }
28773
- const target = fs15.existsSync(path26.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
28774
- const targetPath = path26.join(dir, target);
29256
+ const target = fs15.existsSync(path27.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
29257
+ const targetPath = path27.join(dir, target);
28775
29258
  try {
28776
29259
  if (fs15.existsSync(targetPath)) fs15.copyFileSync(targetPath, targetPath + ".bak");
28777
29260
  fs15.writeFileSync(targetPath, source, "utf-8");
@@ -28918,7 +29401,7 @@ var DevServer = class _DevServer {
28918
29401
  }
28919
29402
  let targetDir;
28920
29403
  targetDir = this.providerLoader.getUserProviderDir(category, type);
28921
- const jsonPath = path26.join(targetDir, "provider.json");
29404
+ const jsonPath = path27.join(targetDir, "provider.json");
28922
29405
  if (fs15.existsSync(jsonPath)) {
28923
29406
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
28924
29407
  return;
@@ -28930,8 +29413,8 @@ var DevServer = class _DevServer {
28930
29413
  const createdFiles = ["provider.json"];
28931
29414
  if (result.files) {
28932
29415
  for (const [relPath, content] of Object.entries(result.files)) {
28933
- const fullPath = path26.join(targetDir, relPath);
28934
- fs15.mkdirSync(path26.dirname(fullPath), { recursive: true });
29416
+ const fullPath = path27.join(targetDir, relPath);
29417
+ fs15.mkdirSync(path27.dirname(fullPath), { recursive: true });
28935
29418
  fs15.writeFileSync(fullPath, content, "utf-8");
28936
29419
  createdFiles.push(relPath);
28937
29420
  }
@@ -28984,22 +29467,22 @@ var DevServer = class _DevServer {
28984
29467
  if (!fs15.existsSync(scriptsDir)) return null;
28985
29468
  const versions = fs15.readdirSync(scriptsDir).filter((d) => {
28986
29469
  try {
28987
- return fs15.statSync(path26.join(scriptsDir, d)).isDirectory();
29470
+ return fs15.statSync(path27.join(scriptsDir, d)).isDirectory();
28988
29471
  } catch {
28989
29472
  return false;
28990
29473
  }
28991
29474
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
28992
29475
  if (versions.length === 0) return null;
28993
- return path26.join(scriptsDir, versions[0]);
29476
+ return path27.join(scriptsDir, versions[0]);
28994
29477
  }
28995
29478
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
28996
- const canonicalUserDir = path26.resolve(this.providerLoader.getUserProviderDir(category, type));
28997
- const desiredDir = requestedDir ? path26.resolve(requestedDir) : canonicalUserDir;
28998
- const upstreamRoot = path26.resolve(this.providerLoader.getUpstreamDir());
28999
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path26.sep}`)) {
29479
+ const canonicalUserDir = path27.resolve(this.providerLoader.getUserProviderDir(category, type));
29480
+ const desiredDir = requestedDir ? path27.resolve(requestedDir) : canonicalUserDir;
29481
+ const upstreamRoot = path27.resolve(this.providerLoader.getUpstreamDir());
29482
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path27.sep}`)) {
29000
29483
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
29001
29484
  }
29002
- if (path26.basename(desiredDir) !== type) {
29485
+ if (path27.basename(desiredDir) !== type) {
29003
29486
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
29004
29487
  }
29005
29488
  const sourceDir = this.findProviderDir(type);
@@ -29007,11 +29490,11 @@ var DevServer = class _DevServer {
29007
29490
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
29008
29491
  }
29009
29492
  if (!fs15.existsSync(desiredDir)) {
29010
- fs15.mkdirSync(path26.dirname(desiredDir), { recursive: true });
29493
+ fs15.mkdirSync(path27.dirname(desiredDir), { recursive: true });
29011
29494
  fs15.cpSync(sourceDir, desiredDir, { recursive: true });
29012
29495
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
29013
29496
  }
29014
- const providerJson = path26.join(desiredDir, "provider.json");
29497
+ const providerJson = path27.join(desiredDir, "provider.json");
29015
29498
  if (!fs15.existsSync(providerJson)) {
29016
29499
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
29017
29500
  }
@@ -29047,7 +29530,7 @@ var DevServer = class _DevServer {
29047
29530
  setMode: "set_mode.js"
29048
29531
  };
29049
29532
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
29050
- const scriptsDir = path26.join(providerDir, "scripts");
29533
+ const scriptsDir = path27.join(providerDir, "scripts");
29051
29534
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
29052
29535
  if (latestScriptsDir) {
29053
29536
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -29058,7 +29541,7 @@ var DevServer = class _DevServer {
29058
29541
  for (const file of fs15.readdirSync(latestScriptsDir)) {
29059
29542
  if (file.endsWith(".js") && targetFileNames.has(file)) {
29060
29543
  try {
29061
- const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
29544
+ const content = fs15.readFileSync(path27.join(latestScriptsDir, file), "utf-8");
29062
29545
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
29063
29546
  lines.push("```javascript");
29064
29547
  lines.push(content);
@@ -29075,7 +29558,7 @@ var DevServer = class _DevServer {
29075
29558
  lines.push("");
29076
29559
  for (const file of refFiles) {
29077
29560
  try {
29078
- const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
29561
+ const content = fs15.readFileSync(path27.join(latestScriptsDir, file), "utf-8");
29079
29562
  lines.push(`### \`${file}\` \u{1F512}`);
29080
29563
  lines.push("```javascript");
29081
29564
  lines.push(content);
@@ -29116,10 +29599,10 @@ var DevServer = class _DevServer {
29116
29599
  lines.push("");
29117
29600
  }
29118
29601
  }
29119
- const docsDir = path26.join(providerDir, "../../docs");
29602
+ const docsDir = path27.join(providerDir, "../../docs");
29120
29603
  const loadGuide = (name) => {
29121
29604
  try {
29122
- const p = path26.join(docsDir, name);
29605
+ const p = path27.join(docsDir, name);
29123
29606
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
29124
29607
  } catch {
29125
29608
  }
@@ -29293,7 +29776,7 @@ var DevServer = class _DevServer {
29293
29776
  parseApproval: "parse_approval.js"
29294
29777
  };
29295
29778
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
29296
- const scriptsDir = path26.join(providerDir, "scripts");
29779
+ const scriptsDir = path27.join(providerDir, "scripts");
29297
29780
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
29298
29781
  if (latestScriptsDir) {
29299
29782
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -29305,7 +29788,7 @@ var DevServer = class _DevServer {
29305
29788
  if (!file.endsWith(".js")) continue;
29306
29789
  if (!targetFileNames.has(file)) continue;
29307
29790
  try {
29308
- const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
29791
+ const content = fs15.readFileSync(path27.join(latestScriptsDir, file), "utf-8");
29309
29792
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
29310
29793
  lines.push("```javascript");
29311
29794
  lines.push(content);
@@ -29321,7 +29804,7 @@ var DevServer = class _DevServer {
29321
29804
  lines.push("");
29322
29805
  for (const file of refFiles) {
29323
29806
  try {
29324
- const content = fs15.readFileSync(path26.join(latestScriptsDir, file), "utf-8");
29807
+ const content = fs15.readFileSync(path27.join(latestScriptsDir, file), "utf-8");
29325
29808
  lines.push(`### \`${file}\` \u{1F512}`);
29326
29809
  lines.push("```javascript");
29327
29810
  lines.push(content);
@@ -29354,10 +29837,10 @@ var DevServer = class _DevServer {
29354
29837
  lines.push("");
29355
29838
  }
29356
29839
  }
29357
- const docsDir = path26.join(providerDir, "../../docs");
29840
+ const docsDir = path27.join(providerDir, "../../docs");
29358
29841
  const loadGuide = (name) => {
29359
29842
  try {
29360
- const p = path26.join(docsDir, name);
29843
+ const p = path27.join(docsDir, name);
29361
29844
  if (fs15.existsSync(p)) return fs15.readFileSync(p, "utf-8");
29362
29845
  } catch {
29363
29846
  }
@@ -30622,6 +31105,12 @@ export {
30622
31105
  AcpProviderInstance,
30623
31106
  AgentStreamPoller,
30624
31107
  BUILTIN_CHAT_MESSAGE_KINDS,
31108
+ CHAT_MESSAGE_ACTIVITY_SOURCES,
31109
+ CHAT_MESSAGE_AUDIENCES,
31110
+ CHAT_MESSAGE_INTERNAL_SOURCES,
31111
+ CHAT_MESSAGE_SOURCES,
31112
+ CHAT_MESSAGE_TRANSCRIPT_VISIBILITIES,
31113
+ CHAT_MESSAGE_VISIBILITIES,
30625
31114
  CdpDomHandlers,
30626
31115
  CliProviderInstance,
30627
31116
  DAEMON_WS_PATH,
@@ -30684,6 +31173,7 @@ export {
30684
31173
  buildThoughtChatMessage,
30685
31174
  buildToolChatMessage,
30686
31175
  buildUserChatMessage,
31176
+ classifyChatMessageVisibility,
30687
31177
  classifyHotChatSessionsForSubscriptionFlush,
30688
31178
  clearDebugTrace,
30689
31179
  compareGitSnapshots,
@@ -30703,6 +31193,9 @@ export {
30703
31193
  detectIDEs,
30704
31194
  ensureSessionHostReady,
30705
31195
  execNpmCommandSync,
31196
+ filterActivityChatMessages,
31197
+ filterChatMessagesByVisibility,
31198
+ filterInternalChatMessages,
30706
31199
  filterUserFacingChatMessages,
30707
31200
  findCdpManager,
30708
31201
  flattenMessageParts,
@@ -30734,11 +31227,13 @@ export {
30734
31227
  initDaemonComponents,
30735
31228
  installExtensions,
30736
31229
  installGlobalInterceptor,
31230
+ isActivityChatMessage,
30737
31231
  isBuiltinChatMessageKind,
30738
31232
  isCdpConnected,
30739
31233
  isExtensionInstalled,
30740
31234
  isGitCommandName,
30741
31235
  isIdeRunning,
31236
+ isInternalChatMessage,
30742
31237
  isManagedStatusWaiting,
30743
31238
  isManagedStatusWorking,
30744
31239
  isPathInside,