@adhdev/daemon-core 0.8.33 → 0.8.35

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 (89) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +127 -102
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +127 -102
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/shared-types.d.ts +38 -0
  7. package/dist/status/reporter.d.ts +3 -0
  8. package/node_modules/@adhdev/session-host-core/package.json +1 -1
  9. package/package.json +1 -1
  10. package/src/agent-stream/forward.d.ts +8 -0
  11. package/src/agent-stream/index.d.ts +6 -0
  12. package/src/agent-stream/manager.d.ts +60 -0
  13. package/src/agent-stream/poller.d.ts +41 -0
  14. package/src/agent-stream/provider-adapter.d.ts +36 -0
  15. package/src/agent-stream/types.d.ts +68 -0
  16. package/src/boot/daemon-lifecycle.d.ts +100 -0
  17. package/src/cdp/devtools.d.ts +51 -0
  18. package/src/cdp/initializer.d.ts +50 -0
  19. package/src/cdp/manager.d.ts +147 -0
  20. package/src/cdp/scanner.d.ts +58 -0
  21. package/src/cdp/setup.d.ts +58 -0
  22. package/src/cli-adapter-types.d.ts +57 -0
  23. package/src/cli-adapters/provider-cli-adapter.d.ts +177 -0
  24. package/src/cli-adapters/provider-cli-adapter.ts +115 -91
  25. package/src/cli-adapters/provider-cli-config.d.ts +30 -0
  26. package/src/cli-adapters/provider-cli-parse.d.ts +42 -0
  27. package/src/cli-adapters/provider-cli-runtime.d.ts +29 -0
  28. package/src/cli-adapters/provider-cli-shared.d.ts +158 -0
  29. package/src/cli-adapters/pty-transport.d.ts +48 -0
  30. package/src/cli-adapters/session-host-transport.d.ts +20 -0
  31. package/src/cli-adapters/spawn-env.d.ts +8 -0
  32. package/src/cli-adapters/terminal-backends/ghostty-vt-backend.d.ts +16 -0
  33. package/src/cli-adapters/terminal-backends/types.d.ts +18 -0
  34. package/src/cli-adapters/terminal-backends/xterm-backend.d.ts +17 -0
  35. package/src/cli-adapters/terminal-screen.d.ts +33 -0
  36. package/src/commands/cdp-commands.d.ts +15 -0
  37. package/src/commands/chat-commands.d.ts +15 -0
  38. package/src/commands/cli-manager.d.ts +94 -0
  39. package/src/commands/handler.d.ts +103 -0
  40. package/src/commands/router.d.ts +98 -0
  41. package/src/commands/stream-commands.d.ts +14 -0
  42. package/src/commands/upgrade-helper.d.ts +10 -0
  43. package/src/commands/workspace-commands.d.ts +11 -0
  44. package/src/config/chat-history.d.ts +99 -0
  45. package/src/config/config.d.ts +14 -0
  46. package/src/config/recent-activity.d.ts +29 -0
  47. package/src/config/saved-sessions.d.ts +22 -0
  48. package/src/config/state-store.d.ts +32 -0
  49. package/src/config/workspaces.d.ts +0 -1
  50. package/src/daemon/dev-auto-implement.d.ts +43 -0
  51. package/src/daemon/dev-cdp-handlers.d.ts +22 -0
  52. package/src/daemon/dev-cli-debug.d.ts +106 -0
  53. package/src/daemon/dev-server-types.d.ts +43 -0
  54. package/src/daemon/dev-server.d.ts +140 -0
  55. package/src/daemon/scaffold-template.d.ts +32 -0
  56. package/src/daemon-core.d.ts +36 -0
  57. package/src/detection/cli-detector.d.ts +31 -0
  58. package/src/detection/ide-detector.d.ts +35 -0
  59. package/src/index.d.ts +83 -0
  60. package/src/index.ts +2 -0
  61. package/src/installer.d.ts +50 -0
  62. package/src/ipc-protocol.d.ts +111 -0
  63. package/src/launch.d.ts +46 -0
  64. package/src/logging/command-log.d.ts +31 -0
  65. package/src/logging/logger.d.ts +89 -0
  66. package/src/providers/acp-provider-instance.d.ts +102 -0
  67. package/src/providers/approval-utils.d.ts +7 -0
  68. package/src/providers/cli-provider-instance.d.ts +86 -0
  69. package/src/providers/contracts.d.ts +193 -1
  70. package/src/providers/control-effects.d.ts +4 -0
  71. package/src/providers/extension-provider-instance.d.ts +61 -0
  72. package/src/providers/ide-provider-instance.d.ts +70 -0
  73. package/src/providers/provider-instance-manager.d.ts +84 -0
  74. package/src/providers/provider-instance.d.ts +7 -1
  75. package/src/providers/provider-loader.d.ts +299 -0
  76. package/src/providers/status-monitor.d.ts +48 -0
  77. package/src/providers/version-archive.d.ts +52 -0
  78. package/src/session-host/runtime-support.d.ts +8 -0
  79. package/src/sessions/reconcile.d.ts +22 -0
  80. package/src/sessions/registry.d.ts +24 -0
  81. package/src/shared-types-extra.d.ts +29 -0
  82. package/src/shared-types.d.ts +79 -22
  83. package/src/shared-types.ts +40 -0
  84. package/src/status/builders.d.ts +33 -0
  85. package/src/status/reporter.d.ts +69 -0
  86. package/src/status/reporter.ts +16 -13
  87. package/src/status/snapshot.d.ts +58 -0
  88. package/src/system/host-memory.d.ts +19 -0
  89. package/src/types.d.ts +3 -7
@@ -0,0 +1,89 @@
1
+ /**
2
+ * ADHDev Daemon — unified logger (v2)
3
+ *
4
+ * log level: DEBUG < INFO < WARN < ERROR
5
+ *
6
+ * Features:
7
+ * 1. daemonLog(category, msg, level) — explicit per-category logging
8
+ * 2. installGlobalInterceptor() — Auto-intercept console.log (once on daemon start)
9
+ * 3. Recent log ring buffer — for remote transmission via P2P/WS
10
+ * 4. File logging — ~/Library/Logs/adhdev/daemon.log (10MB rolling)
11
+ *
12
+ * use:
13
+ * import { daemonLog, LOG } from './daemon-logger';
14
+ * LOG.info('CDP', 'Connected to cursor on port 9333');
15
+ * LOG.debug('StatusReport', 'P2P heartbeat sent');
16
+ * LOG.warn('IdeInstance', 'onTick error: ...');
17
+ * LOG.error('Server', 'WebSocket disconnected');
18
+ */
19
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error';
20
+ export declare function setLogLevel(level: LogLevel): void;
21
+ export declare function getLogLevel(): LogLevel;
22
+ export declare function getDaemonLogDir(): string;
23
+ export declare function getCurrentDaemonLogPath(date?: Date): string;
24
+ export interface LogEntry {
25
+ ts: number;
26
+ level: LogLevel;
27
+ category: string;
28
+ message: string;
29
+ }
30
+ /** Get recent N logs (for remote transmission) */
31
+ export declare function getRecentLogs(count?: number, minLevel?: LogLevel): LogEntry[];
32
+ /** Ring buffer current size */
33
+ export declare function getLogBufferSize(): number;
34
+ /**
35
+ * Explicit per-category logging
36
+ * level filter apply, File logging, Ring buffer save
37
+ */
38
+ export declare function daemonLog(category: string, msg: string, level?: LogLevel): void;
39
+ /**
40
+ * Scoped logger instance for a specific component.
41
+ * Created via LOG.forComponent('CDP:cursor').
42
+ */
43
+ export interface ScopedLogger {
44
+ debug: (msg: string) => void;
45
+ info: (msg: string) => void;
46
+ warn: (msg: string) => void;
47
+ error: (msg: string) => void;
48
+ /** Returns a plain (msg: string) => void function at the given level.
49
+ * Useful as logFn callback for ProviderLoader, DaemonStatusReporter, etc. */
50
+ asLogFn: (level?: LogLevel) => (msg: string) => void;
51
+ }
52
+ /**
53
+ * LOG — unified logging API
54
+ *
55
+ * Usage:
56
+ * LOG.info('CDP', 'Connected to cursor on port 9333');
57
+ * LOG.debug('StatusReport', 'P2P heartbeat sent');
58
+ *
59
+ * Component-scoped logger:
60
+ * const log = LOG.forComponent('ACP:cursor');
61
+ * log.info('Session created');
62
+ * log.debug('Heartbeat');
63
+ *
64
+ * As callback for external components:
65
+ * new ProviderLoader({ logFn: LOG.forComponent('Provider').asLogFn() });
66
+ * new DaemonStatusReporter({ logFn: LOG.forComponent('Status').asLogFn() });
67
+ */
68
+ export declare const LOG: {
69
+ debug: (category: string, msg: string) => void;
70
+ info: (category: string, msg: string) => void;
71
+ warn: (category: string, msg: string) => void;
72
+ error: (category: string, msg: string) => void;
73
+ /**
74
+ * Create a scoped logger for a specific component.
75
+ * Category is baked in so callers only pass the message.
76
+ */
77
+ forComponent(category: string): ScopedLogger;
78
+ };
79
+ /**
80
+ * console.log/warn/error global interceptor install
81
+ * Prevent recording in places not using daemonLog.
82
+ * daemon start when 1time call.
83
+ */
84
+ export declare function installGlobalInterceptor(): void;
85
+ /** current log file path (dateper) */
86
+ export declare function getLogPath(): string;
87
+ /** LOG_PATH — backward compat (current date file) */
88
+ export declare const LOG_PATH: string;
89
+ export declare const LOG_DIR_PATH: string;
@@ -0,0 +1,102 @@
1
+ /**
2
+ * AcpProviderInstance — ACP (Agent Client Protocol) Provider runtime instance
3
+ *
4
+ * Spawns ACP agent process and communicates via the official ACP SDK.
5
+ * Uses ClientSideConnection + ndJsonStream for structured protocol communication.
6
+ *
7
+ * ACP spec: https://agentclientprotocol.com
8
+ * ACP SDK: @agentclientprotocol/sdk@0.16.1
9
+ *
10
+ * lifecycle:
11
+ * 1. init() → Spawn agent process + ACP initialize handshake
12
+ * 2. onTick() → no-op (ACP event based)
13
+ * 3. getState() → ProviderState return (dashboard for display)
14
+ * 4. onEvent('send_message') → session/prompt transmit
15
+ * 5. dispose() → kill process
16
+ */
17
+ import type { ProviderModule, ContentBlock } from './contracts.js';
18
+ import type { ProviderInstance, AcpProviderState, InstanceContext } from './provider-instance.js';
19
+ export declare class AcpProviderInstance implements ProviderInstance {
20
+ private cliArgs;
21
+ readonly type: string;
22
+ readonly category: "acp";
23
+ private readonly log;
24
+ private provider;
25
+ private context;
26
+ private settings;
27
+ private events;
28
+ private monitor;
29
+ private process;
30
+ private connection;
31
+ private sessionId;
32
+ private messages;
33
+ private currentStatus;
34
+ private lastStatus;
35
+ private generatingStartedAt;
36
+ private agentCapabilities;
37
+ private currentModel;
38
+ private currentMode;
39
+ private activeToolCalls;
40
+ private stopReason;
41
+ private partialContent;
42
+ /** Rich content blocks accumulated during streaming */
43
+ private partialBlocks;
44
+ /** Tool calls collected during current turn */
45
+ private turnToolCalls;
46
+ private errorMessage;
47
+ private errorReason;
48
+ private stderrBuffer;
49
+ private spawnedAt;
50
+ private configOptions;
51
+ private availableModes;
52
+ /** Static config mode — agent doesn't support config/* methods */
53
+ private useStaticConfig;
54
+ /** Current config selections (for spawnArgBuilder) */
55
+ private selectedConfig;
56
+ private workingDir;
57
+ private instanceId;
58
+ constructor(provider: ProviderModule, workingDir: string, cliArgs?: string[]);
59
+ init(context: InstanceContext): Promise<void>;
60
+ onTick(): Promise<void>;
61
+ getState(): AcpProviderState;
62
+ onEvent(event: string, data?: any): void;
63
+ getInstanceId(): string;
64
+ private parseConfigOptions;
65
+ private parseModes;
66
+ setConfigOption(category: string, value: string): Promise<void>;
67
+ setMode(modeId: string): Promise<void>;
68
+ /** Static config: kill process and restart with new args */
69
+ private restartWithNewConfig;
70
+ /** Update settings at runtime (called when user changes settings from dashboard) */
71
+ updateSettings(newSettings: Record<string, any>): void;
72
+ dispose(): void;
73
+ private spawnAgent;
74
+ private createClient;
75
+ private initialize;
76
+ private createSession;
77
+ sendPrompt(text: string, contentBlocks?: ContentBlock[]): Promise<void>;
78
+ private cancelSession;
79
+ private permissionResolvers;
80
+ resolvePermission(approved: boolean): Promise<void>;
81
+ private handleSessionUpdate;
82
+ /** Handle legacy session/update formats (pre-standardization compat) */
83
+ private handleLegacyUpdate;
84
+ /** Map SDK ToolCallStatus to internal status */
85
+ private mapToolCallStatus;
86
+ /** Truncate content for transport (text: 2000 chars, images preserved) */
87
+ private truncateContent;
88
+ /** Build ContentBlock[] from current partial state */
89
+ private buildPartialBlocks;
90
+ /** Finalize streaming content into an assistant message */
91
+ private finalizeAssistantMessage;
92
+ /** Convert ACP ToolCallContent[] to our ToolCallContent[] */
93
+ private convertToolCallContent;
94
+ private detectStatusTransition;
95
+ private pushEvent;
96
+ private appendSystemMessage;
97
+ private flushEvents;
98
+ get cliType(): string;
99
+ get cliName(): string;
100
+ /** ACP Agent capabilities (available after initialize) */
101
+ getCapabilities(): Record<string, any>;
102
+ }
@@ -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;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * CliProviderInstance — Runtime instance for CLI Provider
3
+ *
4
+ * Lifecycle layer on top of ProviderCliAdapter.
5
+ * collectCliData() + status transition logic from daemon-status.ts moved here.
6
+ */
7
+ import type { ProviderModule } from './contracts.js';
8
+ import type { ProviderInstance, ProviderState, InstanceContext } from './provider-instance.js';
9
+ import { ProviderCliAdapter } from '../cli-adapters/provider-cli-adapter.js';
10
+ import type { PtyTransportFactory } from '../cli-adapters/pty-transport.js';
11
+ export declare class CliProviderInstance implements ProviderInstance {
12
+ private provider;
13
+ private workingDir;
14
+ private cliArgs;
15
+ readonly type: string;
16
+ readonly category: "cli";
17
+ private adapter;
18
+ private context;
19
+ private events;
20
+ private lastStatus;
21
+ private generatingStartedAt;
22
+ private settings;
23
+ private monitor;
24
+ private generatingDebounceTimer;
25
+ private generatingDebouncePending;
26
+ private lastApprovalEventAt;
27
+ private controlValues;
28
+ private appliedEffectKeys;
29
+ private historyWriter;
30
+ private runtimeMessages;
31
+ readonly instanceId: string;
32
+ private suppressIdleHistoryReplay;
33
+ private presentationMode;
34
+ private providerSessionId?;
35
+ private launchMode;
36
+ private readonly startedAt;
37
+ private onProviderSessionResolved?;
38
+ constructor(provider: ProviderModule, workingDir: string, cliArgs?: string[], instanceId?: string, transportFactory?: PtyTransportFactory, options?: {
39
+ providerSessionId?: string;
40
+ launchMode?: 'new' | 'resume' | 'manual';
41
+ onProviderSessionResolved?: (info: {
42
+ instanceId: string;
43
+ providerType: string;
44
+ providerName: string;
45
+ workspace: string;
46
+ providerSessionId: string;
47
+ previousProviderSessionId?: string;
48
+ }) => void;
49
+ });
50
+ init(context: InstanceContext): Promise<void>;
51
+ onTick(): Promise<void>;
52
+ /**
53
+ * Generic session ID probe using declarative ProviderSessionProbe config.
54
+ * Replaces the previously duplicated probeOpenCode/Codex/Goose functions.
55
+ */
56
+ private probeSessionIdFromConfig;
57
+ getState(): ProviderState;
58
+ setPresentationMode(mode: 'terminal' | 'chat'): void;
59
+ getPresentationMode(): 'terminal' | 'chat';
60
+ updateSettings(newSettings: Record<string, any>): void;
61
+ onEvent(event: string, data?: any): void;
62
+ dispose(): void;
63
+ private completedDebounceTimer;
64
+ private completedDebouncePending;
65
+ private detectStatusTransition;
66
+ private pushEvent;
67
+ private flushEvents;
68
+ private applyProviderResponse;
69
+ private getEffectDedupKey;
70
+ private getPersistedEffectContent;
71
+ getAdapter(): ProviderCliAdapter;
72
+ get cliType(): string;
73
+ get cliName(): string;
74
+ private shouldAutoApprove;
75
+ private recordAutoApproval;
76
+ recordApprovalSelection(buttonText: string): void;
77
+ private formatMarkerTimestamp;
78
+ private maybeAppendRuntimeRecoveryMessage;
79
+ private appendRuntimeSystemMessage;
80
+ private mergeConversationMessages;
81
+ private formatApprovalRequestMessage;
82
+ private promoteProviderSessionId;
83
+ private getProbeDirectories;
84
+ private buildSqlPlaceholderList;
85
+ private querySqliteText;
86
+ }
@@ -23,6 +23,10 @@ export interface ReadChatResult {
23
23
  inputContent?: string;
24
24
  model?: string;
25
25
  autoApprove?: string;
26
+ /** Explicit dynamic control values returned by the provider */
27
+ controlValues?: Record<string, string | number | boolean>;
28
+ /** Provider-driven UI effects derived from chat state */
29
+ effects?: ProviderEffect[];
26
30
  }
27
31
  import type { ChatMessage } from '../types.js';
28
32
  export type { ChatMessage };
@@ -33,6 +37,38 @@ export interface ModalInfo {
33
37
  width?: number;
34
38
  height?: number;
35
39
  }
40
+ export interface ProviderEffectMessage {
41
+ role?: 'system' | 'assistant' | 'user';
42
+ content: string | ContentBlock[];
43
+ kind?: string;
44
+ senderName?: string;
45
+ }
46
+ export interface ProviderEffectToast {
47
+ level?: 'info' | 'success' | 'warning';
48
+ message: string;
49
+ }
50
+ export type ProviderNotificationPreferenceKey = 'disconnect' | 'completion' | 'approval' | 'browser';
51
+ export type ProviderNotificationChannel = 'bubble' | 'toast' | 'browser';
52
+ export interface ProviderEffectNotification {
53
+ title?: string;
54
+ body: string;
55
+ level?: 'info' | 'success' | 'warning';
56
+ channels?: ProviderNotificationChannel[];
57
+ preferenceKey?: ProviderNotificationPreferenceKey;
58
+ bubbleContent?: string | ContentBlock[];
59
+ }
60
+ export interface ProviderEffect {
61
+ type: 'message' | 'toast' | 'notification';
62
+ /** Stable dedup key; falls back to a content hash when omitted */
63
+ id?: string;
64
+ /** Default immediate. turn_completed fires only on generating/waiting -> idle transitions. */
65
+ when?: 'immediate' | 'turn_completed';
66
+ /** Default true. False keeps the effect UI-only. */
67
+ persist?: boolean;
68
+ message?: ProviderEffectMessage;
69
+ toast?: ProviderEffectToast;
70
+ notification?: ProviderEffectNotification;
71
+ }
36
72
  /**
37
73
  * ContentBlock — ACP ContentBlock union type
38
74
  * Represents displayable content in messages, tool call results, etc.
@@ -197,6 +233,11 @@ export interface CdpTargetFilter {
197
233
  /** Page title regex pattern for titles to EXCLUDE (e.g. 'Debug Console|Output') */
198
234
  titleExcludes?: string;
199
235
  }
236
+ export type ProviderVersionCommand = string | Partial<Record<string, string>>;
237
+ export interface ProviderCompatibilityEntry {
238
+ ideVersion: string;
239
+ scriptDir: string;
240
+ }
200
241
  export interface ProviderModule {
201
242
  /** Unique identifier (e.g. 'cline', 'cursor', 'gemini-cli') */
202
243
  type: string;
@@ -219,7 +260,7 @@ export interface ProviderModule {
219
260
  /** Install instructions (shown when command is missing) */
220
261
  install?: string;
221
262
  /** Custom version detection command (e.g. 'cursor --version', 'claude -v') */
222
- versionCommand?: string;
263
+ versionCommand?: ProviderVersionCommand;
223
264
  /** Versions tested by provider maintainer (informational) */
224
265
  testedVersions?: string[];
225
266
  /** Per-OS process names — used by launch.ts to detect/kill IDE processes */
@@ -229,6 +270,28 @@ export interface ProviderModule {
229
270
  linux?: string[];
230
271
  [key: string]: string | string[] | undefined;
231
272
  };
273
+ /**
274
+ * IDE launch preferences.
275
+ * Lets each provider choose how its GUI app should be started per platform.
276
+ */
277
+ launch?: {
278
+ /**
279
+ * Preferred launch method by platform.
280
+ * - 'cli': use the IDE CLI wrapper/binary
281
+ * - 'app': use platform app launcher (e.g. `open -a` on macOS)
282
+ * - 'auto': let core choose a sensible default
283
+ */
284
+ prefer?: {
285
+ darwin?: 'auto' | 'cli' | 'app';
286
+ win32?: 'auto' | 'cli' | 'app';
287
+ linux?: 'auto' | 'cli' | 'app';
288
+ [key: string]: 'auto' | 'cli' | 'app' | undefined;
289
+ };
290
+ /**
291
+ * Override how long core waits for CDP to come up after launch.
292
+ */
293
+ cdpStartupTimeoutMs?: number;
294
+ };
232
295
  /** Per-OS install paths — used by detector.ts to detect IDE installation */
233
296
  paths?: {
234
297
  darwin?: string[];
@@ -238,6 +301,9 @@ export interface ProviderModule {
238
301
  };
239
302
  extensionId?: string;
240
303
  extensionIdPattern?: RegExp;
304
+ extensionIdPattern_flags?: string;
305
+ compatibility?: ProviderCompatibilityEntry[];
306
+ defaultScriptDir?: string;
241
307
  binary?: string;
242
308
  spawn?: {
243
309
  command: string;
@@ -245,6 +311,7 @@ export interface ProviderModule {
245
311
  shell?: boolean;
246
312
  env?: Record<string, string>;
247
313
  };
314
+ approvalKeys?: Record<number, string>;
248
315
  patterns?: {
249
316
  prompt?: RegExp[];
250
317
  generating?: RegExp[];
@@ -253,6 +320,9 @@ export interface ProviderModule {
253
320
  };
254
321
  cleanOutput?: (raw: string, lastUserInput?: string) => string;
255
322
  resume?: ProviderResumeCapability;
323
+ /** Session ID probe config — auto-discovers provider session ID from local SQLite DB */
324
+ sessionProbe?: ProviderSessionProbe;
325
+ /** Approval button priority hints used when auto-approve must pick a positive action */
256
326
  approvalPositiveHints?: string[];
257
327
  scripts?: ProviderScripts;
258
328
  vscodeCommands?: {
@@ -288,6 +358,8 @@ export interface ProviderModule {
288
358
  __dir?: string;
289
359
  }>;
290
360
  settings?: Record<string, ProviderSettingDef>;
361
+ /** Dynamic controls declared by provider — rendered in chat panel bar/header */
362
+ controls?: ProviderControlDef[];
291
363
  /** Static options used when agent does not provide configOptions */
292
364
  staticConfigOptions?: Array<{
293
365
  category: 'model' | 'mode' | 'thought_level' | 'other';
@@ -310,7 +382,46 @@ export interface ProviderResumeCapability {
310
382
  stopStrategy?: 'command' | 'ctrl_c';
311
383
  stopCommand?: string;
312
384
  shutdownGraceMs?: number;
385
+ /** Delay (ms) between Ctrl+C interrupt and stop command (default 500ms) */
386
+ interruptGraceMs?: number;
313
387
  resumeArgs?: string[];
388
+ resumeSessionArgs?: string[];
389
+ newSessionArgs?: string[];
390
+ sessionIdFormat?: 'uuid' | 'string';
391
+ }
392
+ /**
393
+ * Declarative session ID probe config for CLI providers.
394
+ * Instead of hardcoded probe functions, providers declare their SQLite schema.
395
+ *
396
+ * Example (OpenCode):
397
+ * ```
398
+ * sessionProbe: {
399
+ * dbPath: '~/.local/share/opencode/opencode.db',
400
+ * query: 'SELECT id FROM session WHERE directory IN ({dirs}) AND time_created >= ? AND time_archived IS NULL ORDER BY time_updated DESC LIMIT 1',
401
+ * timestampFormat: 'unix_ms',
402
+ * }
403
+ * ```
404
+ */
405
+ export interface ProviderSessionProbe {
406
+ /**
407
+ * Path to SQLite database. Supports ~ for home directory.
408
+ * Supports platform-specific paths via {platform} placeholder.
409
+ */
410
+ dbPath: string;
411
+ /**
412
+ * SQL query to find the session ID.
413
+ * Use {dirs} placeholder for the directory IN-clause parameters.
414
+ * The query must SELECT a column named 'id'.
415
+ * A '?' placeholder after {dirs} receives the min-created-at timestamp.
416
+ */
417
+ query: string;
418
+ /**
419
+ * How the provider stores timestamps.
420
+ * - 'unix_ms': milliseconds since epoch (default)
421
+ * - 'unix_s': seconds since epoch
422
+ * - 'iso': ISO 8601 string (YYYY-MM-DD HH:MM:SS)
423
+ */
424
+ timestampFormat?: 'unix_ms' | 'unix_s' | 'iso';
314
425
  }
315
426
  /** ACP auth method — based on ACP official spec */
316
427
  export type AcpAuthMethod = AcpAuthEnvVar | AcpAuthAgent | AcpAuthTerminal;
@@ -385,6 +496,14 @@ export interface ResolvedProvider extends ProviderModule {
385
496
  _resolvedVersion?: string;
386
497
  /** Warning when detected version is not in compatibility matrix */
387
498
  _versionWarning?: string;
499
+ /** On-disk provider directory selected by ProviderLoader */
500
+ _resolvedProviderDir?: string;
501
+ /** Script directory selected by compatibility/default resolution */
502
+ _resolvedScriptDir?: string;
503
+ /** scripts.js path or fallback script directory used to build runtime scripts */
504
+ _resolvedScriptsPath?: string;
505
+ /** Why this script selection was chosen */
506
+ _resolvedScriptsSource?: string;
388
507
  }
389
508
  /** Setting variable definition declared by provider */
390
509
  export interface ProviderSettingDef {
@@ -407,3 +526,76 @@ export interface ProviderSettingDef {
407
526
  export interface ProviderSettingSchema extends ProviderSettingDef {
408
527
  key: string;
409
528
  }
529
+ /**
530
+ * Control types:
531
+ * - 'select' — dropdown list (model picker, mode picker)
532
+ * - 'toggle' — on/off switch (compact mode, auto-approve)
533
+ * - 'cycle' — click-to-cycle through options (thinking level: low→med→high)
534
+ * - 'slider' — numeric range (temperature: 0–2)
535
+ * - 'action' — one-shot button (show usage, restart, clear context)
536
+ */
537
+ export type ProviderControlType = 'select' | 'toggle' | 'cycle' | 'slider' | 'action' | 'display';
538
+ /**
539
+ * Where the control appears in the chat UI:
540
+ * - 'bar' — thin strip below/above the chat input (always visible)
541
+ * - 'header' — in the agent header area
542
+ * - 'menu' — inside a ⋯ overflow menu
543
+ */
544
+ export type ProviderControlPlacement = 'bar' | 'header' | 'menu';
545
+ /** Static option for select/cycle controls */
546
+ export interface ProviderControlOption {
547
+ value: string;
548
+ label: string;
549
+ description?: string;
550
+ group?: string;
551
+ }
552
+ /**
553
+ * ProviderControlDef — A single interactive control declared by a provider.
554
+ *
555
+ * Controls are different from Settings:
556
+ * - Settings: background config, infrequently changed, managed in settings page
557
+ * - Controls: interactive, changed during chat, rendered inside chat panel
558
+ *
559
+ * Each control maps to provider scripts for get/set operations.
560
+ * The frontend renders controls automatically based on this schema —
561
+ * no hardcoded model/mode assumptions needed.
562
+ *
563
+ * For 'action' type:
564
+ * - Renders as a button. On click → calls invokeScript.
565
+ * - No value state. Optionally shows result via toast/inline.
566
+ */
567
+ export interface ProviderControlDef {
568
+ /** Unique identifier (e.g. 'model', 'mode', 'thinking', 'usage') */
569
+ id: string;
570
+ /** Control type */
571
+ type: ProviderControlType;
572
+ /** Display label */
573
+ label: string;
574
+ /** Icon (emoji or icon name) */
575
+ icon?: string;
576
+ /** Where to show this control in the UI */
577
+ placement: ProviderControlPlacement;
578
+ /** Static options — used when the list is known at definition time */
579
+ options?: ProviderControlOption[];
580
+ /** Dynamic options — load via script at runtime */
581
+ dynamic?: boolean;
582
+ /** Script name to list options (e.g. 'listModels') — required when dynamic=true */
583
+ listScript?: string;
584
+ /** Script name to change value (e.g. 'setModel') — required for value-based controls */
585
+ setScript?: string;
586
+ /** Field name in readChat() result to read current value (e.g. 'model', 'mode') */
587
+ readFrom?: string;
588
+ /** Default value */
589
+ defaultValue?: string | number | boolean;
590
+ /** Script name to invoke (one-shot call, no value) */
591
+ invokeScript?: string;
592
+ /** How to display action result: 'toast' = notification, 'inline' = show in bar, 'none' = silent */
593
+ resultDisplay?: 'toast' | 'inline' | 'none';
594
+ min?: number;
595
+ max?: number;
596
+ step?: number;
597
+ /** Sort order within placement group (lower = first) */
598
+ order?: number;
599
+ /** Hide this control when condition not met */
600
+ hidden?: boolean;
601
+ }
@@ -0,0 +1,4 @@
1
+ import type { ProviderControlDef, ProviderEffect } from './contracts.js';
2
+ export type ProviderControlValue = string | number | boolean;
3
+ export declare function extractProviderControlValues(controls: ProviderControlDef[] | undefined, data: any): Record<string, ProviderControlValue> | undefined;
4
+ export declare function normalizeProviderEffects(data: any): ProviderEffect[];
@@ -0,0 +1,61 @@
1
+ /**
2
+ * ExtensionProviderInstance — Runtime instance for Extension Provider
3
+ *
4
+ * Manages IDE extensions (Cline, Roo Code, etc).
5
+ * CDP webview discovery + agent stream collection moved here.
6
+ */
7
+ import type { ProviderModule } from './contracts.js';
8
+ import type { ProviderInstance, ProviderState, InstanceContext } from './provider-instance.js';
9
+ export declare class ExtensionProviderInstance implements ProviderInstance {
10
+ readonly type: string;
11
+ readonly category: "extension";
12
+ private provider;
13
+ private context;
14
+ private settings;
15
+ private events;
16
+ private currentStatus;
17
+ private agentStreams;
18
+ private messages;
19
+ private prevMessageHashes;
20
+ private activeModal;
21
+ private currentModel;
22
+ private currentMode;
23
+ private controlValues;
24
+ private appliedEffectKeys;
25
+ private runtimeMessages;
26
+ private lastAgentStatus;
27
+ private generatingStartedAt;
28
+ private monitor;
29
+ private historyWriter;
30
+ private instanceId;
31
+ private ideType;
32
+ private chatId;
33
+ private chatTitle;
34
+ private agentName;
35
+ private extensionId;
36
+ constructor(provider: ProviderModule);
37
+ init(context: InstanceContext): Promise<void>;
38
+ onTick(): Promise<void>;
39
+ getState(): ProviderState;
40
+ onEvent(event: string, data?: any): void;
41
+ dispose(): void;
42
+ updateSettings(newSettings: Record<string, any>): void;
43
+ /** Query UUID instanceId */
44
+ getInstanceId(): string;
45
+ private detectTransition;
46
+ private pushEvent;
47
+ private applyProviderResponse;
48
+ private appendRuntimeSystemMessage;
49
+ /**
50
+ * Assign stable receivedAt to extension messages.
51
+ * Same pattern as IdeProviderInstance.readChat() prevByHash —
52
+ * preserves first-seen timestamp across polling cycles.
53
+ */
54
+ private assignReceivedAt;
55
+ private mergeConversationMessages;
56
+ private getPersistedEffectContent;
57
+ private getEffectDedupKey;
58
+ private flushEvents;
59
+ private resolveChatTitle;
60
+ private resetStreamState;
61
+ }