@adhdev/daemon-core 0.9.76-rc.24 → 0.9.76-rc.26
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 +96 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +96 -5
- package/dist/index.mjs.map +1 -1
- package/dist/providers/provider-instance-manager.d.ts +1 -0
- package/dist/providers/provider-instance.d.ts +2 -0
- package/dist/repo-mesh-types.d.ts +1 -0
- package/dist/shared-types.d.ts +4 -0
- package/package.json +1 -1
- package/src/commands/chat-commands.ts +1 -1
- package/src/commands/router.ts +77 -2
- package/src/providers/cli-provider-instance.ts +23 -1
- package/src/providers/provider-instance-manager.ts +20 -1
- package/src/providers/provider-instance.ts +2 -0
- package/src/repo-mesh-types.ts +1 -0
- package/src/shared-types.ts +4 -0
- package/src/status/reporter.ts +6 -0
|
@@ -67,6 +67,7 @@ export declare class ProviderInstanceManager {
|
|
|
67
67
|
onEvent(listener: (event: ProviderEvent & {
|
|
68
68
|
providerType: string;
|
|
69
69
|
}) => void): void;
|
|
70
|
+
emitProviderEvent(providerType: string, instanceId: string, event: ProviderEvent): void;
|
|
70
71
|
private emitPendingEvents;
|
|
71
72
|
/**
|
|
72
73
|
* Forward event to specific Instance
|
|
@@ -147,6 +147,8 @@ export interface InstanceContext {
|
|
|
147
147
|
onPtyData?: (data: string) => void;
|
|
148
148
|
/** Provider configvalue (resolved) */
|
|
149
149
|
settings: Record<string, any>;
|
|
150
|
+
/** Immediate provider-originated status/event emission. Used to avoid waiting for status polling. */
|
|
151
|
+
emitProviderEvent?: (event: ProviderEvent) => void;
|
|
150
152
|
}
|
|
151
153
|
export interface ProviderInstance {
|
|
152
154
|
/** Provider type */
|
|
@@ -53,6 +53,7 @@ export interface RepoMeshNodePolicy {
|
|
|
53
53
|
readOnly?: boolean;
|
|
54
54
|
canPush?: boolean;
|
|
55
55
|
maxConcurrentSessions?: number;
|
|
56
|
+
providerPriority?: string[];
|
|
56
57
|
}
|
|
57
58
|
export declare const DEFAULT_MESH_POLICY: RepoMeshPolicy;
|
|
58
59
|
export interface RepoMeshNodeCapabilities {
|
package/dist/shared-types.d.ts
CHANGED
|
@@ -522,6 +522,8 @@ export interface DaemonStatusEventPayload {
|
|
|
522
522
|
timestamp: number;
|
|
523
523
|
targetSessionId?: string;
|
|
524
524
|
providerType?: string;
|
|
525
|
+
providerSessionId?: string;
|
|
526
|
+
workspaceName?: string;
|
|
525
527
|
duration?: number;
|
|
526
528
|
elapsedSec?: number;
|
|
527
529
|
modalMessage?: string;
|
|
@@ -535,6 +537,8 @@ export interface DashboardStatusEventPayload {
|
|
|
535
537
|
daemonId?: string;
|
|
536
538
|
providerType?: string;
|
|
537
539
|
targetSessionId?: string;
|
|
540
|
+
providerSessionId?: string;
|
|
541
|
+
workspaceName?: string;
|
|
538
542
|
duration?: number;
|
|
539
543
|
elapsedSec?: number;
|
|
540
544
|
modalMessage?: string;
|
package/package.json
CHANGED
|
@@ -758,7 +758,7 @@ export async function handleChatHistory(h: CommandHelpers, args: any): Promise<C
|
|
|
758
758
|
}
|
|
759
759
|
|
|
760
760
|
export async function handleReadChat(h: CommandHelpers, args: any): Promise<CommandResult> {
|
|
761
|
-
const provider = h.getProvider(args?.agentType);
|
|
761
|
+
const provider = h.getProvider(args?.agentType || args?.providerType);
|
|
762
762
|
const transport = getTargetTransport(h, provider);
|
|
763
763
|
const historySessionId = getHistorySessionId(h, args);
|
|
764
764
|
|
package/src/commands/router.ts
CHANGED
|
@@ -62,6 +62,54 @@ function resolveUpgradeChannel(args: any): ReleaseChannel {
|
|
|
62
62
|
|| normalizeReleaseChannel(loadConfig().updateChannel)
|
|
63
63
|
|| 'stable';
|
|
64
64
|
}
|
|
65
|
+
|
|
66
|
+
function readProviderPriorityFromPolicy(policy: unknown): string[] {
|
|
67
|
+
const record = policy && typeof policy === 'object' && !Array.isArray(policy)
|
|
68
|
+
? policy as Record<string, unknown>
|
|
69
|
+
: {};
|
|
70
|
+
const raw = record.providerPriority;
|
|
71
|
+
if (!Array.isArray(raw)) return [];
|
|
72
|
+
const seen = new Set<string>();
|
|
73
|
+
return raw
|
|
74
|
+
.map(type => typeof type === 'string' ? type.trim() : '')
|
|
75
|
+
.filter(Boolean)
|
|
76
|
+
.filter(type => {
|
|
77
|
+
if (seen.has(type)) return false;
|
|
78
|
+
seen.add(type);
|
|
79
|
+
return true;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function resolveProviderTypeFromPriority(args: {
|
|
84
|
+
nodeId: string;
|
|
85
|
+
providerPriority: string[];
|
|
86
|
+
providerLoader: ProviderLoader;
|
|
87
|
+
onStatusChange?: () => void;
|
|
88
|
+
}): Promise<{ providerType?: string; error?: string }> {
|
|
89
|
+
if (!args.providerPriority.length) {
|
|
90
|
+
return { error: `Node '${args.nodeId}' has no providerPriority policy; pass cliType explicitly or configure node.policy.providerPriority` };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const failed: string[] = [];
|
|
94
|
+
for (const requestedType of args.providerPriority) {
|
|
95
|
+
const normalizedType = args.providerLoader.resolveAlias(requestedType);
|
|
96
|
+
if (!args.providerLoader.isMachineProviderEnabled(normalizedType)) {
|
|
97
|
+
failed.push(`${requestedType}: disabled`);
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const detected = await detectCLI(normalizedType, args.providerLoader, { includeVersion: false });
|
|
101
|
+
args.providerLoader.setCliDetectionResults([{
|
|
102
|
+
id: normalizedType,
|
|
103
|
+
installed: !!detected,
|
|
104
|
+
path: detected?.path,
|
|
105
|
+
}], false);
|
|
106
|
+
args.onStatusChange?.();
|
|
107
|
+
if (detected) return { providerType: normalizedType };
|
|
108
|
+
failed.push(`${requestedType}: not detected`);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return { error: `No usable provider detected for node '${args.nodeId}' from providerPriority: ${failed.join('; ')}` };
|
|
112
|
+
}
|
|
65
113
|
import * as fs from 'fs';
|
|
66
114
|
|
|
67
115
|
type MeshCoordinatorConfigFormat = 'claude_mcp_json' | 'hermes_config_yaml';
|
|
@@ -1069,7 +1117,15 @@ export class DaemonCommandRouter {
|
|
|
1069
1117
|
if (!workspace) return { success: false, error: 'workspace required' };
|
|
1070
1118
|
try {
|
|
1071
1119
|
const { addNode } = await import('../config/mesh-config.js');
|
|
1072
|
-
const
|
|
1120
|
+
const providerPriority = Array.isArray(args?.providerPriority)
|
|
1121
|
+
? args.providerPriority.map((type: any) => typeof type === 'string' ? type.trim() : '').filter(Boolean)
|
|
1122
|
+
: [];
|
|
1123
|
+
const readOnly = args?.readOnly === true;
|
|
1124
|
+
const policy = {
|
|
1125
|
+
...(readOnly ? { readOnly: true } : {}),
|
|
1126
|
+
...(providerPriority.length ? { providerPriority } : {}),
|
|
1127
|
+
};
|
|
1128
|
+
const node = addNode(meshId, { workspace, ...(policy ? { policy } : {}) });
|
|
1073
1129
|
if (!node) return { success: false, error: 'Mesh not found' };
|
|
1074
1130
|
return { success: true, node };
|
|
1075
1131
|
} catch (e: any) {
|
|
@@ -1186,7 +1242,7 @@ export class DaemonCommandRouter {
|
|
|
1186
1242
|
// ─── Mesh Coordinator Launch ───
|
|
1187
1243
|
case 'launch_mesh_coordinator': {
|
|
1188
1244
|
const meshId = typeof args?.meshId === 'string' ? args.meshId.trim() : '';
|
|
1189
|
-
|
|
1245
|
+
let cliType = typeof args?.cliType === 'string' ? args.cliType.trim() : '';
|
|
1190
1246
|
if (!meshId) return { success: false, error: 'meshId required' };
|
|
1191
1247
|
|
|
1192
1248
|
try {
|
|
@@ -1224,6 +1280,25 @@ export class DaemonCommandRouter {
|
|
|
1224
1280
|
}
|
|
1225
1281
|
const workspace = typeof coordinatorNode.workspace === 'string' ? coordinatorNode.workspace.trim() : '';
|
|
1226
1282
|
if (!workspace) return { success: false, error: 'Coordinator node workspace required', meshId, cliType };
|
|
1283
|
+
if (!cliType) {
|
|
1284
|
+
const resolved = await resolveProviderTypeFromPriority({
|
|
1285
|
+
nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || 'coordinator'),
|
|
1286
|
+
providerPriority: readProviderPriorityFromPolicy(coordinatorNode.policy),
|
|
1287
|
+
providerLoader: this.deps.providerLoader,
|
|
1288
|
+
onStatusChange: this.deps.onStatusChange,
|
|
1289
|
+
});
|
|
1290
|
+
if (!resolved.providerType) {
|
|
1291
|
+
return {
|
|
1292
|
+
success: false,
|
|
1293
|
+
code: 'mesh_coordinator_provider_priority_unusable',
|
|
1294
|
+
error: resolved.error || 'No usable provider found from node providerPriority',
|
|
1295
|
+
meshId,
|
|
1296
|
+
cliType,
|
|
1297
|
+
workspace,
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
cliType = resolved.providerType;
|
|
1301
|
+
}
|
|
1227
1302
|
const providerMeta = this.deps.providerLoader.resolve?.(cliType) || this.deps.providerLoader.getMeta(cliType);
|
|
1228
1303
|
const coordinatorSetup = resolveMeshCoordinatorSetup({
|
|
1229
1304
|
provider: providerMeta,
|
|
@@ -738,7 +738,29 @@ export class CliProviderInstance implements ProviderInstance {
|
|
|
738
738
|
}
|
|
739
739
|
|
|
740
740
|
private pushEvent(event: ProviderEvent): void {
|
|
741
|
-
|
|
741
|
+
const enrichedEvent: ProviderEvent = {
|
|
742
|
+
...event,
|
|
743
|
+
instanceId: typeof event.instanceId === 'string' && event.instanceId.trim()
|
|
744
|
+
? event.instanceId
|
|
745
|
+
: this.instanceId,
|
|
746
|
+
targetSessionId: typeof event.targetSessionId === 'string' && event.targetSessionId.trim()
|
|
747
|
+
? event.targetSessionId
|
|
748
|
+
: this.instanceId,
|
|
749
|
+
providerType: typeof event.providerType === 'string' && event.providerType.trim()
|
|
750
|
+
? event.providerType
|
|
751
|
+
: this.type,
|
|
752
|
+
workspaceName: typeof event.workspaceName === 'string' && event.workspaceName.trim()
|
|
753
|
+
? event.workspaceName
|
|
754
|
+
: this.workingDir,
|
|
755
|
+
providerSessionId: typeof event.providerSessionId === 'string' && event.providerSessionId.trim()
|
|
756
|
+
? event.providerSessionId
|
|
757
|
+
: this.providerSessionId,
|
|
758
|
+
};
|
|
759
|
+
if (this.context?.emitProviderEvent) {
|
|
760
|
+
this.context.emitProviderEvent(enrichedEvent);
|
|
761
|
+
return;
|
|
762
|
+
}
|
|
763
|
+
this.events.push(enrichedEvent);
|
|
742
764
|
}
|
|
743
765
|
|
|
744
766
|
private flushEvents(): ProviderEvent[] {
|
|
@@ -47,7 +47,10 @@ export class ProviderInstanceManager {
|
|
|
47
47
|
this.instances.get(id)!.dispose();
|
|
48
48
|
}
|
|
49
49
|
this.instances.set(id, instance);
|
|
50
|
-
await instance.init(
|
|
50
|
+
await instance.init({
|
|
51
|
+
...context,
|
|
52
|
+
emitProviderEvent: (event) => this.emitProviderEvent(instance.type, id, event),
|
|
53
|
+
});
|
|
51
54
|
}
|
|
52
55
|
|
|
53
56
|
/**
|
|
@@ -237,6 +240,22 @@ export class ProviderInstanceManager {
|
|
|
237
240
|
this.eventListeners.push(listener);
|
|
238
241
|
}
|
|
239
242
|
|
|
243
|
+
emitProviderEvent(providerType: string, instanceId: string, event: ProviderEvent): void {
|
|
244
|
+
const payload = {
|
|
245
|
+
...event,
|
|
246
|
+
providerType,
|
|
247
|
+
instanceId: typeof event.instanceId === 'string' && event.instanceId.trim()
|
|
248
|
+
? event.instanceId
|
|
249
|
+
: instanceId,
|
|
250
|
+
targetSessionId: typeof event.targetSessionId === 'string' && event.targetSessionId.trim()
|
|
251
|
+
? event.targetSessionId
|
|
252
|
+
: instanceId,
|
|
253
|
+
} as ProviderEvent & { providerType: string };
|
|
254
|
+
for (const listener of this.eventListeners) {
|
|
255
|
+
listener(payload);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
240
259
|
private emitPendingEvents(
|
|
241
260
|
providerType: string,
|
|
242
261
|
state: ProviderState,
|
|
@@ -174,6 +174,8 @@ export interface InstanceContext {
|
|
|
174
174
|
onPtyData?: (data: string) => void;
|
|
175
175
|
/** Provider configvalue (resolved) */
|
|
176
176
|
settings: Record<string, any>;
|
|
177
|
+
/** Immediate provider-originated status/event emission. Used to avoid waiting for status polling. */
|
|
178
|
+
emitProviderEvent?: (event: ProviderEvent) => void;
|
|
177
179
|
}
|
|
178
180
|
|
|
179
181
|
export interface ProviderInstance {
|
package/src/repo-mesh-types.ts
CHANGED
package/src/shared-types.ts
CHANGED
|
@@ -641,6 +641,8 @@ export interface DaemonStatusEventPayload {
|
|
|
641
641
|
timestamp: number;
|
|
642
642
|
targetSessionId?: string;
|
|
643
643
|
providerType?: string;
|
|
644
|
+
providerSessionId?: string;
|
|
645
|
+
workspaceName?: string;
|
|
644
646
|
duration?: number;
|
|
645
647
|
elapsedSec?: number;
|
|
646
648
|
modalMessage?: string;
|
|
@@ -662,6 +664,8 @@ export interface DashboardStatusEventPayload {
|
|
|
662
664
|
daemonId?: string;
|
|
663
665
|
providerType?: string;
|
|
664
666
|
targetSessionId?: string;
|
|
667
|
+
providerSessionId?: string;
|
|
668
|
+
workspaceName?: string;
|
|
665
669
|
duration?: number;
|
|
666
670
|
elapsedSec?: number;
|
|
667
671
|
modalMessage?: string;
|
package/src/status/reporter.ts
CHANGED
|
@@ -151,6 +151,12 @@ export class DaemonStatusReporter {
|
|
|
151
151
|
if (providerType) {
|
|
152
152
|
payload.providerType = providerType;
|
|
153
153
|
}
|
|
154
|
+
if (typeof event.providerSessionId === 'string' && event.providerSessionId.trim()) {
|
|
155
|
+
payload.providerSessionId = event.providerSessionId.trim();
|
|
156
|
+
}
|
|
157
|
+
if (typeof event.workspaceName === 'string' && event.workspaceName.trim()) {
|
|
158
|
+
payload.workspaceName = event.workspaceName.trim();
|
|
159
|
+
}
|
|
154
160
|
if (typeof event.duration === 'number' && Number.isFinite(event.duration)) {
|
|
155
161
|
payload.duration = event.duration;
|
|
156
162
|
}
|