@adhdev/daemon-core 0.9.40 → 0.9.41

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.
@@ -15,7 +15,7 @@
15
15
  * 5. dispose() → kill process
16
16
  */
17
17
  import type { ProviderModule, ContentBlock, InputEnvelope } from './contracts.js';
18
- import type { ProviderInstance, AcpProviderState, InstanceContext } from './provider-instance.js';
18
+ import type { ProviderInstance, AcpProviderState, InstanceContext, SessionModalState } from './provider-instance.js';
19
19
  export declare function buildAcpPromptParts(input: InputEnvelope, agentCapabilities?: Record<string, any>): ContentBlock[];
20
20
  export declare class AcpProviderInstance implements ProviderInstance {
21
21
  private cliArgs;
@@ -59,6 +59,7 @@ export declare class AcpProviderInstance implements ProviderInstance {
59
59
  constructor(provider: ProviderModule, workingDir: string, cliArgs?: string[]);
60
60
  init(context: InstanceContext): Promise<void>;
61
61
  onTick(): Promise<void>;
62
+ getSessionModalState(): SessionModalState;
62
63
  getState(): AcpProviderState;
63
64
  onEvent(event: string, data?: any): void;
64
65
  getInstanceId(): string;
@@ -5,7 +5,7 @@
5
5
  * collectCliData() + status transition logic from daemon-status.ts moved here.
6
6
  */
7
7
  import { type ProviderModule } from './contracts.js';
8
- import type { ProviderInstance, ProviderState, InstanceContext, HotChatSessionState } from './provider-instance.js';
8
+ import type { ProviderInstance, ProviderState, InstanceContext, HotChatSessionState, SessionModalState } from './provider-instance.js';
9
9
  import { ProviderCliAdapter } from '../cli-adapters/provider-cli-adapter.js';
10
10
  import type { PtyTransportFactory } from '../cli-adapters/pty-transport.js';
11
11
  type PersistableCliHistoryMessage = {
@@ -91,6 +91,7 @@ export declare class CliProviderInstance implements ProviderInstance {
91
91
  setPresentationMode(mode: 'terminal' | 'chat'): void;
92
92
  getPresentationMode(): 'terminal' | 'chat';
93
93
  getHotChatSessionState(): HotChatSessionState;
94
+ getSessionModalState(): SessionModalState;
94
95
  updateSettings(newSettings: Record<string, any>): void;
95
96
  onEvent(event: string, data?: any): void;
96
97
  dispose(): void;
@@ -5,7 +5,7 @@
5
5
  * CDP webview discovery + agent stream collection moved here.
6
6
  */
7
7
  import { type ProviderModule } from './contracts.js';
8
- import type { ProviderInstance, ProviderState, InstanceContext } from './provider-instance.js';
8
+ import type { ProviderInstance, ProviderState, InstanceContext, SessionModalState } from './provider-instance.js';
9
9
  export declare class ExtensionProviderInstance implements ProviderInstance {
10
10
  readonly type: string;
11
11
  readonly category: "extension";
@@ -37,6 +37,7 @@ export declare class ExtensionProviderInstance implements ProviderInstance {
37
37
  init(context: InstanceContext): Promise<void>;
38
38
  onTick(): Promise<void>;
39
39
  getState(): ProviderState;
40
+ getSessionModalState(sessionId?: string): SessionModalState | null;
40
41
  onEvent(event: string, data?: any): void;
41
42
  dispose(): void;
42
43
  updateSettings(newSettings: Record<string, any>): void;
@@ -9,7 +9,7 @@
9
9
  * Daemon collects all via a single IDE Instance.getState() call.
10
10
  */
11
11
  import { type ProviderModule } from './contracts.js';
12
- import type { ProviderInstance, ProviderState, InstanceContext } from './provider-instance.js';
12
+ import type { ProviderInstance, ProviderState, InstanceContext, SessionModalState } from './provider-instance.js';
13
13
  import { ExtensionProviderInstance } from './extension-provider-instance.js';
14
14
  export declare class IdeProviderInstance implements ProviderInstance {
15
15
  readonly type: string;
@@ -37,6 +37,7 @@ export declare class IdeProviderInstance implements ProviderInstance {
37
37
  init(context: InstanceContext): Promise<void>;
38
38
  onTick(): Promise<void>;
39
39
  getState(): ProviderState;
40
+ getSessionModalState(sessionId?: string): SessionModalState | null;
40
41
  onEvent(event: string, data?: any): void;
41
42
  dispose(): void;
42
43
  updateSettings(newSettings: Record<string, any>): void;
@@ -7,7 +7,7 @@
7
7
  * 3. Collect overall state
8
8
  * 4. Event collection and propagation
9
9
  */
10
- import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext, HotChatSessionState } from './provider-instance.js';
10
+ import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext, HotChatSessionState, SessionModalState } from './provider-instance.js';
11
11
  export declare class ProviderInstanceManager {
12
12
  private instances;
13
13
  private tickTimer;
@@ -46,6 +46,9 @@ export declare class ProviderInstanceManager {
46
46
  */
47
47
  collectAllStates(): ProviderState[];
48
48
  collectHotChatSessionStates(): HotChatSessionState[];
49
+ getSessionModalState(sessionId: string, options?: {
50
+ instanceKey?: string | null;
51
+ }): SessionModalState | null;
49
52
  /**
50
53
  * Per-category status collect
51
54
  */
@@ -123,6 +123,12 @@ export interface HotChatSessionState {
123
123
  runtimeRestoredFromStorage?: unknown;
124
124
  runtimeRecoveryState?: unknown;
125
125
  }
126
+ export interface SessionModalState {
127
+ id: string;
128
+ status?: unknown;
129
+ title?: unknown;
130
+ activeModal?: unknown;
131
+ }
126
132
  export interface InstanceContext {
127
133
  /** CDP connection (IDE/Extension) */
128
134
  cdp?: {
@@ -159,6 +165,11 @@ export interface ProviderInstance {
159
165
  * parsing here; callers use this on P2P hot flush paths.
160
166
  */
161
167
  getHotChatSessionState?(): HotChatSessionState | HotChatSessionState[] | null;
168
+ /**
169
+ * Return the cheap modal metadata for a single session subscription. This is
170
+ * used on P2P topic flushes and must not invoke rich chat/transcript parsing.
171
+ */
172
+ getSessionModalState?(sessionId?: string): SessionModalState | null;
162
173
  /** Receive event (external → Instance) */
163
174
  onEvent(event: string, data?: any): void;
164
175
  /** Update settings at runtime (called when user changes settings from dashboard) */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/session-host-core",
3
- "version": "0.9.40",
3
+ "version": "0.9.41",
4
4
  "description": "ADHDev local session host core \u2014 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.9.40",
3
+ "version": "0.9.41",
4
4
  "description": "ADHDev daemon core \u2014 CDP, IDE detection, providers, command execution",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -273,12 +273,10 @@ export class ProviderCliAdapter implements CliAdapter {
273
273
  currentTurnScope: TurnParseScope | null;
274
274
  recentOutputBuffer: string;
275
275
  accumulatedBuffer: string;
276
- accumulatedRawBuffer: string;
277
276
  screenText: string;
278
277
  currentStatus: CliSessionStatus['status'];
279
278
  activeModal: { message: string; buttons: string[] } | null;
280
279
  cliName: string;
281
- lastOutputAt: number;
282
280
  result: any;
283
281
  } | null = null;
284
282
  private lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
@@ -352,12 +350,10 @@ export class ProviderCliAdapter implements CliAdapter {
352
350
  && cached.currentTurnScope === this.currentTurnScope
353
351
  && cached.recentOutputBuffer === this.recentOutputBuffer
354
352
  && cached.accumulatedBuffer === this.accumulatedBuffer
355
- && cached.accumulatedRawBuffer === this.accumulatedRawBuffer
356
353
  && cached.screenText === this.lastScreenText
357
354
  && cached.currentStatus === this.currentStatus
358
355
  && cached.activeModal === this.activeModal
359
356
  && cached.cliName === this.cliName
360
- && cached.lastOutputAt === this.lastOutputAt
361
357
  ) {
362
358
  return cached.result;
363
359
  }
@@ -1835,12 +1831,10 @@ export class ProviderCliAdapter implements CliAdapter {
1835
1831
  && cached.currentTurnScope === this.currentTurnScope
1836
1832
  && cached.recentOutputBuffer === this.recentOutputBuffer
1837
1833
  && cached.accumulatedBuffer === this.accumulatedBuffer
1838
- && cached.accumulatedRawBuffer === this.accumulatedRawBuffer
1839
1834
  && cached.screenText === screenText
1840
1835
  && cached.currentStatus === this.currentStatus
1841
1836
  && cached.activeModal === this.activeModal
1842
1837
  && cached.cliName === this.cliName
1843
- && cached.lastOutputAt === this.lastOutputAt
1844
1838
  ) {
1845
1839
  return cached.result;
1846
1840
  }
@@ -2002,12 +1996,10 @@ export class ProviderCliAdapter implements CliAdapter {
2002
1996
  currentTurnScope: this.currentTurnScope,
2003
1997
  recentOutputBuffer: this.recentOutputBuffer,
2004
1998
  accumulatedBuffer: this.accumulatedBuffer,
2005
- accumulatedRawBuffer: this.accumulatedRawBuffer,
2006
1999
  screenText,
2007
2000
  currentStatus: this.currentStatus,
2008
2001
  activeModal: this.activeModal,
2009
2002
  cliName: this.cliName,
2010
- lastOutputAt: this.lastOutputAt,
2011
2003
  result,
2012
2004
  };
2013
2005
  return result;
@@ -49,7 +49,7 @@ import {
49
49
  import type { ProviderModule, ContentBlock, InputEnvelope, ToolCallInfo, ToolCallContent as TCC, ToolKind, ToolCallStatus as TCS } from './contracts.js';
50
50
  import { normalizeContent, flattenContent, normalizeInputEnvelope } from './contracts.js';
51
51
  import { assertProviderSupportsDeclaredInput } from './provider-input-support.js';
52
- import type { ProviderInstance, ProviderState, AcpProviderState, ProviderErrorReason, ProviderEvent, InstanceContext } from './provider-instance.js';
52
+ import type { ProviderInstance, ProviderState, AcpProviderState, ProviderErrorReason, ProviderEvent, InstanceContext, SessionModalState } from './provider-instance.js';
53
53
  import { StatusMonitor } from './status-monitor.js';
54
54
  import { buildLegacyModelModeSummaryMetadata } from './summary-metadata.js';
55
55
  import {
@@ -283,6 +283,19 @@ export class AcpProviderInstance implements ProviderInstance {
283
283
  }
284
284
  }
285
285
 
286
+ getSessionModalState(): SessionModalState {
287
+ const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
288
+ return {
289
+ id: this.instanceId,
290
+ status: this.currentStatus,
291
+ title: `${this.provider.name} · ${dirName}`,
292
+ activeModal: this.currentStatus === 'waiting_approval' ? {
293
+ message: this.activeToolCalls.find(t => t.status === 'running')?.name || 'Permission requested',
294
+ buttons: ['Approve', 'Reject'],
295
+ } : null,
296
+ };
297
+ }
298
+
286
299
  getState(): AcpProviderState {
287
300
  const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
288
301
 
@@ -12,7 +12,7 @@ import * as fs from 'fs';
12
12
  import { createRequire } from 'node:module';
13
13
  import { normalizeInputEnvelope, type ProviderModule, flattenContent } from './contracts.js';
14
14
  import { assertTextOnlyInput } from './provider-input-support.js';
15
- import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext, ProviderErrorReason, HotChatSessionState } from './provider-instance.js';
15
+ import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext, ProviderErrorReason, HotChatSessionState, SessionModalState } from './provider-instance.js';
16
16
  import { ProviderCliAdapter } from '../cli-adapters/provider-cli-adapter.js';
17
17
  import type { CliProviderModule } from '../cli-adapters/provider-cli-adapter.js';
18
18
  import type { PtyRuntimeMetadata, PtyTransportFactory } from '../cli-adapters/pty-transport.js';
@@ -533,6 +533,19 @@ export class CliProviderInstance implements ProviderInstance {
533
533
  };
534
534
  }
535
535
 
536
+ getSessionModalState(): SessionModalState {
537
+ const adapterStatus = this.adapter.getStatus({ allowParse: false });
538
+ const autoApproveActive = adapterStatus.status === 'waiting_approval' && this.shouldAutoApprove();
539
+ const visibleStatus = autoApproveActive ? 'generating' : adapterStatus.status;
540
+ const dirName = this.workingDir.split('/').filter(Boolean).pop() || 'session';
541
+ return {
542
+ id: this.instanceId,
543
+ status: visibleStatus,
544
+ title: dirName,
545
+ activeModal: autoApproveActive ? null : adapterStatus.activeModal,
546
+ };
547
+ }
548
+
536
549
  updateSettings(newSettings: Record<string, any>): void {
537
550
  this.settings = { ...newSettings };
538
551
  this.adapter.updateRuntimeSettings?.(this.settings);
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import { flattenContent, type ProviderModule } from './contracts.js';
9
- import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext } from './provider-instance.js';
9
+ import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext, SessionModalState } from './provider-instance.js';
10
10
  import { StatusMonitor } from './status-monitor.js';
11
11
  import { buildPersistedProviderEffectMessage, normalizeProviderEffects } from './control-effects.js';
12
12
  import { ChatHistoryWriter } from '../config/chat-history.js';
@@ -110,6 +110,16 @@ export class ExtensionProviderInstance implements ProviderInstance {
110
110
  };
111
111
  }
112
112
 
113
+ getSessionModalState(sessionId?: string): SessionModalState | null {
114
+ if (sessionId && sessionId !== this.instanceId) return null;
115
+ return {
116
+ id: this.instanceId,
117
+ status: this.currentStatus,
118
+ title: this.chatTitle || this.agentName || this.provider.name,
119
+ activeModal: this.activeModal,
120
+ };
121
+ }
122
+
113
123
  onEvent(event: string, data?: any): void {
114
124
  if (event === 'stream_update') {
115
125
  // Reflect data collected from agent-stream-manager
@@ -12,7 +12,7 @@
12
12
  import * as os from 'os';
13
13
  import * as crypto from 'crypto';
14
14
  import { flattenContent, type ProviderModule } from './contracts.js';
15
- import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext } from './provider-instance.js';
15
+ import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext, SessionModalState } from './provider-instance.js';
16
16
  import { ExtensionProviderInstance } from './extension-provider-instance.js';
17
17
  import { StatusMonitor } from './status-monitor.js';
18
18
  import { ChatHistoryWriter } from '../config/chat-history.js';
@@ -172,6 +172,30 @@ export class IdeProviderInstance implements ProviderInstance {
172
172
  };
173
173
  }
174
174
 
175
+ getSessionModalState(sessionId?: string): SessionModalState | null {
176
+ if (sessionId && sessionId !== this.instanceId) {
177
+ for (const ext of this.extensions.values()) {
178
+ const projected = ext.getSessionModalState?.(sessionId);
179
+ if (projected?.id === sessionId) return projected;
180
+ }
181
+ return null;
182
+ }
183
+
184
+ const autoApproveActive = (
185
+ this.currentStatus === 'waiting_approval'
186
+ || this.cachedChat?.status === 'waiting_approval'
187
+ ) && this.canAutoApprove();
188
+ const visibleStatus = autoApproveActive ? 'generating' : this.currentStatus;
189
+ return {
190
+ id: this.instanceId,
191
+ status: autoApproveActive && this.cachedChat?.status === 'waiting_approval'
192
+ ? 'generating'
193
+ : (this.cachedChat?.status || visibleStatus),
194
+ title: this.cachedChat?.title || this.type,
195
+ activeModal: autoApproveActive ? null : (this.cachedChat?.activeModal || null),
196
+ };
197
+ }
198
+
175
199
  onEvent(event: string, data?: any): void {
176
200
  if (event === 'cdp_connected') {
177
201
  // CDP connection done
@@ -8,7 +8,7 @@
8
8
  * 4. Event collection and propagation
9
9
  */
10
10
 
11
- import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext, HotChatSessionState } from './provider-instance.js';
11
+ import type { ProviderInstance, ProviderState, ProviderEvent, InstanceContext, HotChatSessionState, SessionModalState } from './provider-instance.js';
12
12
  import { LOG } from '../logging/logger.js';
13
13
 
14
14
  function projectHotChatSessionStatesFromProviderState(state: ProviderState): HotChatSessionState[] {
@@ -165,6 +165,32 @@ export class ProviderInstanceManager {
165
165
  return sessions;
166
166
  }
167
167
 
168
+ getSessionModalState(sessionId: string, options: { instanceKey?: string | null } = {}): SessionModalState | null {
169
+ if (!sessionId) return null;
170
+ const candidates = [sessionId];
171
+ if (options.instanceKey && options.instanceKey !== sessionId) {
172
+ candidates.push(options.instanceKey);
173
+ }
174
+
175
+ for (const id of candidates) {
176
+ const instance = this.instances.get(id);
177
+ if (!instance?.getSessionModalState) continue;
178
+ try {
179
+ const projected = instance.getSessionModalState(sessionId);
180
+ if (!projected?.id) continue;
181
+ if (projected.id !== sessionId) {
182
+ LOG.warn('InstanceMgr', `[InstanceManager] Ignoring mismatched session modal projection from ${id}: requested=${sessionId} projected=${projected.id}`);
183
+ continue;
184
+ }
185
+ return projected;
186
+ } catch (e) {
187
+ LOG.warn('InstanceMgr', `[InstanceManager] Failed to project session modal metadata from ${id}: ${(e as Error).message}`);
188
+ }
189
+ }
190
+
191
+ return null;
192
+ }
193
+
168
194
  /**
169
195
  * Per-category status collect
170
196
  */
@@ -147,6 +147,13 @@ export interface HotChatSessionState {
147
147
  runtimeRecoveryState?: unknown;
148
148
  }
149
149
 
150
+ export interface SessionModalState {
151
+ id: string;
152
+ status?: unknown;
153
+ title?: unknown;
154
+ activeModal?: unknown;
155
+ }
156
+
150
157
  // ─── ProviderInstance interface ─────────────────
151
158
 
152
159
  export interface InstanceContext {
@@ -191,6 +198,12 @@ export interface ProviderInstance {
191
198
  */
192
199
  getHotChatSessionState?(): HotChatSessionState | HotChatSessionState[] | null;
193
200
 
201
+ /**
202
+ * Return the cheap modal metadata for a single session subscription. This is
203
+ * used on P2P topic flushes and must not invoke rich chat/transcript parsing.
204
+ */
205
+ getSessionModalState?(sessionId?: string): SessionModalState | null;
206
+
194
207
  /** Receive event (external → Instance) */
195
208
  onEvent(event: string, data?: any): void;
196
209