@adhdev/daemon-core 0.8.58 → 0.8.60

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 (59) hide show
  1. package/dist/agent-stream/types.d.ts +3 -4
  2. package/dist/cli-adapters/provider-cli-adapter.d.ts +3 -0
  3. package/dist/commands/router.d.ts +1 -0
  4. package/dist/commands/stream-commands.d.ts +1 -0
  5. package/dist/config/recent-activity.d.ts +2 -1
  6. package/dist/config/saved-sessions.d.ts +2 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.js +579 -190
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +579 -190
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/providers/acp-provider-instance.d.ts +8 -2
  13. package/dist/providers/cli-provider-instance.d.ts +1 -0
  14. package/dist/providers/contracts.d.ts +3 -2
  15. package/dist/providers/extension-provider-instance.d.ts +1 -2
  16. package/dist/providers/provider-instance.d.ts +3 -4
  17. package/dist/providers/provider-patch-state.d.ts +23 -0
  18. package/dist/providers/summary-metadata.d.ts +22 -0
  19. package/dist/shared-types.d.ts +15 -9
  20. package/dist/status/snapshot.d.ts +16 -1
  21. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  22. package/package.json +1 -1
  23. package/src/agent-stream/forward.ts +1 -2
  24. package/src/agent-stream/manager.ts +2 -1
  25. package/src/agent-stream/provider-adapter.ts +7 -3
  26. package/src/agent-stream/types.d.ts +3 -4
  27. package/src/agent-stream/types.ts +3 -4
  28. package/src/cli-adapters/provider-cli-adapter.ts +26 -9
  29. package/src/commands/cli-manager.ts +10 -5
  30. package/src/commands/router.ts +155 -22
  31. package/src/commands/stream-commands.ts +19 -2
  32. package/src/config/recent-activity.d.ts +2 -1
  33. package/src/config/recent-activity.ts +12 -1
  34. package/src/config/saved-sessions.d.ts +2 -1
  35. package/src/config/saved-sessions.ts +12 -2
  36. package/src/daemon/dev-auto-implement.ts +1 -1
  37. package/src/daemon/dev-cli-debug.ts +0 -1
  38. package/src/daemon/dev-server.ts +1 -1
  39. package/src/daemon/scaffold-template.ts +8 -1
  40. package/src/index.d.ts +1 -1
  41. package/src/index.ts +2 -0
  42. package/src/providers/acp-provider-instance.d.ts +8 -2
  43. package/src/providers/acp-provider-instance.ts +80 -23
  44. package/src/providers/cli-provider-instance.ts +17 -22
  45. package/src/providers/contracts.d.ts +3 -2
  46. package/src/providers/contracts.ts +6 -4
  47. package/src/providers/control-effects.ts +3 -4
  48. package/src/providers/extension-provider-instance.d.ts +1 -2
  49. package/src/providers/extension-provider-instance.ts +26 -14
  50. package/src/providers/ide-provider-instance.ts +28 -15
  51. package/src/providers/provider-instance.d.ts +3 -4
  52. package/src/providers/provider-instance.ts +6 -7
  53. package/src/providers/provider-patch-state.ts +91 -0
  54. package/src/providers/summary-metadata.ts +118 -0
  55. package/src/shared-types.d.ts +15 -9
  56. package/src/shared-types.ts +17 -9
  57. package/src/status/builders.ts +18 -13
  58. package/src/status/reporter.ts +2 -4
  59. package/src/status/snapshot.ts +60 -2
package/dist/index.js CHANGED
@@ -1420,6 +1420,7 @@ var init_provider_cli_adapter = __esm({
1420
1420
  static MAX_TRACE_ENTRIES = 250;
1421
1421
  providerResolutionMeta;
1422
1422
  static IDLE_FINISH_CONFIRM_MS = 2e3;
1423
+ static HERMES_IDLE_FINISH_CONFIRM_MS = 5e3;
1423
1424
  static STATUS_ACTIVITY_HOLD_MS = 2e3;
1424
1425
  static FINISH_RETRY_DELAY_MS = 300;
1425
1426
  static MAX_FINISH_RETRIES = 2;
@@ -1427,6 +1428,12 @@ var init_provider_cli_adapter = __esm({
1427
1428
  this.messages = [...this.committedMessages];
1428
1429
  this.structuredMessages = [...this.committedMessages];
1429
1430
  }
1431
+ getIdleFinishConfirmMs() {
1432
+ return this.cliType === "hermes-cli" ? _ProviderCliAdapter.HERMES_IDLE_FINISH_CONFIRM_MS : _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS;
1433
+ }
1434
+ getStatusActivityHoldMs() {
1435
+ return this.cliType === "hermes-cli" ? _ProviderCliAdapter.HERMES_IDLE_FINISH_CONFIRM_MS : _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
1436
+ }
1430
1437
  setStatus(status, trigger) {
1431
1438
  const prev = this.currentStatus;
1432
1439
  if (prev === status) return;
@@ -1449,6 +1456,7 @@ var init_provider_cli_adapter = __esm({
1449
1456
  }
1450
1457
  armIdleFinishCandidate(assistantLength) {
1451
1458
  const now = Date.now();
1459
+ const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
1452
1460
  this.idleFinishCandidate = {
1453
1461
  armedAt: now,
1454
1462
  lastOutputAt: this.lastOutputAt,
@@ -1457,7 +1465,7 @@ var init_provider_cli_adapter = __esm({
1457
1465
  assistantLength
1458
1466
  };
1459
1467
  this.recordTrace("idle_candidate_armed", {
1460
- confirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
1468
+ confirmMs: idleFinishConfirmMs,
1461
1469
  candidate: this.idleFinishCandidate,
1462
1470
  ...buildCliTraceParseSnapshot({
1463
1471
  accumulatedBuffer: this.accumulatedBuffer,
@@ -1472,7 +1480,7 @@ var init_provider_cli_adapter = __esm({
1472
1480
  this.settleTimer = null;
1473
1481
  this.settledBuffer = this.recentOutputBuffer;
1474
1482
  this.evaluateSettled();
1475
- }, _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS);
1483
+ }, idleFinishConfirmMs);
1476
1484
  }
1477
1485
  recordTrace(type, payload = {}) {
1478
1486
  const entry = {
@@ -1851,7 +1859,8 @@ var init_provider_cli_adapter = __esm({
1851
1859
  hasRecentInteractiveActivity(now) {
1852
1860
  const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
1853
1861
  const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : Number.MAX_SAFE_INTEGER;
1854
- return quietForMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS || screenStableMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
1862
+ const holdMs = this.getStatusActivityHoldMs();
1863
+ return quietForMs < holdMs || screenStableMs < holdMs;
1855
1864
  }
1856
1865
  getStartupConfirmationModal(screenText) {
1857
1866
  const text = sanitizeTerminalText(String(screenText || ""));
@@ -2003,6 +2012,7 @@ var init_provider_cli_adapter = __esm({
2003
2012
  clearPendingScriptStatus();
2004
2013
  }
2005
2014
  const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
2015
+ const statusActivityHoldMs = this.getStatusActivityHoldMs();
2006
2016
  const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity;
2007
2017
  if (shouldHoldGenerating) {
2008
2018
  this.clearIdleFinishCandidate("hold_generating_recent_activity");
@@ -2018,7 +2028,7 @@ var init_provider_cli_adapter = __esm({
2018
2028
  recentInteractiveActivity,
2019
2029
  lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
2020
2030
  lastScreenChangeAt: this.lastScreenChangeAt,
2021
- holdMs: _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS,
2031
+ holdMs: statusActivityHoldMs,
2022
2032
  ...buildCliTraceParseSnapshot({
2023
2033
  accumulatedBuffer: this.accumulatedBuffer,
2024
2034
  accumulatedRawBuffer: this.accumulatedRawBuffer,
@@ -2107,11 +2117,12 @@ var init_provider_cli_adapter = __esm({
2107
2117
  const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
2108
2118
  const hasAssistantTurn = !!lastParsedAssistant;
2109
2119
  const assistantLength = lastParsedAssistant?.content?.length || 0;
2110
- const idleQuietThresholdMs = Math.max(2e3, this.timeouts.outputSettle);
2111
- const idleStableThresholdMs = 2e3;
2120
+ const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
2121
+ const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
2122
+ const idleStableThresholdMs = idleFinishConfirmMs;
2112
2123
  const idleReady = visibleIdlePrompt && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
2113
2124
  const candidate = this.idleFinishCandidate;
2114
- const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS;
2125
+ const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
2115
2126
  const canFinishImmediately = idleReady && candidateQuiet;
2116
2127
  this.recordTrace("idle_decision", {
2117
2128
  visibleIdlePrompt,
@@ -2123,7 +2134,7 @@ var init_provider_cli_adapter = __esm({
2123
2134
  idleQuietThresholdMs,
2124
2135
  idleStableThresholdMs,
2125
2136
  idleReady,
2126
- idleFinishConfirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
2137
+ idleFinishConfirmMs,
2127
2138
  idleFinishCandidate: candidate,
2128
2139
  candidateQuiet,
2129
2140
  canFinishImmediately,
@@ -3287,6 +3298,70 @@ function setDefaultWorkspaceId(config, id) {
3287
3298
 
3288
3299
  // src/config/recent-activity.ts
3289
3300
  var path2 = __toESM(require("path"));
3301
+
3302
+ // src/providers/summary-metadata.ts
3303
+ function normalizeSummaryItem(item) {
3304
+ if (!item || typeof item !== "object") return null;
3305
+ const id = String(item.id || "").trim();
3306
+ const value = String(item.value || "").trim();
3307
+ if (!id || !value) return null;
3308
+ const normalized = {
3309
+ id,
3310
+ value
3311
+ };
3312
+ if (typeof item.label === "string" && item.label.trim()) normalized.label = item.label.trim();
3313
+ if (typeof item.shortValue === "string" && item.shortValue.trim()) normalized.shortValue = item.shortValue.trim();
3314
+ if (typeof item.icon === "string" && item.icon.trim()) normalized.icon = item.icon.trim();
3315
+ if (typeof item.order === "number" && Number.isFinite(item.order)) normalized.order = item.order;
3316
+ return normalized;
3317
+ }
3318
+ function normalizeProviderSummaryMetadata(summary) {
3319
+ if (!summary || !Array.isArray(summary.items)) return void 0;
3320
+ const items = summary.items.map((item) => normalizeSummaryItem(item)).filter((item) => !!item).sort((left, right) => {
3321
+ const orderDiff = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
3322
+ if (orderDiff !== 0) return orderDiff;
3323
+ return left.id.localeCompare(right.id);
3324
+ });
3325
+ return items.length > 0 ? { items } : void 0;
3326
+ }
3327
+ function buildProviderSummaryMetadata(items) {
3328
+ return normalizeProviderSummaryMetadata({ items: items.filter(Boolean) });
3329
+ }
3330
+ function buildLegacyModelModeSummaryMetadata(params) {
3331
+ return buildProviderSummaryMetadata([
3332
+ params.model ? {
3333
+ id: "model",
3334
+ label: "Model",
3335
+ value: String(params.modelLabel || params.model).trim(),
3336
+ shortValue: String(params.model).trim(),
3337
+ order: 10
3338
+ } : null,
3339
+ params.mode ? {
3340
+ id: "mode",
3341
+ label: "Mode",
3342
+ value: String(params.modeLabel || params.mode).trim(),
3343
+ shortValue: String(params.mode).trim(),
3344
+ order: 20
3345
+ } : null
3346
+ ]);
3347
+ }
3348
+ function resolveProviderStateSummaryMetadata(params) {
3349
+ const explicit = normalizeProviderSummaryMetadata(params.summaryMetadata);
3350
+ if (explicit) return explicit;
3351
+ const model = typeof params.controlValues?.model === "string" ? params.controlValues.model : void 0;
3352
+ const mode = typeof params.controlValues?.mode === "string" ? params.controlValues.mode : void 0;
3353
+ return buildLegacyModelModeSummaryMetadata({
3354
+ model,
3355
+ mode,
3356
+ modelLabel: params.modelLabel,
3357
+ modeLabel: params.modeLabel
3358
+ });
3359
+ }
3360
+ function normalizePersistedSummaryMetadata(params) {
3361
+ return normalizeProviderSummaryMetadata(params.summaryMetadata);
3362
+ }
3363
+
3364
+ // src/config/recent-activity.ts
3290
3365
  var MAX_ACTIVITY = 30;
3291
3366
  function normalizeWorkspace(workspace) {
3292
3367
  if (!workspace) return "";
@@ -3310,6 +3385,9 @@ function appendRecentActivity(state, entry) {
3310
3385
  const nextEntry = {
3311
3386
  ...entry,
3312
3387
  workspace: entry.workspace ? normalizeWorkspace(entry.workspace) : void 0,
3388
+ summaryMetadata: normalizePersistedSummaryMetadata({
3389
+ summaryMetadata: entry.summaryMetadata
3390
+ }),
3313
3391
  id: buildRecentActivityKeyForEntry(entry),
3314
3392
  lastUsedAt: entry.lastUsedAt || Date.now()
3315
3393
  };
@@ -3320,7 +3398,12 @@ function appendRecentActivity(state, entry) {
3320
3398
  };
3321
3399
  }
3322
3400
  function getRecentActivity(state, limit = 20) {
3323
- return [...state.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
3401
+ return [...state.recentActivity || []].map((entry) => ({
3402
+ ...entry,
3403
+ summaryMetadata: normalizePersistedSummaryMetadata({
3404
+ summaryMetadata: entry.summaryMetadata
3405
+ })
3406
+ })).sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
3324
3407
  }
3325
3408
  function getSessionSeenAt(state, sessionId) {
3326
3409
  return state.sessionReads?.[sessionId] || 0;
@@ -3372,7 +3455,9 @@ function upsertSavedProviderSession(state, entry) {
3372
3455
  providerName: entry.providerName,
3373
3456
  providerSessionId,
3374
3457
  workspace: entry.workspace ? normalizeWorkspace2(entry.workspace) : void 0,
3375
- currentModel: entry.currentModel,
3458
+ summaryMetadata: normalizePersistedSummaryMetadata({
3459
+ summaryMetadata: entry.summaryMetadata
3460
+ }),
3376
3461
  title: entry.title,
3377
3462
  createdAt: existing?.createdAt || entry.createdAt || Date.now(),
3378
3463
  lastUsedAt: entry.lastUsedAt || Date.now()
@@ -3388,7 +3473,12 @@ function getSavedProviderSessions(state, filters) {
3388
3473
  if (filters?.providerType && entry.providerType !== filters.providerType) return false;
3389
3474
  if (filters?.kind && entry.kind !== filters.kind) return false;
3390
3475
  return true;
3391
- }).sort((a, b) => b.lastUsedAt - a.lastUsedAt);
3476
+ }).map((entry) => ({
3477
+ ...entry,
3478
+ summaryMetadata: normalizePersistedSummaryMetadata({
3479
+ summaryMetadata: entry.summaryMetadata
3480
+ })
3481
+ })).sort((a, b) => b.lastUsedAt - a.lastUsedAt);
3392
3482
  }
3393
3483
 
3394
3484
  // src/config/state-store.ts
@@ -5145,8 +5235,6 @@ function extractProviderControlValues(controls, data) {
5145
5235
  if (rawValue === void 0 || rawValue === null) continue;
5146
5236
  values[ctrl.id] = normalizeControlValue(rawValue);
5147
5237
  }
5148
- if (data.model !== void 0 && values.model === void 0) values.model = normalizeControlValue(data.model);
5149
- if (data.mode !== void 0 && values.mode === void 0) values.mode = normalizeControlValue(data.mode);
5150
5238
  return Object.keys(values).length > 0 ? values : void 0;
5151
5239
  }
5152
5240
  function normalizeProviderEffects(data) {
@@ -5248,7 +5336,7 @@ function normalizeControlOption(option) {
5248
5336
  }
5249
5337
  if (!option || typeof option !== "object") return null;
5250
5338
  const record = option;
5251
- const value = typeof record.value === "string" ? record.value : typeof record.id === "string" ? record.id : null;
5339
+ const value = typeof record.value === "string" ? record.value : typeof record.id === "string" ? record.id : typeof record.name === "string" ? record.name : null;
5252
5340
  if (!value) return null;
5253
5341
  const label = typeof record.label === "string" ? record.label : typeof record.name === "string" ? record.name : value;
5254
5342
  const normalized = { value, label };
@@ -5783,6 +5871,61 @@ function listSavedHistorySessions(agentType, options = {}) {
5783
5871
  }
5784
5872
  }
5785
5873
 
5874
+ // src/providers/provider-patch-state.ts
5875
+ function isControlValue(value) {
5876
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
5877
+ }
5878
+ function asControlValueMap(value) {
5879
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
5880
+ const result = {};
5881
+ for (const [entryKey, entryValue] of Object.entries(value)) {
5882
+ if (isControlValue(entryValue)) result[entryKey] = entryValue;
5883
+ }
5884
+ return Object.keys(result).length > 0 ? result : void 0;
5885
+ }
5886
+ function getLegacyModelModeValues(data) {
5887
+ if (!data || typeof data !== "object") return void 0;
5888
+ const legacy = {};
5889
+ if (typeof data.model === "string" && data.model.trim()) legacy.model = data.model.trim();
5890
+ if (typeof data.mode === "string" && data.mode.trim()) legacy.mode = data.mode.trim();
5891
+ return Object.keys(legacy).length > 0 ? legacy : void 0;
5892
+ }
5893
+ function mergeProviderPatchState(params) {
5894
+ const {
5895
+ providerControls,
5896
+ data,
5897
+ currentControlValues,
5898
+ currentSummaryMetadata,
5899
+ mergeWithCurrent = true
5900
+ } = params;
5901
+ const sources = [
5902
+ mergeWithCurrent ? asControlValueMap(currentControlValues) : void 0,
5903
+ asControlValueMap(data?.controlValues),
5904
+ asControlValueMap(extractProviderControlValues(providerControls, data)),
5905
+ getLegacyModelModeValues(data)
5906
+ ];
5907
+ const controlValues = Object.assign({}, ...sources.filter(Boolean));
5908
+ return {
5909
+ controlValues,
5910
+ summaryMetadata: data?.summaryMetadata !== void 0 ? data.summaryMetadata : currentSummaryMetadata
5911
+ };
5912
+ }
5913
+ function normalizeProviderStateControlValues(controlValues) {
5914
+ return controlValues && Object.keys(controlValues).length > 0 ? controlValues : void 0;
5915
+ }
5916
+ function resolveProviderStateSurface(params) {
5917
+ const controlValues = normalizeProviderStateControlValues(params.controlValues);
5918
+ return {
5919
+ controlValues,
5920
+ summaryMetadata: resolveProviderStateSummaryMetadata({
5921
+ summaryMetadata: params.summaryMetadata,
5922
+ controlValues,
5923
+ modelLabel: params.modelLabel,
5924
+ modeLabel: params.modeLabel
5925
+ })
5926
+ };
5927
+ }
5928
+
5786
5929
  // src/providers/extension-provider-instance.ts
5787
5930
  var ExtensionProviderInstance = class {
5788
5931
  type;
@@ -5797,9 +5940,8 @@ var ExtensionProviderInstance = class {
5797
5940
  messages = [];
5798
5941
  prevMessageHashes = /* @__PURE__ */ new Map();
5799
5942
  activeModal = null;
5800
- currentModel = "";
5801
- currentMode = "";
5802
5943
  controlValues = {};
5944
+ summaryMetadata = void 0;
5803
5945
  appliedEffectKeys = /* @__PURE__ */ new Set();
5804
5946
  runtimeMessages = [];
5805
5947
  lastAgentStatus = "idle";
@@ -5834,6 +5976,10 @@ var ExtensionProviderInstance = class {
5834
5976
  if (!this.context?.cdp?.isConnected) return;
5835
5977
  }
5836
5978
  getState() {
5979
+ const surface = resolveProviderStateSurface({
5980
+ summaryMetadata: this.summaryMetadata,
5981
+ controlValues: this.controlValues
5982
+ });
5837
5983
  return {
5838
5984
  type: this.type,
5839
5985
  name: this.provider.name,
@@ -5847,10 +5993,9 @@ var ExtensionProviderInstance = class {
5847
5993
  activeModal: this.activeModal,
5848
5994
  inputContent: ""
5849
5995
  } : null,
5850
- currentModel: this.currentModel || void 0,
5851
- currentPlan: this.currentMode || void 0,
5852
- controlValues: this.controlValues,
5996
+ controlValues: surface.controlValues,
5853
5997
  providerControls: this.provider.controls,
5998
+ summaryMetadata: surface.summaryMetadata,
5854
5999
  agentStreams: this.agentStreams,
5855
6000
  instanceId: this.instanceId,
5856
6001
  lastUpdated: Date.now(),
@@ -5863,10 +6008,14 @@ var ExtensionProviderInstance = class {
5863
6008
  if (data?.streams) this.agentStreams = data.streams;
5864
6009
  if (data?.messages) this.messages = this.assignReceivedAt(data.messages);
5865
6010
  if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
5866
- if (data?.model) this.currentModel = data.model;
5867
- if (data?.mode) this.currentMode = data.mode;
5868
- const controlValues = extractProviderControlValues(this.provider.controls, data) || data?.controlValues;
5869
- if (controlValues) this.controlValues = controlValues;
6011
+ const patchedState = mergeProviderPatchState({
6012
+ providerControls: this.provider.controls,
6013
+ data,
6014
+ currentControlValues: this.controlValues,
6015
+ currentSummaryMetadata: this.summaryMetadata
6016
+ });
6017
+ this.controlValues = patchedState.controlValues;
6018
+ this.summaryMetadata = patchedState.summaryMetadata;
5870
6019
  if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
5871
6020
  if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
5872
6021
  if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
@@ -5967,8 +6116,14 @@ var ExtensionProviderInstance = class {
5967
6116
  }
5968
6117
  applyProviderResponse(data, options) {
5969
6118
  if (!data || typeof data !== "object") return;
5970
- const controlValues = extractProviderControlValues(this.provider.controls, data);
5971
- if (controlValues) this.controlValues = { ...this.controlValues, ...controlValues };
6119
+ const patchedState = mergeProviderPatchState({
6120
+ providerControls: this.provider.controls,
6121
+ data,
6122
+ currentControlValues: this.controlValues,
6123
+ currentSummaryMetadata: this.summaryMetadata
6124
+ });
6125
+ this.controlValues = patchedState.controlValues;
6126
+ this.summaryMetadata = patchedState.summaryMetadata;
5972
6127
  const effects = normalizeProviderEffects(data);
5973
6128
  for (const effect of effects) {
5974
6129
  const effectWhen = effect.when || "immediate";
@@ -6118,8 +6273,6 @@ ${effect.notification.body || ""}`.trim();
6118
6273
  this.messages = [];
6119
6274
  this.prevMessageHashes.clear();
6120
6275
  this.activeModal = null;
6121
- this.currentModel = "";
6122
- this.currentMode = "";
6123
6276
  this.controlValues = {};
6124
6277
  this.currentStatus = "idle";
6125
6278
  this.chatId = null;
@@ -6255,6 +6408,10 @@ var IdeProviderInstance = class {
6255
6408
  for (const ext of this.extensions.values()) {
6256
6409
  extensionStates.push(ext.getState());
6257
6410
  }
6411
+ const surface = resolveProviderStateSurface({
6412
+ summaryMetadata: this.cachedChat?.summaryMetadata,
6413
+ controlValues: this.cachedChat?.controlValues
6414
+ });
6258
6415
  return {
6259
6416
  type: this.type,
6260
6417
  name: this.provider.name,
@@ -6271,11 +6428,9 @@ var IdeProviderInstance = class {
6271
6428
  workspace: this.workspace || null,
6272
6429
  extensions: extensionStates,
6273
6430
  cdpConnected: cdp?.isConnected || false,
6274
- currentModel: this.cachedChat?.model || void 0,
6275
- currentPlan: this.cachedChat?.mode || void 0,
6276
- currentAutoApprove: this.cachedChat?.autoApprove || void 0,
6277
- controlValues: this.cachedChat?.controlValues || void 0,
6431
+ controlValues: surface.controlValues,
6278
6432
  providerControls: this.provider.controls,
6433
+ summaryMetadata: surface.summaryMetadata,
6279
6434
  instanceId: this.instanceId,
6280
6435
  lastUpdated: Date.now(),
6281
6436
  settings: this.settings,
@@ -6447,8 +6602,13 @@ var IdeProviderInstance = class {
6447
6602
  chat.messages = messages.filter((m) => !hiddenKinds.has(m.kind || ""));
6448
6603
  }
6449
6604
  }
6450
- const controlValues = extractProviderControlValues(this.provider.controls, chat);
6451
- if (controlValues) chat.controlValues = controlValues;
6605
+ const patchedState = mergeProviderPatchState({
6606
+ providerControls: this.provider.controls,
6607
+ data: chat,
6608
+ mergeWithCurrent: false
6609
+ });
6610
+ chat.controlValues = Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : void 0;
6611
+ chat.summaryMetadata = patchedState.summaryMetadata;
6452
6612
  this.cachedChat = { ...chat, activeModal };
6453
6613
  this.detectAgentTransitions(chat, now);
6454
6614
  const persistedMessages = chat.messages || messages;
@@ -6535,14 +6695,18 @@ var IdeProviderInstance = class {
6535
6695
  }
6536
6696
  applyProviderResponse(data, options) {
6537
6697
  if (!data || typeof data !== "object") return;
6538
- const controlValues = extractProviderControlValues(this.provider.controls, data);
6539
- if (controlValues) {
6540
- this.cachedChat = {
6541
- ...this.cachedChat || {},
6542
- ...data,
6543
- controlValues: { ...this.cachedChat?.controlValues || {}, ...controlValues }
6544
- };
6545
- }
6698
+ const patchedState = mergeProviderPatchState({
6699
+ providerControls: this.provider.controls,
6700
+ data,
6701
+ currentControlValues: this.cachedChat?.controlValues,
6702
+ currentSummaryMetadata: this.cachedChat?.summaryMetadata
6703
+ });
6704
+ this.cachedChat = {
6705
+ ...this.cachedChat || {},
6706
+ ...data,
6707
+ controlValues: Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : void 0,
6708
+ summaryMetadata: patchedState.summaryMetadata
6709
+ };
6546
6710
  const effects = normalizeProviderEffects(data);
6547
6711
  for (const effect of effects) {
6548
6712
  const effectWhen = effect.when || "immediate";
@@ -7325,6 +7489,8 @@ var ACP_SESSION_CAPABILITIES = [
7325
7489
  function buildIdeWorkspaceSession(state, cdpManagers, options) {
7326
7490
  const profile = options.profile || "full";
7327
7491
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7492
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7493
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7328
7494
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7329
7495
  const includeSessionControls = shouldIncludeSessionControls(profile);
7330
7496
  const title = activeChat?.title || state.name;
@@ -7341,13 +7507,11 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
7341
7507
  title,
7342
7508
  ...includeSessionMetadata && { workspace: state.workspace || null },
7343
7509
  activeChat,
7510
+ ...summaryMetadata && { summaryMetadata },
7344
7511
  ...includeSessionMetadata && { capabilities: IDE_SESSION_CAPABILITIES },
7345
7512
  cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
7346
- currentModel: state.currentModel,
7347
- currentPlan: state.currentPlan,
7348
- currentAutoApprove: state.currentAutoApprove,
7349
7513
  ...includeSessionControls && {
7350
- controlValues: state.controlValues,
7514
+ ...controlValues && { controlValues },
7351
7515
  providerControls: state.providerControls
7352
7516
  },
7353
7517
  errorMessage: state.errorMessage,
@@ -7358,6 +7522,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
7358
7522
  function buildExtensionAgentSession(parent, ext, options) {
7359
7523
  const profile = options.profile || "full";
7360
7524
  const activeChat = normalizeActiveChatData(ext.activeChat, getActiveChatOptions(profile));
7525
+ const summaryMetadata = normalizeProviderSummaryMetadata(ext.summaryMetadata);
7526
+ const controlValues = normalizeProviderStateControlValues(ext.controlValues);
7361
7527
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7362
7528
  const includeSessionControls = shouldIncludeSessionControls(profile);
7363
7529
  return {
@@ -7373,11 +7539,10 @@ function buildExtensionAgentSession(parent, ext, options) {
7373
7539
  title: activeChat?.title || ext.name,
7374
7540
  ...includeSessionMetadata && { workspace: parent.workspace || null },
7375
7541
  activeChat,
7542
+ ...summaryMetadata && { summaryMetadata },
7376
7543
  ...includeSessionMetadata && { capabilities: EXTENSION_SESSION_CAPABILITIES },
7377
- currentModel: ext.currentModel,
7378
- currentPlan: ext.currentPlan,
7379
7544
  ...includeSessionControls && {
7380
- controlValues: ext.controlValues,
7545
+ ...controlValues && { controlValues },
7381
7546
  providerControls: ext.providerControls
7382
7547
  },
7383
7548
  errorMessage: ext.errorMessage,
@@ -7388,6 +7553,8 @@ function buildExtensionAgentSession(parent, ext, options) {
7388
7553
  function buildCliSession(state, options) {
7389
7554
  const profile = options.profile || "full";
7390
7555
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7556
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7557
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7391
7558
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7392
7559
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
7393
7560
  const includeSessionControls = shouldIncludeSessionControls(profile);
@@ -7414,11 +7581,12 @@ function buildCliSession(state, options) {
7414
7581
  mode: state.mode,
7415
7582
  resume: state.resume,
7416
7583
  activeChat,
7584
+ ...summaryMetadata && { summaryMetadata },
7417
7585
  ...includeSessionMetadata && {
7418
7586
  capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES
7419
7587
  },
7420
7588
  ...includeSessionControls && {
7421
- controlValues: state.controlValues,
7589
+ ...controlValues && { controlValues },
7422
7590
  providerControls: state.providerControls
7423
7591
  },
7424
7592
  errorMessage: state.errorMessage,
@@ -7429,6 +7597,8 @@ function buildCliSession(state, options) {
7429
7597
  function buildAcpSession(state, options) {
7430
7598
  const profile = options.profile || "full";
7431
7599
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7600
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7601
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7432
7602
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7433
7603
  const includeSessionControls = shouldIncludeSessionControls(profile);
7434
7604
  return {
@@ -7444,13 +7614,10 @@ function buildAcpSession(state, options) {
7444
7614
  title: activeChat?.title || state.name,
7445
7615
  ...includeSessionMetadata && { workspace: state.workspace || null },
7446
7616
  activeChat,
7617
+ ...summaryMetadata && { summaryMetadata },
7447
7618
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
7448
- currentModel: state.currentModel,
7449
- currentPlan: state.currentPlan,
7450
7619
  ...includeSessionControls && {
7451
- acpConfigOptions: state.acpConfigOptions,
7452
- acpModes: state.acpModes,
7453
- controlValues: state.controlValues,
7620
+ ...controlValues && { controlValues },
7454
7621
  providerControls: state.providerControls
7455
7622
  },
7456
7623
  errorMessage: state.errorMessage,
@@ -9510,8 +9677,17 @@ async function handleSetProviderSourceConfig(h, args) {
9510
9677
  );
9511
9678
  return { success: true, reloaded: true, ...sourceConfig };
9512
9679
  }
9513
- function normalizeProviderScriptArgs(args) {
9680
+ function normalizeProviderScriptArgs(args, scriptName) {
9514
9681
  const normalizedArgs = { ...args || {} };
9682
+ const normalizedScriptName = String(scriptName || "").toLowerCase();
9683
+ if (Object.prototype.hasOwnProperty.call(normalizedArgs, "value")) {
9684
+ if (normalizedArgs.model === void 0 && (normalizedScriptName === "setmodel" || normalizedScriptName === "setmodelgui" || normalizedScriptName === "webviewsetmodel")) {
9685
+ normalizedArgs.model = normalizedArgs.value;
9686
+ }
9687
+ if (normalizedArgs.mode === void 0 && (normalizedScriptName === "setmode" || normalizedScriptName === "webviewsetmode")) {
9688
+ normalizedArgs.mode = normalizedArgs.value;
9689
+ }
9690
+ }
9515
9691
  for (const key of ["mode", "model", "message", "action", "button", "text", "sessionId", "value"]) {
9516
9692
  if (key in normalizedArgs && !(key.toUpperCase() in normalizedArgs)) {
9517
9693
  normalizedArgs[key.toUpperCase()] = normalizedArgs[key];
@@ -9557,7 +9733,7 @@ async function executeProviderScript(h, args, scriptName) {
9557
9733
  if (!provider.scripts?.[actualScriptName]) {
9558
9734
  return { success: false, error: `Script '${actualScriptName}' not available for ${resolvedProviderType}` };
9559
9735
  }
9560
- const normalizedArgs = normalizeProviderScriptArgs(args);
9736
+ const normalizedArgs = normalizeProviderScriptArgs(args, actualScriptName);
9561
9737
  if (provider.category === "cli") {
9562
9738
  const adapter = h.getCliAdapter(args?.targetSessionId || resolvedProviderType);
9563
9739
  if (!adapter?.invokeScript) {
@@ -10418,6 +10594,7 @@ var CliProviderInstance = class {
10418
10594
  generatingDebouncePending = null;
10419
10595
  lastApprovalEventAt = 0;
10420
10596
  controlValues = {};
10597
+ summaryMetadata = void 0;
10421
10598
  appliedEffectKeys = /* @__PURE__ */ new Set();
10422
10599
  historyWriter;
10423
10600
  runtimeMessages = [];
@@ -10560,13 +10737,7 @@ var CliProviderInstance = class {
10560
10737
  if (historyMessageCount !== null) {
10561
10738
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
10562
10739
  }
10563
- const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
10564
- if (controlValues) {
10565
- this.controlValues = { ...this.controlValues, ...controlValues };
10566
- }
10567
10740
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
10568
- 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;
10569
- 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;
10570
10741
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
10571
10742
  if (parsedMessages.length > 0) {
10572
10743
  const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
@@ -10588,6 +10759,10 @@ var CliProviderInstance = class {
10588
10759
  }
10589
10760
  }
10590
10761
  this.applyProviderResponse(parsedStatus, { phase: "immediate" });
10762
+ const surface = resolveProviderStateSurface({
10763
+ summaryMetadata: this.summaryMetadata,
10764
+ controlValues: this.controlValues
10765
+ });
10591
10766
  return {
10592
10767
  type: this.type,
10593
10768
  name: this.provider.name,
@@ -10603,8 +10778,6 @@ var CliProviderInstance = class {
10603
10778
  inputContent: ""
10604
10779
  },
10605
10780
  workspace: this.workingDir,
10606
- currentModel,
10607
- currentPlan,
10608
10781
  instanceId: this.instanceId,
10609
10782
  providerSessionId: this.providerSessionId,
10610
10783
  lastUpdated: Date.now(),
@@ -10619,8 +10792,9 @@ var CliProviderInstance = class {
10619
10792
  attachedClients: runtime.attachedClients || []
10620
10793
  } : void 0,
10621
10794
  resume: this.provider.resume,
10622
- controlValues: this.controlValues,
10623
- providerControls: this.provider.controls
10795
+ controlValues: surface.controlValues,
10796
+ providerControls: this.provider.controls,
10797
+ summaryMetadata: surface.summaryMetadata
10624
10798
  };
10625
10799
  }
10626
10800
  setPresentationMode(mode) {
@@ -10824,10 +10998,14 @@ var CliProviderInstance = class {
10824
10998
  this.suppressIdleHistoryReplay = false;
10825
10999
  this.adapter.clearHistory();
10826
11000
  }
10827
- const controlValues = extractProviderControlValues(this.provider.controls, data);
10828
- if (controlValues) {
10829
- this.controlValues = { ...this.controlValues, ...controlValues };
10830
- }
11001
+ const patchedState = mergeProviderPatchState({
11002
+ providerControls: this.provider.controls,
11003
+ data,
11004
+ currentControlValues: this.controlValues,
11005
+ currentSummaryMetadata: this.summaryMetadata
11006
+ });
11007
+ this.controlValues = patchedState.controlValues;
11008
+ this.summaryMetadata = patchedState.summaryMetadata;
10831
11009
  const effects = normalizeProviderEffects(data);
10832
11010
  for (const effect of effects) {
10833
11011
  const effectWhen = effect.when || "immediate";
@@ -11193,8 +11371,7 @@ var AcpProviderInstance = class {
11193
11371
  lastStatus = "starting";
11194
11372
  generatingStartedAt = 0;
11195
11373
  agentCapabilities = {};
11196
- currentModel;
11197
- currentMode;
11374
+ currentSelections = {};
11198
11375
  activeToolCalls = [];
11199
11376
  stopReason = null;
11200
11377
  partialContent = "";
@@ -11274,8 +11451,6 @@ var AcpProviderInstance = class {
11274
11451
  inputContent: ""
11275
11452
  },
11276
11453
  workspace: this.workingDir,
11277
- currentModel: this.currentModel,
11278
- currentPlan: this.currentMode,
11279
11454
  instanceId: this.instanceId,
11280
11455
  lastUpdated: Date.now(),
11281
11456
  settings: this.settings,
@@ -11286,11 +11461,9 @@ var AcpProviderInstance = class {
11286
11461
  // Error details for dashboard display
11287
11462
  errorMessage: this.errorMessage || void 0,
11288
11463
  errorReason: this.errorReason || void 0,
11289
- controlValues: {
11290
- ...this.currentModel ? { model: this.currentModel } : {},
11291
- ...this.currentMode ? { mode: this.currentMode } : {}
11292
- },
11293
- providerControls: this.provider.controls
11464
+ controlValues: this.getSelectionControlValues(),
11465
+ providerControls: this.provider.controls,
11466
+ summaryMetadata: this.buildSelectionSummaryMetadata()
11294
11467
  };
11295
11468
  }
11296
11469
  onEvent(event, data) {
@@ -11324,6 +11497,54 @@ var AcpProviderInstance = class {
11324
11497
  getInstanceId() {
11325
11498
  return this.instanceId;
11326
11499
  }
11500
+ resolveConfigOptionLabel(category, value) {
11501
+ if (!value) return void 0;
11502
+ const option = this.configOptions.find((entry) => entry.category === category);
11503
+ return option?.options.find((candidate) => candidate.value === value)?.name || value;
11504
+ }
11505
+ resolveModeLabel(modeId) {
11506
+ if (!modeId) return void 0;
11507
+ return this.availableModes.find((mode) => mode.id === modeId)?.name || modeId;
11508
+ }
11509
+ getCurrentSelection(category) {
11510
+ return this.currentSelections[category];
11511
+ }
11512
+ setCurrentSelection(category, value) {
11513
+ const normalized = typeof value === "string" ? value.trim() : "";
11514
+ if (normalized) {
11515
+ this.currentSelections[category] = normalized;
11516
+ return;
11517
+ }
11518
+ delete this.currentSelections[category];
11519
+ }
11520
+ getSelectionControlValues() {
11521
+ const model = this.getCurrentSelection("model");
11522
+ const mode = this.getCurrentSelection("mode");
11523
+ return {
11524
+ ...model ? { model } : {},
11525
+ ...mode ? { mode } : {}
11526
+ };
11527
+ }
11528
+ resolveSelectionLabel(category, value) {
11529
+ if (!value) return void 0;
11530
+ const configLabel = this.resolveConfigOptionLabel(category, value);
11531
+ if (configLabel && configLabel !== value) return configLabel;
11532
+ if (category === "mode") {
11533
+ const modeLabel = this.resolveModeLabel(value);
11534
+ if (modeLabel) return modeLabel;
11535
+ }
11536
+ return configLabel || value;
11537
+ }
11538
+ buildSelectionSummaryMetadata() {
11539
+ const model = this.getCurrentSelection("model");
11540
+ const mode = this.getCurrentSelection("mode");
11541
+ return buildLegacyModelModeSummaryMetadata({
11542
+ model,
11543
+ mode,
11544
+ modelLabel: this.resolveSelectionLabel("model", model),
11545
+ modeLabel: this.resolveSelectionLabel("mode", mode)
11546
+ });
11547
+ }
11327
11548
  // ─── ACP Config Options & Modes ─────────────────────
11328
11549
  parseConfigOptions(raw) {
11329
11550
  if (!Array.isArray(raw)) return;
@@ -11355,12 +11576,14 @@ var AcpProviderInstance = class {
11355
11576
  }
11356
11577
  }
11357
11578
  this.configOptions.push({ category, configId, currentValue, options: flatOptions });
11358
- if (category === "model" && currentValue) this.currentModel = currentValue;
11579
+ if (category === "model" || category === "mode") {
11580
+ this.setCurrentSelection(category, currentValue);
11581
+ }
11359
11582
  }
11360
11583
  }
11361
11584
  parseModes(raw) {
11362
11585
  if (!raw) return;
11363
- if (raw.currentModeId) this.currentMode = raw.currentModeId;
11586
+ this.setCurrentSelection("mode", raw.currentModeId);
11364
11587
  if (Array.isArray(raw.availableModes)) {
11365
11588
  this.availableModes = raw.availableModes.map((m) => ({
11366
11589
  id: m.id,
@@ -11379,8 +11602,7 @@ var AcpProviderInstance = class {
11379
11602
  if (this.useStaticConfig) {
11380
11603
  opt.currentValue = value;
11381
11604
  this.selectedConfig[opt.configId] = value;
11382
- if (category === "model") this.currentModel = value;
11383
- if (category === "mode") this.currentMode = value;
11605
+ if (category === "model" || category === "mode") this.setCurrentSelection(category, value);
11384
11606
  this.log.info(`[${this.type}] Static config ${category} set to: ${value} \u2014 restarting agent`);
11385
11607
  await this.restartWithNewConfig();
11386
11608
  return;
@@ -11398,7 +11620,7 @@ var AcpProviderInstance = class {
11398
11620
  value
11399
11621
  });
11400
11622
  opt.currentValue = value;
11401
- if (category === "model") this.currentModel = value;
11623
+ if (category === "model" || category === "mode") this.setCurrentSelection(category, value);
11402
11624
  if (result?.configOptions) this.parseConfigOptions(result.configOptions);
11403
11625
  this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
11404
11626
  } catch (e) {
@@ -11414,7 +11636,7 @@ var AcpProviderInstance = class {
11414
11636
  opt.currentValue = modeId;
11415
11637
  this.selectedConfig[opt.configId] = modeId;
11416
11638
  }
11417
- this.currentMode = modeId;
11639
+ this.setCurrentSelection("mode", modeId);
11418
11640
  this.log.info(`[${this.type}] Static mode set to: ${modeId} \u2014 restarting agent`);
11419
11641
  await this.restartWithNewConfig();
11420
11642
  return;
@@ -11429,7 +11651,7 @@ var AcpProviderInstance = class {
11429
11651
  sessionId: this.sessionId,
11430
11652
  modeId
11431
11653
  });
11432
- this.currentMode = modeId;
11654
+ this.setCurrentSelection("mode", modeId);
11433
11655
  this.log.info(`[${this.type}] Mode set to: ${modeId}`);
11434
11656
  } catch (e) {
11435
11657
  const message = e?.message || "Unknown ACP mode error";
@@ -11687,8 +11909,8 @@ var AcpProviderInstance = class {
11687
11909
  if (result?.modes) this.log.debug(`[${this.type}] modes: ${JSON.stringify(result.modes).slice(0, 300)}`);
11688
11910
  this.parseConfigOptions(result?.configOptions);
11689
11911
  this.parseModes(result?.modes);
11690
- if (!this.currentModel && result?.models?.currentModelId) {
11691
- this.currentModel = result.models.currentModelId;
11912
+ if (!this.getCurrentSelection("model") && result?.models?.currentModelId) {
11913
+ this.setCurrentSelection("model", result.models.currentModelId);
11692
11914
  }
11693
11915
  if (this.configOptions.length === 0 && this.provider.staticConfigOptions?.length) {
11694
11916
  this.useStaticConfig = true;
@@ -11702,13 +11924,16 @@ var AcpProviderInstance = class {
11702
11924
  });
11703
11925
  if (defaultVal) {
11704
11926
  this.selectedConfig[sc.configId] = defaultVal;
11705
- if (sc.category === "model") this.currentModel = defaultVal;
11706
- if (sc.category === "mode") this.currentMode = defaultVal;
11927
+ if (sc.category === "model" || sc.category === "mode") {
11928
+ this.setCurrentSelection(sc.category, defaultVal);
11929
+ }
11707
11930
  }
11708
11931
  }
11709
11932
  this.log.info(`[${this.type}] Using static configOptions (${this.configOptions.length} options)`);
11710
11933
  }
11711
- this.log.info(`[${this.type}] Session created: ${this.sessionId}${this.currentModel ? ` (model: ${this.currentModel})` : ""}${this.currentMode ? ` (mode: ${this.currentMode})` : ""}`);
11934
+ const currentModel = this.getCurrentSelection("model");
11935
+ const currentMode = this.getCurrentSelection("mode");
11936
+ this.log.info(`[${this.type}] Session created: ${this.sessionId}${currentModel ? ` (model: ${currentModel})` : ""}${currentMode ? ` (mode: ${currentMode})` : ""}`);
11712
11937
  if (this.configOptions.length > 0) {
11713
11938
  this.log.info(`[${this.type}] Config options: ${this.configOptions.map((c) => `${c.category}(${c.options.length})`).join(", ")}`);
11714
11939
  }
@@ -11883,7 +12108,7 @@ var AcpProviderInstance = class {
11883
12108
  break;
11884
12109
  }
11885
12110
  case "current_mode_update": {
11886
- this.currentMode = update.currentModeId;
12111
+ this.setCurrentSelection("mode", update.currentModeId);
11887
12112
  break;
11888
12113
  }
11889
12114
  case "config_option_update": {
@@ -11956,7 +12181,7 @@ var AcpProviderInstance = class {
11956
12181
  this.detectStatusTransition();
11957
12182
  }
11958
12183
  if (params.model) {
11959
- this.currentModel = params.model;
12184
+ this.setCurrentSelection("model", params.model);
11960
12185
  }
11961
12186
  }
11962
12187
  /** Map SDK ToolCallStatus to internal status */
@@ -12245,7 +12470,11 @@ var DaemonCliManager = class {
12245
12470
  }
12246
12471
  persistRecentActivity(entry) {
12247
12472
  try {
12248
- let nextState = appendRecentActivity(loadState(), entry);
12473
+ const summaryMetadata = normalizeProviderSummaryMetadata(entry.summaryMetadata);
12474
+ let nextState = appendRecentActivity(loadState(), {
12475
+ ...entry,
12476
+ summaryMetadata
12477
+ });
12249
12478
  if (entry.providerSessionId && (entry.kind === "cli" || entry.kind === "acp")) {
12250
12479
  nextState = upsertSavedProviderSession(nextState, {
12251
12480
  kind: entry.kind,
@@ -12253,7 +12482,7 @@ var DaemonCliManager = class {
12253
12482
  providerName: entry.providerName,
12254
12483
  providerSessionId: entry.providerSessionId,
12255
12484
  workspace: entry.workspace,
12256
- currentModel: entry.currentModel,
12485
+ summaryMetadata,
12257
12486
  title: entry.title
12258
12487
  });
12259
12488
  }
@@ -12443,7 +12672,7 @@ ${installInfo}`
12443
12672
  providerType: normalizedType,
12444
12673
  providerName: provider.displayName || provider.name || normalizedType,
12445
12674
  workspace: resolvedDir,
12446
- currentModel: initialModel,
12675
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
12447
12676
  sessionId,
12448
12677
  title: provider.displayName || provider.name || normalizedType
12449
12678
  });
@@ -12545,7 +12774,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
12545
12774
  providerName: provider?.displayName || provider?.name || normalizedType,
12546
12775
  providerSessionId: sessionBinding.providerSessionId,
12547
12776
  workspace: resolvedDir,
12548
- currentModel: initialModel,
12777
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
12549
12778
  sessionId: key,
12550
12779
  title: provider?.displayName || provider?.name || normalizedType
12551
12780
  });
@@ -14710,12 +14939,90 @@ cleanOldFiles();
14710
14939
  // src/commands/router.ts
14711
14940
  init_logger();
14712
14941
 
14942
+ // src/session-host/runtime-surface.ts
14943
+ var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
14944
+ function isSessionHostLiveRuntime(record) {
14945
+ const lifecycle = String(record?.lifecycle || "").trim();
14946
+ return LIVE_LIFECYCLES.has(lifecycle);
14947
+ }
14948
+ function getSessionHostRecoveryLabel(meta) {
14949
+ const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
14950
+ if (!recoveryState) return null;
14951
+ if (recoveryState === "auto_resumed") return "restored after restart";
14952
+ if (recoveryState === "resume_failed") return "restore failed";
14953
+ if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
14954
+ if (recoveryState === "orphan_snapshot") return "snapshot recovered";
14955
+ return recoveryState.replace(/_/g, " ");
14956
+ }
14957
+ function isSessionHostRecoverySnapshot(record) {
14958
+ if (!record) return false;
14959
+ if (isSessionHostLiveRuntime(record)) return false;
14960
+ const lifecycle = String(record.lifecycle || "").trim();
14961
+ if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
14962
+ return false;
14963
+ }
14964
+ const meta = record.meta || void 0;
14965
+ if (meta?.restoredFromStorage === true) return true;
14966
+ return getSessionHostRecoveryLabel(meta) !== null;
14967
+ }
14968
+ function getSessionHostSurfaceKind(record) {
14969
+ if (isSessionHostLiveRuntime(record)) return "live_runtime";
14970
+ if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
14971
+ return "inactive_record";
14972
+ }
14973
+ function partitionSessionHostRecords(records) {
14974
+ const liveRuntimes = [];
14975
+ const recoverySnapshots = [];
14976
+ const inactiveRecords = [];
14977
+ for (const record of records) {
14978
+ const kind = getSessionHostSurfaceKind(record);
14979
+ if (kind === "live_runtime") {
14980
+ liveRuntimes.push(record);
14981
+ } else if (kind === "recovery_snapshot") {
14982
+ recoverySnapshots.push(record);
14983
+ } else {
14984
+ inactiveRecords.push(record);
14985
+ }
14986
+ }
14987
+ return {
14988
+ liveRuntimes,
14989
+ recoverySnapshots,
14990
+ inactiveRecords
14991
+ };
14992
+ }
14993
+ function partitionSessionHostDiagnosticsSessions(records) {
14994
+ return partitionSessionHostRecords(records || []);
14995
+ }
14996
+
14713
14997
  // src/status/snapshot.ts
14714
14998
  var os16 = __toESM(require("os"));
14715
14999
  init_config();
14716
15000
  init_terminal_screen();
14717
15001
  init_logger();
14718
15002
  var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
15003
+ var recentReadDebugSignatureBySession = /* @__PURE__ */ new Map();
15004
+ function buildRecentReadDebugSignature(snapshot) {
15005
+ return [
15006
+ snapshot.providerType,
15007
+ snapshot.status,
15008
+ snapshot.inboxBucket,
15009
+ snapshot.unread ? "1" : "0",
15010
+ String(snapshot.lastSeenAt),
15011
+ snapshot.completionMarker,
15012
+ snapshot.seenCompletionMarker,
15013
+ String(snapshot.lastUpdated),
15014
+ String(snapshot.lastUsedAt),
15015
+ snapshot.lastRole,
15016
+ String(snapshot.messageUpdatedAt)
15017
+ ].join("|");
15018
+ }
15019
+ function shouldEmitRecentReadDebugLog(cache, snapshot) {
15020
+ const nextSignature = buildRecentReadDebugSignature(snapshot);
15021
+ const previousSignature = cache.get(snapshot.sessionId);
15022
+ if (previousSignature === nextSignature) return false;
15023
+ cache.set(snapshot.sessionId, nextSignature);
15024
+ return true;
15025
+ }
14719
15026
  function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
14720
15027
  return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
14721
15028
  id: ide.id,
@@ -14867,7 +15174,7 @@ function buildRecentLaunches(recentActivity) {
14867
15174
  providerSessionId: item.providerSessionId,
14868
15175
  title: item.title || item.providerName,
14869
15176
  workspace: item.workspace,
14870
- currentModel: item.currentModel,
15177
+ summaryMetadata: item.summaryMetadata,
14871
15178
  lastLaunchedAt: item.lastUsedAt
14872
15179
  })).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
14873
15180
  }
@@ -14908,9 +15215,24 @@ function buildStatusSnapshot(options) {
14908
15215
  session.unread = unread;
14909
15216
  session.inboxBucket = inboxBucket;
14910
15217
  if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
15218
+ const recentReadSnapshot = {
15219
+ sessionId: session.id,
15220
+ providerType: session.providerType,
15221
+ status: String(session.status || ""),
15222
+ inboxBucket,
15223
+ unread,
15224
+ lastSeenAt,
15225
+ completionMarker: completionMarker || "-",
15226
+ seenCompletionMarker: seenCompletionMarker || "-",
15227
+ lastUpdated: Number(session.lastUpdated || 0),
15228
+ lastUsedAt,
15229
+ lastRole: getLastMessageRole(sourceSession),
15230
+ messageUpdatedAt: getSessionMessageUpdatedAt(sourceSession)
15231
+ };
15232
+ if (!shouldEmitRecentReadDebugLog(recentReadDebugSignatureBySession, recentReadSnapshot)) continue;
14911
15233
  LOG.info(
14912
15234
  "RecentRead",
14913
- `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)}`
15235
+ `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}`
14914
15236
  );
14915
15237
  }
14916
15238
  const lastDisplayMessage = getLastDisplayMessage(sourceSession);
@@ -15185,11 +15507,104 @@ function toHostedCliRuntimeDescriptor(record) {
15185
15507
  providerSessionId: typeof record.meta?.providerSessionId === "string" ? String(record.meta.providerSessionId) : void 0
15186
15508
  };
15187
15509
  }
15510
+ function getWriteConflictOwnerClientId(error) {
15511
+ const message = typeof error === "string" ? error : error instanceof Error ? error.message : "";
15512
+ const match = /^Write owned by\s+(.+)$/.exec(message.trim());
15513
+ return match?.[1]?.trim() || void 0;
15514
+ }
15515
+ function summarizeSessionHostRecord(result) {
15516
+ if (!result || typeof result !== "object") return {};
15517
+ const record = result;
15518
+ return {
15519
+ runtimeKey: typeof record.runtimeKey === "string" ? record.runtimeKey : void 0,
15520
+ lifecycle: typeof record.lifecycle === "string" ? record.lifecycle : void 0,
15521
+ surfaceKind: getSessionHostSurfaceKind(record),
15522
+ attachedClientCount: Array.isArray(record.attachedClients) ? record.attachedClients.length : void 0,
15523
+ hasWriteOwner: !!record.writeOwner,
15524
+ writeOwnerClientId: typeof record.writeOwner?.clientId === "string" ? record.writeOwner.clientId : void 0
15525
+ };
15526
+ }
15527
+ function summarizeSessionHostRecords(result) {
15528
+ const records = Array.isArray(result) ? result : [];
15529
+ const groups = partitionSessionHostRecords(records);
15530
+ return {
15531
+ sessionCount: records.length,
15532
+ liveRuntimeCount: groups.liveRuntimes.length,
15533
+ recoverySnapshotCount: groups.recoverySnapshots.length,
15534
+ inactiveRecordCount: groups.inactiveRecords.length
15535
+ };
15536
+ }
15537
+ function summarizeSessionHostDiagnostics(result) {
15538
+ const diagnostics = result && typeof result === "object" ? result : {};
15539
+ const sessions = Array.isArray(diagnostics.sessions) ? diagnostics.sessions : [];
15540
+ return {
15541
+ runtimeCount: typeof diagnostics.runtimeCount === "number" ? diagnostics.runtimeCount : void 0,
15542
+ ...summarizeSessionHostRecords(sessions)
15543
+ };
15544
+ }
15545
+ function summarizeSessionHostPruneResult(result) {
15546
+ const value = result && typeof result === "object" ? result : {};
15547
+ return {
15548
+ duplicateGroupCount: typeof value.duplicateGroupCount === "number" ? value.duplicateGroupCount : void 0,
15549
+ prunedCount: Array.isArray(value.prunedSessionIds) ? value.prunedSessionIds.length : void 0,
15550
+ keptCount: Array.isArray(value.keptSessionIds) ? value.keptSessionIds.length : void 0
15551
+ };
15552
+ }
15188
15553
  var DaemonCommandRouter = class {
15189
15554
  deps;
15190
15555
  constructor(deps) {
15191
15556
  this.deps = deps;
15192
15557
  }
15558
+ async traceSessionHostAction(action, args, run, summarizeResult) {
15559
+ const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
15560
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
15561
+ const requestedPayload = { action };
15562
+ if (sessionId) requestedPayload.sessionId = sessionId;
15563
+ if (typeof args?.clientId === "string") requestedPayload.clientId = args.clientId;
15564
+ if (typeof args?.signal === "string") requestedPayload.signal = args.signal;
15565
+ if (typeof args?.providerType === "string") requestedPayload.providerType = args.providerType;
15566
+ if (typeof args?.workspace === "string") requestedPayload.workspace = args.workspace;
15567
+ if (typeof args?.dryRun === "boolean") requestedPayload.dryRun = args.dryRun;
15568
+ recordDebugTrace({
15569
+ interactionId,
15570
+ category: "session_host",
15571
+ stage: "action_requested",
15572
+ level: "info",
15573
+ sessionId,
15574
+ payload: requestedPayload
15575
+ });
15576
+ try {
15577
+ const result = await run();
15578
+ recordDebugTrace({
15579
+ interactionId,
15580
+ category: "session_host",
15581
+ stage: "action_result",
15582
+ level: "info",
15583
+ sessionId,
15584
+ payload: {
15585
+ ...requestedPayload,
15586
+ success: true,
15587
+ ...summarizeResult ? summarizeResult(result) : {}
15588
+ }
15589
+ });
15590
+ return result;
15591
+ } catch (error) {
15592
+ recordDebugTrace({
15593
+ interactionId,
15594
+ category: "session_host",
15595
+ stage: "action_failed",
15596
+ level: "error",
15597
+ sessionId,
15598
+ payload: {
15599
+ ...requestedPayload,
15600
+ error: error?.message || String(error),
15601
+ failureKind: getWriteConflictOwnerClientId(error) ? "write_conflict" : "request_failed",
15602
+ conflictOwnerClientId: getWriteConflictOwnerClientId(error)
15603
+ }
15604
+ });
15605
+ throw error;
15606
+ }
15607
+ }
15193
15608
  /**
15194
15609
  * Unified command routing.
15195
15610
  * Returns result for all commands:
@@ -15299,44 +15714,60 @@ var DaemonCommandRouter = class {
15299
15714
  }
15300
15715
  case "session_host_get_diagnostics": {
15301
15716
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15302
- const diagnostics = await this.deps.sessionHostControl.getDiagnostics({
15717
+ const diagnostics = await this.traceSessionHostAction("session_host_get_diagnostics", args, () => this.deps.sessionHostControl.getDiagnostics({
15303
15718
  includeSessions: args?.includeSessions !== false,
15304
15719
  limit: Number(args?.limit) || void 0
15305
- });
15720
+ }), (result) => ({
15721
+ includeSessions: args?.includeSessions !== false,
15722
+ limit: Number(args?.limit) || void 0,
15723
+ ...summarizeSessionHostDiagnostics(result)
15724
+ }));
15306
15725
  return { success: true, diagnostics };
15307
15726
  }
15308
15727
  case "session_host_list_sessions": {
15309
15728
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15310
- const sessions = await this.deps.sessionHostControl.listSessions();
15729
+ const sessions = await this.traceSessionHostAction("session_host_list_sessions", args, () => this.deps.sessionHostControl.listSessions(), (records) => summarizeSessionHostRecords(records));
15311
15730
  return { success: true, sessions };
15312
15731
  }
15313
15732
  case "session_host_stop_session": {
15314
15733
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15315
15734
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15316
15735
  if (!sessionId) return { success: false, error: "sessionId required" };
15317
- const record = await this.deps.sessionHostControl.stopSession(sessionId);
15736
+ const record = await this.traceSessionHostAction("session_host_stop_session", args, () => this.deps.sessionHostControl.stopSession(sessionId), (result) => summarizeSessionHostRecord(result));
15318
15737
  return { success: true, record };
15319
15738
  }
15320
15739
  case "session_host_resume_session": {
15321
15740
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15322
15741
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15323
15742
  if (!sessionId) return { success: false, error: "sessionId required" };
15324
- const record = await this.deps.sessionHostControl.resumeSession(sessionId);
15325
- const hosted = toHostedCliRuntimeDescriptor(record);
15326
- if (hosted) {
15327
- await this.deps.cliManager.restoreHostedSessions([hosted]);
15328
- }
15743
+ const record = await this.traceSessionHostAction("session_host_resume_session", args, async () => {
15744
+ const nextRecord = await this.deps.sessionHostControl.resumeSession(sessionId);
15745
+ const hosted = toHostedCliRuntimeDescriptor(nextRecord);
15746
+ if (hosted) {
15747
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
15748
+ }
15749
+ return nextRecord;
15750
+ }, (result) => ({
15751
+ ...summarizeSessionHostRecord(result),
15752
+ restoredHostedSession: !!toHostedCliRuntimeDescriptor(result)
15753
+ }));
15329
15754
  return { success: true, record };
15330
15755
  }
15331
15756
  case "session_host_restart_session": {
15332
15757
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15333
15758
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15334
15759
  if (!sessionId) return { success: false, error: "sessionId required" };
15335
- const record = await this.deps.sessionHostControl.restartSession(sessionId);
15336
- const hosted = toHostedCliRuntimeDescriptor(record);
15337
- if (hosted) {
15338
- await this.deps.cliManager.restoreHostedSessions([hosted]);
15339
- }
15760
+ const record = await this.traceSessionHostAction("session_host_restart_session", args, async () => {
15761
+ const nextRecord = await this.deps.sessionHostControl.restartSession(sessionId);
15762
+ const hosted = toHostedCliRuntimeDescriptor(nextRecord);
15763
+ if (hosted) {
15764
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
15765
+ }
15766
+ return nextRecord;
15767
+ }, (result) => ({
15768
+ ...summarizeSessionHostRecord(result),
15769
+ restoredHostedSession: !!toHostedCliRuntimeDescriptor(result)
15770
+ }));
15340
15771
  return { success: true, record };
15341
15772
  }
15342
15773
  case "session_host_send_signal": {
@@ -15345,7 +15776,7 @@ var DaemonCommandRouter = class {
15345
15776
  const signal = typeof args?.signal === "string" ? args.signal : "";
15346
15777
  if (!sessionId) return { success: false, error: "sessionId required" };
15347
15778
  if (!signal) return { success: false, error: "signal required" };
15348
- const record = await this.deps.sessionHostControl.sendSignal(sessionId, signal);
15779
+ const record = await this.traceSessionHostAction("session_host_send_signal", args, () => this.deps.sessionHostControl.sendSignal(sessionId, signal), (result) => summarizeSessionHostRecord(result));
15349
15780
  return { success: true, record };
15350
15781
  }
15351
15782
  case "session_host_force_detach_client": {
@@ -15354,16 +15785,16 @@ var DaemonCommandRouter = class {
15354
15785
  const clientId = typeof args?.clientId === "string" ? args.clientId : "";
15355
15786
  if (!sessionId) return { success: false, error: "sessionId required" };
15356
15787
  if (!clientId) return { success: false, error: "clientId required" };
15357
- const record = await this.deps.sessionHostControl.forceDetachClient(sessionId, clientId);
15788
+ const record = await this.traceSessionHostAction("session_host_force_detach_client", args, () => this.deps.sessionHostControl.forceDetachClient(sessionId, clientId), (result) => summarizeSessionHostRecord(result));
15358
15789
  return { success: true, record };
15359
15790
  }
15360
15791
  case "session_host_prune_duplicate_sessions": {
15361
15792
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15362
- const result = await this.deps.sessionHostControl.pruneDuplicateSessions({
15793
+ const result = await this.traceSessionHostAction("session_host_prune_duplicate_sessions", args, () => this.deps.sessionHostControl.pruneDuplicateSessions({
15363
15794
  providerType: typeof args?.providerType === "string" ? args.providerType : void 0,
15364
15795
  workspace: typeof args?.workspace === "string" ? args.workspace : void 0,
15365
15796
  dryRun: args?.dryRun === true
15366
- });
15797
+ }), (value) => summarizeSessionHostPruneResult(value));
15367
15798
  return { success: true, result };
15368
15799
  }
15369
15800
  case "session_host_acquire_write": {
@@ -15373,12 +15804,15 @@ var DaemonCommandRouter = class {
15373
15804
  const ownerType = args?.ownerType === "agent" ? "agent" : "user";
15374
15805
  if (!sessionId) return { success: false, error: "sessionId required" };
15375
15806
  if (!clientId) return { success: false, error: "clientId required" };
15376
- const record = await this.deps.sessionHostControl.acquireWrite({
15807
+ const record = await this.traceSessionHostAction("session_host_acquire_write", args, () => this.deps.sessionHostControl.acquireWrite({
15377
15808
  sessionId,
15378
15809
  clientId,
15379
15810
  ownerType,
15380
15811
  force: args?.force !== false
15381
- });
15812
+ }), (result) => ({
15813
+ ...summarizeSessionHostRecord(result),
15814
+ ownerType
15815
+ }));
15382
15816
  return { success: true, record };
15383
15817
  }
15384
15818
  case "session_host_release_write": {
@@ -15387,7 +15821,10 @@ var DaemonCommandRouter = class {
15387
15821
  const clientId = typeof args?.clientId === "string" ? args.clientId : "";
15388
15822
  if (!sessionId) return { success: false, error: "sessionId required" };
15389
15823
  if (!clientId) return { success: false, error: "clientId required" };
15390
- const record = await this.deps.sessionHostControl.releaseWrite({ sessionId, clientId });
15824
+ const record = await this.traceSessionHostAction("session_host_release_write", args, () => this.deps.sessionHostControl.releaseWrite({
15825
+ sessionId,
15826
+ clientId
15827
+ }), (result) => summarizeSessionHostRecord(result));
15391
15828
  return { success: true, record };
15392
15829
  }
15393
15830
  case "list_saved_sessions": {
@@ -15420,7 +15857,7 @@ var DaemonCommandRouter = class {
15420
15857
  kind: saved?.kind || recent?.kind || kind,
15421
15858
  title: saved?.title || recent?.title || session.sessionTitle || session.preview || providerType,
15422
15859
  workspace: saved?.workspace || recent?.workspace || session.workspace,
15423
- currentModel: saved?.currentModel || recent?.currentModel,
15860
+ summaryMetadata: saved?.summaryMetadata || recent?.summaryMetadata,
15424
15861
  preview: session.preview,
15425
15862
  messageCount: session.messageCount,
15426
15863
  firstMessageAt: session.firstMessageAt,
@@ -15859,7 +16296,7 @@ var DaemonStatusReporter = class {
15859
16296
  const ideSummary = ideStates.map((s) => {
15860
16297
  const msgs = s.activeChat?.messages?.length || 0;
15861
16298
  const exts = s.extensions.length;
15862
- return `${s.type}(${s.status},${msgs}msg,${exts}ext${s.currentModel ? ",model=" + s.currentModel : ""})`;
16299
+ return `${s.type}(${s.status},${msgs}msg,${exts}ext)`;
15863
16300
  }).join(", ");
15864
16301
  const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
15865
16302
  const acpSummary = acpStates.map((s) => `${s.type}(${s.status})`).join(", ");
@@ -15921,9 +16358,7 @@ var DaemonStatusReporter = class {
15921
16358
  workspace: session.workspace ?? null,
15922
16359
  title: session.title,
15923
16360
  cdpConnected: session.cdpConnected,
15924
- currentModel: session.currentModel,
15925
- currentPlan: session.currentPlan,
15926
- currentAutoApprove: session.currentAutoApprove
16361
+ summaryMetadata: session.summaryMetadata
15927
16362
  })),
15928
16363
  p2p: payload.p2p,
15929
16364
  timestamp: now
@@ -16089,15 +16524,18 @@ var ProviderStreamAdapter = class {
16089
16524
  status: data.status || "idle",
16090
16525
  messages: data.messages || [],
16091
16526
  inputContent: data.inputContent || "",
16092
- model: data.model,
16093
- mode: data.mode,
16094
16527
  activeModal: data.activeModal
16095
16528
  };
16096
16529
  if (typeof data.title === "string" && data.title.trim()) {
16097
16530
  state.title = data.title.trim();
16098
16531
  }
16099
16532
  const controlValues = extractProviderControlValues(this.provider.controls, data);
16100
- if (controlValues) state.controlValues = controlValues;
16533
+ const surface = resolveProviderStateSurface({
16534
+ controlValues,
16535
+ summaryMetadata: data.summaryMetadata
16536
+ });
16537
+ if (surface.controlValues) state.controlValues = surface.controlValues;
16538
+ if (surface.summaryMetadata) state.summaryMetadata = surface.summaryMetadata;
16101
16539
  const effects = normalizeProviderEffects(data);
16102
16540
  if (effects.length > 0) state.effects = effects;
16103
16541
  if (state.messages.length > 0) {
@@ -16371,7 +16809,8 @@ var DaemonAgentStreamManager = class {
16371
16809
  const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
16372
16810
  const state = await agent.adapter.readChat(evaluate);
16373
16811
  const stateError = this.getStateError(state);
16374
- 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) : ""}`);
16812
+ const selectedModelValue = typeof state.controlValues?.model === "string" ? state.controlValues.model : "";
16813
+ LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${selectedModelValue}${state.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
16375
16814
  if (state.status === "error" && this.isRecoverableSessionError(stateError)) {
16376
16815
  throw new Error(stateError);
16377
16816
  }
@@ -16719,9 +17158,8 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
16719
17158
  messages: stream.messages || [],
16720
17159
  status: stream.status || "idle",
16721
17160
  activeModal: stream.activeModal || null,
16722
- model: stream.model || void 0,
16723
- mode: stream.mode || void 0,
16724
17161
  controlValues: stream.controlValues || void 0,
17162
+ summaryMetadata: stream.summaryMetadata || void 0,
16725
17163
  effects: stream.effects || void 0,
16726
17164
  sessionId: stream.sessionId || stream.instanceId || void 0,
16727
17165
  title: stream.title || stream.agentName || void 0,
@@ -17257,7 +17695,11 @@ module.exports.setMode = (params) => {
17257
17695
  * 5. Approval dialog detection (buttons, modal)
17258
17696
  * 6. Input field selector
17259
17697
  *
17260
- * \u2192 { id, status, title, messages[], inputContent, activeModal }
17698
+ * Preferred live-state surface:
17699
+ * - controlValues: explicit current control selections (model/mode/etc.)
17700
+ * - summaryMetadata: compact always-visible metadata for dashboard/recent views
17701
+ * Legacy top-level model/mode output is no longer the preferred shape.
17702
+ * \u2192 { id, status, title, messages[], inputContent, activeModal, controlValues?, summaryMetadata? }
17261
17703
  */
17262
17704
  (() => {
17263
17705
  try {
@@ -17285,6 +17727,9 @@ module.exports.setMode = (params) => {
17285
17727
  messages,
17286
17728
  inputContent,
17287
17729
  activeModal,
17730
+ // TODO: Return explicit selections when available, e.g.
17731
+ // controlValues: { model: selectedModel, mode: selectedMode },
17732
+ // summaryMetadata: { items: [{ id: 'model', value: selectedModelLabel || selectedModel, shortValue: selectedModel, order: 10 }] },
17288
17733
  });
17289
17734
  } catch(e) {
17290
17735
  return JSON.stringify({ id: '', status: 'error', messages: [], error: e.message });
@@ -19025,7 +19470,6 @@ async function handleCliStatus(ctx, _req, res) {
19025
19470
  lastMessage: s.activeChat?.messages?.slice(-1)[0] || null,
19026
19471
  activeModal: s.activeChat?.activeModal || null,
19027
19472
  pendingEvents: s.pendingEvents || [],
19028
- currentModel: s.currentModel,
19029
19473
  settings: s.settings
19030
19474
  }));
19031
19475
  ctx.json(res, 200, { instances: result, count: result.length });
@@ -20182,7 +20626,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
20182
20626
  lines.push("## Required Return Format");
20183
20627
  lines.push("| Function | Return JSON |");
20184
20628
  lines.push("|---|---|");
20185
- 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 |");
20629
+ 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 |");
20186
20630
  lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
20187
20631
  lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
20188
20632
  lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
@@ -21817,7 +22261,7 @@ var DevServer = class _DevServer {
21817
22261
  lines.push("## Required Return Format");
21818
22262
  lines.push("| Function | Return JSON |");
21819
22263
  lines.push("|---|---|");
21820
- 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 |");
22264
+ 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 |");
21821
22265
  lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
21822
22266
  lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
21823
22267
  lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
@@ -22723,61 +23167,6 @@ async function listHostedCliRuntimes(endpoint) {
22723
23167
  }
22724
23168
  }
22725
23169
 
22726
- // src/session-host/runtime-surface.ts
22727
- var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
22728
- function isSessionHostLiveRuntime(record) {
22729
- const lifecycle = String(record?.lifecycle || "").trim();
22730
- return LIVE_LIFECYCLES.has(lifecycle);
22731
- }
22732
- function getSessionHostRecoveryLabel(meta) {
22733
- const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
22734
- if (!recoveryState) return null;
22735
- if (recoveryState === "auto_resumed") return "restored after restart";
22736
- if (recoveryState === "resume_failed") return "restore failed";
22737
- if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
22738
- if (recoveryState === "orphan_snapshot") return "snapshot recovered";
22739
- return recoveryState.replace(/_/g, " ");
22740
- }
22741
- function isSessionHostRecoverySnapshot(record) {
22742
- if (!record) return false;
22743
- if (isSessionHostLiveRuntime(record)) return false;
22744
- const lifecycle = String(record.lifecycle || "").trim();
22745
- if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
22746
- return false;
22747
- }
22748
- const meta = record.meta || void 0;
22749
- if (meta?.restoredFromStorage === true) return true;
22750
- return getSessionHostRecoveryLabel(meta) !== null;
22751
- }
22752
- function getSessionHostSurfaceKind(record) {
22753
- if (isSessionHostLiveRuntime(record)) return "live_runtime";
22754
- if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
22755
- return "inactive_record";
22756
- }
22757
- function partitionSessionHostRecords(records) {
22758
- const liveRuntimes = [];
22759
- const recoverySnapshots = [];
22760
- const inactiveRecords = [];
22761
- for (const record of records) {
22762
- const kind = getSessionHostSurfaceKind(record);
22763
- if (kind === "live_runtime") {
22764
- liveRuntimes.push(record);
22765
- } else if (kind === "recovery_snapshot") {
22766
- recoverySnapshots.push(record);
22767
- } else {
22768
- inactiveRecords.push(record);
22769
- }
22770
- }
22771
- return {
22772
- liveRuntimes,
22773
- recoverySnapshots,
22774
- inactiveRecords
22775
- };
22776
- }
22777
- function partitionSessionHostDiagnosticsSessions(records) {
22778
- return partitionSessionHostRecords(records || []);
22779
- }
22780
-
22781
23170
  // src/session-host/startup-restore-policy.js
22782
23171
  function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
22783
23172
  const raw = typeof env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";