@adhdev/daemon-core 0.9.76-rc.37 → 0.9.76-rc.39
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 +7 -0
- package/dist/index.js +164 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +164 -5
- package/dist/index.mjs.map +1 -1
- package/dist/repo-mesh-types.d.ts +7 -0
- package/package.json +1 -1
- package/src/commands/router.d.ts +1 -0
- package/src/commands/router.ts +181 -2
- package/src/config/mesh-config.ts +17 -2
- package/src/repo-mesh-types.ts +9 -0
package/dist/index.mjs
CHANGED
|
@@ -36,7 +36,8 @@ var init_repo_mesh_types = __esm({
|
|
|
36
36
|
requireApprovalForPush: true,
|
|
37
37
|
requireApprovalForDestructiveGit: true,
|
|
38
38
|
dirtyWorkspaceBehavior: "warn",
|
|
39
|
-
maxParallelTasks: 2
|
|
39
|
+
maxParallelTasks: 2,
|
|
40
|
+
sessionCleanupOnNodeRemove: "preserve"
|
|
40
41
|
};
|
|
41
42
|
}
|
|
42
43
|
});
|
|
@@ -458,6 +459,18 @@ function normalizeRepoIdentity(remoteUrl) {
|
|
|
458
459
|
if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;
|
|
459
460
|
return identity;
|
|
460
461
|
}
|
|
462
|
+
function mergeMeshPolicy(base, patch) {
|
|
463
|
+
const policy = { ...DEFAULT_MESH_POLICY, ...base || {}, ...patch || {} };
|
|
464
|
+
if (!["block", "warn", "checkpoint_then_continue"].includes(policy.dirtyWorkspaceBehavior)) {
|
|
465
|
+
policy.dirtyWorkspaceBehavior = "warn";
|
|
466
|
+
}
|
|
467
|
+
const maxParallelTasks = Number(policy.maxParallelTasks);
|
|
468
|
+
policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
|
|
469
|
+
if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
|
|
470
|
+
policy.sessionCleanupOnNodeRemove = "preserve";
|
|
471
|
+
}
|
|
472
|
+
return policy;
|
|
473
|
+
}
|
|
461
474
|
function listMeshes() {
|
|
462
475
|
return loadMeshConfig().meshes;
|
|
463
476
|
}
|
|
@@ -481,7 +494,7 @@ function createMesh(opts) {
|
|
|
481
494
|
repoIdentity,
|
|
482
495
|
repoRemoteUrl: opts.repoRemoteUrl,
|
|
483
496
|
defaultBranch: opts.defaultBranch,
|
|
484
|
-
policy:
|
|
497
|
+
policy: mergeMeshPolicy(void 0, opts.policy),
|
|
485
498
|
coordinator: opts.coordinator || {},
|
|
486
499
|
nodes: [],
|
|
487
500
|
createdAt: now,
|
|
@@ -497,7 +510,7 @@ function updateMesh(meshId, opts) {
|
|
|
497
510
|
if (!mesh) return void 0;
|
|
498
511
|
if (opts.name !== void 0) mesh.name = opts.name.trim().slice(0, 100);
|
|
499
512
|
if (opts.defaultBranch !== void 0) mesh.defaultBranch = opts.defaultBranch;
|
|
500
|
-
if (opts.policy) mesh.policy =
|
|
513
|
+
if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
|
|
501
514
|
if (opts.coordinator) mesh.coordinator = opts.coordinator;
|
|
502
515
|
mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
503
516
|
saveMeshConfig(config);
|
|
@@ -560,11 +573,13 @@ function updateNode(meshId, nodeId, opts) {
|
|
|
560
573
|
saveMeshConfig(config);
|
|
561
574
|
return node;
|
|
562
575
|
}
|
|
576
|
+
var SESSION_CLEANUP_MODES;
|
|
563
577
|
var init_mesh_config = __esm({
|
|
564
578
|
"src/config/mesh-config.ts"() {
|
|
565
579
|
"use strict";
|
|
566
580
|
init_config();
|
|
567
581
|
init_repo_mesh_types();
|
|
582
|
+
SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set(["preserve", "stop", "delete_stopped", "stop_and_delete"]);
|
|
568
583
|
}
|
|
569
584
|
});
|
|
570
585
|
|
|
@@ -21299,6 +21314,75 @@ var DaemonCommandRouter = class {
|
|
|
21299
21314
|
this.inlineMeshCache.set(meshId, mesh);
|
|
21300
21315
|
return true;
|
|
21301
21316
|
}
|
|
21317
|
+
normalizeMeshSessionCleanupMode(value) {
|
|
21318
|
+
return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
|
|
21319
|
+
}
|
|
21320
|
+
sessionMatchesMeshNode(record, node, nodeId, sessionIds) {
|
|
21321
|
+
const sessionId = typeof record?.sessionId === "string" ? record.sessionId : "";
|
|
21322
|
+
if (!sessionId) return false;
|
|
21323
|
+
if (sessionIds?.size) return sessionIds.has(sessionId);
|
|
21324
|
+
const workspace = typeof node?.workspace === "string" ? node.workspace : "";
|
|
21325
|
+
if (workspace && record?.workspace === workspace) return true;
|
|
21326
|
+
if (record?.meta?.meshNodeId === nodeId) return true;
|
|
21327
|
+
return false;
|
|
21328
|
+
}
|
|
21329
|
+
isCompletedHostedSession(record) {
|
|
21330
|
+
return record?.lifecycle === "stopped" || record?.lifecycle === "failed" || record?.lifecycle === "interrupted";
|
|
21331
|
+
}
|
|
21332
|
+
async cleanupMeshSessions(args) {
|
|
21333
|
+
if (args.mode === "preserve") {
|
|
21334
|
+
return { success: true, mode: "preserve", matchedCount: 0, stoppedSessionIds: [], deletedSessionIds: [], skippedSessionIds: [] };
|
|
21335
|
+
}
|
|
21336
|
+
if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
|
|
21337
|
+
const requestedSessionIds = Array.isArray(args.sessionIds) ? new Set(args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean)) : void 0;
|
|
21338
|
+
const sessions = await this.deps.sessionHostControl.listSessions();
|
|
21339
|
+
const matched = sessions.filter((record) => this.sessionMatchesMeshNode(record, args.node, args.nodeId, requestedSessionIds));
|
|
21340
|
+
const stoppedSessionIds = [];
|
|
21341
|
+
const deletedSessionIds = [];
|
|
21342
|
+
const skippedSessionIds = [];
|
|
21343
|
+
const errors = [];
|
|
21344
|
+
for (const record of matched) {
|
|
21345
|
+
const sessionId = String(record.sessionId);
|
|
21346
|
+
const completed = this.isCompletedHostedSession(record);
|
|
21347
|
+
try {
|
|
21348
|
+
if (args.mode === "stop") {
|
|
21349
|
+
if (!completed) {
|
|
21350
|
+
if (!args.dryRun) await this.deps.sessionHostControl.stopSession(sessionId);
|
|
21351
|
+
stoppedSessionIds.push(sessionId);
|
|
21352
|
+
} else {
|
|
21353
|
+
skippedSessionIds.push(sessionId);
|
|
21354
|
+
}
|
|
21355
|
+
continue;
|
|
21356
|
+
}
|
|
21357
|
+
if (args.mode === "delete_stopped") {
|
|
21358
|
+
if (completed) {
|
|
21359
|
+
if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: false });
|
|
21360
|
+
deletedSessionIds.push(sessionId);
|
|
21361
|
+
} else {
|
|
21362
|
+
skippedSessionIds.push(sessionId);
|
|
21363
|
+
}
|
|
21364
|
+
continue;
|
|
21365
|
+
}
|
|
21366
|
+
if (args.mode === "stop_and_delete") {
|
|
21367
|
+
if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: true });
|
|
21368
|
+
deletedSessionIds.push(sessionId);
|
|
21369
|
+
continue;
|
|
21370
|
+
}
|
|
21371
|
+
} catch (e) {
|
|
21372
|
+
errors.push({ sessionId, error: e?.message || String(e) });
|
|
21373
|
+
}
|
|
21374
|
+
}
|
|
21375
|
+
return {
|
|
21376
|
+
success: errors.length === 0,
|
|
21377
|
+
mode: args.mode,
|
|
21378
|
+
dryRun: args.dryRun === true,
|
|
21379
|
+
matchedCount: matched.length,
|
|
21380
|
+
stoppedSessionIds,
|
|
21381
|
+
deletedSessionIds,
|
|
21382
|
+
skippedSessionIds,
|
|
21383
|
+
...errors.length ? { errors } : {}
|
|
21384
|
+
};
|
|
21385
|
+
}
|
|
21302
21386
|
async traceSessionHostAction(action, args, run, summarizeResult) {
|
|
21303
21387
|
const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
|
|
21304
21388
|
const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
|
|
@@ -21965,7 +22049,26 @@ var DaemonCommandRouter = class {
|
|
|
21965
22049
|
if (!name) return { success: false, error: "name required" };
|
|
21966
22050
|
try {
|
|
21967
22051
|
const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
21968
|
-
const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch });
|
|
22052
|
+
const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch, policy: args?.policy });
|
|
22053
|
+
return { success: true, mesh };
|
|
22054
|
+
} catch (e) {
|
|
22055
|
+
return { success: false, error: e.message };
|
|
22056
|
+
}
|
|
22057
|
+
}
|
|
22058
|
+
case "update_mesh": {
|
|
22059
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
22060
|
+
if (!meshId) return { success: false, error: "meshId required" };
|
|
22061
|
+
try {
|
|
22062
|
+
const { updateMesh: updateMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22063
|
+
const patch = {};
|
|
22064
|
+
if (typeof args?.name === "string") patch.name = args.name;
|
|
22065
|
+
if (typeof args?.defaultBranch === "string") patch.defaultBranch = args.defaultBranch;
|
|
22066
|
+
if (args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy)) patch.policy = args.policy;
|
|
22067
|
+
if (args?.coordinator && typeof args.coordinator === "object" && !Array.isArray(args.coordinator)) patch.coordinator = args.coordinator;
|
|
22068
|
+
if (!Object.keys(patch).length) return { success: false, error: "No updates provided" };
|
|
22069
|
+
const mesh = updateMesh2(meshId, patch);
|
|
22070
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
22071
|
+
this.inlineMeshCache.set(meshId, mesh);
|
|
21969
22072
|
return { success: true, mesh };
|
|
21970
22073
|
} catch (e) {
|
|
21971
22074
|
return { success: false, error: e.message };
|
|
@@ -22002,6 +22105,54 @@ var DaemonCommandRouter = class {
|
|
|
22002
22105
|
return { success: false, error: e.message };
|
|
22003
22106
|
}
|
|
22004
22107
|
}
|
|
22108
|
+
case "update_mesh_node": {
|
|
22109
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
22110
|
+
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
22111
|
+
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
22112
|
+
try {
|
|
22113
|
+
const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22114
|
+
const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
|
|
22115
|
+
if (Array.isArray(args?.providerPriority)) {
|
|
22116
|
+
const providerPriority = args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean);
|
|
22117
|
+
delete policy.provider_priority;
|
|
22118
|
+
if (providerPriority.length) {
|
|
22119
|
+
policy.providerPriority = providerPriority;
|
|
22120
|
+
} else {
|
|
22121
|
+
delete policy.providerPriority;
|
|
22122
|
+
}
|
|
22123
|
+
}
|
|
22124
|
+
const node = updateNode2(meshId, nodeId, { policy });
|
|
22125
|
+
if (!node) return { success: false, error: "Mesh node not found" };
|
|
22126
|
+
return { success: true, node };
|
|
22127
|
+
} catch (e) {
|
|
22128
|
+
return { success: false, error: e.message };
|
|
22129
|
+
}
|
|
22130
|
+
}
|
|
22131
|
+
case "cleanup_mesh_sessions": {
|
|
22132
|
+
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
22133
|
+
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
22134
|
+
if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
|
|
22135
|
+
try {
|
|
22136
|
+
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
22137
|
+
const mesh = meshRecord?.mesh;
|
|
22138
|
+
if (!mesh) return { success: false, error: "Mesh not found" };
|
|
22139
|
+
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
22140
|
+
if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
|
|
22141
|
+
const mode = this.normalizeMeshSessionCleanupMode(args?.mode ?? mesh?.policy?.sessionCleanupOnNodeRemove);
|
|
22142
|
+
const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
|
|
22143
|
+
const result = await this.cleanupMeshSessions({
|
|
22144
|
+
meshId,
|
|
22145
|
+
nodeId,
|
|
22146
|
+
node,
|
|
22147
|
+
mode,
|
|
22148
|
+
sessionIds,
|
|
22149
|
+
dryRun: args?.dryRun === true
|
|
22150
|
+
});
|
|
22151
|
+
return result;
|
|
22152
|
+
} catch (e) {
|
|
22153
|
+
return { success: false, error: e.message };
|
|
22154
|
+
}
|
|
22155
|
+
}
|
|
22005
22156
|
case "remove_mesh_node": {
|
|
22006
22157
|
const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
|
|
22007
22158
|
const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
|
|
@@ -22010,6 +22161,14 @@ var DaemonCommandRouter = class {
|
|
|
22010
22161
|
const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
|
|
22011
22162
|
const mesh = meshRecord?.mesh;
|
|
22012
22163
|
const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
|
|
22164
|
+
const sessionCleanupMode = this.normalizeMeshSessionCleanupMode(
|
|
22165
|
+
args?.sessionCleanupMode ?? args?.session_cleanup_mode ?? mesh?.policy?.sessionCleanupOnNodeRemove
|
|
22166
|
+
);
|
|
22167
|
+
let sessionCleanup;
|
|
22168
|
+
if (node && sessionCleanupMode !== "preserve") {
|
|
22169
|
+
sessionCleanup = await this.cleanupMeshSessions({ meshId, nodeId, node, mode: sessionCleanupMode });
|
|
22170
|
+
if (sessionCleanup.success === false) return { success: false, removed: false, sessionCleanup };
|
|
22171
|
+
}
|
|
22013
22172
|
if (node?.isLocalWorktree && node.workspace) {
|
|
22014
22173
|
try {
|
|
22015
22174
|
const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
|
|
@@ -22029,7 +22188,7 @@ var DaemonCommandRouter = class {
|
|
|
22029
22188
|
const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
|
|
22030
22189
|
removed = removeNode3(meshId, nodeId);
|
|
22031
22190
|
}
|
|
22032
|
-
return { success: true, removed };
|
|
22191
|
+
return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
|
|
22033
22192
|
} catch (e) {
|
|
22034
22193
|
return { success: false, error: e.message };
|
|
22035
22194
|
}
|