@adhdev/daemon-standalone 0.9.76-rc.37 → 0.9.76-rc.38

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 CHANGED
@@ -31231,7 +31231,8 @@ var require_dist2 = __commonJS({
31231
31231
  requireApprovalForPush: true,
31232
31232
  requireApprovalForDestructiveGit: true,
31233
31233
  dirtyWorkspaceBehavior: "warn",
31234
- maxParallelTasks: 2
31234
+ maxParallelTasks: 2,
31235
+ sessionCleanupOnNodeRemove: "preserve"
31235
31236
  };
31236
31237
  }
31237
31238
  });
@@ -31657,6 +31658,18 @@ var require_dist2 = __commonJS({
31657
31658
  if (sshMatch) return `${sshMatch[1]}/${sshMatch[2]}`;
31658
31659
  return identity;
31659
31660
  }
31661
+ function mergeMeshPolicy(base, patch) {
31662
+ const policy = { ...DEFAULT_MESH_POLICY, ...base || {}, ...patch || {} };
31663
+ if (!["block", "warn", "checkpoint_then_continue"].includes(policy.dirtyWorkspaceBehavior)) {
31664
+ policy.dirtyWorkspaceBehavior = "warn";
31665
+ }
31666
+ const maxParallelTasks = Number(policy.maxParallelTasks);
31667
+ policy.maxParallelTasks = Number.isFinite(maxParallelTasks) ? Math.max(1, Math.min(8, Math.floor(maxParallelTasks))) : 2;
31668
+ if (!SESSION_CLEANUP_MODES.has(String(policy.sessionCleanupOnNodeRemove))) {
31669
+ policy.sessionCleanupOnNodeRemove = "preserve";
31670
+ }
31671
+ return policy;
31672
+ }
31660
31673
  function listMeshes() {
31661
31674
  return loadMeshConfig().meshes;
31662
31675
  }
@@ -31680,7 +31693,7 @@ var require_dist2 = __commonJS({
31680
31693
  repoIdentity,
31681
31694
  repoRemoteUrl: opts.repoRemoteUrl,
31682
31695
  defaultBranch: opts.defaultBranch,
31683
- policy: { ...DEFAULT_MESH_POLICY, ...opts.policy },
31696
+ policy: mergeMeshPolicy(void 0, opts.policy),
31684
31697
  coordinator: opts.coordinator || {},
31685
31698
  nodes: [],
31686
31699
  createdAt: now,
@@ -31696,7 +31709,7 @@ var require_dist2 = __commonJS({
31696
31709
  if (!mesh) return void 0;
31697
31710
  if (opts.name !== void 0) mesh.name = opts.name.trim().slice(0, 100);
31698
31711
  if (opts.defaultBranch !== void 0) mesh.defaultBranch = opts.defaultBranch;
31699
- if (opts.policy) mesh.policy = { ...mesh.policy, ...opts.policy };
31712
+ if (opts.policy) mesh.policy = mergeMeshPolicy(mesh.policy, opts.policy);
31700
31713
  if (opts.coordinator) mesh.coordinator = opts.coordinator;
31701
31714
  mesh.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
31702
31715
  saveMeshConfig(config2);
@@ -31762,6 +31775,7 @@ var require_dist2 = __commonJS({
31762
31775
  var import_fs2;
31763
31776
  var import_path22;
31764
31777
  var import_crypto32;
31778
+ var SESSION_CLEANUP_MODES;
31765
31779
  var init_mesh_config = __esm2({
31766
31780
  "src/config/mesh-config.ts"() {
31767
31781
  "use strict";
@@ -31770,6 +31784,7 @@ var require_dist2 = __commonJS({
31770
31784
  import_crypto32 = require("crypto");
31771
31785
  init_config();
31772
31786
  init_repo_mesh_types();
31787
+ SESSION_CLEANUP_MODES = /* @__PURE__ */ new Set(["preserve", "stop", "delete_stopped", "stop_and_delete"]);
31773
31788
  }
31774
31789
  });
31775
31790
  var coordinator_prompt_exports = {};
@@ -52532,6 +52547,75 @@ Run 'adhdev doctor' for detailed diagnostics.`
52532
52547
  this.inlineMeshCache.set(meshId, mesh);
52533
52548
  return true;
52534
52549
  }
52550
+ normalizeMeshSessionCleanupMode(value) {
52551
+ return value === "stop" || value === "delete_stopped" || value === "stop_and_delete" || value === "preserve" ? value : "preserve";
52552
+ }
52553
+ sessionMatchesMeshNode(record2, node, nodeId, sessionIds) {
52554
+ const sessionId = typeof record2?.sessionId === "string" ? record2.sessionId : "";
52555
+ if (!sessionId) return false;
52556
+ if (sessionIds?.size) return sessionIds.has(sessionId);
52557
+ const workspace = typeof node?.workspace === "string" ? node.workspace : "";
52558
+ if (workspace && record2?.workspace === workspace) return true;
52559
+ if (record2?.meta?.meshNodeId === nodeId) return true;
52560
+ return false;
52561
+ }
52562
+ isCompletedHostedSession(record2) {
52563
+ return record2?.lifecycle === "stopped" || record2?.lifecycle === "failed" || record2?.lifecycle === "interrupted";
52564
+ }
52565
+ async cleanupMeshSessions(args) {
52566
+ if (args.mode === "preserve") {
52567
+ return { success: true, mode: "preserve", matchedCount: 0, stoppedSessionIds: [], deletedSessionIds: [], skippedSessionIds: [] };
52568
+ }
52569
+ if (!this.deps.sessionHostControl) return { success: false, error: "Session host control unavailable" };
52570
+ const requestedSessionIds = Array.isArray(args.sessionIds) ? new Set(args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean)) : void 0;
52571
+ const sessions = await this.deps.sessionHostControl.listSessions();
52572
+ const matched = sessions.filter((record2) => this.sessionMatchesMeshNode(record2, args.node, args.nodeId, requestedSessionIds));
52573
+ const stoppedSessionIds = [];
52574
+ const deletedSessionIds = [];
52575
+ const skippedSessionIds = [];
52576
+ const errors = [];
52577
+ for (const record2 of matched) {
52578
+ const sessionId = String(record2.sessionId);
52579
+ const completed = this.isCompletedHostedSession(record2);
52580
+ try {
52581
+ if (args.mode === "stop") {
52582
+ if (!completed) {
52583
+ if (!args.dryRun) await this.deps.sessionHostControl.stopSession(sessionId);
52584
+ stoppedSessionIds.push(sessionId);
52585
+ } else {
52586
+ skippedSessionIds.push(sessionId);
52587
+ }
52588
+ continue;
52589
+ }
52590
+ if (args.mode === "delete_stopped") {
52591
+ if (completed) {
52592
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: false });
52593
+ deletedSessionIds.push(sessionId);
52594
+ } else {
52595
+ skippedSessionIds.push(sessionId);
52596
+ }
52597
+ continue;
52598
+ }
52599
+ if (args.mode === "stop_and_delete") {
52600
+ if (!args.dryRun) await this.deps.sessionHostControl.deleteSession(sessionId, { force: true });
52601
+ deletedSessionIds.push(sessionId);
52602
+ continue;
52603
+ }
52604
+ } catch (e) {
52605
+ errors.push({ sessionId, error: e?.message || String(e) });
52606
+ }
52607
+ }
52608
+ return {
52609
+ success: errors.length === 0,
52610
+ mode: args.mode,
52611
+ dryRun: args.dryRun === true,
52612
+ matchedCount: matched.length,
52613
+ stoppedSessionIds,
52614
+ deletedSessionIds,
52615
+ skippedSessionIds,
52616
+ ...errors.length ? { errors } : {}
52617
+ };
52618
+ }
52535
52619
  async traceSessionHostAction(action, args, run, summarizeResult) {
52536
52620
  const interactionId = typeof args?._interactionId === "string" ? args._interactionId : void 0;
52537
52621
  const sessionId = typeof args?.sessionId === "string" ? args.sessionId : void 0;
@@ -53198,7 +53282,26 @@ Run 'adhdev doctor' for detailed diagnostics.`
53198
53282
  if (!name) return { success: false, error: "name required" };
53199
53283
  try {
53200
53284
  const { createMesh: createMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
53201
- const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch });
53285
+ const mesh = createMesh2({ name, repoIdentity, repoRemoteUrl, defaultBranch, policy: args?.policy });
53286
+ return { success: true, mesh };
53287
+ } catch (e) {
53288
+ return { success: false, error: e.message };
53289
+ }
53290
+ }
53291
+ case "update_mesh": {
53292
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53293
+ if (!meshId) return { success: false, error: "meshId required" };
53294
+ try {
53295
+ const { updateMesh: updateMesh2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
53296
+ const patch = {};
53297
+ if (typeof args?.name === "string") patch.name = args.name;
53298
+ if (typeof args?.defaultBranch === "string") patch.defaultBranch = args.defaultBranch;
53299
+ if (args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy)) patch.policy = args.policy;
53300
+ if (args?.coordinator && typeof args.coordinator === "object" && !Array.isArray(args.coordinator)) patch.coordinator = args.coordinator;
53301
+ if (!Object.keys(patch).length) return { success: false, error: "No updates provided" };
53302
+ const mesh = updateMesh2(meshId, patch);
53303
+ if (!mesh) return { success: false, error: "Mesh not found" };
53304
+ this.inlineMeshCache.set(meshId, mesh);
53202
53305
  return { success: true, mesh };
53203
53306
  } catch (e) {
53204
53307
  return { success: false, error: e.message };
@@ -53235,6 +53338,54 @@ Run 'adhdev doctor' for detailed diagnostics.`
53235
53338
  return { success: false, error: e.message };
53236
53339
  }
53237
53340
  }
53341
+ case "update_mesh_node": {
53342
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53343
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
53344
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
53345
+ try {
53346
+ const { updateNode: updateNode2 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
53347
+ const policy = args?.policy && typeof args.policy === "object" && !Array.isArray(args.policy) ? { ...args.policy } : {};
53348
+ if (Array.isArray(args?.providerPriority)) {
53349
+ const providerPriority = args.providerPriority.map((type) => typeof type === "string" ? type.trim() : "").filter(Boolean);
53350
+ delete policy.provider_priority;
53351
+ if (providerPriority.length) {
53352
+ policy.providerPriority = providerPriority;
53353
+ } else {
53354
+ delete policy.providerPriority;
53355
+ }
53356
+ }
53357
+ const node = updateNode2(meshId, nodeId, { policy });
53358
+ if (!node) return { success: false, error: "Mesh node not found" };
53359
+ return { success: true, node };
53360
+ } catch (e) {
53361
+ return { success: false, error: e.message };
53362
+ }
53363
+ }
53364
+ case "cleanup_mesh_sessions": {
53365
+ const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53366
+ const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
53367
+ if (!meshId || !nodeId) return { success: false, error: "meshId and nodeId required" };
53368
+ try {
53369
+ const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
53370
+ const mesh = meshRecord?.mesh;
53371
+ if (!mesh) return { success: false, error: "Mesh not found" };
53372
+ const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
53373
+ if (!node) return { success: false, error: `Node '${nodeId}' not found in mesh` };
53374
+ const mode = this.normalizeMeshSessionCleanupMode(args?.mode ?? mesh?.policy?.sessionCleanupOnNodeRemove);
53375
+ const sessionIds = Array.isArray(args?.sessionIds) ? args.sessionIds.map((id) => typeof id === "string" ? id.trim() : "").filter(Boolean) : void 0;
53376
+ const result = await this.cleanupMeshSessions({
53377
+ meshId,
53378
+ nodeId,
53379
+ node,
53380
+ mode,
53381
+ sessionIds,
53382
+ dryRun: args?.dryRun === true
53383
+ });
53384
+ return result;
53385
+ } catch (e) {
53386
+ return { success: false, error: e.message };
53387
+ }
53388
+ }
53238
53389
  case "remove_mesh_node": {
53239
53390
  const meshId = typeof args?.meshId === "string" ? args.meshId.trim() : "";
53240
53391
  const nodeId = typeof args?.nodeId === "string" ? args.nodeId.trim() : "";
@@ -53243,6 +53394,14 @@ Run 'adhdev doctor' for detailed diagnostics.`
53243
53394
  const meshRecord = await this.getMeshForCommand(meshId, args?.inlineMesh);
53244
53395
  const mesh = meshRecord?.mesh;
53245
53396
  const node = mesh?.nodes?.find((n) => n.id === nodeId || n.nodeId === nodeId);
53397
+ const sessionCleanupMode = this.normalizeMeshSessionCleanupMode(
53398
+ args?.sessionCleanupMode ?? args?.session_cleanup_mode ?? mesh?.policy?.sessionCleanupOnNodeRemove
53399
+ );
53400
+ let sessionCleanup;
53401
+ if (node && sessionCleanupMode !== "preserve") {
53402
+ sessionCleanup = await this.cleanupMeshSessions({ meshId, nodeId, node, mode: sessionCleanupMode });
53403
+ if (sessionCleanup.success === false) return { success: false, removed: false, sessionCleanup };
53404
+ }
53246
53405
  if (node?.isLocalWorktree && node.workspace) {
53247
53406
  try {
53248
53407
  const sourceNode = node.clonedFromNodeId ? mesh?.nodes.find((n) => n.id === node.clonedFromNodeId || n.nodeId === node.clonedFromNodeId) : mesh?.nodes.find((n) => !n.isLocalWorktree);
@@ -53262,7 +53421,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
53262
53421
  const { removeNode: removeNode3 } = await Promise.resolve().then(() => (init_mesh_config(), mesh_config_exports));
53263
53422
  removed = removeNode3(meshId, nodeId);
53264
53423
  }
53265
- return { success: true, removed };
53424
+ return { success: true, removed, ...sessionCleanup ? { sessionCleanup } : {} };
53266
53425
  } catch (e) {
53267
53426
  return { success: false, error: e.message };
53268
53427
  }
@@ -61856,6 +62015,9 @@ var StandaloneSessionHostControlPlane = class {
61856
62015
  async stopSession(sessionId) {
61857
62016
  return this.request("stop_session", { sessionId });
61858
62017
  }
62018
+ async deleteSession(sessionId, opts = {}) {
62019
+ return this.request("delete_session", { sessionId, force: opts.force === true });
62020
+ }
61859
62021
  async resumeSession(sessionId) {
61860
62022
  return this.request("resume_session", { sessionId });
61861
62023
  }