@adhdev/daemon-core 0.8.24 → 0.8.25
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/index.js +88 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +88 -5
- package/dist/index.mjs.map +1 -1
- package/dist/sessions/reconcile.d.ts +22 -0
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/agent-stream/poller.ts +4 -0
- package/src/commands/handler.ts +54 -10
- package/src/sessions/reconcile.ts +85 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SessionRegistry } from './registry.js';
|
|
2
|
+
interface IdeLikeInstance {
|
|
3
|
+
category?: string;
|
|
4
|
+
type?: string;
|
|
5
|
+
getInstanceId?: () => string;
|
|
6
|
+
getExtensionInstances?: () => Array<{
|
|
7
|
+
type?: string;
|
|
8
|
+
getInstanceId?: () => string;
|
|
9
|
+
}>;
|
|
10
|
+
}
|
|
11
|
+
interface InstanceManagerLike {
|
|
12
|
+
listInstanceIds(): string[];
|
|
13
|
+
getInstance(id: string): IdeLikeInstance | undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Rebuild missing IDE/runtime session registry entries from live ProviderInstance objects.
|
|
17
|
+
*
|
|
18
|
+
* This is a defensive repair path for cases where an IDE extension instance still exists
|
|
19
|
+
* in InstanceManager/status, but its runtime session entry has been dropped from SessionRegistry.
|
|
20
|
+
*/
|
|
21
|
+
export declare function reconcileIdeRuntimeSessions(instanceManager: InstanceManagerLike | undefined, sessionRegistry: SessionRegistry | undefined): void;
|
|
22
|
+
export {};
|
package/package.json
CHANGED
|
@@ -16,6 +16,7 @@ import type { ProviderLoader } from '../providers/provider-loader.js';
|
|
|
16
16
|
import type { ProviderInstanceManager } from '../providers/provider-instance-manager.js';
|
|
17
17
|
import { registerExtensionProviders } from '../cdp/setup.js';
|
|
18
18
|
import type { SessionRegistry } from '../sessions/registry.js';
|
|
19
|
+
import { reconcileIdeRuntimeSessions } from '../sessions/reconcile.js';
|
|
19
20
|
import { LOG } from '../logging/logger.js';
|
|
20
21
|
import type { AgentStreamState } from './types.js';
|
|
21
22
|
|
|
@@ -78,6 +79,9 @@ export class AgentStreamPoller {
|
|
|
78
79
|
|
|
79
80
|
if (!agentStreamManager || cdpManagers.size === 0) return;
|
|
80
81
|
|
|
82
|
+
// Defensive repair: keep SessionRegistry aligned with live IDE/extension instances.
|
|
83
|
+
reconcileIdeRuntimeSessions(instanceManager as any, sessionRegistry);
|
|
84
|
+
|
|
81
85
|
// ─── Phase 1: Refresh extension providers + IDE instance extensions ───
|
|
82
86
|
for (const [ideType, cdp] of cdpManagers) {
|
|
83
87
|
// 1a. Refresh CDP manager's extension providers from config
|
package/src/commands/handler.ts
CHANGED
|
@@ -21,6 +21,7 @@ import type { DaemonAgentStreamManager } from '../agent-stream/index.js';
|
|
|
21
21
|
import { loadConfig } from '../config/config.js';
|
|
22
22
|
import { ChatHistoryWriter } from '../config/chat-history.js';
|
|
23
23
|
import type { SessionRegistry, SessionRuntimeTarget } from '../sessions/registry.js';
|
|
24
|
+
import { reconcileIdeRuntimeSessions } from '../sessions/reconcile.js';
|
|
24
25
|
import { LOG } from '../logging/logger.js';
|
|
25
26
|
|
|
26
27
|
// Sub-module imports
|
|
@@ -165,6 +166,7 @@ export class DaemonCommandHandler implements CommandHelpers {
|
|
|
165
166
|
session?: SessionRuntimeTarget;
|
|
166
167
|
managerKey?: string;
|
|
167
168
|
providerType?: string;
|
|
169
|
+
sessionLookupFailed?: boolean;
|
|
168
170
|
} = {};
|
|
169
171
|
|
|
170
172
|
constructor(ctx: CommandContext) {
|
|
@@ -284,23 +286,36 @@ export class DaemonCommandHandler implements CommandHelpers {
|
|
|
284
286
|
return key.split('_')[0];
|
|
285
287
|
}
|
|
286
288
|
|
|
287
|
-
private resolveRoute(args: any): { session?: SessionRuntimeTarget; managerKey?: string; providerType?: string } {
|
|
288
|
-
const
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
289
|
+
private resolveRoute(args: any): { session?: SessionRuntimeTarget; managerKey?: string; providerType?: string; sessionLookupFailed?: boolean } {
|
|
290
|
+
const targetSessionId = typeof args?.targetSessionId === 'string' ? args.targetSessionId.trim() : '';
|
|
291
|
+
let session = targetSessionId ? this._ctx.sessionRegistry?.get(targetSessionId) : undefined;
|
|
292
|
+
if (targetSessionId && !session) {
|
|
293
|
+
reconcileIdeRuntimeSessions(this._ctx.instanceManager as any, this._ctx.sessionRegistry);
|
|
294
|
+
session = this._ctx.sessionRegistry?.get(targetSessionId);
|
|
295
|
+
}
|
|
296
|
+
const sessionLookupFailed = !!targetSessionId && !session;
|
|
297
|
+
|
|
298
|
+
const managerKey = this.extractIdeType(args, sessionLookupFailed);
|
|
299
|
+
let providerType: string | undefined;
|
|
300
|
+
|
|
301
|
+
if (!sessionLookupFailed) {
|
|
302
|
+
providerType =
|
|
303
|
+
session?.providerType
|
|
304
|
+
|| args?.agentType
|
|
305
|
+
|| args?.providerType
|
|
306
|
+
|| this.inferProviderType(managerKey);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return { session, managerKey, providerType, sessionLookupFailed };
|
|
296
310
|
}
|
|
297
311
|
|
|
298
312
|
/** Extract CDP scope key from target session or explicit ideType */
|
|
299
|
-
private extractIdeType(args: any): string | undefined {
|
|
313
|
+
private extractIdeType(args: any, sessionLookupFailed = false): string | undefined {
|
|
300
314
|
if (args?.targetSessionId) {
|
|
301
315
|
const target = this._ctx.sessionRegistry?.get(args.targetSessionId);
|
|
302
316
|
if (target?.cdpManagerKey) return target.cdpManagerKey;
|
|
303
317
|
if (this._ctx.cdpManagers.has(args.targetSessionId)) return args.targetSessionId;
|
|
318
|
+
if (sessionLookupFailed) return undefined;
|
|
304
319
|
}
|
|
305
320
|
|
|
306
321
|
// Also accept explicit ideType from args (P2P input, agentType for extensions)
|
|
@@ -360,6 +375,35 @@ export class DaemonCommandHandler implements CommandHelpers {
|
|
|
360
375
|
const startedAt = Date.now();
|
|
361
376
|
this.logCommandStart(cmd, args);
|
|
362
377
|
|
|
378
|
+
const sessionScopedCommands = new Set([
|
|
379
|
+
'read_chat',
|
|
380
|
+
'send_chat',
|
|
381
|
+
'list_chats',
|
|
382
|
+
'new_chat',
|
|
383
|
+
'switch_chat',
|
|
384
|
+
'set_mode',
|
|
385
|
+
'change_model',
|
|
386
|
+
'set_thought_level',
|
|
387
|
+
'resolve_action',
|
|
388
|
+
'focus_session',
|
|
389
|
+
'pty_input',
|
|
390
|
+
'pty_resize',
|
|
391
|
+
'invoke_provider_script',
|
|
392
|
+
'list_extension_models',
|
|
393
|
+
'set_extension_model',
|
|
394
|
+
'list_extension_modes',
|
|
395
|
+
'set_extension_mode',
|
|
396
|
+
]);
|
|
397
|
+
|
|
398
|
+
if (this._currentRoute.sessionLookupFailed && sessionScopedCommands.has(cmd)) {
|
|
399
|
+
const result = {
|
|
400
|
+
success: false,
|
|
401
|
+
error: `Live session not found for targetSessionId: ${String(args?.targetSessionId || '').trim() || 'unknown'}`,
|
|
402
|
+
};
|
|
403
|
+
this.logCommandEnd(cmd, result, startedAt);
|
|
404
|
+
return result;
|
|
405
|
+
}
|
|
406
|
+
|
|
363
407
|
// Commands without ideType CDP silently fail (prevent P2P retry spam)
|
|
364
408
|
let result: CommandResult;
|
|
365
409
|
if (!this._currentRoute.session && !this._currentRoute.managerKey && !this._currentRoute.providerType) {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { SessionRegistry, SessionRuntimeTarget } from './registry.js';
|
|
2
|
+
|
|
3
|
+
interface IdeLikeInstance {
|
|
4
|
+
category?: string;
|
|
5
|
+
type?: string;
|
|
6
|
+
getInstanceId?: () => string;
|
|
7
|
+
getExtensionInstances?: () => Array<{
|
|
8
|
+
type?: string;
|
|
9
|
+
getInstanceId?: () => string;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface InstanceManagerLike {
|
|
14
|
+
listInstanceIds(): string[];
|
|
15
|
+
getInstance(id: string): IdeLikeInstance | undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function upsertSessionTarget(sessionRegistry: SessionRegistry, target: SessionRuntimeTarget): void {
|
|
19
|
+
const existing = sessionRegistry.get(target.sessionId);
|
|
20
|
+
if (
|
|
21
|
+
existing
|
|
22
|
+
&& existing.parentSessionId === target.parentSessionId
|
|
23
|
+
&& existing.providerType === target.providerType
|
|
24
|
+
&& existing.transport === target.transport
|
|
25
|
+
&& existing.cdpManagerKey === target.cdpManagerKey
|
|
26
|
+
&& existing.instanceKey === target.instanceKey
|
|
27
|
+
) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
sessionRegistry.register(target);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Rebuild missing IDE/runtime session registry entries from live ProviderInstance objects.
|
|
35
|
+
*
|
|
36
|
+
* This is a defensive repair path for cases where an IDE extension instance still exists
|
|
37
|
+
* in InstanceManager/status, but its runtime session entry has been dropped from SessionRegistry.
|
|
38
|
+
*/
|
|
39
|
+
export function reconcileIdeRuntimeSessions(
|
|
40
|
+
instanceManager: InstanceManagerLike | undefined,
|
|
41
|
+
sessionRegistry: SessionRegistry | undefined,
|
|
42
|
+
): void {
|
|
43
|
+
if (!instanceManager || !sessionRegistry) return;
|
|
44
|
+
|
|
45
|
+
for (const instanceKey of instanceManager.listInstanceIds()) {
|
|
46
|
+
if (!instanceKey.startsWith('ide:')) continue;
|
|
47
|
+
|
|
48
|
+
const ideInstance = instanceManager.getInstance(instanceKey);
|
|
49
|
+
if (!ideInstance || ideInstance.category !== 'ide' || typeof ideInstance.getInstanceId !== 'function') {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const managerKey = instanceKey.slice(4);
|
|
54
|
+
const ideType = typeof ideInstance.type === 'string' && ideInstance.type.trim()
|
|
55
|
+
? ideInstance.type.trim()
|
|
56
|
+
: managerKey.split('_')[0];
|
|
57
|
+
const parentSessionId = ideInstance.getInstanceId();
|
|
58
|
+
if (!parentSessionId) continue;
|
|
59
|
+
|
|
60
|
+
upsertSessionTarget(sessionRegistry, {
|
|
61
|
+
sessionId: parentSessionId,
|
|
62
|
+
parentSessionId: null,
|
|
63
|
+
providerType: ideType,
|
|
64
|
+
transport: 'cdp-page',
|
|
65
|
+
cdpManagerKey: managerKey,
|
|
66
|
+
instanceKey,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const extensions = ideInstance.getExtensionInstances?.() || [];
|
|
70
|
+
for (const ext of extensions) {
|
|
71
|
+
const extType = typeof ext?.type === 'string' ? ext.type.trim() : '';
|
|
72
|
+
const extSessionId = ext?.getInstanceId?.();
|
|
73
|
+
if (!extType || !extSessionId) continue;
|
|
74
|
+
|
|
75
|
+
upsertSessionTarget(sessionRegistry, {
|
|
76
|
+
sessionId: extSessionId,
|
|
77
|
+
parentSessionId,
|
|
78
|
+
providerType: extType,
|
|
79
|
+
transport: 'cdp-webview',
|
|
80
|
+
cdpManagerKey: managerKey,
|
|
81
|
+
instanceKey,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|