@adhdev/daemon-core 0.8.12 → 0.8.14
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.
- package/dist/cli-adapters/spawn-env.d.ts +8 -0
- package/dist/cli-adapters/terminal-screen.d.ts +5 -3
- package/dist/detection/cli-detector.d.ts +1 -1
- package/dist/index.js +347 -236
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +343 -229
- package/dist/index.mjs.map +1 -1
- package/dist/providers/cli-provider-instance.d.ts +5 -3
- package/dist/providers/contracts.d.ts +38 -0
- package/node_modules/@adhdev/session-host-core/dist/index.d.mts +30 -1
- package/node_modules/@adhdev/session-host-core/dist/index.d.ts +30 -1
- package/node_modules/@adhdev/session-host-core/dist/index.js +73 -6
- package/node_modules/@adhdev/session-host-core/dist/index.js.map +1 -1
- package/node_modules/@adhdev/session-host-core/dist/index.mjs +77 -6
- package/node_modules/@adhdev/session-host-core/dist/index.mjs.map +1 -1
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +3 -3
- package/src/cli-adapters/provider-cli-adapter.ts +36 -62
- package/src/cli-adapters/pty-transport.ts +13 -1
- package/src/cli-adapters/spawn-env.ts +12 -0
- package/src/cli-adapters/terminal-screen.ts +12 -3
- package/src/commands/cli-manager.ts +13 -2
- package/src/commands/workspace-commands.ts +37 -9
- package/src/detection/cli-detector.ts +36 -2
- package/src/providers/cli-provider-instance.ts +62 -36
- package/src/providers/contracts.ts +39 -0
|
@@ -148,12 +148,32 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
148
148
|
if (this.providerSessionId) return;
|
|
149
149
|
|
|
150
150
|
let probedSessionId: string | null = null;
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
151
|
+
|
|
152
|
+
// Prefer declarative probe from provider.json schema
|
|
153
|
+
const probeConfig = this.provider.sessionProbe;
|
|
154
|
+
if (probeConfig) {
|
|
155
|
+
probedSessionId = this.probeSessionIdFromConfig(probeConfig);
|
|
156
|
+
} else {
|
|
157
|
+
// Legacy hardcoded probes (backward compat until providers migrate)
|
|
158
|
+
if (this.type === 'opencode-cli') {
|
|
159
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
160
|
+
dbPath: '~/.local/share/opencode/opencode.db',
|
|
161
|
+
query: 'select id from session where directory in ({dirs}) and time_created >= ? and time_archived is null order by time_updated desc limit 1',
|
|
162
|
+
timestampFormat: 'unix_ms',
|
|
163
|
+
});
|
|
164
|
+
} else if (this.type === 'codex-cli') {
|
|
165
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
166
|
+
dbPath: '~/.codex/state_5.sqlite',
|
|
167
|
+
query: 'select id from threads where cwd in ({dirs}) and created_at >= ? and archived = 0 order by created_at desc limit 1',
|
|
168
|
+
timestampFormat: 'unix_s',
|
|
169
|
+
});
|
|
170
|
+
} else if (this.type === 'goose-cli') {
|
|
171
|
+
probedSessionId = this.probeSessionIdFromConfig({
|
|
172
|
+
dbPath: '~/.local/share/goose/sessions/sessions.db',
|
|
173
|
+
query: 'select id from sessions where working_dir in ({dirs}) and created_at >= ? order by updated_at desc limit 1',
|
|
174
|
+
timestampFormat: 'iso',
|
|
175
|
+
});
|
|
176
|
+
}
|
|
157
177
|
}
|
|
158
178
|
|
|
159
179
|
if (probedSessionId) {
|
|
@@ -161,6 +181,42 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
161
181
|
}
|
|
162
182
|
}
|
|
163
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Generic session ID probe using declarative ProviderSessionProbe config.
|
|
186
|
+
* Replaces the previously duplicated probeOpenCode/Codex/Goose functions.
|
|
187
|
+
*/
|
|
188
|
+
private probeSessionIdFromConfig(probe: {
|
|
189
|
+
dbPath: string;
|
|
190
|
+
query: string;
|
|
191
|
+
timestampFormat?: 'unix_ms' | 'unix_s' | 'iso';
|
|
192
|
+
}): string | null {
|
|
193
|
+
const resolvedDbPath = probe.dbPath.replace(/^~/, os.homedir());
|
|
194
|
+
if (!fs.existsSync(resolvedDbPath)) return null;
|
|
195
|
+
|
|
196
|
+
const directories = this.getProbeDirectories();
|
|
197
|
+
const minCreatedAt = Math.max(0, this.startedAt - 60_000);
|
|
198
|
+
const tsFormat = probe.timestampFormat || 'unix_ms';
|
|
199
|
+
|
|
200
|
+
let timestampParam: string | number;
|
|
201
|
+
if (tsFormat === 'unix_s') {
|
|
202
|
+
timestampParam = Math.floor(minCreatedAt / 1000);
|
|
203
|
+
} else if (tsFormat === 'iso') {
|
|
204
|
+
timestampParam = new Date(minCreatedAt).toISOString().slice(0, 19).replace('T', ' ');
|
|
205
|
+
} else {
|
|
206
|
+
timestampParam = minCreatedAt;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Build query: replace {dirs} with SQL placeholder list
|
|
210
|
+
const placeholders = this.buildSqlPlaceholderList(directories.length);
|
|
211
|
+
const query = probe.query.replace('{dirs}', placeholders);
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
return this.querySqliteText(resolvedDbPath, query, [...directories, timestampParam]);
|
|
215
|
+
} catch {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
164
220
|
getState(): ProviderState {
|
|
165
221
|
const adapterStatus = this.adapter.getStatus();
|
|
166
222
|
const parsedStatus = this.adapter.getScriptParsedStatus?.() || null;
|
|
@@ -480,36 +536,6 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
480
536
|
LOG.info('CLI', `[${this.type}] discovered provider session id: ${nextSessionId}`);
|
|
481
537
|
}
|
|
482
538
|
|
|
483
|
-
private probeOpenCodeSessionId(): string | null {
|
|
484
|
-
const dbPath = path.join(os.homedir(), '.local', 'share', 'opencode', 'opencode.db');
|
|
485
|
-
if (!fs.existsSync(dbPath)) return null;
|
|
486
|
-
const minCreatedAt = Math.max(0, this.startedAt - 60_000);
|
|
487
|
-
const directories = this.getProbeDirectories();
|
|
488
|
-
const query = `select id from session where directory in (${this.buildSqlPlaceholderList(directories.length)}) and time_created >= ? and time_archived is null order by time_updated desc limit 1;`;
|
|
489
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
private probeCodexSessionId(): string | null {
|
|
493
|
-
const dbPath = path.join(os.homedir(), '.codex', 'state_5.sqlite');
|
|
494
|
-
if (!fs.existsSync(dbPath)) return null;
|
|
495
|
-
const minCreatedAt = Math.max(0, Math.floor((this.startedAt - 60_000) / 1000));
|
|
496
|
-
const directories = this.getProbeDirectories();
|
|
497
|
-
const query = `select id from threads where cwd in (${this.buildSqlPlaceholderList(directories.length)}) and created_at >= ? and archived = 0 order by created_at desc limit 1;`;
|
|
498
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAt]);
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
private probeGooseSessionId(): string | null {
|
|
502
|
-
const dbPath = path.join(os.homedir(), '.local', 'share', 'goose', 'sessions', 'sessions.db');
|
|
503
|
-
if (!fs.existsSync(dbPath)) return null;
|
|
504
|
-
const minCreatedAtIso = new Date(Math.max(0, this.startedAt - 60_000)).toISOString().slice(0, 19).replace('T', ' ');
|
|
505
|
-
const directories = this.getProbeDirectories();
|
|
506
|
-
const query = `select id from sessions where working_dir in (${this.buildSqlPlaceholderList(directories.length)}) and created_at >= ? order by updated_at desc limit 1;`;
|
|
507
|
-
try {
|
|
508
|
-
return this.querySqliteText(dbPath, query, [...directories, minCreatedAtIso]);
|
|
509
|
-
} catch {
|
|
510
|
-
return null;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
539
|
|
|
514
540
|
private getProbeDirectories(): string[] {
|
|
515
541
|
const dirs = new Set<string>();
|
|
@@ -325,6 +325,8 @@ export interface ProviderModule {
|
|
|
325
325
|
};
|
|
326
326
|
cleanOutput?: (raw: string, lastUserInput?: string) => string;
|
|
327
327
|
resume?: ProviderResumeCapability;
|
|
328
|
+
/** Session ID probe config — auto-discovers provider session ID from local SQLite DB */
|
|
329
|
+
sessionProbe?: ProviderSessionProbe;
|
|
328
330
|
|
|
329
331
|
// ─── CDP scripts (ide/extension category) ───
|
|
330
332
|
scripts?: ProviderScripts;
|
|
@@ -398,12 +400,49 @@ export interface ProviderResumeCapability {
|
|
|
398
400
|
stopStrategy?: 'command' | 'ctrl_c';
|
|
399
401
|
stopCommand?: string;
|
|
400
402
|
shutdownGraceMs?: number;
|
|
403
|
+
/** Delay (ms) between Ctrl+C interrupt and stop command (default 500ms) */
|
|
404
|
+
interruptGraceMs?: number;
|
|
401
405
|
resumeArgs?: string[];
|
|
402
406
|
resumeSessionArgs?: string[];
|
|
403
407
|
newSessionArgs?: string[];
|
|
404
408
|
sessionIdFormat?: 'uuid' | 'string';
|
|
405
409
|
}
|
|
406
410
|
|
|
411
|
+
/**
|
|
412
|
+
* Declarative session ID probe config for CLI providers.
|
|
413
|
+
* Instead of hardcoded probe functions, providers declare their SQLite schema.
|
|
414
|
+
*
|
|
415
|
+
* Example (OpenCode):
|
|
416
|
+
* ```
|
|
417
|
+
* sessionProbe: {
|
|
418
|
+
* dbPath: '~/.local/share/opencode/opencode.db',
|
|
419
|
+
* query: 'SELECT id FROM session WHERE directory IN ({dirs}) AND time_created >= ? AND time_archived IS NULL ORDER BY time_updated DESC LIMIT 1',
|
|
420
|
+
* timestampFormat: 'unix_ms',
|
|
421
|
+
* }
|
|
422
|
+
* ```
|
|
423
|
+
*/
|
|
424
|
+
export interface ProviderSessionProbe {
|
|
425
|
+
/**
|
|
426
|
+
* Path to SQLite database. Supports ~ for home directory.
|
|
427
|
+
* Supports platform-specific paths via {platform} placeholder.
|
|
428
|
+
*/
|
|
429
|
+
dbPath: string;
|
|
430
|
+
/**
|
|
431
|
+
* SQL query to find the session ID.
|
|
432
|
+
* Use {dirs} placeholder for the directory IN-clause parameters.
|
|
433
|
+
* The query must SELECT a column named 'id'.
|
|
434
|
+
* A '?' placeholder after {dirs} receives the min-created-at timestamp.
|
|
435
|
+
*/
|
|
436
|
+
query: string;
|
|
437
|
+
/**
|
|
438
|
+
* How the provider stores timestamps.
|
|
439
|
+
* - 'unix_ms': milliseconds since epoch (default)
|
|
440
|
+
* - 'unix_s': seconds since epoch
|
|
441
|
+
* - 'iso': ISO 8601 string (YYYY-MM-DD HH:MM:SS)
|
|
442
|
+
*/
|
|
443
|
+
timestampFormat?: 'unix_ms' | 'unix_s' | 'iso';
|
|
444
|
+
}
|
|
445
|
+
|
|
407
446
|
// ─── ACP Auth Types ─────────────────────────────────
|
|
408
447
|
|
|
409
448
|
/** ACP auth method — based on ACP official spec */
|