@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.mjs CHANGED
@@ -35,6 +35,7 @@ __export(config_exports, {
35
35
  loadConfig: () => loadConfig,
36
36
  markSetupComplete: () => markSetupComplete,
37
37
  resetConfig: () => resetConfig,
38
+ resolveProviderSourceMode: () => resolveProviderSourceMode,
38
39
  saveConfig: () => saveConfig,
39
40
  updateConfig: () => updateConfig
40
41
  });
@@ -42,6 +43,12 @@ import { homedir } from "os";
42
43
  import { join } from "path";
43
44
  import { existsSync, mkdirSync, readFileSync, writeFileSync, chmodSync } from "fs";
44
45
  import { randomUUID } from "crypto";
46
+ function resolveProviderSourceMode(providerSourceMode, legacyDisableUpstream) {
47
+ if (providerSourceMode === "normal" || providerSourceMode === "no-upstream") {
48
+ return providerSourceMode;
49
+ }
50
+ return legacyDisableUpstream === true ? "no-upstream" : "normal";
51
+ }
45
52
  function isPlainObject(value) {
46
53
  return !!value && typeof value === "object" && !Array.isArray(value);
47
54
  }
@@ -79,7 +86,7 @@ function normalizeConfig(raw) {
79
86
  registeredMachineId: asOptionalString(parsed.registeredMachineId),
80
87
  providerSettings: isPlainObject(parsed.providerSettings) ? parsed.providerSettings : {},
81
88
  ideSettings: isPlainObject(parsed.ideSettings) ? parsed.ideSettings : {},
82
- disableUpstream: asBoolean(parsed.disableUpstream, DEFAULT_CONFIG.disableUpstream ?? false),
89
+ providerSourceMode: resolveProviderSourceMode(parsed.providerSourceMode, parsed.disableUpstream),
83
90
  providerDir: asOptionalString(parsed.providerDir),
84
91
  terminalSizingMode: parsed.terminalSizingMode === "fit" ? "fit" : "measured"
85
92
  };
@@ -224,7 +231,7 @@ var init_config = __esm({
224
231
  registeredMachineId: void 0,
225
232
  providerSettings: {},
226
233
  ideSettings: {},
227
- disableUpstream: false,
234
+ providerSourceMode: "normal",
228
235
  terminalSizingMode: "measured"
229
236
  };
230
237
  MACHINE_ID_PREFIX = "mach_";
@@ -1894,7 +1901,7 @@ var init_provider_cli_adapter = __esm({
1894
1901
  `[${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)}`
1895
1902
  );
1896
1903
  }
1897
- await new Promise((resolve12) => setTimeout(resolve12, 50));
1904
+ await new Promise((resolve11) => setTimeout(resolve11, 50));
1898
1905
  }
1899
1906
  const finalScreenText = this.terminalScreen.getText() || "";
1900
1907
  LOG.warn(
@@ -2467,7 +2474,7 @@ ${data.message || ""}`.trim();
2467
2474
  const deadline = Date.now() + 1e4;
2468
2475
  while (this.startupParseGate && Date.now() < deadline) {
2469
2476
  this.resolveStartupState("send_wait");
2470
- await new Promise((resolve12) => setTimeout(resolve12, 50));
2477
+ await new Promise((resolve11) => setTimeout(resolve11, 50));
2471
2478
  }
2472
2479
  }
2473
2480
  await this.waitForInteractivePrompt();
@@ -2537,12 +2544,12 @@ ${data.message || ""}`.trim();
2537
2544
  if (this.isWaitingForResponse) this.finishResponse();
2538
2545
  }, this.timeouts.maxResponse);
2539
2546
  };
2540
- await new Promise((resolve12) => {
2547
+ await new Promise((resolve11) => {
2541
2548
  let resolved = false;
2542
2549
  const resolveOnce = () => {
2543
2550
  if (resolved) return;
2544
2551
  resolved = true;
2545
- resolve12();
2552
+ resolve11();
2546
2553
  };
2547
2554
  const submit = () => {
2548
2555
  if (!this.ptyProcess) {
@@ -2716,17 +2723,17 @@ ${data.message || ""}`.trim();
2716
2723
  }
2717
2724
  }
2718
2725
  waitForStopped(timeoutMs) {
2719
- return new Promise((resolve12) => {
2726
+ return new Promise((resolve11) => {
2720
2727
  const startedAt = Date.now();
2721
2728
  const timer = setInterval(() => {
2722
2729
  if (!this.ptyProcess || this.currentStatus === "stopped") {
2723
2730
  clearInterval(timer);
2724
- resolve12(true);
2731
+ resolve11(true);
2725
2732
  return;
2726
2733
  }
2727
2734
  if (Date.now() - startedAt >= timeoutMs) {
2728
2735
  clearInterval(timer);
2729
- resolve12(false);
2736
+ resolve11(false);
2730
2737
  }
2731
2738
  }, 100);
2732
2739
  });
@@ -3168,6 +3175,70 @@ function setDefaultWorkspaceId(config, id) {
3168
3175
 
3169
3176
  // src/config/recent-activity.ts
3170
3177
  import * as path2 from "path";
3178
+
3179
+ // src/providers/summary-metadata.ts
3180
+ function normalizeSummaryItem(item) {
3181
+ if (!item || typeof item !== "object") return null;
3182
+ const id = String(item.id || "").trim();
3183
+ const value = String(item.value || "").trim();
3184
+ if (!id || !value) return null;
3185
+ const normalized = {
3186
+ id,
3187
+ value
3188
+ };
3189
+ if (typeof item.label === "string" && item.label.trim()) normalized.label = item.label.trim();
3190
+ if (typeof item.shortValue === "string" && item.shortValue.trim()) normalized.shortValue = item.shortValue.trim();
3191
+ if (typeof item.icon === "string" && item.icon.trim()) normalized.icon = item.icon.trim();
3192
+ if (typeof item.order === "number" && Number.isFinite(item.order)) normalized.order = item.order;
3193
+ return normalized;
3194
+ }
3195
+ function normalizeProviderSummaryMetadata(summary) {
3196
+ if (!summary || !Array.isArray(summary.items)) return void 0;
3197
+ const items = summary.items.map((item) => normalizeSummaryItem(item)).filter((item) => !!item).sort((left, right) => {
3198
+ const orderDiff = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
3199
+ if (orderDiff !== 0) return orderDiff;
3200
+ return left.id.localeCompare(right.id);
3201
+ });
3202
+ return items.length > 0 ? { items } : void 0;
3203
+ }
3204
+ function buildProviderSummaryMetadata(items) {
3205
+ return normalizeProviderSummaryMetadata({ items: items.filter(Boolean) });
3206
+ }
3207
+ function buildLegacyModelModeSummaryMetadata(params) {
3208
+ return buildProviderSummaryMetadata([
3209
+ params.model ? {
3210
+ id: "model",
3211
+ label: "Model",
3212
+ value: String(params.modelLabel || params.model).trim(),
3213
+ shortValue: String(params.model).trim(),
3214
+ order: 10
3215
+ } : null,
3216
+ params.mode ? {
3217
+ id: "mode",
3218
+ label: "Mode",
3219
+ value: String(params.modeLabel || params.mode).trim(),
3220
+ shortValue: String(params.mode).trim(),
3221
+ order: 20
3222
+ } : null
3223
+ ]);
3224
+ }
3225
+ function resolveProviderStateSummaryMetadata(params) {
3226
+ const explicit = normalizeProviderSummaryMetadata(params.summaryMetadata);
3227
+ if (explicit) return explicit;
3228
+ const model = typeof params.controlValues?.model === "string" ? params.controlValues.model : void 0;
3229
+ const mode = typeof params.controlValues?.mode === "string" ? params.controlValues.mode : void 0;
3230
+ return buildLegacyModelModeSummaryMetadata({
3231
+ model,
3232
+ mode,
3233
+ modelLabel: params.modelLabel,
3234
+ modeLabel: params.modeLabel
3235
+ });
3236
+ }
3237
+ function normalizePersistedSummaryMetadata(params) {
3238
+ return normalizeProviderSummaryMetadata(params.summaryMetadata);
3239
+ }
3240
+
3241
+ // src/config/recent-activity.ts
3171
3242
  var MAX_ACTIVITY = 30;
3172
3243
  function normalizeWorkspace(workspace) {
3173
3244
  if (!workspace) return "";
@@ -3191,6 +3262,9 @@ function appendRecentActivity(state, entry) {
3191
3262
  const nextEntry = {
3192
3263
  ...entry,
3193
3264
  workspace: entry.workspace ? normalizeWorkspace(entry.workspace) : void 0,
3265
+ summaryMetadata: normalizePersistedSummaryMetadata({
3266
+ summaryMetadata: entry.summaryMetadata
3267
+ }),
3194
3268
  id: buildRecentActivityKeyForEntry(entry),
3195
3269
  lastUsedAt: entry.lastUsedAt || Date.now()
3196
3270
  };
@@ -3201,7 +3275,12 @@ function appendRecentActivity(state, entry) {
3201
3275
  };
3202
3276
  }
3203
3277
  function getRecentActivity(state, limit = 20) {
3204
- return [...state.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
3278
+ return [...state.recentActivity || []].map((entry) => ({
3279
+ ...entry,
3280
+ summaryMetadata: normalizePersistedSummaryMetadata({
3281
+ summaryMetadata: entry.summaryMetadata
3282
+ })
3283
+ })).sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
3205
3284
  }
3206
3285
  function getSessionSeenAt(state, sessionId) {
3207
3286
  return state.sessionReads?.[sessionId] || 0;
@@ -3253,7 +3332,9 @@ function upsertSavedProviderSession(state, entry) {
3253
3332
  providerName: entry.providerName,
3254
3333
  providerSessionId,
3255
3334
  workspace: entry.workspace ? normalizeWorkspace2(entry.workspace) : void 0,
3256
- currentModel: entry.currentModel,
3335
+ summaryMetadata: normalizePersistedSummaryMetadata({
3336
+ summaryMetadata: entry.summaryMetadata
3337
+ }),
3257
3338
  title: entry.title,
3258
3339
  createdAt: existing?.createdAt || entry.createdAt || Date.now(),
3259
3340
  lastUsedAt: entry.lastUsedAt || Date.now()
@@ -3269,7 +3350,12 @@ function getSavedProviderSessions(state, filters) {
3269
3350
  if (filters?.providerType && entry.providerType !== filters.providerType) return false;
3270
3351
  if (filters?.kind && entry.kind !== filters.kind) return false;
3271
3352
  return true;
3272
- }).sort((a, b) => b.lastUsedAt - a.lastUsedAt);
3353
+ }).map((entry) => ({
3354
+ ...entry,
3355
+ summaryMetadata: normalizePersistedSummaryMetadata({
3356
+ summaryMetadata: entry.summaryMetadata
3357
+ })
3358
+ })).sort((a, b) => b.lastUsedAt - a.lastUsedAt);
3273
3359
  }
3274
3360
 
3275
3361
  // src/config/state-store.ts
@@ -3465,15 +3551,15 @@ function resolveCommandPath(command) {
3465
3551
  return null;
3466
3552
  }
3467
3553
  function execAsync(cmd, timeoutMs = 5e3) {
3468
- return new Promise((resolve12) => {
3554
+ return new Promise((resolve11) => {
3469
3555
  const child = exec(cmd, { encoding: "utf-8", timeout: timeoutMs }, (err, stdout) => {
3470
3556
  if (err || !stdout?.trim()) {
3471
- resolve12(null);
3557
+ resolve11(null);
3472
3558
  } else {
3473
- resolve12(stdout.trim());
3559
+ resolve11(stdout.trim());
3474
3560
  }
3475
3561
  });
3476
- child.on("error", () => resolve12(null));
3562
+ child.on("error", () => resolve11(null));
3477
3563
  });
3478
3564
  }
3479
3565
  async function detectCLIs(providerLoader, options) {
@@ -3684,7 +3770,7 @@ var DaemonCdpManager = class {
3684
3770
  * Returns multiple entries if multiple IDE windows are open on same port
3685
3771
  */
3686
3772
  static listAllTargets(port) {
3687
- return new Promise((resolve12) => {
3773
+ return new Promise((resolve11) => {
3688
3774
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3689
3775
  let data = "";
3690
3776
  res.on("data", (chunk) => data += chunk.toString());
@@ -3700,16 +3786,16 @@ var DaemonCdpManager = class {
3700
3786
  (t) => !isNonMain(t.title || "") && t.url?.includes("workbench.html") && !t.url?.includes("agent")
3701
3787
  );
3702
3788
  const fallbackPages = pages.filter((t) => !isNonMain(t.title || ""));
3703
- resolve12(mainPages.length > 0 ? mainPages : fallbackPages);
3789
+ resolve11(mainPages.length > 0 ? mainPages : fallbackPages);
3704
3790
  } catch {
3705
- resolve12([]);
3791
+ resolve11([]);
3706
3792
  }
3707
3793
  });
3708
3794
  });
3709
- req.on("error", () => resolve12([]));
3795
+ req.on("error", () => resolve11([]));
3710
3796
  req.setTimeout(2e3, () => {
3711
3797
  req.destroy();
3712
- resolve12([]);
3798
+ resolve11([]);
3713
3799
  });
3714
3800
  });
3715
3801
  }
@@ -3749,7 +3835,7 @@ var DaemonCdpManager = class {
3749
3835
  }
3750
3836
  }
3751
3837
  findTargetOnPort(port) {
3752
- return new Promise((resolve12) => {
3838
+ return new Promise((resolve11) => {
3753
3839
  const req = http.get(`http://127.0.0.1:${port}/json`, (res) => {
3754
3840
  let data = "";
3755
3841
  res.on("data", (chunk) => data += chunk.toString());
@@ -3760,7 +3846,7 @@ var DaemonCdpManager = class {
3760
3846
  (t) => (t.type === "page" || t.type === "browser" || t.type === "Page") && t.webSocketDebuggerUrl
3761
3847
  );
3762
3848
  if (pages.length === 0) {
3763
- resolve12(targets.find((t) => t.webSocketDebuggerUrl) || null);
3849
+ resolve11(targets.find((t) => t.webSocketDebuggerUrl) || null);
3764
3850
  return;
3765
3851
  }
3766
3852
  const mainPages = pages.filter((t) => !this.isNonMainTitle(t.title || ""));
@@ -3770,24 +3856,24 @@ var DaemonCdpManager = class {
3770
3856
  const specific = list.find((t) => t.id === this._targetId);
3771
3857
  if (specific) {
3772
3858
  this._pageTitle = specific.title || "";
3773
- resolve12(specific);
3859
+ resolve11(specific);
3774
3860
  } else {
3775
3861
  this.log(`[CDP] Target ${this._targetId} not found in page list`);
3776
- resolve12(null);
3862
+ resolve11(null);
3777
3863
  }
3778
3864
  return;
3779
3865
  }
3780
3866
  this._pageTitle = list[0]?.title || "";
3781
- resolve12(list[0]);
3867
+ resolve11(list[0]);
3782
3868
  } catch {
3783
- resolve12(null);
3869
+ resolve11(null);
3784
3870
  }
3785
3871
  });
3786
3872
  });
3787
- req.on("error", () => resolve12(null));
3873
+ req.on("error", () => resolve11(null));
3788
3874
  req.setTimeout(2e3, () => {
3789
3875
  req.destroy();
3790
- resolve12(null);
3876
+ resolve11(null);
3791
3877
  });
3792
3878
  });
3793
3879
  }
@@ -3798,7 +3884,7 @@ var DaemonCdpManager = class {
3798
3884
  this.extensionProviders = providers;
3799
3885
  }
3800
3886
  connectToTarget(wsUrl) {
3801
- return new Promise((resolve12) => {
3887
+ return new Promise((resolve11) => {
3802
3888
  this.ws = new WebSocket(wsUrl);
3803
3889
  this.ws.on("open", async () => {
3804
3890
  this._connected = true;
@@ -3808,17 +3894,17 @@ var DaemonCdpManager = class {
3808
3894
  }
3809
3895
  this.connectBrowserWs().catch(() => {
3810
3896
  });
3811
- resolve12(true);
3897
+ resolve11(true);
3812
3898
  });
3813
3899
  this.ws.on("message", (data) => {
3814
3900
  try {
3815
3901
  const msg = JSON.parse(data.toString());
3816
3902
  if (msg.id && this.pending.has(msg.id)) {
3817
- const { resolve: resolve13, reject } = this.pending.get(msg.id);
3903
+ const { resolve: resolve12, reject } = this.pending.get(msg.id);
3818
3904
  this.pending.delete(msg.id);
3819
3905
  this.failureCount = 0;
3820
3906
  if (msg.error) reject(new Error(msg.error.message));
3821
- else resolve13(msg.result);
3907
+ else resolve12(msg.result);
3822
3908
  } else if (msg.method === "Runtime.executionContextCreated") {
3823
3909
  this.contexts.add(msg.params.context.id);
3824
3910
  } else if (msg.method === "Runtime.executionContextDestroyed") {
@@ -3841,7 +3927,7 @@ var DaemonCdpManager = class {
3841
3927
  this.ws.on("error", (err) => {
3842
3928
  this.log(`[CDP] WebSocket error: ${err.message}`);
3843
3929
  this._connected = false;
3844
- resolve12(false);
3930
+ resolve11(false);
3845
3931
  });
3846
3932
  });
3847
3933
  }
@@ -3855,7 +3941,7 @@ var DaemonCdpManager = class {
3855
3941
  return;
3856
3942
  }
3857
3943
  this.log(`[CDP] Connecting browser WS for target discovery...`);
3858
- await new Promise((resolve12, reject) => {
3944
+ await new Promise((resolve11, reject) => {
3859
3945
  this.browserWs = new WebSocket(browserWsUrl);
3860
3946
  this.browserWs.on("open", async () => {
3861
3947
  this._browserConnected = true;
@@ -3865,16 +3951,16 @@ var DaemonCdpManager = class {
3865
3951
  } catch (e) {
3866
3952
  this.log(`[CDP] setDiscoverTargets failed: ${e.message}`);
3867
3953
  }
3868
- resolve12();
3954
+ resolve11();
3869
3955
  });
3870
3956
  this.browserWs.on("message", (data) => {
3871
3957
  try {
3872
3958
  const msg = JSON.parse(data.toString());
3873
3959
  if (msg.id && this.browserPending.has(msg.id)) {
3874
- const { resolve: resolve13, reject: reject2 } = this.browserPending.get(msg.id);
3960
+ const { resolve: resolve12, reject: reject2 } = this.browserPending.get(msg.id);
3875
3961
  this.browserPending.delete(msg.id);
3876
3962
  if (msg.error) reject2(new Error(msg.error.message));
3877
- else resolve13(msg.result);
3963
+ else resolve12(msg.result);
3878
3964
  }
3879
3965
  } catch {
3880
3966
  }
@@ -3894,31 +3980,31 @@ var DaemonCdpManager = class {
3894
3980
  }
3895
3981
  }
3896
3982
  getBrowserWsUrl() {
3897
- return new Promise((resolve12) => {
3983
+ return new Promise((resolve11) => {
3898
3984
  const req = http.get(`http://127.0.0.1:${this.port}/json/version`, (res) => {
3899
3985
  let data = "";
3900
3986
  res.on("data", (chunk) => data += chunk.toString());
3901
3987
  res.on("end", () => {
3902
3988
  try {
3903
3989
  const info = JSON.parse(data);
3904
- resolve12(info.webSocketDebuggerUrl || null);
3990
+ resolve11(info.webSocketDebuggerUrl || null);
3905
3991
  } catch {
3906
- resolve12(null);
3992
+ resolve11(null);
3907
3993
  }
3908
3994
  });
3909
3995
  });
3910
- req.on("error", () => resolve12(null));
3996
+ req.on("error", () => resolve11(null));
3911
3997
  req.setTimeout(3e3, () => {
3912
3998
  req.destroy();
3913
- resolve12(null);
3999
+ resolve11(null);
3914
4000
  });
3915
4001
  });
3916
4002
  }
3917
4003
  sendBrowser(method, params = {}, timeoutMs = 15e3) {
3918
- return new Promise((resolve12, reject) => {
4004
+ return new Promise((resolve11, reject) => {
3919
4005
  if (!this.browserWs || !this._browserConnected) return reject(new Error("Browser WS not connected"));
3920
4006
  const id = this.browserMsgId++;
3921
- this.browserPending.set(id, { resolve: resolve12, reject });
4007
+ this.browserPending.set(id, { resolve: resolve11, reject });
3922
4008
  this.browserWs.send(JSON.stringify({ id, method, params }));
3923
4009
  setTimeout(() => {
3924
4010
  if (this.browserPending.has(id)) {
@@ -3958,11 +4044,11 @@ var DaemonCdpManager = class {
3958
4044
  }
3959
4045
  // ─── CDP Protocol ────────────────────────────────────────
3960
4046
  sendInternal(method, params = {}, timeoutMs = 15e3) {
3961
- return new Promise((resolve12, reject) => {
4047
+ return new Promise((resolve11, reject) => {
3962
4048
  if (!this.ws || !this._connected) return reject(new Error("CDP not connected"));
3963
4049
  if (this.ws.readyState !== WebSocket.OPEN) return reject(new Error("WebSocket not open"));
3964
4050
  const id = this.msgId++;
3965
- this.pending.set(id, { resolve: resolve12, reject });
4051
+ this.pending.set(id, { resolve: resolve11, reject });
3966
4052
  this.ws.send(JSON.stringify({ id, method, params }));
3967
4053
  setTimeout(() => {
3968
4054
  if (this.pending.has(id)) {
@@ -4211,7 +4297,7 @@ var DaemonCdpManager = class {
4211
4297
  const browserWs = this.browserWs;
4212
4298
  let msgId = this.browserMsgId;
4213
4299
  const sendWs = (method, params = {}, sessionId) => {
4214
- return new Promise((resolve12, reject) => {
4300
+ return new Promise((resolve11, reject) => {
4215
4301
  const mid = msgId++;
4216
4302
  this.browserMsgId = msgId;
4217
4303
  const handler = (raw) => {
@@ -4220,7 +4306,7 @@ var DaemonCdpManager = class {
4220
4306
  if (msg.id === mid) {
4221
4307
  browserWs.removeListener("message", handler);
4222
4308
  if (msg.error) reject(new Error(msg.error.message || JSON.stringify(msg.error)));
4223
- else resolve12(msg.result);
4309
+ else resolve11(msg.result);
4224
4310
  }
4225
4311
  } catch {
4226
4312
  }
@@ -4421,14 +4507,14 @@ var DaemonCdpManager = class {
4421
4507
  if (!ws || ws.readyState !== WebSocket.OPEN) {
4422
4508
  throw new Error("CDP not connected");
4423
4509
  }
4424
- return new Promise((resolve12, reject) => {
4510
+ return new Promise((resolve11, reject) => {
4425
4511
  const id = getNextId();
4426
4512
  pendingMap.set(id, {
4427
4513
  resolve: (result) => {
4428
4514
  if (result?.result?.subtype === "error") {
4429
4515
  reject(new Error(result.result.description));
4430
4516
  } else {
4431
- resolve12(result?.result?.value);
4517
+ resolve11(result?.result?.value);
4432
4518
  }
4433
4519
  },
4434
4520
  reject
@@ -4460,10 +4546,10 @@ var DaemonCdpManager = class {
4460
4546
  throw new Error("CDP not connected");
4461
4547
  }
4462
4548
  const sendViaSession = (method, params = {}) => {
4463
- return new Promise((resolve12, reject) => {
4549
+ return new Promise((resolve11, reject) => {
4464
4550
  const pendingMap = this._browserConnected ? this.browserPending : this.pending;
4465
4551
  const id = this._browserConnected ? this.browserMsgId++ : this.msgId++;
4466
- pendingMap.set(id, { resolve: resolve12, reject });
4552
+ pendingMap.set(id, { resolve: resolve11, reject });
4467
4553
  ws.send(JSON.stringify({ id, sessionId, method, params }));
4468
4554
  setTimeout(() => {
4469
4555
  if (pendingMap.has(id)) {
@@ -5026,8 +5112,6 @@ function extractProviderControlValues(controls, data) {
5026
5112
  if (rawValue === void 0 || rawValue === null) continue;
5027
5113
  values[ctrl.id] = normalizeControlValue(rawValue);
5028
5114
  }
5029
- if (data.model !== void 0 && values.model === void 0) values.model = normalizeControlValue(data.model);
5030
- if (data.mode !== void 0 && values.mode === void 0) values.mode = normalizeControlValue(data.mode);
5031
5115
  return Object.keys(values).length > 0 ? values : void 0;
5032
5116
  }
5033
5117
  function normalizeProviderEffects(data) {
@@ -5129,7 +5213,7 @@ function normalizeControlOption(option) {
5129
5213
  }
5130
5214
  if (!option || typeof option !== "object") return null;
5131
5215
  const record = option;
5132
- const value = typeof record.value === "string" ? record.value : typeof record.id === "string" ? record.id : null;
5216
+ const value = typeof record.value === "string" ? record.value : typeof record.id === "string" ? record.id : typeof record.name === "string" ? record.name : null;
5133
5217
  if (!value) return null;
5134
5218
  const label = typeof record.label === "string" ? record.label : typeof record.name === "string" ? record.name : value;
5135
5219
  const normalized = { value, label };
@@ -5373,6 +5457,30 @@ var ChatHistoryWriter = class {
5373
5457
  options.historySessionId
5374
5458
  );
5375
5459
  }
5460
+ writeSessionStart(agentType, historySessionId, workspace, instanceId) {
5461
+ const id = String(historySessionId || "").trim();
5462
+ const ws = String(workspace || "").trim();
5463
+ if (!id || !ws) return;
5464
+ try {
5465
+ const dir = path7.join(HISTORY_DIR, this.sanitize(agentType));
5466
+ fs3.mkdirSync(dir, { recursive: true });
5467
+ const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
5468
+ const filePath = path7.join(dir, `${this.sanitize(id)}_${date}.jsonl`);
5469
+ const record = {
5470
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
5471
+ receivedAt: Date.now(),
5472
+ role: "system",
5473
+ kind: "session_start",
5474
+ content: ws,
5475
+ agent: agentType,
5476
+ instanceId,
5477
+ historySessionId: id,
5478
+ workspace: ws
5479
+ };
5480
+ fs3.appendFileSync(filePath, JSON.stringify(record) + "\n", "utf-8");
5481
+ } catch {
5482
+ }
5483
+ }
5376
5484
  promoteHistorySession(agentType, previousHistorySessionId, nextHistorySessionId) {
5377
5485
  const fromId = String(previousHistorySessionId || "").trim();
5378
5486
  const toId = String(nextHistorySessionId || "").trim();
@@ -5592,6 +5700,7 @@ function listSavedHistorySessions(agentType, options = {}) {
5592
5700
  let lastMessageAt = 0;
5593
5701
  let sessionTitle = "";
5594
5702
  let preview = "";
5703
+ let workspace = "";
5595
5704
  for (const file of files.sort()) {
5596
5705
  const filePath = path7.join(dir, file);
5597
5706
  const content = fs3.readFileSync(filePath, "utf-8");
@@ -5604,6 +5713,10 @@ function listSavedHistorySessions(agentType, options = {}) {
5604
5713
  parsed = null;
5605
5714
  }
5606
5715
  if (!parsed || parsed.historySessionId !== historySessionId) continue;
5716
+ if (parsed.kind === "session_start") {
5717
+ if (!workspace && parsed.workspace) workspace = parsed.workspace;
5718
+ continue;
5719
+ }
5607
5720
  messageCount += 1;
5608
5721
  if (!firstMessageAt || parsed.receivedAt < firstMessageAt) firstMessageAt = parsed.receivedAt;
5609
5722
  if (!lastMessageAt || parsed.receivedAt > lastMessageAt) lastMessageAt = parsed.receivedAt;
@@ -5618,7 +5731,8 @@ function listSavedHistorySessions(agentType, options = {}) {
5618
5731
  messageCount,
5619
5732
  firstMessageAt,
5620
5733
  lastMessageAt,
5621
- preview: preview || void 0
5734
+ preview: preview || void 0,
5735
+ workspace: workspace || void 0
5622
5736
  });
5623
5737
  }
5624
5738
  summaries.sort((a, b) => b.lastMessageAt - a.lastMessageAt);
@@ -5634,6 +5748,61 @@ function listSavedHistorySessions(agentType, options = {}) {
5634
5748
  }
5635
5749
  }
5636
5750
 
5751
+ // src/providers/provider-patch-state.ts
5752
+ function isControlValue(value) {
5753
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
5754
+ }
5755
+ function asControlValueMap(value) {
5756
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
5757
+ const result = {};
5758
+ for (const [entryKey, entryValue] of Object.entries(value)) {
5759
+ if (isControlValue(entryValue)) result[entryKey] = entryValue;
5760
+ }
5761
+ return Object.keys(result).length > 0 ? result : void 0;
5762
+ }
5763
+ function getLegacyModelModeValues(data) {
5764
+ if (!data || typeof data !== "object") return void 0;
5765
+ const legacy = {};
5766
+ if (typeof data.model === "string" && data.model.trim()) legacy.model = data.model.trim();
5767
+ if (typeof data.mode === "string" && data.mode.trim()) legacy.mode = data.mode.trim();
5768
+ return Object.keys(legacy).length > 0 ? legacy : void 0;
5769
+ }
5770
+ function mergeProviderPatchState(params) {
5771
+ const {
5772
+ providerControls,
5773
+ data,
5774
+ currentControlValues,
5775
+ currentSummaryMetadata,
5776
+ mergeWithCurrent = true
5777
+ } = params;
5778
+ const sources = [
5779
+ mergeWithCurrent ? asControlValueMap(currentControlValues) : void 0,
5780
+ asControlValueMap(data?.controlValues),
5781
+ asControlValueMap(extractProviderControlValues(providerControls, data)),
5782
+ getLegacyModelModeValues(data)
5783
+ ];
5784
+ const controlValues = Object.assign({}, ...sources.filter(Boolean));
5785
+ return {
5786
+ controlValues,
5787
+ summaryMetadata: data?.summaryMetadata !== void 0 ? data.summaryMetadata : currentSummaryMetadata
5788
+ };
5789
+ }
5790
+ function normalizeProviderStateControlValues(controlValues) {
5791
+ return controlValues && Object.keys(controlValues).length > 0 ? controlValues : void 0;
5792
+ }
5793
+ function resolveProviderStateSurface(params) {
5794
+ const controlValues = normalizeProviderStateControlValues(params.controlValues);
5795
+ return {
5796
+ controlValues,
5797
+ summaryMetadata: resolveProviderStateSummaryMetadata({
5798
+ summaryMetadata: params.summaryMetadata,
5799
+ controlValues,
5800
+ modelLabel: params.modelLabel,
5801
+ modeLabel: params.modeLabel
5802
+ })
5803
+ };
5804
+ }
5805
+
5637
5806
  // src/providers/extension-provider-instance.ts
5638
5807
  var ExtensionProviderInstance = class {
5639
5808
  type;
@@ -5648,9 +5817,8 @@ var ExtensionProviderInstance = class {
5648
5817
  messages = [];
5649
5818
  prevMessageHashes = /* @__PURE__ */ new Map();
5650
5819
  activeModal = null;
5651
- currentModel = "";
5652
- currentMode = "";
5653
5820
  controlValues = {};
5821
+ summaryMetadata = void 0;
5654
5822
  appliedEffectKeys = /* @__PURE__ */ new Set();
5655
5823
  runtimeMessages = [];
5656
5824
  lastAgentStatus = "idle";
@@ -5685,6 +5853,10 @@ var ExtensionProviderInstance = class {
5685
5853
  if (!this.context?.cdp?.isConnected) return;
5686
5854
  }
5687
5855
  getState() {
5856
+ const surface = resolveProviderStateSurface({
5857
+ summaryMetadata: this.summaryMetadata,
5858
+ controlValues: this.controlValues
5859
+ });
5688
5860
  return {
5689
5861
  type: this.type,
5690
5862
  name: this.provider.name,
@@ -5698,10 +5870,9 @@ var ExtensionProviderInstance = class {
5698
5870
  activeModal: this.activeModal,
5699
5871
  inputContent: ""
5700
5872
  } : null,
5701
- currentModel: this.currentModel || void 0,
5702
- currentPlan: this.currentMode || void 0,
5703
- controlValues: this.controlValues,
5873
+ controlValues: surface.controlValues,
5704
5874
  providerControls: this.provider.controls,
5875
+ summaryMetadata: surface.summaryMetadata,
5705
5876
  agentStreams: this.agentStreams,
5706
5877
  instanceId: this.instanceId,
5707
5878
  lastUpdated: Date.now(),
@@ -5714,10 +5885,14 @@ var ExtensionProviderInstance = class {
5714
5885
  if (data?.streams) this.agentStreams = data.streams;
5715
5886
  if (data?.messages) this.messages = this.assignReceivedAt(data.messages);
5716
5887
  if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
5717
- if (data?.model) this.currentModel = data.model;
5718
- if (data?.mode) this.currentMode = data.mode;
5719
- const controlValues = extractProviderControlValues(this.provider.controls, data) || data?.controlValues;
5720
- if (controlValues) this.controlValues = controlValues;
5888
+ const patchedState = mergeProviderPatchState({
5889
+ providerControls: this.provider.controls,
5890
+ data,
5891
+ currentControlValues: this.controlValues,
5892
+ currentSummaryMetadata: this.summaryMetadata
5893
+ });
5894
+ this.controlValues = patchedState.controlValues;
5895
+ this.summaryMetadata = patchedState.summaryMetadata;
5721
5896
  if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
5722
5897
  if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
5723
5898
  if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
@@ -5818,8 +5993,14 @@ var ExtensionProviderInstance = class {
5818
5993
  }
5819
5994
  applyProviderResponse(data, options) {
5820
5995
  if (!data || typeof data !== "object") return;
5821
- const controlValues = extractProviderControlValues(this.provider.controls, data);
5822
- if (controlValues) this.controlValues = { ...this.controlValues, ...controlValues };
5996
+ const patchedState = mergeProviderPatchState({
5997
+ providerControls: this.provider.controls,
5998
+ data,
5999
+ currentControlValues: this.controlValues,
6000
+ currentSummaryMetadata: this.summaryMetadata
6001
+ });
6002
+ this.controlValues = patchedState.controlValues;
6003
+ this.summaryMetadata = patchedState.summaryMetadata;
5823
6004
  const effects = normalizeProviderEffects(data);
5824
6005
  for (const effect of effects) {
5825
6006
  const effectWhen = effect.when || "immediate";
@@ -5969,8 +6150,6 @@ ${effect.notification.body || ""}`.trim();
5969
6150
  this.messages = [];
5970
6151
  this.prevMessageHashes.clear();
5971
6152
  this.activeModal = null;
5972
- this.currentModel = "";
5973
- this.currentMode = "";
5974
6153
  this.controlValues = {};
5975
6154
  this.currentStatus = "idle";
5976
6155
  this.chatId = null;
@@ -6106,6 +6285,10 @@ var IdeProviderInstance = class {
6106
6285
  for (const ext of this.extensions.values()) {
6107
6286
  extensionStates.push(ext.getState());
6108
6287
  }
6288
+ const surface = resolveProviderStateSurface({
6289
+ summaryMetadata: this.cachedChat?.summaryMetadata,
6290
+ controlValues: this.cachedChat?.controlValues
6291
+ });
6109
6292
  return {
6110
6293
  type: this.type,
6111
6294
  name: this.provider.name,
@@ -6122,11 +6305,9 @@ var IdeProviderInstance = class {
6122
6305
  workspace: this.workspace || null,
6123
6306
  extensions: extensionStates,
6124
6307
  cdpConnected: cdp?.isConnected || false,
6125
- currentModel: this.cachedChat?.model || void 0,
6126
- currentPlan: this.cachedChat?.mode || void 0,
6127
- currentAutoApprove: this.cachedChat?.autoApprove || void 0,
6128
- controlValues: this.cachedChat?.controlValues || void 0,
6308
+ controlValues: surface.controlValues,
6129
6309
  providerControls: this.provider.controls,
6310
+ summaryMetadata: surface.summaryMetadata,
6130
6311
  instanceId: this.instanceId,
6131
6312
  lastUpdated: Date.now(),
6132
6313
  settings: this.settings,
@@ -6298,8 +6479,13 @@ var IdeProviderInstance = class {
6298
6479
  chat.messages = messages.filter((m) => !hiddenKinds.has(m.kind || ""));
6299
6480
  }
6300
6481
  }
6301
- const controlValues = extractProviderControlValues(this.provider.controls, chat);
6302
- if (controlValues) chat.controlValues = controlValues;
6482
+ const patchedState = mergeProviderPatchState({
6483
+ providerControls: this.provider.controls,
6484
+ data: chat,
6485
+ mergeWithCurrent: false
6486
+ });
6487
+ chat.controlValues = Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : void 0;
6488
+ chat.summaryMetadata = patchedState.summaryMetadata;
6303
6489
  this.cachedChat = { ...chat, activeModal };
6304
6490
  this.detectAgentTransitions(chat, now);
6305
6491
  const persistedMessages = chat.messages || messages;
@@ -6386,14 +6572,18 @@ var IdeProviderInstance = class {
6386
6572
  }
6387
6573
  applyProviderResponse(data, options) {
6388
6574
  if (!data || typeof data !== "object") return;
6389
- const controlValues = extractProviderControlValues(this.provider.controls, data);
6390
- if (controlValues) {
6391
- this.cachedChat = {
6392
- ...this.cachedChat || {},
6393
- ...data,
6394
- controlValues: { ...this.cachedChat?.controlValues || {}, ...controlValues }
6395
- };
6396
- }
6575
+ const patchedState = mergeProviderPatchState({
6576
+ providerControls: this.provider.controls,
6577
+ data,
6578
+ currentControlValues: this.cachedChat?.controlValues,
6579
+ currentSummaryMetadata: this.cachedChat?.summaryMetadata
6580
+ });
6581
+ this.cachedChat = {
6582
+ ...this.cachedChat || {},
6583
+ ...data,
6584
+ controlValues: Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : void 0,
6585
+ summaryMetadata: patchedState.summaryMetadata
6586
+ };
6397
6587
  const effects = normalizeProviderEffects(data);
6398
6588
  for (const effect of effects) {
6399
6589
  const effectWhen = effect.when || "immediate";
@@ -7176,6 +7366,8 @@ var ACP_SESSION_CAPABILITIES = [
7176
7366
  function buildIdeWorkspaceSession(state, cdpManagers, options) {
7177
7367
  const profile = options.profile || "full";
7178
7368
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7369
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7370
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7179
7371
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7180
7372
  const includeSessionControls = shouldIncludeSessionControls(profile);
7181
7373
  const title = activeChat?.title || state.name;
@@ -7192,13 +7384,11 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
7192
7384
  title,
7193
7385
  ...includeSessionMetadata && { workspace: state.workspace || null },
7194
7386
  activeChat,
7387
+ ...summaryMetadata && { summaryMetadata },
7195
7388
  ...includeSessionMetadata && { capabilities: IDE_SESSION_CAPABILITIES },
7196
7389
  cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
7197
- currentModel: state.currentModel,
7198
- currentPlan: state.currentPlan,
7199
- currentAutoApprove: state.currentAutoApprove,
7200
7390
  ...includeSessionControls && {
7201
- controlValues: state.controlValues,
7391
+ ...controlValues && { controlValues },
7202
7392
  providerControls: state.providerControls
7203
7393
  },
7204
7394
  errorMessage: state.errorMessage,
@@ -7209,6 +7399,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
7209
7399
  function buildExtensionAgentSession(parent, ext, options) {
7210
7400
  const profile = options.profile || "full";
7211
7401
  const activeChat = normalizeActiveChatData(ext.activeChat, getActiveChatOptions(profile));
7402
+ const summaryMetadata = normalizeProviderSummaryMetadata(ext.summaryMetadata);
7403
+ const controlValues = normalizeProviderStateControlValues(ext.controlValues);
7212
7404
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7213
7405
  const includeSessionControls = shouldIncludeSessionControls(profile);
7214
7406
  return {
@@ -7224,11 +7416,10 @@ function buildExtensionAgentSession(parent, ext, options) {
7224
7416
  title: activeChat?.title || ext.name,
7225
7417
  ...includeSessionMetadata && { workspace: parent.workspace || null },
7226
7418
  activeChat,
7419
+ ...summaryMetadata && { summaryMetadata },
7227
7420
  ...includeSessionMetadata && { capabilities: EXTENSION_SESSION_CAPABILITIES },
7228
- currentModel: ext.currentModel,
7229
- currentPlan: ext.currentPlan,
7230
7421
  ...includeSessionControls && {
7231
- controlValues: ext.controlValues,
7422
+ ...controlValues && { controlValues },
7232
7423
  providerControls: ext.providerControls
7233
7424
  },
7234
7425
  errorMessage: ext.errorMessage,
@@ -7239,6 +7430,8 @@ function buildExtensionAgentSession(parent, ext, options) {
7239
7430
  function buildCliSession(state, options) {
7240
7431
  const profile = options.profile || "full";
7241
7432
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7433
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7434
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7242
7435
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7243
7436
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
7244
7437
  const includeSessionControls = shouldIncludeSessionControls(profile);
@@ -7265,11 +7458,12 @@ function buildCliSession(state, options) {
7265
7458
  mode: state.mode,
7266
7459
  resume: state.resume,
7267
7460
  activeChat,
7461
+ ...summaryMetadata && { summaryMetadata },
7268
7462
  ...includeSessionMetadata && {
7269
7463
  capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES
7270
7464
  },
7271
7465
  ...includeSessionControls && {
7272
- controlValues: state.controlValues,
7466
+ ...controlValues && { controlValues },
7273
7467
  providerControls: state.providerControls
7274
7468
  },
7275
7469
  errorMessage: state.errorMessage,
@@ -7280,6 +7474,8 @@ function buildCliSession(state, options) {
7280
7474
  function buildAcpSession(state, options) {
7281
7475
  const profile = options.profile || "full";
7282
7476
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7477
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7478
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7283
7479
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7284
7480
  const includeSessionControls = shouldIncludeSessionControls(profile);
7285
7481
  return {
@@ -7295,13 +7491,10 @@ function buildAcpSession(state, options) {
7295
7491
  title: activeChat?.title || state.name,
7296
7492
  ...includeSessionMetadata && { workspace: state.workspace || null },
7297
7493
  activeChat,
7494
+ ...summaryMetadata && { summaryMetadata },
7298
7495
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
7299
- currentModel: state.currentModel,
7300
- currentPlan: state.currentPlan,
7301
7496
  ...includeSessionControls && {
7302
- acpConfigOptions: state.acpConfigOptions,
7303
- acpModes: state.acpModes,
7304
- controlValues: state.controlValues,
7497
+ ...controlValues && { controlValues },
7305
7498
  providerControls: state.providerControls
7306
7499
  },
7307
7500
  errorMessage: state.errorMessage,
@@ -7993,7 +8186,7 @@ function getStateLastSignature(state) {
7993
8186
  async function getStableExtensionBaseline(h) {
7994
8187
  const first = await readExtensionChatState(h);
7995
8188
  if (getStateMessageCount(first) > 0 || getStateLastSignature(first)) return first;
7996
- await new Promise((resolve12) => setTimeout(resolve12, 150));
8189
+ await new Promise((resolve11) => setTimeout(resolve11, 150));
7997
8190
  const second = await readExtensionChatState(h);
7998
8191
  return getStateMessageCount(second) >= getStateMessageCount(first) ? second : first;
7999
8192
  }
@@ -8001,7 +8194,7 @@ async function verifyExtensionSendObserved(h, before) {
8001
8194
  const beforeCount = getStateMessageCount(before);
8002
8195
  const beforeSignature = getStateLastSignature(before);
8003
8196
  for (let attempt = 0; attempt < 12; attempt += 1) {
8004
- await new Promise((resolve12) => setTimeout(resolve12, 250));
8197
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
8005
8198
  const state = await readExtensionChatState(h);
8006
8199
  if (state?.status === "waiting_approval") return true;
8007
8200
  const afterCount = getStateMessageCount(state);
@@ -9193,6 +9386,30 @@ async function handleFileListBrowse(h, args) {
9193
9386
  }
9194
9387
  }
9195
9388
 
9389
+ // src/commands/stream-commands.ts
9390
+ init_config();
9391
+
9392
+ // src/config/provider-source-config.ts
9393
+ function normalizeProviderDir(value) {
9394
+ if (typeof value !== "string") return void 0;
9395
+ const trimmed = value.trim();
9396
+ return trimmed ? trimmed : void 0;
9397
+ }
9398
+ function parseProviderSourceConfigUpdate(input) {
9399
+ const updates = {};
9400
+ if (Object.prototype.hasOwnProperty.call(input, "providerSourceMode")) {
9401
+ const { providerSourceMode } = input;
9402
+ if (providerSourceMode !== "normal" && providerSourceMode !== "no-upstream") {
9403
+ return { ok: false, error: "providerSourceMode must be 'normal' or 'no-upstream'" };
9404
+ }
9405
+ updates.providerSourceMode = providerSourceMode;
9406
+ }
9407
+ if (Object.prototype.hasOwnProperty.call(input, "providerDir")) {
9408
+ updates.providerDir = normalizeProviderDir(input.providerDir);
9409
+ }
9410
+ return { ok: true, updates };
9411
+ }
9412
+
9196
9413
  // src/providers/cli-script-results.ts
9197
9414
  function parseCliScriptResult(result) {
9198
9415
  if (typeof result === "string") {
@@ -9305,8 +9522,49 @@ async function handleSetProviderSetting(h, args) {
9305
9522
  }
9306
9523
  return { success: false, error: `Failed to set ${providerType}.${key} \u2014 invalid key, value, or not a public setting` };
9307
9524
  }
9308
- function normalizeProviderScriptArgs(args) {
9525
+ function handleGetProviderSourceConfig(h, _args) {
9526
+ const loader = h.ctx.providerLoader;
9527
+ if (!loader) return { success: false, error: "providerLoader not available" };
9528
+ return { success: true, ...loader.getSourceConfig() };
9529
+ }
9530
+ async function handleSetProviderSourceConfig(h, args) {
9531
+ const loader = h.ctx.providerLoader;
9532
+ if (!loader) return { success: false, error: "providerLoader not available" };
9533
+ const parsed = parseProviderSourceConfigUpdate(args || {});
9534
+ if ("error" in parsed) {
9535
+ return { success: false, error: parsed.error };
9536
+ }
9537
+ const currentConfig2 = loadConfig();
9538
+ const nextConfig = {
9539
+ ...currentConfig2,
9540
+ ...parsed.updates.providerSourceMode ? { providerSourceMode: parsed.updates.providerSourceMode } : {},
9541
+ ...Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? { providerDir: parsed.updates.providerDir } : {}
9542
+ };
9543
+ saveConfig(nextConfig);
9544
+ const sourceConfig = loader.applySourceConfig({
9545
+ sourceMode: nextConfig.providerSourceMode,
9546
+ userDir: Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? parsed.updates.providerDir : loader.getSourceConfig().explicitProviderDir || void 0
9547
+ });
9548
+ loader.reload();
9549
+ loader.registerToDetector();
9550
+ await h.ctx.onProviderSourceConfigChanged?.();
9551
+ LOG.info(
9552
+ "Command",
9553
+ `[set_provider_source_config] mode=${sourceConfig.sourceMode} explicitProviderDir=${sourceConfig.explicitProviderDir || "-"} userDir=${sourceConfig.userDir}`
9554
+ );
9555
+ return { success: true, reloaded: true, ...sourceConfig };
9556
+ }
9557
+ function normalizeProviderScriptArgs(args, scriptName) {
9309
9558
  const normalizedArgs = { ...args || {} };
9559
+ const normalizedScriptName = String(scriptName || "").toLowerCase();
9560
+ if (Object.prototype.hasOwnProperty.call(normalizedArgs, "value")) {
9561
+ if (normalizedArgs.model === void 0 && (normalizedScriptName === "setmodel" || normalizedScriptName === "setmodelgui" || normalizedScriptName === "webviewsetmodel")) {
9562
+ normalizedArgs.model = normalizedArgs.value;
9563
+ }
9564
+ if (normalizedArgs.mode === void 0 && (normalizedScriptName === "setmode" || normalizedScriptName === "webviewsetmode")) {
9565
+ normalizedArgs.mode = normalizedArgs.value;
9566
+ }
9567
+ }
9310
9568
  for (const key of ["mode", "model", "message", "action", "button", "text", "sessionId", "value"]) {
9311
9569
  if (key in normalizedArgs && !(key.toUpperCase() in normalizedArgs)) {
9312
9570
  normalizedArgs[key.toUpperCase()] = normalizedArgs[key];
@@ -9352,7 +9610,7 @@ async function executeProviderScript(h, args, scriptName) {
9352
9610
  if (!provider.scripts?.[actualScriptName]) {
9353
9611
  return { success: false, error: `Script '${actualScriptName}' not available for ${resolvedProviderType}` };
9354
9612
  }
9355
- const normalizedArgs = normalizeProviderScriptArgs(args);
9613
+ const normalizedArgs = normalizeProviderScriptArgs(args, actualScriptName);
9356
9614
  if (provider.category === "cli") {
9357
9615
  const adapter = h.getCliAdapter(args?.targetSessionId || resolvedProviderType);
9358
9616
  if (!adapter?.invokeScript) {
@@ -9998,6 +10256,10 @@ var DaemonCommandHandler = class {
9998
10256
  return handleGetProviderSettings(this, args);
9999
10257
  case "set_provider_setting":
10000
10258
  return handleSetProviderSetting(this, args);
10259
+ case "get_provider_source_config":
10260
+ return handleGetProviderSourceConfig(this, args);
10261
+ case "set_provider_source_config":
10262
+ return handleSetProviderSourceConfig(this, args);
10001
10263
  // ─── IDE Extension Settings (stream-commands.ts) ──────────
10002
10264
  case "get_ide_extensions":
10003
10265
  return handleGetIdeExtensions(this, args);
@@ -10037,7 +10299,7 @@ var DaemonCommandHandler = class {
10037
10299
  try {
10038
10300
  const http3 = await import("http");
10039
10301
  const postData = JSON.stringify(body);
10040
- const result = await new Promise((resolve12, reject) => {
10302
+ const result = await new Promise((resolve11, reject) => {
10041
10303
  const req = http3.request({
10042
10304
  hostname: "127.0.0.1",
10043
10305
  port: 19280,
@@ -10049,9 +10311,9 @@ var DaemonCommandHandler = class {
10049
10311
  res.on("data", (chunk) => data += chunk);
10050
10312
  res.on("end", () => {
10051
10313
  try {
10052
- resolve12(JSON.parse(data));
10314
+ resolve11(JSON.parse(data));
10053
10315
  } catch {
10054
- resolve12({ raw: data });
10316
+ resolve11({ raw: data });
10055
10317
  }
10056
10318
  });
10057
10319
  });
@@ -10069,15 +10331,15 @@ var DaemonCommandHandler = class {
10069
10331
  if (!providerType) return { success: false, error: "providerType required" };
10070
10332
  try {
10071
10333
  const http3 = await import("http");
10072
- const result = await new Promise((resolve12, reject) => {
10334
+ const result = await new Promise((resolve11, reject) => {
10073
10335
  http3.get(`http://127.0.0.1:19280/api/providers/${providerType}/${endpoint}`, (res) => {
10074
10336
  let data = "";
10075
10337
  res.on("data", (chunk) => data += chunk);
10076
10338
  res.on("end", () => {
10077
10339
  try {
10078
- resolve12(JSON.parse(data));
10340
+ resolve11(JSON.parse(data));
10079
10341
  } catch {
10080
- resolve12({ raw: data });
10342
+ resolve11({ raw: data });
10081
10343
  }
10082
10344
  });
10083
10345
  }).on("error", reject);
@@ -10091,7 +10353,7 @@ var DaemonCommandHandler = class {
10091
10353
  try {
10092
10354
  const http3 = await import("http");
10093
10355
  const postData = JSON.stringify(args || {});
10094
- const result = await new Promise((resolve12, reject) => {
10356
+ const result = await new Promise((resolve11, reject) => {
10095
10357
  const req = http3.request({
10096
10358
  hostname: "127.0.0.1",
10097
10359
  port: 19280,
@@ -10103,9 +10365,9 @@ var DaemonCommandHandler = class {
10103
10365
  res.on("data", (chunk) => data += chunk);
10104
10366
  res.on("end", () => {
10105
10367
  try {
10106
- resolve12(JSON.parse(data));
10368
+ resolve11(JSON.parse(data));
10107
10369
  } catch {
10108
- resolve12({ raw: data });
10370
+ resolve11({ raw: data });
10109
10371
  }
10110
10372
  });
10111
10373
  });
@@ -10155,6 +10417,9 @@ function getForcedNewSessionScriptName(provider, launchMode) {
10155
10417
  const controls = Array.isArray(provider.controls) ? provider.controls : [];
10156
10418
  for (const control of controls) {
10157
10419
  if (control?.type !== "action") continue;
10420
+ if (typeof control?.confirmTitle === "string" && control.confirmTitle.trim()) continue;
10421
+ if (typeof control?.confirmMessage === "string" && control.confirmMessage.trim()) continue;
10422
+ if (typeof control?.confirmLabel === "string" && control.confirmLabel.trim()) continue;
10158
10423
  const invokeScript = typeof control?.invokeScript === "string" ? control.invokeScript.trim() : "";
10159
10424
  if (!invokeScript) continue;
10160
10425
  const controlId = typeof control?.id === "string" ? control.id.trim() : "";
@@ -10164,6 +10429,20 @@ function getForcedNewSessionScriptName(provider, launchMode) {
10164
10429
  }
10165
10430
  return null;
10166
10431
  }
10432
+ async function waitForCliAdapterReady(adapter, options) {
10433
+ const timeoutMs = Math.max(100, options?.timeoutMs ?? 15e3);
10434
+ const pollMs = Math.max(10, options?.pollMs ?? 50);
10435
+ const deadline = Date.now() + timeoutMs;
10436
+ while (Date.now() < deadline) {
10437
+ if (adapter?.isReady?.()) return;
10438
+ const status = adapter?.getStatus?.()?.status;
10439
+ if (status === "stopped") {
10440
+ throw new Error("CLI runtime stopped before it became ready");
10441
+ }
10442
+ await new Promise((resolve11) => setTimeout(resolve11, pollMs));
10443
+ }
10444
+ throw new Error(`CLI runtime did not become ready within ${timeoutMs}ms`);
10445
+ }
10167
10446
  var CliProviderInstance = class {
10168
10447
  constructor(provider, workingDir, cliArgs = [], instanceId, transportFactory, options) {
10169
10448
  this.provider = provider;
@@ -10192,6 +10471,7 @@ var CliProviderInstance = class {
10192
10471
  generatingDebouncePending = null;
10193
10472
  lastApprovalEventAt = 0;
10194
10473
  controlValues = {};
10474
+ summaryMetadata = void 0;
10195
10475
  appliedEffectKeys = /* @__PURE__ */ new Set();
10196
10476
  historyWriter;
10197
10477
  runtimeMessages = [];
@@ -10334,13 +10614,7 @@ var CliProviderInstance = class {
10334
10614
  if (historyMessageCount !== null) {
10335
10615
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
10336
10616
  }
10337
- const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
10338
- if (controlValues) {
10339
- this.controlValues = { ...this.controlValues, ...controlValues };
10340
- }
10341
10617
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
10342
- 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;
10343
- 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;
10344
10618
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
10345
10619
  if (parsedMessages.length > 0) {
10346
10620
  const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
@@ -10362,6 +10636,10 @@ var CliProviderInstance = class {
10362
10636
  }
10363
10637
  }
10364
10638
  this.applyProviderResponse(parsedStatus, { phase: "immediate" });
10639
+ const surface = resolveProviderStateSurface({
10640
+ summaryMetadata: this.summaryMetadata,
10641
+ controlValues: this.controlValues
10642
+ });
10365
10643
  return {
10366
10644
  type: this.type,
10367
10645
  name: this.provider.name,
@@ -10377,8 +10655,6 @@ var CliProviderInstance = class {
10377
10655
  inputContent: ""
10378
10656
  },
10379
10657
  workspace: this.workingDir,
10380
- currentModel,
10381
- currentPlan,
10382
10658
  instanceId: this.instanceId,
10383
10659
  providerSessionId: this.providerSessionId,
10384
10660
  lastUpdated: Date.now(),
@@ -10393,8 +10669,9 @@ var CliProviderInstance = class {
10393
10669
  attachedClients: runtime.attachedClients || []
10394
10670
  } : void 0,
10395
10671
  resume: this.provider.resume,
10396
- controlValues: this.controlValues,
10397
- providerControls: this.provider.controls
10672
+ controlValues: surface.controlValues,
10673
+ providerControls: this.provider.controls,
10674
+ summaryMetadata: surface.summaryMetadata
10398
10675
  };
10399
10676
  }
10400
10677
  setPresentationMode(mode) {
@@ -10442,6 +10719,7 @@ var CliProviderInstance = class {
10442
10719
  const scriptName = getForcedNewSessionScriptName(this.provider, this.launchMode);
10443
10720
  if (!scriptName) return;
10444
10721
  LOG.info("CLI", `[${this.type}] forcing fresh session launch via script: ${scriptName}`);
10722
+ await waitForCliAdapterReady(this.adapter);
10445
10723
  const raw = await this.adapter.invokeScript(scriptName, {});
10446
10724
  const parsed = parseCliScriptResult(raw);
10447
10725
  if (!parsed.success) {
@@ -10597,10 +10875,14 @@ var CliProviderInstance = class {
10597
10875
  this.suppressIdleHistoryReplay = false;
10598
10876
  this.adapter.clearHistory();
10599
10877
  }
10600
- const controlValues = extractProviderControlValues(this.provider.controls, data);
10601
- if (controlValues) {
10602
- this.controlValues = { ...this.controlValues, ...controlValues };
10603
- }
10878
+ const patchedState = mergeProviderPatchState({
10879
+ providerControls: this.provider.controls,
10880
+ data,
10881
+ currentControlValues: this.controlValues,
10882
+ currentSummaryMetadata: this.summaryMetadata
10883
+ });
10884
+ this.controlValues = patchedState.controlValues;
10885
+ this.summaryMetadata = patchedState.summaryMetadata;
10604
10886
  const effects = normalizeProviderEffects(data);
10605
10887
  for (const effect of effects) {
10606
10888
  const effectWhen = effect.when || "immediate";
@@ -10791,6 +11073,7 @@ ${effect.notification.body || ""}`.trim();
10791
11073
  const previousProviderSessionId = this.providerSessionId;
10792
11074
  this.providerSessionId = nextSessionId;
10793
11075
  this.historyWriter.promoteHistorySession(this.type, previousHistorySessionId, nextSessionId);
11076
+ this.historyWriter.writeSessionStart(this.type, nextSessionId, this.workingDir, this.instanceId);
10794
11077
  this.adapter.updateRuntimeMeta({ providerSessionId: nextSessionId });
10795
11078
  this.onProviderSessionResolved?.({
10796
11079
  instanceId: this.instanceId,
@@ -10970,8 +11253,7 @@ var AcpProviderInstance = class {
10970
11253
  lastStatus = "starting";
10971
11254
  generatingStartedAt = 0;
10972
11255
  agentCapabilities = {};
10973
- currentModel;
10974
- currentMode;
11256
+ currentSelections = {};
10975
11257
  activeToolCalls = [];
10976
11258
  stopReason = null;
10977
11259
  partialContent = "";
@@ -11051,8 +11333,6 @@ var AcpProviderInstance = class {
11051
11333
  inputContent: ""
11052
11334
  },
11053
11335
  workspace: this.workingDir,
11054
- currentModel: this.currentModel,
11055
- currentPlan: this.currentMode,
11056
11336
  instanceId: this.instanceId,
11057
11337
  lastUpdated: Date.now(),
11058
11338
  settings: this.settings,
@@ -11063,11 +11343,9 @@ var AcpProviderInstance = class {
11063
11343
  // Error details for dashboard display
11064
11344
  errorMessage: this.errorMessage || void 0,
11065
11345
  errorReason: this.errorReason || void 0,
11066
- controlValues: {
11067
- ...this.currentModel ? { model: this.currentModel } : {},
11068
- ...this.currentMode ? { mode: this.currentMode } : {}
11069
- },
11070
- providerControls: this.provider.controls
11346
+ controlValues: this.getSelectionControlValues(),
11347
+ providerControls: this.provider.controls,
11348
+ summaryMetadata: this.buildSelectionSummaryMetadata()
11071
11349
  };
11072
11350
  }
11073
11351
  onEvent(event, data) {
@@ -11101,6 +11379,54 @@ var AcpProviderInstance = class {
11101
11379
  getInstanceId() {
11102
11380
  return this.instanceId;
11103
11381
  }
11382
+ resolveConfigOptionLabel(category, value) {
11383
+ if (!value) return void 0;
11384
+ const option = this.configOptions.find((entry) => entry.category === category);
11385
+ return option?.options.find((candidate) => candidate.value === value)?.name || value;
11386
+ }
11387
+ resolveModeLabel(modeId) {
11388
+ if (!modeId) return void 0;
11389
+ return this.availableModes.find((mode) => mode.id === modeId)?.name || modeId;
11390
+ }
11391
+ getCurrentSelection(category) {
11392
+ return this.currentSelections[category];
11393
+ }
11394
+ setCurrentSelection(category, value) {
11395
+ const normalized = typeof value === "string" ? value.trim() : "";
11396
+ if (normalized) {
11397
+ this.currentSelections[category] = normalized;
11398
+ return;
11399
+ }
11400
+ delete this.currentSelections[category];
11401
+ }
11402
+ getSelectionControlValues() {
11403
+ const model = this.getCurrentSelection("model");
11404
+ const mode = this.getCurrentSelection("mode");
11405
+ return {
11406
+ ...model ? { model } : {},
11407
+ ...mode ? { mode } : {}
11408
+ };
11409
+ }
11410
+ resolveSelectionLabel(category, value) {
11411
+ if (!value) return void 0;
11412
+ const configLabel = this.resolveConfigOptionLabel(category, value);
11413
+ if (configLabel && configLabel !== value) return configLabel;
11414
+ if (category === "mode") {
11415
+ const modeLabel = this.resolveModeLabel(value);
11416
+ if (modeLabel) return modeLabel;
11417
+ }
11418
+ return configLabel || value;
11419
+ }
11420
+ buildSelectionSummaryMetadata() {
11421
+ const model = this.getCurrentSelection("model");
11422
+ const mode = this.getCurrentSelection("mode");
11423
+ return buildLegacyModelModeSummaryMetadata({
11424
+ model,
11425
+ mode,
11426
+ modelLabel: this.resolveSelectionLabel("model", model),
11427
+ modeLabel: this.resolveSelectionLabel("mode", mode)
11428
+ });
11429
+ }
11104
11430
  // ─── ACP Config Options & Modes ─────────────────────
11105
11431
  parseConfigOptions(raw) {
11106
11432
  if (!Array.isArray(raw)) return;
@@ -11132,12 +11458,14 @@ var AcpProviderInstance = class {
11132
11458
  }
11133
11459
  }
11134
11460
  this.configOptions.push({ category, configId, currentValue, options: flatOptions });
11135
- if (category === "model" && currentValue) this.currentModel = currentValue;
11461
+ if (category === "model" || category === "mode") {
11462
+ this.setCurrentSelection(category, currentValue);
11463
+ }
11136
11464
  }
11137
11465
  }
11138
11466
  parseModes(raw) {
11139
11467
  if (!raw) return;
11140
- if (raw.currentModeId) this.currentMode = raw.currentModeId;
11468
+ this.setCurrentSelection("mode", raw.currentModeId);
11141
11469
  if (Array.isArray(raw.availableModes)) {
11142
11470
  this.availableModes = raw.availableModes.map((m) => ({
11143
11471
  id: m.id,
@@ -11156,8 +11484,7 @@ var AcpProviderInstance = class {
11156
11484
  if (this.useStaticConfig) {
11157
11485
  opt.currentValue = value;
11158
11486
  this.selectedConfig[opt.configId] = value;
11159
- if (category === "model") this.currentModel = value;
11160
- if (category === "mode") this.currentMode = value;
11487
+ if (category === "model" || category === "mode") this.setCurrentSelection(category, value);
11161
11488
  this.log.info(`[${this.type}] Static config ${category} set to: ${value} \u2014 restarting agent`);
11162
11489
  await this.restartWithNewConfig();
11163
11490
  return;
@@ -11175,7 +11502,7 @@ var AcpProviderInstance = class {
11175
11502
  value
11176
11503
  });
11177
11504
  opt.currentValue = value;
11178
- if (category === "model") this.currentModel = value;
11505
+ if (category === "model" || category === "mode") this.setCurrentSelection(category, value);
11179
11506
  if (result?.configOptions) this.parseConfigOptions(result.configOptions);
11180
11507
  this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
11181
11508
  } catch (e) {
@@ -11191,7 +11518,7 @@ var AcpProviderInstance = class {
11191
11518
  opt.currentValue = modeId;
11192
11519
  this.selectedConfig[opt.configId] = modeId;
11193
11520
  }
11194
- this.currentMode = modeId;
11521
+ this.setCurrentSelection("mode", modeId);
11195
11522
  this.log.info(`[${this.type}] Static mode set to: ${modeId} \u2014 restarting agent`);
11196
11523
  await this.restartWithNewConfig();
11197
11524
  return;
@@ -11206,7 +11533,7 @@ var AcpProviderInstance = class {
11206
11533
  sessionId: this.sessionId,
11207
11534
  modeId
11208
11535
  });
11209
- this.currentMode = modeId;
11536
+ this.setCurrentSelection("mode", modeId);
11210
11537
  this.log.info(`[${this.type}] Mode set to: ${modeId}`);
11211
11538
  } catch (e) {
11212
11539
  const message = e?.message || "Unknown ACP mode error";
@@ -11377,13 +11704,13 @@ var AcpProviderInstance = class {
11377
11704
  }
11378
11705
  this.currentStatus = "waiting_approval";
11379
11706
  this.detectStatusTransition();
11380
- const approved = await new Promise((resolve12) => {
11381
- this.permissionResolvers.push(resolve12);
11707
+ const approved = await new Promise((resolve11) => {
11708
+ this.permissionResolvers.push(resolve11);
11382
11709
  setTimeout(() => {
11383
- const idx = this.permissionResolvers.indexOf(resolve12);
11710
+ const idx = this.permissionResolvers.indexOf(resolve11);
11384
11711
  if (idx >= 0) {
11385
11712
  this.permissionResolvers.splice(idx, 1);
11386
- resolve12(false);
11713
+ resolve11(false);
11387
11714
  }
11388
11715
  }, 3e5);
11389
11716
  });
@@ -11464,8 +11791,8 @@ var AcpProviderInstance = class {
11464
11791
  if (result?.modes) this.log.debug(`[${this.type}] modes: ${JSON.stringify(result.modes).slice(0, 300)}`);
11465
11792
  this.parseConfigOptions(result?.configOptions);
11466
11793
  this.parseModes(result?.modes);
11467
- if (!this.currentModel && result?.models?.currentModelId) {
11468
- this.currentModel = result.models.currentModelId;
11794
+ if (!this.getCurrentSelection("model") && result?.models?.currentModelId) {
11795
+ this.setCurrentSelection("model", result.models.currentModelId);
11469
11796
  }
11470
11797
  if (this.configOptions.length === 0 && this.provider.staticConfigOptions?.length) {
11471
11798
  this.useStaticConfig = true;
@@ -11479,13 +11806,16 @@ var AcpProviderInstance = class {
11479
11806
  });
11480
11807
  if (defaultVal) {
11481
11808
  this.selectedConfig[sc.configId] = defaultVal;
11482
- if (sc.category === "model") this.currentModel = defaultVal;
11483
- if (sc.category === "mode") this.currentMode = defaultVal;
11809
+ if (sc.category === "model" || sc.category === "mode") {
11810
+ this.setCurrentSelection(sc.category, defaultVal);
11811
+ }
11484
11812
  }
11485
11813
  }
11486
11814
  this.log.info(`[${this.type}] Using static configOptions (${this.configOptions.length} options)`);
11487
11815
  }
11488
- this.log.info(`[${this.type}] Session created: ${this.sessionId}${this.currentModel ? ` (model: ${this.currentModel})` : ""}${this.currentMode ? ` (mode: ${this.currentMode})` : ""}`);
11816
+ const currentModel = this.getCurrentSelection("model");
11817
+ const currentMode = this.getCurrentSelection("mode");
11818
+ this.log.info(`[${this.type}] Session created: ${this.sessionId}${currentModel ? ` (model: ${currentModel})` : ""}${currentMode ? ` (mode: ${currentMode})` : ""}`);
11489
11819
  if (this.configOptions.length > 0) {
11490
11820
  this.log.info(`[${this.type}] Config options: ${this.configOptions.map((c) => `${c.category}(${c.options.length})`).join(", ")}`);
11491
11821
  }
@@ -11660,7 +11990,7 @@ var AcpProviderInstance = class {
11660
11990
  break;
11661
11991
  }
11662
11992
  case "current_mode_update": {
11663
- this.currentMode = update.currentModeId;
11993
+ this.setCurrentSelection("mode", update.currentModeId);
11664
11994
  break;
11665
11995
  }
11666
11996
  case "config_option_update": {
@@ -11733,7 +12063,7 @@ var AcpProviderInstance = class {
11733
12063
  this.detectStatusTransition();
11734
12064
  }
11735
12065
  if (params.model) {
11736
- this.currentModel = params.model;
12066
+ this.setCurrentSelection("model", params.model);
11737
12067
  }
11738
12068
  }
11739
12069
  /** Map SDK ToolCallStatus to internal status */
@@ -12022,7 +12352,11 @@ var DaemonCliManager = class {
12022
12352
  }
12023
12353
  persistRecentActivity(entry) {
12024
12354
  try {
12025
- let nextState = appendRecentActivity(loadState(), entry);
12355
+ const summaryMetadata = normalizeProviderSummaryMetadata(entry.summaryMetadata);
12356
+ let nextState = appendRecentActivity(loadState(), {
12357
+ ...entry,
12358
+ summaryMetadata
12359
+ });
12026
12360
  if (entry.providerSessionId && (entry.kind === "cli" || entry.kind === "acp")) {
12027
12361
  nextState = upsertSavedProviderSession(nextState, {
12028
12362
  kind: entry.kind,
@@ -12030,7 +12364,7 @@ var DaemonCliManager = class {
12030
12364
  providerName: entry.providerName,
12031
12365
  providerSessionId: entry.providerSessionId,
12032
12366
  workspace: entry.workspace,
12033
- currentModel: entry.currentModel,
12367
+ summaryMetadata,
12034
12368
  title: entry.title
12035
12369
  });
12036
12370
  }
@@ -12220,7 +12554,7 @@ ${installInfo}`
12220
12554
  providerType: normalizedType,
12221
12555
  providerName: provider.displayName || provider.name || normalizedType,
12222
12556
  workspace: resolvedDir,
12223
- currentModel: initialModel,
12557
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
12224
12558
  sessionId,
12225
12559
  title: provider.displayName || provider.name || normalizedType
12226
12560
  });
@@ -12322,7 +12656,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
12322
12656
  providerName: provider?.displayName || provider?.name || normalizedType,
12323
12657
  providerSessionId: sessionBinding.providerSessionId,
12324
12658
  workspace: resolvedDir,
12325
- currentModel: initialModel,
12659
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
12326
12660
  sessionId: key,
12327
12661
  title: provider?.displayName || provider?.name || normalizedType
12328
12662
  });
@@ -12699,6 +13033,9 @@ function validateProviderDefinition(raw) {
12699
13033
  warnings.push(`Unknown provider field: ${key}`);
12700
13034
  }
12701
13035
  }
13036
+ if (provider.disableUpstream !== void 0) {
13037
+ warnings.push("disableUpstream is deprecated in provider definitions; use machine-level provider source policy instead");
13038
+ }
12702
13039
  const category = provider.category;
12703
13040
  if (category === "cli" || category === "acp") {
12704
13041
  const spawn4 = provider.spawn;
@@ -12758,8 +13095,11 @@ function validateControl(control, errors) {
12758
13095
  var ProviderLoader = class _ProviderLoader {
12759
13096
  providers = /* @__PURE__ */ new Map();
12760
13097
  providerAvailability = /* @__PURE__ */ new Map();
13098
+ defaultProvidersDir;
13099
+ explicitProviderDir = null;
12761
13100
  userDir;
12762
13101
  upstreamDir;
13102
+ sourceMode = "normal";
12763
13103
  disableUpstream;
12764
13104
  watchers = [];
12765
13105
  logFn;
@@ -12773,22 +13113,15 @@ var ProviderLoader = class _ProviderLoader {
12773
13113
  static META_FILE = ".meta.json";
12774
13114
  constructor(options) {
12775
13115
  this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
12776
- const defaultProvidersDir = path14.join(os13.homedir(), ".adhdev", "providers");
12777
- if (options?.userDir) {
12778
- this.userDir = options.userDir;
12779
- this.log(`Config 'providerDir' applied: ${this.userDir}`);
12780
- } else {
12781
- const localRepoPath = path14.resolve(__dirname, "../../../../../adhdev-providers");
12782
- if (fs6.existsSync(localRepoPath)) {
12783
- this.userDir = localRepoPath;
12784
- this.log(`Auto-detected local public repository: ${this.userDir} (Dev workspace speedup)`);
12785
- } else {
12786
- this.userDir = defaultProvidersDir;
12787
- this.log(`Using default user providers directory: ${this.userDir}`);
12788
- }
12789
- }
12790
- this.upstreamDir = path14.join(defaultProvidersDir, ".upstream");
12791
- this.disableUpstream = options?.disableUpstream ?? false;
13116
+ this.defaultProvidersDir = path14.join(os13.homedir(), ".adhdev", "providers");
13117
+ this.userDir = this.defaultProvidersDir;
13118
+ this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
13119
+ this.disableUpstream = false;
13120
+ this.applySourceConfig({
13121
+ userDir: options?.userDir,
13122
+ sourceMode: options?.sourceMode,
13123
+ disableUpstream: options?.disableUpstream
13124
+ });
12792
13125
  }
12793
13126
  log(msg) {
12794
13127
  this.logFn(`[ProviderLoader] ${msg}`);
@@ -12813,6 +13146,33 @@ var ProviderLoader = class _ProviderLoader {
12813
13146
  getProviderRoots() {
12814
13147
  return [this.userDir, this.upstreamDir];
12815
13148
  }
13149
+ getSourceConfig() {
13150
+ return {
13151
+ sourceMode: this.sourceMode,
13152
+ disableUpstream: this.disableUpstream,
13153
+ explicitProviderDir: this.explicitProviderDir,
13154
+ userDir: this.userDir,
13155
+ upstreamDir: this.upstreamDir,
13156
+ providerRoots: this.getProviderRoots()
13157
+ };
13158
+ }
13159
+ applySourceConfig(options) {
13160
+ const nextSourceMode = options?.sourceMode === "no-upstream" ? "no-upstream" : options?.sourceMode === "normal" ? "normal" : options?.disableUpstream ? "no-upstream" : this.sourceMode || "normal";
13161
+ if (options && Object.prototype.hasOwnProperty.call(options, "userDir")) {
13162
+ this.explicitProviderDir = options.userDir?.trim() ? options.userDir : null;
13163
+ }
13164
+ this.sourceMode = nextSourceMode;
13165
+ this.userDir = this.explicitProviderDir || this.defaultProvidersDir;
13166
+ this.upstreamDir = path14.join(this.defaultProvidersDir, ".upstream");
13167
+ this.disableUpstream = this.sourceMode === "no-upstream";
13168
+ if (this.explicitProviderDir) {
13169
+ this.log(`Config 'providerDir' applied: ${this.userDir}`);
13170
+ } else {
13171
+ this.log(`Using default user providers directory: ${this.userDir}`);
13172
+ }
13173
+ this.log(`Provider source config: mode=${this.sourceMode} explicitProviderDir=${this.explicitProviderDir || "-"} userDir=${this.userDir} upstreamDir=${this.upstreamDir}`);
13174
+ return this.getSourceConfig();
13175
+ }
12816
13176
  /**
12817
13177
  * Canonical provider directory shape for a given root.
12818
13178
  */
@@ -12863,7 +13223,7 @@ var ProviderLoader = class _ProviderLoader {
12863
13223
  this.log(`Loaded ${upstreamCount} upstream providers (auto-updated)`);
12864
13224
  }
12865
13225
  } else if (this.disableUpstream) {
12866
- this.log("Upstream loading disabled (disableUpstream=true)");
13226
+ this.log("Upstream loading disabled (sourceMode=no-upstream)");
12867
13227
  }
12868
13228
  if (fs6.existsSync(this.userDir)) {
12869
13229
  const userCount = this.loadDir(this.userDir, [".upstream"]);
@@ -13374,7 +13734,7 @@ var ProviderLoader = class _ProviderLoader {
13374
13734
  */
13375
13735
  async fetchLatest() {
13376
13736
  if (this.disableUpstream) {
13377
- this.log("Upstream fetch skipped (disableUpstream=true)");
13737
+ this.log("Upstream fetch skipped (sourceMode=no-upstream)");
13378
13738
  return { updated: false };
13379
13739
  }
13380
13740
  const https = __require("https");
@@ -13396,7 +13756,7 @@ var ProviderLoader = class _ProviderLoader {
13396
13756
  return { updated: false };
13397
13757
  }
13398
13758
  try {
13399
- const etag = await new Promise((resolve12, reject) => {
13759
+ const etag = await new Promise((resolve11, reject) => {
13400
13760
  const options = {
13401
13761
  method: "HEAD",
13402
13762
  hostname: "github.com",
@@ -13414,7 +13774,7 @@ var ProviderLoader = class _ProviderLoader {
13414
13774
  headers: { "User-Agent": "adhdev-launcher" },
13415
13775
  timeout: 1e4
13416
13776
  }, (res2) => {
13417
- resolve12(res2.headers.etag || res2.headers["last-modified"] || "");
13777
+ resolve11(res2.headers.etag || res2.headers["last-modified"] || "");
13418
13778
  });
13419
13779
  req2.on("error", reject);
13420
13780
  req2.on("timeout", () => {
@@ -13423,7 +13783,7 @@ var ProviderLoader = class _ProviderLoader {
13423
13783
  });
13424
13784
  req2.end();
13425
13785
  } else {
13426
- resolve12(res.headers.etag || res.headers["last-modified"] || "");
13786
+ resolve11(res.headers.etag || res.headers["last-modified"] || "");
13427
13787
  }
13428
13788
  });
13429
13789
  req.on("error", reject);
@@ -13487,7 +13847,7 @@ var ProviderLoader = class _ProviderLoader {
13487
13847
  downloadFile(url, destPath) {
13488
13848
  const https = __require("https");
13489
13849
  const http3 = __require("http");
13490
- return new Promise((resolve12, reject) => {
13850
+ return new Promise((resolve11, reject) => {
13491
13851
  const doRequest = (reqUrl, redirectCount = 0) => {
13492
13852
  if (redirectCount > 5) {
13493
13853
  reject(new Error("Too many redirects"));
@@ -13507,7 +13867,7 @@ var ProviderLoader = class _ProviderLoader {
13507
13867
  res.pipe(ws);
13508
13868
  ws.on("finish", () => {
13509
13869
  ws.close();
13510
- resolve12();
13870
+ resolve11();
13511
13871
  });
13512
13872
  ws.on("error", reject);
13513
13873
  });
@@ -13982,17 +14342,17 @@ async function findFreePort(ports) {
13982
14342
  throw new Error("No free port found");
13983
14343
  }
13984
14344
  function checkPortFree(port) {
13985
- return new Promise((resolve12) => {
14345
+ return new Promise((resolve11) => {
13986
14346
  const server = net.createServer();
13987
14347
  server.unref();
13988
- server.on("error", () => resolve12(false));
14348
+ server.on("error", () => resolve11(false));
13989
14349
  server.listen(port, "127.0.0.1", () => {
13990
- server.close(() => resolve12(true));
14350
+ server.close(() => resolve11(true));
13991
14351
  });
13992
14352
  });
13993
14353
  }
13994
14354
  async function isCdpActive(port) {
13995
- return new Promise((resolve12) => {
14355
+ return new Promise((resolve11) => {
13996
14356
  const req = __require("http").get(`http://127.0.0.1:${port}/json/version`, {
13997
14357
  timeout: 2e3
13998
14358
  }, (res) => {
@@ -14001,16 +14361,16 @@ async function isCdpActive(port) {
14001
14361
  res.on("end", () => {
14002
14362
  try {
14003
14363
  const info = JSON.parse(data);
14004
- resolve12(!!info["WebKit-Version"] || !!info["Browser"]);
14364
+ resolve11(!!info["WebKit-Version"] || !!info["Browser"]);
14005
14365
  } catch {
14006
- resolve12(false);
14366
+ resolve11(false);
14007
14367
  }
14008
14368
  });
14009
14369
  });
14010
- req.on("error", () => resolve12(false));
14370
+ req.on("error", () => resolve11(false));
14011
14371
  req.on("timeout", () => {
14012
14372
  req.destroy();
14013
- resolve12(false);
14373
+ resolve11(false);
14014
14374
  });
14015
14375
  });
14016
14376
  }
@@ -14461,12 +14821,90 @@ cleanOldFiles();
14461
14821
  // src/commands/router.ts
14462
14822
  init_logger();
14463
14823
 
14824
+ // src/session-host/runtime-surface.ts
14825
+ var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
14826
+ function isSessionHostLiveRuntime(record) {
14827
+ const lifecycle = String(record?.lifecycle || "").trim();
14828
+ return LIVE_LIFECYCLES.has(lifecycle);
14829
+ }
14830
+ function getSessionHostRecoveryLabel(meta) {
14831
+ const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
14832
+ if (!recoveryState) return null;
14833
+ if (recoveryState === "auto_resumed") return "restored after restart";
14834
+ if (recoveryState === "resume_failed") return "restore failed";
14835
+ if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
14836
+ if (recoveryState === "orphan_snapshot") return "snapshot recovered";
14837
+ return recoveryState.replace(/_/g, " ");
14838
+ }
14839
+ function isSessionHostRecoverySnapshot(record) {
14840
+ if (!record) return false;
14841
+ if (isSessionHostLiveRuntime(record)) return false;
14842
+ const lifecycle = String(record.lifecycle || "").trim();
14843
+ if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
14844
+ return false;
14845
+ }
14846
+ const meta = record.meta || void 0;
14847
+ if (meta?.restoredFromStorage === true) return true;
14848
+ return getSessionHostRecoveryLabel(meta) !== null;
14849
+ }
14850
+ function getSessionHostSurfaceKind(record) {
14851
+ if (isSessionHostLiveRuntime(record)) return "live_runtime";
14852
+ if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
14853
+ return "inactive_record";
14854
+ }
14855
+ function partitionSessionHostRecords(records) {
14856
+ const liveRuntimes = [];
14857
+ const recoverySnapshots = [];
14858
+ const inactiveRecords = [];
14859
+ for (const record of records) {
14860
+ const kind = getSessionHostSurfaceKind(record);
14861
+ if (kind === "live_runtime") {
14862
+ liveRuntimes.push(record);
14863
+ } else if (kind === "recovery_snapshot") {
14864
+ recoverySnapshots.push(record);
14865
+ } else {
14866
+ inactiveRecords.push(record);
14867
+ }
14868
+ }
14869
+ return {
14870
+ liveRuntimes,
14871
+ recoverySnapshots,
14872
+ inactiveRecords
14873
+ };
14874
+ }
14875
+ function partitionSessionHostDiagnosticsSessions(records) {
14876
+ return partitionSessionHostRecords(records || []);
14877
+ }
14878
+
14464
14879
  // src/status/snapshot.ts
14465
14880
  init_config();
14466
14881
  import * as os16 from "os";
14467
14882
  init_terminal_screen();
14468
14883
  init_logger();
14469
14884
  var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
14885
+ var recentReadDebugSignatureBySession = /* @__PURE__ */ new Map();
14886
+ function buildRecentReadDebugSignature(snapshot) {
14887
+ return [
14888
+ snapshot.providerType,
14889
+ snapshot.status,
14890
+ snapshot.inboxBucket,
14891
+ snapshot.unread ? "1" : "0",
14892
+ String(snapshot.lastSeenAt),
14893
+ snapshot.completionMarker,
14894
+ snapshot.seenCompletionMarker,
14895
+ String(snapshot.lastUpdated),
14896
+ String(snapshot.lastUsedAt),
14897
+ snapshot.lastRole,
14898
+ String(snapshot.messageUpdatedAt)
14899
+ ].join("|");
14900
+ }
14901
+ function shouldEmitRecentReadDebugLog(cache, snapshot) {
14902
+ const nextSignature = buildRecentReadDebugSignature(snapshot);
14903
+ const previousSignature = cache.get(snapshot.sessionId);
14904
+ if (previousSignature === nextSignature) return false;
14905
+ cache.set(snapshot.sessionId, nextSignature);
14906
+ return true;
14907
+ }
14470
14908
  function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
14471
14909
  return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
14472
14910
  id: ide.id,
@@ -14618,7 +15056,7 @@ function buildRecentLaunches(recentActivity) {
14618
15056
  providerSessionId: item.providerSessionId,
14619
15057
  title: item.title || item.providerName,
14620
15058
  workspace: item.workspace,
14621
- currentModel: item.currentModel,
15059
+ summaryMetadata: item.summaryMetadata,
14622
15060
  lastLaunchedAt: item.lastUsedAt
14623
15061
  })).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
14624
15062
  }
@@ -14659,9 +15097,24 @@ function buildStatusSnapshot(options) {
14659
15097
  session.unread = unread;
14660
15098
  session.inboxBucket = inboxBucket;
14661
15099
  if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
15100
+ const recentReadSnapshot = {
15101
+ sessionId: session.id,
15102
+ providerType: session.providerType,
15103
+ status: String(session.status || ""),
15104
+ inboxBucket,
15105
+ unread,
15106
+ lastSeenAt,
15107
+ completionMarker: completionMarker || "-",
15108
+ seenCompletionMarker: seenCompletionMarker || "-",
15109
+ lastUpdated: Number(session.lastUpdated || 0),
15110
+ lastUsedAt,
15111
+ lastRole: getLastMessageRole(sourceSession),
15112
+ messageUpdatedAt: getSessionMessageUpdatedAt(sourceSession)
15113
+ };
15114
+ if (!shouldEmitRecentReadDebugLog(recentReadDebugSignatureBySession, recentReadSnapshot)) continue;
14662
15115
  LOG.info(
14663
15116
  "RecentRead",
14664
- `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)}`
15117
+ `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}`
14665
15118
  );
14666
15119
  }
14667
15120
  const lastDisplayMessage = getLastDisplayMessage(sourceSession);
@@ -14739,7 +15192,7 @@ async function waitForPidExit(pid, timeoutMs) {
14739
15192
  while (Date.now() - start < timeoutMs) {
14740
15193
  try {
14741
15194
  process.kill(pid, 0);
14742
- await new Promise((resolve12) => setTimeout(resolve12, 250));
15195
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
14743
15196
  } catch {
14744
15197
  return;
14745
15198
  }
@@ -14854,7 +15307,7 @@ async function runDaemonUpgradeHelper(payload) {
14854
15307
  appendUpgradeLog(installOutput.trim());
14855
15308
  }
14856
15309
  if (process.platform === "win32") {
14857
- await new Promise((resolve12) => setTimeout(resolve12, 500));
15310
+ await new Promise((resolve11) => setTimeout(resolve11, 500));
14858
15311
  cleanupStaleGlobalInstallDirs(payload.packageName);
14859
15312
  appendUpgradeLog("Post-install staging cleanup complete");
14860
15313
  }
@@ -14936,11 +15389,104 @@ function toHostedCliRuntimeDescriptor(record) {
14936
15389
  providerSessionId: typeof record.meta?.providerSessionId === "string" ? String(record.meta.providerSessionId) : void 0
14937
15390
  };
14938
15391
  }
15392
+ function getWriteConflictOwnerClientId(error) {
15393
+ const message = typeof error === "string" ? error : error instanceof Error ? error.message : "";
15394
+ const match = /^Write owned by\s+(.+)$/.exec(message.trim());
15395
+ return match?.[1]?.trim() || void 0;
15396
+ }
15397
+ function summarizeSessionHostRecord(result) {
15398
+ if (!result || typeof result !== "object") return {};
15399
+ const record = result;
15400
+ return {
15401
+ runtimeKey: typeof record.runtimeKey === "string" ? record.runtimeKey : void 0,
15402
+ lifecycle: typeof record.lifecycle === "string" ? record.lifecycle : void 0,
15403
+ surfaceKind: getSessionHostSurfaceKind(record),
15404
+ attachedClientCount: Array.isArray(record.attachedClients) ? record.attachedClients.length : void 0,
15405
+ hasWriteOwner: !!record.writeOwner,
15406
+ writeOwnerClientId: typeof record.writeOwner?.clientId === "string" ? record.writeOwner.clientId : void 0
15407
+ };
15408
+ }
15409
+ function summarizeSessionHostRecords(result) {
15410
+ const records = Array.isArray(result) ? result : [];
15411
+ const groups = partitionSessionHostRecords(records);
15412
+ return {
15413
+ sessionCount: records.length,
15414
+ liveRuntimeCount: groups.liveRuntimes.length,
15415
+ recoverySnapshotCount: groups.recoverySnapshots.length,
15416
+ inactiveRecordCount: groups.inactiveRecords.length
15417
+ };
15418
+ }
15419
+ function summarizeSessionHostDiagnostics(result) {
15420
+ const diagnostics = result && typeof result === "object" ? result : {};
15421
+ const sessions = Array.isArray(diagnostics.sessions) ? diagnostics.sessions : [];
15422
+ return {
15423
+ runtimeCount: typeof diagnostics.runtimeCount === "number" ? diagnostics.runtimeCount : void 0,
15424
+ ...summarizeSessionHostRecords(sessions)
15425
+ };
15426
+ }
15427
+ function summarizeSessionHostPruneResult(result) {
15428
+ const value = result && typeof result === "object" ? result : {};
15429
+ return {
15430
+ duplicateGroupCount: typeof value.duplicateGroupCount === "number" ? value.duplicateGroupCount : void 0,
15431
+ prunedCount: Array.isArray(value.prunedSessionIds) ? value.prunedSessionIds.length : void 0,
15432
+ keptCount: Array.isArray(value.keptSessionIds) ? value.keptSessionIds.length : void 0
15433
+ };
15434
+ }
14939
15435
  var DaemonCommandRouter = class {
14940
15436
  deps;
14941
15437
  constructor(deps) {
14942
15438
  this.deps = deps;
14943
15439
  }
15440
+ async traceSessionHostAction(action, args, run, summarizeResult) {
15441
+ const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
15442
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
15443
+ const requestedPayload = { action };
15444
+ if (sessionId) requestedPayload.sessionId = sessionId;
15445
+ if (typeof args?.clientId === "string") requestedPayload.clientId = args.clientId;
15446
+ if (typeof args?.signal === "string") requestedPayload.signal = args.signal;
15447
+ if (typeof args?.providerType === "string") requestedPayload.providerType = args.providerType;
15448
+ if (typeof args?.workspace === "string") requestedPayload.workspace = args.workspace;
15449
+ if (typeof args?.dryRun === "boolean") requestedPayload.dryRun = args.dryRun;
15450
+ recordDebugTrace({
15451
+ interactionId,
15452
+ category: "session_host",
15453
+ stage: "action_requested",
15454
+ level: "info",
15455
+ sessionId,
15456
+ payload: requestedPayload
15457
+ });
15458
+ try {
15459
+ const result = await run();
15460
+ recordDebugTrace({
15461
+ interactionId,
15462
+ category: "session_host",
15463
+ stage: "action_result",
15464
+ level: "info",
15465
+ sessionId,
15466
+ payload: {
15467
+ ...requestedPayload,
15468
+ success: true,
15469
+ ...summarizeResult ? summarizeResult(result) : {}
15470
+ }
15471
+ });
15472
+ return result;
15473
+ } catch (error) {
15474
+ recordDebugTrace({
15475
+ interactionId,
15476
+ category: "session_host",
15477
+ stage: "action_failed",
15478
+ level: "error",
15479
+ sessionId,
15480
+ payload: {
15481
+ ...requestedPayload,
15482
+ error: error?.message || String(error),
15483
+ failureKind: getWriteConflictOwnerClientId(error) ? "write_conflict" : "request_failed",
15484
+ conflictOwnerClientId: getWriteConflictOwnerClientId(error)
15485
+ }
15486
+ });
15487
+ throw error;
15488
+ }
15489
+ }
14944
15490
  /**
14945
15491
  * Unified command routing.
14946
15492
  * Returns result for all commands:
@@ -15050,44 +15596,60 @@ var DaemonCommandRouter = class {
15050
15596
  }
15051
15597
  case "session_host_get_diagnostics": {
15052
15598
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15053
- const diagnostics = await this.deps.sessionHostControl.getDiagnostics({
15599
+ const diagnostics = await this.traceSessionHostAction("session_host_get_diagnostics", args, () => this.deps.sessionHostControl.getDiagnostics({
15054
15600
  includeSessions: args?.includeSessions !== false,
15055
15601
  limit: Number(args?.limit) || void 0
15056
- });
15602
+ }), (result) => ({
15603
+ includeSessions: args?.includeSessions !== false,
15604
+ limit: Number(args?.limit) || void 0,
15605
+ ...summarizeSessionHostDiagnostics(result)
15606
+ }));
15057
15607
  return { success: true, diagnostics };
15058
15608
  }
15059
15609
  case "session_host_list_sessions": {
15060
15610
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15061
- const sessions = await this.deps.sessionHostControl.listSessions();
15611
+ const sessions = await this.traceSessionHostAction("session_host_list_sessions", args, () => this.deps.sessionHostControl.listSessions(), (records) => summarizeSessionHostRecords(records));
15062
15612
  return { success: true, sessions };
15063
15613
  }
15064
15614
  case "session_host_stop_session": {
15065
15615
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15066
15616
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15067
15617
  if (!sessionId) return { success: false, error: "sessionId required" };
15068
- const record = await this.deps.sessionHostControl.stopSession(sessionId);
15618
+ const record = await this.traceSessionHostAction("session_host_stop_session", args, () => this.deps.sessionHostControl.stopSession(sessionId), (result) => summarizeSessionHostRecord(result));
15069
15619
  return { success: true, record };
15070
15620
  }
15071
15621
  case "session_host_resume_session": {
15072
15622
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15073
15623
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15074
15624
  if (!sessionId) return { success: false, error: "sessionId required" };
15075
- const record = await this.deps.sessionHostControl.resumeSession(sessionId);
15076
- const hosted = toHostedCliRuntimeDescriptor(record);
15077
- if (hosted) {
15078
- await this.deps.cliManager.restoreHostedSessions([hosted]);
15079
- }
15625
+ const record = await this.traceSessionHostAction("session_host_resume_session", args, async () => {
15626
+ const nextRecord = await this.deps.sessionHostControl.resumeSession(sessionId);
15627
+ const hosted = toHostedCliRuntimeDescriptor(nextRecord);
15628
+ if (hosted) {
15629
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
15630
+ }
15631
+ return nextRecord;
15632
+ }, (result) => ({
15633
+ ...summarizeSessionHostRecord(result),
15634
+ restoredHostedSession: !!toHostedCliRuntimeDescriptor(result)
15635
+ }));
15080
15636
  return { success: true, record };
15081
15637
  }
15082
15638
  case "session_host_restart_session": {
15083
15639
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15084
15640
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15085
15641
  if (!sessionId) return { success: false, error: "sessionId required" };
15086
- const record = await this.deps.sessionHostControl.restartSession(sessionId);
15087
- const hosted = toHostedCliRuntimeDescriptor(record);
15088
- if (hosted) {
15089
- await this.deps.cliManager.restoreHostedSessions([hosted]);
15090
- }
15642
+ const record = await this.traceSessionHostAction("session_host_restart_session", args, async () => {
15643
+ const nextRecord = await this.deps.sessionHostControl.restartSession(sessionId);
15644
+ const hosted = toHostedCliRuntimeDescriptor(nextRecord);
15645
+ if (hosted) {
15646
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
15647
+ }
15648
+ return nextRecord;
15649
+ }, (result) => ({
15650
+ ...summarizeSessionHostRecord(result),
15651
+ restoredHostedSession: !!toHostedCliRuntimeDescriptor(result)
15652
+ }));
15091
15653
  return { success: true, record };
15092
15654
  }
15093
15655
  case "session_host_send_signal": {
@@ -15096,7 +15658,7 @@ var DaemonCommandRouter = class {
15096
15658
  const signal = typeof args?.signal === "string" ? args.signal : "";
15097
15659
  if (!sessionId) return { success: false, error: "sessionId required" };
15098
15660
  if (!signal) return { success: false, error: "signal required" };
15099
- const record = await this.deps.sessionHostControl.sendSignal(sessionId, signal);
15661
+ const record = await this.traceSessionHostAction("session_host_send_signal", args, () => this.deps.sessionHostControl.sendSignal(sessionId, signal), (result) => summarizeSessionHostRecord(result));
15100
15662
  return { success: true, record };
15101
15663
  }
15102
15664
  case "session_host_force_detach_client": {
@@ -15105,16 +15667,16 @@ var DaemonCommandRouter = class {
15105
15667
  const clientId = typeof args?.clientId === "string" ? args.clientId : "";
15106
15668
  if (!sessionId) return { success: false, error: "sessionId required" };
15107
15669
  if (!clientId) return { success: false, error: "clientId required" };
15108
- const record = await this.deps.sessionHostControl.forceDetachClient(sessionId, clientId);
15670
+ const record = await this.traceSessionHostAction("session_host_force_detach_client", args, () => this.deps.sessionHostControl.forceDetachClient(sessionId, clientId), (result) => summarizeSessionHostRecord(result));
15109
15671
  return { success: true, record };
15110
15672
  }
15111
15673
  case "session_host_prune_duplicate_sessions": {
15112
15674
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15113
- const result = await this.deps.sessionHostControl.pruneDuplicateSessions({
15675
+ const result = await this.traceSessionHostAction("session_host_prune_duplicate_sessions", args, () => this.deps.sessionHostControl.pruneDuplicateSessions({
15114
15676
  providerType: typeof args?.providerType === "string" ? args.providerType : void 0,
15115
15677
  workspace: typeof args?.workspace === "string" ? args.workspace : void 0,
15116
15678
  dryRun: args?.dryRun === true
15117
- });
15679
+ }), (value) => summarizeSessionHostPruneResult(value));
15118
15680
  return { success: true, result };
15119
15681
  }
15120
15682
  case "session_host_acquire_write": {
@@ -15124,12 +15686,15 @@ var DaemonCommandRouter = class {
15124
15686
  const ownerType = args?.ownerType === "agent" ? "agent" : "user";
15125
15687
  if (!sessionId) return { success: false, error: "sessionId required" };
15126
15688
  if (!clientId) return { success: false, error: "clientId required" };
15127
- const record = await this.deps.sessionHostControl.acquireWrite({
15689
+ const record = await this.traceSessionHostAction("session_host_acquire_write", args, () => this.deps.sessionHostControl.acquireWrite({
15128
15690
  sessionId,
15129
15691
  clientId,
15130
15692
  ownerType,
15131
15693
  force: args?.force !== false
15132
- });
15694
+ }), (result) => ({
15695
+ ...summarizeSessionHostRecord(result),
15696
+ ownerType
15697
+ }));
15133
15698
  return { success: true, record };
15134
15699
  }
15135
15700
  case "session_host_release_write": {
@@ -15138,7 +15703,10 @@ var DaemonCommandRouter = class {
15138
15703
  const clientId = typeof args?.clientId === "string" ? args.clientId : "";
15139
15704
  if (!sessionId) return { success: false, error: "sessionId required" };
15140
15705
  if (!clientId) return { success: false, error: "clientId required" };
15141
- const record = await this.deps.sessionHostControl.releaseWrite({ sessionId, clientId });
15706
+ const record = await this.traceSessionHostAction("session_host_release_write", args, () => this.deps.sessionHostControl.releaseWrite({
15707
+ sessionId,
15708
+ clientId
15709
+ }), (result) => summarizeSessionHostRecord(result));
15142
15710
  return { success: true, record };
15143
15711
  }
15144
15712
  case "list_saved_sessions": {
@@ -15147,8 +15715,9 @@ var DaemonCommandRouter = class {
15147
15715
  if (!providerType) {
15148
15716
  return { success: false, error: "providerType required" };
15149
15717
  }
15150
- const offset = Math.max(0, Number(args?.offset) || 0);
15151
- const limit = Math.max(1, Math.min(100, Number(args?.limit) || 30));
15718
+ const wantsAll = args?.all === true;
15719
+ const offset = wantsAll ? 0 : Math.max(0, Number(args?.offset) || 0);
15720
+ const limit = wantsAll ? Number.MAX_SAFE_INTEGER : Math.max(1, Math.min(100, Number(args?.limit) || 30));
15152
15721
  const { sessions: historySessions, hasMore } = listSavedHistorySessions(providerType, { offset, limit });
15153
15722
  const state = loadState();
15154
15723
  const savedSessions = getSavedProviderSessions(state, { providerType, kind });
@@ -15169,13 +15738,13 @@ var DaemonCommandRouter = class {
15169
15738
  providerName: saved?.providerName || recent?.providerName || providerType,
15170
15739
  kind: saved?.kind || recent?.kind || kind,
15171
15740
  title: saved?.title || recent?.title || session.sessionTitle || session.preview || providerType,
15172
- workspace: saved?.workspace || recent?.workspace,
15173
- currentModel: saved?.currentModel || recent?.currentModel,
15741
+ workspace: saved?.workspace || recent?.workspace || session.workspace,
15742
+ summaryMetadata: saved?.summaryMetadata || recent?.summaryMetadata,
15174
15743
  preview: session.preview,
15175
15744
  messageCount: session.messageCount,
15176
15745
  firstMessageAt: session.firstMessageAt,
15177
15746
  lastMessageAt: session.lastMessageAt,
15178
- canResume: !!(saved?.workspace || recent?.workspace) && canResumeById
15747
+ canResume: !!(saved?.workspace || recent?.workspace || session.workspace) && canResumeById
15179
15748
  };
15180
15749
  }),
15181
15750
  hasMore
@@ -15609,7 +16178,7 @@ var DaemonStatusReporter = class {
15609
16178
  const ideSummary = ideStates.map((s) => {
15610
16179
  const msgs = s.activeChat?.messages?.length || 0;
15611
16180
  const exts = s.extensions.length;
15612
- return `${s.type}(${s.status},${msgs}msg,${exts}ext${s.currentModel ? ",model=" + s.currentModel : ""})`;
16181
+ return `${s.type}(${s.status},${msgs}msg,${exts}ext)`;
15613
16182
  }).join(", ");
15614
16183
  const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
15615
16184
  const acpSummary = acpStates.map((s) => `${s.type}(${s.status})`).join(", ");
@@ -15671,9 +16240,7 @@ var DaemonStatusReporter = class {
15671
16240
  workspace: session.workspace ?? null,
15672
16241
  title: session.title,
15673
16242
  cdpConnected: session.cdpConnected,
15674
- currentModel: session.currentModel,
15675
- currentPlan: session.currentPlan,
15676
- currentAutoApprove: session.currentAutoApprove
16243
+ summaryMetadata: session.summaryMetadata
15677
16244
  })),
15678
16245
  p2p: payload.p2p,
15679
16246
  timestamp: now
@@ -15792,7 +16359,7 @@ var ProviderStreamAdapter = class {
15792
16359
  const beforeCount = this.messageCount(before);
15793
16360
  const beforeSignature = this.lastMessageSignature(before);
15794
16361
  for (let attempt = 0; attempt < 12; attempt += 1) {
15795
- await new Promise((resolve12) => setTimeout(resolve12, 250));
16362
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
15796
16363
  let state;
15797
16364
  try {
15798
16365
  state = await this.readChat(evaluate);
@@ -15814,7 +16381,7 @@ var ProviderStreamAdapter = class {
15814
16381
  if (this.messageCount(first) > 0 || this.lastMessageSignature(first)) {
15815
16382
  return first;
15816
16383
  }
15817
- await new Promise((resolve12) => setTimeout(resolve12, 150));
16384
+ await new Promise((resolve11) => setTimeout(resolve11, 150));
15818
16385
  const second = await this.readChat(evaluate);
15819
16386
  return this.messageCount(second) >= this.messageCount(first) ? second : first;
15820
16387
  }
@@ -15839,15 +16406,18 @@ var ProviderStreamAdapter = class {
15839
16406
  status: data.status || "idle",
15840
16407
  messages: data.messages || [],
15841
16408
  inputContent: data.inputContent || "",
15842
- model: data.model,
15843
- mode: data.mode,
15844
16409
  activeModal: data.activeModal
15845
16410
  };
15846
16411
  if (typeof data.title === "string" && data.title.trim()) {
15847
16412
  state.title = data.title.trim();
15848
16413
  }
15849
16414
  const controlValues = extractProviderControlValues(this.provider.controls, data);
15850
- if (controlValues) state.controlValues = controlValues;
16415
+ const surface = resolveProviderStateSurface({
16416
+ controlValues,
16417
+ summaryMetadata: data.summaryMetadata
16418
+ });
16419
+ if (surface.controlValues) state.controlValues = surface.controlValues;
16420
+ if (surface.summaryMetadata) state.summaryMetadata = surface.summaryMetadata;
15851
16421
  const effects = normalizeProviderEffects(data);
15852
16422
  if (effects.length > 0) state.effects = effects;
15853
16423
  if (state.messages.length > 0) {
@@ -15954,7 +16524,7 @@ var ProviderStreamAdapter = class {
15954
16524
  if (typeof data.error === "string" && data.error.trim()) return false;
15955
16525
  }
15956
16526
  for (let attempt = 0; attempt < 6; attempt += 1) {
15957
- await new Promise((resolve12) => setTimeout(resolve12, 250));
16527
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
15958
16528
  const state = await this.readChat(evaluate);
15959
16529
  const title = this.getStateTitle(state);
15960
16530
  if (this.titlesMatch(title, sessionId)) return true;
@@ -16121,7 +16691,8 @@ var DaemonAgentStreamManager = class {
16121
16691
  const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
16122
16692
  const state = await agent.adapter.readChat(evaluate);
16123
16693
  const stateError = this.getStateError(state);
16124
- 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) : ""}`);
16694
+ const selectedModelValue = typeof state.controlValues?.model === "string" ? state.controlValues.model : "";
16695
+ LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${selectedModelValue}${state.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
16125
16696
  if (state.status === "error" && this.isRecoverableSessionError(stateError)) {
16126
16697
  throw new Error(stateError);
16127
16698
  }
@@ -16469,9 +17040,8 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
16469
17040
  messages: stream.messages || [],
16470
17041
  status: stream.status || "idle",
16471
17042
  activeModal: stream.activeModal || null,
16472
- model: stream.model || void 0,
16473
- mode: stream.mode || void 0,
16474
17043
  controlValues: stream.controlValues || void 0,
17044
+ summaryMetadata: stream.summaryMetadata || void 0,
16475
17045
  effects: stream.effects || void 0,
16476
17046
  sessionId: stream.sessionId || stream.instanceId || void 0,
16477
17047
  title: stream.title || stream.agentName || void 0,
@@ -16876,6 +17446,7 @@ async function detectAllVersions(loader, archive) {
16876
17446
  import * as http2 from "http";
16877
17447
  import * as fs14 from "fs";
16878
17448
  import * as path22 from "path";
17449
+ init_config();
16879
17450
 
16880
17451
  // src/daemon/scaffold-template.ts
16881
17452
  function generateFiles(type, name, category, opts = {}) {
@@ -17006,7 +17577,11 @@ module.exports.setMode = (params) => {
17006
17577
  * 5. Approval dialog detection (buttons, modal)
17007
17578
  * 6. Input field selector
17008
17579
  *
17009
- * \u2192 { id, status, title, messages[], inputContent, activeModal }
17580
+ * Preferred live-state surface:
17581
+ * - controlValues: explicit current control selections (model/mode/etc.)
17582
+ * - summaryMetadata: compact always-visible metadata for dashboard/recent views
17583
+ * Legacy top-level model/mode output is no longer the preferred shape.
17584
+ * \u2192 { id, status, title, messages[], inputContent, activeModal, controlValues?, summaryMetadata? }
17010
17585
  */
17011
17586
  (() => {
17012
17587
  try {
@@ -17034,6 +17609,9 @@ module.exports.setMode = (params) => {
17034
17609
  messages,
17035
17610
  inputContent,
17036
17611
  activeModal,
17612
+ // TODO: Return explicit selections when available, e.g.
17613
+ // controlValues: { model: selectedModel, mode: selectedMode },
17614
+ // summaryMetadata: { items: [{ id: 'model', value: selectedModelLabel || selectedModel, shortValue: selectedModel, order: 10 }] },
17037
17615
  });
17038
17616
  } catch(e) {
17039
17617
  return JSON.stringify({ id: '', status: 'error', messages: [], error: e.message });
@@ -18412,7 +18990,7 @@ function getCliTargetBundle(ctx, type, instanceId) {
18412
18990
  return { target, instance, adapter };
18413
18991
  }
18414
18992
  function sleep(ms) {
18415
- return new Promise((resolve12) => setTimeout(resolve12, ms));
18993
+ return new Promise((resolve11) => setTimeout(resolve11, ms));
18416
18994
  }
18417
18995
  async function waitForCliReady(ctx, type, instanceId, timeoutMs) {
18418
18996
  const startedAt = Date.now();
@@ -18774,7 +19352,6 @@ async function handleCliStatus(ctx, _req, res) {
18774
19352
  lastMessage: s.activeChat?.messages?.slice(-1)[0] || null,
18775
19353
  activeModal: s.activeChat?.activeModal || null,
18776
19354
  pendingEvents: s.pendingEvents || [],
18777
- currentModel: s.currentModel,
18778
19355
  settings: s.settings
18779
19356
  }));
18780
19357
  ctx.json(res, 200, { instances: result, count: result.length });
@@ -19259,18 +19836,6 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
19259
19836
  if (!fs13.existsSync(providerJson)) {
19260
19837
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
19261
19838
  }
19262
- try {
19263
- const providerData = JSON.parse(fs13.readFileSync(providerJson, "utf-8"));
19264
- if (providerData.disableUpstream !== true) {
19265
- providerData.disableUpstream = true;
19266
- fs13.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
19267
- }
19268
- } catch (error) {
19269
- return {
19270
- dir: null,
19271
- reason: `Failed to update provider.json in writable provider directory: ${error.message}`
19272
- };
19273
- }
19274
19839
  return { dir: desiredDir };
19275
19840
  }
19276
19841
  function loadAutoImplReferenceScripts(ctx, referenceType) {
@@ -19943,7 +20508,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
19943
20508
  lines.push("## Required Return Format");
19944
20509
  lines.push("| Function | Return JSON |");
19945
20510
  lines.push("|---|---|");
19946
- 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 |");
20511
+ 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 |");
19947
20512
  lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
19948
20513
  lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
19949
20514
  lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
@@ -20557,6 +21122,7 @@ var DevServer = class _DevServer {
20557
21122
  cdpManagers;
20558
21123
  instanceManager;
20559
21124
  cliManager;
21125
+ onProviderSourceConfigChanged;
20560
21126
  logFn;
20561
21127
  sseClients = [];
20562
21128
  watchScriptPath = null;
@@ -20573,6 +21139,7 @@ var DevServer = class _DevServer {
20573
21139
  this.cdpManagers = options.cdpManagers;
20574
21140
  this.instanceManager = options.instanceManager || null;
20575
21141
  this.cliManager = options.cliManager || null;
21142
+ this.onProviderSourceConfigChanged = options.onProviderSourceConfigChanged || null;
20576
21143
  this.logFn = options.logFn || LOG.forComponent("DevServer").asLogFn();
20577
21144
  }
20578
21145
  log(msg) {
@@ -20582,6 +21149,8 @@ var DevServer = class _DevServer {
20582
21149
  routes = [
20583
21150
  // Static routes
20584
21151
  { method: "GET", pattern: "/api/providers", handler: (q, s) => this.handleListProviders(q, s) },
21152
+ { method: "GET", pattern: "/api/providers/source-config", handler: (q, s) => this.handleGetProviderSourceConfig(q, s) },
21153
+ { method: "POST", pattern: "/api/providers/source-config", handler: (q, s) => this.handleSetProviderSourceConfig(q, s) },
20585
21154
  { method: "GET", pattern: "/api/providers/versions", handler: (q, s) => this.handleDetectVersions(q, s) },
20586
21155
  { method: "POST", pattern: "/api/providers/reload", handler: (q, s) => this.handleReload(q, s) },
20587
21156
  { method: "POST", pattern: "/api/cdp/evaluate", handler: (q, s) => this.handleCdpEvaluate(q, s) },
@@ -20679,15 +21248,15 @@ var DevServer = class _DevServer {
20679
21248
  this.json(res, 500, { error: e.message });
20680
21249
  }
20681
21250
  });
20682
- return new Promise((resolve12, reject) => {
21251
+ return new Promise((resolve11, reject) => {
20683
21252
  this.server.listen(port, "127.0.0.1", () => {
20684
21253
  this.log(`Dev server listening on http://127.0.0.1:${port}`);
20685
- resolve12();
21254
+ resolve11();
20686
21255
  });
20687
21256
  this.server.on("error", (e) => {
20688
21257
  if (e.code === "EADDRINUSE") {
20689
21258
  this.log(`Port ${port} in use, skipping dev server`);
20690
- resolve12();
21259
+ resolve11();
20691
21260
  } else {
20692
21261
  reject(e);
20693
21262
  }
@@ -20701,7 +21270,33 @@ var DevServer = class _DevServer {
20701
21270
  // ─── Handlers ───
20702
21271
  async handleListProviders(_req, res) {
20703
21272
  const providers = this.providerLoader.getAll().map(toProviderListEntry);
20704
- this.json(res, 200, { providers, count: providers.length });
21273
+ this.json(res, 200, { providers, count: providers.length, sourceConfig: this.providerLoader.getSourceConfig() });
21274
+ }
21275
+ async handleGetProviderSourceConfig(_req, res) {
21276
+ this.json(res, 200, { success: true, sourceConfig: this.providerLoader.getSourceConfig() });
21277
+ }
21278
+ async handleSetProviderSourceConfig(req, res) {
21279
+ const body = await this.readBody(req);
21280
+ const parsed = parseProviderSourceConfigUpdate(body || {});
21281
+ if (!parsed.ok) {
21282
+ this.json(res, 400, { success: false, error: parsed.error });
21283
+ return;
21284
+ }
21285
+ const currentConfig2 = loadConfig();
21286
+ const nextConfig = {
21287
+ ...currentConfig2,
21288
+ ...parsed.updates.providerSourceMode ? { providerSourceMode: parsed.updates.providerSourceMode } : {},
21289
+ ...Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? { providerDir: parsed.updates.providerDir } : {}
21290
+ };
21291
+ saveConfig(nextConfig);
21292
+ const sourceConfig = this.providerLoader.applySourceConfig({
21293
+ sourceMode: nextConfig.providerSourceMode,
21294
+ userDir: Object.prototype.hasOwnProperty.call(parsed.updates, "providerDir") ? parsed.updates.providerDir : this.providerLoader.getSourceConfig().explicitProviderDir || void 0
21295
+ });
21296
+ this.providerLoader.reload();
21297
+ this.providerLoader.registerToDetector();
21298
+ await this.onProviderSourceConfigChanged?.();
21299
+ this.json(res, 200, { success: true, reloaded: true, sourceConfig });
20705
21300
  }
20706
21301
  async handleProviderConfig(type, _req, res) {
20707
21302
  const provider = this.providerLoader.resolve(type);
@@ -20743,20 +21338,20 @@ var DevServer = class _DevServer {
20743
21338
  child.stderr?.on("data", (d) => {
20744
21339
  stderr += d.toString().slice(0, 2e3);
20745
21340
  });
20746
- await new Promise((resolve12) => {
21341
+ await new Promise((resolve11) => {
20747
21342
  const timer = setTimeout(() => {
20748
21343
  child.kill();
20749
- resolve12();
21344
+ resolve11();
20750
21345
  }, 3e3);
20751
21346
  child.on("exit", () => {
20752
21347
  clearTimeout(timer);
20753
- resolve12();
21348
+ resolve11();
20754
21349
  });
20755
21350
  child.stdout?.once("data", () => {
20756
21351
  setTimeout(() => {
20757
21352
  child.kill();
20758
21353
  clearTimeout(timer);
20759
- resolve12();
21354
+ resolve11();
20760
21355
  }, 500);
20761
21356
  });
20762
21357
  });
@@ -21252,14 +21847,14 @@ var DevServer = class _DevServer {
21252
21847
  child.stderr?.on("data", (d) => {
21253
21848
  stderr += d.toString();
21254
21849
  });
21255
- await new Promise((resolve12) => {
21850
+ await new Promise((resolve11) => {
21256
21851
  const timer = setTimeout(() => {
21257
21852
  child.kill();
21258
- resolve12();
21853
+ resolve11();
21259
21854
  }, timeout);
21260
21855
  child.on("exit", () => {
21261
21856
  clearTimeout(timer);
21262
- resolve12();
21857
+ resolve11();
21263
21858
  });
21264
21859
  });
21265
21860
  const elapsed = Date.now() - start;
@@ -21404,18 +21999,6 @@ var DevServer = class _DevServer {
21404
21999
  if (!fs14.existsSync(providerJson)) {
21405
22000
  return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
21406
22001
  }
21407
- try {
21408
- const providerData = JSON.parse(fs14.readFileSync(providerJson, "utf-8"));
21409
- if (providerData.disableUpstream !== true) {
21410
- providerData.disableUpstream = true;
21411
- fs14.writeFileSync(providerJson, JSON.stringify(providerData, null, 2));
21412
- }
21413
- } catch (error) {
21414
- return {
21415
- dir: null,
21416
- reason: `Failed to update provider.json in writable provider directory: ${error.message}`
21417
- };
21418
- }
21419
22002
  return { dir: desiredDir };
21420
22003
  }
21421
22004
  async handleAutoImplement(type, req, res) {
@@ -21560,7 +22143,7 @@ var DevServer = class _DevServer {
21560
22143
  lines.push("## Required Return Format");
21561
22144
  lines.push("| Function | Return JSON |");
21562
22145
  lines.push("|---|---|");
21563
- 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 |");
22146
+ 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 |");
21564
22147
  lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
21565
22148
  lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
21566
22149
  lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
@@ -21941,14 +22524,14 @@ data: ${JSON.stringify(msg.data)}
21941
22524
  res.end(JSON.stringify(data, null, 2));
21942
22525
  }
21943
22526
  async readBody(req) {
21944
- return new Promise((resolve12) => {
22527
+ return new Promise((resolve11) => {
21945
22528
  let body = "";
21946
22529
  req.on("data", (chunk) => body += chunk);
21947
22530
  req.on("end", () => {
21948
22531
  try {
21949
- resolve12(JSON.parse(body));
22532
+ resolve11(JSON.parse(body));
21950
22533
  } catch {
21951
- resolve12({});
22534
+ resolve11({});
21952
22535
  }
21953
22536
  });
21954
22537
  });
@@ -22431,7 +23014,7 @@ async function waitForReady(endpoint, timeoutMs = STARTUP_TIMEOUT_MS) {
22431
23014
  const deadline = Date.now() + timeoutMs;
22432
23015
  while (Date.now() < deadline) {
22433
23016
  if (await canConnect(endpoint)) return;
22434
- await new Promise((resolve12) => setTimeout(resolve12, STARTUP_POLL_MS));
23017
+ await new Promise((resolve11) => setTimeout(resolve11, STARTUP_POLL_MS));
22435
23018
  }
22436
23019
  throw new Error(`Session host did not become ready within ${timeoutMs}ms`);
22437
23020
  }
@@ -22471,61 +23054,6 @@ async function listHostedCliRuntimes(endpoint) {
22471
23054
  }
22472
23055
  }
22473
23056
 
22474
- // src/session-host/runtime-surface.ts
22475
- var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
22476
- function isSessionHostLiveRuntime(record) {
22477
- const lifecycle = String(record?.lifecycle || "").trim();
22478
- return LIVE_LIFECYCLES.has(lifecycle);
22479
- }
22480
- function getSessionHostRecoveryLabel(meta) {
22481
- const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
22482
- if (!recoveryState) return null;
22483
- if (recoveryState === "auto_resumed") return "restored after restart";
22484
- if (recoveryState === "resume_failed") return "restore failed";
22485
- if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
22486
- if (recoveryState === "orphan_snapshot") return "snapshot recovered";
22487
- return recoveryState.replace(/_/g, " ");
22488
- }
22489
- function isSessionHostRecoverySnapshot(record) {
22490
- if (!record) return false;
22491
- if (isSessionHostLiveRuntime(record)) return false;
22492
- const lifecycle = String(record.lifecycle || "").trim();
22493
- if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
22494
- return false;
22495
- }
22496
- const meta = record.meta || void 0;
22497
- if (meta?.restoredFromStorage === true) return true;
22498
- return getSessionHostRecoveryLabel(meta) !== null;
22499
- }
22500
- function getSessionHostSurfaceKind(record) {
22501
- if (isSessionHostLiveRuntime(record)) return "live_runtime";
22502
- if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
22503
- return "inactive_record";
22504
- }
22505
- function partitionSessionHostRecords(records) {
22506
- const liveRuntimes = [];
22507
- const recoverySnapshots = [];
22508
- const inactiveRecords = [];
22509
- for (const record of records) {
22510
- const kind = getSessionHostSurfaceKind(record);
22511
- if (kind === "live_runtime") {
22512
- liveRuntimes.push(record);
22513
- } else if (kind === "recovery_snapshot") {
22514
- recoverySnapshots.push(record);
22515
- } else {
22516
- inactiveRecords.push(record);
22517
- }
22518
- }
22519
- return {
22520
- liveRuntimes,
22521
- recoverySnapshots,
22522
- inactiveRecords
22523
- };
22524
- }
22525
- function partitionSessionHostDiagnosticsSessions(records) {
22526
- return partitionSessionHostRecords(records || []);
22527
- }
22528
-
22529
23057
  // src/session-host/startup-restore-policy.js
22530
23058
  function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
22531
23059
  const raw = typeof env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";
@@ -22662,10 +23190,10 @@ async function installExtension(ide, extension) {
22662
23190
  const buffer = Buffer.from(await res.arrayBuffer());
22663
23191
  const fs15 = await import("fs");
22664
23192
  fs15.writeFileSync(vsixPath, buffer);
22665
- return new Promise((resolve12) => {
23193
+ return new Promise((resolve11) => {
22666
23194
  const cmd = `"${ide.cliCommand}" --install-extension "${vsixPath}" --force`;
22667
23195
  exec2(cmd, { timeout: 6e4 }, (error, _stdout, stderr) => {
22668
- resolve12({
23196
+ resolve11({
22669
23197
  extensionId: extension.id,
22670
23198
  marketplaceId: extension.marketplaceId,
22671
23199
  success: !error,
@@ -22678,11 +23206,11 @@ async function installExtension(ide, extension) {
22678
23206
  } catch (e) {
22679
23207
  }
22680
23208
  }
22681
- return new Promise((resolve12) => {
23209
+ return new Promise((resolve11) => {
22682
23210
  const cmd = `"${ide.cliCommand}" --install-extension ${extension.marketplaceId} --force`;
22683
23211
  exec2(cmd, { timeout: 6e4 }, (error, stdout, stderr) => {
22684
23212
  if (error) {
22685
- resolve12({
23213
+ resolve11({
22686
23214
  extensionId: extension.id,
22687
23215
  marketplaceId: extension.marketplaceId,
22688
23216
  success: false,
@@ -22690,7 +23218,7 @@ async function installExtension(ide, extension) {
22690
23218
  error: stderr || error.message
22691
23219
  });
22692
23220
  } else {
22693
- resolve12({
23221
+ resolve11({
22694
23222
  extensionId: extension.id,
22695
23223
  marketplaceId: extension.marketplaceId,
22696
23224
  success: true,
@@ -22787,10 +23315,11 @@ init_config();
22787
23315
  async function initDaemonComponents(config) {
22788
23316
  installGlobalInterceptor();
22789
23317
  const appConfig = loadConfig();
22790
- const disableUpstream = appConfig.disableUpstream ?? false;
23318
+ const providerSourceMode = appConfig.providerSourceMode || "normal";
23319
+ const disableUpstream = providerSourceMode === "no-upstream";
22791
23320
  const providerLoader = new ProviderLoader({
22792
23321
  logFn: config.providerLogFn,
22793
- disableUpstream,
23322
+ sourceMode: providerSourceMode,
22794
23323
  userDir: appConfig.providerDir
22795
23324
  });
22796
23325
  if (!disableUpstream && !providerLoader.hasUpstream()) {
@@ -22895,6 +23424,10 @@ async function initDaemonComponents(config) {
22895
23424
  onProviderSettingChanged: async (providerType) => {
22896
23425
  await refreshProviderAvailability(providerType);
22897
23426
  config.onStatusChange?.();
23427
+ },
23428
+ onProviderSourceConfigChanged: async () => {
23429
+ await refreshProviderAvailability();
23430
+ config.onStatusChange?.();
22898
23431
  }
22899
23432
  });
22900
23433
  agentStreamManager = new DaemonAgentStreamManager(
@@ -22944,7 +23477,8 @@ async function initDaemonComponents(config) {
22944
23477
  cdpInitializer,
22945
23478
  cdpManagers,
22946
23479
  sessionRegistry,
22947
- detectedIdes: detectedIdesRef
23480
+ detectedIdes: detectedIdesRef,
23481
+ refreshProviderAvailability
22948
23482
  };
22949
23483
  }
22950
23484
  async function startDaemonDevSupport(options) {
@@ -22953,7 +23487,10 @@ async function startDaemonDevSupport(options) {
22953
23487
  cdpManagers: options.components.cdpManagers,
22954
23488
  instanceManager: options.components.instanceManager,
22955
23489
  cliManager: options.components.cliManager,
22956
- logFn: options.logFn
23490
+ logFn: options.logFn,
23491
+ onProviderSourceConfigChanged: async () => {
23492
+ await options.components.refreshProviderAvailability();
23493
+ }
22957
23494
  });
22958
23495
  await devServer.start();
22959
23496
  options.components.providerLoader.watch();
@@ -23079,6 +23616,7 @@ export {
23079
23616
  normalizeInputEnvelope,
23080
23617
  normalizeManagedStatus,
23081
23618
  normalizeMessageParts,
23619
+ parseProviderSourceConfigUpdate,
23082
23620
  partitionSessionHostDiagnosticsSessions,
23083
23621
  partitionSessionHostRecords,
23084
23622
  probeCdpPort,