@adhdev/daemon-core 0.9.82-rc.460 → 0.9.82-rc.462
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/config/mesh-config.d.ts +7 -0
- package/dist/detection/cli-detector.d.ts +17 -0
- package/dist/git/git-commands.d.ts +14 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +567 -28
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +565 -27
- package/dist/index.mjs.map +1 -1
- package/dist/mesh/mesh-events-pending.d.ts +75 -1
- package/dist/mesh/mesh-events.d.ts +2 -2
- package/dist/mesh/mesh-node-identity.d.ts +4 -0
- package/dist/mesh/mesh-reconcile-loop.d.ts +12 -0
- package/dist/mesh/mesh-runtime-store.d.ts +17 -0
- package/dist/providers/approval-utils.d.ts +1 -0
- package/dist/repo-mesh-types.d.ts +111 -0
- package/package.json +3 -3
- package/src/boot/daemon-lifecycle.ts +15 -2
- package/src/commands/high-family/mesh-events.ts +14 -1
- package/src/commands/high-family/mesh-status.ts +29 -2
- package/src/config/mesh-config.ts +13 -0
- package/src/detection/cli-detector.ts +66 -0
- package/src/git/git-commands.ts +35 -2
- package/src/index.ts +1 -1
- package/src/mesh/coordinator-prompt.ts +19 -1
- package/src/mesh/mesh-event-forwarding.ts +19 -1
- package/src/mesh/mesh-events-pending.ts +465 -5
- package/src/mesh/mesh-events.ts +5 -0
- package/src/mesh/mesh-node-identity.ts +77 -6
- package/src/mesh/mesh-reconcile-loop.ts +74 -1
- package/src/mesh/mesh-runtime-store.ts +30 -0
- package/src/providers/approval-utils.ts +1 -1
- package/src/providers/cli-provider-instance.ts +24 -12
- package/src/repo-mesh-types.ts +111 -0
package/src/git/git-commands.ts
CHANGED
|
@@ -102,6 +102,14 @@ export interface GitCommandServices {
|
|
|
102
102
|
checkoutFiles?: (params: { workspace: string; paths: string[] }) => Promise<{ checkedOut: string[] }>;
|
|
103
103
|
getRemoteUrl?: (params: { workspace: string; remote?: string }) => Promise<{ remoteUrl: string; remote: string }>;
|
|
104
104
|
push?: (params: { workspace: string; remote?: string; branch?: string; setUpstream?: boolean }) => Promise<GitPushResult>;
|
|
105
|
+
/**
|
|
106
|
+
* Best-effort, non-blocking source of this daemon's detected provider CLI/ACP
|
|
107
|
+
* versions (keyed by provider id) + its build version, folded onto the git_status
|
|
108
|
+
* envelope so a mesh coordinator can self-heal each node's providerVersions the
|
|
109
|
+
* same way it does platform/arch. Wired at daemon boot from the cached CLI
|
|
110
|
+
* detection snapshot; omitted (⇒ versions not reported) when unavailable.
|
|
111
|
+
*/
|
|
112
|
+
getReporterProviderVersions?: () => { providerVersions?: Record<string, string>; daemonBuildVersion?: string };
|
|
105
113
|
}
|
|
106
114
|
|
|
107
115
|
type GitCommandFailure = {
|
|
@@ -116,7 +124,7 @@ type GitCommandSuccess =
|
|
|
116
124
|
// node's userOverrides.platform/arch (the fields capability-tag routing reads).
|
|
117
125
|
// reporterMachineNickname carries the responding daemon's config.machineNickname
|
|
118
126
|
// so the coordinator can populate node.machineNickname → the friendly display label.
|
|
119
|
-
| { success: true; status: GitRepoStatus; reporterPlatform?: string; reporterArch?: string; reporterMachineNickname?: string }
|
|
127
|
+
| { success: true; status: GitRepoStatus; reporterPlatform?: string; reporterArch?: string; reporterMachineNickname?: string; reporterProviderVersions?: Record<string, string>; reporterDaemonBuildVersion?: string }
|
|
120
128
|
| { success: true; diffSummary: GitDiffSummary }
|
|
121
129
|
| { success: true; diff: GitFileDiff }
|
|
122
130
|
| { success: true; snapshot: GitSnapshot }
|
|
@@ -179,7 +187,9 @@ const defaultSnapshotStore = createGitSnapshotStore({
|
|
|
179
187
|
getDiffSummary: (workspace) => getGitDiffSummary(workspace),
|
|
180
188
|
});
|
|
181
189
|
|
|
182
|
-
export function createDefaultGitCommandServices(
|
|
190
|
+
export function createDefaultGitCommandServices(
|
|
191
|
+
overrides?: Pick<GitCommandServices, 'getReporterProviderVersions'>,
|
|
192
|
+
): GitCommandServices {
|
|
183
193
|
return {
|
|
184
194
|
getStatus: ({ workspace, refreshUpstream }) => getGitRepoStatus(workspace, { refreshUpstream }),
|
|
185
195
|
getDiffSummary: ({ workspace, base }) => getGitDiffSummary(workspace, base ? { baseRef: base } : {}),
|
|
@@ -199,6 +209,9 @@ export function createDefaultGitCommandServices(): GitCommandServices {
|
|
|
199
209
|
getRemoteUrl: async ({ workspace, remote = 'origin' }) => gitGetRemoteUrl(workspace, remote),
|
|
200
210
|
push: async ({ workspace, remote = 'origin', branch, setUpstream = false }) =>
|
|
201
211
|
gitPush(workspace, remote, branch, setUpstream),
|
|
212
|
+
...(overrides?.getReporterProviderVersions
|
|
213
|
+
? { getReporterProviderVersions: overrides.getReporterProviderVersions }
|
|
214
|
+
: {}),
|
|
202
215
|
};
|
|
203
216
|
}
|
|
204
217
|
|
|
@@ -328,12 +341,32 @@ export async function handleGitCommand(
|
|
|
328
341
|
return undefined;
|
|
329
342
|
}
|
|
330
343
|
})();
|
|
344
|
+
// Provider versions + build version ride the same self-report channel (T7
|
|
345
|
+
// visibility). Best-effort and non-blocking: the service reads a cached
|
|
346
|
+
// snapshot, so a cold cache simply omits the fields on this probe.
|
|
347
|
+
const reporterVersions = (() => {
|
|
348
|
+
try {
|
|
349
|
+
return services.getReporterProviderVersions?.() ?? {};
|
|
350
|
+
} catch {
|
|
351
|
+
return {};
|
|
352
|
+
}
|
|
353
|
+
})();
|
|
354
|
+
const reporterProviderVersions =
|
|
355
|
+
reporterVersions.providerVersions && Object.keys(reporterVersions.providerVersions).length > 0
|
|
356
|
+
? reporterVersions.providerVersions
|
|
357
|
+
: undefined;
|
|
358
|
+
const reporterDaemonBuildVersion =
|
|
359
|
+
typeof reporterVersions.daemonBuildVersion === 'string' && reporterVersions.daemonBuildVersion.trim()
|
|
360
|
+
? reporterVersions.daemonBuildVersion.trim()
|
|
361
|
+
: undefined;
|
|
331
362
|
return {
|
|
332
363
|
success: true,
|
|
333
364
|
status,
|
|
334
365
|
reporterPlatform: process.platform,
|
|
335
366
|
reporterArch: process.arch,
|
|
336
367
|
...(reporterMachineNickname ? { reporterMachineNickname } : {}),
|
|
368
|
+
...(reporterProviderVersions ? { reporterProviderVersions } : {}),
|
|
369
|
+
...(reporterDaemonBuildVersion ? { reporterDaemonBuildVersion } : {}),
|
|
337
370
|
};
|
|
338
371
|
}
|
|
339
372
|
|
package/src/index.ts
CHANGED
|
@@ -295,7 +295,7 @@ export { buildMeshHostRequiredFailure, createDefaultMeshHostMetadata, isMeshHost
|
|
|
295
295
|
// export type { MeshGraph, MeshGraphNode, MeshGraphEdge, MeshGraphNodeType, MeshGraphEdgeType } from './mesh/mesh-visualization.js';
|
|
296
296
|
|
|
297
297
|
// ── Mesh Events ──
|
|
298
|
-
export { triggerMeshQueue, drainPendingMeshCoordinatorEvents, getPendingMeshCoordinatorEvents, clearPendingMeshCoordinatorEvents, queuePendingMeshCoordinatorEvent, reconcileDirectDispatchCompletionFromTranscript } from './mesh/mesh-events.js';
|
|
298
|
+
export { triggerMeshQueue, drainPendingMeshCoordinatorEvents, getPendingMeshCoordinatorEvents, clearPendingMeshCoordinatorEvents, queuePendingMeshCoordinatorEvent, serializeV2EnvelopeToWire, readV2EnvelopeFromWire, reconcileDirectDispatchCompletionFromTranscript } from './mesh/mesh-events.js';
|
|
299
299
|
export type { PendingMeshCoordinatorEvent } from './mesh/mesh-events.js';
|
|
300
300
|
// The coordinator-side preview surfaced from a worker's completion/status event
|
|
301
301
|
// (finalSummary / workerResult.summary / lastMessagePreview). Same data the mobile
|
|
@@ -392,9 +392,27 @@ function buildNodeStatusSection(nodes: RepoMeshNodeStatus[]): string {
|
|
|
392
392
|
? `sessions: ${n.activeSessions.join(', ')}`
|
|
393
393
|
: 'no active sessions';
|
|
394
394
|
const branch = n.git?.branch ? `branch: \`${n.git.branch}\`` : '';
|
|
395
|
+
// Render each provider with its detected version when known (T7 visibility)
|
|
396
|
+
// so the coordinator can eyeball a per-node provider-version skew inline —
|
|
397
|
+
// e.g. `claude-cli@1.2.3`. Providers without a reported version render bare.
|
|
398
|
+
const providerVersions = n.providerVersions && typeof n.providerVersions === 'object'
|
|
399
|
+
? n.providerVersions
|
|
400
|
+
: undefined;
|
|
401
|
+
const providersRendered = n.providers?.length
|
|
402
|
+
? n.providers
|
|
403
|
+
.map((p) => {
|
|
404
|
+
const version = providerVersions?.[p];
|
|
405
|
+
return version ? `${p}@${version}` : p;
|
|
406
|
+
})
|
|
407
|
+
.join(', ')
|
|
408
|
+
: '';
|
|
409
|
+
const buildVersion = typeof n.daemonBuildVersion === 'string' && n.daemonBuildVersion
|
|
410
|
+
? `build: ${n.daemonBuildVersion}`
|
|
411
|
+
: '';
|
|
395
412
|
const context = [
|
|
396
413
|
n.daemonId ? `daemon: \`${n.daemonId}\`` : '',
|
|
397
|
-
|
|
414
|
+
providersRendered ? `providers: ${providersRendered}` : '',
|
|
415
|
+
buildVersion,
|
|
398
416
|
].filter(Boolean).join(' | ');
|
|
399
417
|
lines.push(`- ${healthIcon} **${n.machineLabel}** (nodeId: \`${n.nodeId}\`)`);
|
|
400
418
|
lines.push(` workspace: \`${n.workspace}\`${context ? ` | ${context}` : ''} | ${branch} | ${sessions}`);
|
|
@@ -7,7 +7,7 @@ import type { SessionRecoveryContext } from './mesh-ledger.js';
|
|
|
7
7
|
import { updateSessionTaskStatus, enqueueTask, updateDirectDispatchStatus, cleanupTerminalDirectDispatches, getActiveDirectDispatches, hasPendingDependents, getQueue } from './mesh-work-queue.js';
|
|
8
8
|
import { markSessionDeliveriesTerminal, updateSessionDeliveryStatus, recordCompletionConflict } from './mesh-delivery-policy.js';
|
|
9
9
|
import { MeshRuntimeStore } from './mesh-runtime-store.js';
|
|
10
|
-
import { queuePendingMeshCoordinatorEvent, drainPendingMeshCoordinatorEvents, type PendingMeshCoordinatorEvent } from './mesh-events-pending.js';
|
|
10
|
+
import { queuePendingMeshCoordinatorEvent, drainPendingMeshCoordinatorEvents, readV2EnvelopeFromWire, type PendingMeshCoordinatorEvent } from './mesh-events-pending.js';
|
|
11
11
|
import type { ProviderInstance } from '../providers/provider-instance.js';
|
|
12
12
|
import { resolveWorkerDelegateRouting, recordUnroutableDelegateEvent, isUnroutableDelegateRejection } from './mesh-routing.js';
|
|
13
13
|
import { resolveMeshHostStatus } from './mesh-host-ownership.js';
|
|
@@ -681,6 +681,13 @@ function injectMeshSystemMessage(components: DaemonComponents, args: {
|
|
|
681
681
|
nodeLabel: string;
|
|
682
682
|
event: string;
|
|
683
683
|
metadataEvent: Record<string, unknown>;
|
|
684
|
+
// T4 (B3b): v2 envelope restored from a remote (P2P) relay's flat payload. Only the
|
|
685
|
+
// relay path (handleMeshForwardEvent) sets it; the in-process forward path leaves it
|
|
686
|
+
// undefined and the local emit stamp applies as usual. When present with a preserved
|
|
687
|
+
// eventId, it is spread onto the re-queued pending event so stampPendingEventV2's
|
|
688
|
+
// already-stamped short-circuit keeps the ORIGINAL eventId (cross-machine idempotency).
|
|
689
|
+
v2Envelope?: Partial<Pick<PendingMeshCoordinatorEvent,
|
|
690
|
+
'protocolVersion' | 'eventId' | 'scope' | 'dispatchedBy' | 'intendedFor'>>;
|
|
684
691
|
}) {
|
|
685
692
|
const eventSessionId = resolveEventSessionId(args.metadataEvent, args.sourceInstanceId);
|
|
686
693
|
const eventNodeId = readNonEmptyString(args.nodeId) || readNonEmptyString(args.metadataEvent.meshNodeId);
|
|
@@ -1363,6 +1370,12 @@ function injectMeshSystemMessage(components: DaemonComponents, args: {
|
|
|
1363
1370
|
// Top-level session anchor for the local PHASE 2 strict-match on the coordinator
|
|
1364
1371
|
// daemon. Absent → daemon-level broadcast (legacy / single-coordinator path).
|
|
1365
1372
|
...(workerCoordinatorSessionId ? { targetCoordinatorSessionId: workerCoordinatorSessionId } : {}),
|
|
1373
|
+
// T4 (B3b): restore the v2 envelope from the remote relay so the re-queue keeps the
|
|
1374
|
+
// ORIGINAL eventId. Spread LAST so its authoritative eventId/scope/identity win over
|
|
1375
|
+
// any default. queuePendingMeshCoordinatorEvent → stampPendingEventV2 then no-ops
|
|
1376
|
+
// (already-stamped short-circuit) instead of minting a fresh eventId. Empty object
|
|
1377
|
+
// for a v1 relay → unchanged v1 emit-stamp path (version-skew safe).
|
|
1378
|
+
...(args.v2Envelope ?? {}),
|
|
1366
1379
|
};
|
|
1367
1380
|
if (queuePendingMeshCoordinatorEvent(pendingEvent)) {
|
|
1368
1381
|
LOG.info('MeshEvents', `Queued ${args.event} for coordinator (mesh ${args.meshId}${workerCoordinatorDaemonId ? `, coordinator daemon ${workerCoordinatorDaemonId}` : ''}${workerCoordinatorSessionId ? `, coordinator session ${workerCoordinatorSessionId}` : ''})`);
|
|
@@ -1518,6 +1531,11 @@ export function handleMeshForwardEvent(components: DaemonComponents, payload: Re
|
|
|
1518
1531
|
nodeLabel,
|
|
1519
1532
|
event: eventName,
|
|
1520
1533
|
metadataEvent: buildRelayMetadataEvent(payload),
|
|
1534
|
+
// T4 (B3b): restore the v2 envelope carried at the top level of the relayed flat
|
|
1535
|
+
// payload (buildForwardPayloadFromPending → serializeV2EnvelopeToWire) so the
|
|
1536
|
+
// re-queue preserves the original eventId (idempotency) and unicast routing rather
|
|
1537
|
+
// than re-stamping a fresh v1/broadcast event. Empty for a v1 relay (version-skew safe).
|
|
1538
|
+
v2Envelope: readV2EnvelopeFromWire(payload),
|
|
1521
1539
|
});
|
|
1522
1540
|
}
|
|
1523
1541
|
|