@adhdev/daemon-core 0.9.82-rc.448 → 0.9.82-rc.449
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/cli-manager.d.ts +10 -0
- package/dist/commands/med-family/types.d.ts +10 -0
- package/dist/index.js +64 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +64 -20
- package/dist/index.mjs.map +1 -1
- package/dist/providers/spec/adapter.d.ts +7 -0
- package/dist/providers/spec/fsm-driver.d.ts +6 -0
- package/package.json +2 -2
- package/src/commands/cli-manager.ts +41 -17
- package/src/commands/med-family/mesh-crud.ts +12 -1
- package/src/commands/med-family/types.ts +10 -0
- package/src/commands/router.ts +46 -1
- package/src/providers/spec/adapter.ts +11 -0
- package/src/providers/spec/cli-adapter.ts +9 -1
- package/src/providers/spec/fsm-driver.ts +9 -0
|
@@ -38,6 +38,16 @@ export interface CliTransportFactoryParams {
|
|
|
38
38
|
cliArgs?: string[];
|
|
39
39
|
providerSessionId?: string;
|
|
40
40
|
attachExisting?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Launch-time record meta (meshNodeId / meshNodeFor / launchedByCoordinator /
|
|
43
|
+
* autoLaunchedForQueueTaskId). Defense-in-depth for SESSION-ACCUMULATION-LEAK:
|
|
44
|
+
* a session-host factory impl SHOULD seed the create_session record with this
|
|
45
|
+
* so the node binding is present the instant the record exists, rather than
|
|
46
|
+
* relying solely on the post-spawn updateRuntimeMeta round-trip. Optional and
|
|
47
|
+
* additive — factory impls that ignore it keep the prior behavior; the
|
|
48
|
+
* post-spawn WTDISPATCH stamp in register() still runs as the primary path.
|
|
49
|
+
*/
|
|
50
|
+
initialMeta?: Record<string, unknown>;
|
|
41
51
|
}
|
|
42
52
|
export interface HostedCliRuntimeDescriptor {
|
|
43
53
|
runtimeId: string;
|
|
@@ -94,6 +94,16 @@ export interface MedFamilyContext {
|
|
|
94
94
|
dryRun?: boolean;
|
|
95
95
|
source?: 'mesh_cleanup_sessions' | 'mesh_remove_node' | 'magi_session_cleanup';
|
|
96
96
|
requireAutoLaunchedForTaskIds?: Record<string, string>;
|
|
97
|
+
/**
|
|
98
|
+
* Opt-in orphan reclaim (default false). When true, a workspace-only live
|
|
99
|
+
* session (no node binding) OR a session bound to a node that no longer
|
|
100
|
+
* exists in `liveMeshNodeIds` is stopped instead of skipped — reclaims the
|
|
101
|
+
* SESSION-ACCUMULATION-LEAK orphans. `liveMeshNodeIds` is the current mesh's
|
|
102
|
+
* node id set; a session whose meshNodeId is still present is treated as an
|
|
103
|
+
* active sibling and left alone.
|
|
104
|
+
*/
|
|
105
|
+
reclaimOrphans?: boolean;
|
|
106
|
+
liveMeshNodeIds?: string[];
|
|
97
107
|
}) => Promise<{
|
|
98
108
|
success: boolean;
|
|
99
109
|
[key: string]: unknown;
|
package/dist/index.js
CHANGED
|
@@ -409,10 +409,10 @@ function readInjected(value) {
|
|
|
409
409
|
}
|
|
410
410
|
function getDaemonBuildInfo() {
|
|
411
411
|
if (cached) return cached;
|
|
412
|
-
const commit = readInjected(true ? "
|
|
413
|
-
const commitShort = readInjected(true ? "
|
|
414
|
-
const version = readInjected(true ? "0.9.82-rc.
|
|
415
|
-
const builtAt = readInjected(true ? "2026-07-
|
|
412
|
+
const commit = readInjected(true ? "fe0e4d2aa03aea2793c2379e5ffc89abef5143d6" : void 0) ?? "unknown";
|
|
413
|
+
const commitShort = readInjected(true ? "fe0e4d2a" : void 0) ?? (commit !== "unknown" ? commit.slice(0, 7) : "unknown");
|
|
414
|
+
const version = readInjected(true ? "0.9.82-rc.449" : void 0) ?? readInjected(typeof process !== "undefined" ? process.env?.ADHDEV_PKG_VERSION : void 0) ?? "unknown";
|
|
415
|
+
const builtAt = readInjected(true ? "2026-07-03T01:58:07.610Z" : void 0);
|
|
416
416
|
cached = builtAt ? { commit, commitShort, version, builtAt } : { commit, commitShort, version };
|
|
417
417
|
return cached;
|
|
418
418
|
}
|
|
@@ -38006,6 +38006,16 @@ var TerminalAdapter = class {
|
|
|
38006
38006
|
this.recordEvent("input", capPreview(escapeControl(text)), text.length);
|
|
38007
38007
|
this.pty?.write(text);
|
|
38008
38008
|
}
|
|
38009
|
+
/** Forward runtime metadata (meshNodeId, workspaceLabel, lifecycle, …) to
|
|
38010
|
+
* the underlying transport so it reaches the session registry. The spec
|
|
38011
|
+
* path previously dropped everything but providerSessionId here, which
|
|
38012
|
+
* left autoLaunch's meshNodeId stamp unbound on the record (see
|
|
38013
|
+
* SESSION-ACCUMULATION-LEAK). No-op when the transport does not support
|
|
38014
|
+
* metadata updates (e.g. plain node-pty). */
|
|
38015
|
+
updateMeta(meta, replace = false) {
|
|
38016
|
+
if (!this.pty || typeof this.pty.updateMeta !== "function") return;
|
|
38017
|
+
this.pty.updateMeta(meta, replace);
|
|
38018
|
+
}
|
|
38009
38019
|
/** Debug-only: most-recent PTY input/output/resize/cursor events, oldest
|
|
38010
38020
|
* first. Pure observation — never consulted by the FSM. */
|
|
38011
38021
|
getEventTimeline(limit = MAX_PTY_EVENTS) {
|
|
@@ -38305,6 +38315,13 @@ var FsmDriver = class {
|
|
|
38305
38315
|
return;
|
|
38306
38316
|
}
|
|
38307
38317
|
}
|
|
38318
|
+
/** Forward runtime metadata to the terminal transport so mesh binding
|
|
38319
|
+
* fields (meshNodeId / meshNodeFor / workspaceLabel / lifecycle) reach
|
|
38320
|
+
* the session registry. Not a DashboardCommand — this is a control-plane
|
|
38321
|
+
* update, not user input. */
|
|
38322
|
+
updateMeta(meta, replace = false) {
|
|
38323
|
+
this.adapter.updateMeta(meta, replace);
|
|
38324
|
+
}
|
|
38308
38325
|
snapshot() {
|
|
38309
38326
|
return this.adapter.snapshot();
|
|
38310
38327
|
}
|
|
@@ -40509,9 +40526,14 @@ var SpecCliAdapter = class _SpecCliAdapter {
|
|
|
40509
40526
|
};
|
|
40510
40527
|
}
|
|
40511
40528
|
updateRuntimeMeta(meta) {
|
|
40512
|
-
if (meta
|
|
40529
|
+
if (!meta) return;
|
|
40530
|
+
if (typeof meta.providerSessionId === "string") {
|
|
40513
40531
|
this.providerSessionId = meta.providerSessionId;
|
|
40514
40532
|
}
|
|
40533
|
+
try {
|
|
40534
|
+
this.driver.updateMeta(meta);
|
|
40535
|
+
} catch {
|
|
40536
|
+
}
|
|
40515
40537
|
}
|
|
40516
40538
|
refreshProviderDefinition() {
|
|
40517
40539
|
}
|
|
@@ -44947,14 +44969,15 @@ var DaemonCliManager = class {
|
|
|
44947
44969
|
console.error(colorize("red", ` \u2717 Failed to save recent activity: ${e}`));
|
|
44948
44970
|
}
|
|
44949
44971
|
}
|
|
44950
|
-
getTransportFactory(runtimeId, providerType, workspace, cliArgs, providerSessionId, attachExisting = false) {
|
|
44972
|
+
getTransportFactory(runtimeId, providerType, workspace, cliArgs, providerSessionId, attachExisting = false, initialMeta) {
|
|
44951
44973
|
return this.deps.createPtyTransportFactory?.({
|
|
44952
44974
|
runtimeId,
|
|
44953
44975
|
providerType,
|
|
44954
44976
|
workspace,
|
|
44955
44977
|
cliArgs,
|
|
44956
44978
|
providerSessionId,
|
|
44957
|
-
attachExisting
|
|
44979
|
+
attachExisting,
|
|
44980
|
+
...initialMeta && Object.keys(initialMeta).length ? { initialMeta } : {}
|
|
44958
44981
|
}) || void 0;
|
|
44959
44982
|
}
|
|
44960
44983
|
createAdapter(cliType, workingDir, cliArgs, runtimeId, providerSessionId, attachExisting = false, extraEnv) {
|
|
@@ -45010,13 +45033,25 @@ var DaemonCliManager = class {
|
|
|
45010
45033
|
const instanceManager = this.deps.getInstanceManager();
|
|
45011
45034
|
const sessionRegistry = this.deps.getSessionRegistry?.() || null;
|
|
45012
45035
|
if (!instanceManager) throw new Error("InstanceManager not available");
|
|
45036
|
+
const launchMeshNodeId = typeof settings?.meshNodeId === "string" ? settings.meshNodeId.trim() : "";
|
|
45037
|
+
const launchMeshNodeFor = typeof settings?.meshNodeFor === "string" ? settings.meshNodeFor.trim() : "";
|
|
45038
|
+
const launchAutoLaunchedForQueueTaskId = typeof settings?.autoLaunchedForQueueTaskId === "string" ? settings.autoLaunchedForQueueTaskId.trim() : "";
|
|
45039
|
+
const launchRecordMeta = {
|
|
45040
|
+
...launchMeshNodeId ? { meshNodeId: launchMeshNodeId } : {},
|
|
45041
|
+
...launchMeshNodeFor ? { meshNodeFor: launchMeshNodeFor } : {},
|
|
45042
|
+
...settings?.launchedByCoordinator === true ? { launchedByCoordinator: true } : {},
|
|
45043
|
+
...launchAutoLaunchedForQueueTaskId ? { autoLaunchedForQueueTaskId: launchAutoLaunchedForQueueTaskId } : {}
|
|
45044
|
+
};
|
|
45013
45045
|
const transportFactory = this.getTransportFactory(
|
|
45014
45046
|
key2,
|
|
45015
45047
|
normalizedType,
|
|
45016
45048
|
resolvedDir,
|
|
45017
45049
|
cliArgs,
|
|
45018
45050
|
options?.providerSessionId,
|
|
45019
|
-
attachExisting
|
|
45051
|
+
attachExisting,
|
|
45052
|
+
// Only seed at create time for fresh launches — an attach restores an
|
|
45053
|
+
// existing record whose meta is already stamped; re-seeding could clobber.
|
|
45054
|
+
attachExisting ? void 0 : launchRecordMeta
|
|
45020
45055
|
);
|
|
45021
45056
|
const cliInstance = new CliProviderInstance(provider, resolvedDir, cliArgs, key2, transportFactory, options);
|
|
45022
45057
|
try {
|
|
@@ -45053,17 +45088,9 @@ var DaemonCliManager = class {
|
|
|
45053
45088
|
throw new Error(`Failed to start ${provider.displayName || provider.name || cliType}: ${spawnErr?.message}`);
|
|
45054
45089
|
}
|
|
45055
45090
|
this.adapters.set(key2, cliInstance.getAdapter());
|
|
45056
|
-
|
|
45057
|
-
const launchMeshNodeFor = typeof settings?.meshNodeFor === "string" ? settings.meshNodeFor.trim() : "";
|
|
45058
|
-
const launchAutoLaunchedForQueueTaskId = typeof settings?.autoLaunchedForQueueTaskId === "string" ? settings.autoLaunchedForQueueTaskId.trim() : "";
|
|
45059
|
-
if (launchMeshNodeId || launchMeshNodeFor || launchAutoLaunchedForQueueTaskId) {
|
|
45091
|
+
if (Object.keys(launchRecordMeta).length) {
|
|
45060
45092
|
try {
|
|
45061
|
-
cliInstance.getAdapter().updateRuntimeMeta?.({
|
|
45062
|
-
...launchMeshNodeId ? { meshNodeId: launchMeshNodeId } : {},
|
|
45063
|
-
...launchMeshNodeFor ? { meshNodeFor: launchMeshNodeFor } : {},
|
|
45064
|
-
...settings?.launchedByCoordinator === true ? { launchedByCoordinator: true } : {},
|
|
45065
|
-
...launchAutoLaunchedForQueueTaskId ? { autoLaunchedForQueueTaskId: launchAutoLaunchedForQueueTaskId } : {}
|
|
45066
|
-
});
|
|
45093
|
+
cliInstance.getAdapter().updateRuntimeMeta?.({ ...launchRecordMeta });
|
|
45067
45094
|
} catch {
|
|
45068
45095
|
}
|
|
45069
45096
|
}
|
|
@@ -50533,6 +50560,8 @@ var meshCrudHandlers = {
|
|
|
50533
50560
|
const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
|
|
50534
50561
|
const source = args?.source === "magi_session_cleanup" ? "magi_session_cleanup" : "mesh_cleanup_sessions";
|
|
50535
50562
|
const requireAutoLaunchedForTaskIds = args?.requireAutoLaunchedForTaskIds && typeof args.requireAutoLaunchedForTaskIds === "object" && !Array.isArray(args.requireAutoLaunchedForTaskIds) ? args.requireAutoLaunchedForTaskIds : void 0;
|
|
50563
|
+
const reclaimOrphans = args?.reclaimOrphans === true;
|
|
50564
|
+
const liveMeshNodeIds = Array.isArray(mesh?.nodes) ? mesh.nodes.map((n) => normalizeMeshNodeId(n)).filter(Boolean) : [];
|
|
50536
50565
|
const result = await ctx.cleanupMeshSessions({
|
|
50537
50566
|
meshId,
|
|
50538
50567
|
nodeId,
|
|
@@ -50541,7 +50570,9 @@ var meshCrudHandlers = {
|
|
|
50541
50570
|
sessionIds,
|
|
50542
50571
|
dryRun: args?.dryRun === true,
|
|
50543
50572
|
source,
|
|
50544
|
-
requireAutoLaunchedForTaskIds
|
|
50573
|
+
requireAutoLaunchedForTaskIds,
|
|
50574
|
+
reclaimOrphans,
|
|
50575
|
+
liveMeshNodeIds
|
|
50545
50576
|
});
|
|
50546
50577
|
return result;
|
|
50547
50578
|
} catch (e) {
|
|
@@ -56626,6 +56657,13 @@ var DaemonCommandRouter = class {
|
|
|
56626
56657
|
}
|
|
56627
56658
|
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
56628
56659
|
const requestedSessionIds = Array.isArray(args.sessionIds) ? new Set(args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean)) : void 0;
|
|
56660
|
+
const reclaimOrphans = args.reclaimOrphans === true;
|
|
56661
|
+
const liveMeshNodeIds = Array.isArray(args.liveMeshNodeIds) ? args.liveMeshNodeIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : [];
|
|
56662
|
+
const isNodeStillLive = (candidateNodeId) => {
|
|
56663
|
+
if (!candidateNodeId) return false;
|
|
56664
|
+
return liveMeshNodeIds.some((liveId) => liveId === candidateNodeId || meshNodeIdMatches({ id: liveId }, candidateNodeId) || daemonIdsEquivalent(liveId, candidateNodeId));
|
|
56665
|
+
};
|
|
56666
|
+
const reclaimedOrphanSessionIds = [];
|
|
56629
56667
|
const sessions = await this.deps.sessionHostControl.listSessions();
|
|
56630
56668
|
const matched = sessions.filter((record) => this.sessionMatchesMeshNode(record, args.node, args.nodeId, requestedSessionIds));
|
|
56631
56669
|
const hasExplicitSessionIds = !!requestedSessionIds?.size;
|
|
@@ -56694,7 +56732,8 @@ var DaemonCommandRouter = class {
|
|
|
56694
56732
|
const matchedByWorkspaceOnly = !recordNodeId;
|
|
56695
56733
|
const isWorktreeNodeRemoval = cleanupSource === "mesh_remove_node" && args.node?.isLocalWorktree === true;
|
|
56696
56734
|
const cleanWorkspaceOnlyForWorktree = isWorktreeNodeRemoval && matchedByWorkspaceOnly;
|
|
56697
|
-
|
|
56735
|
+
const reclaimableOrphan = reclaimOrphans && liveRuntime && !delegateBoundToThisNode && (matchedByWorkspaceOnly || !isNodeStillLive(recordNodeId));
|
|
56736
|
+
if (!hasExplicitSessionIds && liveRuntime && !delegateBoundToThisNode && !cleanWorkspaceOnlyForWorktree && !reclaimableOrphan) {
|
|
56698
56737
|
skippedSessionIds.push(sessionId);
|
|
56699
56738
|
skippedLiveSessionIds.push(sessionId);
|
|
56700
56739
|
const reason = recordNodeId && recordNodeId !== args.nodeId ? `live_delegate_bound_to_other_node:${recordNodeId}` : matchedByWorkspaceOnly ? "live_session_matched_by_workspace_only_no_node_binding" : "live_session_not_bound_to_this_node";
|
|
@@ -56704,6 +56743,10 @@ var DaemonCommandRouter = class {
|
|
|
56704
56743
|
if (cleanWorkspaceOnlyForWorktree && !delegateBoundToThisNode) {
|
|
56705
56744
|
actedLiveDelegateSessionIds.push(sessionId);
|
|
56706
56745
|
}
|
|
56746
|
+
if (reclaimableOrphan && !cleanWorkspaceOnlyForWorktree && !delegateBoundToThisNode) {
|
|
56747
|
+
reclaimedOrphanSessionIds.push(sessionId);
|
|
56748
|
+
actedLiveDelegateSessionIds.push(sessionId);
|
|
56749
|
+
}
|
|
56707
56750
|
if (!hasExplicitSessionIds && liveRuntime && delegateBoundToThisNode && args.mode === "delete_stopped") {
|
|
56708
56751
|
skippedSessionIds.push(sessionId);
|
|
56709
56752
|
skippedLiveSessionIds.push(sessionId);
|
|
@@ -56776,6 +56819,7 @@ var DaemonCommandRouter = class {
|
|
|
56776
56819
|
skippedCoordinatorSessionIds,
|
|
56777
56820
|
...skippedMarkerMismatchSessionIds.length ? { skippedMarkerMismatchSessionIds } : {},
|
|
56778
56821
|
...actedLiveDelegateSessionIds.length ? { actedLiveDelegateSessionIds } : {},
|
|
56822
|
+
...reclaimedOrphanSessionIds.length ? { reclaimedOrphanSessionIds } : {},
|
|
56779
56823
|
...skippedLiveSessionReasons.length ? { skippedLiveSessionReasons } : {},
|
|
56780
56824
|
...deleteUnsupported ? {
|
|
56781
56825
|
deleteUnsupported: true,
|