@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
@@ -35,8 +35,7 @@ export declare class AcpProviderInstance implements ProviderInstance {
35
35
  private lastStatus;
36
36
  private generatingStartedAt;
37
37
  private agentCapabilities;
38
- private currentModel;
39
- private currentMode;
38
+ private currentSelections;
40
39
  private activeToolCalls;
41
40
  private stopReason;
42
41
  private partialContent;
@@ -62,6 +61,13 @@ export declare class AcpProviderInstance implements ProviderInstance {
62
61
  getState(): AcpProviderState;
63
62
  onEvent(event: string, data?: any): void;
64
63
  getInstanceId(): string;
64
+ private resolveConfigOptionLabel;
65
+ private resolveModeLabel;
66
+ private getCurrentSelection;
67
+ private setCurrentSelection;
68
+ private getSelectionControlValues;
69
+ private resolveSelectionLabel;
70
+ private buildSelectionSummaryMetadata;
65
71
  private parseConfigOptions;
66
72
  private parseModes;
67
73
  setConfigOption(category: string, value: string): Promise<void>;
@@ -35,6 +35,7 @@ export declare class CliProviderInstance implements ProviderInstance {
35
35
  private generatingDebouncePending;
36
36
  private lastApprovalEventAt;
37
37
  private controlValues;
38
+ private summaryMetadata;
38
39
  private appliedEffectKeys;
39
40
  private historyWriter;
40
41
  private runtimeMessages;
@@ -6,6 +6,7 @@
6
6
  * - Common across all categories (cli, ide, extension)
7
7
  * - User custom providers use the same contracts
8
8
  */
9
+ import type { ProviderSummaryMetadata } from '../shared-types.js';
9
10
  export interface ReadChatResult {
10
11
  messages: ChatMessage[];
11
12
  status: AgentStatus;
@@ -21,10 +22,10 @@ export interface ReadChatResult {
21
22
  isVisible?: boolean;
22
23
  isWelcomeScreen?: boolean;
23
24
  inputContent?: string;
24
- model?: string;
25
- autoApprove?: string;
26
25
  /** Explicit dynamic control values returned by the provider */
27
26
  controlValues?: Record<string, string | number | boolean>;
27
+ /** Flexible always-visible metadata for compact/live surfaces. */
28
+ summaryMetadata?: ProviderSummaryMetadata;
28
29
  /** Provider-driven UI effects derived from chat state */
29
30
  effects?: ProviderEffect[];
30
31
  }
@@ -18,9 +18,8 @@ export declare class ExtensionProviderInstance implements ProviderInstance {
18
18
  private messages;
19
19
  private prevMessageHashes;
20
20
  private activeModal;
21
- private currentModel;
22
- private currentMode;
23
21
  private controlValues;
22
+ private summaryMetadata;
24
23
  private appliedEffectKeys;
25
24
  private runtimeMessages;
26
25
  private lastAgentStatus;
@@ -8,7 +8,7 @@
8
8
  * Each Instance manages its own status.
9
9
  */
10
10
  import type { ProviderResumeCapability } from './contracts.js';
11
- import type { AcpConfigOption, AcpMode, ProviderControlSchema } from '../shared-types.js';
11
+ import type { AcpConfigOption, AcpMode, ProviderControlSchema, ProviderSummaryMetadata } from '../shared-types.js';
12
12
  import type { ChatMessage } from '../types.js';
13
13
  export type ProviderStatus = 'idle' | 'generating' | 'waiting_approval' | 'error' | 'stopped' | 'starting';
14
14
  export interface ProviderRuntimeWriteOwner {
@@ -54,8 +54,6 @@ interface ProviderStateBase {
54
54
  /** Workspace — project path or name (all categories) */
55
55
  workspace?: string | null;
56
56
  /** Runtime info (real-time detection) */
57
- currentModel?: string;
58
- currentPlan?: string;
59
57
  /** Error details (when status === 'error') */
60
58
  errorMessage?: string;
61
59
  errorReason?: ProviderErrorReason;
@@ -72,6 +70,8 @@ interface ProviderStateBase {
72
70
  controlValues?: Record<string, string | number | boolean>;
73
71
  /** Provider-declared controls schema (from provider.controls) */
74
72
  providerControls?: ProviderControlSchema[];
73
+ /** Flexible always-visible metadata for compact/live surfaces. */
74
+ summaryMetadata?: ProviderSummaryMetadata;
75
75
  }
76
76
  /** IDE provider state */
77
77
  export interface IdeProviderState extends ProviderStateBase {
@@ -79,7 +79,6 @@ export interface IdeProviderState extends ProviderStateBase {
79
79
  cdpConnected: boolean;
80
80
  /** IDE child Extension Instance status */
81
81
  extensions: ProviderState[];
82
- currentAutoApprove?: string;
83
82
  }
84
83
  /** CLI provider state */
85
84
  export interface CliProviderState extends ProviderStateBase {
@@ -0,0 +1,23 @@
1
+ import type { ProviderControlDef } from './contracts.js';
2
+ export type ProviderControlValue = string | number | boolean;
3
+ export type ProviderControlValueMap = Record<string, ProviderControlValue>;
4
+ export declare function mergeProviderPatchState(params: {
5
+ providerControls?: ProviderControlDef[];
6
+ data: any;
7
+ currentControlValues?: ProviderControlValueMap;
8
+ currentSummaryMetadata?: unknown;
9
+ mergeWithCurrent?: boolean;
10
+ }): {
11
+ controlValues: ProviderControlValueMap;
12
+ summaryMetadata: unknown;
13
+ };
14
+ export declare function normalizeProviderStateControlValues(controlValues: ProviderControlValueMap | undefined): ProviderControlValueMap | undefined;
15
+ export declare function resolveProviderStateSurface(params: {
16
+ controlValues?: ProviderControlValueMap;
17
+ summaryMetadata?: unknown;
18
+ modelLabel?: string | null;
19
+ modeLabel?: string | null;
20
+ }): {
21
+ controlValues: ProviderControlValueMap | undefined;
22
+ summaryMetadata: unknown;
23
+ };
@@ -0,0 +1,22 @@
1
+ import type { ProviderSummaryItem, ProviderSummaryMetadata } from '../shared-types.js';
2
+ export declare function normalizeProviderSummaryMetadata(summary: ProviderSummaryMetadata | null | undefined): ProviderSummaryMetadata | undefined;
3
+ export declare function buildProviderSummaryMetadata(items: Array<ProviderSummaryItem | null | undefined>): ProviderSummaryMetadata | undefined;
4
+ export declare function getProviderSummaryItem(summary: ProviderSummaryMetadata | null | undefined, id: string): ProviderSummaryItem | undefined;
5
+ export declare function getProviderSummaryValue(summary: ProviderSummaryMetadata | null | undefined, id: string, options?: {
6
+ preferShortValue?: boolean;
7
+ }): string | undefined;
8
+ export declare function buildLegacyModelModeSummaryMetadata(params: {
9
+ model?: string | null;
10
+ mode?: string | null;
11
+ modelLabel?: string | null;
12
+ modeLabel?: string | null;
13
+ }): ProviderSummaryMetadata | undefined;
14
+ export declare function resolveProviderStateSummaryMetadata(params: {
15
+ summaryMetadata?: ProviderSummaryMetadata | null;
16
+ controlValues?: Record<string, string | number | boolean> | null;
17
+ modelLabel?: string | null;
18
+ modeLabel?: string | null;
19
+ }): ProviderSummaryMetadata | undefined;
20
+ export declare function normalizePersistedSummaryMetadata(params: {
21
+ summaryMetadata?: ProviderSummaryMetadata | null;
22
+ }): ProviderSummaryMetadata | undefined;
@@ -52,6 +52,17 @@ export interface ReadChatSyncResult {
52
52
  totalMessages: number;
53
53
  lastMessageSignature: string;
54
54
  }
55
+ export interface ProviderSummaryItem {
56
+ id: string;
57
+ value: string;
58
+ label?: string;
59
+ shortValue?: string;
60
+ icon?: string;
61
+ order?: number;
62
+ }
63
+ export interface ProviderSummaryMetadata {
64
+ items: ProviderSummaryItem[];
65
+ }
55
66
  export interface SessionHostAttachedClient {
56
67
  clientId: string;
57
68
  type: string;
@@ -239,15 +250,12 @@ export interface SessionEntry {
239
250
  activeChat: _ActiveChatData | null;
240
251
  capabilities?: SessionCapability[];
241
252
  cdpConnected?: boolean;
242
- currentModel?: string;
243
- currentPlan?: string;
244
- currentAutoApprove?: string;
245
- acpConfigOptions?: AcpConfigOption[];
246
- acpModes?: AcpMode[];
247
253
  /** Dynamic control current values (generic key-value) */
248
254
  controlValues?: Record<string, string | number | boolean>;
249
255
  /** Provider-declared controls schema (transmitted once, cached by frontend) */
250
256
  providerControls?: ProviderControlSchema[];
257
+ /** Flexible always-visible metadata for compact/live surfaces. */
258
+ summaryMetadata?: ProviderSummaryMetadata;
251
259
  errorMessage?: string;
252
260
  errorReason?: _ProviderErrorReason;
253
261
  lastMessagePreview?: string;
@@ -275,9 +283,7 @@ export interface CompactSessionEntry {
275
283
  title: string;
276
284
  workspace: string | null;
277
285
  cdpConnected?: boolean;
278
- currentModel?: string;
279
- currentPlan?: string;
280
- currentAutoApprove?: string;
286
+ summaryMetadata?: ProviderSummaryMetadata;
281
287
  }
282
288
  export type VersionUpdateReason = 'force_update_below' | 'major_minor_mismatch' | 'patch_mismatch' | 'daemon_ahead';
283
289
  /** Available provider information */
@@ -384,7 +390,7 @@ export interface RecentLaunchEntry {
384
390
  providerSessionId?: string;
385
391
  title?: string;
386
392
  workspace?: string | null;
387
- currentModel?: string;
393
+ summaryMetadata?: ProviderSummaryMetadata;
388
394
  lastLaunchedAt: number;
389
395
  }
390
396
  /** Compact machine payload broadcast by UserSessionDO to cloud dashboards. */
@@ -8,7 +8,7 @@
8
8
  import type { DaemonCdpManager } from '../cdp/manager.js';
9
9
  import { type SessionEntryProfile } from './builders.js';
10
10
  import type { ProviderState } from '../providers/provider-instance.js';
11
- import type { MachineInfo, StatusReportPayload } from '../shared-types.js';
11
+ import type { MachineInfo, RecentSessionBucket, StatusReportPayload } from '../shared-types.js';
12
12
  export interface StatusSnapshotOptions {
13
13
  allStates: ProviderState[];
14
14
  cdpManagers: Map<string, DaemonCdpManager>;
@@ -43,6 +43,21 @@ export interface StatusSnapshotOptions {
43
43
  profile?: SessionEntryProfile;
44
44
  }
45
45
  export type StatusSnapshot = StatusReportPayload;
46
+ export interface RecentReadDebugSnapshot {
47
+ sessionId: string;
48
+ providerType: string;
49
+ status: string;
50
+ inboxBucket: RecentSessionBucket;
51
+ unread: boolean;
52
+ lastSeenAt: number;
53
+ completionMarker: string;
54
+ seenCompletionMarker: string;
55
+ lastUpdated: number;
56
+ lastUsedAt: number;
57
+ lastRole: string;
58
+ messageUpdatedAt: number;
59
+ }
60
+ export declare function shouldEmitRecentReadDebugLog(cache: Map<string, string>, snapshot: RecentReadDebugSnapshot): boolean;
46
61
  export declare function buildMachineInfo(profile?: 'full' | 'live' | 'metadata'): MachineInfo;
47
62
  export declare function getSessionCompletionMarker(session: {
48
63
  activeChat?: {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/session-host-core",
3
- "version": "0.8.58",
3
+ "version": "0.8.60",
4
4
  "description": "ADHDev local session host core — session registry, protocol, buffers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/daemon-core",
3
- "version": "0.8.58",
3
+ "version": "0.8.60",
4
4
  "description": "ADHDev daemon core — CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -30,9 +30,8 @@ export function forwardAgentStreamsToIdeInstance(
30
30
  messages: stream.messages || [],
31
31
  status: stream.status || 'idle',
32
32
  activeModal: stream.activeModal || null,
33
- model: stream.model || undefined,
34
- mode: stream.mode || undefined,
35
33
  controlValues: stream.controlValues || undefined,
34
+ summaryMetadata: stream.summaryMetadata || undefined,
36
35
  effects: stream.effects || undefined,
37
36
  sessionId: stream.sessionId || stream.instanceId || undefined,
38
37
  title: stream.title || stream.agentName || undefined,
@@ -201,7 +201,8 @@ export class DaemonAgentStreamManager {
201
201
  cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
202
202
  const state = await agent.adapter.readChat(evaluate);
203
203
  const stateError = this.getStateError(state);
204
- 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) : ''}`);
204
+ const selectedModelValue = typeof state.controlValues?.model === 'string' ? state.controlValues.model : '';
205
+ LOG.debug('AgentStream', `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${selectedModelValue}${state.status === 'error' ? ' error=' + JSON.stringify(stateError) : ''}`);
205
206
  if (state.status === 'error' && this.isRecoverableSessionError(stateError)) {
206
207
  throw new Error(stateError);
207
208
  }
@@ -13,6 +13,7 @@ import type {
13
13
  } from './types.js';
14
14
  import type { ProviderModule, ProviderScripts } from '../providers/contracts.js';
15
15
  import { extractProviderControlValues, normalizeProviderEffects } from '../providers/control-effects.js';
16
+ import { resolveProviderStateSurface } from '../providers/provider-patch-state.js';
16
17
 
17
18
  export class ProviderStreamAdapter implements IAgentStreamAdapter {
18
19
  readonly agentType: string;
@@ -154,15 +155,18 @@ export class ProviderStreamAdapter implements IAgentStreamAdapter {
154
155
  status: data.status || 'idle',
155
156
  messages: data.messages || [],
156
157
  inputContent: data.inputContent || '',
157
- model: data.model,
158
- mode: data.mode,
159
158
  activeModal: data.activeModal,
160
159
  };
161
160
  if (typeof data.title === 'string' && data.title.trim()) {
162
161
  state.title = data.title.trim();
163
162
  }
164
163
  const controlValues = extractProviderControlValues(this.provider.controls, data);
165
- if (controlValues) state.controlValues = controlValues;
164
+ const surface = resolveProviderStateSurface({
165
+ controlValues,
166
+ summaryMetadata: data.summaryMetadata,
167
+ });
168
+ if (surface.controlValues) state.controlValues = surface.controlValues;
169
+ if (surface.summaryMetadata) state.summaryMetadata = surface.summaryMetadata as any;
166
170
  const effects = normalizeProviderEffects(data);
167
171
  if (effects.length > 0) state.effects = effects;
168
172
  if (state.messages.length > 0) {
@@ -5,6 +5,7 @@
5
5
  * No vscode dependency — can be used as-is.
6
6
  */
7
7
  import type { ProviderEffect } from '../providers/contracts.js';
8
+ import type { ProviderSummaryMetadata } from '../shared-types.js';
8
9
  /** Agent chat message */
9
10
  export interface AgentChatMessage {
10
11
  role: 'user' | 'assistant' | 'system';
@@ -28,10 +29,6 @@ export interface AgentStreamState {
28
29
  messages: AgentChatMessage[];
29
30
  inputContent: string;
30
31
  title?: string;
31
- /** @deprecated Use controlValues['model'] — kept for backward compatibility */
32
- model?: string;
33
- /** @deprecated Use controlValues['mode'] — kept for backward compatibility */
34
- mode?: string;
35
32
  activeModal?: {
36
33
  message: string;
37
34
  buttons: string[];
@@ -40,6 +37,8 @@ export interface AgentStreamState {
40
37
  _error?: string;
41
38
  /** Dynamic control current values (populated from readChat + provider controls schema) */
42
39
  controlValues?: Record<string, string | number | boolean>;
40
+ /** Flexible compact/live summary metadata from readChat */
41
+ summaryMetadata?: ProviderSummaryMetadata;
43
42
  /** Provider-driven UI effects from readChat */
44
43
  effects?: ProviderEffect[];
45
44
  }
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  import type { ProviderEffect } from '../providers/contracts.js';
9
+ import type { ProviderSummaryMetadata } from '../shared-types.js';
9
10
 
10
11
  /** Agent chat message */
11
12
  export interface AgentChatMessage {
@@ -32,15 +33,13 @@ export interface AgentStreamState {
32
33
  messages: AgentChatMessage[];
33
34
  inputContent: string;
34
35
  title?: string;
35
- /** @deprecated Use controlValues['model'] — kept for backward compatibility */
36
- model?: string;
37
- /** @deprecated Use controlValues['mode'] — kept for backward compatibility */
38
- mode?: string;
39
36
  activeModal?: { message: string; buttons: string[] };
40
37
  error?: string;
41
38
  _error?: string;
42
39
  /** Dynamic control current values (populated from readChat + provider controls schema) */
43
40
  controlValues?: Record<string, string | number | boolean>;
41
+ /** Flexible compact/live summary metadata from readChat */
42
+ summaryMetadata?: ProviderSummaryMetadata;
44
43
  /** Provider-driven UI effects from readChat */
45
44
  effects?: ProviderEffect[];
46
45
  }
@@ -183,6 +183,7 @@ export class ProviderCliAdapter implements CliAdapter {
183
183
  private static readonly MAX_TRACE_ENTRIES = 250;
184
184
  private readonly providerResolutionMeta: ProviderResolutionMeta;
185
185
  private static readonly IDLE_FINISH_CONFIRM_MS = 2000;
186
+ private static readonly HERMES_IDLE_FINISH_CONFIRM_MS = 5000;
186
187
  private static readonly STATUS_ACTIVITY_HOLD_MS = 2000;
187
188
  private static readonly FINISH_RETRY_DELAY_MS = 300;
188
189
  private static readonly MAX_FINISH_RETRIES = 2;
@@ -192,6 +193,18 @@ export class ProviderCliAdapter implements CliAdapter {
192
193
  this.structuredMessages = [...this.committedMessages];
193
194
  }
194
195
 
196
+ private getIdleFinishConfirmMs(): number {
197
+ return this.cliType === 'hermes-cli'
198
+ ? ProviderCliAdapter.HERMES_IDLE_FINISH_CONFIRM_MS
199
+ : ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS;
200
+ }
201
+
202
+ private getStatusActivityHoldMs(): number {
203
+ return this.cliType === 'hermes-cli'
204
+ ? ProviderCliAdapter.HERMES_IDLE_FINISH_CONFIRM_MS
205
+ : ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
206
+ }
207
+
195
208
  private setStatus(status: CliSessionStatus['status'], trigger?: string): void {
196
209
  const prev = this.currentStatus;
197
210
  if (prev === status) return;
@@ -216,6 +229,7 @@ export class ProviderCliAdapter implements CliAdapter {
216
229
 
217
230
  private armIdleFinishCandidate(assistantLength: number): void {
218
231
  const now = Date.now();
232
+ const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
219
233
  this.idleFinishCandidate = {
220
234
  armedAt: now,
221
235
  lastOutputAt: this.lastOutputAt,
@@ -224,7 +238,7 @@ export class ProviderCliAdapter implements CliAdapter {
224
238
  assistantLength,
225
239
  };
226
240
  this.recordTrace('idle_candidate_armed', {
227
- confirmMs: ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
241
+ confirmMs: idleFinishConfirmMs,
228
242
  candidate: this.idleFinishCandidate,
229
243
  ...buildCliTraceParseSnapshot({
230
244
  accumulatedBuffer: this.accumulatedBuffer,
@@ -239,7 +253,7 @@ export class ProviderCliAdapter implements CliAdapter {
239
253
  this.settleTimer = null;
240
254
  this.settledBuffer = this.recentOutputBuffer;
241
255
  this.evaluateSettled();
242
- }, ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS);
256
+ }, idleFinishConfirmMs);
243
257
  }
244
258
 
245
259
 
@@ -719,8 +733,9 @@ export class ProviderCliAdapter implements CliAdapter {
719
733
  private hasRecentInteractiveActivity(now: number): boolean {
720
734
  const quietForMs = this.lastNonEmptyOutputAt ? (now - this.lastNonEmptyOutputAt) : Number.MAX_SAFE_INTEGER;
721
735
  const screenStableMs = this.lastScreenChangeAt ? (now - this.lastScreenChangeAt) : Number.MAX_SAFE_INTEGER;
722
- return quietForMs < ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS
723
- || screenStableMs < ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS;
736
+ const holdMs = this.getStatusActivityHoldMs();
737
+ return quietForMs < holdMs
738
+ || screenStableMs < holdMs;
724
739
  }
725
740
 
726
741
  private getStartupConfirmationModal(screenText: string): { message: string; buttons: string[] } | null {
@@ -901,6 +916,7 @@ export class ProviderCliAdapter implements CliAdapter {
901
916
  }
902
917
 
903
918
  const recentInteractiveActivity = this.hasRecentInteractiveActivity(now);
919
+ const statusActivityHoldMs = this.getStatusActivityHoldMs();
904
920
  const shouldHoldGenerating =
905
921
  scriptStatus === 'idle'
906
922
  && this.isWaitingForResponse
@@ -921,7 +937,7 @@ export class ProviderCliAdapter implements CliAdapter {
921
937
  recentInteractiveActivity,
922
938
  lastNonEmptyOutputAt: this.lastNonEmptyOutputAt,
923
939
  lastScreenChangeAt: this.lastScreenChangeAt,
924
- holdMs: ProviderCliAdapter.STATUS_ACTIVITY_HOLD_MS,
940
+ holdMs: statusActivityHoldMs,
925
941
  ...buildCliTraceParseSnapshot({
926
942
  accumulatedBuffer: this.accumulatedBuffer,
927
943
  accumulatedRawBuffer: this.accumulatedRawBuffer,
@@ -1013,8 +1029,9 @@ export class ProviderCliAdapter implements CliAdapter {
1013
1029
  const screenStableMs = this.lastScreenChangeAt ? (now - this.lastScreenChangeAt) : 0;
1014
1030
  const hasAssistantTurn = !!lastParsedAssistant;
1015
1031
  const assistantLength = lastParsedAssistant?.content?.length || 0;
1016
- const idleQuietThresholdMs = Math.max(2000, this.timeouts.outputSettle);
1017
- const idleStableThresholdMs = 2000;
1032
+ const idleFinishConfirmMs = this.getIdleFinishConfirmMs();
1033
+ const idleQuietThresholdMs = Math.max(idleFinishConfirmMs, this.timeouts.outputSettle);
1034
+ const idleStableThresholdMs = idleFinishConfirmMs;
1018
1035
  const idleReady = visibleIdlePrompt
1019
1036
  && !modal
1020
1037
  && hasAssistantTurn
@@ -1026,7 +1043,7 @@ export class ProviderCliAdapter implements CliAdapter {
1026
1043
  && candidate.lastOutputAt === this.lastOutputAt
1027
1044
  && candidate.lastScreenChangeAt === this.lastScreenChangeAt
1028
1045
  && assistantLength >= candidate.assistantLength
1029
- && (now - candidate.armedAt) >= ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS;
1046
+ && (now - candidate.armedAt) >= idleFinishConfirmMs;
1030
1047
  const canFinishImmediately = idleReady && candidateQuiet;
1031
1048
 
1032
1049
  this.recordTrace('idle_decision', {
@@ -1039,7 +1056,7 @@ export class ProviderCliAdapter implements CliAdapter {
1039
1056
  idleQuietThresholdMs,
1040
1057
  idleStableThresholdMs,
1041
1058
  idleReady,
1042
- idleFinishConfirmMs: ProviderCliAdapter.IDLE_FINISH_CONFIRM_MS,
1059
+ idleFinishConfirmMs,
1043
1060
  idleFinishCandidate: candidate,
1044
1061
  candidateQuiet,
1045
1062
  canFinishImmediately,
@@ -17,6 +17,7 @@ import { loadState, saveState } from '../config/state-store.js';
17
17
  import { getWorkspaceState, resolveLaunchDirectory } from '../config/workspaces.js';
18
18
  import { appendRecentActivity } from '../config/recent-activity.js';
19
19
  import { upsertSavedProviderSession } from '../config/saved-sessions.js';
20
+ import { buildLegacyModelModeSummaryMetadata, normalizeProviderSummaryMetadata } from '../providers/summary-metadata.js';
20
21
  import { CliProviderInstance } from '../providers/cli-provider-instance.js';
21
22
  import { AcpProviderInstance } from '../providers/acp-provider-instance.js';
22
23
  import type { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
@@ -273,12 +274,16 @@ export class DaemonCliManager {
273
274
  providerName: string;
274
275
  providerSessionId?: string;
275
276
  workspace?: string;
276
- currentModel?: string;
277
+ summaryMetadata?: unknown;
277
278
  sessionId?: string;
278
279
  title?: string;
279
280
  }): void {
280
281
  try {
281
- let nextState = appendRecentActivity(loadState(), entry);
282
+ const summaryMetadata = normalizeProviderSummaryMetadata(entry.summaryMetadata as any);
283
+ let nextState = appendRecentActivity(loadState(), {
284
+ ...entry,
285
+ summaryMetadata,
286
+ });
282
287
  if (entry.providerSessionId && (entry.kind === 'cli' || entry.kind === 'acp')) {
283
288
  nextState = upsertSavedProviderSession(nextState, {
284
289
  kind: entry.kind,
@@ -286,7 +291,7 @@ export class DaemonCliManager {
286
291
  providerName: entry.providerName,
287
292
  providerSessionId: entry.providerSessionId,
288
293
  workspace: entry.workspace,
289
- currentModel: entry.currentModel,
294
+ summaryMetadata,
290
295
  title: entry.title,
291
296
  });
292
297
  }
@@ -534,7 +539,7 @@ export class DaemonCliManager {
534
539
  providerType: normalizedType,
535
540
  providerName: provider.displayName || provider.name || normalizedType,
536
541
  workspace: resolvedDir,
537
- currentModel: initialModel,
542
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
538
543
  sessionId,
539
544
  title: provider.displayName || provider.name || normalizedType,
540
545
  });
@@ -646,7 +651,7 @@ export class DaemonCliManager {
646
651
  providerName: provider?.displayName || provider?.name || normalizedType,
647
652
  providerSessionId: sessionBinding.providerSessionId,
648
653
  workspace: resolvedDir,
649
- currentModel: initialModel,
654
+ summaryMetadata: buildLegacyModelModeSummaryMetadata({ model: initialModel }),
650
655
  sessionId: key,
651
656
  title: provider?.displayName || provider?.name || normalizedType,
652
657
  });