@adhdev/daemon-core 0.9.82-rc.17 → 0.9.82-rc.19
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/commands/router.d.ts +1 -0
- package/dist/index.js +91 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +91 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/commands/router.ts +122 -15
package/package.json
CHANGED
package/src/commands/router.ts
CHANGED
|
@@ -328,6 +328,59 @@ function summarizeMeshSessionRecord(record: any): Record<string, unknown> {
|
|
|
328
328
|
};
|
|
329
329
|
}
|
|
330
330
|
|
|
331
|
+
function readLiveMeshNodeWorkspace(args: {
|
|
332
|
+
meshId: string;
|
|
333
|
+
nodeId: string;
|
|
334
|
+
liveSessionRecords: any[];
|
|
335
|
+
allowCoordinatorSession?: boolean;
|
|
336
|
+
}): string {
|
|
337
|
+
const directNodeWorkspace = args.liveSessionRecords.find((record) => (
|
|
338
|
+
readStringValue(record?.meta?.meshNodeId) === args.nodeId
|
|
339
|
+
&& readStringValue(record?.workspace)
|
|
340
|
+
));
|
|
341
|
+
if (directNodeWorkspace) {
|
|
342
|
+
return readStringValue(directNodeWorkspace.workspace) || '';
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (args.allowCoordinatorSession) {
|
|
346
|
+
const coordinatorWorkspace = args.liveSessionRecords.find((record) => (
|
|
347
|
+
readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId
|
|
348
|
+
&& readStringValue(record?.workspace)
|
|
349
|
+
));
|
|
350
|
+
if (coordinatorWorkspace) {
|
|
351
|
+
return readStringValue(coordinatorWorkspace.workspace) || '';
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
return '';
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function collectLiveMeshSessionRecords(args: {
|
|
359
|
+
meshId: string;
|
|
360
|
+
node: any;
|
|
361
|
+
nodeId: string;
|
|
362
|
+
liveSessionRecords: any[];
|
|
363
|
+
allowCoordinatorSession?: boolean;
|
|
364
|
+
}): any[] {
|
|
365
|
+
const matches = args.liveSessionRecords.filter((record) => {
|
|
366
|
+
if (readStringValue(record?.meta?.meshNodeId) === args.nodeId) return true;
|
|
367
|
+
const recordWorkspace = readStringValue(record?.workspace);
|
|
368
|
+
const nodeWorkspace = readStringValue(args.node?.workspace);
|
|
369
|
+
return !!recordWorkspace && !!nodeWorkspace && recordWorkspace === nodeWorkspace;
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
if (args.allowCoordinatorSession) {
|
|
373
|
+
for (const record of args.liveSessionRecords) {
|
|
374
|
+
if (readStringValue(record?.meta?.meshCoordinatorFor) !== args.meshId) continue;
|
|
375
|
+
const sessionId = readStringValue(record?.sessionId);
|
|
376
|
+
if (sessionId && matches.some((entry) => readStringValue(entry?.sessionId) === sessionId)) continue;
|
|
377
|
+
matches.push(record);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return matches;
|
|
382
|
+
}
|
|
383
|
+
|
|
331
384
|
function applyCachedInlineMeshNodeStatus(status: Record<string, unknown>, node: any): boolean {
|
|
332
385
|
const cachedStatus = readObjectRecord(node?.cachedStatus);
|
|
333
386
|
const git = buildCachedInlineMeshGitStatus(node);
|
|
@@ -900,29 +953,40 @@ export class DaemonCommandRouter {
|
|
|
900
953
|
|
|
901
954
|
public getCachedInlineMesh(meshId: string, inlineMesh?: unknown): any | undefined {
|
|
902
955
|
if (inlineMesh && typeof inlineMesh === 'object') {
|
|
903
|
-
this.
|
|
904
|
-
return inlineMesh as any;
|
|
956
|
+
return this.warmInlineMeshCache(meshId, inlineMesh);
|
|
905
957
|
}
|
|
906
958
|
return this.inlineMeshCache.get(meshId);
|
|
907
959
|
}
|
|
908
960
|
|
|
961
|
+
private warmInlineMeshCache(meshId: string, inlineMesh?: unknown): any | undefined {
|
|
962
|
+
if (!inlineMesh || typeof inlineMesh !== 'object') return undefined;
|
|
963
|
+
const cached = this.inlineMeshCache.get(meshId);
|
|
964
|
+
if (cached) return cached;
|
|
965
|
+
this.inlineMeshCache.set(meshId, inlineMesh as any);
|
|
966
|
+
return inlineMesh as any;
|
|
967
|
+
}
|
|
968
|
+
|
|
909
969
|
private async getMeshForCommand(
|
|
910
970
|
meshId: string,
|
|
911
971
|
inlineMesh?: unknown,
|
|
912
972
|
options?: { preferInline?: boolean },
|
|
913
|
-
): Promise<{ mesh: any; inline: boolean } | null> {
|
|
973
|
+
): Promise<{ mesh: any; inline: boolean; source: 'inline_cache' | 'inline_bootstrap' | 'local_config' } | null> {
|
|
914
974
|
const preferInline = options?.preferInline === true;
|
|
915
975
|
if (preferInline) {
|
|
916
|
-
const cached = this.getCachedInlineMesh(meshId
|
|
917
|
-
if (cached) return { mesh: cached, inline: true };
|
|
976
|
+
const cached = this.getCachedInlineMesh(meshId);
|
|
977
|
+
if (cached) return { mesh: cached, inline: true, source: 'inline_cache' };
|
|
978
|
+
const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
979
|
+
if (warmedInline) return { mesh: warmedInline, inline: true, source: 'inline_bootstrap' };
|
|
918
980
|
}
|
|
919
981
|
try {
|
|
920
982
|
const { getMesh } = await import('../config/mesh-config.js');
|
|
921
983
|
const mesh = getMesh(meshId);
|
|
922
|
-
if (mesh) return { mesh, inline: false };
|
|
984
|
+
if (mesh) return { mesh, inline: false, source: 'local_config' };
|
|
923
985
|
} catch { /* fall through to inline cache */ }
|
|
924
|
-
const cached = this.getCachedInlineMesh(meshId
|
|
925
|
-
|
|
986
|
+
const cached = this.getCachedInlineMesh(meshId);
|
|
987
|
+
if (cached) return { mesh: cached, inline: true, source: 'inline_cache' };
|
|
988
|
+
const warmedInline = this.warmInlineMeshCache(meshId, inlineMesh);
|
|
989
|
+
return warmedInline ? { mesh: warmedInline, inline: true, source: 'inline_bootstrap' } : null;
|
|
926
990
|
}
|
|
927
991
|
|
|
928
992
|
private updateInlineMeshNode(meshId: string, mesh: any, node: any): void {
|
|
@@ -1219,6 +1283,7 @@ export class DaemonCommandRouter {
|
|
|
1219
1283
|
const deletedSessionIds: string[] = [];
|
|
1220
1284
|
const skippedSessionIds: string[] = [];
|
|
1221
1285
|
const skippedLiveSessionIds: string[] = [];
|
|
1286
|
+
const skippedCoordinatorSessionIds: string[] = [];
|
|
1222
1287
|
const deleteUnsupportedSessionIds: string[] = [];
|
|
1223
1288
|
const recordsRemainSessionIds: string[] = [];
|
|
1224
1289
|
const errors: Array<{ sessionId: string; error: string }> = [];
|
|
@@ -1253,6 +1318,12 @@ export class DaemonCommandRouter {
|
|
|
1253
1318
|
const completed = this.isCompletedHostedSession(record);
|
|
1254
1319
|
const surfaceKind = getSessionHostSurfaceKind(record);
|
|
1255
1320
|
const liveRuntime = surfaceKind === 'live_runtime';
|
|
1321
|
+
const coordinatorSession = readStringValue(record?.meta?.meshCoordinatorFor) === args.meshId;
|
|
1322
|
+
if (!hasExplicitSessionIds && coordinatorSession) {
|
|
1323
|
+
skippedSessionIds.push(sessionId);
|
|
1324
|
+
skippedCoordinatorSessionIds.push(sessionId);
|
|
1325
|
+
continue;
|
|
1326
|
+
}
|
|
1256
1327
|
if (!hasExplicitSessionIds && liveRuntime) {
|
|
1257
1328
|
skippedSessionIds.push(sessionId);
|
|
1258
1329
|
skippedLiveSessionIds.push(sessionId);
|
|
@@ -1322,6 +1393,7 @@ export class DaemonCommandRouter {
|
|
|
1322
1393
|
deletedSessionIds,
|
|
1323
1394
|
skippedSessionIds,
|
|
1324
1395
|
skippedLiveSessionIds,
|
|
1396
|
+
skippedCoordinatorSessionIds,
|
|
1325
1397
|
...(deleteUnsupported ? {
|
|
1326
1398
|
deleteUnsupported: true,
|
|
1327
1399
|
effectiveCleanup: args.mode === 'stop_and_delete'
|
|
@@ -2669,7 +2741,16 @@ export class DaemonCommandRouter {
|
|
|
2669
2741
|
cliType,
|
|
2670
2742
|
};
|
|
2671
2743
|
}
|
|
2672
|
-
const
|
|
2744
|
+
const sessionHostRecords = this.deps.sessionHostControl?.listSessions
|
|
2745
|
+
? await this.deps.sessionHostControl.listSessions().catch(() => [])
|
|
2746
|
+
: [];
|
|
2747
|
+
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
2748
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
2749
|
+
meshId,
|
|
2750
|
+
nodeId: String(coordinatorNode.id || coordinatorNode.nodeId || preferredCoordinatorNodeId || ''),
|
|
2751
|
+
liveSessionRecords: liveMeshSessions,
|
|
2752
|
+
allowCoordinatorSession: true,
|
|
2753
|
+
}) || (typeof coordinatorNode.workspace === 'string' ? coordinatorNode.workspace.trim() : '');
|
|
2673
2754
|
if (!workspace) return { success: false, error: 'Coordinator node workspace required', meshId, cliType };
|
|
2674
2755
|
if (!cliType) {
|
|
2675
2756
|
const resolved = await resolveProviderTypeFromPriority({
|
|
@@ -3028,8 +3109,13 @@ export class DaemonCommandRouter {
|
|
|
3028
3109
|
const liveMeshSessions = partitionSessionHostRecords(Array.isArray(sessionHostRecords) ? sessionHostRecords : []).liveRuntimes;
|
|
3029
3110
|
|
|
3030
3111
|
const localMachineId = loadConfig().machineId || '';
|
|
3112
|
+
const selectedCoordinatorNodeId = readStringValue(
|
|
3113
|
+
mesh.coordinator?.preferredNodeId,
|
|
3114
|
+
(mesh.nodes?.[0] as any)?.id,
|
|
3115
|
+
(mesh.nodes?.[0] as any)?.nodeId,
|
|
3116
|
+
);
|
|
3031
3117
|
const inlineCoordinatorNodeId = meshRecord?.inline && Array.isArray(mesh.nodes)
|
|
3032
|
-
?
|
|
3118
|
+
? selectedCoordinatorNodeId
|
|
3033
3119
|
: undefined;
|
|
3034
3120
|
const refreshedAt = new Date().toISOString();
|
|
3035
3121
|
const nodeStatuses = [];
|
|
@@ -3089,8 +3175,20 @@ export class DaemonCommandRouter {
|
|
|
3089
3175
|
reason: 'Node has no daemon id, so mesh transport cannot be reported from the selected coordinator.',
|
|
3090
3176
|
};
|
|
3091
3177
|
}
|
|
3092
|
-
const matchedLiveSessionRecords =
|
|
3093
|
-
|
|
3178
|
+
const matchedLiveSessionRecords = collectLiveMeshSessionRecords({
|
|
3179
|
+
meshId,
|
|
3180
|
+
node,
|
|
3181
|
+
nodeId,
|
|
3182
|
+
liveSessionRecords: liveMeshSessions,
|
|
3183
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId,
|
|
3184
|
+
});
|
|
3185
|
+
const workspace = readLiveMeshNodeWorkspace({
|
|
3186
|
+
meshId,
|
|
3187
|
+
nodeId,
|
|
3188
|
+
liveSessionRecords: matchedLiveSessionRecords,
|
|
3189
|
+
allowCoordinatorSession: nodeId === selectedCoordinatorNodeId,
|
|
3190
|
+
}) || (typeof node.workspace === 'string' ? node.workspace : '');
|
|
3191
|
+
status.workspace = workspace || node.workspace;
|
|
3094
3192
|
if (matchedLiveSessionRecords.length > 0) {
|
|
3095
3193
|
const sessionIds = matchedLiveSessionRecords
|
|
3096
3194
|
.map((record: any) => typeof record?.sessionId === 'string' ? record.sessionId : '')
|
|
@@ -3104,14 +3202,14 @@ export class DaemonCommandRouter {
|
|
|
3104
3202
|
status.providers = Array.from(new Set([...(Array.isArray(status.providers) ? status.providers as string[] : []), ...providerTypes]));
|
|
3105
3203
|
}
|
|
3106
3204
|
}
|
|
3107
|
-
if (
|
|
3108
|
-
if (!fs.existsSync(
|
|
3205
|
+
if (workspace) {
|
|
3206
|
+
if (!fs.existsSync(workspace) && applyCachedInlineMeshNodeStatus(status, node)) {
|
|
3109
3207
|
status.launchReady = !!daemonId && (readStringValue(status.machineStatus) === 'online' || isSelfNode);
|
|
3110
3208
|
nodeStatuses.push(status);
|
|
3111
3209
|
continue;
|
|
3112
3210
|
}
|
|
3113
3211
|
try {
|
|
3114
|
-
const gitStatus = await getGitRepoStatus(
|
|
3212
|
+
const gitStatus = await getGitRepoStatus(workspace, { timeoutMs: 10_000, refreshUpstream: true });
|
|
3115
3213
|
status.git = gitStatus;
|
|
3116
3214
|
if (gitStatus.isGitRepo) {
|
|
3117
3215
|
status.health = deriveMeshNodeHealthFromGit(gitStatus as unknown as Record<string, unknown>);
|
|
@@ -3138,6 +3236,15 @@ export class DaemonCommandRouter {
|
|
|
3138
3236
|
repoIdentity: mesh.repoIdentity,
|
|
3139
3237
|
defaultBranch: mesh.defaultBranch,
|
|
3140
3238
|
refreshedAt: new Date().toISOString(),
|
|
3239
|
+
sourceOfTruth: {
|
|
3240
|
+
membership: meshRecord?.source === 'inline_cache'
|
|
3241
|
+
? 'coordinator_inline_mesh_cache'
|
|
3242
|
+
: meshRecord?.source === 'local_config'
|
|
3243
|
+
? 'local_mesh_config'
|
|
3244
|
+
: 'inline_bootstrap_snapshot',
|
|
3245
|
+
coordinatorOwnsLiveTruth: meshRecord?.source !== 'inline_bootstrap',
|
|
3246
|
+
historicalEvidenceOnly: ['recoveryHints', 'ledger.summary', 'queue.summary'],
|
|
3247
|
+
},
|
|
3141
3248
|
nodes: nodeStatuses,
|
|
3142
3249
|
queue: { tasks: queue, summary: queueSummary },
|
|
3143
3250
|
ledger: { entries: ledgerEntries, summary: ledgerSummary },
|