@adhdev/daemon-core 0.8.29 → 0.8.31

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 (63) hide show
  1. package/dist/agent-stream/manager.d.ts +1 -0
  2. package/dist/agent-stream/provider-adapter.d.ts +1 -0
  3. package/dist/agent-stream/types.d.ts +3 -0
  4. package/dist/boot/daemon-lifecycle.d.ts +2 -1
  5. package/dist/cdp/manager.d.ts +2 -0
  6. package/dist/cli-adapter-types.d.ts +34 -5
  7. package/dist/cli-adapters/provider-cli-adapter.d.ts +4 -158
  8. package/dist/cli-adapters/provider-cli-config.d.ts +30 -0
  9. package/dist/cli-adapters/provider-cli-parse.d.ts +42 -0
  10. package/dist/cli-adapters/provider-cli-runtime.d.ts +29 -0
  11. package/dist/cli-adapters/provider-cli-shared.d.ts +158 -0
  12. package/dist/commands/handler.d.ts +4 -3
  13. package/dist/config/config.d.ts +4 -3
  14. package/dist/index.js +1033 -621
  15. package/dist/index.js.map +1 -1
  16. package/dist/index.mjs +1035 -624
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/providers/acp-provider-instance.d.ts +1 -0
  19. package/dist/providers/approval-utils.d.ts +7 -0
  20. package/dist/providers/cli-provider-instance.d.ts +2 -0
  21. package/dist/providers/contracts.d.ts +12 -1
  22. package/dist/providers/ide-provider-instance.d.ts +1 -0
  23. package/dist/providers/provider-loader.d.ts +3 -0
  24. package/dist/status/reporter.d.ts +2 -3
  25. package/dist/status/snapshot.d.ts +2 -1
  26. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  27. package/package.json +3 -1
  28. package/src/agent-stream/manager.ts +8 -2
  29. package/src/agent-stream/poller.ts +57 -6
  30. package/src/agent-stream/provider-adapter.ts +11 -7
  31. package/src/agent-stream/types.ts +3 -0
  32. package/src/boot/daemon-lifecycle.ts +7 -6
  33. package/src/cdp/initializer.ts +2 -2
  34. package/src/cdp/manager.ts +5 -0
  35. package/src/cdp/setup.ts +1 -1
  36. package/src/cli-adapter-types.ts +37 -5
  37. package/src/cli-adapters/provider-cli-adapter.ts +212 -795
  38. package/src/cli-adapters/provider-cli-config.ts +66 -0
  39. package/src/cli-adapters/provider-cli-parse.ts +202 -0
  40. package/src/cli-adapters/provider-cli-runtime.ts +142 -0
  41. package/src/cli-adapters/provider-cli-shared.ts +439 -0
  42. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.ts +1 -1
  43. package/src/commands/cdp-commands.ts +6 -1
  44. package/src/commands/chat-commands.ts +45 -29
  45. package/src/commands/cli-manager.ts +28 -9
  46. package/src/commands/handler.ts +14 -10
  47. package/src/commands/router.ts +23 -10
  48. package/src/commands/stream-commands.ts +11 -5
  49. package/src/config/config.ts +4 -10
  50. package/src/daemon/dev-auto-implement.ts +22 -18
  51. package/src/daemon/dev-cli-debug.ts +59 -16
  52. package/src/daemon/dev-server.ts +67 -43
  53. package/src/providers/acp-provider-instance.ts +18 -3
  54. package/src/providers/approval-utils.ts +66 -0
  55. package/src/providers/cli-provider-instance.ts +32 -6
  56. package/src/providers/contracts.d.ts +1 -0
  57. package/src/providers/contracts.ts +15 -2
  58. package/src/providers/extension-provider-instance.ts +1 -1
  59. package/src/providers/ide-provider-instance.ts +67 -41
  60. package/src/providers/provider-loader.ts +110 -55
  61. package/src/providers/version-archive.ts +23 -5
  62. package/src/status/reporter.ts +18 -14
  63. package/src/status/snapshot.ts +5 -4
@@ -93,6 +93,7 @@ export declare class AcpProviderInstance implements ProviderInstance {
93
93
  private convertToolCallContent;
94
94
  private detectStatusTransition;
95
95
  private pushEvent;
96
+ private appendSystemMessage;
96
97
  private flushEvents;
97
98
  get cliType(): string;
98
99
  get cliName(): string;
@@ -0,0 +1,7 @@
1
+ import type { ProviderModule } from './contracts.js';
2
+ export declare function getApprovalPositiveHints(provider?: Pick<ProviderModule, 'approvalPositiveHints'> | null): string[];
3
+ export declare function pickApprovalButton(buttons: string[] | null | undefined, provider?: Pick<ProviderModule, 'approvalPositiveHints'> | null): {
4
+ index: number;
5
+ label: string;
6
+ };
7
+ export declare function formatAutoApprovalMessage(modalMessage?: string, buttonLabel?: string): string;
@@ -71,6 +71,8 @@ export declare class CliProviderInstance implements ProviderInstance {
71
71
  getAdapter(): ProviderCliAdapter;
72
72
  get cliType(): string;
73
73
  get cliName(): string;
74
+ private shouldAutoApprove;
75
+ private recordAutoApproval;
74
76
  recordApprovalSelection(buttonText: string): void;
75
77
  private formatMarkerTimestamp;
76
78
  private maybeAppendRuntimeRecoveryMessage;
@@ -233,6 +233,11 @@ export interface CdpTargetFilter {
233
233
  /** Page title regex pattern for titles to EXCLUDE (e.g. 'Debug Console|Output') */
234
234
  titleExcludes?: string;
235
235
  }
236
+ export type ProviderVersionCommand = string | Partial<Record<string, string>>;
237
+ export interface ProviderCompatibilityEntry {
238
+ ideVersion: string;
239
+ scriptDir: string;
240
+ }
236
241
  export interface ProviderModule {
237
242
  /** Unique identifier (e.g. 'cline', 'cursor', 'gemini-cli') */
238
243
  type: string;
@@ -255,7 +260,7 @@ export interface ProviderModule {
255
260
  /** Install instructions (shown when command is missing) */
256
261
  install?: string;
257
262
  /** Custom version detection command (e.g. 'cursor --version', 'claude -v') */
258
- versionCommand?: string;
263
+ versionCommand?: ProviderVersionCommand;
259
264
  /** Versions tested by provider maintainer (informational) */
260
265
  testedVersions?: string[];
261
266
  /** Per-OS process names — used by launch.ts to detect/kill IDE processes */
@@ -296,6 +301,9 @@ export interface ProviderModule {
296
301
  };
297
302
  extensionId?: string;
298
303
  extensionIdPattern?: RegExp;
304
+ extensionIdPattern_flags?: string;
305
+ compatibility?: ProviderCompatibilityEntry[];
306
+ defaultScriptDir?: string;
299
307
  binary?: string;
300
308
  spawn?: {
301
309
  command: string;
@@ -303,6 +311,7 @@ export interface ProviderModule {
303
311
  shell?: boolean;
304
312
  env?: Record<string, string>;
305
313
  };
314
+ approvalKeys?: Record<number, string>;
306
315
  patterns?: {
307
316
  prompt?: RegExp[];
308
317
  generating?: RegExp[];
@@ -313,6 +322,8 @@ export interface ProviderModule {
313
322
  resume?: ProviderResumeCapability;
314
323
  /** Session ID probe config — auto-discovers provider session ID from local SQLite DB */
315
324
  sessionProbe?: ProviderSessionProbe;
325
+ /** Approval button priority hints used when auto-approve must pick a positive action */
326
+ approvalPositiveHints?: string[];
316
327
  scripts?: ProviderScripts;
317
328
  vscodeCommands?: {
318
329
  focusPanel?: string;
@@ -65,5 +65,6 @@ export declare class IdeProviderInstance implements ProviderInstance {
65
65
  private getEffectDedupKey;
66
66
  private flushEvents;
67
67
  updateCdp(cdp: InstanceContext['cdp']): void;
68
+ private canAutoApprove;
68
69
  private autoApproveViaScript;
69
70
  }
@@ -266,6 +266,9 @@ export declare class ProviderLoader {
266
266
  */
267
267
  setSetting(type: string, key: string, value: any): boolean;
268
268
  private getOptionalStringSetting;
269
+ protected readConfig(): any | null;
270
+ protected writeConfig(config: any): void;
271
+ private getPlatformVersionCommand;
269
272
  private getSettingsSchema;
270
273
  private getSyntheticSettings;
271
274
  /**
@@ -4,6 +4,7 @@
4
4
  * Collect status from ProviderInstanceManager → assemble payload → transmit
5
5
  * Each Instance manages its own status/transition. This module only assembles + transmits.
6
6
  */
7
+ import type { DaemonCdpManager } from '../cdp/manager.js';
7
8
  import type { ProviderState } from '../providers/provider-instance.js';
8
9
  export interface StatusReporterDeps {
9
10
  serverConn: {
@@ -11,9 +12,7 @@ export interface StatusReporterDeps {
11
12
  sendMessage(type: string, data: any): void;
12
13
  getUserPlan(): string;
13
14
  } | null;
14
- cdpManagers: Map<string, {
15
- isConnected: boolean;
16
- }>;
15
+ cdpManagers: Map<string, DaemonCdpManager>;
17
16
  p2p: {
18
17
  isConnected: boolean;
19
18
  isAvailable: boolean;
@@ -5,11 +5,12 @@
5
5
  * - DaemonStatusReporter (cloud)
6
6
  * - daemon-standalone HTTP/WS status responses
7
7
  */
8
+ import type { DaemonCdpManager } from '../cdp/manager.js';
8
9
  import type { ProviderState } from '../providers/provider-instance.js';
9
10
  import type { AvailableProviderInfo, StatusReportPayload } from '../shared-types.js';
10
11
  export interface StatusSnapshotOptions {
11
12
  allStates: ProviderState[];
12
- cdpManagers: Map<string, unknown>;
13
+ cdpManagers: Map<string, DaemonCdpManager>;
13
14
  providerLoader: {
14
15
  getAll(): Array<{
15
16
  type: string;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adhdev/session-host-core",
3
- "version": "0.8.29",
3
+ "version": "0.8.31",
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.29",
3
+ "version": "0.8.31",
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",
@@ -22,6 +22,8 @@
22
22
  "build": "tsup && npm run build:types",
23
23
  "build:types": "tsc -p tsconfig.json --emitDeclarationOnly --declaration --declarationMap false",
24
24
  "dev": "tsup --watch",
25
+ "test": "vitest run",
26
+ "test:watch": "vitest",
25
27
  "typecheck": "tsc --noEmit -p tsconfig.json"
26
28
  },
27
29
  "files": [
@@ -121,6 +121,12 @@ export class DaemonAgentStreamManager {
121
121
  return child?.sessionId || null;
122
122
  }
123
123
 
124
+ private getStateError(state: AgentStreamState): string {
125
+ if (typeof state.error === 'string' && state.error.trim()) return state.error.trim();
126
+ if (typeof state._error === 'string' && state._error.trim()) return state._error.trim();
127
+ return 'unknown';
128
+ }
129
+
124
130
  private async connectManagedSession(
125
131
  cdp: DaemonCdpManager,
126
132
  parentSessionId: string,
@@ -194,8 +200,8 @@ export class DaemonAgentStreamManager {
194
200
  const evaluate: AgentEvaluateFn = (expr, timeout) =>
195
201
  cdp.evaluateInSessionFrame(agent.cdpSessionId, expr, timeout);
196
202
  const state = await agent.adapter.readChat(evaluate);
197
- LOG.debug('AgentStream', `[AgentStream] readChat(${type}) result: status=${state.status} msgs=${state.messages?.length || 0} model=${state.model || ''}${state.status === 'error' ? ' error=' + JSON.stringify((state as any).error || (state as any)._error || 'unknown') : ''}`);
198
- const stateError = String((state as any).error || (state as any)._error || '');
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) : ''}`);
199
205
  if (state.status === 'error' && this.isRecoverableSessionError(stateError)) {
200
206
  throw new Error(stateError);
201
207
  }
@@ -19,6 +19,21 @@ import type { SessionRegistry } from '../sessions/registry.js';
19
19
  import { reconcileIdeRuntimeSessions } from '../sessions/reconcile.js';
20
20
  import { LOG } from '../logging/logger.js';
21
21
  import type { AgentStreamState } from './types.js';
22
+ import { formatAutoApprovalMessage, pickApprovalButton } from '../providers/approval-utils.js';
23
+ import type { ProviderModule } from '../providers/contracts.js';
24
+
25
+ interface ExtensionInstanceLike {
26
+ type?: string;
27
+ getInstanceId?(): string;
28
+ }
29
+
30
+ interface IdeInstanceLike {
31
+ getInstanceId?(): string;
32
+ getExtensionTypes?(): string[];
33
+ getExtension?(type: string): ExtensionInstanceLike | undefined;
34
+ addExtension?(provider: ProviderModule, settings: Record<string, unknown>): void;
35
+ removeExtension?(type: string): void;
36
+ }
22
37
 
23
38
  // ─── Types ───
24
39
 
@@ -80,7 +95,7 @@ export class AgentStreamPoller {
80
95
  if (!agentStreamManager || cdpManagers.size === 0) return;
81
96
 
82
97
  // Defensive repair: keep SessionRegistry aligned with live IDE/extension instances.
83
- reconcileIdeRuntimeSessions(instanceManager as any, sessionRegistry);
98
+ reconcileIdeRuntimeSessions(instanceManager, sessionRegistry);
84
99
 
85
100
  // ─── Phase 1: Refresh extension providers + IDE instance extensions ───
86
101
  for (const [ideType, cdp] of cdpManagers) {
@@ -88,12 +103,12 @@ export class AgentStreamPoller {
88
103
  registerExtensionProviders(providerLoader, cdp, ideType);
89
104
 
90
105
  // 1b. Dynamically add/remove IDE instance extensions
91
- const ideInstance = instanceManager.getInstance(`ide:${ideType}`) as any;
106
+ const ideInstance = instanceManager.getInstance(`ide:${ideType}`) as IdeInstanceLike | undefined;
92
107
  const parentSessionId = ideInstance?.getInstanceId?.();
93
108
  if (ideInstance?.getExtensionTypes && ideInstance?.addExtension && ideInstance?.removeExtension) {
94
- const currentExtTypes = new Set(ideInstance.getExtensionTypes() as string[]);
109
+ const currentExtTypes = new Set(ideInstance.getExtensionTypes());
95
110
  const enabledExtTypes = new Set(
96
- providerLoader.getEnabledByCategory('extension', ideType).map((p: any) => p.type)
111
+ providerLoader.getEnabledByCategory('extension', ideType).map((p) => p.type)
97
112
  );
98
113
 
99
114
  // Remove disabled extensions
@@ -145,7 +160,7 @@ export class AgentStreamPoller {
145
160
  const activeSessionId = parentSessionId ? agentStreamManager.getActiveSessionId(parentSessionId) : null;
146
161
  if (activeSessionId) {
147
162
  const activeTarget = sessionRegistry.get(activeSessionId);
148
- const enabledExtTypes = new Set(providerLoader.getEnabledExtensionProviders(ideType).map((p: any) => p.type));
163
+ const enabledExtTypes = new Set(providerLoader.getEnabledExtensionProviders(ideType).map((p) => p.type));
149
164
  if (!activeTarget || !enabledExtTypes.has(activeTarget.providerType)) {
150
165
  LOG.info('AgentStream', `Active agent ${activeTarget?.providerType || activeSessionId} was disabled for ${ideType} — detaching`);
151
166
  await agentStreamManager.setActiveSession(cdp, parentSessionId!, null);
@@ -189,7 +204,43 @@ export class AgentStreamPoller {
189
204
 
190
205
  try {
191
206
  await agentStreamManager.syncActiveSession(cdp, parentSessionId);
192
- const stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
207
+ let stream = await agentStreamManager.collectActiveSession(cdp, parentSessionId);
208
+ if (stream?.status === 'waiting_approval') {
209
+ const autoApprove = providerLoader.getSettings(stream.agentType).autoApprove !== false;
210
+ if (autoApprove && resolvedActiveSessionId) {
211
+ const provider = providerLoader.getMeta(stream.agentType);
212
+ const { label: buttonLabel } = pickApprovalButton(stream.activeModal?.buttons, provider);
213
+ const approved = await agentStreamManager.resolveSessionAction(cdp, resolvedActiveSessionId, 'approve', buttonLabel);
214
+ if (approved) {
215
+ const effectId = [
216
+ 'auto_approval',
217
+ resolvedActiveSessionId,
218
+ String(stream.messages?.length || 0),
219
+ buttonLabel,
220
+ String(stream.activeModal?.message || '').trim(),
221
+ ].join(':');
222
+ stream = {
223
+ ...stream,
224
+ status: 'streaming',
225
+ activeModal: undefined,
226
+ effects: [
227
+ ...(stream.effects || []),
228
+ {
229
+ type: 'message',
230
+ id: effectId,
231
+ persist: true,
232
+ message: {
233
+ role: 'system',
234
+ senderName: 'System',
235
+ kind: 'system',
236
+ content: formatAutoApprovalMessage(stream.activeModal?.message, buttonLabel),
237
+ },
238
+ },
239
+ ],
240
+ };
241
+ }
242
+ }
243
+ }
193
244
  this.deps.onStreamsUpdated?.(ideType, stream ? [stream] : []);
194
245
  } catch { }
195
246
  }
@@ -11,7 +11,7 @@ import type {
11
11
  AgentChatListItem,
12
12
  AgentEvaluateFn,
13
13
  } from './types.js';
14
- import type { ProviderModule } from '../providers/contracts.js';
14
+ import type { ProviderModule, ProviderScripts } from '../providers/contracts.js';
15
15
  import { extractProviderControlValues, normalizeProviderEffects } from '../providers/control-effects.js';
16
16
 
17
17
  export class ProviderStreamAdapter implements IAgentStreamAdapter {
@@ -32,13 +32,17 @@ export class ProviderStreamAdapter implements IAgentStreamAdapter {
32
32
  }
33
33
 
34
34
  private callScript(name: string, ...args: any[]): string | null {
35
- const fn = (this.provider.scripts as any)?.[name];
35
+ const fn = this.provider.scripts?.[name];
36
36
  if (typeof fn !== 'function') return null;
37
37
  return fn(...args) || null;
38
38
  }
39
39
 
40
40
  private hasScript(name: string): boolean {
41
- return typeof (this.provider.scripts as any)?.[name] === 'function';
41
+ return typeof this.provider.scripts?.[name] === 'function';
42
+ }
43
+
44
+ private getStateTitle(state: AgentStreamState): string {
45
+ return typeof state.title === 'string' ? state.title : '';
42
46
  }
43
47
 
44
48
  private parseMaybeJson(raw: unknown): any {
@@ -83,7 +87,7 @@ export class ProviderStreamAdapter implements IAgentStreamAdapter {
83
87
 
84
88
  private lastMessageSignature(state: AgentStreamState | null | undefined): string {
85
89
  const messages = Array.isArray(state?.messages) ? state!.messages : [];
86
- const last = messages[messages.length - 1] as any;
90
+ const last = messages[messages.length - 1];
87
91
  if (!last) return '';
88
92
  return `${last.role || ''}:${String(last.content || '').replace(/\s+/g, ' ').trim()}`;
89
93
  }
@@ -155,7 +159,7 @@ export class ProviderStreamAdapter implements IAgentStreamAdapter {
155
159
  activeModal: data.activeModal,
156
160
  };
157
161
  if (typeof data.title === 'string' && data.title.trim()) {
158
- (state as any).title = data.title.trim();
162
+ state.title = data.title.trim();
159
163
  }
160
164
  const controlValues = extractProviderControlValues(this.provider.controls, data);
161
165
  if (controlValues) state.controlValues = controlValues;
@@ -282,7 +286,7 @@ export class ProviderStreamAdapter implements IAgentStreamAdapter {
282
286
  for (let attempt = 0; attempt < 6; attempt += 1) {
283
287
  await new Promise((resolve) => setTimeout(resolve, 250));
284
288
  const state = await this.readChat(evaluate);
285
- const title = typeof (state as any).title === 'string' ? (state as any).title : '';
289
+ const title = this.getStateTitle(state);
286
290
  if (this.titlesMatch(title, sessionId)) return true;
287
291
  }
288
292
  return false;
@@ -303,6 +307,6 @@ export class ProviderStreamAdapter implements IAgentStreamAdapter {
303
307
  messages: [],
304
308
  inputContent: '',
305
309
  _error: message,
306
- } as any;
310
+ };
307
311
  }
308
312
  }
@@ -31,11 +31,14 @@ export interface AgentStreamState {
31
31
  status: 'idle' | 'streaming' | 'waiting_approval' | 'error' | 'disconnected' | 'panel_hidden' | 'not_monitored';
32
32
  messages: AgentChatMessage[];
33
33
  inputContent: string;
34
+ title?: string;
34
35
  /** @deprecated Use controlValues['model'] — kept for backward compatibility */
35
36
  model?: string;
36
37
  /** @deprecated Use controlValues['mode'] — kept for backward compatibility */
37
38
  mode?: string;
38
39
  activeModal?: { message: string; buttons: string[] };
40
+ error?: string;
41
+ _error?: string;
39
42
  /** Dynamic control current values (populated from readChat + provider controls schema) */
40
43
  controlValues?: Record<string, string | number | boolean>;
41
44
  /** Provider-driven UI effects from readChat */
@@ -24,12 +24,13 @@ import { ProviderLoader } from '../providers/provider-loader.js';
24
24
  import { VersionArchive, detectAllVersions } from '../providers/version-archive.js';
25
25
  import { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
26
26
  import { DevServer } from '../daemon/dev-server.js';
27
- import { detectIDEs } from '../detection/ide-detector.js';
27
+ import { detectIDEs, type IDEInfo } from '../detection/ide-detector.js';
28
28
  import { detectCLI, detectCLIs } from '../detection/cli-detector.js';
29
29
  import { SessionRegistry } from '../sessions/registry.js';
30
30
  import { installGlobalInterceptor, LOG } from '../logging/logger.js';
31
31
  import { loadConfig } from '../config/config.js';
32
32
  import type { PtyTransportFactory } from '../cli-adapters/pty-transport.js';
33
+ import type { IdeProviderInstance } from '../providers/ide-provider-instance.js';
33
34
 
34
35
  // ─── Init Config ───
35
36
 
@@ -82,7 +83,7 @@ export interface DaemonComponents {
82
83
  cdpInitializer: DaemonCdpInitializer;
83
84
  cdpManagers: Map<string, DaemonCdpManager>;
84
85
  sessionRegistry: SessionRegistry;
85
- detectedIdes: { value: any[] };
86
+ detectedIdes: { value: IDEInfo[] };
86
87
  }
87
88
 
88
89
  export interface DaemonDevSupportOptions {
@@ -157,7 +158,7 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
157
158
  const instanceManager = new ProviderInstanceManager();
158
159
  const cdpManagers = new Map<string, DaemonCdpManager>();
159
160
  const sessionRegistry = new SessionRegistry();
160
- const detectedIdesRef = { value: [] as any[] };
161
+ const detectedIdesRef: { value: IDEInfo[] } = { value: [] };
161
162
  let agentStreamManager: DaemonAgentStreamManager | null = null;
162
163
  let poller: AgentStreamPoller | null = null;
163
164
 
@@ -193,8 +194,8 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
193
194
  // 5. Detect IDEs
194
195
  LOG.info('Init', 'Detecting IDEs...');
195
196
  await refreshProviderAvailability();
196
- const installed = detectedIdesRef.value.filter((i: any) => i.installed);
197
- LOG.info('Init', `Found ${installed.length} IDE(s): ${installed.map((i: any) => i.id).join(', ') || 'none'}`);
197
+ const installed = detectedIdesRef.value.filter((i) => i.installed);
198
+ LOG.info('Init', `Found ${installed.length} IDE(s): ${installed.map((i) => i.id).join(', ') || 'none'}`);
198
199
 
199
200
  // 6. CDP Initializer — connect + register instances
200
201
  const cdpSetupContext: CdpSetupContext = {
@@ -217,7 +218,7 @@ export async function initDaemonComponents(config: DaemonInitConfig): Promise<Da
217
218
  onDisconnected: async (_ideType, _manager, managerKey) => {
218
219
  sessionRegistry.unregisterByManagerKey(managerKey);
219
220
  const instanceKey = `ide:${managerKey}`;
220
- const ideInstance = instanceManager.getInstance(instanceKey) as any;
221
+ const ideInstance = instanceManager.getInstance(instanceKey) as IdeProviderInstance | undefined;
221
222
 
222
223
  if (ideInstance) {
223
224
  instanceManager.removeInstance(instanceKey);
@@ -107,7 +107,7 @@ export class DaemonCdpInitializer {
107
107
  port,
108
108
  LOG.forComponent(`CDP:${ide}`).asLogFn(),
109
109
  undefined,
110
- (provider as any)?.targetFilter,
110
+ provider?.targetFilter,
111
111
  );
112
112
  const connected = await manager.connect();
113
113
  if (connected) {
@@ -148,7 +148,7 @@ export class DaemonCdpInitializer {
148
148
  port,
149
149
  LOG.forComponent(`CDP:${managerKey}`).asLogFn(),
150
150
  target.id,
151
- (provider as any)?.targetFilter,
151
+ provider?.targetFilter,
152
152
  );
153
153
 
154
154
  const connected = await manager.connect();
@@ -77,6 +77,11 @@ export class DaemonCdpManager {
77
77
  this._targetFilter = filter;
78
78
  }
79
79
 
80
+ /** Clear a previously pinned target so the next connect can reselect a page. */
81
+ clearTargetId(): void {
82
+ this._targetId = null;
83
+ }
84
+
80
85
  /**
81
86
  * Check if a page title should be excluded (non-main page).
82
87
  * Uses provider-configured titleExcludes, falls back to default pattern.
package/src/cdp/setup.ts CHANGED
@@ -138,7 +138,7 @@ export async function connectCdpManager(
138
138
  port,
139
139
  logFn,
140
140
  targetId,
141
- (provider as any)?.targetFilter,
141
+ provider?.targetFilter,
142
142
  );
143
143
  const connected = await manager.connect();
144
144
  return connected ? manager : null;
@@ -4,15 +4,44 @@
4
4
  * Contract implemented by all CLI adapters (ProviderCliAdapter etc).
5
5
  */
6
6
 
7
+ import type { ChatMessage } from './types.js';
8
+
9
+ export interface CliAdapterStatus {
10
+ status?: string;
11
+ messages?: ChatMessage[];
12
+ activeModal?: {
13
+ message: string;
14
+ buttons: string[];
15
+ } | null;
16
+ }
17
+
18
+ export interface AcpAdapterHandle {
19
+ onEvent(event: string, data?: unknown): void;
20
+ getState(): {
21
+ status: string;
22
+ activeChat?: {
23
+ messages?: ChatMessage[];
24
+ activeModal?: {
25
+ message: string;
26
+ buttons: string[];
27
+ } | null;
28
+ } | null;
29
+ };
30
+ setMode?(mode: string): Promise<void>;
31
+ setConfigOption?(configId: string, value: string): Promise<void>;
32
+ resolvePermission?(approved: boolean): Promise<void>;
33
+ }
34
+
7
35
  export interface CliAdapter {
8
36
  cliType: string;
9
37
  cliName: string;
10
38
  workingDir: string;
39
+ _acpInstance?: AcpAdapterHandle;
11
40
  spawn(): Promise<void>;
12
41
  sendMessage(text: string): Promise<void>;
13
- getStatus(): any;
14
- getScriptParsedStatus?(): any;
15
- invokeScript?(scriptName: string, args?: any): Promise<any>;
42
+ getStatus(): CliAdapterStatus;
43
+ getScriptParsedStatus?(): unknown;
44
+ invokeScript?(scriptName: string, args?: Record<string, unknown>): Promise<unknown>;
16
45
  getPartialResponse(): string;
17
46
  saveAndStop?(): Promise<void>;
18
47
  shutdown(): void;
@@ -21,8 +50,11 @@ export interface CliAdapter {
21
50
  isProcessing(): boolean;
22
51
  isReady(): boolean;
23
52
  setOnStatusChange(callback: () => void): void;
24
- updateRuntimeSettings?(settings: Record<string, any>): void;
25
- setServerConn?(serverConn: any): void;
53
+ updateRuntimeSettings?(settings: Record<string, unknown>): void;
54
+ setServerConn?(serverConn: unknown): void;
55
+ clearHistory?(): void;
56
+ resolveAction?(data: unknown): Promise<void>;
57
+ resolveModal?(buttonIndex: number): void;
26
58
  // Raw PTY I/O (for terminal view)
27
59
  setOnPtyData?(callback: (data: string) => void): void;
28
60
  writeRaw?(data: string): void;