@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.mjs CHANGED
@@ -1417,6 +1417,7 @@ var init_provider_cli_adapter = __esm({
1417
1417
  static MAX_TRACE_ENTRIES = 250;
1418
1418
  providerResolutionMeta;
1419
1419
  static IDLE_FINISH_CONFIRM_MS = 2e3;
1420
+ static HERMES_IDLE_FINISH_CONFIRM_MS = 5e3;
1420
1421
  static STATUS_ACTIVITY_HOLD_MS = 2e3;
1421
1422
  static FINISH_RETRY_DELAY_MS = 300;
1422
1423
  static MAX_FINISH_RETRIES = 2;
@@ -1424,6 +1425,12 @@ var init_provider_cli_adapter = __esm({
1424
1425
  this.messages = [...this.committedMessages];
1425
1426
  this.structuredMessages = [...this.committedMessages];
1426
1427
  }
1428
+ getIdleFinishConfirmMs() {
1429
+ return this.cliType === "hermes-cli" ? _ProviderCliAdapter.HERMES_IDLE_FINISH_CONFIRM_MS : _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS;
1430
+ }
1431
+ getStatusActivityHoldMs() {
1432
+ return this.cliType === "hermes-cli" ? _ProviderCliAdapter.HERMES_IDLE_FINISH_CONFIRM_MS : _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
1433
+ }
1427
1434
  setStatus(status, trigger) {
1428
1435
  const prev = this.currentStatus;
1429
1436
  if (prev === status) return;
@@ -1446,6 +1453,7 @@ var init_provider_cli_adapter = __esm({
1446
1453
  }
1447
1454
  armIdleFinishCandidate(assistantLength) {
1448
1455
  const now = Date.now();
1456
+ const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
1449
1457
  this.idleFinishCandidate = {
1450
1458
  armedAt: now,
1451
1459
  lastOutputAt: this.lastOutputAt,
@@ -1454,7 +1462,7 @@ var init_provider_cli_adapter = __esm({
1454
1462
  assistantLength
1455
1463
  };
1456
1464
  this.recordTrace("idle_candidate_armed", {
1457
- confirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
1465
+ confirmMs: idleFinishConfirmMs,
1458
1466
  candidate: this.idleFinishCandidate,
1459
1467
  ...buildCliTraceParseSnapshot({
1460
1468
  accumulatedBuffer: this.accumulatedBuffer,
@@ -1469,7 +1477,7 @@ var init_provider_cli_adapter = __esm({
1469
1477
  this.settleTimer = null;
1470
1478
  this.settledBuffer = this.recentOutputBuffer;
1471
1479
  this.evaluateSettled();
1472
- }, _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS);
1480
+ }, idleFinishConfirmMs);
1473
1481
  }
1474
1482
  recordTrace(type, payload = {}) {
1475
1483
  const entry = {
@@ -1848,7 +1856,8 @@ var init_provider_cli_adapter = __esm({
1848
1856
  hasRecentInteractiveActivity(now) {
1849
1857
  const quietForMs = this.lastNonEmptyOutputAt ? now - this.lastNonEmptyOutputAt : Number.MAX_SAFE_INTEGER;
1850
1858
  const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : Number.MAX_SAFE_INTEGER;
1851
- return quietForMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS || screenStableMs < _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
1859
+ const holdMs = this.getStatusActivityHoldMs();
1860
+ return quietForMs < holdMs || screenStableMs < holdMs;
1852
1861
  }
1853
1862
  getStartupConfirmationModal(screenText) {
1854
1863
  const text = sanitizeTerminalText(String(screenText || ""));
@@ -2000,6 +2009,7 @@ var init_provider_cli_adapter = __esm({
2000
2009
  clearPendingScriptStatus();
2001
2010
  }
2002
2011
  const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
2012
+ const statusActivityHoldMs = this.getStatusActivityHoldMs();
2003
2013
  const shouldHoldGenerating = scriptStatus === "idle" && this.isWaitingForResponse && !modal && recentInteractiveActivity;
2004
2014
  if (shouldHoldGenerating) {
2005
2015
  this.clearIdleFinishCandidate("hold_generating_recent_activity");
@@ -2015,7 +2025,7 @@ var init_provider_cli_adapter = __esm({
2015
2025
  recentInteractiveActivity,
2016
2026
  lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
2017
2027
  lastScreenChangeAt: this.lastScreenChangeAt,
2018
- holdMs: _ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS,
2028
+ holdMs: statusActivityHoldMs,
2019
2029
  ...buildCliTraceParseSnapshot({
2020
2030
  accumulatedBuffer: this.accumulatedBuffer,
2021
2031
  accumulatedRawBuffer: this.accumulatedRawBuffer,
@@ -2104,11 +2114,12 @@ var init_provider_cli_adapter = __esm({
2104
2114
  const screenStableMs = this.lastScreenChangeAt ? now - this.lastScreenChangeAt : 0;
2105
2115
  const hasAssistantTurn = !!lastParsedAssistant;
2106
2116
  const assistantLength = lastParsedAssistant?.content?.length || 0;
2107
- const idleQuietThresholdMs = Math.max(2e3, this.timeouts.outputSettle);
2108
- const idleStableThresholdMs = 2e3;
2117
+ const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
2118
+ const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
2119
+ const idleStableThresholdMs = idleFinishConfirmMs;
2109
2120
  const idleReady = visibleIdlePrompt && !modal && hasAssistantTurn && quietForMs >= idleQuietThresholdMs && screenStableMs >= idleStableThresholdMs;
2110
2121
  const candidate = this.idleFinishCandidate;
2111
- 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;
2122
+ const candidateQuiet = !!candidate && candidate.responseEpoch === this.responseEpoch && candidate.lastOutputAt === this.lastOutputAt && candidate.lastScreenChangeAt === this.lastScreenChangeAt && assistantLength >= candidate.assistantLength && now - candidate.armedAt >= idleFinishConfirmMs;
2112
2123
  const canFinishImmediately = idleReady && candidateQuiet;
2113
2124
  this.recordTrace("idle_decision", {
2114
2125
  visibleIdlePrompt,
@@ -2120,7 +2131,7 @@ var init_provider_cli_adapter = __esm({
2120
2131
  idleQuietThresholdMs,
2121
2132
  idleStableThresholdMs,
2122
2133
  idleReady,
2123
- idleFinishConfirmMs: _ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
2134
+ idleFinishConfirmMs,
2124
2135
  idleFinishCandidate: candidate,
2125
2136
  candidateQuiet,
2126
2137
  canFinishImmediately,
@@ -3175,6 +3186,70 @@ function setDefaultWorkspaceId(config, id) {
3175
3186
 
3176
3187
  // src/config/recent-activity.ts
3177
3188
  import * as path2 from "path";
3189
+
3190
+ // src/providers/summary-metadata.ts
3191
+ function normalizeSummaryItem(item) {
3192
+ if (!item || typeof item !== "object") return null;
3193
+ const id = String(item.id || "").trim();
3194
+ const value = String(item.value || "").trim();
3195
+ if (!id || !value) return null;
3196
+ const normalized = {
3197
+ id,
3198
+ value
3199
+ };
3200
+ if (typeof item.label === "string" && item.label.trim()) normalized.label = item.label.trim();
3201
+ if (typeof item.shortValue === "string" && item.shortValue.trim()) normalized.shortValue = item.shortValue.trim();
3202
+ if (typeof item.icon === "string" && item.icon.trim()) normalized.icon = item.icon.trim();
3203
+ if (typeof item.order === "number" && Number.isFinite(item.order)) normalized.order = item.order;
3204
+ return normalized;
3205
+ }
3206
+ function normalizeProviderSummaryMetadata(summary) {
3207
+ if (!summary || !Array.isArray(summary.items)) return void 0;
3208
+ const items = summary.items.map((item) => normalizeSummaryItem(item)).filter((item) => !!item).sort((left, right) => {
3209
+ const orderDiff = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
3210
+ if (orderDiff !== 0) return orderDiff;
3211
+ return left.id.localeCompare(right.id);
3212
+ });
3213
+ return items.length > 0 ? { items } : void 0;
3214
+ }
3215
+ function buildProviderSummaryMetadata(items) {
3216
+ return normalizeProviderSummaryMetadata({ items: items.filter(Boolean) });
3217
+ }
3218
+ function buildLegacyModelModeSummaryMetadata(params) {
3219
+ return buildProviderSummaryMetadata([
3220
+ params.model ? {
3221
+ id: "model",
3222
+ label: "Model",
3223
+ value: String(params.modelLabel || params.model).trim(),
3224
+ shortValue: String(params.model).trim(),
3225
+ order: 10
3226
+ } : null,
3227
+ params.mode ? {
3228
+ id: "mode",
3229
+ label: "Mode",
3230
+ value: String(params.modeLabel || params.mode).trim(),
3231
+ shortValue: String(params.mode).trim(),
3232
+ order: 20
3233
+ } : null
3234
+ ]);
3235
+ }
3236
+ function resolveProviderStateSummaryMetadata(params) {
3237
+ const explicit = normalizeProviderSummaryMetadata(params.summaryMetadata);
3238
+ if (explicit) return explicit;
3239
+ const model = typeof params.controlValues?.model === "string" ? params.controlValues.model : void 0;
3240
+ const mode = typeof params.controlValues?.mode === "string" ? params.controlValues.mode : void 0;
3241
+ return buildLegacyModelModeSummaryMetadata({
3242
+ model,
3243
+ mode,
3244
+ modelLabel: params.modelLabel,
3245
+ modeLabel: params.modeLabel
3246
+ });
3247
+ }
3248
+ function normalizePersistedSummaryMetadata(params) {
3249
+ return normalizeProviderSummaryMetadata(params.summaryMetadata);
3250
+ }
3251
+
3252
+ // src/config/recent-activity.ts
3178
3253
  var MAX_ACTIVITY = 30;
3179
3254
  function normalizeWorkspace(workspace) {
3180
3255
  if (!workspace) return "";
@@ -3198,6 +3273,9 @@ function appendRecentActivity(state, entry) {
3198
3273
  const nextEntry = {
3199
3274
  ...entry,
3200
3275
  workspace: entry.workspace ? normalizeWorkspace(entry.workspace) : void 0,
3276
+ summaryMetadata: normalizePersistedSummaryMetadata({
3277
+ summaryMetadata: entry.summaryMetadata
3278
+ }),
3201
3279
  id: buildRecentActivityKeyForEntry(entry),
3202
3280
  lastUsedAt: entry.lastUsedAt || Date.now()
3203
3281
  };
@@ -3208,7 +3286,12 @@ function appendRecentActivity(state, entry) {
3208
3286
  };
3209
3287
  }
3210
3288
  function getRecentActivity(state, limit = 20) {
3211
- return [...state.recentActivity || []].sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
3289
+ return [...state.recentActivity || []].map((entry) => ({
3290
+ ...entry,
3291
+ summaryMetadata: normalizePersistedSummaryMetadata({
3292
+ summaryMetadata: entry.summaryMetadata
3293
+ })
3294
+ })).sort((a, b) => b.lastUsedAt - a.lastUsedAt).slice(0, limit);
3212
3295
  }
3213
3296
  function getSessionSeenAt(state, sessionId) {
3214
3297
  return state.sessionReads?.[sessionId] || 0;
@@ -3260,7 +3343,9 @@ function upsertSavedProviderSession(state, entry) {
3260
3343
  providerName: entry.providerName,
3261
3344
  providerSessionId,
3262
3345
  workspace: entry.workspace ? normalizeWorkspace2(entry.workspace) : void 0,
3263
- currentModel: entry.currentModel,
3346
+ summaryMetadata: normalizePersistedSummaryMetadata({
3347
+ summaryMetadata: entry.summaryMetadata
3348
+ }),
3264
3349
  title: entry.title,
3265
3350
  createdAt: existing?.createdAt || entry.createdAt || Date.now(),
3266
3351
  lastUsedAt: entry.lastUsedAt || Date.now()
@@ -3276,7 +3361,12 @@ function getSavedProviderSessions(state, filters) {
3276
3361
  if (filters?.providerType && entry.providerType !== filters.providerType) return false;
3277
3362
  if (filters?.kind && entry.kind !== filters.kind) return false;
3278
3363
  return true;
3279
- }).sort((a, b) => b.lastUsedAt - a.lastUsedAt);
3364
+ }).map((entry) => ({
3365
+ ...entry,
3366
+ summaryMetadata: normalizePersistedSummaryMetadata({
3367
+ summaryMetadata: entry.summaryMetadata
3368
+ })
3369
+ })).sort((a, b) => b.lastUsedAt - a.lastUsedAt);
3280
3370
  }
3281
3371
 
3282
3372
  // src/config/state-store.ts
@@ -5033,8 +5123,6 @@ function extractProviderControlValues(controls, data) {
5033
5123
  if (rawValue === void 0 || rawValue === null) continue;
5034
5124
  values[ctrl.id] = normalizeControlValue(rawValue);
5035
5125
  }
5036
- if (data.model !== void 0 && values.model === void 0) values.model = normalizeControlValue(data.model);
5037
- if (data.mode !== void 0 && values.mode === void 0) values.mode = normalizeControlValue(data.mode);
5038
5126
  return Object.keys(values).length > 0 ? values : void 0;
5039
5127
  }
5040
5128
  function normalizeProviderEffects(data) {
@@ -5136,7 +5224,7 @@ function normalizeControlOption(option) {
5136
5224
  }
5137
5225
  if (!option || typeof option !== "object") return null;
5138
5226
  const record = option;
5139
- const value = typeof record.value === "string" ? record.value : typeof record.id === "string" ? record.id : null;
5227
+ const value = typeof record.value === "string" ? record.value : typeof record.id === "string" ? record.id : typeof record.name === "string" ? record.name : null;
5140
5228
  if (!value) return null;
5141
5229
  const label = typeof record.label === "string" ? record.label : typeof record.name === "string" ? record.name : value;
5142
5230
  const normalized = { value, label };
@@ -5671,6 +5759,61 @@ function listSavedHistorySessions(agentType, options = {}) {
5671
5759
  }
5672
5760
  }
5673
5761
 
5762
+ // src/providers/provider-patch-state.ts
5763
+ function isControlValue(value) {
5764
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
5765
+ }
5766
+ function asControlValueMap(value) {
5767
+ if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
5768
+ const result = {};
5769
+ for (const [entryKey, entryValue] of Object.entries(value)) {
5770
+ if (isControlValue(entryValue)) result[entryKey] = entryValue;
5771
+ }
5772
+ return Object.keys(result).length > 0 ? result : void 0;
5773
+ }
5774
+ function getLegacyModelModeValues(data) {
5775
+ if (!data || typeof data !== "object") return void 0;
5776
+ const legacy = {};
5777
+ if (typeof data.model === "string" && data.model.trim()) legacy.model = data.model.trim();
5778
+ if (typeof data.mode === "string" && data.mode.trim()) legacy.mode = data.mode.trim();
5779
+ return Object.keys(legacy).length > 0 ? legacy : void 0;
5780
+ }
5781
+ function mergeProviderPatchState(params) {
5782
+ const {
5783
+ providerControls,
5784
+ data,
5785
+ currentControlValues,
5786
+ currentSummaryMetadata,
5787
+ mergeWithCurrent = true
5788
+ } = params;
5789
+ const sources = [
5790
+ mergeWithCurrent ? asControlValueMap(currentControlValues) : void 0,
5791
+ asControlValueMap(data?.controlValues),
5792
+ asControlValueMap(extractProviderControlValues(providerControls, data)),
5793
+ getLegacyModelModeValues(data)
5794
+ ];
5795
+ const controlValues = Object.assign({}, ...sources.filter(Boolean));
5796
+ return {
5797
+ controlValues,
5798
+ summaryMetadata: data?.summaryMetadata !== void 0 ? data.summaryMetadata : currentSummaryMetadata
5799
+ };
5800
+ }
5801
+ function normalizeProviderStateControlValues(controlValues) {
5802
+ return controlValues && Object.keys(controlValues).length > 0 ? controlValues : void 0;
5803
+ }
5804
+ function resolveProviderStateSurface(params) {
5805
+ const controlValues = normalizeProviderStateControlValues(params.controlValues);
5806
+ return {
5807
+ controlValues,
5808
+ summaryMetadata: resolveProviderStateSummaryMetadata({
5809
+ summaryMetadata: params.summaryMetadata,
5810
+ controlValues,
5811
+ modelLabel: params.modelLabel,
5812
+ modeLabel: params.modeLabel
5813
+ })
5814
+ };
5815
+ }
5816
+
5674
5817
  // src/providers/extension-provider-instance.ts
5675
5818
  var ExtensionProviderInstance = class {
5676
5819
  type;
@@ -5685,9 +5828,8 @@ var ExtensionProviderInstance = class {
5685
5828
  messages = [];
5686
5829
  prevMessageHashes = /* @__PURE__ */ new Map();
5687
5830
  activeModal = null;
5688
- currentModel = "";
5689
- currentMode = "";
5690
5831
  controlValues = {};
5832
+ summaryMetadata = void 0;
5691
5833
  appliedEffectKeys = /* @__PURE__ */ new Set();
5692
5834
  runtimeMessages = [];
5693
5835
  lastAgentStatus = "idle";
@@ -5722,6 +5864,10 @@ var ExtensionProviderInstance = class {
5722
5864
  if (!this.context?.cdp?.isConnected) return;
5723
5865
  }
5724
5866
  getState() {
5867
+ const surface = resolveProviderStateSurface({
5868
+ summaryMetadata: this.summaryMetadata,
5869
+ controlValues: this.controlValues
5870
+ });
5725
5871
  return {
5726
5872
  type: this.type,
5727
5873
  name: this.provider.name,
@@ -5735,10 +5881,9 @@ var ExtensionProviderInstance = class {
5735
5881
  activeModal: this.activeModal,
5736
5882
  inputContent: ""
5737
5883
  } : null,
5738
- currentModel: this.currentModel || void 0,
5739
- currentPlan: this.currentMode || void 0,
5740
- controlValues: this.controlValues,
5884
+ controlValues: surface.controlValues,
5741
5885
  providerControls: this.provider.controls,
5886
+ summaryMetadata: surface.summaryMetadata,
5742
5887
  agentStreams: this.agentStreams,
5743
5888
  instanceId: this.instanceId,
5744
5889
  lastUpdated: Date.now(),
@@ -5751,10 +5896,14 @@ var ExtensionProviderInstance = class {
5751
5896
  if (data?.streams) this.agentStreams = data.streams;
5752
5897
  if (data?.messages) this.messages = this.assignReceivedAt(data.messages);
5753
5898
  if (data?.activeModal !== void 0) this.activeModal = data.activeModal;
5754
- if (data?.model) this.currentModel = data.model;
5755
- if (data?.mode) this.currentMode = data.mode;
5756
- const controlValues = extractProviderControlValues(this.provider.controls, data) || data?.controlValues;
5757
- if (controlValues) this.controlValues = controlValues;
5899
+ const patchedState = mergeProviderPatchState({
5900
+ providerControls: this.provider.controls,
5901
+ data,
5902
+ currentControlValues: this.controlValues,
5903
+ currentSummaryMetadata: this.summaryMetadata
5904
+ });
5905
+ this.controlValues = patchedState.controlValues;
5906
+ this.summaryMetadata = patchedState.summaryMetadata;
5758
5907
  if (typeof data?.sessionId === "string" && data.sessionId.trim()) this.chatId = data.sessionId;
5759
5908
  if (typeof data?.title === "string" && data.title.trim()) this.chatTitle = data.title;
5760
5909
  if (typeof data?.agentName === "string" && data.agentName.trim()) this.agentName = data.agentName;
@@ -5855,8 +6004,14 @@ var ExtensionProviderInstance = class {
5855
6004
  }
5856
6005
  applyProviderResponse(data, options) {
5857
6006
  if (!data || typeof data !== "object") return;
5858
- const controlValues = extractProviderControlValues(this.provider.controls, data);
5859
- if (controlValues) this.controlValues = { ...this.controlValues, ...controlValues };
6007
+ const patchedState = mergeProviderPatchState({
6008
+ providerControls: this.provider.controls,
6009
+ data,
6010
+ currentControlValues: this.controlValues,
6011
+ currentSummaryMetadata: this.summaryMetadata
6012
+ });
6013
+ this.controlValues = patchedState.controlValues;
6014
+ this.summaryMetadata = patchedState.summaryMetadata;
5860
6015
  const effects = normalizeProviderEffects(data);
5861
6016
  for (const effect of effects) {
5862
6017
  const effectWhen = effect.when || "immediate";
@@ -6006,8 +6161,6 @@ ${effect.notification.body || ""}`.trim();
6006
6161
  this.messages = [];
6007
6162
  this.prevMessageHashes.clear();
6008
6163
  this.activeModal = null;
6009
- this.currentModel = "";
6010
- this.currentMode = "";
6011
6164
  this.controlValues = {};
6012
6165
  this.currentStatus = "idle";
6013
6166
  this.chatId = null;
@@ -6143,6 +6296,10 @@ var IdeProviderInstance = class {
6143
6296
  for (const ext of this.extensions.values()) {
6144
6297
  extensionStates.push(ext.getState());
6145
6298
  }
6299
+ const surface = resolveProviderStateSurface({
6300
+ summaryMetadata: this.cachedChat?.summaryMetadata,
6301
+ controlValues: this.cachedChat?.controlValues
6302
+ });
6146
6303
  return {
6147
6304
  type: this.type,
6148
6305
  name: this.provider.name,
@@ -6159,11 +6316,9 @@ var IdeProviderInstance = class {
6159
6316
  workspace: this.workspace || null,
6160
6317
  extensions: extensionStates,
6161
6318
  cdpConnected: cdp?.isConnected || false,
6162
- currentModel: this.cachedChat?.model || void 0,
6163
- currentPlan: this.cachedChat?.mode || void 0,
6164
- currentAutoApprove: this.cachedChat?.autoApprove || void 0,
6165
- controlValues: this.cachedChat?.controlValues || void 0,
6319
+ controlValues: surface.controlValues,
6166
6320
  providerControls: this.provider.controls,
6321
+ summaryMetadata: surface.summaryMetadata,
6167
6322
  instanceId: this.instanceId,
6168
6323
  lastUpdated: Date.now(),
6169
6324
  settings: this.settings,
@@ -6335,8 +6490,13 @@ var IdeProviderInstance = class {
6335
6490
  chat.messages = messages.filter((m) => !hiddenKinds.has(m.kind || ""));
6336
6491
  }
6337
6492
  }
6338
- const controlValues = extractProviderControlValues(this.provider.controls, chat);
6339
- if (controlValues) chat.controlValues = controlValues;
6493
+ const patchedState = mergeProviderPatchState({
6494
+ providerControls: this.provider.controls,
6495
+ data: chat,
6496
+ mergeWithCurrent: false
6497
+ });
6498
+ chat.controlValues = Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : void 0;
6499
+ chat.summaryMetadata = patchedState.summaryMetadata;
6340
6500
  this.cachedChat = { ...chat, activeModal };
6341
6501
  this.detectAgentTransitions(chat, now);
6342
6502
  const persistedMessages = chat.messages || messages;
@@ -6423,14 +6583,18 @@ var IdeProviderInstance = class {
6423
6583
  }
6424
6584
  applyProviderResponse(data, options) {
6425
6585
  if (!data || typeof data !== "object") return;
6426
- const controlValues = extractProviderControlValues(this.provider.controls, data);
6427
- if (controlValues) {
6428
- this.cachedChat = {
6429
- ...this.cachedChat || {},
6430
- ...data,
6431
- controlValues: { ...this.cachedChat?.controlValues || {}, ...controlValues }
6432
- };
6433
- }
6586
+ const patchedState = mergeProviderPatchState({
6587
+ providerControls: this.provider.controls,
6588
+ data,
6589
+ currentControlValues: this.cachedChat?.controlValues,
6590
+ currentSummaryMetadata: this.cachedChat?.summaryMetadata
6591
+ });
6592
+ this.cachedChat = {
6593
+ ...this.cachedChat || {},
6594
+ ...data,
6595
+ controlValues: Object.keys(patchedState.controlValues).length > 0 ? patchedState.controlValues : void 0,
6596
+ summaryMetadata: patchedState.summaryMetadata
6597
+ };
6434
6598
  const effects = normalizeProviderEffects(data);
6435
6599
  for (const effect of effects) {
6436
6600
  const effectWhen = effect.when || "immediate";
@@ -7213,6 +7377,8 @@ var ACP_SESSION_CAPABILITIES = [
7213
7377
  function buildIdeWorkspaceSession(state, cdpManagers, options) {
7214
7378
  const profile = options.profile || "full";
7215
7379
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7380
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7381
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7216
7382
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7217
7383
  const includeSessionControls = shouldIncludeSessionControls(profile);
7218
7384
  const title = activeChat?.title || state.name;
@@ -7229,13 +7395,11 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
7229
7395
  title,
7230
7396
  ...includeSessionMetadata && { workspace: state.workspace || null },
7231
7397
  activeChat,
7398
+ ...summaryMetadata && { summaryMetadata },
7232
7399
  ...includeSessionMetadata && { capabilities: IDE_SESSION_CAPABILITIES },
7233
7400
  cdpConnected: state.cdpConnected ?? isCdpConnected(cdpManagers, state.type),
7234
- currentModel: state.currentModel,
7235
- currentPlan: state.currentPlan,
7236
- currentAutoApprove: state.currentAutoApprove,
7237
7401
  ...includeSessionControls && {
7238
- controlValues: state.controlValues,
7402
+ ...controlValues && { controlValues },
7239
7403
  providerControls: state.providerControls
7240
7404
  },
7241
7405
  errorMessage: state.errorMessage,
@@ -7246,6 +7410,8 @@ function buildIdeWorkspaceSession(state, cdpManagers, options) {
7246
7410
  function buildExtensionAgentSession(parent, ext, options) {
7247
7411
  const profile = options.profile || "full";
7248
7412
  const activeChat = normalizeActiveChatData(ext.activeChat, getActiveChatOptions(profile));
7413
+ const summaryMetadata = normalizeProviderSummaryMetadata(ext.summaryMetadata);
7414
+ const controlValues = normalizeProviderStateControlValues(ext.controlValues);
7249
7415
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7250
7416
  const includeSessionControls = shouldIncludeSessionControls(profile);
7251
7417
  return {
@@ -7261,11 +7427,10 @@ function buildExtensionAgentSession(parent, ext, options) {
7261
7427
  title: activeChat?.title || ext.name,
7262
7428
  ...includeSessionMetadata && { workspace: parent.workspace || null },
7263
7429
  activeChat,
7430
+ ...summaryMetadata && { summaryMetadata },
7264
7431
  ...includeSessionMetadata && { capabilities: EXTENSION_SESSION_CAPABILITIES },
7265
- currentModel: ext.currentModel,
7266
- currentPlan: ext.currentPlan,
7267
7432
  ...includeSessionControls && {
7268
- controlValues: ext.controlValues,
7433
+ ...controlValues && { controlValues },
7269
7434
  providerControls: ext.providerControls
7270
7435
  },
7271
7436
  errorMessage: ext.errorMessage,
@@ -7276,6 +7441,8 @@ function buildExtensionAgentSession(parent, ext, options) {
7276
7441
  function buildCliSession(state, options) {
7277
7442
  const profile = options.profile || "full";
7278
7443
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7444
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7445
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7279
7446
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7280
7447
  const includeRuntimeMetadata = shouldIncludeRuntimeMetadata(profile);
7281
7448
  const includeSessionControls = shouldIncludeSessionControls(profile);
@@ -7302,11 +7469,12 @@ function buildCliSession(state, options) {
7302
7469
  mode: state.mode,
7303
7470
  resume: state.resume,
7304
7471
  activeChat,
7472
+ ...summaryMetadata && { summaryMetadata },
7305
7473
  ...includeSessionMetadata && {
7306
7474
  capabilities: state.mode === "terminal" ? PTY_SESSION_CAPABILITIES : CLI_CHAT_SESSION_CAPABILITIES
7307
7475
  },
7308
7476
  ...includeSessionControls && {
7309
- controlValues: state.controlValues,
7477
+ ...controlValues && { controlValues },
7310
7478
  providerControls: state.providerControls
7311
7479
  },
7312
7480
  errorMessage: state.errorMessage,
@@ -7317,6 +7485,8 @@ function buildCliSession(state, options) {
7317
7485
  function buildAcpSession(state, options) {
7318
7486
  const profile = options.profile || "full";
7319
7487
  const activeChat = normalizeActiveChatData(state.activeChat, getActiveChatOptions(profile));
7488
+ const summaryMetadata = normalizeProviderSummaryMetadata(state.summaryMetadata);
7489
+ const controlValues = normalizeProviderStateControlValues(state.controlValues);
7320
7490
  const includeSessionMetadata = shouldIncludeSessionMetadata(profile);
7321
7491
  const includeSessionControls = shouldIncludeSessionControls(profile);
7322
7492
  return {
@@ -7332,13 +7502,10 @@ function buildAcpSession(state, options) {
7332
7502
  title: activeChat?.title || state.name,
7333
7503
  ...includeSessionMetadata && { workspace: state.workspace || null },
7334
7504
  activeChat,
7505
+ ...summaryMetadata && { summaryMetadata },
7335
7506
  ...includeSessionMetadata && { capabilities: ACP_SESSION_CAPABILITIES },
7336
- currentModel: state.currentModel,
7337
- currentPlan: state.currentPlan,
7338
7507
  ...includeSessionControls && {
7339
- acpConfigOptions: state.acpConfigOptions,
7340
- acpModes: state.acpModes,
7341
- controlValues: state.controlValues,
7508
+ ...controlValues && { controlValues },
7342
7509
  providerControls: state.providerControls
7343
7510
  },
7344
7511
  errorMessage: state.errorMessage,
@@ -9398,8 +9565,17 @@ async function handleSetProviderSourceConfig(h, args) {
9398
9565
  );
9399
9566
  return { success: true, reloaded: true, ...sourceConfig };
9400
9567
  }
9401
- function normalizeProviderScriptArgs(args) {
9568
+ function normalizeProviderScriptArgs(args, scriptName) {
9402
9569
  const normalizedArgs = { ...args || {} };
9570
+ const normalizedScriptName = String(scriptName || "").toLowerCase();
9571
+ if (Object.prototype.hasOwnProperty.call(normalizedArgs, "value")) {
9572
+ if (normalizedArgs.model === void 0 && (normalizedScriptName === "setmodel" || normalizedScriptName === "setmodelgui" || normalizedScriptName === "webviewsetmodel")) {
9573
+ normalizedArgs.model = normalizedArgs.value;
9574
+ }
9575
+ if (normalizedArgs.mode === void 0 && (normalizedScriptName === "setmode" || normalizedScriptName === "webviewsetmode")) {
9576
+ normalizedArgs.mode = normalizedArgs.value;
9577
+ }
9578
+ }
9403
9579
  for (const key of ["mode", "model", "message", "action", "button", "text", "sessionId", "value"]) {
9404
9580
  if (key in normalizedArgs && !(key.toUpperCase() in normalizedArgs)) {
9405
9581
  normalizedArgs[key.toUpperCase()] = normalizedArgs[key];
@@ -9445,7 +9621,7 @@ async function executeProviderScript(h, args, scriptName) {
9445
9621
  if (!provider.scripts?.[actualScriptName]) {
9446
9622
  return { success: false, error: `Script '${actualScriptName}' not available for ${resolvedProviderType}` };
9447
9623
  }
9448
- const normalizedArgs = normalizeProviderScriptArgs(args);
9624
+ const normalizedArgs = normalizeProviderScriptArgs(args, actualScriptName);
9449
9625
  if (provider.category === "cli") {
9450
9626
  const adapter = h.getCliAdapter(args?.targetSessionId || resolvedProviderType);
9451
9627
  if (!adapter?.invokeScript) {
@@ -10306,6 +10482,7 @@ var CliProviderInstance = class {
10306
10482
  generatingDebouncePending = null;
10307
10483
  lastApprovalEventAt = 0;
10308
10484
  controlValues = {};
10485
+ summaryMetadata = void 0;
10309
10486
  appliedEffectKeys = /* @__PURE__ */ new Set();
10310
10487
  historyWriter;
10311
10488
  runtimeMessages = [];
@@ -10448,13 +10625,7 @@ var CliProviderInstance = class {
10448
10625
  if (historyMessageCount !== null) {
10449
10626
  parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
10450
10627
  }
10451
- const controlValues = extractProviderControlValues(this.provider.controls, parsedStatus);
10452
- if (controlValues) {
10453
- this.controlValues = { ...this.controlValues, ...controlValues };
10454
- }
10455
10628
  const mergedMessages = this.mergeConversationMessages(parsedMessages);
10456
- 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;
10457
- 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;
10458
10629
  const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
10459
10630
  if (parsedMessages.length > 0) {
10460
10631
  const shouldSkipReplayPersist = this.suppressIdleHistoryReplay && adapterStatus.status === "idle" && parsedStatus?.status === "idle";
@@ -10476,6 +10647,10 @@ var CliProviderInstance = class {
10476
10647
  }
10477
10648
  }
10478
10649
  this.applyProviderResponse(parsedStatus, { phase: "immediate" });
10650
+ const surface = resolveProviderStateSurface({
10651
+ summaryMetadata: this.summaryMetadata,
10652
+ controlValues: this.controlValues
10653
+ });
10479
10654
  return {
10480
10655
  type: this.type,
10481
10656
  name: this.provider.name,
@@ -10491,8 +10666,6 @@ var CliProviderInstance = class {
10491
10666
  inputContent: ""
10492
10667
  },
10493
10668
  workspace: this.workingDir,
10494
- currentModel,
10495
- currentPlan,
10496
10669
  instanceId: this.instanceId,
10497
10670
  providerSessionId: this.providerSessionId,
10498
10671
  lastUpdated: Date.now(),
@@ -10507,8 +10680,9 @@ var CliProviderInstance = class {
10507
10680
  attachedClients: runtime.attachedClients || []
10508
10681
  } : void 0,
10509
10682
  resume: this.provider.resume,
10510
- controlValues: this.controlValues,
10511
- providerControls: this.provider.controls
10683
+ controlValues: surface.controlValues,
10684
+ providerControls: this.provider.controls,
10685
+ summaryMetadata: surface.summaryMetadata
10512
10686
  };
10513
10687
  }
10514
10688
  setPresentationMode(mode) {
@@ -10712,10 +10886,14 @@ var CliProviderInstance = class {
10712
10886
  this.suppressIdleHistoryReplay = false;
10713
10887
  this.adapter.clearHistory();
10714
10888
  }
10715
- const controlValues = extractProviderControlValues(this.provider.controls, data);
10716
- if (controlValues) {
10717
- this.controlValues = { ...this.controlValues, ...controlValues };
10718
- }
10889
+ const patchedState = mergeProviderPatchState({
10890
+ providerControls: this.provider.controls,
10891
+ data,
10892
+ currentControlValues: this.controlValues,
10893
+ currentSummaryMetadata: this.summaryMetadata
10894
+ });
10895
+ this.controlValues = patchedState.controlValues;
10896
+ this.summaryMetadata = patchedState.summaryMetadata;
10719
10897
  const effects = normalizeProviderEffects(data);
10720
10898
  for (const effect of effects) {
10721
10899
  const effectWhen = effect.when || "immediate";
@@ -11086,8 +11264,7 @@ var AcpProviderInstance = class {
11086
11264
  lastStatus = "starting";
11087
11265
  generatingStartedAt = 0;
11088
11266
  agentCapabilities = {};
11089
- currentModel;
11090
- currentMode;
11267
+ currentSelections = {};
11091
11268
  activeToolCalls = [];
11092
11269
  stopReason = null;
11093
11270
  partialContent = "";
@@ -11167,8 +11344,6 @@ var AcpProviderInstance = class {
11167
11344
  inputContent: ""
11168
11345
  },
11169
11346
  workspace: this.workingDir,
11170
- currentModel: this.currentModel,
11171
- currentPlan: this.currentMode,
11172
11347
  instanceId: this.instanceId,
11173
11348
  lastUpdated: Date.now(),
11174
11349
  settings: this.settings,
@@ -11179,11 +11354,9 @@ var AcpProviderInstance = class {
11179
11354
  // Error details for dashboard display
11180
11355
  errorMessage: this.errorMessage || void 0,
11181
11356
  errorReason: this.errorReason || void 0,
11182
- controlValues: {
11183
- ...this.currentModel ? { model: this.currentModel } : {},
11184
- ...this.currentMode ? { mode: this.currentMode } : {}
11185
- },
11186
- providerControls: this.provider.controls
11357
+ controlValues: this.getSelectionControlValues(),
11358
+ providerControls: this.provider.controls,
11359
+ summaryMetadata: this.buildSelectionSummaryMetadata()
11187
11360
  };
11188
11361
  }
11189
11362
  onEvent(event, data) {
@@ -11217,6 +11390,54 @@ var AcpProviderInstance = class {
11217
11390
  getInstanceId() {
11218
11391
  return this.instanceId;
11219
11392
  }
11393
+ resolveConfigOptionLabel(category, value) {
11394
+ if (!value) return void 0;
11395
+ const option = this.configOptions.find((entry) => entry.category === category);
11396
+ return option?.options.find((candidate) => candidate.value === value)?.name || value;
11397
+ }
11398
+ resolveModeLabel(modeId) {
11399
+ if (!modeId) return void 0;
11400
+ return this.availableModes.find((mode) => mode.id === modeId)?.name || modeId;
11401
+ }
11402
+ getCurrentSelection(category) {
11403
+ return this.currentSelections[category];
11404
+ }
11405
+ setCurrentSelection(category, value) {
11406
+ const normalized = typeof value === "string" ? value.trim() : "";
11407
+ if (normalized) {
11408
+ this.currentSelections[category] = normalized;
11409
+ return;
11410
+ }
11411
+ delete this.currentSelections[category];
11412
+ }
11413
+ getSelectionControlValues() {
11414
+ const model = this.getCurrentSelection("model");
11415
+ const mode = this.getCurrentSelection("mode");
11416
+ return {
11417
+ ...model ? { model } : {},
11418
+ ...mode ? { mode } : {}
11419
+ };
11420
+ }
11421
+ resolveSelectionLabel(category, value) {
11422
+ if (!value) return void 0;
11423
+ const configLabel = this.resolveConfigOptionLabel(category, value);
11424
+ if (configLabel && configLabel !== value) return configLabel;
11425
+ if (category === "mode") {
11426
+ const modeLabel = this.resolveModeLabel(value);
11427
+ if (modeLabel) return modeLabel;
11428
+ }
11429
+ return configLabel || value;
11430
+ }
11431
+ buildSelectionSummaryMetadata() {
11432
+ const model = this.getCurrentSelection("model");
11433
+ const mode = this.getCurrentSelection("mode");
11434
+ return buildLegacyModelModeSummaryMetadata({
11435
+ model,
11436
+ mode,
11437
+ modelLabel: this.resolveSelectionLabel("model", model),
11438
+ modeLabel: this.resolveSelectionLabel("mode", mode)
11439
+ });
11440
+ }
11220
11441
  // ─── ACP Config Options & Modes ─────────────────────
11221
11442
  parseConfigOptions(raw) {
11222
11443
  if (!Array.isArray(raw)) return;
@@ -11248,12 +11469,14 @@ var AcpProviderInstance = class {
11248
11469
  }
11249
11470
  }
11250
11471
  this.configOptions.push({ category, configId, currentValue, options: flatOptions });
11251
- if (category === "model" && currentValue) this.currentModel = currentValue;
11472
+ if (category === "model" || category === "mode") {
11473
+ this.setCurrentSelection(category, currentValue);
11474
+ }
11252
11475
  }
11253
11476
  }
11254
11477
  parseModes(raw) {
11255
11478
  if (!raw) return;
11256
- if (raw.currentModeId) this.currentMode = raw.currentModeId;
11479
+ this.setCurrentSelection("mode", raw.currentModeId);
11257
11480
  if (Array.isArray(raw.availableModes)) {
11258
11481
  this.availableModes = raw.availableModes.map((m) => ({
11259
11482
  id: m.id,
@@ -11272,8 +11495,7 @@ var AcpProviderInstance = class {
11272
11495
  if (this.useStaticConfig) {
11273
11496
  opt.currentValue = value;
11274
11497
  this.selectedConfig[opt.configId] = value;
11275
- if (category === "model") this.currentModel = value;
11276
- if (category === "mode") this.currentMode = value;
11498
+ if (category === "model" || category === "mode") this.setCurrentSelection(category, value);
11277
11499
  this.log.info(`[${this.type}] Static config ${category} set to: ${value} \u2014 restarting agent`);
11278
11500
  await this.restartWithNewConfig();
11279
11501
  return;
@@ -11291,7 +11513,7 @@ var AcpProviderInstance = class {
11291
11513
  value
11292
11514
  });
11293
11515
  opt.currentValue = value;
11294
- if (category === "model") this.currentModel = value;
11516
+ if (category === "model" || category === "mode") this.setCurrentSelection(category, value);
11295
11517
  if (result?.configOptions) this.parseConfigOptions(result.configOptions);
11296
11518
  this.log.info(`[${this.type}] Config ${category} set to: ${value} | response: ${JSON.stringify(result)?.slice(0, 300)}`);
11297
11519
  } catch (e) {
@@ -11307,7 +11529,7 @@ var AcpProviderInstance = class {
11307
11529
  opt.currentValue = modeId;
11308
11530
  this.selectedConfig[opt.configId] = modeId;
11309
11531
  }
11310
- this.currentMode = modeId;
11532
+ this.setCurrentSelection("mode", modeId);
11311
11533
  this.log.info(`[${this.type}] Static mode set to: ${modeId} \u2014 restarting agent`);
11312
11534
  await this.restartWithNewConfig();
11313
11535
  return;
@@ -11322,7 +11544,7 @@ var AcpProviderInstance = class {
11322
11544
  sessionId: this.sessionId,
11323
11545
  modeId
11324
11546
  });
11325
- this.currentMode = modeId;
11547
+ this.setCurrentSelection("mode", modeId);
11326
11548
  this.log.info(`[${this.type}] Mode set to: ${modeId}`);
11327
11549
  } catch (e) {
11328
11550
  const message = e?.message || "Unknown ACP mode error";
@@ -11580,8 +11802,8 @@ var AcpProviderInstance = class {
11580
11802
  if (result?.modes) this.log.debug(`[${this.type}] modes: ${JSON.stringify(result.modes).slice(0, 300)}`);
11581
11803
  this.parseConfigOptions(result?.configOptions);
11582
11804
  this.parseModes(result?.modes);
11583
- if (!this.currentModel && result?.models?.currentModelId) {
11584
- this.currentModel = result.models.currentModelId;
11805
+ if (!this.getCurrentSelection("model") && result?.models?.currentModelId) {
11806
+ this.setCurrentSelection("model", result.models.currentModelId);
11585
11807
  }
11586
11808
  if (this.configOptions.length === 0 && this.provider.staticConfigOptions?.length) {
11587
11809
  this.useStaticConfig = true;
@@ -11595,13 +11817,16 @@ var AcpProviderInstance = class {
11595
11817
  });
11596
11818
  if (defaultVal) {
11597
11819
  this.selectedConfig[sc.configId] = defaultVal;
11598
- if (sc.category === "model") this.currentModel = defaultVal;
11599
- if (sc.category === "mode") this.currentMode = defaultVal;
11820
+ if (sc.category === "model" || sc.category === "mode") {
11821
+ this.setCurrentSelection(sc.category, defaultVal);
11822
+ }
11600
11823
  }
11601
11824
  }
11602
11825
  this.log.info(`[${this.type}] Using static configOptions (${this.configOptions.length} options)`);
11603
11826
  }
11604
- this.log.info(`[${this.type}] Session created: ${this.sessionId}${this.currentModel ? ` (model: ${this.currentModel})` : ""}${this.currentMode ? ` (mode: ${this.currentMode})` : ""}`);
11827
+ const currentModel = this.getCurrentSelection("model");
11828
+ const currentMode = this.getCurrentSelection("mode");
11829
+ this.log.info(`[${this.type}] Session created: ${this.sessionId}${currentModel ? ` (model: ${currentModel})` : ""}${currentMode ? ` (mode: ${currentMode})` : ""}`);
11605
11830
  if (this.configOptions.length > 0) {
11606
11831
  this.log.info(`[${this.type}] Config options: ${this.configOptions.map((c) => `${c.category}(${c.options.length})`).join(", ")}`);
11607
11832
  }
@@ -11776,7 +12001,7 @@ var AcpProviderInstance = class {
11776
12001
  break;
11777
12002
  }
11778
12003
  case "current_mode_update": {
11779
- this.currentMode = update.currentModeId;
12004
+ this.setCurrentSelection("mode", update.currentModeId);
11780
12005
  break;
11781
12006
  }
11782
12007
  case "config_option_update": {
@@ -11849,7 +12074,7 @@ var AcpProviderInstance = class {
11849
12074
  this.detectStatusTransition();
11850
12075
  }
11851
12076
  if (params.model) {
11852
- this.currentModel = params.model;
12077
+ this.setCurrentSelection("model", params.model);
11853
12078
  }
11854
12079
  }
11855
12080
  /** Map SDK ToolCallStatus to internal status */
@@ -12138,7 +12363,11 @@ var DaemonCliManager = class {
12138
12363
  }
12139
12364
  persistRecentActivity(entry) {
12140
12365
  try {
12141
- let nextState = appendRecentActivity(loadState(), entry);
12366
+ const summaryMetadata = normalizeProviderSummaryMetadata(entry.summaryMetadata);
12367
+ let nextState = appendRecentActivity(loadState(), {
12368
+ ...entry,
12369
+ summaryMetadata
12370
+ });
12142
12371
  if (entry.providerSessionId && (entry.kind === "cli" || entry.kind === "acp")) {
12143
12372
  nextState = upsertSavedProviderSession(nextState, {
12144
12373
  kind: entry.kind,
@@ -12146,7 +12375,7 @@ var DaemonCliManager = class {
12146
12375
  providerName: entry.providerName,
12147
12376
  providerSessionId: entry.providerSessionId,
12148
12377
  workspace: entry.workspace,
12149
- currentModel: entry.currentModel,
12378
+ summaryMetadata,
12150
12379
  title: entry.title
12151
12380
  });
12152
12381
  }
@@ -12336,7 +12565,7 @@ ${installInfo}`
12336
12565
  providerType: normalizedType,
12337
12566
  providerName: provider.displayName || provider.name || normalizedType,
12338
12567
  workspace: resolvedDir,
12339
- currentModel: initialModel,
12568
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
12340
12569
  sessionId,
12341
12570
  title: provider.displayName || provider.name || normalizedType
12342
12571
  });
@@ -12438,7 +12667,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
12438
12667
  providerName: provider?.displayName || provider?.name || normalizedType,
12439
12668
  providerSessionId: sessionBinding.providerSessionId,
12440
12669
  workspace: resolvedDir,
12441
- currentModel: initialModel,
12670
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
12442
12671
  sessionId: key,
12443
12672
  title: provider?.displayName || provider?.name || normalizedType
12444
12673
  });
@@ -14603,12 +14832,90 @@ cleanOldFiles();
14603
14832
  // src/commands/router.ts
14604
14833
  init_logger();
14605
14834
 
14835
+ // src/session-host/runtime-surface.ts
14836
+ var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
14837
+ function isSessionHostLiveRuntime(record) {
14838
+ const lifecycle = String(record?.lifecycle || "").trim();
14839
+ return LIVE_LIFECYCLES.has(lifecycle);
14840
+ }
14841
+ function getSessionHostRecoveryLabel(meta) {
14842
+ const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
14843
+ if (!recoveryState) return null;
14844
+ if (recoveryState === "auto_resumed") return "restored after restart";
14845
+ if (recoveryState === "resume_failed") return "restore failed";
14846
+ if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
14847
+ if (recoveryState === "orphan_snapshot") return "snapshot recovered";
14848
+ return recoveryState.replace(/_/g, " ");
14849
+ }
14850
+ function isSessionHostRecoverySnapshot(record) {
14851
+ if (!record) return false;
14852
+ if (isSessionHostLiveRuntime(record)) return false;
14853
+ const lifecycle = String(record.lifecycle || "").trim();
14854
+ if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
14855
+ return false;
14856
+ }
14857
+ const meta = record.meta || void 0;
14858
+ if (meta?.restoredFromStorage === true) return true;
14859
+ return getSessionHostRecoveryLabel(meta) !== null;
14860
+ }
14861
+ function getSessionHostSurfaceKind(record) {
14862
+ if (isSessionHostLiveRuntime(record)) return "live_runtime";
14863
+ if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
14864
+ return "inactive_record";
14865
+ }
14866
+ function partitionSessionHostRecords(records) {
14867
+ const liveRuntimes = [];
14868
+ const recoverySnapshots = [];
14869
+ const inactiveRecords = [];
14870
+ for (const record of records) {
14871
+ const kind = getSessionHostSurfaceKind(record);
14872
+ if (kind === "live_runtime") {
14873
+ liveRuntimes.push(record);
14874
+ } else if (kind === "recovery_snapshot") {
14875
+ recoverySnapshots.push(record);
14876
+ } else {
14877
+ inactiveRecords.push(record);
14878
+ }
14879
+ }
14880
+ return {
14881
+ liveRuntimes,
14882
+ recoverySnapshots,
14883
+ inactiveRecords
14884
+ };
14885
+ }
14886
+ function partitionSessionHostDiagnosticsSessions(records) {
14887
+ return partitionSessionHostRecords(records || []);
14888
+ }
14889
+
14606
14890
  // src/status/snapshot.ts
14607
14891
  init_config();
14608
14892
  import * as os16 from "os";
14609
14893
  init_terminal_screen();
14610
14894
  init_logger();
14611
14895
  var READ_DEBUG_ENABLED = process.argv.includes("--dev") || process.env.ADHDEV_READ_DEBUG === "1";
14896
+ var recentReadDebugSignatureBySession = /* @__PURE__ */ new Map();
14897
+ function buildRecentReadDebugSignature(snapshot) {
14898
+ return [
14899
+ snapshot.providerType,
14900
+ snapshot.status,
14901
+ snapshot.inboxBucket,
14902
+ snapshot.unread ? "1" : "0",
14903
+ String(snapshot.lastSeenAt),
14904
+ snapshot.completionMarker,
14905
+ snapshot.seenCompletionMarker,
14906
+ String(snapshot.lastUpdated),
14907
+ String(snapshot.lastUsedAt),
14908
+ snapshot.lastRole,
14909
+ String(snapshot.messageUpdatedAt)
14910
+ ].join("|");
14911
+ }
14912
+ function shouldEmitRecentReadDebugLog(cache, snapshot) {
14913
+ const nextSignature = buildRecentReadDebugSignature(snapshot);
14914
+ const previousSignature = cache.get(snapshot.sessionId);
14915
+ if (previousSignature === nextSignature) return false;
14916
+ cache.set(snapshot.sessionId, nextSignature);
14917
+ return true;
14918
+ }
14612
14919
  function buildDetectedIdeInfos(detectedIdes, cdpManagers) {
14613
14920
  return detectedIdes.filter((ide) => ide.installed !== false).map((ide) => ({
14614
14921
  id: ide.id,
@@ -14760,7 +15067,7 @@ function buildRecentLaunches(recentActivity) {
14760
15067
  providerSessionId: item.providerSessionId,
14761
15068
  title: item.title || item.providerName,
14762
15069
  workspace: item.workspace,
14763
- currentModel: item.currentModel,
15070
+ summaryMetadata: item.summaryMetadata,
14764
15071
  lastLaunchedAt: item.lastUsedAt
14765
15072
  })).sort((a, b) => b.lastLaunchedAt - a.lastLaunchedAt).slice(0, 12);
14766
15073
  }
@@ -14801,9 +15108,24 @@ function buildStatusSnapshot(options) {
14801
15108
  session.unread = unread;
14802
15109
  session.inboxBucket = inboxBucket;
14803
15110
  if (READ_DEBUG_ENABLED && (session.unread || session.inboxBucket !== "idle" || session.providerType.includes("codex"))) {
15111
+ const recentReadSnapshot = {
15112
+ sessionId: session.id,
15113
+ providerType: session.providerType,
15114
+ status: String(session.status || ""),
15115
+ inboxBucket,
15116
+ unread,
15117
+ lastSeenAt,
15118
+ completionMarker: completionMarker || "-",
15119
+ seenCompletionMarker: seenCompletionMarker || "-",
15120
+ lastUpdated: Number(session.lastUpdated || 0),
15121
+ lastUsedAt,
15122
+ lastRole: getLastMessageRole(sourceSession),
15123
+ messageUpdatedAt: getSessionMessageUpdatedAt(sourceSession)
15124
+ };
15125
+ if (!shouldEmitRecentReadDebugLog(recentReadDebugSignatureBySession, recentReadSnapshot)) continue;
14804
15126
  LOG.info(
14805
15127
  "RecentRead",
14806
- `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)}`
15128
+ `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}`
14807
15129
  );
14808
15130
  }
14809
15131
  const lastDisplayMessage = getLastDisplayMessage(sourceSession);
@@ -15078,11 +15400,104 @@ function toHostedCliRuntimeDescriptor(record) {
15078
15400
  providerSessionId: typeof record.meta?.providerSessionId === "string" ? String(record.meta.providerSessionId) : void 0
15079
15401
  };
15080
15402
  }
15403
+ function getWriteConflictOwnerClientId(error) {
15404
+ const message = typeof error === "string" ? error : error instanceof Error ? error.message : "";
15405
+ const match = /^Write owned by\s+(.+)$/.exec(message.trim());
15406
+ return match?.[1]?.trim() || void 0;
15407
+ }
15408
+ function summarizeSessionHostRecord(result) {
15409
+ if (!result || typeof result !== "object") return {};
15410
+ const record = result;
15411
+ return {
15412
+ runtimeKey: typeof record.runtimeKey === "string" ? record.runtimeKey : void 0,
15413
+ lifecycle: typeof record.lifecycle === "string" ? record.lifecycle : void 0,
15414
+ surfaceKind: getSessionHostSurfaceKind(record),
15415
+ attachedClientCount: Array.isArray(record.attachedClients) ? record.attachedClients.length : void 0,
15416
+ hasWriteOwner: !!record.writeOwner,
15417
+ writeOwnerClientId: typeof record.writeOwner?.clientId === "string" ? record.writeOwner.clientId : void 0
15418
+ };
15419
+ }
15420
+ function summarizeSessionHostRecords(result) {
15421
+ const records = Array.isArray(result) ? result : [];
15422
+ const groups = partitionSessionHostRecords(records);
15423
+ return {
15424
+ sessionCount: records.length,
15425
+ liveRuntimeCount: groups.liveRuntimes.length,
15426
+ recoverySnapshotCount: groups.recoverySnapshots.length,
15427
+ inactiveRecordCount: groups.inactiveRecords.length
15428
+ };
15429
+ }
15430
+ function summarizeSessionHostDiagnostics(result) {
15431
+ const diagnostics = result && typeof result === "object" ? result : {};
15432
+ const sessions = Array.isArray(diagnostics.sessions) ? diagnostics.sessions : [];
15433
+ return {
15434
+ runtimeCount: typeof diagnostics.runtimeCount === "number" ? diagnostics.runtimeCount : void 0,
15435
+ ...summarizeSessionHostRecords(sessions)
15436
+ };
15437
+ }
15438
+ function summarizeSessionHostPruneResult(result) {
15439
+ const value = result && typeof result === "object" ? result : {};
15440
+ return {
15441
+ duplicateGroupCount: typeof value.duplicateGroupCount === "number" ? value.duplicateGroupCount : void 0,
15442
+ prunedCount: Array.isArray(value.prunedSessionIds) ? value.prunedSessionIds.length : void 0,
15443
+ keptCount: Array.isArray(value.keptSessionIds) ? value.keptSessionIds.length : void 0
15444
+ };
15445
+ }
15081
15446
  var DaemonCommandRouter = class {
15082
15447
  deps;
15083
15448
  constructor(deps) {
15084
15449
  this.deps = deps;
15085
15450
  }
15451
+ async traceSessionHostAction(action, args, run, summarizeResult) {
15452
+ const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
15453
+ const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
15454
+ const requestedPayload = { action };
15455
+ if (sessionId) requestedPayload.sessionId = sessionId;
15456
+ if (typeof args?.clientId === "string") requestedPayload.clientId = args.clientId;
15457
+ if (typeof args?.signal === "string") requestedPayload.signal = args.signal;
15458
+ if (typeof args?.providerType === "string") requestedPayload.providerType = args.providerType;
15459
+ if (typeof args?.workspace === "string") requestedPayload.workspace = args.workspace;
15460
+ if (typeof args?.dryRun === "boolean") requestedPayload.dryRun = args.dryRun;
15461
+ recordDebugTrace({
15462
+ interactionId,
15463
+ category: "session_host",
15464
+ stage: "action_requested",
15465
+ level: "info",
15466
+ sessionId,
15467
+ payload: requestedPayload
15468
+ });
15469
+ try {
15470
+ const result = await run();
15471
+ recordDebugTrace({
15472
+ interactionId,
15473
+ category: "session_host",
15474
+ stage: "action_result",
15475
+ level: "info",
15476
+ sessionId,
15477
+ payload: {
15478
+ ...requestedPayload,
15479
+ success: true,
15480
+ ...summarizeResult ? summarizeResult(result) : {}
15481
+ }
15482
+ });
15483
+ return result;
15484
+ } catch (error) {
15485
+ recordDebugTrace({
15486
+ interactionId,
15487
+ category: "session_host",
15488
+ stage: "action_failed",
15489
+ level: "error",
15490
+ sessionId,
15491
+ payload: {
15492
+ ...requestedPayload,
15493
+ error: error?.message || String(error),
15494
+ failureKind: getWriteConflictOwnerClientId(error) ? "write_conflict" : "request_failed",
15495
+ conflictOwnerClientId: getWriteConflictOwnerClientId(error)
15496
+ }
15497
+ });
15498
+ throw error;
15499
+ }
15500
+ }
15086
15501
  /**
15087
15502
  * Unified command routing.
15088
15503
  * Returns result for all commands:
@@ -15192,44 +15607,60 @@ var DaemonCommandRouter = class {
15192
15607
  }
15193
15608
  case "session_host_get_diagnostics": {
15194
15609
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15195
- const diagnostics = await this.deps.sessionHostControl.getDiagnostics({
15610
+ const diagnostics = await this.traceSessionHostAction("session_host_get_diagnostics", args, () => this.deps.sessionHostControl.getDiagnostics({
15196
15611
  includeSessions: args?.includeSessions !== false,
15197
15612
  limit: Number(args?.limit) || void 0
15198
- });
15613
+ }), (result) => ({
15614
+ includeSessions: args?.includeSessions !== false,
15615
+ limit: Number(args?.limit) || void 0,
15616
+ ...summarizeSessionHostDiagnostics(result)
15617
+ }));
15199
15618
  return { success: true, diagnostics };
15200
15619
  }
15201
15620
  case "session_host_list_sessions": {
15202
15621
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15203
- const sessions = await this.deps.sessionHostControl.listSessions();
15622
+ const sessions = await this.traceSessionHostAction("session_host_list_sessions", args, () => this.deps.sessionHostControl.listSessions(), (records) => summarizeSessionHostRecords(records));
15204
15623
  return { success: true, sessions };
15205
15624
  }
15206
15625
  case "session_host_stop_session": {
15207
15626
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15208
15627
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15209
15628
  if (!sessionId) return { success: false, error: "sessionId required" };
15210
- const record = await this.deps.sessionHostControl.stopSession(sessionId);
15629
+ const record = await this.traceSessionHostAction("session_host_stop_session", args, () => this.deps.sessionHostControl.stopSession(sessionId), (result) => summarizeSessionHostRecord(result));
15211
15630
  return { success: true, record };
15212
15631
  }
15213
15632
  case "session_host_resume_session": {
15214
15633
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15215
15634
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15216
15635
  if (!sessionId) return { success: false, error: "sessionId required" };
15217
- const record = await this.deps.sessionHostControl.resumeSession(sessionId);
15218
- const hosted = toHostedCliRuntimeDescriptor(record);
15219
- if (hosted) {
15220
- await this.deps.cliManager.restoreHostedSessions([hosted]);
15221
- }
15636
+ const record = await this.traceSessionHostAction("session_host_resume_session", args, async () => {
15637
+ const nextRecord = await this.deps.sessionHostControl.resumeSession(sessionId);
15638
+ const hosted = toHostedCliRuntimeDescriptor(nextRecord);
15639
+ if (hosted) {
15640
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
15641
+ }
15642
+ return nextRecord;
15643
+ }, (result) => ({
15644
+ ...summarizeSessionHostRecord(result),
15645
+ restoredHostedSession: !!toHostedCliRuntimeDescriptor(result)
15646
+ }));
15222
15647
  return { success: true, record };
15223
15648
  }
15224
15649
  case "session_host_restart_session": {
15225
15650
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15226
15651
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : "";
15227
15652
  if (!sessionId) return { success: false, error: "sessionId required" };
15228
- const record = await this.deps.sessionHostControl.restartSession(sessionId);
15229
- const hosted = toHostedCliRuntimeDescriptor(record);
15230
- if (hosted) {
15231
- await this.deps.cliManager.restoreHostedSessions([hosted]);
15232
- }
15653
+ const record = await this.traceSessionHostAction("session_host_restart_session", args, async () => {
15654
+ const nextRecord = await this.deps.sessionHostControl.restartSession(sessionId);
15655
+ const hosted = toHostedCliRuntimeDescriptor(nextRecord);
15656
+ if (hosted) {
15657
+ await this.deps.cliManager.restoreHostedSessions([hosted]);
15658
+ }
15659
+ return nextRecord;
15660
+ }, (result) => ({
15661
+ ...summarizeSessionHostRecord(result),
15662
+ restoredHostedSession: !!toHostedCliRuntimeDescriptor(result)
15663
+ }));
15233
15664
  return { success: true, record };
15234
15665
  }
15235
15666
  case "session_host_send_signal": {
@@ -15238,7 +15669,7 @@ var DaemonCommandRouter = class {
15238
15669
  const signal = typeof args?.signal === "string" ? args.signal : "";
15239
15670
  if (!sessionId) return { success: false, error: "sessionId required" };
15240
15671
  if (!signal) return { success: false, error: "signal required" };
15241
- const record = await this.deps.sessionHostControl.sendSignal(sessionId, signal);
15672
+ const record = await this.traceSessionHostAction("session_host_send_signal", args, () => this.deps.sessionHostControl.sendSignal(sessionId, signal), (result) => summarizeSessionHostRecord(result));
15242
15673
  return { success: true, record };
15243
15674
  }
15244
15675
  case "session_host_force_detach_client": {
@@ -15247,16 +15678,16 @@ var DaemonCommandRouter = class {
15247
15678
  const clientId = typeof args?.clientId === "string" ? args.clientId : "";
15248
15679
  if (!sessionId) return { success: false, error: "sessionId required" };
15249
15680
  if (!clientId) return { success: false, error: "clientId required" };
15250
- const record = await this.deps.sessionHostControl.forceDetachClient(sessionId, clientId);
15681
+ const record = await this.traceSessionHostAction("session_host_force_detach_client", args, () => this.deps.sessionHostControl.forceDetachClient(sessionId, clientId), (result) => summarizeSessionHostRecord(result));
15251
15682
  return { success: true, record };
15252
15683
  }
15253
15684
  case "session_host_prune_duplicate_sessions": {
15254
15685
  if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
15255
- const result = await this.deps.sessionHostControl.pruneDuplicateSessions({
15686
+ const result = await this.traceSessionHostAction("session_host_prune_duplicate_sessions", args, () => this.deps.sessionHostControl.pruneDuplicateSessions({
15256
15687
  providerType: typeof args?.providerType === "string" ? args.providerType : void 0,
15257
15688
  workspace: typeof args?.workspace === "string" ? args.workspace : void 0,
15258
15689
  dryRun: args?.dryRun === true
15259
- });
15690
+ }), (value) => summarizeSessionHostPruneResult(value));
15260
15691
  return { success: true, result };
15261
15692
  }
15262
15693
  case "session_host_acquire_write": {
@@ -15266,12 +15697,15 @@ var DaemonCommandRouter = class {
15266
15697
  const ownerType = args?.ownerType === "agent" ? "agent" : "user";
15267
15698
  if (!sessionId) return { success: false, error: "sessionId required" };
15268
15699
  if (!clientId) return { success: false, error: "clientId required" };
15269
- const record = await this.deps.sessionHostControl.acquireWrite({
15700
+ const record = await this.traceSessionHostAction("session_host_acquire_write", args, () => this.deps.sessionHostControl.acquireWrite({
15270
15701
  sessionId,
15271
15702
  clientId,
15272
15703
  ownerType,
15273
15704
  force: args?.force !== false
15274
- });
15705
+ }), (result) => ({
15706
+ ...summarizeSessionHostRecord(result),
15707
+ ownerType
15708
+ }));
15275
15709
  return { success: true, record };
15276
15710
  }
15277
15711
  case "session_host_release_write": {
@@ -15280,7 +15714,10 @@ var DaemonCommandRouter = class {
15280
15714
  const clientId = typeof args?.clientId === "string" ? args.clientId : "";
15281
15715
  if (!sessionId) return { success: false, error: "sessionId required" };
15282
15716
  if (!clientId) return { success: false, error: "clientId required" };
15283
- const record = await this.deps.sessionHostControl.releaseWrite({ sessionId, clientId });
15717
+ const record = await this.traceSessionHostAction("session_host_release_write", args, () => this.deps.sessionHostControl.releaseWrite({
15718
+ sessionId,
15719
+ clientId
15720
+ }), (result) => summarizeSessionHostRecord(result));
15284
15721
  return { success: true, record };
15285
15722
  }
15286
15723
  case "list_saved_sessions": {
@@ -15313,7 +15750,7 @@ var DaemonCommandRouter = class {
15313
15750
  kind: saved?.kind || recent?.kind || kind,
15314
15751
  title: saved?.title || recent?.title || session.sessionTitle || session.preview || providerType,
15315
15752
  workspace: saved?.workspace || recent?.workspace || session.workspace,
15316
- currentModel: saved?.currentModel || recent?.currentModel,
15753
+ summaryMetadata: saved?.summaryMetadata || recent?.summaryMetadata,
15317
15754
  preview: session.preview,
15318
15755
  messageCount: session.messageCount,
15319
15756
  firstMessageAt: session.firstMessageAt,
@@ -15752,7 +16189,7 @@ var DaemonStatusReporter = class {
15752
16189
  const ideSummary = ideStates.map((s) => {
15753
16190
  const msgs = s.activeChat?.messages?.length || 0;
15754
16191
  const exts = s.extensions.length;
15755
- return `${s.type}(${s.status},${msgs}msg,${exts}ext${s.currentModel ? ",model=" + s.currentModel : ""})`;
16192
+ return `${s.type}(${s.status},${msgs}msg,${exts}ext)`;
15756
16193
  }).join(", ");
15757
16194
  const cliSummary = cliStates.map((s) => `${s.type}(${s.status})`).join(", ");
15758
16195
  const acpSummary = acpStates.map((s) => `${s.type}(${s.status})`).join(", ");
@@ -15814,9 +16251,7 @@ var DaemonStatusReporter = class {
15814
16251
  workspace: session.workspace ?? null,
15815
16252
  title: session.title,
15816
16253
  cdpConnected: session.cdpConnected,
15817
- currentModel: session.currentModel,
15818
- currentPlan: session.currentPlan,
15819
- currentAutoApprove: session.currentAutoApprove
16254
+ summaryMetadata: session.summaryMetadata
15820
16255
  })),
15821
16256
  p2p: payload.p2p,
15822
16257
  timestamp: now
@@ -15982,15 +16417,18 @@ var ProviderStreamAdapter = class {
15982
16417
  status: data.status || "idle",
15983
16418
  messages: data.messages || [],
15984
16419
  inputContent: data.inputContent || "",
15985
- model: data.model,
15986
- mode: data.mode,
15987
16420
  activeModal: data.activeModal
15988
16421
  };
15989
16422
  if (typeof data.title === "string" && data.title.trim()) {
15990
16423
  state.title = data.title.trim();
15991
16424
  }
15992
16425
  const controlValues = extractProviderControlValues(this.provider.controls, data);
15993
- if (controlValues) state.controlValues = controlValues;
16426
+ const surface = resolveProviderStateSurface({
16427
+ controlValues,
16428
+ summaryMetadata: data.summaryMetadata
16429
+ });
16430
+ if (surface.controlValues) state.controlValues = surface.controlValues;
16431
+ if (surface.summaryMetadata) state.summaryMetadata = surface.summaryMetadata;
15994
16432
  const effects = normalizeProviderEffects(data);
15995
16433
  if (effects.length > 0) state.effects = effects;
15996
16434
  if (state.messages.length > 0) {
@@ -16264,7 +16702,8 @@ var DaemonAgentStreamManager = class {
16264
16702
  const evaluate = (expr, timeout) => cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
16265
16703
  const state = await agent.adapter.readChat(evaluate);
16266
16704
  const stateError = this.getStateError(state);
16267
- 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) : ""}`);
16705
+ const selectedModelValue = typeof state.controlValues?.model === "string" ? state.controlValues.model : "";
16706
+ LOG.debug("AgentStream", `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${selectedModelValue}${state.status === "error" ? " error=" + JSON.stringify(stateError) : ""}`);
16268
16707
  if (state.status === "error" && this.isRecoverableSessionError(stateError)) {
16269
16708
  throw new Error(stateError);
16270
16709
  }
@@ -16612,9 +17051,8 @@ function forwardAgentStreamsToIdeInstance(instanceManager, ideType, streams) {
16612
17051
  messages: stream.messages || [],
16613
17052
  status: stream.status || "idle",
16614
17053
  activeModal: stream.activeModal || null,
16615
- model: stream.model || void 0,
16616
- mode: stream.mode || void 0,
16617
17054
  controlValues: stream.controlValues || void 0,
17055
+ summaryMetadata: stream.summaryMetadata || void 0,
16618
17056
  effects: stream.effects || void 0,
16619
17057
  sessionId: stream.sessionId || stream.instanceId || void 0,
16620
17058
  title: stream.title || stream.agentName || void 0,
@@ -17150,7 +17588,11 @@ module.exports.setMode = (params) => {
17150
17588
  * 5. Approval dialog detection (buttons, modal)
17151
17589
  * 6. Input field selector
17152
17590
  *
17153
- * \u2192 { id, status, title, messages[], inputContent, activeModal }
17591
+ * Preferred live-state surface:
17592
+ * - controlValues: explicit current control selections (model/mode/etc.)
17593
+ * - summaryMetadata: compact always-visible metadata for dashboard/recent views
17594
+ * Legacy top-level model/mode output is no longer the preferred shape.
17595
+ * \u2192 { id, status, title, messages[], inputContent, activeModal, controlValues?, summaryMetadata? }
17154
17596
  */
17155
17597
  (() => {
17156
17598
  try {
@@ -17178,6 +17620,9 @@ module.exports.setMode = (params) => {
17178
17620
  messages,
17179
17621
  inputContent,
17180
17622
  activeModal,
17623
+ // TODO: Return explicit selections when available, e.g.
17624
+ // controlValues: { model: selectedModel, mode: selectedMode },
17625
+ // summaryMetadata: { items: [{ id: 'model', value: selectedModelLabel || selectedModel, shortValue: selectedModel, order: 10 }] },
17181
17626
  });
17182
17627
  } catch(e) {
17183
17628
  return JSON.stringify({ id: '', status: 'error', messages: [], error: e.message });
@@ -18918,7 +19363,6 @@ async function handleCliStatus(ctx, _req, res) {
18918
19363
  lastMessage: s.activeChat?.messages?.slice(-1)[0] || null,
18919
19364
  activeModal: s.activeChat?.activeModal || null,
18920
19365
  pendingEvents: s.pendingEvents || [],
18921
- currentModel: s.currentModel,
18922
19366
  settings: s.settings
18923
19367
  }));
18924
19368
  ctx.json(res, 200, { instances: result, count: result.length });
@@ -20075,7 +20519,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
20075
20519
  lines.push("## Required Return Format");
20076
20520
  lines.push("| Function | Return JSON |");
20077
20521
  lines.push("|---|---|");
20078
- 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 |");
20522
+ 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 |");
20079
20523
  lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
20080
20524
  lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
20081
20525
  lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
@@ -21710,7 +22154,7 @@ var DevServer = class _DevServer {
21710
22154
  lines.push("## Required Return Format");
21711
22155
  lines.push("| Function | Return JSON |");
21712
22156
  lines.push("|---|---|");
21713
- 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 |");
22157
+ 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 |");
21714
22158
  lines.push("| sendMessage | `{ sent: false, needsTypeAndSend: true, selector }` |");
21715
22159
  lines.push("| resolveAction | `{ resolved: true/false, clicked? }` |");
21716
22160
  lines.push("| listSessions | `{ sessions: [{ id, title, active, index }] }` |");
@@ -22621,61 +23065,6 @@ async function listHostedCliRuntimes(endpoint) {
22621
23065
  }
22622
23066
  }
22623
23067
 
22624
- // src/session-host/runtime-surface.ts
22625
- var LIVE_LIFECYCLES = /* @__PURE__ */ new Set(["starting", "running", "stopping", "interrupted"]);
22626
- function isSessionHostLiveRuntime(record) {
22627
- const lifecycle = String(record?.lifecycle || "").trim();
22628
- return LIVE_LIFECYCLES.has(lifecycle);
22629
- }
22630
- function getSessionHostRecoveryLabel(meta) {
22631
- const recoveryState = typeof meta?.runtimeRecoveryState === "string" ? String(meta.runtimeRecoveryState).trim() : "";
22632
- if (!recoveryState) return null;
22633
- if (recoveryState === "auto_resumed") return "restored after restart";
22634
- if (recoveryState === "resume_failed") return "restore failed";
22635
- if (recoveryState === "host_restart_interrupted") return "host restart interrupted";
22636
- if (recoveryState === "orphan_snapshot") return "snapshot recovered";
22637
- return recoveryState.replace(/_/g, " ");
22638
- }
22639
- function isSessionHostRecoverySnapshot(record) {
22640
- if (!record) return false;
22641
- if (isSessionHostLiveRuntime(record)) return false;
22642
- const lifecycle = String(record.lifecycle || "").trim();
22643
- if (lifecycle && lifecycle !== "stopped" && lifecycle !== "failed") {
22644
- return false;
22645
- }
22646
- const meta = record.meta || void 0;
22647
- if (meta?.restoredFromStorage === true) return true;
22648
- return getSessionHostRecoveryLabel(meta) !== null;
22649
- }
22650
- function getSessionHostSurfaceKind(record) {
22651
- if (isSessionHostLiveRuntime(record)) return "live_runtime";
22652
- if (isSessionHostRecoverySnapshot(record)) return "recovery_snapshot";
22653
- return "inactive_record";
22654
- }
22655
- function partitionSessionHostRecords(records) {
22656
- const liveRuntimes = [];
22657
- const recoverySnapshots = [];
22658
- const inactiveRecords = [];
22659
- for (const record of records) {
22660
- const kind = getSessionHostSurfaceKind(record);
22661
- if (kind === "live_runtime") {
22662
- liveRuntimes.push(record);
22663
- } else if (kind === "recovery_snapshot") {
22664
- recoverySnapshots.push(record);
22665
- } else {
22666
- inactiveRecords.push(record);
22667
- }
22668
- }
22669
- return {
22670
- liveRuntimes,
22671
- recoverySnapshots,
22672
- inactiveRecords
22673
- };
22674
- }
22675
- function partitionSessionHostDiagnosticsSessions(records) {
22676
- return partitionSessionHostRecords(records || []);
22677
- }
22678
-
22679
23068
  // src/session-host/startup-restore-policy.js
22680
23069
  function shouldAutoRestoreHostedSessionsOnStartup(env = process.env) {
22681
23070
  const raw = typeof env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP === "string" ? env.ADHDEV_RESTORE_HOSTED_SESSIONS_ON_STARTUP.trim().toLowerCase() : "";