@adhdev/daemon-core 0.8.51 → 0.8.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/commands/cli-manager.d.ts +8 -1
  2. package/dist/index.d.ts +5 -1
  3. package/dist/index.js +896 -299
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +887 -300
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/providers/acp-provider-instance.d.ts +2 -1
  8. package/dist/providers/cli-provider-instance.d.ts +3 -1
  9. package/dist/providers/cli-script-results.d.ts +8 -0
  10. package/dist/providers/contracts.d.ts +58 -9
  11. package/dist/providers/control-effects.d.ts +4 -1
  12. package/dist/providers/io-contracts.d.ts +91 -0
  13. package/dist/providers/provider-schema.d.ts +5 -0
  14. package/dist/session-host/runtime-surface.d.ts +16 -0
  15. package/dist/session-host/startup-restore-policy.d.ts +1 -0
  16. package/dist/shared-types.d.ts +6 -0
  17. package/dist/types.d.ts +3 -3
  18. package/node_modules/@adhdev/session-host-core/dist/index.d.mts +16 -1
  19. package/node_modules/@adhdev/session-host-core/dist/index.d.ts +16 -1
  20. package/node_modules/@adhdev/session-host-core/dist/index.js +59 -0
  21. package/node_modules/@adhdev/session-host-core/dist/index.js.map +1 -1
  22. package/node_modules/@adhdev/session-host-core/dist/index.mjs +54 -0
  23. package/node_modules/@adhdev/session-host-core/dist/index.mjs.map +1 -1
  24. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  25. package/package.json +1 -1
  26. package/src/commands/cdp-commands.ts +27 -0
  27. package/src/commands/chat-commands.ts +7 -2
  28. package/src/commands/cli-manager.ts +9 -5
  29. package/src/commands/handler.ts +1 -9
  30. package/src/commands/stream-commands.ts +26 -36
  31. package/src/daemon/dev-server.ts +4 -18
  32. package/src/index.d.ts +3 -0
  33. package/src/index.ts +12 -1
  34. package/src/providers/acp-provider-instance.ts +156 -14
  35. package/src/providers/cli-provider-instance.ts +54 -5
  36. package/src/providers/cli-script-results.ts +39 -0
  37. package/src/providers/contracts.ts +72 -19
  38. package/src/providers/control-effects.ts +86 -1
  39. package/src/providers/io-contracts.ts +340 -0
  40. package/src/providers/provider-loader.ts +18 -13
  41. package/src/providers/provider-schema.ts +154 -0
  42. package/src/session-host/runtime-surface.ts +80 -0
  43. package/src/session-host/startup-restore-policy.d.ts +1 -0
  44. package/src/session-host/startup-restore-policy.js +7 -0
  45. package/src/session-host/startup-restore-policy.ts +7 -0
  46. package/src/shared-types.ts +6 -0
  47. package/src/status/builders.ts +5 -81
  48. package/src/types.ts +3 -3
package/dist/index.js CHANGED
@@ -3042,6 +3042,7 @@ __export(index_exports, {
3042
3042
  detectIDEs: () => detectIDEs,
3043
3043
  ensureSessionHostReady: () => ensureSessionHostReady,
3044
3044
  findCdpManager: () => findCdpManager,
3045
+ flattenMessageParts: () => flattenMessageParts,
3045
3046
  forwardAgentStreamsToIdeInstance: () => forwardAgentStreamsToIdeInstance,
3046
3047
  getAIExtensions: () => getAIExtensions,
3047
3048
  getAvailableIdeIds: () => getAvailableIdeIds,
@@ -3055,6 +3056,8 @@ __export(index_exports, {
3055
3056
  getRecentDebugTrace: () => getRecentDebugTrace,
3056
3057
  getRecentLogs: () => getRecentLogs,
3057
3058
  getSavedProviderSessions: () => getSavedProviderSessions,
3059
+ getSessionHostRecoveryLabel: () => getSessionHostRecoveryLabel,
3060
+ getSessionHostSurfaceKind: () => getSessionHostSurfaceKind,
3058
3061
  getWorkspaceState: () => getWorkspaceState,
3059
3062
  hasCdpManager: () => hasCdpManager,
3060
3063
  initDaemonComponents: () => initDaemonComponents,
@@ -3065,6 +3068,8 @@ __export(index_exports, {
3065
3068
  isIdeRunning: () => isIdeRunning,
3066
3069
  isManagedStatusWaiting: () => isManagedStatusWaiting,
3067
3070
  isManagedStatusWorking: () => isManagedStatusWorking,
3071
+ isSessionHostLiveRuntime: () => isSessionHostLiveRuntime,
3072
+ isSessionHostRecoverySnapshot: () => isSessionHostRecoverySnapshot,
3068
3073
  isSetupComplete: () => isSetupComplete,
3069
3074
  killIdeProcess: () => killIdeProcess,
3070
3075
  launchIDE: () => launchIDE,
@@ -3076,7 +3081,11 @@ __export(index_exports, {
3076
3081
  markSetupComplete: () => markSetupComplete,
3077
3082
  maybeRunDaemonUpgradeHelperFromEnv: () => maybeRunDaemonUpgradeHelperFromEnv,
3078
3083
  normalizeActiveChatData: () => normalizeActiveChatData,
3084
+ normalizeInputEnvelope: () => normalizeInputEnvelope,
3079
3085
  normalizeManagedStatus: () => normalizeManagedStatus,
3086
+ normalizeMessageParts: () => normalizeMessageParts,
3087
+ partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
3088
+ partitionSessionHostRecords: () => partitionSessionHostRecords,
3080
3089
  probeCdpPort: () => probeCdpPort,
3081
3090
  readChatHistory: () => readChatHistory,
3082
3091
  recordDebugTrace: () => recordDebugTrace,
@@ -3091,6 +3100,7 @@ __export(index_exports, {
3091
3100
  setDebugRuntimeConfig: () => setDebugRuntimeConfig,
3092
3101
  setLogLevel: () => setLogLevel,
3093
3102
  setupIdeInstance: () => setupIdeInstance,
3103
+ shouldAutoRestoreHostedSessionsOnStartup: () => shouldAutoRestoreHostedSessionsOnStartup,
3094
3104
  shouldCollectTraceCategory: () => shouldCollectTraceCategory,
3095
3105
  shutdownDaemonComponents: () => shutdownDaemonComponents,
3096
3106
  spawnDetachedDaemonUpgradeHelper: () => spawnDetachedDaemonUpgradeHelper,
@@ -5186,6 +5196,61 @@ function normalizeProviderEffects(data) {
5186
5196
  }
5187
5197
  return effects;
5188
5198
  }
5199
+ function normalizeControlListResult(data) {
5200
+ if (data && typeof data === "object" && Array.isArray(data.options)) {
5201
+ return {
5202
+ options: normalizeControlOptions(data.options),
5203
+ ...isScalarControlValue(data.currentValue) ? { currentValue: data.currentValue } : {},
5204
+ ...typeof data.error === "string" ? { error: data.error } : {}
5205
+ };
5206
+ }
5207
+ const rawOptions = Array.isArray(data?.models) ? data.models : Array.isArray(data?.modes) ? data.modes : Array.isArray(data?.options) ? data.options : [];
5208
+ const options = normalizeControlOptions(rawOptions);
5209
+ return {
5210
+ options,
5211
+ ...isScalarControlValue(data?.current) ? { currentValue: data.current } : {},
5212
+ ...isScalarControlValue(data?.currentValue) ? { currentValue: data.currentValue } : {},
5213
+ ...typeof data?.error === "string" ? { error: data.error } : {}
5214
+ };
5215
+ }
5216
+ function normalizeControlSetResult(data) {
5217
+ const currentValue = isScalarControlValue(data?.currentValue) ? data.currentValue : isScalarControlValue(data?.value) ? data.value : void 0;
5218
+ return {
5219
+ ok: data?.ok === true || data?.success === true,
5220
+ ...currentValue !== void 0 ? { currentValue } : {},
5221
+ ...Array.isArray(data?.effects) ? { effects: normalizeProviderEffects(data) } : {},
5222
+ ...typeof data?.error === "string" ? { error: data.error } : {}
5223
+ };
5224
+ }
5225
+ function normalizeControlInvokeResult(data) {
5226
+ const currentValue = isScalarControlValue(data?.currentValue) ? data.currentValue : isScalarControlValue(data?.value) ? data.value : void 0;
5227
+ return {
5228
+ ok: data?.ok === true || data?.success === true,
5229
+ ...currentValue !== void 0 ? { currentValue } : {},
5230
+ ...Array.isArray(data?.effects) ? { effects: normalizeProviderEffects(data) } : {},
5231
+ ...typeof data?.error === "string" ? { error: data.error } : {}
5232
+ };
5233
+ }
5234
+ function normalizeControlOptions(options) {
5235
+ return options.map((option) => normalizeControlOption(option)).filter((option) => !!option);
5236
+ }
5237
+ function normalizeControlOption(option) {
5238
+ if (typeof option === "string") {
5239
+ return { value: option, label: option };
5240
+ }
5241
+ if (!option || typeof option !== "object") return null;
5242
+ const record = option;
5243
+ const value = typeof record.value === "string" ? record.value : typeof record.id === "string" ? record.id : null;
5244
+ if (!value) return null;
5245
+ const label = typeof record.label === "string" ? record.label : typeof record.name === "string" ? record.name : value;
5246
+ const normalized = { value, label };
5247
+ if (typeof record.description === "string") normalized.description = record.description;
5248
+ if (typeof record.group === "string") normalized.group = record.group;
5249
+ return normalized;
5250
+ }
5251
+ function isScalarControlValue(value) {
5252
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
5253
+ }
5189
5254
  function normalizeControlValue(value) {
5190
5255
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
5191
5256
  return value;
@@ -7177,50 +7242,6 @@ function isCdpConnected(cdpManagers, key) {
7177
7242
  }
7178
7243
  return false;
7179
7244
  }
7180
- function buildFallbackControls(providerControls, serverModel, serverMode, acpConfigOptions, acpModes) {
7181
- if (providerControls && providerControls.length > 0) return providerControls;
7182
- const controls = [];
7183
- const isAcp = !!(acpConfigOptions || acpModes);
7184
- const modelFromAcp = acpConfigOptions?.find((c) => c.category === "model");
7185
- if (!isAcp || modelFromAcp) {
7186
- controls.push({
7187
- id: "model",
7188
- type: "select",
7189
- label: "Model",
7190
- icon: "\u{1F916}",
7191
- placement: "bar",
7192
- dynamic: !modelFromAcp,
7193
- listScript: "listModels",
7194
- setScript: "setModel",
7195
- readFrom: "model",
7196
- ...modelFromAcp && {
7197
- options: modelFromAcp.options.map((o) => ({ value: o.value, label: o.name || o.value }))
7198
- }
7199
- });
7200
- }
7201
- const modeFromAcp = acpModes && acpModes.length > 0;
7202
- const thoughtFromAcp = !modeFromAcp && acpConfigOptions?.find((c) => c.category !== "model");
7203
- if (!isAcp || modeFromAcp || thoughtFromAcp) {
7204
- controls.push({
7205
- id: "mode",
7206
- type: thoughtFromAcp ? "cycle" : "select",
7207
- label: thoughtFromAcp ? "Thinking" : "Mode",
7208
- icon: thoughtFromAcp ? "\u{1F9E0}" : "\u26A1",
7209
- placement: "bar",
7210
- dynamic: !modeFromAcp && !thoughtFromAcp,
7211
- listScript: "listModes",
7212
- setScript: thoughtFromAcp ? "setThinkingLevel" : "setMode",
7213
- readFrom: "mode",
7214
- ...modeFromAcp && {
7215
- options: acpModes.map((m) => ({ value: m.id, label: m.name || m.id }))
7216
- },
7217
- ...thoughtFromAcp && {
7218
- options: thoughtFromAcp.options.map((o) => ({ value: o.value, label: o.name || o.value }))
7219
- }
7220
- });
7221
- }
7222
- return controls;
7223
- }
7224
7245
  var IDE_SESSION_CAPABILITIES = [
7225
7246
  "read_chat",
7226
7247
  "send_message",
@@ -7289,11 +7310,7 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
7289
7310
  currentAutoApprove: state.currentAutoApprove,
7290
7311
  ...includeSessionControls && {
7291
7312
  controlValues: state.controlValues,
7292
- providerControls: buildFallbackControls(
7293
- state.providerControls,
7294
- state.currentModel,
7295
- state.currentPlan
7296
- )
7313
+ providerControls: state.providerControls
7297
7314
  },
7298
7315
  errorMessage: state.errorMessage,
7299
7316
  errorReason: state.errorReason,
@@ -7323,11 +7340,7 @@ function buildExtensionAgentSession(parent, ext, options) {
7323
7340
  currentPlan: ext.currentPlan,
7324
7341
  ...includeSessionControls && {
7325
7342
  controlValues: ext.controlValues,
7326
- providerControls: buildFallbackControls(
7327
- ext.providerControls,
7328
- ext.currentModel,
7329
- ext.currentPlan
7330
- )
7343
+ providerControls: ext.providerControls
7331
7344
  },
7332
7345
  errorMessage: ext.errorMessage,
7333
7346
  errorReason: ext.errorReason,
@@ -7368,9 +7381,7 @@ function buildCliSession(state, options) {
7368
7381
  },
7369
7382
  ...includeSessionControls && {
7370
7383
  controlValues: state.controlValues,
7371
- providerControls: buildFallbackControls(
7372
- state.providerControls
7373
- )
7384
+ providerControls: state.providerControls
7374
7385
  },
7375
7386
  errorMessage: state.errorMessage,
7376
7387
  errorReason: state.errorReason,
@@ -7402,13 +7413,7 @@ function buildAcpSession(state, options) {
7402
7413
  acpConfigOptions: state.acpConfigOptions,
7403
7414
  acpModes: state.acpModes,
7404
7415
  controlValues: state.controlValues,
7405
- providerControls: buildFallbackControls(
7406
- state.providerControls,
7407
- state.currentModel,
7408
- state.currentPlan,
7409
- state.acpConfigOptions,
7410
- state.acpModes
7411
- )
7416
+ providerControls: state.providerControls
7412
7417
  },
7413
7418
  errorMessage: state.errorMessage,
7414
7419
  errorReason: state.errorReason,
@@ -7491,10 +7496,217 @@ function reconcileIdeRuntimeSessions(instanceManager, sessionRegistry) {
7491
7496
  // src/commands/handler.ts
7492
7497
  init_logger();
7493
7498
 
7499
+ // src/providers/io-contracts.ts
7500
+ function normalizeInputEnvelope(input) {
7501
+ const normalized = normalizeInputEnvelopePayload(input);
7502
+ const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
7503
+ return {
7504
+ parts: normalized.parts,
7505
+ textFallback,
7506
+ ...normalized.metadata ? { metadata: normalized.metadata } : {}
7507
+ };
7508
+ }
7509
+ function normalizeMessageParts(content) {
7510
+ if (typeof content === "string") return [{ type: "text", text: content }];
7511
+ if (!Array.isArray(content)) {
7512
+ if (content && typeof content === "object" && typeof content.text === "string") {
7513
+ return [{ type: "text", text: String(content.text) }];
7514
+ }
7515
+ return [];
7516
+ }
7517
+ const parts = [];
7518
+ for (const raw of content) {
7519
+ if (typeof raw === "string") {
7520
+ parts.push({ type: "text", text: raw });
7521
+ continue;
7522
+ }
7523
+ if (!raw || typeof raw !== "object") continue;
7524
+ const part = normalizeMessagePartObject(raw);
7525
+ if (part) parts.push(part);
7526
+ }
7527
+ return parts;
7528
+ }
7529
+ function flattenMessageParts(parts) {
7530
+ return parts.map((part) => {
7531
+ if (part.type === "text") return part.text;
7532
+ if (part.type === "resource") return part.resource.text || "";
7533
+ return "";
7534
+ }).filter((value) => value.length > 0).join("\n");
7535
+ }
7536
+ function normalizeInputEnvelopePayload(input) {
7537
+ if (typeof input === "string") {
7538
+ return { parts: [{ type: "text", text: input }], textFallback: input };
7539
+ }
7540
+ if (!input || typeof input !== "object") {
7541
+ return { parts: [], textFallback: "" };
7542
+ }
7543
+ const record = input;
7544
+ const nestedInput = record.input;
7545
+ if (nestedInput && typeof nestedInput === "object") {
7546
+ const nested = nestedInput;
7547
+ return {
7548
+ parts: normalizeInputParts(nested.parts ?? nested.prompt),
7549
+ textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
7550
+ metadata: normalizeInputMetadata(nested.metadata)
7551
+ };
7552
+ }
7553
+ const directText = typeof record.text === "string" ? record.text : typeof record.message === "string" ? record.message : void 0;
7554
+ if (directText !== void 0) {
7555
+ return { parts: [{ type: "text", text: directText }], textFallback: directText };
7556
+ }
7557
+ const directParts = normalizeInputParts(record.parts ?? record.prompt);
7558
+ return {
7559
+ parts: directParts,
7560
+ textFallback: typeof record.textFallback === "string" ? record.textFallback : void 0,
7561
+ metadata: normalizeInputMetadata(record.metadata)
7562
+ };
7563
+ }
7564
+ function normalizeInputMetadata(value) {
7565
+ if (!value || typeof value !== "object") return void 0;
7566
+ const record = value;
7567
+ const metadata = {};
7568
+ if (record.source === "dashboard" || record.source === "shortcut_api" || record.source === "provider_script" || record.source === "session_replay") {
7569
+ metadata.source = record.source;
7570
+ }
7571
+ if (typeof record.clientTimestamp === "number" && Number.isFinite(record.clientTimestamp)) {
7572
+ metadata.clientTimestamp = record.clientTimestamp;
7573
+ }
7574
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
7575
+ }
7576
+ function normalizeInputParts(value) {
7577
+ if (!Array.isArray(value)) return [];
7578
+ const parts = [];
7579
+ for (const raw of value) {
7580
+ if (typeof raw === "string") {
7581
+ parts.push({ type: "text", text: raw });
7582
+ continue;
7583
+ }
7584
+ if (!raw || typeof raw !== "object") continue;
7585
+ const part = normalizeInputPartObject(raw);
7586
+ if (part) parts.push(part);
7587
+ }
7588
+ return parts;
7589
+ }
7590
+ function normalizeInputPartObject(raw) {
7591
+ const type = raw.type;
7592
+ if (type === "text" && typeof raw.text === "string") {
7593
+ return { type, text: raw.text };
7594
+ }
7595
+ if (type === "image" && typeof raw.mimeType === "string") {
7596
+ return {
7597
+ type,
7598
+ mimeType: raw.mimeType,
7599
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
7600
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
7601
+ ...typeof raw.alt === "string" ? { alt: raw.alt } : {}
7602
+ };
7603
+ }
7604
+ if (type === "audio" && typeof raw.mimeType === "string") {
7605
+ return {
7606
+ type,
7607
+ mimeType: raw.mimeType,
7608
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
7609
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
7610
+ ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
7611
+ };
7612
+ }
7613
+ if (type === "video" && typeof raw.mimeType === "string") {
7614
+ return {
7615
+ type,
7616
+ mimeType: raw.mimeType,
7617
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
7618
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
7619
+ ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
7620
+ };
7621
+ }
7622
+ if (type === "resource" && typeof raw.uri === "string") {
7623
+ return {
7624
+ type,
7625
+ uri: raw.uri,
7626
+ ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
7627
+ ...typeof raw.name === "string" ? { name: raw.name } : {},
7628
+ ...typeof raw.text === "string" ? { text: raw.text } : {},
7629
+ ...typeof raw.data === "string" ? { data: raw.data } : {}
7630
+ };
7631
+ }
7632
+ if (type === "resource_link" && typeof raw.uri === "string") {
7633
+ return {
7634
+ type: "resource",
7635
+ uri: raw.uri,
7636
+ ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
7637
+ ...typeof raw.name === "string" ? { name: raw.name } : {}
7638
+ };
7639
+ }
7640
+ return null;
7641
+ }
7642
+ function normalizeMessagePartObject(raw) {
7643
+ const type = raw.type;
7644
+ if (type === "text" && typeof raw.text === "string") {
7645
+ return { type, text: raw.text };
7646
+ }
7647
+ if (type === "image" && typeof raw.mimeType === "string") {
7648
+ return {
7649
+ type,
7650
+ mimeType: raw.mimeType,
7651
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
7652
+ ...typeof raw.data === "string" ? { data: raw.data } : {}
7653
+ };
7654
+ }
7655
+ if (type === "audio" && typeof raw.mimeType === "string") {
7656
+ return {
7657
+ type,
7658
+ mimeType: raw.mimeType,
7659
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
7660
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
7661
+ ...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
7662
+ };
7663
+ }
7664
+ if (type === "video" && typeof raw.mimeType === "string") {
7665
+ return {
7666
+ type,
7667
+ mimeType: raw.mimeType,
7668
+ ...typeof raw.uri === "string" ? { uri: raw.uri } : {},
7669
+ ...typeof raw.data === "string" ? { data: raw.data } : {},
7670
+ ...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
7671
+ };
7672
+ }
7673
+ if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
7674
+ return {
7675
+ type,
7676
+ uri: raw.uri,
7677
+ name: raw.name,
7678
+ ...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
7679
+ ...typeof raw.size === "number" ? { size: raw.size } : {}
7680
+ };
7681
+ }
7682
+ if (type === "resource" && raw.resource && typeof raw.resource === "object") {
7683
+ const resource = raw.resource;
7684
+ if (typeof resource.uri !== "string") return null;
7685
+ return {
7686
+ type,
7687
+ resource: {
7688
+ uri: resource.uri,
7689
+ ...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
7690
+ ...typeof resource.text === "string" ? { text: resource.text } : {},
7691
+ ...typeof resource.blob === "string" ? { blob: resource.blob } : {}
7692
+ }
7693
+ };
7694
+ }
7695
+ return null;
7696
+ }
7697
+ function flattenInputParts(parts) {
7698
+ return parts.map((part) => {
7699
+ if (part.type === "text") return part.text;
7700
+ if (part.type === "audio") return part.transcript || "";
7701
+ if (part.type === "resource") return part.text || "";
7702
+ return "";
7703
+ }).filter((value) => value.length > 0).join("\n");
7704
+ }
7705
+
7494
7706
  // src/providers/contracts.ts
7495
7707
  function flattenContent(content) {
7496
7708
  if (typeof content === "string") return content;
7497
- return content.filter((b) => b.type === "text").map((b) => b.text).join("\n");
7709
+ return flattenMessageParts(normalizeMessageParts(content));
7498
7710
  }
7499
7711
 
7500
7712
  // src/commands/chat-commands.ts
@@ -7683,6 +7895,9 @@ function buildRecentSendKey(h, args, provider, text) {
7683
7895
  const target = args?.targetSessionId || args?.agentType || h.currentSession?.providerType || h.currentProviderType || h.currentManagerKey || "unknown";
7684
7896
  return `${transport}:${target}:${text.trim()}`;
7685
7897
  }
7898
+ function getSendChatInputEnvelope(args) {
7899
+ return normalizeInputEnvelope(args?.input ? { input: args.input } : args);
7900
+ }
7686
7901
  function getHistorySessionId(h, args) {
7687
7902
  const explicit = typeof args?.historySessionId === "string" ? args.historySessionId.trim() : "";
7688
7903
  if (explicit) return explicit;
@@ -8087,7 +8302,8 @@ async function handleReadChat(h, args) {
8087
8302
  return buildReadChatCommandResult({ messages: [], status: "idle" }, args);
8088
8303
  }
8089
8304
  async function handleSendChat(h, args) {
8090
- const text = args?.text || args?.message;
8305
+ const input = getSendChatInputEnvelope(args);
8306
+ const text = input.textFallback;
8091
8307
  if (!text) return { success: false, error: "text required" };
8092
8308
  const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
8093
8309
  const provider = h.getProvider(args?.agentType);
@@ -9027,6 +9243,21 @@ function listDirectoryEntriesSafe(dirPath) {
9027
9243
  }
9028
9244
  return files;
9029
9245
  }
9246
+ function listWindowsDriveEntries(excludePath) {
9247
+ const excluded = typeof excludePath === "string" ? excludePath.toLowerCase() : "";
9248
+ const drives = [];
9249
+ for (let code = 65; code <= 90; code += 1) {
9250
+ const letter = String.fromCharCode(code);
9251
+ const root = `${letter}:\\`;
9252
+ try {
9253
+ if (!fs4.existsSync(root)) continue;
9254
+ if (excluded && root.toLowerCase() === excluded) continue;
9255
+ drives.push({ name: `${letter}:`, type: "directory", path: root });
9256
+ } catch {
9257
+ }
9258
+ }
9259
+ return drives;
9260
+ }
9030
9261
  async function handleFileRead(h, args) {
9031
9262
  try {
9032
9263
  const filePath = resolveSafePath(args?.path);
@@ -9059,12 +9290,51 @@ async function handleFileListBrowse(h, args) {
9059
9290
  try {
9060
9291
  const dirPath = resolveSafePath(args?.path || ".");
9061
9292
  const files = listDirectoryEntriesSafe(dirPath).filter((entry) => entry.type === "directory").sort((a, b) => a.name.localeCompare(b.name));
9293
+ if (process.platform === "win32" && /^[A-Za-z]:\\?$/.test(dirPath)) {
9294
+ const driveEntries = listWindowsDriveEntries(dirPath);
9295
+ return {
9296
+ success: true,
9297
+ files: [...driveEntries, ...files],
9298
+ path: dirPath
9299
+ };
9300
+ }
9062
9301
  return { success: true, files, path: dirPath };
9063
9302
  } catch (e) {
9064
9303
  return { success: false, error: e.message };
9065
9304
  }
9066
9305
  }
9067
9306
 
9307
+ // src/providers/cli-script-results.ts
9308
+ function parseCliScriptResult(result) {
9309
+ if (typeof result === "string") {
9310
+ try {
9311
+ const parsed = JSON.parse(result);
9312
+ if (parsed && typeof parsed === "object" && parsed.success === false) {
9313
+ return { success: false, payload: parsed };
9314
+ }
9315
+ return { success: true, payload: parsed };
9316
+ } catch {
9317
+ return { success: true, payload: { result } };
9318
+ }
9319
+ }
9320
+ if (result && typeof result === "object" && "success" in result && result.success === false) {
9321
+ return { success: false, payload: result };
9322
+ }
9323
+ return { success: true, payload: result };
9324
+ }
9325
+ function getCliScriptCommand(payload) {
9326
+ if (!payload || typeof payload !== "object") return null;
9327
+ if (typeof payload.sendMessage === "string" && payload.sendMessage.trim()) {
9328
+ return { type: "send_message", text: payload.sendMessage.trim() };
9329
+ }
9330
+ const command = payload.command;
9331
+ if (!command || typeof command !== "object") return null;
9332
+ if (command.type !== "send_message" && command.type !== "pty_write") return null;
9333
+ const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
9334
+ if (!text) return null;
9335
+ return { type: command.type, text };
9336
+ }
9337
+
9068
9338
  // src/commands/stream-commands.ts
9069
9339
  init_logger();
9070
9340
  function getCliPresentationMode(h, targetSessionId) {
@@ -9155,34 +9425,19 @@ function normalizeProviderScriptArgs(args) {
9155
9425
  }
9156
9426
  return normalizedArgs;
9157
9427
  }
9158
- function parseScriptResult(result) {
9159
- if (typeof result === "string") {
9160
- try {
9161
- const parsed = JSON.parse(result);
9162
- if (parsed && typeof parsed === "object" && parsed.success === false) {
9163
- return { success: false, payload: parsed };
9164
- }
9165
- return { success: true, payload: parsed };
9166
- } catch {
9167
- return { success: true, payload: { result } };
9168
- }
9428
+ function buildControlScriptResult(scriptName, payload) {
9429
+ if (!payload || typeof payload !== "object") return {};
9430
+ if (Array.isArray(payload.options) || Array.isArray(payload.models) || Array.isArray(payload.modes)) {
9431
+ return { controlResult: normalizeControlListResult(payload) };
9169
9432
  }
9170
- if (result && typeof result === "object" && "success" in result && result.success === false) {
9171
- return { success: false, payload: result };
9433
+ const looksLikeValueMutation = /^set|^change/i.test(scriptName) || payload.currentValue !== void 0 || payload.value !== void 0;
9434
+ if (looksLikeValueMutation) {
9435
+ return { controlResult: normalizeControlSetResult(payload) };
9172
9436
  }
9173
- return { success: true, payload: result };
9174
- }
9175
- function getCliScriptCommand(payload) {
9176
- if (!payload || typeof payload !== "object") return null;
9177
- if (typeof payload.sendMessage === "string" && payload.sendMessage.trim()) {
9178
- return { type: "send_message", text: payload.sendMessage.trim() };
9437
+ if (payload.ok !== void 0 || payload.success !== void 0 || Array.isArray(payload.effects)) {
9438
+ return { controlResult: normalizeControlInvokeResult(payload) };
9179
9439
  }
9180
- const command = payload.command;
9181
- if (!command || typeof command !== "object") return null;
9182
- if (command.type !== "send_message" && command.type !== "pty_write") return null;
9183
- const text = typeof command.text === "string" ? command.text.trim() : typeof command.message === "string" ? command.message.trim() : "";
9184
- if (!text) return null;
9185
- return { type: command.type, text };
9440
+ return {};
9186
9441
  }
9187
9442
  function applyProviderPatch(h, args, payload) {
9188
9443
  if (!payload || typeof payload !== "object") return;
@@ -9216,7 +9471,7 @@ async function executeProviderScript(h, args, scriptName) {
9216
9471
  }
9217
9472
  try {
9218
9473
  const raw = await adapter.invokeScript(actualScriptName, normalizedArgs);
9219
- const parsed = parseScriptResult(raw);
9474
+ const parsed = parseCliScriptResult(raw);
9220
9475
  if (!parsed.success) {
9221
9476
  return { success: false, ...parsed.payload || {} };
9222
9477
  }
@@ -9227,7 +9482,11 @@ async function executeProviderScript(h, args, scriptName) {
9227
9482
  adapter.writeRaw(cliCommand.text + "\r");
9228
9483
  }
9229
9484
  applyProviderPatch(h, args, parsed.payload);
9230
- return { success: true, ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload } };
9485
+ return {
9486
+ success: true,
9487
+ ...parsed.payload && typeof parsed.payload === "object" ? parsed.payload : { result: parsed.payload },
9488
+ ...buildControlScriptResult(scriptName, parsed.payload)
9489
+ };
9231
9490
  } catch (e) {
9232
9491
  return { success: false, error: `Script execution failed: ${e.message}` };
9233
9492
  }
@@ -9290,7 +9549,7 @@ async function executeProviderScript(h, args, scriptName) {
9290
9549
  if (parsed && typeof parsed === "object" && parsed.success === false) {
9291
9550
  return { success: false, ...parsed };
9292
9551
  }
9293
- return { success: true, ...parsed };
9552
+ return { success: true, ...parsed, ...buildControlScriptResult(scriptName, parsed) };
9294
9553
  } catch {
9295
9554
  return { success: true, result };
9296
9555
  }
@@ -9301,9 +9560,6 @@ async function executeProviderScript(h, args, scriptName) {
9301
9560
  return { success: false, error: `Script execution failed: ${e.message}` };
9302
9561
  }
9303
9562
  }
9304
- async function handleExtensionScript(h, args, scriptName) {
9305
- return executeProviderScript(h, args, scriptName);
9306
- }
9307
9563
  async function handleProviderScript(h, args) {
9308
9564
  const scriptName = typeof args?.scriptName === "string" ? args.scriptName.trim() : "";
9309
9565
  if (!scriptName) return { success: false, error: "scriptName is required" };
@@ -9746,11 +10002,7 @@ var DaemonCommandHandler = class {
9746
10002
  "focus_session",
9747
10003
  "pty_input",
9748
10004
  "pty_resize",
9749
- "invoke_provider_script",
9750
- "list_extension_models",
9751
- "set_extension_model",
9752
- "list_extension_modes",
9753
- "set_extension_mode"
10005
+ "invoke_provider_script"
9754
10006
  ]);
9755
10007
  if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd)) {
9756
10008
  const result2 = {
@@ -9862,17 +10114,9 @@ var DaemonCommandHandler = class {
9862
10114
  return handleGetIdeExtensions(this, args);
9863
10115
  case "set_ide_extension":
9864
10116
  return handleSetIdeExtension(this, args);
9865
- // ─── Extension Model / Mode Control (stream-commands.ts) ──────────
10117
+ // ─── Provider control execution (stream-commands.ts) ──────────
9866
10118
  case "invoke_provider_script":
9867
10119
  return handleProviderScript(this, args);
9868
- case "list_extension_models":
9869
- return handleExtensionScript(this, args, "listModels");
9870
- case "set_extension_model":
9871
- return handleExtensionScript(this, args, "setModel");
9872
- case "list_extension_modes":
9873
- return handleExtensionScript(this, args, "listModes");
9874
- case "set_extension_mode":
9875
- return handleExtensionScript(this, args, "setMode");
9876
10120
  // ─── Provider Auto-Fix / Clone (DevServer proxy) ──────────
9877
10121
  case "provider_auto_fix":
9878
10122
  return this.proxyDevServerPost(args, "auto-implement");
@@ -9989,7 +10233,7 @@ var DaemonCommandHandler = class {
9989
10233
 
9990
10234
  // src/commands/cli-manager.ts
9991
10235
  var os12 = __toESM(require("os"));
9992
- var path12 = __toESM(require("path"));
10236
+ var path13 = __toESM(require("path"));
9993
10237
  var crypto4 = __toESM(require("crypto"));
9994
10238
  var import_chalk = __toESM(require("chalk"));
9995
10239
  init_provider_cli_adapter();
@@ -10014,6 +10258,23 @@ function getDatabaseSync() {
10014
10258
  }
10015
10259
  return CachedDatabaseSync;
10016
10260
  }
10261
+ function getForcedNewSessionScriptName(provider, launchMode) {
10262
+ if (!provider || launchMode !== "new") return null;
10263
+ const resume = provider.resume;
10264
+ if (!resume?.supported) return null;
10265
+ if (Array.isArray(resume.newSessionArgs) && resume.newSessionArgs.length > 0) return null;
10266
+ const controls = Array.isArray(provider.controls) ? provider.controls : [];
10267
+ for (const control of controls) {
10268
+ if (control?.type !== "action") continue;
10269
+ const invokeScript = typeof control?.invokeScript === "string" ? control.invokeScript.trim() : "";
10270
+ if (!invokeScript) continue;
10271
+ const controlId = typeof control?.id === "string" ? control.id.trim() : "";
10272
+ if (controlId === "new_session" || /^new.?session$/i.test(invokeScript)) {
10273
+ return invokeScript;
10274
+ }
10275
+ }
10276
+ return null;
10277
+ }
10017
10278
  var CliProviderInstance = class {
10018
10279
  constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, options) {
10019
10280
  this.provider = provider;
@@ -10072,6 +10333,7 @@ var CliProviderInstance = class {
10072
10333
  this.detectStatusTransition();
10073
10334
  });
10074
10335
  await this.adapter.spawn();
10336
+ await this.enforceFreshSessionLaunchIfNeeded();
10075
10337
  this.maybeAppendRuntimeRecoveryMessage(this.adapter.getRuntimeMetadata());
10076
10338
  if (this.providerSessionId) {
10077
10339
  this.historyWriter.compactHistorySession(this.type, this.providerSessionId);
@@ -10263,10 +10525,13 @@ var CliProviderInstance = class {
10263
10525
  });
10264
10526
  }
10265
10527
  onEvent(event, data) {
10266
- if (event === "send_message" && data?.text) {
10267
- void this.adapter.sendMessage(data.text).catch((e) => {
10268
- LOG.warn("CLI", `[${this.type}] send_message failed: ${e?.message || e}`);
10269
- });
10528
+ if (event === "send_message") {
10529
+ const input = normalizeInputEnvelope(data);
10530
+ if (input.textFallback) {
10531
+ void this.adapter.sendMessage(input.textFallback).catch((e) => {
10532
+ LOG.warn("CLI", `[${this.type}] send_message failed: ${e?.message || e}`);
10533
+ });
10534
+ }
10270
10535
  } else if (event === "server_connected" && data?.serverConn) {
10271
10536
  this.adapter.setServerConn(data.serverConn);
10272
10537
  } else if (event === "resolve_action" && data) {
@@ -10284,6 +10549,23 @@ var CliProviderInstance = class {
10284
10549
  }
10285
10550
  completedDebounceTimer = null;
10286
10551
  completedDebouncePending = null;
10552
+ async enforceFreshSessionLaunchIfNeeded() {
10553
+ const scriptName = getForcedNewSessionScriptName(this.provider, this.launchMode);
10554
+ if (!scriptName) return;
10555
+ LOG.info("CLI", `[${this.type}] forcing fresh session launch via script: ${scriptName}`);
10556
+ const raw = await this.adapter.invokeScript(scriptName, {});
10557
+ const parsed = parseCliScriptResult(raw);
10558
+ if (!parsed.success) {
10559
+ throw new Error(parsed.payload?.error || `Failed to invoke fresh-session script '${scriptName}'`);
10560
+ }
10561
+ const cliCommand = getCliScriptCommand(parsed.payload);
10562
+ if (cliCommand?.type === "send_message" && cliCommand.text) {
10563
+ await this.adapter.sendMessage(cliCommand.text);
10564
+ } else if (cliCommand?.type === "pty_write" && cliCommand.text) {
10565
+ this.adapter.writeRaw(cliCommand.text + "\r");
10566
+ }
10567
+ this.applyProviderResponse(parsed.payload, { phase: "immediate" });
10568
+ }
10287
10569
  detectStatusTransition() {
10288
10570
  const now = Date.now();
10289
10571
  const adapterStatus = this.adapter.getStatus();
@@ -10667,10 +10949,106 @@ ${effect.notification.body || ""}`.trim();
10667
10949
  };
10668
10950
 
10669
10951
  // src/providers/acp-provider-instance.ts
10952
+ var path12 = __toESM(require("path"));
10670
10953
  var import_stream = require("stream");
10671
10954
  var import_child_process5 = require("child_process");
10672
10955
  var import_sdk = require("@agentclientprotocol/sdk");
10673
10956
  init_logger();
10957
+ function getPromptCapabilityFlags(agentCapabilities) {
10958
+ const prompt = agentCapabilities?.promptCapabilities || {};
10959
+ return {
10960
+ image: prompt.image === true,
10961
+ audio: prompt.audio === true,
10962
+ embeddedContext: prompt.embeddedContext === true
10963
+ };
10964
+ }
10965
+ function getResourceNameFromUri(uri, fallback) {
10966
+ try {
10967
+ if (uri.startsWith("file://")) {
10968
+ return path12.basename(new URL(uri).pathname) || fallback;
10969
+ }
10970
+ return path12.basename(uri) || fallback;
10971
+ } catch {
10972
+ return fallback;
10973
+ }
10974
+ }
10975
+ function inputPartToResourceLink(part, fallbackName) {
10976
+ if (!part.uri) return null;
10977
+ return {
10978
+ type: "resource_link",
10979
+ uri: part.uri,
10980
+ name: getResourceNameFromUri(part.uri, fallbackName),
10981
+ ...part.mimeType ? { mimeType: part.mimeType } : {}
10982
+ };
10983
+ }
10984
+ function appendPromptText(promptParts, text) {
10985
+ const normalized = typeof text === "string" ? text.trim() : "";
10986
+ if (!normalized) return;
10987
+ const last = promptParts[promptParts.length - 1];
10988
+ if (last?.type === "text" && last.text === normalized) return;
10989
+ promptParts.push({ type: "text", text: normalized });
10990
+ }
10991
+ function buildAcpPromptParts(input, agentCapabilities) {
10992
+ const caps = getPromptCapabilityFlags(agentCapabilities);
10993
+ const promptParts = [];
10994
+ for (const part of input.parts) {
10995
+ if (part.type === "text") {
10996
+ promptParts.push({ type: "text", text: part.text });
10997
+ continue;
10998
+ }
10999
+ if (part.type === "image") {
11000
+ if (caps.image && part.data) {
11001
+ promptParts.push({
11002
+ type: "image",
11003
+ data: part.data,
11004
+ mimeType: part.mimeType,
11005
+ ...part.uri ? { uri: part.uri } : {}
11006
+ });
11007
+ continue;
11008
+ }
11009
+ const fallback = inputPartToResourceLink(part, "image");
11010
+ if (fallback) promptParts.push(fallback);
11011
+ appendPromptText(promptParts, part.alt || (!part.uri ? `Attached image (${part.mimeType})` : void 0));
11012
+ continue;
11013
+ }
11014
+ if (part.type === "audio") {
11015
+ if (caps.audio && part.data) {
11016
+ promptParts.push({
11017
+ type: "audio",
11018
+ data: part.data,
11019
+ mimeType: part.mimeType
11020
+ });
11021
+ continue;
11022
+ }
11023
+ const fallback = inputPartToResourceLink(part, "audio");
11024
+ if (fallback) promptParts.push(fallback);
11025
+ appendPromptText(promptParts, part.transcript || (!part.uri ? `Attached audio (${part.mimeType})` : void 0));
11026
+ continue;
11027
+ }
11028
+ if (part.type === "resource") {
11029
+ if (caps.embeddedContext && (part.text || part.data)) {
11030
+ promptParts.push({
11031
+ type: "resource",
11032
+ resource: part.text ? { uri: part.uri, text: part.text, mimeType: part.mimeType ?? null } : { uri: part.uri, blob: part.data || "", mimeType: part.mimeType ?? null }
11033
+ });
11034
+ continue;
11035
+ }
11036
+ const fallback = inputPartToResourceLink(part, part.name || "resource");
11037
+ if (fallback) promptParts.push(fallback);
11038
+ appendPromptText(promptParts, part.text || (!part.uri && part.name ? part.name : void 0));
11039
+ continue;
11040
+ }
11041
+ if (part.type === "video") {
11042
+ const fallback = inputPartToResourceLink(part, "video");
11043
+ if (fallback) promptParts.push(fallback);
11044
+ appendPromptText(promptParts, !part.uri ? `Attached video (${part.mimeType})` : void 0);
11045
+ }
11046
+ }
11047
+ if (!promptParts.some((part) => part.type === "text") && input.textFallback) {
11048
+ promptParts.unshift({ type: "text", text: input.textFallback });
11049
+ }
11050
+ return promptParts;
11051
+ }
10674
11052
  var AcpProviderInstance = class {
10675
11053
  constructor(provider, workingDir, cliArgs = []) {
10676
11054
  this.cliArgs = cliArgs;
@@ -10799,8 +11177,10 @@ var AcpProviderInstance = class {
10799
11177
  };
10800
11178
  }
10801
11179
  onEvent(event, data) {
10802
- if (event === "send_message" && data?.text) {
10803
- this.sendPrompt(data.text).catch(
11180
+ if (event === "send_message") {
11181
+ const input = normalizeInputEnvelope(data);
11182
+ const promptParts = buildAcpPromptParts(input, this.agentCapabilities);
11183
+ this.sendPrompt(input.textFallback, promptParts.length > 0 ? promptParts : void 0).catch(
10804
11184
  (e) => this.log.warn(`[${this.type}] sendPrompt error: ${e?.message}`)
10805
11185
  );
10806
11186
  } else if (event === "resolve_action") {
@@ -11225,18 +11605,34 @@ var AcpProviderInstance = class {
11225
11605
  this.log.warn(`[${this.type}] Cannot send prompt: no active connection/session`);
11226
11606
  return;
11227
11607
  }
11228
- let promptParts;
11229
- if (contentBlocks && contentBlocks.length > 0) {
11230
- promptParts = contentBlocks.map((b) => {
11231
- if (b.type === "text") return { type: "text", text: b.text };
11232
- if (b.type === "image") return { type: "image", data: b.data, mimeType: b.mimeType };
11233
- if (b.type === "resource_link") return { type: "resource_link", uri: b.uri, name: b.name };
11234
- if (b.type === "resource") return { type: "resource", resource: b.resource };
11235
- return { type: "text", text: flattenContent([b]) };
11236
- });
11237
- } else {
11238
- promptParts = [{ type: "text", text }];
11239
- }
11608
+ const promptParts = contentBlocks && contentBlocks.length > 0 ? contentBlocks.map((b) => {
11609
+ if (b.type === "text") return { type: "text", text: b.text };
11610
+ if (b.type === "image") {
11611
+ return {
11612
+ type: "image",
11613
+ data: b.data,
11614
+ mimeType: b.mimeType,
11615
+ ...b.uri ? { uri: b.uri } : {}
11616
+ };
11617
+ }
11618
+ if (b.type === "audio") {
11619
+ return {
11620
+ type: "audio",
11621
+ data: b.data,
11622
+ mimeType: b.mimeType
11623
+ };
11624
+ }
11625
+ if (b.type === "resource_link") {
11626
+ return {
11627
+ type: "resource_link",
11628
+ uri: b.uri,
11629
+ name: b.name,
11630
+ ...b.mimeType ? { mimeType: b.mimeType } : {}
11631
+ };
11632
+ }
11633
+ if (b.type === "resource") return { type: "resource", resource: b.resource };
11634
+ return { type: "text", text: flattenContent([b]) };
11635
+ }) : [{ type: "text", text }];
11240
11636
  this.messages.push({
11241
11637
  role: "user",
11242
11638
  content: contentBlocks && contentBlocks.length > 0 ? contentBlocks : text,
@@ -11300,6 +11696,13 @@ var AcpProviderInstance = class {
11300
11696
  this.partialBlocks.push({
11301
11697
  type: "image",
11302
11698
  data: content.data,
11699
+ mimeType: content.mimeType,
11700
+ ...content.uri ? { uri: content.uri } : {}
11701
+ });
11702
+ } else if (content.type === "audio") {
11703
+ this.partialBlocks.push({
11704
+ type: "audio",
11705
+ data: content.data,
11303
11706
  mimeType: content.mimeType
11304
11707
  });
11305
11708
  } else if (content.type === "resource_link") {
@@ -11691,7 +12094,7 @@ function resolveCliSessionBinding(provider, normalizedType, cliArgs, requestedRe
11691
12094
  };
11692
12095
  }
11693
12096
  if (!supportsExplicitSessionStart(resume)) {
11694
- return { cliArgs: baseArgs, launchMode: "manual" };
12097
+ return { cliArgs: baseArgs, launchMode: "new" };
11695
12098
  }
11696
12099
  const providerSessionId = crypto4.randomUUID();
11697
12100
  const newSessionArgs = expandResumeArgs(resume.newSessionArgs, providerSessionId);
@@ -11839,7 +12242,7 @@ var DaemonCliManager = class {
11839
12242
  async startSession(cliType, workingDir, cliArgs, initialModel, options) {
11840
12243
  const trimmed = (workingDir || "").trim();
11841
12244
  if (!trimmed) throw new Error("working directory required");
11842
- const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) : path12.resolve(trimmed);
12245
+ const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) : path13.resolve(trimmed);
11843
12246
  const normalizedType = this.providerLoader.resolveAlias(cliType);
11844
12247
  const provider = this.providerLoader.getByAlias(cliType);
11845
12248
  const key = crypto4.randomUUID();
@@ -11887,7 +12290,8 @@ ${installInfo}`
11887
12290
  instanceManager2.removeInstance(key);
11888
12291
  },
11889
12292
  sendMessage: async (text) => {
11890
- acpInstance.onEvent("send_message", { text });
12293
+ const input = normalizeInputEnvelope(text);
12294
+ acpInstance.onEvent("send_message", { input });
11891
12295
  },
11892
12296
  getStatus: () => {
11893
12297
  const state = acpInstance.getState();
@@ -12296,7 +12700,8 @@ Run 'adhdev doctor' for detailed diagnostics.`
12296
12700
  if (!found) throw new Error(`CLI agent not running: ${agentType}`);
12297
12701
  const { adapter, key } = found;
12298
12702
  if (action === "send_chat") {
12299
- const message = args.message || args.text;
12703
+ const input = normalizeInputEnvelope(args?.input ? { input: args.input } : args);
12704
+ const message = input.textFallback;
12300
12705
  if (!message) throw new Error("message required for send_chat");
12301
12706
  await adapter.sendMessage(message);
12302
12707
  return { success: true, status: "generating" };
@@ -12318,14 +12723,144 @@ Run 'adhdev doctor' for detailed diagnostics.`
12318
12723
  var import_child_process6 = require("child_process");
12319
12724
  var net = __toESM(require("net"));
12320
12725
  var os14 = __toESM(require("os"));
12321
- var path14 = __toESM(require("path"));
12726
+ var path15 = __toESM(require("path"));
12322
12727
 
12323
12728
  // src/providers/provider-loader.ts
12324
12729
  var fs6 = __toESM(require("fs"));
12325
- var path13 = __toESM(require("path"));
12730
+ var path14 = __toESM(require("path"));
12326
12731
  var os13 = __toESM(require("os"));
12327
12732
  var chokidar = __toESM(require("chokidar"));
12328
12733
  init_logger();
12734
+
12735
+ // src/providers/provider-schema.ts
12736
+ var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
12737
+ "type",
12738
+ "name",
12739
+ "category",
12740
+ "aliases",
12741
+ "cdpPorts",
12742
+ "targetFilter",
12743
+ "cli",
12744
+ "icon",
12745
+ "displayName",
12746
+ "install",
12747
+ "versionCommand",
12748
+ "testedVersions",
12749
+ "processNames",
12750
+ "launch",
12751
+ "paths",
12752
+ "extensionId",
12753
+ "extensionIdPattern",
12754
+ "extensionIdPattern_flags",
12755
+ "compatibility",
12756
+ "defaultScriptDir",
12757
+ "binary",
12758
+ "spawn",
12759
+ "approvalKeys",
12760
+ "patterns",
12761
+ "cleanOutput",
12762
+ "resume",
12763
+ "sessionProbe",
12764
+ "approvalPositiveHints",
12765
+ "scripts",
12766
+ "vscodeCommands",
12767
+ "inputMethod",
12768
+ "inputSelector",
12769
+ "webviewMatchText",
12770
+ "os",
12771
+ "versions",
12772
+ "overrides",
12773
+ "settings",
12774
+ "controls",
12775
+ "staticConfigOptions",
12776
+ "spawnArgBuilder",
12777
+ "auth",
12778
+ "contractVersion",
12779
+ "capabilities",
12780
+ "providerVersion",
12781
+ "status",
12782
+ "details",
12783
+ "sendDelayMs",
12784
+ "sendKey",
12785
+ "submitStrategy",
12786
+ "disableUpstream"
12787
+ ]);
12788
+ var VALUE_CONTROL_TYPES = /* @__PURE__ */ new Set(["select", "toggle", "cycle", "slider"]);
12789
+ function validateProviderDefinition(raw) {
12790
+ const errors = [];
12791
+ const warnings = [];
12792
+ if (!raw || typeof raw !== "object") {
12793
+ return { errors: ["Provider definition must be an object"], warnings };
12794
+ }
12795
+ const provider = raw;
12796
+ if (!provider.type) errors.push("Missing required field: type");
12797
+ if (!provider.name) errors.push("Missing required field: name");
12798
+ if (!provider.category) {
12799
+ errors.push("Missing required field: category");
12800
+ } else if (!["ide", "extension", "cli", "acp"].includes(String(provider.category))) {
12801
+ errors.push(`Invalid category: ${String(provider.category)}`);
12802
+ }
12803
+ for (const key of Object.keys(provider)) {
12804
+ if (!KNOWN_PROVIDER_FIELDS.has(key)) {
12805
+ warnings.push(`Unknown provider field: ${key}`);
12806
+ }
12807
+ }
12808
+ const category = provider.category;
12809
+ if (category === "cli" || category === "acp") {
12810
+ const spawn4 = provider.spawn;
12811
+ const command = spawn4 && typeof spawn4 === "object" ? spawn4.command : void 0;
12812
+ if (!spawn4 || typeof spawn4 !== "object") {
12813
+ errors.push(`${String(category).toUpperCase()}/CLI providers must have spawn config`);
12814
+ } else if (typeof command !== "string" || !command.trim()) {
12815
+ errors.push("spawn.command is required");
12816
+ }
12817
+ }
12818
+ if ((category === "ide" || category === "extension") && provider.cdpPorts !== void 0) {
12819
+ if (!Array.isArray(provider.cdpPorts) || provider.cdpPorts.length === 0) {
12820
+ warnings.push("IDE/Extension providers should have cdpPorts");
12821
+ }
12822
+ }
12823
+ if (category === "extension" && !provider.extensionId) {
12824
+ warnings.push("Extension providers should have extensionId");
12825
+ }
12826
+ for (const control of Array.isArray(provider.controls) ? provider.controls : []) {
12827
+ validateControl(control, errors);
12828
+ }
12829
+ return { errors, warnings };
12830
+ }
12831
+ function validateControl(control, errors) {
12832
+ if (!control || typeof control !== "object") {
12833
+ errors.push("controls: each control must be an object");
12834
+ return;
12835
+ }
12836
+ const id = typeof control.id === "string" && control.id.trim() ? control.id.trim() : "unknown";
12837
+ const prefix = `controls.${id}`;
12838
+ if (!control.id || !String(control.id).trim()) errors.push(`${prefix}: id is required`);
12839
+ if (!control.type) errors.push(`${prefix}: type is required`);
12840
+ if (!control.label || !String(control.label).trim()) errors.push(`${prefix}: label is required`);
12841
+ if (!control.placement) errors.push(`${prefix}: placement is required`);
12842
+ if (control.dynamic && !control.listScript) {
12843
+ errors.push(`${prefix}: dynamic controls require listScript`);
12844
+ }
12845
+ if (VALUE_CONTROL_TYPES.has(control.type) && !control.setScript) {
12846
+ errors.push(`${prefix}: ${control.type} controls require setScript`);
12847
+ }
12848
+ if (control.type === "action" && !control.invokeScript) {
12849
+ errors.push(`${prefix}: action controls require invokeScript`);
12850
+ }
12851
+ if (control.type === "slider") {
12852
+ if (typeof control.min !== "number" || typeof control.max !== "number") {
12853
+ errors.push(`${prefix}: slider controls require numeric min and max`);
12854
+ } else if (control.min > control.max) {
12855
+ errors.push(`${prefix}: slider min cannot exceed max`);
12856
+ }
12857
+ }
12858
+ if (control.readFrom !== void 0 && (typeof control.readFrom !== "string" || !control.readFrom.trim())) {
12859
+ errors.push(`${prefix}: readFrom must be a non-empty string when provided`);
12860
+ }
12861
+ }
12862
+
12863
+ // src/providers/provider-loader.ts
12329
12864
  var ProviderLoader = class _ProviderLoader {
12330
12865
  providers = /* @__PURE__ */ new Map();
12331
12866
  providerAvailability = /* @__PURE__ */ new Map();
@@ -12344,12 +12879,12 @@ var ProviderLoader = class _ProviderLoader {
12344
12879
  static META_FILE = ".meta.json";
12345
12880
  constructor(options) {
12346
12881
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
12347
- const defaultProvidersDir = path13.join(os13.homedir(), ".adhdev", "providers");
12882
+ const defaultProvidersDir = path14.join(os13.homedir(), ".adhdev", "providers");
12348
12883
  if (options?.userDir) {
12349
12884
  this.userDir = options.userDir;
12350
12885
  this.log(`Config 'providerDir' applied: ${this.userDir}`);
12351
12886
  } else {
12352
- const localRepoPath = path13.resolve(__dirname, "../../../../../adhdev-providers");
12887
+ const localRepoPath = path14.resolve(__dirname, "../../../../../adhdev-providers");
12353
12888
  if (fs6.existsSync(localRepoPath)) {
12354
12889
  this.userDir = localRepoPath;
12355
12890
  this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
@@ -12358,7 +12893,7 @@ var ProviderLoader = class _ProviderLoader {
12358
12893
  this.log(`Using default user providers directory: ${this.userDir}`);
12359
12894
  }
12360
12895
  }
12361
- this.upstreamDir = path13.join(defaultProvidersDir, ".upstream");
12896
+ this.upstreamDir = path14.join(defaultProvidersDir, ".upstream");
12362
12897
  this.disableUpstream = options?.disableUpstream ?? false;
12363
12898
  }
12364
12899
  log(msg) {
@@ -12388,7 +12923,7 @@ var ProviderLoader = class _ProviderLoader {
12388
12923
  * Canonical provider directory shape for a given root.
12389
12924
  */
12390
12925
  getProviderDir(root, category, type) {
12391
- return path13.join(root, category, type);
12926
+ return path14.join(root, category, type);
12392
12927
  }
12393
12928
  /**
12394
12929
  * Canonical user override directory for a provider.
@@ -12415,7 +12950,7 @@ var ProviderLoader = class _ProviderLoader {
12415
12950
  resolveProviderFile(type, ...segments) {
12416
12951
  const dir = this.findProviderDirInternal(type);
12417
12952
  if (!dir) return null;
12418
- return path13.join(dir, ...segments);
12953
+ return path14.join(dir, ...segments);
12419
12954
  }
12420
12955
  /**
12421
12956
  * Load all providers (3-tier priority)
@@ -12454,7 +12989,7 @@ var ProviderLoader = class _ProviderLoader {
12454
12989
  if (!fs6.existsSync(this.upstreamDir)) return false;
12455
12990
  try {
12456
12991
  return fs6.readdirSync(this.upstreamDir).some(
12457
- (d) => fs6.statSync(path13.join(this.upstreamDir, d)).isDirectory()
12992
+ (d) => fs6.statSync(path14.join(this.upstreamDir, d)).isDirectory()
12458
12993
  );
12459
12994
  } catch {
12460
12995
  return false;
@@ -12769,8 +13304,8 @@ var ProviderLoader = class _ProviderLoader {
12769
13304
  resolved._resolvedScriptDir = entry.scriptDir;
12770
13305
  resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
12771
13306
  if (providerDir) {
12772
- const fullDir = path13.join(providerDir, entry.scriptDir);
12773
- resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
13307
+ const fullDir = path14.join(providerDir, entry.scriptDir);
13308
+ resolved._resolvedScriptsPath = fs6.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
12774
13309
  }
12775
13310
  matched = true;
12776
13311
  }
@@ -12785,8 +13320,8 @@ var ProviderLoader = class _ProviderLoader {
12785
13320
  resolved._resolvedScriptDir = base.defaultScriptDir;
12786
13321
  resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
12787
13322
  if (providerDir) {
12788
- const fullDir = path13.join(providerDir, base.defaultScriptDir);
12789
- resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
13323
+ const fullDir = path14.join(providerDir, base.defaultScriptDir);
13324
+ resolved._resolvedScriptsPath = fs6.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
12790
13325
  }
12791
13326
  }
12792
13327
  resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
@@ -12803,8 +13338,8 @@ var ProviderLoader = class _ProviderLoader {
12803
13338
  resolved._resolvedScriptDir = dirOverride;
12804
13339
  resolved._resolvedScriptsSource = `versions:${range}`;
12805
13340
  if (providerDir) {
12806
- const fullDir = path13.join(providerDir, dirOverride);
12807
- resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
13341
+ const fullDir = path14.join(providerDir, dirOverride);
13342
+ resolved._resolvedScriptsPath = fs6.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
12808
13343
  }
12809
13344
  }
12810
13345
  } else if (override.scripts) {
@@ -12820,8 +13355,8 @@ var ProviderLoader = class _ProviderLoader {
12820
13355
  resolved._resolvedScriptDir = base.defaultScriptDir;
12821
13356
  resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
12822
13357
  if (providerDir) {
12823
- const fullDir = path13.join(providerDir, base.defaultScriptDir);
12824
- resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
13358
+ const fullDir = path14.join(providerDir, base.defaultScriptDir);
13359
+ resolved._resolvedScriptsPath = fs6.existsSync(path14.join(fullDir, "scripts.js")) ? path14.join(fullDir, "scripts.js") : fullDir;
12825
13360
  }
12826
13361
  }
12827
13362
  }
@@ -12846,14 +13381,14 @@ var ProviderLoader = class _ProviderLoader {
12846
13381
  this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
12847
13382
  return null;
12848
13383
  }
12849
- const dir = path13.join(providerDir, scriptDir);
13384
+ const dir = path14.join(providerDir, scriptDir);
12850
13385
  if (!fs6.existsSync(dir)) {
12851
13386
  this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
12852
13387
  return null;
12853
13388
  }
12854
13389
  const cached = this.scriptsCache.get(dir);
12855
13390
  if (cached) return cached;
12856
- const scriptsJs = path13.join(dir, "scripts.js");
13391
+ const scriptsJs = path14.join(dir, "scripts.js");
12857
13392
  if (fs6.existsSync(scriptsJs)) {
12858
13393
  try {
12859
13394
  delete require.cache[require.resolve(scriptsJs)];
@@ -12895,7 +13430,7 @@ var ProviderLoader = class _ProviderLoader {
12895
13430
  return;
12896
13431
  }
12897
13432
  if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
12898
- this.log(`File changed: ${path13.basename(filePath)}, reloading...`);
13433
+ this.log(`File changed: ${path14.basename(filePath)}, reloading...`);
12899
13434
  this.reload();
12900
13435
  }
12901
13436
  };
@@ -12950,7 +13485,7 @@ var ProviderLoader = class _ProviderLoader {
12950
13485
  }
12951
13486
  const https = require("https");
12952
13487
  const { execSync: execSync7 } = require("child_process");
12953
- const metaPath = path13.join(this.upstreamDir, _ProviderLoader.META_FILE);
13488
+ const metaPath = path14.join(this.upstreamDir, _ProviderLoader.META_FILE);
12954
13489
  let prevEtag = "";
12955
13490
  let prevTimestamp = 0;
12956
13491
  try {
@@ -13010,17 +13545,17 @@ var ProviderLoader = class _ProviderLoader {
13010
13545
  return { updated: false };
13011
13546
  }
13012
13547
  this.log("Downloading latest providers from GitHub...");
13013
- const tmpTar = path13.join(os13.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
13014
- const tmpExtract = path13.join(os13.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
13548
+ const tmpTar = path14.join(os13.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
13549
+ const tmpExtract = path14.join(os13.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
13015
13550
  await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
13016
13551
  fs6.mkdirSync(tmpExtract, { recursive: true });
13017
13552
  execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
13018
13553
  const extracted = fs6.readdirSync(tmpExtract);
13019
13554
  const rootDir = extracted.find(
13020
- (d) => fs6.statSync(path13.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
13555
+ (d) => fs6.statSync(path14.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
13021
13556
  );
13022
13557
  if (!rootDir) throw new Error("Unexpected tarball structure");
13023
- const sourceDir = path13.join(tmpExtract, rootDir);
13558
+ const sourceDir = path14.join(tmpExtract, rootDir);
13024
13559
  const backupDir = this.upstreamDir + ".bak";
13025
13560
  if (fs6.existsSync(this.upstreamDir)) {
13026
13561
  if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
@@ -13095,8 +13630,8 @@ var ProviderLoader = class _ProviderLoader {
13095
13630
  copyDirRecursive(src, dest) {
13096
13631
  fs6.mkdirSync(dest, { recursive: true });
13097
13632
  for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
13098
- const srcPath = path13.join(src, entry.name);
13099
- const destPath = path13.join(dest, entry.name);
13633
+ const srcPath = path14.join(src, entry.name);
13634
+ const destPath = path14.join(dest, entry.name);
13100
13635
  if (entry.isDirectory()) {
13101
13636
  this.copyDirRecursive(srcPath, destPath);
13102
13637
  } else {
@@ -13107,7 +13642,7 @@ var ProviderLoader = class _ProviderLoader {
13107
13642
  /** .meta.json save */
13108
13643
  writeMeta(metaPath, etag, timestamp) {
13109
13644
  try {
13110
- fs6.mkdirSync(path13.dirname(metaPath), { recursive: true });
13645
+ fs6.mkdirSync(path14.dirname(metaPath), { recursive: true });
13111
13646
  fs6.writeFileSync(metaPath, JSON.stringify({
13112
13647
  etag,
13113
13648
  timestamp,
@@ -13124,7 +13659,7 @@ var ProviderLoader = class _ProviderLoader {
13124
13659
  const scan = (d) => {
13125
13660
  try {
13126
13661
  for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
13127
- if (entry.isDirectory()) scan(path13.join(d, entry.name));
13662
+ if (entry.isDirectory()) scan(path14.join(d, entry.name));
13128
13663
  else if (entry.name === "provider.json") count++;
13129
13664
  }
13130
13665
  } catch {
@@ -13309,17 +13844,17 @@ var ProviderLoader = class _ProviderLoader {
13309
13844
  for (const root of searchRoots) {
13310
13845
  if (!fs6.existsSync(root)) continue;
13311
13846
  const candidate = this.getProviderDir(root, cat, type);
13312
- if (fs6.existsSync(path13.join(candidate, "provider.json"))) return candidate;
13313
- const catDir = path13.join(root, cat);
13847
+ if (fs6.existsSync(path14.join(candidate, "provider.json"))) return candidate;
13848
+ const catDir = path14.join(root, cat);
13314
13849
  if (fs6.existsSync(catDir)) {
13315
13850
  try {
13316
13851
  for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
13317
13852
  if (!entry.isDirectory()) continue;
13318
- const jsonPath = path13.join(catDir, entry.name, "provider.json");
13853
+ const jsonPath = path14.join(catDir, entry.name, "provider.json");
13319
13854
  if (fs6.existsSync(jsonPath)) {
13320
13855
  try {
13321
13856
  const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
13322
- if (data.type === type) return path13.join(catDir, entry.name);
13857
+ if (data.type === type) return path14.join(catDir, entry.name);
13323
13858
  } catch {
13324
13859
  }
13325
13860
  }
@@ -13336,7 +13871,7 @@ var ProviderLoader = class _ProviderLoader {
13336
13871
  * (template substitution is NOT applied here — scripts.js handles that)
13337
13872
  */
13338
13873
  buildScriptWrappersFromDir(dir) {
13339
- const scriptsJs = path13.join(dir, "scripts.js");
13874
+ const scriptsJs = path14.join(dir, "scripts.js");
13340
13875
  if (fs6.existsSync(scriptsJs)) {
13341
13876
  try {
13342
13877
  delete require.cache[require.resolve(scriptsJs)];
@@ -13350,7 +13885,7 @@ var ProviderLoader = class _ProviderLoader {
13350
13885
  for (const file of fs6.readdirSync(dir)) {
13351
13886
  if (!file.endsWith(".js")) continue;
13352
13887
  const scriptName = toCamel(file.replace(".js", ""));
13353
- const filePath = path13.join(dir, file);
13888
+ const filePath = path14.join(dir, file);
13354
13889
  result[scriptName] = (...args) => {
13355
13890
  try {
13356
13891
  let content = fs6.readFileSync(filePath, "utf-8");
@@ -13410,24 +13945,28 @@ var ProviderLoader = class _ProviderLoader {
13410
13945
  }
13411
13946
  const hasJson = entries.some((e) => e.name === "provider.json");
13412
13947
  if (hasJson) {
13413
- const jsonPath = path13.join(d, "provider.json");
13948
+ const jsonPath = path14.join(d, "provider.json");
13414
13949
  try {
13415
13950
  const raw = fs6.readFileSync(jsonPath, "utf-8");
13416
13951
  const mod = JSON.parse(raw);
13417
- if (!mod.type || !mod.name || !mod.category) {
13418
- this.log(`\u26A0 Invalid provider at ${jsonPath}: missing type/name/category`);
13952
+ if (typeof mod.extensionIdPattern === "string") {
13953
+ const flags = mod.extensionIdPattern_flags || "";
13954
+ mod.extensionIdPattern = new RegExp(mod.extensionIdPattern, flags);
13955
+ }
13956
+ const { extensionIdPattern_flags, extensionIdPattern, ...providerFields } = mod;
13957
+ const normalizedProvider = {
13958
+ ...providerFields,
13959
+ ...extensionIdPattern instanceof RegExp ? { extensionIdPattern } : {}
13960
+ };
13961
+ const validation = validateProviderDefinition(normalizedProvider);
13962
+ for (const warning of validation.warnings) {
13963
+ this.log(`\u26A0 ${jsonPath}: ${warning}`);
13964
+ }
13965
+ if (validation.errors.length > 0) {
13966
+ this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
13419
13967
  } else {
13420
- if (typeof mod.extensionIdPattern === "string") {
13421
- const flags = mod.extensionIdPattern_flags || "";
13422
- mod.extensionIdPattern = new RegExp(mod.extensionIdPattern, flags);
13423
- }
13424
- const { extensionIdPattern_flags, extensionIdPattern, ...providerFields } = mod;
13425
- const normalizedProvider = {
13426
- ...providerFields,
13427
- ...extensionIdPattern instanceof RegExp ? { extensionIdPattern } : {}
13428
- };
13429
13968
  const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
13430
- const scriptsPath = path13.join(d, "scripts.js");
13969
+ const scriptsPath = path14.join(d, "scripts.js");
13431
13970
  if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
13432
13971
  try {
13433
13972
  delete require.cache[require.resolve(scriptsPath)];
@@ -13453,7 +13992,7 @@ var ProviderLoader = class _ProviderLoader {
13453
13992
  if (!entry.isDirectory()) continue;
13454
13993
  if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
13455
13994
  if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
13456
- scan(path13.join(d, entry.name));
13995
+ scan(path14.join(d, entry.name));
13457
13996
  }
13458
13997
  }
13459
13998
  };
@@ -13711,8 +14250,8 @@ function detectCurrentWorkspace(ideId) {
13711
14250
  const appNameMap = getMacAppIdentifiers();
13712
14251
  const appName = appNameMap[ideId];
13713
14252
  if (appName) {
13714
- const storagePath = path14.join(
13715
- process.env.APPDATA || path14.join(os14.homedir(), "AppData", "Roaming"),
14253
+ const storagePath = path15.join(
14254
+ process.env.APPDATA || path15.join(os14.homedir(), "AppData", "Roaming"),
13716
14255
  appName,
13717
14256
  "storage.json"
13718
14257
  );
@@ -13890,9 +14429,9 @@ init_logger();
13890
14429
 
13891
14430
  // src/logging/command-log.ts
13892
14431
  var fs7 = __toESM(require("fs"));
13893
- var path15 = __toESM(require("path"));
14432
+ var path16 = __toESM(require("path"));
13894
14433
  var os15 = __toESM(require("os"));
13895
- var LOG_DIR2 = process.platform === "win32" ? path15.join(process.env.LOCALAPPDATA || process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path15.join(os15.homedir(), "Library", "Logs", "adhdev") : path15.join(os15.homedir(), ".local", "share", "adhdev", "logs");
14434
+ var LOG_DIR2 = process.platform === "win32" ? path16.join(process.env.LOCALAPPDATA || process.env.APPDATA || path16.join(os15.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path16.join(os15.homedir(), "Library", "Logs", "adhdev") : path16.join(os15.homedir(), ".local", "share", "adhdev", "logs");
13896
14435
  var MAX_FILE_SIZE = 5 * 1024 * 1024;
13897
14436
  var MAX_DAYS = 7;
13898
14437
  try {
@@ -13930,13 +14469,13 @@ function getDateStr2() {
13930
14469
  return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
13931
14470
  }
13932
14471
  var currentDate2 = getDateStr2();
13933
- var currentFile = path15.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
14472
+ var currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
13934
14473
  var writeCount2 = 0;
13935
14474
  function checkRotation() {
13936
14475
  const today = getDateStr2();
13937
14476
  if (today !== currentDate2) {
13938
14477
  currentDate2 = today;
13939
- currentFile = path15.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
14478
+ currentFile = path16.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
13940
14479
  cleanOldFiles();
13941
14480
  }
13942
14481
  }
@@ -13950,7 +14489,7 @@ function cleanOldFiles() {
13950
14489
  const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
13951
14490
  if (dateMatch && dateMatch[1] < cutoffStr) {
13952
14491
  try {
13953
- fs7.unlinkSync(path15.join(LOG_DIR2, file));
14492
+ fs7.unlinkSync(path16.join(LOG_DIR2, file));
13954
14493
  } catch {
13955
14494
  }
13956
14495
  }
@@ -14267,13 +14806,13 @@ var import_child_process7 = require("child_process");
14267
14806
  var import_child_process8 = require("child_process");
14268
14807
  var fs8 = __toESM(require("fs"));
14269
14808
  var os17 = __toESM(require("os"));
14270
- var path16 = __toESM(require("path"));
14809
+ var path17 = __toESM(require("path"));
14271
14810
  var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
14272
14811
  function getUpgradeLogPath() {
14273
14812
  const home = os17.homedir();
14274
- const dir = path16.join(home, ".adhdev");
14813
+ const dir = path17.join(home, ".adhdev");
14275
14814
  fs8.mkdirSync(dir, { recursive: true });
14276
- return path16.join(dir, "daemon-upgrade.log");
14815
+ return path17.join(dir, "daemon-upgrade.log");
14277
14816
  }
14278
14817
  function appendUpgradeLog(message) {
14279
14818
  const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
@@ -14313,7 +14852,7 @@ async function waitForPidExit(pid, timeoutMs) {
14313
14852
  }
14314
14853
  }
14315
14854
  function stopSessionHostProcesses(appName) {
14316
- const pidFile = path16.join(os17.homedir(), ".adhdev", `${appName}-session-host.pid`);
14855
+ const pidFile = path17.join(os17.homedir(), ".adhdev", `${appName}-session-host.pid`);
14317
14856
  try {
14318
14857
  if (fs8.existsSync(pidFile)) {
14319
14858
  const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
@@ -14342,7 +14881,7 @@ function stopSessionHostProcesses(appName) {
14342
14881
  }
14343
14882
  }
14344
14883
  function removeDaemonPidFile() {
14345
- const pidFile = path16.join(os17.homedir(), ".adhdev", "daemon.pid");
14884
+ const pidFile = path17.join(os17.homedir(), ".adhdev", "daemon.pid");
14346
14885
  try {
14347
14886
  fs8.unlinkSync(pidFile);
14348
14887
  } catch {
@@ -14353,7 +14892,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
14353
14892
  const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
14354
14893
  if (!npmRoot) return;
14355
14894
  const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
14356
- const binDir = process.platform === "win32" ? npmPrefix : path16.join(npmPrefix, "bin");
14895
+ const binDir = process.platform === "win32" ? npmPrefix : path17.join(npmPrefix, "bin");
14357
14896
  const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
14358
14897
  const binNames = /* @__PURE__ */ new Set([packageBaseName]);
14359
14898
  if (pkgName === "@adhdev/daemon-standalone") {
@@ -14361,25 +14900,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
14361
14900
  }
14362
14901
  if (pkgName.startsWith("@")) {
14363
14902
  const [scope, name] = pkgName.split("/");
14364
- const scopeDir = path16.join(npmRoot, scope);
14903
+ const scopeDir = path17.join(npmRoot, scope);
14365
14904
  if (!fs8.existsSync(scopeDir)) return;
14366
14905
  for (const entry of fs8.readdirSync(scopeDir)) {
14367
14906
  if (!entry.startsWith(`.${name}-`)) continue;
14368
- fs8.rmSync(path16.join(scopeDir, entry), { recursive: true, force: true });
14369
- appendUpgradeLog(`Removed stale scoped staging dir: ${path16.join(scopeDir, entry)}`);
14907
+ fs8.rmSync(path17.join(scopeDir, entry), { recursive: true, force: true });
14908
+ appendUpgradeLog(`Removed stale scoped staging dir: ${path17.join(scopeDir, entry)}`);
14370
14909
  }
14371
14910
  } else {
14372
14911
  for (const entry of fs8.readdirSync(npmRoot)) {
14373
14912
  if (!entry.startsWith(`.${pkgName}-`)) continue;
14374
- fs8.rmSync(path16.join(npmRoot, entry), { recursive: true, force: true });
14375
- appendUpgradeLog(`Removed stale staging dir: ${path16.join(npmRoot, entry)}`);
14913
+ fs8.rmSync(path17.join(npmRoot, entry), { recursive: true, force: true });
14914
+ appendUpgradeLog(`Removed stale staging dir: ${path17.join(npmRoot, entry)}`);
14376
14915
  }
14377
14916
  }
14378
14917
  if (fs8.existsSync(binDir)) {
14379
14918
  for (const entry of fs8.readdirSync(binDir)) {
14380
14919
  if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
14381
- fs8.rmSync(path16.join(binDir, entry), { recursive: true, force: true });
14382
- appendUpgradeLog(`Removed stale bin staging entry: ${path16.join(binDir, entry)}`);
14920
+ fs8.rmSync(path17.join(binDir, entry), { recursive: true, force: true });
14921
+ appendUpgradeLog(`Removed stale bin staging entry: ${path17.join(binDir, entry)}`);
14383
14922
  }
14384
14923
  }
14385
14924
  }
@@ -16257,11 +16796,11 @@ var ProviderInstanceManager = class {
16257
16796
 
16258
16797
  // src/providers/version-archive.ts
16259
16798
  var fs10 = __toESM(require("fs"));
16260
- var path17 = __toESM(require("path"));
16799
+ var path18 = __toESM(require("path"));
16261
16800
  var os18 = __toESM(require("os"));
16262
16801
  var import_child_process9 = require("child_process");
16263
16802
  var import_os3 = require("os");
16264
- var ARCHIVE_PATH = path17.join(os18.homedir(), ".adhdev", "version-history.json");
16803
+ var ARCHIVE_PATH = path18.join(os18.homedir(), ".adhdev", "version-history.json");
16265
16804
  var MAX_ENTRIES_PER_PROVIDER = 20;
16266
16805
  var VersionArchive = class {
16267
16806
  history = {};
@@ -16308,7 +16847,7 @@ var VersionArchive = class {
16308
16847
  }
16309
16848
  save() {
16310
16849
  try {
16311
- fs10.mkdirSync(path17.dirname(ARCHIVE_PATH), { recursive: true });
16850
+ fs10.mkdirSync(path18.dirname(ARCHIVE_PATH), { recursive: true });
16312
16851
  fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
16313
16852
  } catch {
16314
16853
  }
@@ -16365,7 +16904,7 @@ function checkPathExists2(paths) {
16365
16904
  for (const p of paths) {
16366
16905
  if (p.includes("*")) {
16367
16906
  const home = os18.homedir();
16368
- const resolved = p.replace(/\*/g, home.split(path17.sep).pop() || "");
16907
+ const resolved = p.replace(/\*/g, home.split(path18.sep).pop() || "");
16369
16908
  if (fs10.existsSync(resolved)) return resolved;
16370
16909
  } else {
16371
16910
  if (fs10.existsSync(p)) return p;
@@ -16375,7 +16914,7 @@ function checkPathExists2(paths) {
16375
16914
  }
16376
16915
  function getMacAppVersion(appPath) {
16377
16916
  if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
16378
- const plistPath = path17.join(appPath, "Contents", "Info.plist");
16917
+ const plistPath = path18.join(appPath, "Contents", "Info.plist");
16379
16918
  if (!fs10.existsSync(plistPath)) return null;
16380
16919
  const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
16381
16920
  return raw || null;
@@ -16401,7 +16940,7 @@ async function detectAllVersions(loader, archive) {
16401
16940
  const cliBin = provider.cli ? findBinary2(provider.cli) : null;
16402
16941
  let resolvedBin = cliBin;
16403
16942
  if (!resolvedBin && appPath && currentOs === "darwin") {
16404
- const bundled = path17.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
16943
+ const bundled = path18.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
16405
16944
  if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
16406
16945
  }
16407
16946
  info.installed = !!(appPath || resolvedBin);
@@ -16442,7 +16981,7 @@ async function detectAllVersions(loader, archive) {
16442
16981
  // src/daemon/dev-server.ts
16443
16982
  var http2 = __toESM(require("http"));
16444
16983
  var fs14 = __toESM(require("fs"));
16445
- var path21 = __toESM(require("path"));
16984
+ var path22 = __toESM(require("path"));
16446
16985
 
16447
16986
  // src/daemon/scaffold-template.ts
16448
16987
  function generateFiles(type, name, category, opts = {}) {
@@ -16778,7 +17317,7 @@ init_logger();
16778
17317
 
16779
17318
  // src/daemon/dev-cdp-handlers.ts
16780
17319
  var fs11 = __toESM(require("fs"));
16781
- var path18 = __toESM(require("path"));
17320
+ var path19 = __toESM(require("path"));
16782
17321
  init_logger();
16783
17322
  async function handleCdpEvaluate(ctx, req, res) {
16784
17323
  const body = await ctx.readBody(req);
@@ -16957,17 +17496,17 @@ async function handleScriptHints(ctx, type, _req, res) {
16957
17496
  return;
16958
17497
  }
16959
17498
  let scriptsPath = "";
16960
- const directScripts = path18.join(dir, "scripts.js");
17499
+ const directScripts = path19.join(dir, "scripts.js");
16961
17500
  if (fs11.existsSync(directScripts)) {
16962
17501
  scriptsPath = directScripts;
16963
17502
  } else {
16964
- const scriptsDir = path18.join(dir, "scripts");
17503
+ const scriptsDir = path19.join(dir, "scripts");
16965
17504
  if (fs11.existsSync(scriptsDir)) {
16966
17505
  const versions = fs11.readdirSync(scriptsDir).filter((d) => {
16967
- return fs11.statSync(path18.join(scriptsDir, d)).isDirectory();
17506
+ return fs11.statSync(path19.join(scriptsDir, d)).isDirectory();
16968
17507
  }).sort().reverse();
16969
17508
  for (const ver of versions) {
16970
- const p = path18.join(scriptsDir, ver, "scripts.js");
17509
+ const p = path19.join(scriptsDir, ver, "scripts.js");
16971
17510
  if (fs11.existsSync(p)) {
16972
17511
  scriptsPath = p;
16973
17512
  break;
@@ -17796,7 +18335,7 @@ async function handleDomContext(ctx, type, req, res) {
17796
18335
 
17797
18336
  // src/daemon/dev-cli-debug.ts
17798
18337
  var fs12 = __toESM(require("fs"));
17799
- var path19 = __toESM(require("path"));
18338
+ var path20 = __toESM(require("path"));
17800
18339
  function slugifyFixtureName(value) {
17801
18340
  const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
17802
18341
  return normalized || `fixture-${Date.now()}`;
@@ -17806,11 +18345,11 @@ function getCliFixtureDir(ctx, type) {
17806
18345
  if (!providerDir) {
17807
18346
  throw new Error(`Provider directory not found for '${type}'`);
17808
18347
  }
17809
- return path19.join(providerDir, "fixtures");
18348
+ return path20.join(providerDir, "fixtures");
17810
18349
  }
17811
18350
  function readCliFixture(ctx, type, name) {
17812
18351
  const fixtureDir = getCliFixtureDir(ctx, type);
17813
- const filePath = path19.join(fixtureDir, `${name}.json`);
18352
+ const filePath = path20.join(fixtureDir, `${name}.json`);
17814
18353
  if (!fs12.existsSync(filePath)) {
17815
18354
  throw new Error(`Fixture not found: ${filePath}`);
17816
18355
  }
@@ -18578,7 +19117,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
18578
19117
  },
18579
19118
  notes: typeof body?.notes === "string" ? body.notes : void 0
18580
19119
  };
18581
- const filePath = path19.join(fixtureDir, `${name}.json`);
19120
+ const filePath = path20.join(fixtureDir, `${name}.json`);
18582
19121
  fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
18583
19122
  ctx.json(res, 200, {
18584
19123
  saved: true,
@@ -18602,7 +19141,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
18602
19141
  return;
18603
19142
  }
18604
19143
  const fixtures = fs12.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
18605
- const fullPath = path19.join(fixtureDir, file);
19144
+ const fullPath = path20.join(fixtureDir, file);
18606
19145
  try {
18607
19146
  const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
18608
19147
  return {
@@ -18738,7 +19277,7 @@ async function handleCliRaw(ctx, req, res) {
18738
19277
 
18739
19278
  // src/daemon/dev-auto-implement.ts
18740
19279
  var fs13 = __toESM(require("fs"));
18741
- var path20 = __toESM(require("path"));
19280
+ var path21 = __toESM(require("path"));
18742
19281
  var os19 = __toESM(require("os"));
18743
19282
  function getAutoImplPid(ctx) {
18744
19283
  const pid = ctx.autoImplProcess?.pid;
@@ -18795,22 +19334,22 @@ function getLatestScriptVersionDir(scriptsDir) {
18795
19334
  if (!fs13.existsSync(scriptsDir)) return null;
18796
19335
  const versions = fs13.readdirSync(scriptsDir).filter((d) => {
18797
19336
  try {
18798
- return fs13.statSync(path20.join(scriptsDir, d)).isDirectory();
19337
+ return fs13.statSync(path21.join(scriptsDir, d)).isDirectory();
18799
19338
  } catch {
18800
19339
  return false;
18801
19340
  }
18802
19341
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
18803
19342
  if (versions.length === 0) return null;
18804
- return path20.join(scriptsDir, versions[0]);
19343
+ return path21.join(scriptsDir, versions[0]);
18805
19344
  }
18806
19345
  function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
18807
- const canonicalUserDir = path20.resolve(ctx.providerLoader.getUserProviderDir(category, type));
18808
- const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
18809
- const upstreamRoot = path20.resolve(ctx.providerLoader.getUpstreamDir());
18810
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
19346
+ const canonicalUserDir = path21.resolve(ctx.providerLoader.getUserProviderDir(category, type));
19347
+ const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
19348
+ const upstreamRoot = path21.resolve(ctx.providerLoader.getUpstreamDir());
19349
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path21.sep}`)) {
18811
19350
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
18812
19351
  }
18813
- if (path20.basename(desiredDir) !== type) {
19352
+ if (path21.basename(desiredDir) !== type) {
18814
19353
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
18815
19354
  }
18816
19355
  const sourceDir = ctx.findProviderDir(type);
@@ -18818,11 +19357,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
18818
19357
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
18819
19358
  }
18820
19359
  if (!fs13.existsSync(desiredDir)) {
18821
- fs13.mkdirSync(path20.dirname(desiredDir), { recursive: true });
19360
+ fs13.mkdirSync(path21.dirname(desiredDir), { recursive: true });
18822
19361
  fs13.cpSync(sourceDir, desiredDir, { recursive: true });
18823
19362
  ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
18824
19363
  }
18825
- const providerJson = path20.join(desiredDir, "provider.json");
19364
+ const providerJson = path21.join(desiredDir, "provider.json");
18826
19365
  if (!fs13.existsSync(providerJson)) {
18827
19366
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
18828
19367
  }
@@ -18845,13 +19384,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
18845
19384
  const refDir = ctx.findProviderDir(referenceType);
18846
19385
  if (!refDir || !fs13.existsSync(refDir)) return {};
18847
19386
  const referenceScripts = {};
18848
- const scriptsDir = path20.join(refDir, "scripts");
19387
+ const scriptsDir = path21.join(refDir, "scripts");
18849
19388
  const latestDir = getLatestScriptVersionDir(scriptsDir);
18850
19389
  if (!latestDir) return referenceScripts;
18851
19390
  for (const file of fs13.readdirSync(latestDir)) {
18852
19391
  if (!file.endsWith(".js")) continue;
18853
19392
  try {
18854
- referenceScripts[file] = fs13.readFileSync(path20.join(latestDir, file), "utf-8");
19393
+ referenceScripts[file] = fs13.readFileSync(path21.join(latestDir, file), "utf-8");
18855
19394
  } catch {
18856
19395
  }
18857
19396
  }
@@ -18959,9 +19498,9 @@ async function handleAutoImplement(ctx, type, req, res) {
18959
19498
  });
18960
19499
  const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
18961
19500
  const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
18962
- const tmpDir = path20.join(os19.tmpdir(), "adhdev-autoimpl");
19501
+ const tmpDir = path21.join(os19.tmpdir(), "adhdev-autoimpl");
18963
19502
  if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
18964
- const promptFile = path20.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
19503
+ const promptFile = path21.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
18965
19504
  fs13.writeFileSync(promptFile, prompt, "utf-8");
18966
19505
  ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
18967
19506
  const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
@@ -19398,7 +19937,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19398
19937
  setMode: "set_mode.js"
19399
19938
  };
19400
19939
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
19401
- const scriptsDir = path20.join(providerDir, "scripts");
19940
+ const scriptsDir = path21.join(providerDir, "scripts");
19402
19941
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
19403
19942
  if (latestScriptsDir) {
19404
19943
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -19409,7 +19948,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19409
19948
  for (const file of fs13.readdirSync(latestScriptsDir)) {
19410
19949
  if (file.endsWith(".js") && targetFileNames.has(file)) {
19411
19950
  try {
19412
- const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19951
+ const content = fs13.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
19413
19952
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
19414
19953
  lines.push("```javascript");
19415
19954
  lines.push(content);
@@ -19426,7 +19965,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19426
19965
  lines.push("");
19427
19966
  for (const file of refFiles) {
19428
19967
  try {
19429
- const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
19968
+ const content = fs13.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
19430
19969
  lines.push(`### \`${file}\` \u{1F512}`);
19431
19970
  lines.push("```javascript");
19432
19971
  lines.push(content);
@@ -19467,10 +20006,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19467
20006
  lines.push("");
19468
20007
  }
19469
20008
  }
19470
- const docsDir = path20.join(providerDir, "../../docs");
20009
+ const docsDir = path21.join(providerDir, "../../docs");
19471
20010
  const loadGuide = (name) => {
19472
20011
  try {
19473
- const p = path20.join(docsDir, name);
20012
+ const p = path21.join(docsDir, name);
19474
20013
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
19475
20014
  } catch {
19476
20015
  }
@@ -19707,7 +20246,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
19707
20246
  parseApproval: "parse_approval.js"
19708
20247
  };
19709
20248
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
19710
- const scriptsDir = path20.join(providerDir, "scripts");
20249
+ const scriptsDir = path21.join(providerDir, "scripts");
19711
20250
  const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
19712
20251
  if (latestScriptsDir) {
19713
20252
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -19719,7 +20258,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
19719
20258
  if (!file.endsWith(".js")) continue;
19720
20259
  if (!targetFileNames.has(file)) continue;
19721
20260
  try {
19722
- const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
20261
+ const content = fs13.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
19723
20262
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
19724
20263
  lines.push("```javascript");
19725
20264
  lines.push(content);
@@ -19735,7 +20274,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
19735
20274
  lines.push("");
19736
20275
  for (const file of refFiles) {
19737
20276
  try {
19738
- const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
20277
+ const content = fs13.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
19739
20278
  lines.push(`### \`${file}\` \u{1F512}`);
19740
20279
  lines.push("```javascript");
19741
20280
  lines.push(content);
@@ -19768,10 +20307,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
19768
20307
  lines.push("");
19769
20308
  }
19770
20309
  }
19771
- const docsDir = path20.join(providerDir, "../../docs");
20310
+ const docsDir = path21.join(providerDir, "../../docs");
19772
20311
  const loadGuide = (name) => {
19773
20312
  try {
19774
- const p = path20.join(docsDir, name);
20313
+ const p = path21.join(docsDir, name);
19775
20314
  if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
19776
20315
  } catch {
19777
20316
  }
@@ -20214,8 +20753,8 @@ var DevServer = class _DevServer {
20214
20753
  }
20215
20754
  getEndpointList() {
20216
20755
  return this.routes.map((r) => {
20217
- const path22 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
20218
- return `${r.method.padEnd(5)} ${path22}`;
20756
+ const path23 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
20757
+ return `${r.method.padEnd(5)} ${path23}`;
20219
20758
  });
20220
20759
  }
20221
20760
  async start(port = DEV_SERVER_PORT) {
@@ -20470,12 +21009,12 @@ var DevServer = class _DevServer {
20470
21009
  // ─── DevConsole SPA ───
20471
21010
  getConsoleDistDir() {
20472
21011
  const candidates = [
20473
- path21.resolve(__dirname, "../../web-devconsole/dist"),
20474
- path21.resolve(__dirname, "../../../web-devconsole/dist"),
20475
- path21.join(process.cwd(), "packages/web-devconsole/dist")
21012
+ path22.resolve(__dirname, "../../web-devconsole/dist"),
21013
+ path22.resolve(__dirname, "../../../web-devconsole/dist"),
21014
+ path22.join(process.cwd(), "packages/web-devconsole/dist")
20476
21015
  ];
20477
21016
  for (const dir of candidates) {
20478
- if (fs14.existsSync(path21.join(dir, "index.html"))) return dir;
21017
+ if (fs14.existsSync(path22.join(dir, "index.html"))) return dir;
20479
21018
  }
20480
21019
  return null;
20481
21020
  }
@@ -20485,7 +21024,7 @@ var DevServer = class _DevServer {
20485
21024
  this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
20486
21025
  return;
20487
21026
  }
20488
- const htmlPath = path21.join(distDir, "index.html");
21027
+ const htmlPath = path22.join(distDir, "index.html");
20489
21028
  try {
20490
21029
  const html = fs14.readFileSync(htmlPath, "utf-8");
20491
21030
  res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
@@ -20510,15 +21049,15 @@ var DevServer = class _DevServer {
20510
21049
  this.json(res, 404, { error: "Not found" });
20511
21050
  return;
20512
21051
  }
20513
- const safePath = path21.normalize(pathname).replace(/^\.\.\//, "");
20514
- const filePath = path21.join(distDir, safePath);
21052
+ const safePath = path22.normalize(pathname).replace(/^\.\.\//, "");
21053
+ const filePath = path22.join(distDir, safePath);
20515
21054
  if (!filePath.startsWith(distDir)) {
20516
21055
  this.json(res, 403, { error: "Forbidden" });
20517
21056
  return;
20518
21057
  }
20519
21058
  try {
20520
21059
  const content = fs14.readFileSync(filePath);
20521
- const ext = path21.extname(filePath);
21060
+ const ext = path22.extname(filePath);
20522
21061
  const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
20523
21062
  res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
20524
21063
  res.end(content);
@@ -20631,9 +21170,9 @@ var DevServer = class _DevServer {
20631
21170
  const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
20632
21171
  if (entry.isDirectory()) {
20633
21172
  files.push({ path: rel, size: 0, type: "dir" });
20634
- scan(path21.join(d, entry.name), rel);
21173
+ scan(path22.join(d, entry.name), rel);
20635
21174
  } else {
20636
- const stat = fs14.statSync(path21.join(d, entry.name));
21175
+ const stat = fs14.statSync(path22.join(d, entry.name));
20637
21176
  files.push({ path: rel, size: stat.size, type: "file" });
20638
21177
  }
20639
21178
  }
@@ -20656,7 +21195,7 @@ var DevServer = class _DevServer {
20656
21195
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
20657
21196
  return;
20658
21197
  }
20659
- const fullPath = path21.resolve(dir, path21.normalize(filePath));
21198
+ const fullPath = path22.resolve(dir, path22.normalize(filePath));
20660
21199
  if (!fullPath.startsWith(dir)) {
20661
21200
  this.json(res, 403, { error: "Forbidden" });
20662
21201
  return;
@@ -20681,14 +21220,14 @@ var DevServer = class _DevServer {
20681
21220
  this.json(res, 404, { error: `Provider directory not found: ${type}` });
20682
21221
  return;
20683
21222
  }
20684
- const fullPath = path21.resolve(dir, path21.normalize(filePath));
21223
+ const fullPath = path22.resolve(dir, path22.normalize(filePath));
20685
21224
  if (!fullPath.startsWith(dir)) {
20686
21225
  this.json(res, 403, { error: "Forbidden" });
20687
21226
  return;
20688
21227
  }
20689
21228
  try {
20690
21229
  if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
20691
- fs14.mkdirSync(path21.dirname(fullPath), { recursive: true });
21230
+ fs14.mkdirSync(path22.dirname(fullPath), { recursive: true });
20692
21231
  fs14.writeFileSync(fullPath, content, "utf-8");
20693
21232
  this.log(`File saved: ${fullPath} (${content.length} chars)`);
20694
21233
  this.providerLoader.reload();
@@ -20705,7 +21244,7 @@ var DevServer = class _DevServer {
20705
21244
  return;
20706
21245
  }
20707
21246
  for (const name of ["scripts.js", "provider.json"]) {
20708
- const p = path21.join(dir, name);
21247
+ const p = path22.join(dir, name);
20709
21248
  if (fs14.existsSync(p)) {
20710
21249
  const source = fs14.readFileSync(p, "utf-8");
20711
21250
  this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
@@ -20726,8 +21265,8 @@ var DevServer = class _DevServer {
20726
21265
  this.json(res, 404, { error: `Provider not found: ${type}` });
20727
21266
  return;
20728
21267
  }
20729
- const target = fs14.existsSync(path21.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
20730
- const targetPath = path21.join(dir, target);
21268
+ const target = fs14.existsSync(path22.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
21269
+ const targetPath = path22.join(dir, target);
20731
21270
  try {
20732
21271
  if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
20733
21272
  fs14.writeFileSync(targetPath, source, "utf-8");
@@ -20755,22 +21294,9 @@ var DevServer = class _DevServer {
20755
21294
  const warnings = [];
20756
21295
  try {
20757
21296
  const config = typeof content === "string" ? JSON.parse(content) : content;
20758
- if (!config.type) errors.push("Missing required field: type");
20759
- if (!config.name) errors.push("Missing required field: name");
20760
- if (!config.category) errors.push("Missing required field: category");
20761
- else if (!["ide", "extension", "cli", "acp"].includes(config.category)) errors.push(`Invalid category: ${config.category}`);
20762
- if (config.category === "ide" || config.category === "extension") {
20763
- if (!config.cdpPorts || !Array.isArray(config.cdpPorts) || config.cdpPorts.length === 0)
20764
- warnings.push("IDE/Extension providers should have cdpPorts");
20765
- if (config.category === "extension" && !config.extensionId)
20766
- warnings.push("Extension providers should have extensionId");
20767
- }
20768
- if (config.category === "acp" || config.category === "cli") {
20769
- if (!config.spawn) errors.push("ACP/CLI providers must have spawn config");
20770
- else {
20771
- if (!config.spawn.command) errors.push("spawn.command is required");
20772
- }
20773
- }
21297
+ const validation = validateProviderDefinition(config);
21298
+ errors.push(...validation.errors);
21299
+ warnings.push(...validation.warnings);
20774
21300
  if (config.settings) {
20775
21301
  for (const [key, val] of Object.entries(config.settings)) {
20776
21302
  const s = val;
@@ -20887,7 +21413,7 @@ var DevServer = class _DevServer {
20887
21413
  }
20888
21414
  let targetDir;
20889
21415
  targetDir = this.providerLoader.getUserProviderDir(category, type);
20890
- const jsonPath = path21.join(targetDir, "provider.json");
21416
+ const jsonPath = path22.join(targetDir, "provider.json");
20891
21417
  if (fs14.existsSync(jsonPath)) {
20892
21418
  this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
20893
21419
  return;
@@ -20899,8 +21425,8 @@ var DevServer = class _DevServer {
20899
21425
  const createdFiles = ["provider.json"];
20900
21426
  if (result.files) {
20901
21427
  for (const [relPath, content] of Object.entries(result.files)) {
20902
- const fullPath = path21.join(targetDir, relPath);
20903
- fs14.mkdirSync(path21.dirname(fullPath), { recursive: true });
21428
+ const fullPath = path22.join(targetDir, relPath);
21429
+ fs14.mkdirSync(path22.dirname(fullPath), { recursive: true });
20904
21430
  fs14.writeFileSync(fullPath, content, "utf-8");
20905
21431
  createdFiles.push(relPath);
20906
21432
  }
@@ -20953,22 +21479,22 @@ var DevServer = class _DevServer {
20953
21479
  if (!fs14.existsSync(scriptsDir)) return null;
20954
21480
  const versions = fs14.readdirSync(scriptsDir).filter((d) => {
20955
21481
  try {
20956
- return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
21482
+ return fs14.statSync(path22.join(scriptsDir, d)).isDirectory();
20957
21483
  } catch {
20958
21484
  return false;
20959
21485
  }
20960
21486
  }).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
20961
21487
  if (versions.length === 0) return null;
20962
- return path21.join(scriptsDir, versions[0]);
21488
+ return path22.join(scriptsDir, versions[0]);
20963
21489
  }
20964
21490
  resolveAutoImplWritableProviderDir(category, type, requestedDir) {
20965
- const canonicalUserDir = path21.resolve(this.providerLoader.getUserProviderDir(category, type));
20966
- const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
20967
- const upstreamRoot = path21.resolve(this.providerLoader.getUpstreamDir());
20968
- if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path21.sep}`)) {
21491
+ const canonicalUserDir = path22.resolve(this.providerLoader.getUserProviderDir(category, type));
21492
+ const desiredDir = requestedDir ? path22.resolve(requestedDir) : canonicalUserDir;
21493
+ const upstreamRoot = path22.resolve(this.providerLoader.getUpstreamDir());
21494
+ if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path22.sep}`)) {
20969
21495
  return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
20970
21496
  }
20971
- if (path21.basename(desiredDir) !== type) {
21497
+ if (path22.basename(desiredDir) !== type) {
20972
21498
  return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
20973
21499
  }
20974
21500
  const sourceDir = this.findProviderDir(type);
@@ -20976,11 +21502,11 @@ var DevServer = class _DevServer {
20976
21502
  return { dir: null, reason: `Provider source directory not found for '${type}'` };
20977
21503
  }
20978
21504
  if (!fs14.existsSync(desiredDir)) {
20979
- fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
21505
+ fs14.mkdirSync(path22.dirname(desiredDir), { recursive: true });
20980
21506
  fs14.cpSync(sourceDir, desiredDir, { recursive: true });
20981
21507
  this.log(`Auto-implement writable copy created: ${desiredDir}`);
20982
21508
  }
20983
- const providerJson = path21.join(desiredDir, "provider.json");
21509
+ const providerJson = path22.join(desiredDir, "provider.json");
20984
21510
  if (!fs14.existsSync(providerJson)) {
20985
21511
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
20986
21512
  }
@@ -21028,7 +21554,7 @@ var DevServer = class _DevServer {
21028
21554
  setMode: "set_mode.js"
21029
21555
  };
21030
21556
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
21031
- const scriptsDir = path21.join(providerDir, "scripts");
21557
+ const scriptsDir = path22.join(providerDir, "scripts");
21032
21558
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
21033
21559
  if (latestScriptsDir) {
21034
21560
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -21039,7 +21565,7 @@ var DevServer = class _DevServer {
21039
21565
  for (const file of fs14.readdirSync(latestScriptsDir)) {
21040
21566
  if (file.endsWith(".js") && targetFileNames.has(file)) {
21041
21567
  try {
21042
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
21568
+ const content = fs14.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
21043
21569
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
21044
21570
  lines.push("```javascript");
21045
21571
  lines.push(content);
@@ -21056,7 +21582,7 @@ var DevServer = class _DevServer {
21056
21582
  lines.push("");
21057
21583
  for (const file of refFiles) {
21058
21584
  try {
21059
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
21585
+ const content = fs14.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
21060
21586
  lines.push(`### \`${file}\` \u{1F512}`);
21061
21587
  lines.push("```javascript");
21062
21588
  lines.push(content);
@@ -21097,10 +21623,10 @@ var DevServer = class _DevServer {
21097
21623
  lines.push("");
21098
21624
  }
21099
21625
  }
21100
- const docsDir = path21.join(providerDir, "../../docs");
21626
+ const docsDir = path22.join(providerDir, "../../docs");
21101
21627
  const loadGuide = (name) => {
21102
21628
  try {
21103
- const p = path21.join(docsDir, name);
21629
+ const p = path22.join(docsDir, name);
21104
21630
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
21105
21631
  } catch {
21106
21632
  }
@@ -21274,7 +21800,7 @@ var DevServer = class _DevServer {
21274
21800
  parseApproval: "parse_approval.js"
21275
21801
  };
21276
21802
  const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
21277
- const scriptsDir = path21.join(providerDir, "scripts");
21803
+ const scriptsDir = path22.join(providerDir, "scripts");
21278
21804
  const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
21279
21805
  if (latestScriptsDir) {
21280
21806
  lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
@@ -21286,7 +21812,7 @@ var DevServer = class _DevServer {
21286
21812
  if (!file.endsWith(".js")) continue;
21287
21813
  if (!targetFileNames.has(file)) continue;
21288
21814
  try {
21289
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
21815
+ const content = fs14.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
21290
21816
  lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
21291
21817
  lines.push("```javascript");
21292
21818
  lines.push(content);
@@ -21302,7 +21828,7 @@ var DevServer = class _DevServer {
21302
21828
  lines.push("");
21303
21829
  for (const file of refFiles) {
21304
21830
  try {
21305
- const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
21831
+ const content = fs14.readFileSync(path22.join(latestScriptsDir, file), "utf-8");
21306
21832
  lines.push(`### \`${file}\` \u{1F512}`);
21307
21833
  lines.push("```javascript");
21308
21834
  lines.push(content);
@@ -21335,10 +21861,10 @@ var DevServer = class _DevServer {
21335
21861
  lines.push("");
21336
21862
  }
21337
21863
  }
21338
- const docsDir = path21.join(providerDir, "../../docs");
21864
+ const docsDir = path22.join(providerDir, "../../docs");
21339
21865
  const loadGuide = (name) => {
21340
21866
  try {
21341
- const p = path21.join(docsDir, name);
21867
+ const p = path22.join(docsDir, name);
21342
21868
  if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
21343
21869
  } catch {
21344
21870
  }
@@ -22046,6 +22572,67 @@ async function listHostedCliRuntimes(endpoint) {
22046
22572
  }
22047
22573
  }
22048
22574
 
22575
+ // src/session-host/runtime-surface.ts
22576
+ var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
22577
+ function isSessionHostLiveRuntime(record) {
22578
+ const lifecycle = String(record?.lifecycle || "").trim();
22579
+ return LIVE_LIFECYCLES.has(lifecycle);
22580
+ }
22581
+ function getSessionHostRecoveryLabel(meta) {
22582
+ const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
22583
+ if (!recoveryState) return null;
22584
+ if (recoveryState === "auto_resumed") return "restored after restart";
22585
+ if (recoveryState === "resume_failed") return "restore failed";
22586
+ if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
22587
+ if (recoveryState === "orphan_snapshot") return "snapshot recovered";
22588
+ return recoveryState.replace(/_/g, " ");
22589
+ }
22590
+ function isSessionHostRecoverySnapshot(record) {
22591
+ if (!record) return false;
22592
+ if (isSessionHostLiveRuntime(record)) return false;
22593
+ const lifecycle = String(record.lifecycle || "").trim();
22594
+ if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
22595
+ return false;
22596
+ }
22597
+ const meta = record.meta || void 0;
22598
+ if (meta?.restoredFromStorage === true) return true;
22599
+ return getSessionHostRecoveryLabel(meta) !== null;
22600
+ }
22601
+ function getSessionHostSurfaceKind(record) {
22602
+ if (isSessionHostLiveRuntime(record)) return "live_runtime";
22603
+ if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
22604
+ return "inactive_record";
22605
+ }
22606
+ function partitionSessionHostRecords(records) {
22607
+ const liveRuntimes = [];
22608
+ const recoverySnapshots = [];
22609
+ const inactiveRecords = [];
22610
+ for (const record of records) {
22611
+ const kind = getSessionHostSurfaceKind(record);
22612
+ if (kind === "live_runtime") {
22613
+ liveRuntimes.push(record);
22614
+ } else if (kind === "recovery_snapshot") {
22615
+ recoverySnapshots.push(record);
22616
+ } else {
22617
+ inactiveRecords.push(record);
22618
+ }
22619
+ }
22620
+ return {
22621
+ liveRuntimes,
22622
+ recoverySnapshots,
22623
+ inactiveRecords
22624
+ };
22625
+ }
22626
+ function partitionSessionHostDiagnosticsSessions(records) {
22627
+ return partitionSessionHostRecords(records || []);
22628
+ }
22629
+
22630
+ // src/session-host/startup-restore-policy.js
22631
+ function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
22632
+ const raw = typeof env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";
22633
+ return raw === "1" || raw === "true" || raw === "yes";
22634
+ }
22635
+
22049
22636
  // src/installer.ts
22050
22637
  var import_child_process10 = require("child_process");
22051
22638
  var EXTENSION_CATALOG = [
@@ -22552,6 +23139,7 @@ async function shutdownDaemonComponents(components) {
22552
23139
  detectIDEs,
22553
23140
  ensureSessionHostReady,
22554
23141
  findCdpManager,
23142
+ flattenMessageParts,
22555
23143
  forwardAgentStreamsToIdeInstance,
22556
23144
  getAIExtensions,
22557
23145
  getAvailableIdeIds,
@@ -22565,6 +23153,8 @@ async function shutdownDaemonComponents(components) {
22565
23153
  getRecentDebugTrace,
22566
23154
  getRecentLogs,
22567
23155
  getSavedProviderSessions,
23156
+ getSessionHostRecoveryLabel,
23157
+ getSessionHostSurfaceKind,
22568
23158
  getWorkspaceState,
22569
23159
  hasCdpManager,
22570
23160
  initDaemonComponents,
@@ -22575,6 +23165,8 @@ async function shutdownDaemonComponents(components) {
22575
23165
  isIdeRunning,
22576
23166
  isManagedStatusWaiting,
22577
23167
  isManagedStatusWorking,
23168
+ isSessionHostLiveRuntime,
23169
+ isSessionHostRecoverySnapshot,
22578
23170
  isSetupComplete,
22579
23171
  killIdeProcess,
22580
23172
  launchIDE,
@@ -22586,7 +23178,11 @@ async function shutdownDaemonComponents(components) {
22586
23178
  markSetupComplete,
22587
23179
  maybeRunDaemonUpgradeHelperFromEnv,
22588
23180
  normalizeActiveChatData,
23181
+ normalizeInputEnvelope,
22589
23182
  normalizeManagedStatus,
23183
+ normalizeMessageParts,
23184
+ partitionSessionHostDiagnosticsSessions,
23185
+ partitionSessionHostRecords,
22590
23186
  probeCdpPort,
22591
23187
  readChatHistory,
22592
23188
  recordDebugTrace,
@@ -22601,6 +23197,7 @@ async function shutdownDaemonComponents(components) {
22601
23197
  setDebugRuntimeConfig,
22602
23198
  setLogLevel,
22603
23199
  setupIdeInstance,
23200
+ shouldAutoRestoreHostedSessionsOnStartup,
22604
23201
  shouldCollectTraceCategory,
22605
23202
  shutdownDaemonComponents,
22606
23203
  spawnDetachedDaemonUpgradeHelper,