@adhdev/daemon-core 0.8.57 → 0.8.59

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 (75) hide show
  1. package/dist/agent-stream/types.d.ts +3 -4
  2. package/dist/boot/daemon-lifecycle.d.ts +1 -0
  3. package/dist/commands/handler.d.ts +1 -0
  4. package/dist/commands/router.d.ts +1 -0
  5. package/dist/commands/stream-commands.d.ts +3 -0
  6. package/dist/config/chat-history.d.ts +3 -0
  7. package/dist/config/config.d.ts +3 -0
  8. package/dist/config/provider-source-config.d.ts +23 -0
  9. package/dist/config/recent-activity.d.ts +2 -1
  10. package/dist/config/saved-sessions.d.ts +2 -1
  11. package/dist/daemon/dev-server-types.d.ts +1 -0
  12. package/dist/daemon/dev-server.d.ts +4 -0
  13. package/dist/index.d.ts +3 -1
  14. package/dist/index.js +876 -337
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +875 -337
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/providers/acp-provider-instance.d.ts +8 -2
  19. package/dist/providers/cli-provider-instance.d.ts +10 -0
  20. package/dist/providers/contracts.d.ts +4 -2
  21. package/dist/providers/extension-provider-instance.d.ts +1 -2
  22. package/dist/providers/provider-instance.d.ts +3 -4
  23. package/dist/providers/provider-loader.d.ts +14 -1
  24. package/dist/providers/provider-patch-state.d.ts +23 -0
  25. package/dist/providers/summary-metadata.d.ts +22 -0
  26. package/dist/shared-types.d.ts +15 -9
  27. package/dist/status/snapshot.d.ts +16 -1
  28. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  29. package/package.json +1 -1
  30. package/src/agent-stream/forward.ts +1 -2
  31. package/src/agent-stream/manager.ts +2 -1
  32. package/src/agent-stream/provider-adapter.ts +7 -3
  33. package/src/agent-stream/types.d.ts +3 -4
  34. package/src/agent-stream/types.ts +3 -4
  35. package/src/boot/daemon-lifecycle.ts +13 -3
  36. package/src/commands/cli-manager.ts +10 -5
  37. package/src/commands/handler.ts +3 -0
  38. package/src/commands/router.ts +160 -26
  39. package/src/commands/stream-commands.ts +60 -2
  40. package/src/config/chat-history.ts +39 -0
  41. package/src/config/config.d.ts +3 -0
  42. package/src/config/config.ts +19 -3
  43. package/src/config/provider-source-config.ts +42 -0
  44. package/src/config/recent-activity.d.ts +2 -1
  45. package/src/config/recent-activity.ts +12 -1
  46. package/src/config/saved-sessions.d.ts +2 -1
  47. package/src/config/saved-sessions.ts +12 -2
  48. package/src/daemon/dev-auto-implement.ts +1 -14
  49. package/src/daemon/dev-cli-debug.ts +0 -1
  50. package/src/daemon/dev-server-types.ts +1 -0
  51. package/src/daemon/dev-server.ts +46 -21
  52. package/src/daemon/scaffold-template.ts +8 -1
  53. package/src/index.d.ts +1 -1
  54. package/src/index.ts +4 -0
  55. package/src/providers/acp-provider-instance.d.ts +8 -2
  56. package/src/providers/acp-provider-instance.ts +80 -23
  57. package/src/providers/cli-provider-instance.ts +42 -22
  58. package/src/providers/contracts.d.ts +3 -2
  59. package/src/providers/contracts.ts +7 -4
  60. package/src/providers/control-effects.ts +3 -4
  61. package/src/providers/extension-provider-instance.d.ts +1 -2
  62. package/src/providers/extension-provider-instance.ts +26 -14
  63. package/src/providers/ide-provider-instance.ts +28 -15
  64. package/src/providers/provider-instance.d.ts +3 -4
  65. package/src/providers/provider-instance.ts +6 -7
  66. package/src/providers/provider-loader.d.ts +4 -1
  67. package/src/providers/provider-loader.ts +61 -23
  68. package/src/providers/provider-patch-state.ts +91 -0
  69. package/src/providers/provider-schema.ts +3 -0
  70. package/src/providers/summary-metadata.ts +118 -0
  71. package/src/shared-types.d.ts +15 -9
  72. package/src/shared-types.ts +17 -9
  73. package/src/status/builders.ts +18 -13
  74. package/src/status/reporter.ts +2 -4
  75. package/src/status/snapshot.ts +60 -2
package/dist/index.js CHANGED
@@ -40,9 +40,16 @@ __export(config_exports, {
40
40
  loadConfig: () => loadConfig,
41
41
  markSetupComplete: () => markSetupComplete,
42
42
  resetConfig: () => resetConfig,
43
+ resolveProviderSourceMode: () => resolveProviderSourceMode,
43
44
  saveConfig: () => saveConfig,
44
45
  updateConfig: () => updateConfig
45
46
  });
47
+ function resolveProviderSourceMode(providerSourceMode, legacyDisableUpstream) {
48
+ if (providerSourceMode === "normal" || providerSourceMode === "no-upstream") {
49
+ return providerSourceMode;
50
+ }
51
+ return legacyDisableUpstream === true ? "no-upstream" : "normal";
52
+ }
46
53
  function isPlainObject(value) {
47
54
  return !!value && typeof value === "object" && !Array.isArray(value);
48
55
  }
@@ -80,7 +87,7 @@ function normalizeConfig(raw) {
80
87
  registeredMachineId: asOptionalString(parsed.registeredMachineId),
81
88
  providerSettings: isPlainObject(parsed.providerSettings) ? parsed.providerSettings : {},
82
89
  ideSettings: isPlainObject(parsed.ideSettings) ? parsed.ideSettings : {},
83
- disableUpstream: asBoolean(parsed.disableUpstream, DEFAULT_CONFIG.disableUpstream ?? false),
90
+ providerSourceMode: resolveProviderSourceMode(parsed.providerSourceMode, parsed.disableUpstream),
84
91
  providerDir: asOptionalString(parsed.providerDir),
85
92
  terminalSizingMode: parsed.terminalSizingMode === "fit" ? "fit" : "measured"
86
93
  };
@@ -229,7 +236,7 @@ var init_config = __esm({
229
236
  registeredMachineId: void 0,
230
237
  providerSettings: {},
231
238
  ideSettings: {},
232
- disableUpstream: false,
239
+ providerSourceMode: "normal",
233
240
  terminalSizingMode: "measured"
234
241
  };
235
242
  MACHINE_ID_PREFIX = "mach_";
@@ -1897,7 +1904,7 @@ var init_provider_cli_adapter = __esm({
1897
1904
  `[${this.cliType}] Waiting for interactive prompt: hasPrompt=${hasPrompt} stableMs=${stableMs} recentOutputMs=${recentlyOutput} status=${status} startup=${startupLikelyActive} screen=${JSON.stringify(summarizeCliTraceText(screenText, 220)).slice(0, 260)}`
1898
1905
  );
1899
1906
  }
1900
- await new Promise((resolve12) => setTimeout(resolve12, 50));
1907
+ await new Promise((resolve11) => setTimeout(resolve11, 50));
1901
1908
  }
1902
1909
  const finalScreenText = this.terminalScreen.getText() || "";
1903
1910
  LOG.warn(
@@ -2470,7 +2477,7 @@ ${data.message || ""}`.trim();
2470
2477
  const deadline = Date.now() + 1e4;
2471
2478
  while (this.startupParseGate && Date.now() < deadline) {
2472
2479
  this.resolveStartupState("send_wait");
2473
- await new Promise((resolve12) => setTimeout(resolve12, 50));
2480
+ await new Promise((resolve11) => setTimeout(resolve11, 50));
2474
2481
  }
2475
2482
  }
2476
2483
  await this.waitForInteractivePrompt();
@@ -2540,12 +2547,12 @@ ${data.message || ""}`.trim();
2540
2547
  if (this.isWaitingForResponse) this.finishResponse();
2541
2548
  }, this.timeouts.maxResponse);
2542
2549
  };
2543
- await new Promise((resolve12) => {
2550
+ await new Promise((resolve11) => {
2544
2551
  let resolved = false;
2545
2552
  const resolveOnce = () => {
2546
2553
  if (resolved) return;
2547
2554
  resolved = true;
2548
- resolve12();
2555
+ resolve11();
2549
2556
  };
2550
2557
  const submit = () => {
2551
2558
  if (!this.ptyProcess) {
@@ -2719,17 +2726,17 @@ ${data.message || ""}`.trim();
2719
2726
  }
2720
2727
  }
2721
2728
  waitForStopped(timeoutMs) {
2722
- return new Promise((resolve12) => {
2729
+ return new Promise((resolve11) => {
2723
2730
  const startedAt = Date.now();
2724
2731
  const timer = setInterval(() => {
2725
2732
  if (!this.ptyProcess || this.currentStatus === "stopped") {
2726
2733
  clearInterval(timer);
2727
- resolve12(true);
2734
+ resolve11(true);
2728
2735
  return;
2729
2736
  }
2730
2737
  if (Date.now() - startedAt >= timeoutMs) {
2731
2738
  clearInterval(timer);
2732
- resolve12(false);
2739
+ resolve11(false);
2733
2740
  }
2734
2741
  }, 100);
2735
2742
  });
@@ -3084,6 +3091,7 @@ __export(index_exports, {
3084
3091
  normalizeInputEnvelope: () => normalizeInputEnvelope,
3085
3092
  normalizeManagedStatus: () => normalizeManagedStatus,
3086
3093
  normalizeMessageParts: () => normalizeMessageParts,
3094
+ parseProviderSourceConfigUpdate: () => parseProviderSourceConfigUpdate,
3087
3095
  partitionSessionHostDiagnosticsSessions: () => partitionSessionHostDiagnosticsSessions,
3088
3096
  partitionSessionHostRecords: () => partitionSessionHostRecords,
3089
3097
  probeCdpPort: () => probeCdpPort,
@@ -3279,6 +3287,70 @@ function setDefaultWorkspaceId(config, id) {
3279
3287
 
3280
3288
  // src/config/recent-activity.ts
3281
3289
  var path2 = __toESM(require("path"));
3290
+
3291
+ // src/providers/summary-metadata.ts
3292
+ function normalizeSummaryItem(item) {
3293
+ if (!item || typeof item !== "object") return null;
3294
+ const id = String(item.id || "").trim();
3295
+ const value = String(item.value || "").trim();
3296
+ if (!id || !value) return null;
3297
+ const normalized = {
3298
+ id,
3299
+ value
3300
+ };
3301
+ if (typeof item.label === "string" && item.label.trim()) normalized.label = item.label.trim();
3302
+ if (typeof item.shortValue === "string" && item.shortValue.trim()) normalized.shortValue = item.shortValue.trim();
3303
+ if (typeof item.icon === "string" && item.icon.trim()) normalized.icon = item.icon.trim();
3304
+ if (typeof item.order === "number" && Number.isFinite(item.order)) normalized.order = item.order;
3305
+ return normalized;
3306
+ }
3307
+ function normalizeProviderSummaryMetadata(summary) {
3308
+ if (!summary || !Array.isArray(summary.items)) return void 0;
3309
+ const items = summary.items.map((item) => normalizeSummaryItem(item)).filter((item) => !!item).sort((left, right) => {
3310
+ const orderDiff = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
3311
+ if (orderDiff !== 0) return orderDiff;
3312
+ return left.id.localeCompare(right.id);
3313
+ });
3314
+ return items.length > 0 ? { items } : void 0;
3315
+ }
3316
+ function buildProviderSummaryMetadata(items) {
3317
+ return normalizeProviderSummaryMetadata({ items: items.filter(Boolean) });
3318
+ }
3319
+ function buildLegacyModelModeSummaryMetadata(params) {
3320
+ return buildProviderSummaryMetadata([
3321
+ params.model ? {
3322
+ id: "model",
3323
+ label: "Model",
3324
+ value: String(params.modelLabel || params.model).trim(),
3325
+ shortValue: String(params.model).trim(),
3326
+ order: 10
3327
+ } : null,
3328
+ params.mode ? {
3329
+ id: "mode",
3330
+ label: "Mode",
3331
+ value: String(params.modeLabel || params.mode).trim(),
3332
+ shortValue: String(params.mode).trim(),
3333
+ order: 20
3334
+ } : null
3335
+ ]);
3336
+ }
3337
+ function resolveProviderStateSummaryMetadata(params) {
3338
+ const explicit = normalizeProviderSummaryMetadata(params.summaryMetadata);
3339
+ if (explicit) return explicit;
3340
+ const model = typeof params.controlValues?.model === "string" ? params.controlValues.model : void 0;
3341
+ const mode = typeof params.controlValues?.mode === "string" ? params.controlValues.mode : void 0;
3342
+ return buildLegacyModelModeSummaryMetadata({
3343
+ model,
3344
+ mode,
3345
+ modelLabel: params.modelLabel,
3346
+ modeLabel: params.modeLabel
3347
+ });
3348
+ }
3349
+ function normalizePersistedSummaryMetadata(params) {
3350
+ return normalizeProviderSummaryMetadata(params.summaryMetadata);
3351
+ }
3352
+
3353
+ // src/config/recent-activity.ts
3282
3354
  var MAX_ACTIVITY = 30;
3283
3355
  function normalizeWorkspace(workspace) {
3284
3356
  if (!workspace) return "";
@@ -3302,6 +3374,9 @@ function appendRecentActivity(state, entry) {
3302
3374
  const nextEntry = {
3303
3375
  ...entry,
3304
3376
  workspace: entry.workspace ? normalizeWorkspace(entry.workspace) : void 0,
3377
+ summaryMetadata: normalizePersistedSummaryMetadata({
3378
+ summaryMetadata: entry.summaryMetadata
3379
+ }),
3305
3380
  id: buildRecentActivityKeyForEntry(entry),
3306
3381
  lastUsedAt: entry.lastUsedAt || Date.now()
3307
3382
  };
@@ -3312,7 +3387,12 @@ function appendRecentActivity(state, entry) {
3312
3387
  };
3313
3388
  }
3314
3389
  function getRecentActivity(state, limit = 20) {
3315
- return [...state.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
3390
+ return [...state.recentActivity || []].map((entry) => ({
3391
+ ...entry,
3392
+ summaryMetadata: normalizePersistedSummaryMetadata({
3393
+ summaryMetadata: entry.summaryMetadata
3394
+ })
3395
+ })).sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
3316
3396
  }
3317
3397
  function getSessionSeenAt(state, sessionId) {
3318
3398
  return state.sessionReads?.[sessionId] || 0;
@@ -3364,7 +3444,9 @@ function upsertSavedProviderSession(state, entry) {
3364
3444
  providerName: entry.providerName,
3365
3445
  providerSessionId,
3366
3446
  workspace: entry.workspace ? normalizeWorkspace2(entry.workspace) : void 0,
3367
- currentModel: entry.currentModel,
3447
+ summaryMetadata: normalizePersistedSummaryMetadata({
3448
+ summaryMetadata: entry.summaryMetadata
3449
+ }),
3368
3450
  title: entry.title,
3369
3451
  createdAt: existing?.createdAt || entry.createdAt || Date.now(),
3370
3452
  lastUsedAt: entry.lastUsedAt || Date.now()
@@ -3380,7 +3462,12 @@ function getSavedProviderSessions(state, filters) {
3380
3462
  if (filters?.providerType && entry.providerType !== filters.providerType) return false;
3381
3463
  if (filters?.kind && entry.kind !== filters.kind) return false;
3382
3464
  return true;
3383
- }).sort((a, b) => b.lastUsedAt - a.lastUsedAt);
3465
+ }).map((entry) => ({
3466
+ ...entry,
3467
+ summaryMetadata: normalizePersistedSummaryMetadata({
3468
+ summaryMetadata: entry.summaryMetadata
3469
+ })
3470
+ })).sort((a, b) => b.lastUsedAt - a.lastUsedAt);
3384
3471
  }
3385
3472
 
3386
3473
  // src/config/state-store.ts
@@ -3576,15 +3663,15 @@ function resolveCommandPath(command) {
3576
3663
  return null;
3577
3664
  }
3578
3665
  function execAsync(cmd, timeoutMs = 5e3) {
3579
- return new Promise((resolve12) => {
3666
+ return new Promise((resolve11) => {
3580
3667
  const child = (0, import_child_process2.exec)(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
3581
3668
  if (err || !stdout?.trim()) {
3582
- resolve12(null);
3669
+ resolve11(null);
3583
3670
  } else {
3584
- resolve12(stdout.trim());
3671
+ resolve11(stdout.trim());
3585
3672
  }
3586
3673
  });
3587
- child.on("error", () => resolve12(null));
3674
+ child.on("error", () => resolve11(null));
3588
3675
  });
3589
3676
  }
3590
3677
  async function detectCLIs(providerLoader, options) {
@@ -3795,7 +3882,7 @@ var DaemonCdpManager = class {
3795
3882
  * Returns multiple entries if multiple IDE windows are open on same port
3796
3883
  */
3797
3884
  static listAllTargets(port) {
3798
- return new Promise((resolve12) => {
3885
+ return new Promise((resolve11) => {
3799
3886
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3800
3887
  let data = "";
3801
3888
  res.on("data", (chunk) => data += chunk.toString());
@@ -3811,16 +3898,16 @@ var DaemonCdpManager = class {
3811
3898
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
3812
3899
  );
3813
3900
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
3814
- resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
3901
+ resolve11(mainPages.length > 0 ? mainPages : fallbackPages);
3815
3902
  } catch {
3816
- resolve12([]);
3903
+ resolve11([]);
3817
3904
  }
3818
3905
  });
3819
3906
  });
3820
- req.on("error", () => resolve12([]));
3907
+ req.on("error", () => resolve11([]));
3821
3908
  req.setTimeout(2e3, () => {
3822
3909
  req.destroy();
3823
- resolve12([]);
3910
+ resolve11([]);
3824
3911
  });
3825
3912
  });
3826
3913
  }
@@ -3860,7 +3947,7 @@ var DaemonCdpManager = class {
3860
3947
  }
3861
3948
  }
3862
3949
  findTargetOnPort(port) {
3863
- return new Promise((resolve12) => {
3950
+ return new Promise((resolve11) => {
3864
3951
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3865
3952
  let data = "";
3866
3953
  res.on("data", (chunk) => data += chunk.toString());
@@ -3871,7 +3958,7 @@ var DaemonCdpManager = class {
3871
3958
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
3872
3959
  );
3873
3960
  if (pages.length === 0) {
3874
- resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
3961
+ resolve11(targets.find((t) => t.webSocketDebuggerUrl) || null);
3875
3962
  return;
3876
3963
  }
3877
3964
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -3881,24 +3968,24 @@ var DaemonCdpManager = class {
3881
3968
  const specific = list.find((t) => t.id === this._targetId);
3882
3969
  if (specific) {
3883
3970
  this._pageTitle = specific.title || "";
3884
- resolve12(specific);
3971
+ resolve11(specific);
3885
3972
  } else {
3886
3973
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
3887
- resolve12(null);
3974
+ resolve11(null);
3888
3975
  }
3889
3976
  return;
3890
3977
  }
3891
3978
  this._pageTitle = list[0]?.title || "";
3892
- resolve12(list[0]);
3979
+ resolve11(list[0]);
3893
3980
  } catch {
3894
- resolve12(null);
3981
+ resolve11(null);
3895
3982
  }
3896
3983
  });
3897
3984
  });
3898
- req.on("error", () => resolve12(null));
3985
+ req.on("error", () => resolve11(null));
3899
3986
  req.setTimeout(2e3, () => {
3900
3987
  req.destroy();
3901
- resolve12(null);
3988
+ resolve11(null);
3902
3989
  });
3903
3990
  });
3904
3991
  }
@@ -3909,7 +3996,7 @@ var DaemonCdpManager = class {
3909
3996
  this.extensionProviders = providers;
3910
3997
  }
3911
3998
  connectToTarget(wsUrl) {
3912
- return new Promise((resolve12) => {
3999
+ return new Promise((resolve11) => {
3913
4000
  this.ws = new import_ws.default(wsUrl);
3914
4001
  this.ws.on("open", async () => {
3915
4002
  this._connected = true;
@@ -3919,17 +4006,17 @@ var DaemonCdpManager = class {
3919
4006
  }
3920
4007
  this.connectBrowserWs().catch(() => {
3921
4008
  });
3922
- resolve12(true);
4009
+ resolve11(true);
3923
4010
  });
3924
4011
  this.ws.on("message", (data) => {
3925
4012
  try {
3926
4013
  const msg = JSON.parse(data.toString());
3927
4014
  if (msg.id && this.pending.has(msg.id)) {
3928
- const { resolve: resolve13, reject } = this.pending.get(msg.id);
4015
+ const { resolve: resolve12, reject } = this.pending.get(msg.id);
3929
4016
  this.pending.delete(msg.id);
3930
4017
  this.failureCount = 0;
3931
4018
  if (msg.error) reject(new Error(msg.error.message));
3932
- else resolve13(msg.result);
4019
+ else resolve12(msg.result);
3933
4020
  } else if (msg.method === "Runtime.executionContextCreated") {
3934
4021
  this.contexts.add(msg.params.context.id);
3935
4022
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -3952,7 +4039,7 @@ var DaemonCdpManager = class {
3952
4039
  this.ws.on("error", (err) => {
3953
4040
  this.log(`[CDP] WebSocket error: ${err.message}`);
3954
4041
  this._connected = false;
3955
- resolve12(false);
4042
+ resolve11(false);
3956
4043
  });
3957
4044
  });
3958
4045
  }
@@ -3966,7 +4053,7 @@ var DaemonCdpManager = class {
3966
4053
  return;
3967
4054
  }
3968
4055
  this.log(`[CDP] Connecting browser WS for target discovery...`);
3969
- await new Promise((resolve12, reject) => {
4056
+ await new Promise((resolve11, reject) => {
3970
4057
  this.browserWs = new import_ws.default(browserWsUrl);
3971
4058
  this.browserWs.on("open", async () => {
3972
4059
  this._browserConnected = true;
@@ -3976,16 +4063,16 @@ var DaemonCdpManager = class {
3976
4063
  } catch (e) {
3977
4064
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
3978
4065
  }
3979
- resolve12();
4066
+ resolve11();
3980
4067
  });
3981
4068
  this.browserWs.on("message", (data) => {
3982
4069
  try {
3983
4070
  const msg = JSON.parse(data.toString());
3984
4071
  if (msg.id && this.browserPending.has(msg.id)) {
3985
- const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
4072
+ const { resolve: resolve12, reject: reject2 } = this.browserPending.get(msg.id);
3986
4073
  this.browserPending.delete(msg.id);
3987
4074
  if (msg.error) reject2(new Error(msg.error.message));
3988
- else resolve13(msg.result);
4075
+ else resolve12(msg.result);
3989
4076
  }
3990
4077
  } catch {
3991
4078
  }
@@ -4005,31 +4092,31 @@ var DaemonCdpManager = class {
4005
4092
  }
4006
4093
  }
4007
4094
  getBrowserWsUrl() {
4008
- return new Promise((resolve12) => {
4095
+ return new Promise((resolve11) => {
4009
4096
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
4010
4097
  let data = "";
4011
4098
  res.on("data", (chunk) => data += chunk.toString());
4012
4099
  res.on("end", () => {
4013
4100
  try {
4014
4101
  const info = JSON.parse(data);
4015
- resolve12(info.webSocketDebuggerUrl || null);
4102
+ resolve11(info.webSocketDebuggerUrl || null);
4016
4103
  } catch {
4017
- resolve12(null);
4104
+ resolve11(null);
4018
4105
  }
4019
4106
  });
4020
4107
  });
4021
- req.on("error", () => resolve12(null));
4108
+ req.on("error", () => resolve11(null));
4022
4109
  req.setTimeout(3e3, () => {
4023
4110
  req.destroy();
4024
- resolve12(null);
4111
+ resolve11(null);
4025
4112
  });
4026
4113
  });
4027
4114
  }
4028
4115
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
4029
- return new Promise((resolve12, reject) => {
4116
+ return new Promise((resolve11, reject) => {
4030
4117
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
4031
4118
  const id = this.browserMsgId++;
4032
- this.browserPending.set(id, { resolve: resolve12, reject });
4119
+ this.browserPending.set(id, { resolve: resolve11, reject });
4033
4120
  this.browserWs.send(JSON.stringify({ id, method, params }));
4034
4121
  setTimeout(() => {
4035
4122
  if (this.browserPending.has(id)) {
@@ -4069,11 +4156,11 @@ var DaemonCdpManager = class {
4069
4156
  }
4070
4157
  // ─── CDP Protocol ────────────────────────────────────────
4071
4158
  sendInternal(method, params = {}, timeoutMs = 15e3) {
4072
- return new Promise((resolve12, reject) => {
4159
+ return new Promise((resolve11, reject) => {
4073
4160
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
4074
4161
  if (this.ws.readyState !== import_ws.default.OPEN) return reject(new Error("WebSocket not open"));
4075
4162
  const id = this.msgId++;
4076
- this.pending.set(id, { resolve: resolve12, reject });
4163
+ this.pending.set(id, { resolve: resolve11, reject });
4077
4164
  this.ws.send(JSON.stringify({ id, method, params }));
4078
4165
  setTimeout(() => {
4079
4166
  if (this.pending.has(id)) {
@@ -4322,7 +4409,7 @@ var DaemonCdpManager = class {
4322
4409
  const browserWs = this.browserWs;
4323
4410
  let msgId = this.browserMsgId;
4324
4411
  const sendWs = (method, params = {}, sessionId) => {
4325
- return new Promise((resolve12, reject) => {
4412
+ return new Promise((resolve11, reject) => {
4326
4413
  const mid = msgId++;
4327
4414
  this.browserMsgId = msgId;
4328
4415
  const handler = (raw) => {
@@ -4331,7 +4418,7 @@ var DaemonCdpManager = class {
4331
4418
  if (msg.id === mid) {
4332
4419
  browserWs.removeListener("message", handler);
4333
4420
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
4334
- else resolve12(msg.result);
4421
+ else resolve11(msg.result);
4335
4422
  }
4336
4423
  } catch {
4337
4424
  }
@@ -4532,14 +4619,14 @@ var DaemonCdpManager = class {
4532
4619
  if (!ws || ws.readyState !== import_ws.default.OPEN) {
4533
4620
  throw new Error("CDP not connected");
4534
4621
  }
4535
- return new Promise((resolve12, reject) => {
4622
+ return new Promise((resolve11, reject) => {
4536
4623
  const id = getNextId();
4537
4624
  pendingMap.set(id, {
4538
4625
  resolve: (result) => {
4539
4626
  if (result?.result?.subtype === "error") {
4540
4627
  reject(new Error(result.result.description));
4541
4628
  } else {
4542
- resolve12(result?.result?.value);
4629
+ resolve11(result?.result?.value);
4543
4630
  }
4544
4631
  },
4545
4632
  reject
@@ -4571,10 +4658,10 @@ var DaemonCdpManager = class {
4571
4658
  throw new Error("CDP not connected");
4572
4659
  }
4573
4660
  const sendViaSession = (method, params = {}) => {
4574
- return new Promise((resolve12, reject) => {
4661
+ return new Promise((resolve11, reject) => {
4575
4662
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
4576
4663
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
4577
- pendingMap.set(id, { resolve: resolve12, reject });
4664
+ pendingMap.set(id, { resolve: resolve11, reject });
4578
4665
  ws.send(JSON.stringify({ id, sessionId, method, params }));
4579
4666
  setTimeout(() => {
4580
4667
  if (pendingMap.has(id)) {
@@ -5137,8 +5224,6 @@ function extractProviderControlValues(controls, data) {
5137
5224
  if (rawValue === void 0 || rawValue === null) continue;
5138
5225
  values[ctrl.id] = normalizeControlValue(rawValue);
5139
5226
  }
5140
- if (data.model !== void 0 && values.model === void 0) values.model = normalizeControlValue(data.model);
5141
- if (data.mode !== void 0 && values.mode === void 0) values.mode = normalizeControlValue(data.mode);
5142
5227
  return Object.keys(values).length > 0 ? values : void 0;
5143
5228
  }
5144
5229
  function normalizeProviderEffects(data) {
@@ -5240,7 +5325,7 @@ function normalizeControlOption(option) {
5240
5325
  }
5241
5326
  if (!option || typeof option !== "object") return null;
5242
5327
  const record = option;
5243
- const value = typeof record.value === "string" ? record.value : typeof record.id === "string" ? record.id : null;
5328
+ const value = typeof record.value === "string" ? record.value : typeof record.id === "string" ? record.id : typeof record.name === "string" ? record.name : null;
5244
5329
  if (!value) return null;
5245
5330
  const label = typeof record.label === "string" ? record.label : typeof record.name === "string" ? record.name : value;
5246
5331
  const normalized = { value, label };
@@ -5484,6 +5569,30 @@ var ChatHistoryWriter = class {
5484
5569
  options.historySessionId
5485
5570
  );
5486
5571
  }
5572
+ writeSessionStart(agentType, historySessionId, workspace, instanceId) {
5573
+ const id = String(historySessionId || "").trim();
5574
+ const ws = String(workspace || "").trim();
5575
+ if (!id || !ws) return;
5576
+ try {
5577
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
5578
+ fs3.mkdirSync(dir, { recursive: true });
5579
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5580
+ const filePath = path7.join(dir, `${this.sanitize(id)}_${date}.jsonl`);
5581
+ const record = {
5582
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
5583
+ receivedAt: Date.now(),
5584
+ role: "system",
5585
+ kind: "session_start",
5586
+ content: ws,
5587
+ agent: agentType,
5588
+ instanceId,
5589
+ historySessionId: id,
5590
+ workspace: ws
5591
+ };
5592
+ fs3.appendFileSync(filePath, JSON.stringify(record) + "\n", "utf-8");
5593
+ } catch {
5594
+ }
5595
+ }
5487
5596
  promoteHistorySession(agentType, previousHistorySessionId, nextHistorySessionId) {
5488
5597
  const fromId = String(previousHistorySessionId || "").trim();
5489
5598
  const toId = String(nextHistorySessionId || "").trim();
@@ -5703,6 +5812,7 @@ function listSavedHistorySessions(agentType, options = {}) {
5703
5812
  let lastMessageAt = 0;
5704
5813
  let sessionTitle = "";
5705
5814
  let preview = "";
5815
+ let workspace = "";
5706
5816
  for (const file of files.sort()) {
5707
5817
  const filePath = path7.join(dir, file);
5708
5818
  const content = fs3.readFileSync(filePath, "utf-8");
@@ -5715,6 +5825,10 @@ function listSavedHistorySessions(agentType, options = {}) {
5715
5825
  parsed = null;
5716
5826
  }
5717
5827
  if (!parsed || parsed.historySessionId !== historySessionId) continue;
5828
+ if (parsed.kind === "session_start") {
5829
+ if (!workspace && parsed.workspace) workspace = parsed.workspace;
5830
+ continue;
5831
+ }
5718
5832
  messageCount += 1;
5719
5833
  if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
5720
5834
  if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
@@ -5729,7 +5843,8 @@ function listSavedHistorySessions(agentType, options = {}) {
5729
5843
  messageCount,
5730
5844
  firstMessageAt,
5731
5845
  lastMessageAt,
5732
- preview: preview || void 0
5846
+ preview: preview || void 0,
5847
+ workspace: workspace || void 0
5733
5848
  });
5734
5849
  }
5735
5850
  summaries.sort((a, b) => b.lastMessageAt - a.lastMessageAt);
@@ -5745,6 +5860,61 @@ function listSavedHistorySessions(agentType, options = {}) {
5745
5860
  }
5746
5861
  }
5747
5862
 
5863
+ // src/providers/provider-patch-state.ts
5864
+ function isControlValue(value) {
5865
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
5866
+ }
5867
+ function asControlValueMap(value) {
5868
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
5869
+ const result = {};
5870
+ for (const [entryKey, entryValue] of Object.entries(value)) {
5871
+ if (isControlValue(entryValue)) result[entryKey] = entryValue;
5872
+ }
5873
+ return Object.keys(result).length > 0 ? result : void 0;
5874
+ }
5875
+ function getLegacyModelModeValues(data) {
5876
+ if (!data || typeof data !== "object") return void 0;
5877
+ const legacy = {};
5878
+ if (typeof data.model === "string" && data.model.trim()) legacy.model = data.model.trim();
5879
+ if (typeof data.mode === "string" && data.mode.trim()) legacy.mode = data.mode.trim();
5880
+ return Object.keys(legacy).length > 0 ? legacy : void 0;
5881
+ }
5882
+ function mergeProviderPatchState(params) {
5883
+ const {
5884
+ providerControls,
5885
+ data,
5886
+ currentControlValues,
5887
+ currentSummaryMetadata,
5888
+ mergeWithCurrent = true
5889
+ } = params;
5890
+ const sources = [
5891
+ mergeWithCurrent ? asControlValueMap(currentControlValues) : void 0,
5892
+ asControlValueMap(data?.controlValues),
5893
+ asControlValueMap(extractProviderControlValues(providerControls, data)),
5894
+ getLegacyModelModeValues(data)
5895
+ ];
5896
+ const controlValues = Object.assign({}, ...sources.filter(Boolean));
5897
+ return {
5898
+ controlValues,
5899
+ summaryMetadata: data?.summaryMetadata !== void 0 ? data.summaryMetadata : currentSummaryMetadata
5900
+ };
5901
+ }
5902
+ function normalizeProviderStateControlValues(controlValues) {
5903
+ return controlValues && Object.keys(controlValues).length > 0 ? controlValues : void 0;
5904
+ }
5905
+ function resolveProviderStateSurface(params) {
5906
+ const controlValues = normalizeProviderStateControlValues(params.controlValues);
5907
+ return {
5908
+ controlValues,
5909
+ summaryMetadata: resolveProviderStateSummaryMetadata({
5910
+ summaryMetadata: params.summaryMetadata,
5911
+ controlValues,
5912
+ modelLabel: params.modelLabel,
5913
+ modeLabel: params.modeLabel
5914
+ })
5915
+ };
5916
+ }
5917
+
5748
5918
  // src/providers/extension-provider-instance.ts
5749
5919
  var ExtensionProviderInstance = class {
5750
5920
  type;
@@ -5759,9 +5929,8 @@ var ExtensionProviderInstance = class {
5759
5929
  messages = [];
5760
5930
  prevMessageHashes = /* @__PURE__ */ new Map();
5761
5931
  activeModal = null;
5762
- currentModel = "";
5763
- currentMode = "";
5764
5932
  controlValues = {};
5933
+ summaryMetadata = void 0;
5765
5934
  appliedEffectKeys = /* @__PURE__ */ new Set();
5766
5935
  runtimeMessages = [];
5767
5936
  lastAgentStatus = "idle";
@@ -5796,6 +5965,10 @@ var ExtensionProviderInstance = class {
5796
5965
  if (!this.context?.cdp?.isConnected) return;
5797
5966
  }
5798
5967
  getState() {
5968
+ const surface = resolveProviderStateSurface({
5969
+ summaryMetadata: this.summaryMetadata,
5970
+ controlValues: this.controlValues
5971
+ });
5799
5972
  return {
5800
5973
  type: this.type,
5801
5974
  name: this.provider.name,
@@ -5809,10 +5982,9 @@ var ExtensionProviderInstance = class {
5809
5982
  activeModal: this.activeModal,
5810
5983
  inputContent: ""
5811
5984
  } : null,
5812
- currentModel: this.currentModel || void 0,
5813
- currentPlan: this.currentMode || void 0,
5814
- controlValues: this.controlValues,
5985
+ controlValues: surface.controlValues,
5815
5986
  providerControls: this.provider.controls,
5987
+ summaryMetadata: surface.summaryMetadata,
5816
5988
  agentStreams: this.agentStreams,
5817
5989
  instanceId: this.instanceId,
5818
5990
  lastUpdated: Date.now(),
@@ -5825,10 +5997,14 @@ var ExtensionProviderInstance = class {
5825
5997
  if (data?.streams) this.agentStreams = data.streams;
5826
5998
  if (data?.messages) this.messages = this.assignReceivedAt(data.messages);
5827
5999
  if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
5828
- if (data?.model) this.currentModel = data.model;
5829
- if (data?.mode) this.currentMode = data.mode;
5830
- const controlValues = extractProviderControlValues(this.provider.controls, data) || data?.controlValues;
5831
- if (controlValues) this.controlValues = controlValues;
6000
+ const patchedState = mergeProviderPatchState({
6001
+ providerControls: this.provider.controls,
6002
+ data,
6003
+ currentControlValues: this.controlValues,
6004
+ currentSummaryMetadata: this.summaryMetadata
6005
+ });
6006
+ this.controlValues = patchedState.controlValues;
6007
+ this.summaryMetadata = patchedState.summaryMetadata;
5832
6008
  if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
5833
6009
  if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
5834
6010
  if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
@@ -5929,8 +6105,14 @@ var ExtensionProviderInstance = class {
5929
6105
  }
5930
6106
  applyProviderResponse(data, options) {
5931
6107
  if (!data || typeof data !== "object") return;
5932
- const controlValues = extractProviderControlValues(this.provider.controls, data);
5933
- if (controlValues) this.controlValues = { ...this.controlValues, ...controlValues };
6108
+ const patchedState = mergeProviderPatchState({
6109
+ providerControls: this.provider.controls,
6110
+ data,
6111
+ currentControlValues: this.controlValues,
6112
+ currentSummaryMetadata: this.summaryMetadata
6113
+ });
6114
+ this.controlValues = patchedState.controlValues;
6115
+ this.summaryMetadata = patchedState.summaryMetadata;
5934
6116
  const effects = normalizeProviderEffects(data);
5935
6117
  for (const effect of effects) {
5936
6118
  const effectWhen = effect.when || "immediate";
@@ -6080,8 +6262,6 @@ ${effect.notification.body || ""}`.trim();
6080
6262
  this.messages = [];
6081
6263
  this.prevMessageHashes.clear();
6082
6264
  this.activeModal = null;
6083
- this.currentModel = "";
6084
- this.currentMode = "";
6085
6265
  this.controlValues = {};
6086
6266
  this.currentStatus = "idle";
6087
6267
  this.chatId = null;
@@ -6217,6 +6397,10 @@ var IdeProviderInstance = class {
6217
6397
  for (const ext of this.extensions.values()) {
6218
6398
  extensionStates.push(ext.getState());
6219
6399
  }
6400
+ const surface = resolveProviderStateSurface({
6401
+ summaryMetadata: this.cachedChat?.summaryMetadata,
6402
+ controlValues: this.cachedChat?.controlValues
6403
+ });
6220
6404
  return {
6221
6405
  type: this.type,
6222
6406
  name: this.provider.name,
@@ -6233,11 +6417,9 @@ var IdeProviderInstance = class {
6233
6417
  workspace: this.workspace || null,
6234
6418
  extensions: extensionStates,
6235
6419
  cdpConnected: cdp?.isConnected || false,
6236
- currentModel: this.cachedChat?.model || void 0,
6237
- currentPlan: this.cachedChat?.mode || void 0,
6238
- currentAutoApprove: this.cachedChat?.autoApprove || void 0,
6239
- controlValues: this.cachedChat?.controlValues || void 0,
6420
+ controlValues: surface.controlValues,
6240
6421
  providerControls: this.provider.controls,
6422
+ summaryMetadata: surface.summaryMetadata,
6241
6423
  instanceId: this.instanceId,
6242
6424
  lastUpdated: Date.now(),
6243
6425
  settings: this.settings,
@@ -6409,8 +6591,13 @@ var IdeProviderInstance = class {
6409
6591
  chat.messages = messages.filter((m) => !hiddenKinds.has(m.kind || ""));
6410
6592
  }
6411
6593
  }
6412
- const controlValues = extractProviderControlValues(this.provider.controls, chat);
6413
- if (controlValues) chat.controlValues = controlValues;
6594
+ const patchedState = mergeProviderPatchState({
6595
+ providerControls: this.provider.controls,
6596
+ data: chat,
6597
+ mergeWithCurrent: false
6598
+ });
6599
+ chat.controlValues = Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : void 0;
6600
+ chat.summaryMetadata = patchedState.summaryMetadata;
6414
6601
  this.cachedChat = { ...chat, activeModal };
6415
6602
  this.detectAgentTransitions(chat, now);
6416
6603
  const persistedMessages = chat.messages || messages;
@@ -6497,14 +6684,18 @@ var IdeProviderInstance = class {
6497
6684
  }
6498
6685
  applyProviderResponse(data, options) {
6499
6686
  if (!data || typeof data !== "object") return;
6500
- const controlValues = extractProviderControlValues(this.provider.controls, data);
6501
- if (controlValues) {
6502
- this.cachedChat = {
6503
- ...this.cachedChat || {},
6504
- ...data,
6505
- controlValues: { ...this.cachedChat?.controlValues || {}, ...controlValues }
6506
- };
6507
- }
6687
+ const patchedState = mergeProviderPatchState({
6688
+ providerControls: this.provider.controls,
6689
+ data,
6690
+ currentControlValues: this.cachedChat?.controlValues,
6691
+ currentSummaryMetadata: this.cachedChat?.summaryMetadata
6692
+ });
6693
+ this.cachedChat = {
6694
+ ...this.cachedChat || {},
6695
+ ...data,
6696
+ controlValues: Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : void 0,
6697
+ summaryMetadata: patchedState.summaryMetadata
6698
+ };
6508
6699
  const effects = normalizeProviderEffects(data);
6509
6700
  for (const effect of effects) {
6510
6701
  const effectWhen = effect.when || "immediate";
@@ -7287,6 +7478,8 @@ var ACP_SESSION_CAPABILITIES = [
7287
7478
  function buildIdeWorkspaceSession(state, cdpManagers, options) {
7288
7479
  const profile = options.profile || "full";
7289
7480
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7481
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7482
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7290
7483
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7291
7484
  const includeSessionControls = shouldIncludeSessionControls(profile);
7292
7485
  const title = activeChat?.title || state.name;
@@ -7303,13 +7496,11 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
7303
7496
  title,
7304
7497
  ...includeSessionMetadata && { workspace: state.workspace || null },
7305
7498
  activeChat,
7499
+ ...summaryMetadata && { summaryMetadata },
7306
7500
  ...includeSessionMetadata && { capabilities: IDE_SESSION_CAPABILITIES },
7307
7501
  cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
7308
- currentModel: state.currentModel,
7309
- currentPlan: state.currentPlan,
7310
- currentAutoApprove: state.currentAutoApprove,
7311
7502
  ...includeSessionControls && {
7312
- controlValues: state.controlValues,
7503
+ ...controlValues && { controlValues },
7313
7504
  providerControls: state.providerControls
7314
7505
  },
7315
7506
  errorMessage: state.errorMessage,
@@ -7320,6 +7511,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
7320
7511
  function buildExtensionAgentSession(parent, ext, options) {
7321
7512
  const profile = options.profile || "full";
7322
7513
  const activeChat = normalizeActiveChatData(ext.activeChat, getActiveChatOptions(profile));
7514
+ const summaryMetadata = normalizeProviderSummaryMetadata(ext.summaryMetadata);
7515
+ const controlValues = normalizeProviderStateControlValues(ext.controlValues);
7323
7516
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7324
7517
  const includeSessionControls = shouldIncludeSessionControls(profile);
7325
7518
  return {
@@ -7335,11 +7528,10 @@ function buildExtensionAgentSession(parent, ext, options) {
7335
7528
  title: activeChat?.title || ext.name,
7336
7529
  ...includeSessionMetadata && { workspace: parent.workspace || null },
7337
7530
  activeChat,
7531
+ ...summaryMetadata && { summaryMetadata },
7338
7532
  ...includeSessionMetadata && { capabilities: EXTENSION_SESSION_CAPABILITIES },
7339
- currentModel: ext.currentModel,
7340
- currentPlan: ext.currentPlan,
7341
7533
  ...includeSessionControls && {
7342
- controlValues: ext.controlValues,
7534
+ ...controlValues && { controlValues },
7343
7535
  providerControls: ext.providerControls
7344
7536
  },
7345
7537
  errorMessage: ext.errorMessage,
@@ -7350,6 +7542,8 @@ function buildExtensionAgentSession(parent, ext, options) {
7350
7542
  function buildCliSession(state, options) {
7351
7543
  const profile = options.profile || "full";
7352
7544
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7545
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7546
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7353
7547
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7354
7548
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
7355
7549
  const includeSessionControls = shouldIncludeSessionControls(profile);
@@ -7376,11 +7570,12 @@ function buildCliSession(state, options) {
7376
7570
  mode: state.mode,
7377
7571
  resume: state.resume,
7378
7572
  activeChat,
7573
+ ...summaryMetadata && { summaryMetadata },
7379
7574
  ...includeSessionMetadata && {
7380
7575
  capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES
7381
7576
  },
7382
7577
  ...includeSessionControls && {
7383
- controlValues: state.controlValues,
7578
+ ...controlValues && { controlValues },
7384
7579
  providerControls: state.providerControls
7385
7580
  },
7386
7581
  errorMessage: state.errorMessage,
@@ -7391,6 +7586,8 @@ function buildCliSession(state, options) {
7391
7586
  function buildAcpSession(state, options) {
7392
7587
  const profile = options.profile || "full";
7393
7588
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7589
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7590
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7394
7591
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7395
7592
  const includeSessionControls = shouldIncludeSessionControls(profile);
7396
7593
  return {
@@ -7406,13 +7603,10 @@ function buildAcpSession(state, options) {
7406
7603
  title: activeChat?.title || state.name,
7407
7604
  ...includeSessionMetadata && { workspace: state.workspace || null },
7408
7605
  activeChat,
7606
+ ...summaryMetadata && { summaryMetadata },
7409
7607
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
7410
- currentModel: state.currentModel,
7411
- currentPlan: state.currentPlan,
7412
7608
  ...includeSessionControls && {
7413
- acpConfigOptions: state.acpConfigOptions,
7414
- acpModes: state.acpModes,
7415
- controlValues: state.controlValues,
7609
+ ...controlValues && { controlValues },
7416
7610
  providerControls: state.providerControls
7417
7611
  },
7418
7612
  errorMessage: state.errorMessage,
@@ -8104,7 +8298,7 @@ function getStateLastSignature(state) {
8104
8298
  async function getStableExtensionBaseline(h) {
8105
8299
  const first = await readExtensionChatState(h);
8106
8300
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
8107
- await new Promise((resolve12) => setTimeout(resolve12, 150));
8301
+ await new Promise((resolve11) => setTimeout(resolve11, 150));
8108
8302
  const second = await readExtensionChatState(h);
8109
8303
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
8110
8304
  }
@@ -8112,7 +8306,7 @@ async function verifyExtensionSendObserved(h, before) {
8112
8306
  const beforeCount = getStateMessageCount(before);
8113
8307
  const beforeSignature = getStateLastSignature(before);
8114
8308
  for (let attempt = 0; attempt < 12; attempt += 1) {
8115
- await new Promise((resolve12) => setTimeout(resolve12, 250));
8309
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
8116
8310
  const state = await readExtensionChatState(h);
8117
8311
  if (state?.status === "waiting_approval") return true;
8118
8312
  const afterCount = getStateMessageCount(state);
@@ -9304,6 +9498,30 @@ async function handleFileListBrowse(h, args) {
9304
9498
  }
9305
9499
  }
9306
9500
 
9501
+ // src/commands/stream-commands.ts
9502
+ init_config();
9503
+
9504
+ // src/config/provider-source-config.ts
9505
+ function normalizeProviderDir(value) {
9506
+ if (typeof value !== "string") return void 0;
9507
+ const trimmed = value.trim();
9508
+ return trimmed ? trimmed : void 0;
9509
+ }
9510
+ function parseProviderSourceConfigUpdate(input) {
9511
+ const updates = {};
9512
+ if (Object.prototype.hasOwnProperty.call(input, "providerSourceMode")) {
9513
+ const { providerSourceMode } = input;
9514
+ if (providerSourceMode !== "normal" && providerSourceMode !== "no-upstream") {
9515
+ return { ok: false, error: "providerSourceMode must be 'normal' or 'no-upstream'" };
9516
+ }
9517
+ updates.providerSourceMode = providerSourceMode;
9518
+ }
9519
+ if (Object.prototype.hasOwnProperty.call(input, "providerDir")) {
9520
+ updates.providerDir = normalizeProviderDir(input.providerDir);
9521
+ }
9522
+ return { ok: true, updates };
9523
+ }
9524
+
9307
9525
  // src/providers/cli-script-results.ts
9308
9526
  function parseCliScriptResult(result) {
9309
9527
  if (typeof result === "string") {
@@ -9416,8 +9634,49 @@ async function handleSetProviderSetting(h, args) {
9416
9634
  }
9417
9635
  return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
9418
9636
  }
9419
- function normalizeProviderScriptArgs(args) {
9637
+ function handleGetProviderSourceConfig(h, _args) {
9638
+ const loader = h.ctx.providerLoader;
9639
+ if (!loader) return { success: false, error: "providerLoader not available" };
9640
+ return { success: true, ...loader.getSourceConfig() };
9641
+ }
9642
+ async function handleSetProviderSourceConfig(h, args) {
9643
+ const loader = h.ctx.providerLoader;
9644
+ if (!loader) return { success: false, error: "providerLoader not available" };
9645
+ const parsed = parseProviderSourceConfigUpdate(args || {});
9646
+ if ("error" in parsed) {
9647
+ return { success: false, error: parsed.error };
9648
+ }
9649
+ const currentConfig2 = loadConfig();
9650
+ const nextConfig = {
9651
+ ...currentConfig2,
9652
+ ...parsed.updates.providerSourceMode ? { providerSourceMode: parsed.updates.providerSourceMode } : {},
9653
+ ...Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? { providerDir: parsed.updates.providerDir } : {}
9654
+ };
9655
+ saveConfig(nextConfig);
9656
+ const sourceConfig = loader.applySourceConfig({
9657
+ sourceMode: nextConfig.providerSourceMode,
9658
+ userDir: Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? parsed.updates.providerDir : loader.getSourceConfig().explicitProviderDir || void 0
9659
+ });
9660
+ loader.reload();
9661
+ loader.registerToDetector();
9662
+ await h.ctx.onProviderSourceConfigChanged?.();
9663
+ LOG.info(
9664
+ "Command",
9665
+ `[set_provider_source_config] mode=${sourceConfig.sourceMode} explicitProviderDir=${sourceConfig.explicitProviderDir || "-"} userDir=${sourceConfig.userDir}`
9666
+ );
9667
+ return { success: true, reloaded: true, ...sourceConfig };
9668
+ }
9669
+ function normalizeProviderScriptArgs(args, scriptName) {
9420
9670
  const normalizedArgs = { ...args || {} };
9671
+ const normalizedScriptName = String(scriptName || "").toLowerCase();
9672
+ if (Object.prototype.hasOwnProperty.call(normalizedArgs, "value")) {
9673
+ if (normalizedArgs.model === void 0 && (normalizedScriptName === "setmodel" || normalizedScriptName === "setmodelgui" || normalizedScriptName === "webviewsetmodel")) {
9674
+ normalizedArgs.model = normalizedArgs.value;
9675
+ }
9676
+ if (normalizedArgs.mode === void 0 && (normalizedScriptName === "setmode" || normalizedScriptName === "webviewsetmode")) {
9677
+ normalizedArgs.mode = normalizedArgs.value;
9678
+ }
9679
+ }
9421
9680
  for (const key of ["mode", "model", "message", "action", "button", "text", "sessionId", "value"]) {
9422
9681
  if (key in normalizedArgs && !(key.toUpperCase() in normalizedArgs)) {
9423
9682
  normalizedArgs[key.toUpperCase()] = normalizedArgs[key];
@@ -9463,7 +9722,7 @@ async function executeProviderScript(h, args, scriptName) {
9463
9722
  if (!provider.scripts?.[actualScriptName]) {
9464
9723
  return { success: false, error: `Script '${actualScriptName}' not available for ${resolvedProviderType}` };
9465
9724
  }
9466
- const normalizedArgs = normalizeProviderScriptArgs(args);
9725
+ const normalizedArgs = normalizeProviderScriptArgs(args, actualScriptName);
9467
9726
  if (provider.category === "cli") {
9468
9727
  const adapter = h.getCliAdapter(args?.targetSessionId || resolvedProviderType);
9469
9728
  if (!adapter?.invokeScript) {
@@ -10109,6 +10368,10 @@ var DaemonCommandHandler = class {
10109
10368
  return handleGetProviderSettings(this, args);
10110
10369
  case "set_provider_setting":
10111
10370
  return handleSetProviderSetting(this, args);
10371
+ case "get_provider_source_config":
10372
+ return handleGetProviderSourceConfig(this, args);
10373
+ case "set_provider_source_config":
10374
+ return handleSetProviderSourceConfig(this, args);
10112
10375
  // ─── IDE Extension Settings (stream-commands.ts) ──────────
10113
10376
  case "get_ide_extensions":
10114
10377
  return handleGetIdeExtensions(this, args);
@@ -10148,7 +10411,7 @@ var DaemonCommandHandler = class {
10148
10411
  try {
10149
10412
  const http3 = await import("http");
10150
10413
  const postData = JSON.stringify(body);
10151
- const result = await new Promise((resolve12, reject) => {
10414
+ const result = await new Promise((resolve11, reject) => {
10152
10415
  const req = http3.request({
10153
10416
  hostname: "127.0.0.1",
10154
10417
  port: 19280,
@@ -10160,9 +10423,9 @@ var DaemonCommandHandler = class {
10160
10423
  res.on("data", (chunk) => data += chunk);
10161
10424
  res.on("end", () => {
10162
10425
  try {
10163
- resolve12(JSON.parse(data));
10426
+ resolve11(JSON.parse(data));
10164
10427
  } catch {
10165
- resolve12({ raw: data });
10428
+ resolve11({ raw: data });
10166
10429
  }
10167
10430
  });
10168
10431
  });
@@ -10180,15 +10443,15 @@ var DaemonCommandHandler = class {
10180
10443
  if (!providerType) return { success: false, error: "providerType required" };
10181
10444
  try {
10182
10445
  const http3 = await import("http");
10183
- const result = await new Promise((resolve12, reject) => {
10446
+ const result = await new Promise((resolve11, reject) => {
10184
10447
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
10185
10448
  let data = "";
10186
10449
  res.on("data", (chunk) => data += chunk);
10187
10450
  res.on("end", () => {
10188
10451
  try {
10189
- resolve12(JSON.parse(data));
10452
+ resolve11(JSON.parse(data));
10190
10453
  } catch {
10191
- resolve12({ raw: data });
10454
+ resolve11({ raw: data });
10192
10455
  }
10193
10456
  });
10194
10457
  }).on("error", reject);
@@ -10202,7 +10465,7 @@ var DaemonCommandHandler = class {
10202
10465
  try {
10203
10466
  const http3 = await import("http");
10204
10467
  const postData = JSON.stringify(args || {});
10205
- const result = await new Promise((resolve12, reject) => {
10468
+ const result = await new Promise((resolve11, reject) => {
10206
10469
  const req = http3.request({
10207
10470
  hostname: "127.0.0.1",
10208
10471
  port: 19280,
@@ -10214,9 +10477,9 @@ var DaemonCommandHandler = class {
10214
10477
  res.on("data", (chunk) => data += chunk);
10215
10478
  res.on("end", () => {
10216
10479
  try {
10217
- resolve12(JSON.parse(data));
10480
+ resolve11(JSON.parse(data));
10218
10481
  } catch {
10219
- resolve12({ raw: data });
10482
+ resolve11({ raw: data });
10220
10483
  }
10221
10484
  });
10222
10485
  });
@@ -10266,6 +10529,9 @@ function getForcedNewSessionScriptName(provider, launchMode) {
10266
10529
  const controls = Array.isArray(provider.controls) ? provider.controls : [];
10267
10530
  for (const control of controls) {
10268
10531
  if (control?.type !== "action") continue;
10532
+ if (typeof control?.confirmTitle === "string" && control.confirmTitle.trim()) continue;
10533
+ if (typeof control?.confirmMessage === "string" && control.confirmMessage.trim()) continue;
10534
+ if (typeof control?.confirmLabel === "string" && control.confirmLabel.trim()) continue;
10269
10535
  const invokeScript = typeof control?.invokeScript === "string" ? control.invokeScript.trim() : "";
10270
10536
  if (!invokeScript) continue;
10271
10537
  const controlId = typeof control?.id === "string" ? control.id.trim() : "";
@@ -10275,6 +10541,20 @@ function getForcedNewSessionScriptName(provider, launchMode) {
10275
10541
  }
10276
10542
  return null;
10277
10543
  }
10544
+ async function waitForCliAdapterReady(adapter, options) {
10545
+ const timeoutMs = Math.max(100, options?.timeoutMs ?? 15e3);
10546
+ const pollMs = Math.max(10, options?.pollMs ?? 50);
10547
+ const deadline = Date.now() + timeoutMs;
10548
+ while (Date.now() < deadline) {
10549
+ if (adapter?.isReady?.()) return;
10550
+ const status = adapter?.getStatus?.()?.status;
10551
+ if (status === "stopped") {
10552
+ throw new Error("CLI runtime stopped before it became ready");
10553
+ }
10554
+ await new Promise((resolve11) => setTimeout(resolve11, pollMs));
10555
+ }
10556
+ throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
10557
+ }
10278
10558
  var CliProviderInstance = class {
10279
10559
  constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, options) {
10280
10560
  this.provider = provider;
@@ -10303,6 +10583,7 @@ var CliProviderInstance = class {
10303
10583
  generatingDebouncePending = null;
10304
10584
  lastApprovalEventAt = 0;
10305
10585
  controlValues = {};
10586
+ summaryMetadata = void 0;
10306
10587
  appliedEffectKeys = /* @__PURE__ */ new Set();
10307
10588
  historyWriter;
10308
10589
  runtimeMessages = [];
@@ -10445,13 +10726,7 @@ var CliProviderInstance = class {
10445
10726
  if (historyMessageCount !== null) {
10446
10727
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
10447
10728
  }
10448
- const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
10449
- if (controlValues) {
10450
- this.controlValues = { ...this.controlValues, ...controlValues };
10451
- }
10452
10729
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
10453
- const currentModel = typeof parsedStatus?.model === "string" && parsedStatus.model.trim() ? parsedStatus.model.trim() : typeof this.controlValues.model === "string" && this.controlValues.model.trim() ? this.controlValues.model.trim() : void 0;
10454
- const currentPlan = typeof parsedStatus?.mode === "string" && parsedStatus.mode.trim() ? parsedStatus.mode.trim() : typeof this.controlValues.mode === "string" && this.controlValues.mode.trim() ? this.controlValues.mode.trim() : void 0;
10455
10730
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
10456
10731
  if (parsedMessages.length > 0) {
10457
10732
  const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
@@ -10473,6 +10748,10 @@ var CliProviderInstance = class {
10473
10748
  }
10474
10749
  }
10475
10750
  this.applyProviderResponse(parsedStatus, { phase: "immediate" });
10751
+ const surface = resolveProviderStateSurface({
10752
+ summaryMetadata: this.summaryMetadata,
10753
+ controlValues: this.controlValues
10754
+ });
10476
10755
  return {
10477
10756
  type: this.type,
10478
10757
  name: this.provider.name,
@@ -10488,8 +10767,6 @@ var CliProviderInstance = class {
10488
10767
  inputContent: ""
10489
10768
  },
10490
10769
  workspace: this.workingDir,
10491
- currentModel,
10492
- currentPlan,
10493
10770
  instanceId: this.instanceId,
10494
10771
  providerSessionId: this.providerSessionId,
10495
10772
  lastUpdated: Date.now(),
@@ -10504,8 +10781,9 @@ var CliProviderInstance = class {
10504
10781
  attachedClients: runtime.attachedClients || []
10505
10782
  } : void 0,
10506
10783
  resume: this.provider.resume,
10507
- controlValues: this.controlValues,
10508
- providerControls: this.provider.controls
10784
+ controlValues: surface.controlValues,
10785
+ providerControls: this.provider.controls,
10786
+ summaryMetadata: surface.summaryMetadata
10509
10787
  };
10510
10788
  }
10511
10789
  setPresentationMode(mode) {
@@ -10553,6 +10831,7 @@ var CliProviderInstance = class {
10553
10831
  const scriptName = getForcedNewSessionScriptName(this.provider, this.launchMode);
10554
10832
  if (!scriptName) return;
10555
10833
  LOG.info("CLI", `[${this.type}] forcing fresh session launch via script: ${scriptName}`);
10834
+ await waitForCliAdapterReady(this.adapter);
10556
10835
  const raw = await this.adapter.invokeScript(scriptName, {});
10557
10836
  const parsed = parseCliScriptResult(raw);
10558
10837
  if (!parsed.success) {
@@ -10708,10 +10987,14 @@ var CliProviderInstance = class {
10708
10987
  this.suppressIdleHistoryReplay = false;
10709
10988
  this.adapter.clearHistory();
10710
10989
  }
10711
- const controlValues = extractProviderControlValues(this.provider.controls, data);
10712
- if (controlValues) {
10713
- this.controlValues = { ...this.controlValues, ...controlValues };
10714
- }
10990
+ const patchedState = mergeProviderPatchState({
10991
+ providerControls: this.provider.controls,
10992
+ data,
10993
+ currentControlValues: this.controlValues,
10994
+ currentSummaryMetadata: this.summaryMetadata
10995
+ });
10996
+ this.controlValues = patchedState.controlValues;
10997
+ this.summaryMetadata = patchedState.summaryMetadata;
10715
10998
  const effects = normalizeProviderEffects(data);
10716
10999
  for (const effect of effects) {
10717
11000
  const effectWhen = effect.when || "immediate";
@@ -10902,6 +11185,7 @@ ${effect.notification.body || ""}`.trim();
10902
11185
  const previousProviderSessionId = this.providerSessionId;
10903
11186
  this.providerSessionId = nextSessionId;
10904
11187
  this.historyWriter.promoteHistorySession(this.type, previousHistorySessionId, nextSessionId);
11188
+ this.historyWriter.writeSessionStart(this.type, nextSessionId, this.workingDir, this.instanceId);
10905
11189
  this.adapter.updateRuntimeMeta({ providerSessionId: nextSessionId });
10906
11190
  this.onProviderSessionResolved?.({
10907
11191
  instanceId: this.instanceId,
@@ -11076,8 +11360,7 @@ var AcpProviderInstance = class {
11076
11360
  lastStatus = "starting";
11077
11361
  generatingStartedAt = 0;
11078
11362
  agentCapabilities = {};
11079
- currentModel;
11080
- currentMode;
11363
+ currentSelections = {};
11081
11364
  activeToolCalls = [];
11082
11365
  stopReason = null;
11083
11366
  partialContent = "";
@@ -11157,8 +11440,6 @@ var AcpProviderInstance = class {
11157
11440
  inputContent: ""
11158
11441
  },
11159
11442
  workspace: this.workingDir,
11160
- currentModel: this.currentModel,
11161
- currentPlan: this.currentMode,
11162
11443
  instanceId: this.instanceId,
11163
11444
  lastUpdated: Date.now(),
11164
11445
  settings: this.settings,
@@ -11169,11 +11450,9 @@ var AcpProviderInstance = class {
11169
11450
  // Error details for dashboard display
11170
11451
  errorMessage: this.errorMessage || void 0,
11171
11452
  errorReason: this.errorReason || void 0,
11172
- controlValues: {
11173
- ...this.currentModel ? { model: this.currentModel } : {},
11174
- ...this.currentMode ? { mode: this.currentMode } : {}
11175
- },
11176
- providerControls: this.provider.controls
11453
+ controlValues: this.getSelectionControlValues(),
11454
+ providerControls: this.provider.controls,
11455
+ summaryMetadata: this.buildSelectionSummaryMetadata()
11177
11456
  };
11178
11457
  }
11179
11458
  onEvent(event, data) {
@@ -11207,6 +11486,54 @@ var AcpProviderInstance = class {
11207
11486
  getInstanceId() {
11208
11487
  return this.instanceId;
11209
11488
  }
11489
+ resolveConfigOptionLabel(category, value) {
11490
+ if (!value) return void 0;
11491
+ const option = this.configOptions.find((entry) => entry.category === category);
11492
+ return option?.options.find((candidate) => candidate.value === value)?.name || value;
11493
+ }
11494
+ resolveModeLabel(modeId) {
11495
+ if (!modeId) return void 0;
11496
+ return this.availableModes.find((mode) => mode.id === modeId)?.name || modeId;
11497
+ }
11498
+ getCurrentSelection(category) {
11499
+ return this.currentSelections[category];
11500
+ }
11501
+ setCurrentSelection(category, value) {
11502
+ const normalized = typeof value === "string" ? value.trim() : "";
11503
+ if (normalized) {
11504
+ this.currentSelections[category] = normalized;
11505
+ return;
11506
+ }
11507
+ delete this.currentSelections[category];
11508
+ }
11509
+ getSelectionControlValues() {
11510
+ const model = this.getCurrentSelection("model");
11511
+ const mode = this.getCurrentSelection("mode");
11512
+ return {
11513
+ ...model ? { model } : {},
11514
+ ...mode ? { mode } : {}
11515
+ };
11516
+ }
11517
+ resolveSelectionLabel(category, value) {
11518
+ if (!value) return void 0;
11519
+ const configLabel = this.resolveConfigOptionLabel(category, value);
11520
+ if (configLabel && configLabel !== value) return configLabel;
11521
+ if (category === "mode") {
11522
+ const modeLabel = this.resolveModeLabel(value);
11523
+ if (modeLabel) return modeLabel;
11524
+ }
11525
+ return configLabel || value;
11526
+ }
11527
+ buildSelectionSummaryMetadata() {
11528
+ const model = this.getCurrentSelection("model");
11529
+ const mode = this.getCurrentSelection("mode");
11530
+ return buildLegacyModelModeSummaryMetadata({
11531
+ model,
11532
+ mode,
11533
+ modelLabel: this.resolveSelectionLabel("model", model),
11534
+ modeLabel: this.resolveSelectionLabel("mode", mode)
11535
+ });
11536
+ }
11210
11537
  // ─── ACP Config Options & Modes ─────────────────────
11211
11538
  parseConfigOptions(raw) {
11212
11539
  if (!Array.isArray(raw)) return;
@@ -11238,12 +11565,14 @@ var AcpProviderInstance = class {
11238
11565
  }
11239
11566
  }
11240
11567
  this.configOptions.push({ category, configId, currentValue, options: flatOptions });
11241
- if (category === "model" && currentValue) this.currentModel = currentValue;
11568
+ if (category === "model" || category === "mode") {
11569
+ this.setCurrentSelection(category, currentValue);
11570
+ }
11242
11571
  }
11243
11572
  }
11244
11573
  parseModes(raw) {
11245
11574
  if (!raw) return;
11246
- if (raw.currentModeId) this.currentMode = raw.currentModeId;
11575
+ this.setCurrentSelection("mode", raw.currentModeId);
11247
11576
  if (Array.isArray(raw.availableModes)) {
11248
11577
  this.availableModes = raw.availableModes.map((m) => ({
11249
11578
  id: m.id,
@@ -11262,8 +11591,7 @@ var AcpProviderInstance = class {
11262
11591
  if (this.useStaticConfig) {
11263
11592
  opt.currentValue = value;
11264
11593
  this.selectedConfig[opt.configId] = value;
11265
- if (category === "model") this.currentModel = value;
11266
- if (category === "mode") this.currentMode = value;
11594
+ if (category === "model" || category === "mode") this.setCurrentSelection(category, value);
11267
11595
  this.log.info(`[${this.type}] Static config ${category} set to: ${value} \u2014 restarting agent`);
11268
11596
  await this.restartWithNewConfig();
11269
11597
  return;
@@ -11281,7 +11609,7 @@ var AcpProviderInstance = class {
11281
11609
  value
11282
11610
  });
11283
11611
  opt.currentValue = value;
11284
- if (category === "model") this.currentModel = value;
11612
+ if (category === "model" || category === "mode") this.setCurrentSelection(category, value);
11285
11613
  if (result?.configOptions) this.parseConfigOptions(result.configOptions);
11286
11614
  this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
11287
11615
  } catch (e) {
@@ -11297,7 +11625,7 @@ var AcpProviderInstance = class {
11297
11625
  opt.currentValue = modeId;
11298
11626
  this.selectedConfig[opt.configId] = modeId;
11299
11627
  }
11300
- this.currentMode = modeId;
11628
+ this.setCurrentSelection("mode", modeId);
11301
11629
  this.log.info(`[${this.type}] Static mode set to: ${modeId} \u2014 restarting agent`);
11302
11630
  await this.restartWithNewConfig();
11303
11631
  return;
@@ -11312,7 +11640,7 @@ var AcpProviderInstance = class {
11312
11640
  sessionId: this.sessionId,
11313
11641
  modeId
11314
11642
  });
11315
- this.currentMode = modeId;
11643
+ this.setCurrentSelection("mode", modeId);
11316
11644
  this.log.info(`[${this.type}] Mode set to: ${modeId}`);
11317
11645
  } catch (e) {
11318
11646
  const message = e?.message || "Unknown ACP mode error";
@@ -11483,13 +11811,13 @@ var AcpProviderInstance = class {
11483
11811
  }
11484
11812
  this.currentStatus = "waiting_approval";
11485
11813
  this.detectStatusTransition();
11486
- const approved = await new Promise((resolve12) => {
11487
- this.permissionResolvers.push(resolve12);
11814
+ const approved = await new Promise((resolve11) => {
11815
+ this.permissionResolvers.push(resolve11);
11488
11816
  setTimeout(() => {
11489
- const idx = this.permissionResolvers.indexOf(resolve12);
11817
+ const idx = this.permissionResolvers.indexOf(resolve11);
11490
11818
  if (idx >= 0) {
11491
11819
  this.permissionResolvers.splice(idx, 1);
11492
- resolve12(false);
11820
+ resolve11(false);
11493
11821
  }
11494
11822
  }, 3e5);
11495
11823
  });
@@ -11570,8 +11898,8 @@ var AcpProviderInstance = class {
11570
11898
  if (result?.modes) this.log.debug(`[${this.type}] modes: ${JSON.stringify(result.modes).slice(0, 300)}`);
11571
11899
  this.parseConfigOptions(result?.configOptions);
11572
11900
  this.parseModes(result?.modes);
11573
- if (!this.currentModel && result?.models?.currentModelId) {
11574
- this.currentModel = result.models.currentModelId;
11901
+ if (!this.getCurrentSelection("model") && result?.models?.currentModelId) {
11902
+ this.setCurrentSelection("model", result.models.currentModelId);
11575
11903
  }
11576
11904
  if (this.configOptions.length === 0 && this.provider.staticConfigOptions?.length) {
11577
11905
  this.useStaticConfig = true;
@@ -11585,13 +11913,16 @@ var AcpProviderInstance = class {
11585
11913
  });
11586
11914
  if (defaultVal) {
11587
11915
  this.selectedConfig[sc.configId] = defaultVal;
11588
- if (sc.category === "model") this.currentModel = defaultVal;
11589
- if (sc.category === "mode") this.currentMode = defaultVal;
11916
+ if (sc.category === "model" || sc.category === "mode") {
11917
+ this.setCurrentSelection(sc.category, defaultVal);
11918
+ }
11590
11919
  }
11591
11920
  }
11592
11921
  this.log.info(`[${this.type}] Using static configOptions (${this.configOptions.length} options)`);
11593
11922
  }
11594
- this.log.info(`[${this.type}] Session created: ${this.sessionId}${this.currentModel ? ` (model: ${this.currentModel})` : ""}${this.currentMode ? ` (mode: ${this.currentMode})` : ""}`);
11923
+ const currentModel = this.getCurrentSelection("model");
11924
+ const currentMode = this.getCurrentSelection("mode");
11925
+ this.log.info(`[${this.type}] Session created: ${this.sessionId}${currentModel ? ` (model: ${currentModel})` : ""}${currentMode ? ` (mode: ${currentMode})` : ""}`);
11595
11926
  if (this.configOptions.length > 0) {
11596
11927
  this.log.info(`[${this.type}] Config options: ${this.configOptions.map((c) => `${c.category}(${c.options.length})`).join(", ")}`);
11597
11928
  }
@@ -11766,7 +12097,7 @@ var AcpProviderInstance = class {
11766
12097
  break;
11767
12098
  }
11768
12099
  case "current_mode_update": {
11769
- this.currentMode = update.currentModeId;
12100
+ this.setCurrentSelection("mode", update.currentModeId);
11770
12101
  break;
11771
12102
  }
11772
12103
  case "config_option_update": {
@@ -11839,7 +12170,7 @@ var AcpProviderInstance = class {
11839
12170
  this.detectStatusTransition();
11840
12171
  }
11841
12172
  if (params.model) {
11842
- this.currentModel = params.model;
12173
+ this.setCurrentSelection("model", params.model);
11843
12174
  }
11844
12175
  }
11845
12176
  /** Map SDK ToolCallStatus to internal status */
@@ -12128,7 +12459,11 @@ var DaemonCliManager = class {
12128
12459
  }
12129
12460
  persistRecentActivity(entry) {
12130
12461
  try {
12131
- let nextState = appendRecentActivity(loadState(), entry);
12462
+ const summaryMetadata = normalizeProviderSummaryMetadata(entry.summaryMetadata);
12463
+ let nextState = appendRecentActivity(loadState(), {
12464
+ ...entry,
12465
+ summaryMetadata
12466
+ });
12132
12467
  if (entry.providerSessionId && (entry.kind === "cli" || entry.kind === "acp")) {
12133
12468
  nextState = upsertSavedProviderSession(nextState, {
12134
12469
  kind: entry.kind,
@@ -12136,7 +12471,7 @@ var DaemonCliManager = class {
12136
12471
  providerName: entry.providerName,
12137
12472
  providerSessionId: entry.providerSessionId,
12138
12473
  workspace: entry.workspace,
12139
- currentModel: entry.currentModel,
12474
+ summaryMetadata,
12140
12475
  title: entry.title
12141
12476
  });
12142
12477
  }
@@ -12326,7 +12661,7 @@ ${installInfo}`
12326
12661
  providerType: normalizedType,
12327
12662
  providerName: provider.displayName || provider.name || normalizedType,
12328
12663
  workspace: resolvedDir,
12329
- currentModel: initialModel,
12664
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
12330
12665
  sessionId,
12331
12666
  title: provider.displayName || provider.name || normalizedType
12332
12667
  });
@@ -12428,7 +12763,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
12428
12763
  providerName: provider?.displayName || provider?.name || normalizedType,
12429
12764
  providerSessionId: sessionBinding.providerSessionId,
12430
12765
  workspace: resolvedDir,
12431
- currentModel: initialModel,
12766
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
12432
12767
  sessionId: key,
12433
12768
  title: provider?.displayName || provider?.name || normalizedType
12434
12769
  });
@@ -12805,6 +13140,9 @@ function validateProviderDefinition(raw) {
12805
13140
  warnings.push(`Unknown provider field: ${key}`);
12806
13141
  }
12807
13142
  }
13143
+ if (provider.disableUpstream !== void 0) {
13144
+ warnings.push("disableUpstream is deprecated in provider definitions; use machine-level provider source policy instead");
13145
+ }
12808
13146
  const category = provider.category;
12809
13147
  if (category === "cli" || category === "acp") {
12810
13148
  const spawn4 = provider.spawn;
@@ -12864,8 +13202,11 @@ function validateControl(control, errors) {
12864
13202
  var ProviderLoader = class _ProviderLoader {
12865
13203
  providers = /* @__PURE__ */ new Map();
12866
13204
  providerAvailability = /* @__PURE__ */ new Map();
13205
+ defaultProvidersDir;
13206
+ explicitProviderDir = null;
12867
13207
  userDir;
12868
13208
  upstreamDir;
13209
+ sourceMode = "normal";
12869
13210
  disableUpstream;
12870
13211
  watchers = [];
12871
13212
  logFn;
@@ -12879,22 +13220,15 @@ var ProviderLoader = class _ProviderLoader {
12879
13220
  static META_FILE = ".meta.json";
12880
13221
  constructor(options) {
12881
13222
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
12882
- const defaultProvidersDir = path14.join(os13.homedir(), ".adhdev", "providers");
12883
- if (options?.userDir) {
12884
- this.userDir = options.userDir;
12885
- this.log(`Config 'providerDir' applied: ${this.userDir}`);
12886
- } else {
12887
- const localRepoPath = path14.resolve(__dirname, "../../../../../adhdev-providers");
12888
- if (fs6.existsSync(localRepoPath)) {
12889
- this.userDir = localRepoPath;
12890
- this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
12891
- } else {
12892
- this.userDir = defaultProvidersDir;
12893
- this.log(`Using default user providers directory: ${this.userDir}`);
12894
- }
12895
- }
12896
- this.upstreamDir = path14.join(defaultProvidersDir, ".upstream");
12897
- this.disableUpstream = options?.disableUpstream ?? false;
13223
+ this.defaultProvidersDir = path14.join(os13.homedir(), ".adhdev", "providers");
13224
+ this.userDir = this.defaultProvidersDir;
13225
+ this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
13226
+ this.disableUpstream = false;
13227
+ this.applySourceConfig({
13228
+ userDir: options?.userDir,
13229
+ sourceMode: options?.sourceMode,
13230
+ disableUpstream: options?.disableUpstream
13231
+ });
12898
13232
  }
12899
13233
  log(msg) {
12900
13234
  this.logFn(`[ProviderLoader] ${msg}`);
@@ -12919,6 +13253,33 @@ var ProviderLoader = class _ProviderLoader {
12919
13253
  getProviderRoots() {
12920
13254
  return [this.userDir, this.upstreamDir];
12921
13255
  }
13256
+ getSourceConfig() {
13257
+ return {
13258
+ sourceMode: this.sourceMode,
13259
+ disableUpstream: this.disableUpstream,
13260
+ explicitProviderDir: this.explicitProviderDir,
13261
+ userDir: this.userDir,
13262
+ upstreamDir: this.upstreamDir,
13263
+ providerRoots: this.getProviderRoots()
13264
+ };
13265
+ }
13266
+ applySourceConfig(options) {
13267
+ const nextSourceMode = options?.sourceMode === "no-upstream" ? "no-upstream" : options?.sourceMode === "normal" ? "normal" : options?.disableUpstream ? "no-upstream" : this.sourceMode || "normal";
13268
+ if (options && Object.prototype.hasOwnProperty.call(options, "userDir")) {
13269
+ this.explicitProviderDir = options.userDir?.trim() ? options.userDir : null;
13270
+ }
13271
+ this.sourceMode = nextSourceMode;
13272
+ this.userDir = this.explicitProviderDir || this.defaultProvidersDir;
13273
+ this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
13274
+ this.disableUpstream = this.sourceMode === "no-upstream";
13275
+ if (this.explicitProviderDir) {
13276
+ this.log(`Config 'providerDir' applied: ${this.userDir}`);
13277
+ } else {
13278
+ this.log(`Using default user providers directory: ${this.userDir}`);
13279
+ }
13280
+ this.log(`Provider source config: mode=${this.sourceMode} explicitProviderDir=${this.explicitProviderDir || "-"} userDir=${this.userDir} upstreamDir=${this.upstreamDir}`);
13281
+ return this.getSourceConfig();
13282
+ }
12922
13283
  /**
12923
13284
  * Canonical provider directory shape for a given root.
12924
13285
  */
@@ -12969,7 +13330,7 @@ var ProviderLoader = class _ProviderLoader {
12969
13330
  this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
12970
13331
  }
12971
13332
  } else if (this.disableUpstream) {
12972
- this.log("Upstream loading disabled (disableUpstream=true)");
13333
+ this.log("Upstream loading disabled (sourceMode=no-upstream)");
12973
13334
  }
12974
13335
  if (fs6.existsSync(this.userDir)) {
12975
13336
  const userCount = this.loadDir(this.userDir, [".upstream"]);
@@ -13480,7 +13841,7 @@ var ProviderLoader = class _ProviderLoader {
13480
13841
  */
13481
13842
  async fetchLatest() {
13482
13843
  if (this.disableUpstream) {
13483
- this.log("Upstream fetch skipped (disableUpstream=true)");
13844
+ this.log("Upstream fetch skipped (sourceMode=no-upstream)");
13484
13845
  return { updated: false };
13485
13846
  }
13486
13847
  const https = require("https");
@@ -13502,7 +13863,7 @@ var ProviderLoader = class _ProviderLoader {
13502
13863
  return { updated: false };
13503
13864
  }
13504
13865
  try {
13505
- const etag = await new Promise((resolve12, reject) => {
13866
+ const etag = await new Promise((resolve11, reject) => {
13506
13867
  const options = {
13507
13868
  method: "HEAD",
13508
13869
  hostname: "github.com",
@@ -13520,7 +13881,7 @@ var ProviderLoader = class _ProviderLoader {
13520
13881
  headers: { "User-Agent": "adhdev-launcher" },
13521
13882
  timeout: 1e4
13522
13883
  }, (res2) => {
13523
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
13884
+ resolve11(res2.headers.etag || res2.headers["last-modified"] || "");
13524
13885
  });
13525
13886
  req2.on("error", reject);
13526
13887
  req2.on("timeout", () => {
@@ -13529,7 +13890,7 @@ var ProviderLoader = class _ProviderLoader {
13529
13890
  });
13530
13891
  req2.end();
13531
13892
  } else {
13532
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
13893
+ resolve11(res.headers.etag || res.headers["last-modified"] || "");
13533
13894
  }
13534
13895
  });
13535
13896
  req.on("error", reject);
@@ -13593,7 +13954,7 @@ var ProviderLoader = class _ProviderLoader {
13593
13954
  downloadFile(url, destPath) {
13594
13955
  const https = require("https");
13595
13956
  const http3 = require("http");
13596
- return new Promise((resolve12, reject) => {
13957
+ return new Promise((resolve11, reject) => {
13597
13958
  const doRequest = (reqUrl, redirectCount = 0) => {
13598
13959
  if (redirectCount > 5) {
13599
13960
  reject(new Error("Too many redirects"));
@@ -13613,7 +13974,7 @@ var ProviderLoader = class _ProviderLoader {
13613
13974
  res.pipe(ws);
13614
13975
  ws.on("finish", () => {
13615
13976
  ws.close();
13616
- resolve12();
13977
+ resolve11();
13617
13978
  });
13618
13979
  ws.on("error", reject);
13619
13980
  });
@@ -14088,17 +14449,17 @@ async function findFreePort(ports) {
14088
14449
  throw new Error("No free port found");
14089
14450
  }
14090
14451
  function checkPortFree(port) {
14091
- return new Promise((resolve12) => {
14452
+ return new Promise((resolve11) => {
14092
14453
  const server = net.createServer();
14093
14454
  server.unref();
14094
- server.on("error", () => resolve12(false));
14455
+ server.on("error", () => resolve11(false));
14095
14456
  server.listen(port, "127.0.0.1", () => {
14096
- server.close(() => resolve12(true));
14457
+ server.close(() => resolve11(true));
14097
14458
  });
14098
14459
  });
14099
14460
  }
14100
14461
  async function isCdpActive(port) {
14101
- return new Promise((resolve12) => {
14462
+ return new Promise((resolve11) => {
14102
14463
  const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
14103
14464
  timeout: 2e3
14104
14465
  }, (res) => {
@@ -14107,16 +14468,16 @@ async function isCdpActive(port) {
14107
14468
  res.on("end", () => {
14108
14469
  try {
14109
14470
  const info = JSON.parse(data);
14110
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
14471
+ resolve11(!!info["WebKit-Version"] || !!info["Browser"]);
14111
14472
  } catch {
14112
- resolve12(false);
14473
+ resolve11(false);
14113
14474
  }
14114
14475
  });
14115
14476
  });
14116
- req.on("error", () => resolve12(false));
14477
+ req.on("error", () => resolve11(false));
14117
14478
  req.on("timeout", () => {
14118
14479
  req.destroy();
14119
- resolve12(false);
14480
+ resolve11(false);
14120
14481
  });
14121
14482
  });
14122
14483
  }
@@ -14567,12 +14928,90 @@ cleanOldFiles();
14567
14928
  // src/commands/router.ts
14568
14929
  init_logger();
14569
14930
 
14931
+ // src/session-host/runtime-surface.ts
14932
+ var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
14933
+ function isSessionHostLiveRuntime(record) {
14934
+ const lifecycle = String(record?.lifecycle || "").trim();
14935
+ return LIVE_LIFECYCLES.has(lifecycle);
14936
+ }
14937
+ function getSessionHostRecoveryLabel(meta) {
14938
+ const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
14939
+ if (!recoveryState) return null;
14940
+ if (recoveryState === "auto_resumed") return "restored after restart";
14941
+ if (recoveryState === "resume_failed") return "restore failed";
14942
+ if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
14943
+ if (recoveryState === "orphan_snapshot") return "snapshot recovered";
14944
+ return recoveryState.replace(/_/g, " ");
14945
+ }
14946
+ function isSessionHostRecoverySnapshot(record) {
14947
+ if (!record) return false;
14948
+ if (isSessionHostLiveRuntime(record)) return false;
14949
+ const lifecycle = String(record.lifecycle || "").trim();
14950
+ if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
14951
+ return false;
14952
+ }
14953
+ const meta = record.meta || void 0;
14954
+ if (meta?.restoredFromStorage === true) return true;
14955
+ return getSessionHostRecoveryLabel(meta) !== null;
14956
+ }
14957
+ function getSessionHostSurfaceKind(record) {
14958
+ if (isSessionHostLiveRuntime(record)) return "live_runtime";
14959
+ if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
14960
+ return "inactive_record";
14961
+ }
14962
+ function partitionSessionHostRecords(records) {
14963
+ const liveRuntimes = [];
14964
+ const recoverySnapshots = [];
14965
+ const inactiveRecords = [];
14966
+ for (const record of records) {
14967
+ const kind = getSessionHostSurfaceKind(record);
14968
+ if (kind === "live_runtime") {
14969
+ liveRuntimes.push(record);
14970
+ } else if (kind === "recovery_snapshot") {
14971
+ recoverySnapshots.push(record);
14972
+ } else {
14973
+ inactiveRecords.push(record);
14974
+ }
14975
+ }
14976
+ return {
14977
+ liveRuntimes,
14978
+ recoverySnapshots,
14979
+ inactiveRecords
14980
+ };
14981
+ }
14982
+ function partitionSessionHostDiagnosticsSessions(records) {
14983
+ return partitionSessionHostRecords(records || []);
14984
+ }
14985
+
14570
14986
  // src/status/snapshot.ts
14571
14987
  var os16 = __toESM(require("os"));
14572
14988
  init_config();
14573
14989
  init_terminal_screen();
14574
14990
  init_logger();
14575
14991
  var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
14992
+ var recentReadDebugSignatureBySession = /* @__PURE__ */ new Map();
14993
+ function buildRecentReadDebugSignature(snapshot) {
14994
+ return [
14995
+ snapshot.providerType,
14996
+ snapshot.status,
14997
+ snapshot.inboxBucket,
14998
+ snapshot.unread ? "1" : "0",
14999
+ String(snapshot.lastSeenAt),
15000
+ snapshot.completionMarker,
15001
+ snapshot.seenCompletionMarker,
15002
+ String(snapshot.lastUpdated),
15003
+ String(snapshot.lastUsedAt),
15004
+ snapshot.lastRole,
15005
+ String(snapshot.messageUpdatedAt)
15006
+ ].join("|");
15007
+ }
15008
+ function shouldEmitRecentReadDebugLog(cache, snapshot) {
15009
+ const nextSignature = buildRecentReadDebugSignature(snapshot);
15010
+ const previousSignature = cache.get(snapshot.sessionId);
15011
+ if (previousSignature === nextSignature) return false;
15012
+ cache.set(snapshot.sessionId, nextSignature);
15013
+ return true;
15014
+ }
14576
15015
  function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
14577
15016
  return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
14578
15017
  id: ide.id,
@@ -14724,7 +15163,7 @@ function buildRecentLaunches(recentActivity) {
14724
15163
  providerSessionId: item.providerSessionId,
14725
15164
  title: item.title || item.providerName,
14726
15165
  workspace: item.workspace,
14727
- currentModel: item.currentModel,
15166
+ summaryMetadata: item.summaryMetadata,
14728
15167
  lastLaunchedAt: item.lastUsedAt
14729
15168
  })).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
14730
15169
  }
@@ -14765,9 +15204,24 @@ function buildStatusSnapshot(options) {
14765
15204
  session.unread = unread;
14766
15205
  session.inboxBucket = inboxBucket;
14767
15206
  if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
15207
+ const recentReadSnapshot = {
15208
+ sessionId: session.id,
15209
+ providerType: session.providerType,
15210
+ status: String(session.status || ""),
15211
+ inboxBucket,
15212
+ unread,
15213
+ lastSeenAt,
15214
+ completionMarker: completionMarker || "-",
15215
+ seenCompletionMarker: seenCompletionMarker || "-",
15216
+ lastUpdated: Number(session.lastUpdated || 0),
15217
+ lastUsedAt,
15218
+ lastRole: getLastMessageRole(sourceSession),
15219
+ messageUpdatedAt: getSessionMessageUpdatedAt(sourceSession)
15220
+ };
15221
+ if (!shouldEmitRecentReadDebugLog(recentReadDebugSignatureBySession, recentReadSnapshot)) continue;
14768
15222
  LOG.info(
14769
15223
  "RecentRead",
14770
- `snapshot session id=${session.id} provider=${session.providerType} status=${String(session.status || "")} bucket=${inboxBucket} unread=${String(unread)} lastSeenAt=${lastSeenAt} completionMarker=${completionMarker || "-"} seenMarker=${seenCompletionMarker || "-"} lastUpdated=${String(session.lastUpdated || 0)} lastUsedAt=${lastUsedAt} lastRole=${getLastMessageRole(sourceSession)} msgUpdatedAt=${getSessionMessageUpdatedAt(sourceSession)}`
15224
+ `snapshot session id=${recentReadSnapshot.sessionId} provider=${recentReadSnapshot.providerType} status=${recentReadSnapshot.status} bucket=${recentReadSnapshot.inboxBucket} unread=${String(recentReadSnapshot.unread)} lastSeenAt=${recentReadSnapshot.lastSeenAt} completionMarker=${recentReadSnapshot.completionMarker} seenMarker=${recentReadSnapshot.seenCompletionMarker} lastUpdated=${String(recentReadSnapshot.lastUpdated)} lastUsedAt=${recentReadSnapshot.lastUsedAt} lastRole=${recentReadSnapshot.lastRole} msgUpdatedAt=${recentReadSnapshot.messageUpdatedAt}`
14771
15225
  );
14772
15226
  }
14773
15227
  const lastDisplayMessage = getLastDisplayMessage(sourceSession);
@@ -14845,7 +15299,7 @@ async function waitForPidExit(pid, timeoutMs) {
14845
15299
  while (Date.now() - start < timeoutMs) {
14846
15300
  try {
14847
15301
  process.kill(pid, 0);
14848
- await new Promise((resolve12) => setTimeout(resolve12, 250));
15302
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
14849
15303
  } catch {
14850
15304
  return;
14851
15305
  }
@@ -14960,7 +15414,7 @@ async function runDaemonUpgradeHelper(payload) {
14960
15414
  appendUpgradeLog(installOutput.trim());
14961
15415
  }
14962
15416
  if (process.platform === "win32") {
14963
- await new Promise((resolve12) => setTimeout(resolve12, 500));
15417
+ await new Promise((resolve11) => setTimeout(resolve11, 500));
14964
15418
  cleanupStaleGlobalInstallDirs(payload.packageName);
14965
15419
  appendUpgradeLog("Post-install staging cleanup complete");
14966
15420
  }
@@ -15042,11 +15496,104 @@ function toHostedCliRuntimeDescriptor(record) {
15042
15496
  providerSessionId: typeof record.meta?.providerSessionId === "string" ? String(record.meta.providerSessionId) : void 0
15043
15497
  };
15044
15498
  }
15499
+ function getWriteConflictOwnerClientId(error) {
15500
+ const message = typeof error === "string" ? error : error instanceof Error ? error.message : "";
15501
+ const match = /^Write owned by\s+(.+)$/.exec(message.trim());
15502
+ return match?.[1]?.trim() || void 0;
15503
+ }
15504
+ function summarizeSessionHostRecord(result) {
15505
+ if (!result || typeof result !== "object") return {};
15506
+ const record = result;
15507
+ return {
15508
+ runtimeKey: typeof record.runtimeKey === "string" ? record.runtimeKey : void 0,
15509
+ lifecycle: typeof record.lifecycle === "string" ? record.lifecycle : void 0,
15510
+ surfaceKind: getSessionHostSurfaceKind(record),
15511
+ attachedClientCount: Array.isArray(record.attachedClients) ? record.attachedClients.length : void 0,
15512
+ hasWriteOwner: !!record.writeOwner,
15513
+ writeOwnerClientId: typeof record.writeOwner?.clientId === "string" ? record.writeOwner.clientId : void 0
15514
+ };
15515
+ }
15516
+ function summarizeSessionHostRecords(result) {
15517
+ const records = Array.isArray(result) ? result : [];
15518
+ const groups = partitionSessionHostRecords(records);
15519
+ return {
15520
+ sessionCount: records.length,
15521
+ liveRuntimeCount: groups.liveRuntimes.length,
15522
+ recoverySnapshotCount: groups.recoverySnapshots.length,
15523
+ inactiveRecordCount: groups.inactiveRecords.length
15524
+ };
15525
+ }
15526
+ function summarizeSessionHostDiagnostics(result) {
15527
+ const diagnostics = result && typeof result === "object" ? result : {};
15528
+ const sessions = Array.isArray(diagnostics.sessions) ? diagnostics.sessions : [];
15529
+ return {
15530
+ runtimeCount: typeof diagnostics.runtimeCount === "number" ? diagnostics.runtimeCount : void 0,
15531
+ ...summarizeSessionHostRecords(sessions)
15532
+ };
15533
+ }
15534
+ function summarizeSessionHostPruneResult(result) {
15535
+ const value = result && typeof result === "object" ? result : {};
15536
+ return {
15537
+ duplicateGroupCount: typeof value.duplicateGroupCount === "number" ? value.duplicateGroupCount : void 0,
15538
+ prunedCount: Array.isArray(value.prunedSessionIds) ? value.prunedSessionIds.length : void 0,
15539
+ keptCount: Array.isArray(value.keptSessionIds) ? value.keptSessionIds.length : void 0
15540
+ };
15541
+ }
15045
15542
  var DaemonCommandRouter = class {
15046
15543
  deps;
15047
15544
  constructor(deps) {
15048
15545
  this.deps = deps;
15049
15546
  }
15547
+ async traceSessionHostAction(action, args, run, summarizeResult) {
15548
+ const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
15549
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
15550
+ const requestedPayload = { action };
15551
+ if (sessionId) requestedPayload.sessionId = sessionId;
15552
+ if (typeof args?.clientId === "string") requestedPayload.clientId = args.clientId;
15553
+ if (typeof args?.signal === "string") requestedPayload.signal = args.signal;
15554
+ if (typeof args?.providerType === "string") requestedPayload.providerType = args.providerType;
15555
+ if (typeof args?.workspace === "string") requestedPayload.workspace = args.workspace;
15556
+ if (typeof args?.dryRun === "boolean") requestedPayload.dryRun = args.dryRun;
15557
+ recordDebugTrace({
15558
+ interactionId,
15559
+ category: "session_host",
15560
+ stage: "action_requested",
15561
+ level: "info",
15562
+ sessionId,
15563
+ payload: requestedPayload
15564
+ });
15565
+ try {
15566
+ const result = await run();
15567
+ recordDebugTrace({
15568
+ interactionId,
15569
+ category: "session_host",
15570
+ stage: "action_result",
15571
+ level: "info",
15572
+ sessionId,
15573
+ payload: {
15574
+ ...requestedPayload,
15575
+ success: true,
15576
+ ...summarizeResult ? summarizeResult(result) : {}
15577
+ }
15578
+ });
15579
+ return result;
15580
+ } catch (error) {
15581
+ recordDebugTrace({
15582
+ interactionId,
15583
+ category: "session_host",
15584
+ stage: "action_failed",
15585
+ level: "error",
15586
+ sessionId,
15587
+ payload: {
15588
+ ...requestedPayload,
15589
+ error: error?.message || String(error),
15590
+ failureKind: getWriteConflictOwnerClientId(error) ? "write_conflict" : "request_failed",
15591
+ conflictOwnerClientId: getWriteConflictOwnerClientId(error)
15592
+ }
15593
+ });
15594
+ throw error;
15595
+ }
15596
+ }
15050
15597
  /**
15051
15598
  * Unified command routing.
15052
15599
  * Returns result for all commands:
@@ -15156,44 +15703,60 @@ var DaemonCommandRouter = class {
15156
15703
  }
15157
15704
  case "session_host_get_diagnostics": {
15158
15705
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15159
- const diagnostics = await this.deps.sessionHostControl.getDiagnostics({
15706
+ const diagnostics = await this.traceSessionHostAction("session_host_get_diagnostics", args, () => this.deps.sessionHostControl.getDiagnostics({
15160
15707
  includeSessions: args?.includeSessions !== false,
15161
15708
  limit: Number(args?.limit) || void 0
15162
- });
15709
+ }), (result) => ({
15710
+ includeSessions: args?.includeSessions !== false,
15711
+ limit: Number(args?.limit) || void 0,
15712
+ ...summarizeSessionHostDiagnostics(result)
15713
+ }));
15163
15714
  return { success: true, diagnostics };
15164
15715
  }
15165
15716
  case "session_host_list_sessions": {
15166
15717
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15167
- const sessions = await this.deps.sessionHostControl.listSessions();
15718
+ const sessions = await this.traceSessionHostAction("session_host_list_sessions", args, () => this.deps.sessionHostControl.listSessions(), (records) => summarizeSessionHostRecords(records));
15168
15719
  return { success: true, sessions };
15169
15720
  }
15170
15721
  case "session_host_stop_session": {
15171
15722
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15172
15723
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15173
15724
  if (!sessionId) return { success: false, error: "sessionId required" };
15174
- const record = await this.deps.sessionHostControl.stopSession(sessionId);
15725
+ const record = await this.traceSessionHostAction("session_host_stop_session", args, () => this.deps.sessionHostControl.stopSession(sessionId), (result) => summarizeSessionHostRecord(result));
15175
15726
  return { success: true, record };
15176
15727
  }
15177
15728
  case "session_host_resume_session": {
15178
15729
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15179
15730
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15180
15731
  if (!sessionId) return { success: false, error: "sessionId required" };
15181
- const record = await this.deps.sessionHostControl.resumeSession(sessionId);
15182
- const hosted = toHostedCliRuntimeDescriptor(record);
15183
- if (hosted) {
15184
- await this.deps.cliManager.restoreHostedSessions([hosted]);
15185
- }
15732
+ const record = await this.traceSessionHostAction("session_host_resume_session", args, async () => {
15733
+ const nextRecord = await this.deps.sessionHostControl.resumeSession(sessionId);
15734
+ const hosted = toHostedCliRuntimeDescriptor(nextRecord);
15735
+ if (hosted) {
15736
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
15737
+ }
15738
+ return nextRecord;
15739
+ }, (result) => ({
15740
+ ...summarizeSessionHostRecord(result),
15741
+ restoredHostedSession: !!toHostedCliRuntimeDescriptor(result)
15742
+ }));
15186
15743
  return { success: true, record };
15187
15744
  }
15188
15745
  case "session_host_restart_session": {
15189
15746
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15190
15747
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15191
15748
  if (!sessionId) return { success: false, error: "sessionId required" };
15192
- const record = await this.deps.sessionHostControl.restartSession(sessionId);
15193
- const hosted = toHostedCliRuntimeDescriptor(record);
15194
- if (hosted) {
15195
- await this.deps.cliManager.restoreHostedSessions([hosted]);
15196
- }
15749
+ const record = await this.traceSessionHostAction("session_host_restart_session", args, async () => {
15750
+ const nextRecord = await this.deps.sessionHostControl.restartSession(sessionId);
15751
+ const hosted = toHostedCliRuntimeDescriptor(nextRecord);
15752
+ if (hosted) {
15753
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
15754
+ }
15755
+ return nextRecord;
15756
+ }, (result) => ({
15757
+ ...summarizeSessionHostRecord(result),
15758
+ restoredHostedSession: !!toHostedCliRuntimeDescriptor(result)
15759
+ }));
15197
15760
  return { success: true, record };
15198
15761
  }
15199
15762
  case "session_host_send_signal": {
@@ -15202,7 +15765,7 @@ var DaemonCommandRouter = class {
15202
15765
  const signal = typeof args?.signal === "string" ? args.signal : "";
15203
15766
  if (!sessionId) return { success: false, error: "sessionId required" };
15204
15767
  if (!signal) return { success: false, error: "signal required" };
15205
- const record = await this.deps.sessionHostControl.sendSignal(sessionId, signal);
15768
+ const record = await this.traceSessionHostAction("session_host_send_signal", args, () => this.deps.sessionHostControl.sendSignal(sessionId, signal), (result) => summarizeSessionHostRecord(result));
15206
15769
  return { success: true, record };
15207
15770
  }
15208
15771
  case "session_host_force_detach_client": {
@@ -15211,16 +15774,16 @@ var DaemonCommandRouter = class {
15211
15774
  const clientId = typeof args?.clientId === "string" ? args.clientId : "";
15212
15775
  if (!sessionId) return { success: false, error: "sessionId required" };
15213
15776
  if (!clientId) return { success: false, error: "clientId required" };
15214
- const record = await this.deps.sessionHostControl.forceDetachClient(sessionId, clientId);
15777
+ const record = await this.traceSessionHostAction("session_host_force_detach_client", args, () => this.deps.sessionHostControl.forceDetachClient(sessionId, clientId), (result) => summarizeSessionHostRecord(result));
15215
15778
  return { success: true, record };
15216
15779
  }
15217
15780
  case "session_host_prune_duplicate_sessions": {
15218
15781
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15219
- const result = await this.deps.sessionHostControl.pruneDuplicateSessions({
15782
+ const result = await this.traceSessionHostAction("session_host_prune_duplicate_sessions", args, () => this.deps.sessionHostControl.pruneDuplicateSessions({
15220
15783
  providerType: typeof args?.providerType === "string" ? args.providerType : void 0,
15221
15784
  workspace: typeof args?.workspace === "string" ? args.workspace : void 0,
15222
15785
  dryRun: args?.dryRun === true
15223
- });
15786
+ }), (value) => summarizeSessionHostPruneResult(value));
15224
15787
  return { success: true, result };
15225
15788
  }
15226
15789
  case "session_host_acquire_write": {
@@ -15230,12 +15793,15 @@ var DaemonCommandRouter = class {
15230
15793
  const ownerType = args?.ownerType === "agent" ? "agent" : "user";
15231
15794
  if (!sessionId) return { success: false, error: "sessionId required" };
15232
15795
  if (!clientId) return { success: false, error: "clientId required" };
15233
- const record = await this.deps.sessionHostControl.acquireWrite({
15796
+ const record = await this.traceSessionHostAction("session_host_acquire_write", args, () => this.deps.sessionHostControl.acquireWrite({
15234
15797
  sessionId,
15235
15798
  clientId,
15236
15799
  ownerType,
15237
15800
  force: args?.force !== false
15238
- });
15801
+ }), (result) => ({
15802
+ ...summarizeSessionHostRecord(result),
15803
+ ownerType
15804
+ }));
15239
15805
  return { success: true, record };
15240
15806
  }
15241
15807
  case "session_host_release_write": {
@@ -15244,7 +15810,10 @@ var DaemonCommandRouter = class {
15244
15810
  const clientId = typeof args?.clientId === "string" ? args.clientId : "";
15245
15811
  if (!sessionId) return { success: false, error: "sessionId required" };
15246
15812
  if (!clientId) return { success: false, error: "clientId required" };
15247
- const record = await this.deps.sessionHostControl.releaseWrite({ sessionId, clientId });
15813
+ const record = await this.traceSessionHostAction("session_host_release_write", args, () => this.deps.sessionHostControl.releaseWrite({
15814
+ sessionId,
15815
+ clientId
15816
+ }), (result) => summarizeSessionHostRecord(result));
15248
15817
  return { success: true, record };
15249
15818
  }
15250
15819
  case "list_saved_sessions": {
@@ -15253,8 +15822,9 @@ var DaemonCommandRouter = class {
15253
15822
  if (!providerType) {
15254
15823
  return { success: false, error: "providerType required" };
15255
15824
  }
15256
- const offset = Math.max(0, Number(args?.offset) || 0);
15257
- const limit = Math.max(1, Math.min(100, Number(args?.limit) || 30));
15825
+ const wantsAll = args?.all === true;
15826
+ const offset = wantsAll ? 0 : Math.max(0, Number(args?.offset) || 0);
15827
+ const limit = wantsAll ? Number.MAX_SAFE_INTEGER : Math.max(1, Math.min(100, Number(args?.limit) || 30));
15258
15828
  const { sessions: historySessions, hasMore } = listSavedHistorySessions(providerType, { offset, limit });
15259
15829
  const state = loadState();
15260
15830
  const savedSessions = getSavedProviderSessions(state, { providerType, kind });
@@ -15275,13 +15845,13 @@ var DaemonCommandRouter = class {
15275
15845
  providerName: saved?.providerName || recent?.providerName || providerType,
15276
15846
  kind: saved?.kind || recent?.kind || kind,
15277
15847
  title: saved?.title || recent?.title || session.sessionTitle || session.preview || providerType,
15278
- workspace: saved?.workspace || recent?.workspace,
15279
- currentModel: saved?.currentModel || recent?.currentModel,
15848
+ workspace: saved?.workspace || recent?.workspace || session.workspace,
15849
+ summaryMetadata: saved?.summaryMetadata || recent?.summaryMetadata,
15280
15850
  preview: session.preview,
15281
15851
  messageCount: session.messageCount,
15282
15852
  firstMessageAt: session.firstMessageAt,
15283
15853
  lastMessageAt: session.lastMessageAt,
15284
- canResume: !!(saved?.workspace || recent?.workspace) && canResumeById
15854
+ canResume: !!(saved?.workspace || recent?.workspace || session.workspace) && canResumeById
15285
15855
  };
15286
15856
  }),
15287
15857
  hasMore
@@ -15715,7 +16285,7 @@ var DaemonStatusReporter = class {
15715
16285
  const ideSummary = ideStates.map((s) => {
15716
16286
  const msgs = s.activeChat?.messages?.length || 0;
15717
16287
  const exts = s.extensions.length;
15718
- return `${s.type}(${s.status},${msgs}msg,${exts}ext${s.currentModel ? ",model=" + s.currentModel : ""})`;
16288
+ return `${s.type}(${s.status},${msgs}msg,${exts}ext)`;
15719
16289
  }).join(", ");
15720
16290
  const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
15721
16291
  const acpSummary = acpStates.map((s) => `${s.type}(${s.status})`).join(", ");
@@ -15777,9 +16347,7 @@ var DaemonStatusReporter = class {
15777
16347
  workspace: session.workspace ?? null,
15778
16348
  title: session.title,
15779
16349
  cdpConnected: session.cdpConnected,
15780
- currentModel: session.currentModel,
15781
- currentPlan: session.currentPlan,
15782
- currentAutoApprove: session.currentAutoApprove
16350
+ summaryMetadata: session.summaryMetadata
15783
16351
  })),
15784
16352
  p2p: payload.p2p,
15785
16353
  timestamp: now
@@ -15898,7 +16466,7 @@ var ProviderStreamAdapter = class {
15898
16466
  const beforeCount = this.messageCount(before);
15899
16467
  const beforeSignature = this.lastMessageSignature(before);
15900
16468
  for (let attempt = 0; attempt < 12; attempt += 1) {
15901
- await new Promise((resolve12) => setTimeout(resolve12, 250));
16469
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
15902
16470
  let state;
15903
16471
  try {
15904
16472
  state = await this.readChat(evaluate);
@@ -15920,7 +16488,7 @@ var ProviderStreamAdapter = class {
15920
16488
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
15921
16489
  return first;
15922
16490
  }
15923
- await new Promise((resolve12) => setTimeout(resolve12, 150));
16491
+ await new Promise((resolve11) => setTimeout(resolve11, 150));
15924
16492
  const second = await this.readChat(evaluate);
15925
16493
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
15926
16494
  }
@@ -15945,15 +16513,18 @@ var ProviderStreamAdapter = class {
15945
16513
  status: data.status || "idle",
15946
16514
  messages: data.messages || [],
15947
16515
  inputContent: data.inputContent || "",
15948
- model: data.model,
15949
- mode: data.mode,
15950
16516
  activeModal: data.activeModal
15951
16517
  };
15952
16518
  if (typeof data.title === "string" && data.title.trim()) {
15953
16519
  state.title = data.title.trim();
15954
16520
  }
15955
16521
  const controlValues = extractProviderControlValues(this.provider.controls, data);
15956
- if (controlValues) state.controlValues = controlValues;
16522
+ const surface = resolveProviderStateSurface({
16523
+ controlValues,
16524
+ summaryMetadata: data.summaryMetadata
16525
+ });
16526
+ if (surface.controlValues) state.controlValues = surface.controlValues;
16527
+ if (surface.summaryMetadata) state.summaryMetadata = surface.summaryMetadata;
15957
16528
  const effects = normalizeProviderEffects(data);
15958
16529
  if (effects.length > 0) state.effects = effects;
15959
16530
  if (state.messages.length > 0) {
@@ -16060,7 +16631,7 @@ var ProviderStreamAdapter = class {
16060
16631
  if (typeof data.error === "string" && data.error.trim()) return false;
16061
16632
  }
16062
16633
  for (let attempt = 0; attempt < 6; attempt += 1) {
16063
- await new Promise((resolve12) => setTimeout(resolve12, 250));
16634
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
16064
16635
  const state = await this.readChat(evaluate);
16065
16636
  const title = this.getStateTitle(state);
16066
16637
  if (this.titlesMatch(title, sessionId)) return true;
@@ -16227,7 +16798,8 @@ var DaemonAgentStreamManager = class {
16227
16798
  const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
16228
16799
  const state = await agent.adapter.readChat(evaluate);
16229
16800
  const stateError = this.getStateError(state);
16230
- LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${state.model || ""}${state.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
16801
+ const selectedModelValue = typeof state.controlValues?.model === "string" ? state.controlValues.model : "";
16802
+ LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${selectedModelValue}${state.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
16231
16803
  if (state.status === "error" && this.isRecoverableSessionError(stateError)) {
16232
16804
  throw new Error(stateError);
16233
16805
  }
@@ -16575,9 +17147,8 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
16575
17147
  messages: stream.messages || [],
16576
17148
  status: stream.status || "idle",
16577
17149
  activeModal: stream.activeModal || null,
16578
- model: stream.model || void 0,
16579
- mode: stream.mode || void 0,
16580
17150
  controlValues: stream.controlValues || void 0,
17151
+ summaryMetadata: stream.summaryMetadata || void 0,
16581
17152
  effects: stream.effects || void 0,
16582
17153
  sessionId: stream.sessionId || stream.instanceId || void 0,
16583
17154
  title: stream.title || stream.agentName || void 0,
@@ -16982,6 +17553,7 @@ async function detectAllVersions(loader, archive) {
16982
17553
  var http2 = __toESM(require("http"));
16983
17554
  var fs14 = __toESM(require("fs"));
16984
17555
  var path22 = __toESM(require("path"));
17556
+ init_config();
16985
17557
 
16986
17558
  // src/daemon/scaffold-template.ts
16987
17559
  function generateFiles(type, name, category, opts = {}) {
@@ -17112,7 +17684,11 @@ module.exports.setMode = (params) => {
17112
17684
  * 5. Approval dialog detection (buttons, modal)
17113
17685
  * 6. Input field selector
17114
17686
  *
17115
- * \u2192 { id, status, title, messages[], inputContent, activeModal }
17687
+ * Preferred live-state surface:
17688
+ * - controlValues: explicit current control selections (model/mode/etc.)
17689
+ * - summaryMetadata: compact always-visible metadata for dashboard/recent views
17690
+ * Legacy top-level model/mode output is no longer the preferred shape.
17691
+ * \u2192 { id, status, title, messages[], inputContent, activeModal, controlValues?, summaryMetadata? }
17116
17692
  */
17117
17693
  (() => {
17118
17694
  try {
@@ -17140,6 +17716,9 @@ module.exports.setMode = (params) => {
17140
17716
  messages,
17141
17717
  inputContent,
17142
17718
  activeModal,
17719
+ // TODO: Return explicit selections when available, e.g.
17720
+ // controlValues: { model: selectedModel, mode: selectedMode },
17721
+ // summaryMetadata: { items: [{ id: 'model', value: selectedModelLabel || selectedModel, shortValue: selectedModel, order: 10 }] },
17143
17722
  });
17144
17723
  } catch(e) {
17145
17724
  return JSON.stringify({ id: '', status: 'error', messages: [], error: e.message });
@@ -18518,7 +19097,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
18518
19097
  return { target, instance, adapter };
18519
19098
  }
18520
19099
  function sleep(ms) {
18521
- return new Promise((resolve12) => setTimeout(resolve12, ms));
19100
+ return new Promise((resolve11) => setTimeout(resolve11, ms));
18522
19101
  }
18523
19102
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
18524
19103
  const startedAt = Date.now();
@@ -18880,7 +19459,6 @@ async function handleCliStatus(ctx, _req, res) {
18880
19459
  lastMessage: s.activeChat?.messages?.slice(-1)[0] || null,
18881
19460
  activeModal: s.activeChat?.activeModal || null,
18882
19461
  pendingEvents: s.pendingEvents || [],
18883
- currentModel: s.currentModel,
18884
19462
  settings: s.settings
18885
19463
  }));
18886
19464
  ctx.json(res, 200, { instances: result, count: result.length });
@@ -19365,18 +19943,6 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
19365
19943
  if (!fs13.existsSync(providerJson)) {
19366
19944
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
19367
19945
  }
19368
- try {
19369
- const providerData = JSON.parse(fs13.readFileSync(providerJson, "utf-8"));
19370
- if (providerData.disableUpstream !== true) {
19371
- providerData.disableUpstream = true;
19372
- fs13.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
19373
- }
19374
- } catch (error) {
19375
- return {
19376
- dir: null,
19377
- reason: `Failed to update provider.json in writable provider directory: ${error.message}`
19378
- };
19379
- }
19380
19946
  return { dir: desiredDir };
19381
19947
  }
19382
19948
  function loadAutoImplReferenceScripts(ctx, referenceType) {
@@ -20049,7 +20615,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
20049
20615
  lines.push("## Required Return Format");
20050
20616
  lines.push("| Function | Return JSON |");
20051
20617
  lines.push("|---|---|");
20052
- lines.push("| readChat | `{ id, status, title, messages: [{role, content, index, kind?, meta?}], inputContent, activeModal }` \u2014 optional `kind`: standard, thought, tool, terminal; optional `meta`: e.g. `{ label, isRunning }` for dashboard |");
20618
+ lines.push("| readChat | `{ id, status, title, messages: [{role, content, index, kind?, meta?}], inputContent, activeModal, controlValues?, summaryMetadata? }` \u2014 optional `kind`: standard, thought, tool, terminal; prefer explicit `controlValues` for current selections and `summaryMetadata` for compact always-visible UI metadata |");
20053
20619
  lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
20054
20620
  lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
20055
20621
  lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
@@ -20663,6 +21229,7 @@ var DevServer = class _DevServer {
20663
21229
  cdpManagers;
20664
21230
  instanceManager;
20665
21231
  cliManager;
21232
+ onProviderSourceConfigChanged;
20666
21233
  logFn;
20667
21234
  sseClients = [];
20668
21235
  watchScriptPath = null;
@@ -20679,6 +21246,7 @@ var DevServer = class _DevServer {
20679
21246
  this.cdpManagers = options.cdpManagers;
20680
21247
  this.instanceManager = options.instanceManager || null;
20681
21248
  this.cliManager = options.cliManager || null;
21249
+ this.onProviderSourceConfigChanged = options.onProviderSourceConfigChanged || null;
20682
21250
  this.logFn = options.logFn || LOG.forComponent("DevServer").asLogFn();
20683
21251
  }
20684
21252
  log(msg) {
@@ -20688,6 +21256,8 @@ var DevServer = class _DevServer {
20688
21256
  routes = [
20689
21257
  // Static routes
20690
21258
  { method: "GET", pattern: "/api/providers", handler: (q, s) => this.handleListProviders(q, s) },
21259
+ { method: "GET", pattern: "/api/providers/source-config", handler: (q, s) => this.handleGetProviderSourceConfig(q, s) },
21260
+ { method: "POST", pattern: "/api/providers/source-config", handler: (q, s) => this.handleSetProviderSourceConfig(q, s) },
20691
21261
  { method: "GET", pattern: "/api/providers/versions", handler: (q, s) => this.handleDetectVersions(q, s) },
20692
21262
  { method: "POST", pattern: "/api/providers/reload", handler: (q, s) => this.handleReload(q, s) },
20693
21263
  { method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s) => this.handleCdpEvaluate(q, s) },
@@ -20785,15 +21355,15 @@ var DevServer = class _DevServer {
20785
21355
  this.json(res, 500, { error: e.message });
20786
21356
  }
20787
21357
  });
20788
- return new Promise((resolve12, reject) => {
21358
+ return new Promise((resolve11, reject) => {
20789
21359
  this.server.listen(port, "127.0.0.1", () => {
20790
21360
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
20791
- resolve12();
21361
+ resolve11();
20792
21362
  });
20793
21363
  this.server.on("error", (e) => {
20794
21364
  if (e.code === "EADDRINUSE") {
20795
21365
  this.log(`Port ${port} in use, skipping dev server`);
20796
- resolve12();
21366
+ resolve11();
20797
21367
  } else {
20798
21368
  reject(e);
20799
21369
  }
@@ -20807,7 +21377,33 @@ var DevServer = class _DevServer {
20807
21377
  // ─── Handlers ───
20808
21378
  async handleListProviders(_req, res) {
20809
21379
  const providers = this.providerLoader.getAll().map(toProviderListEntry);
20810
- this.json(res, 200, { providers, count: providers.length });
21380
+ this.json(res, 200, { providers, count: providers.length, sourceConfig: this.providerLoader.getSourceConfig() });
21381
+ }
21382
+ async handleGetProviderSourceConfig(_req, res) {
21383
+ this.json(res, 200, { success: true, sourceConfig: this.providerLoader.getSourceConfig() });
21384
+ }
21385
+ async handleSetProviderSourceConfig(req, res) {
21386
+ const body = await this.readBody(req);
21387
+ const parsed = parseProviderSourceConfigUpdate(body || {});
21388
+ if (!parsed.ok) {
21389
+ this.json(res, 400, { success: false, error: parsed.error });
21390
+ return;
21391
+ }
21392
+ const currentConfig2 = loadConfig();
21393
+ const nextConfig = {
21394
+ ...currentConfig2,
21395
+ ...parsed.updates.providerSourceMode ? { providerSourceMode: parsed.updates.providerSourceMode } : {},
21396
+ ...Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? { providerDir: parsed.updates.providerDir } : {}
21397
+ };
21398
+ saveConfig(nextConfig);
21399
+ const sourceConfig = this.providerLoader.applySourceConfig({
21400
+ sourceMode: nextConfig.providerSourceMode,
21401
+ userDir: Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? parsed.updates.providerDir : this.providerLoader.getSourceConfig().explicitProviderDir || void 0
21402
+ });
21403
+ this.providerLoader.reload();
21404
+ this.providerLoader.registerToDetector();
21405
+ await this.onProviderSourceConfigChanged?.();
21406
+ this.json(res, 200, { success: true, reloaded: true, sourceConfig });
20811
21407
  }
20812
21408
  async handleProviderConfig(type, _req, res) {
20813
21409
  const provider = this.providerLoader.resolve(type);
@@ -20849,20 +21445,20 @@ var DevServer = class _DevServer {
20849
21445
  child.stderr?.on("data", (d) => {
20850
21446
  stderr += d.toString().slice(0, 2e3);
20851
21447
  });
20852
- await new Promise((resolve12) => {
21448
+ await new Promise((resolve11) => {
20853
21449
  const timer = setTimeout(() => {
20854
21450
  child.kill();
20855
- resolve12();
21451
+ resolve11();
20856
21452
  }, 3e3);
20857
21453
  child.on("exit", () => {
20858
21454
  clearTimeout(timer);
20859
- resolve12();
21455
+ resolve11();
20860
21456
  });
20861
21457
  child.stdout?.once("data", () => {
20862
21458
  setTimeout(() => {
20863
21459
  child.kill();
20864
21460
  clearTimeout(timer);
20865
- resolve12();
21461
+ resolve11();
20866
21462
  }, 500);
20867
21463
  });
20868
21464
  });
@@ -21358,14 +21954,14 @@ var DevServer = class _DevServer {
21358
21954
  child.stderr?.on("data", (d) => {
21359
21955
  stderr += d.toString();
21360
21956
  });
21361
- await new Promise((resolve12) => {
21957
+ await new Promise((resolve11) => {
21362
21958
  const timer = setTimeout(() => {
21363
21959
  child.kill();
21364
- resolve12();
21960
+ resolve11();
21365
21961
  }, timeout);
21366
21962
  child.on("exit", () => {
21367
21963
  clearTimeout(timer);
21368
- resolve12();
21964
+ resolve11();
21369
21965
  });
21370
21966
  });
21371
21967
  const elapsed = Date.now() - start;
@@ -21510,18 +22106,6 @@ var DevServer = class _DevServer {
21510
22106
  if (!fs14.existsSync(providerJson)) {
21511
22107
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
21512
22108
  }
21513
- try {
21514
- const providerData = JSON.parse(fs14.readFileSync(providerJson, "utf-8"));
21515
- if (providerData.disableUpstream !== true) {
21516
- providerData.disableUpstream = true;
21517
- fs14.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
21518
- }
21519
- } catch (error) {
21520
- return {
21521
- dir: null,
21522
- reason: `Failed to update provider.json in writable provider directory: ${error.message}`
21523
- };
21524
- }
21525
22109
  return { dir: desiredDir };
21526
22110
  }
21527
22111
  async handleAutoImplement(type, req, res) {
@@ -21666,7 +22250,7 @@ var DevServer = class _DevServer {
21666
22250
  lines.push("## Required Return Format");
21667
22251
  lines.push("| Function | Return JSON |");
21668
22252
  lines.push("|---|---|");
21669
- lines.push("| readChat | `{ id, status, title, messages: [{role, content, index, kind?, meta?}], inputContent, activeModal }` \u2014 optional `kind`: standard, thought, tool, terminal; optional `meta`: e.g. `{ label, isRunning }` for dashboard |");
22253
+ lines.push("| readChat | `{ id, status, title, messages: [{role, content, index, kind?, meta?}], inputContent, activeModal, controlValues?, summaryMetadata? }` \u2014 optional `kind`: standard, thought, tool, terminal; prefer explicit `controlValues` for current selections and `summaryMetadata` for compact always-visible UI metadata |");
21670
22254
  lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
21671
22255
  lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
21672
22256
  lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
@@ -22047,14 +22631,14 @@ data: ${JSON.stringify(msg.data)}
22047
22631
  res.end(JSON.stringify(data, null, 2));
22048
22632
  }
22049
22633
  async readBody(req) {
22050
- return new Promise((resolve12) => {
22634
+ return new Promise((resolve11) => {
22051
22635
  let body = "";
22052
22636
  req.on("data", (chunk) => body += chunk);
22053
22637
  req.on("end", () => {
22054
22638
  try {
22055
- resolve12(JSON.parse(body));
22639
+ resolve11(JSON.parse(body));
22056
22640
  } catch {
22057
- resolve12({});
22641
+ resolve11({});
22058
22642
  }
22059
22643
  });
22060
22644
  });
@@ -22532,7 +23116,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
22532
23116
  const deadline = Date.now() + timeoutMs;
22533
23117
  while (Date.now() < deadline) {
22534
23118
  if (await canConnect(endpoint)) return;
22535
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
23119
+ await new Promise((resolve11) => setTimeout(resolve11, STARTUP_POLL_MS));
22536
23120
  }
22537
23121
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
22538
23122
  }
@@ -22572,61 +23156,6 @@ async function listHostedCliRuntimes(endpoint) {
22572
23156
  }
22573
23157
  }
22574
23158
 
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
23159
  // src/session-host/startup-restore-policy.js
22631
23160
  function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
22632
23161
  const raw = typeof env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";
@@ -22763,10 +23292,10 @@ async function installExtension(ide, extension) {
22763
23292
  const buffer = Buffer.from(await res.arrayBuffer());
22764
23293
  const fs15 = await import("fs");
22765
23294
  fs15.writeFileSync(vsixPath, buffer);
22766
- return new Promise((resolve12) => {
23295
+ return new Promise((resolve11) => {
22767
23296
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
22768
23297
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
22769
- resolve12({
23298
+ resolve11({
22770
23299
  extensionId: extension.id,
22771
23300
  marketplaceId: extension.marketplaceId,
22772
23301
  success: !error,
@@ -22779,11 +23308,11 @@ async function installExtension(ide, extension) {
22779
23308
  } catch (e) {
22780
23309
  }
22781
23310
  }
22782
- return new Promise((resolve12) => {
23311
+ return new Promise((resolve11) => {
22783
23312
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
22784
23313
  (0, import_child_process10.exec)(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
22785
23314
  if (error) {
22786
- resolve12({
23315
+ resolve11({
22787
23316
  extensionId: extension.id,
22788
23317
  marketplaceId: extension.marketplaceId,
22789
23318
  success: false,
@@ -22791,7 +23320,7 @@ async function installExtension(ide, extension) {
22791
23320
  error: stderr || error.message
22792
23321
  });
22793
23322
  } else {
22794
- resolve12({
23323
+ resolve11({
22795
23324
  extensionId: extension.id,
22796
23325
  marketplaceId: extension.marketplaceId,
22797
23326
  success: true,
@@ -22888,10 +23417,11 @@ init_config();
22888
23417
  async function initDaemonComponents(config) {
22889
23418
  installGlobalInterceptor();
22890
23419
  const appConfig = loadConfig();
22891
- const disableUpstream = appConfig.disableUpstream ?? false;
23420
+ const providerSourceMode = appConfig.providerSourceMode || "normal";
23421
+ const disableUpstream = providerSourceMode === "no-upstream";
22892
23422
  const providerLoader = new ProviderLoader({
22893
23423
  logFn: config.providerLogFn,
22894
- disableUpstream,
23424
+ sourceMode: providerSourceMode,
22895
23425
  userDir: appConfig.providerDir
22896
23426
  });
22897
23427
  if (!disableUpstream && !providerLoader.hasUpstream()) {
@@ -22996,6 +23526,10 @@ async function initDaemonComponents(config) {
22996
23526
  onProviderSettingChanged: async (providerType) => {
22997
23527
  await refreshProviderAvailability(providerType);
22998
23528
  config.onStatusChange?.();
23529
+ },
23530
+ onProviderSourceConfigChanged: async () => {
23531
+ await refreshProviderAvailability();
23532
+ config.onStatusChange?.();
22999
23533
  }
23000
23534
  });
23001
23535
  agentStreamManager = new DaemonAgentStreamManager(
@@ -23045,7 +23579,8 @@ async function initDaemonComponents(config) {
23045
23579
  cdpInitializer,
23046
23580
  cdpManagers,
23047
23581
  sessionRegistry,
23048
- detectedIdes: detectedIdesRef
23582
+ detectedIdes: detectedIdesRef,
23583
+ refreshProviderAvailability
23049
23584
  };
23050
23585
  }
23051
23586
  async function startDaemonDevSupport(options) {
@@ -23054,7 +23589,10 @@ async function startDaemonDevSupport(options) {
23054
23589
  cdpManagers: options.components.cdpManagers,
23055
23590
  instanceManager: options.components.instanceManager,
23056
23591
  cliManager: options.components.cliManager,
23057
- logFn: options.logFn
23592
+ logFn: options.logFn,
23593
+ onProviderSourceConfigChanged: async () => {
23594
+ await options.components.refreshProviderAvailability();
23595
+ }
23058
23596
  });
23059
23597
  await devServer.start();
23060
23598
  options.components.providerLoader.watch();
@@ -23181,6 +23719,7 @@ async function shutdownDaemonComponents(components) {
23181
23719
  normalizeInputEnvelope,
23182
23720
  normalizeManagedStatus,
23183
23721
  normalizeMessageParts,
23722
+ parseProviderSourceConfigUpdate,
23184
23723
  partitionSessionHostDiagnosticsSessions,
23185
23724
  partitionSessionHostRecords,
23186
23725
  probeCdpPort,