adhdev 0.9.56 → 0.9.58

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
@@ -34934,7 +34934,7 @@ Run 'adhdev doctor' for detailed diagnostics.`
34934
34934
  resolvedDir,
34935
34935
  resolvedCliArgs,
34936
34936
  resolvedProvider,
34937
- {},
34937
+ this.providerLoader.getSettings(normalizedType),
34938
34938
  false,
34939
34939
  {
34940
34940
  providerSessionId: sessionBinding.providerSessionId,
@@ -49343,6 +49343,58 @@ var init_server_connection = __esm({
49343
49343
  onStateChange(callback) {
49344
49344
  this.stateChangeCallbacks.push(callback);
49345
49345
  }
49346
+ /**
49347
+ * Send a command to another daemon owned by the same user, via server relay.
49348
+ * The server validates ownership before forwarding to the target daemon.
49349
+ *
49350
+ * Returns the command result or throws on timeout / auth failure.
49351
+ */
49352
+ sendMeshCommand(targetDaemonId, command, args = {}, timeoutMs = 3e4) {
49353
+ return new Promise((resolve19, reject) => {
49354
+ const requestId = `mesh_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
49355
+ const timer = setTimeout(() => {
49356
+ this.off("daemon_mesh_result", handler);
49357
+ reject(new Error(`Mesh command timed out after ${timeoutMs}ms`));
49358
+ }, timeoutMs);
49359
+ const handler = (msg) => {
49360
+ if (msg.payload?.requestId !== requestId) return;
49361
+ this.off("daemon_mesh_result", handler);
49362
+ clearTimeout(timer);
49363
+ if (msg.payload?.success === false) {
49364
+ reject(new Error(msg.payload?.error ?? "Mesh command failed"));
49365
+ } else {
49366
+ resolve19(msg.payload?.result);
49367
+ }
49368
+ };
49369
+ this.on("daemon_mesh_result", handler);
49370
+ const sent = this.ws?.readyState === 1 && (() => {
49371
+ try {
49372
+ this.ws.send(JSON.stringify({
49373
+ type: "daemon_mesh_command",
49374
+ requestId,
49375
+ targetDaemonId,
49376
+ command,
49377
+ args,
49378
+ timestamp: Date.now()
49379
+ }));
49380
+ return true;
49381
+ } catch {
49382
+ return false;
49383
+ }
49384
+ })();
49385
+ if (!sent) {
49386
+ clearTimeout(timer);
49387
+ this.off("daemon_mesh_result", handler);
49388
+ reject(new Error("Not connected to server"));
49389
+ }
49390
+ });
49391
+ }
49392
+ off(type, handler) {
49393
+ const handlers = this.messageHandlers.get(type);
49394
+ if (!handlers) return;
49395
+ const idx = handlers.indexOf(handler);
49396
+ if (idx !== -1) handlers.splice(idx, 1);
49397
+ }
49346
49398
  getState() {
49347
49399
  return this.state;
49348
49400
  }
@@ -58793,6 +58845,64 @@ var init_version = __esm({
58793
58845
  }
58794
58846
  });
58795
58847
 
58848
+ // src/daemon-mesh-manager.ts
58849
+ var daemon_mesh_manager_exports = {};
58850
+ __export(daemon_mesh_manager_exports, {
58851
+ DaemonMeshManager: () => DaemonMeshManager
58852
+ });
58853
+ function interpolateArgs(args, context) {
58854
+ const result = {};
58855
+ for (const [k, v] of Object.entries(args)) {
58856
+ result[k] = typeof v === "string" ? interpolateString(v, context) : v;
58857
+ }
58858
+ return result;
58859
+ }
58860
+ function interpolateString(template, ctx) {
58861
+ return template.replace(/\{\{(\w+)\}\}/g, (_2, key) => {
58862
+ const val = ctx[key];
58863
+ return val !== void 0 ? String(val) : `{{${key}}}`;
58864
+ });
58865
+ }
58866
+ var DaemonMeshManager;
58867
+ var init_daemon_mesh_manager = __esm({
58868
+ "src/daemon-mesh-manager.ts"() {
58869
+ "use strict";
58870
+ init_src();
58871
+ DaemonMeshManager = class {
58872
+ rules = [];
58873
+ serverConn;
58874
+ constructor(serverConn) {
58875
+ this.serverConn = serverConn;
58876
+ }
58877
+ setRules(rules) {
58878
+ this.rules = rules;
58879
+ LOG.info("Mesh", `[Mesh] ${rules.length} rule(s) loaded`);
58880
+ }
58881
+ async emit(event) {
58882
+ const matching = this.rules.filter((r) => r.trigger === event.trigger);
58883
+ if (matching.length === 0) return;
58884
+ await Promise.allSettled(
58885
+ matching.map((rule) => this.executeRule(rule, event.context ?? {}))
58886
+ );
58887
+ }
58888
+ async executeRule(rule, context) {
58889
+ const args = interpolateArgs(rule.args ?? {}, context);
58890
+ try {
58891
+ LOG.info("Mesh", `[Mesh] Relaying '${rule.command}' \u2192 ${rule.targetDaemonId.slice(0, 12)}\u2026`);
58892
+ await this.serverConn.sendMeshCommand(rule.targetDaemonId, rule.command, args);
58893
+ LOG.info("Mesh", `[Mesh] Relay '${rule.command}' complete`);
58894
+ } catch (err) {
58895
+ LOG.warn("Mesh", `[Mesh] Relay '${rule.command}' failed: ${err?.message ?? err}`);
58896
+ }
58897
+ }
58898
+ /** Convenience: send a one-off mesh command without a rule. */
58899
+ async sendCommand(targetDaemonId, command, args = {}) {
58900
+ return this.serverConn.sendMeshCommand(targetDaemonId, command, args);
58901
+ }
58902
+ };
58903
+ }
58904
+ });
58905
+
58796
58906
  // src/adhdev-daemon.ts
58797
58907
  var adhdev_daemon_exports = {};
58798
58908
  __export(adhdev_daemon_exports, {
@@ -59037,13 +59147,14 @@ var init_adhdev_daemon = __esm({
59037
59147
  init_version();
59038
59148
  init_src();
59039
59149
  init_runtime_defaults();
59040
- pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.56" });
59150
+ pkgVersion = resolvePackageVersion({ injectedVersion: "0.9.58" });
59041
59151
  AdhdevDaemon = class _AdhdevDaemon {
59042
59152
  localHttpServer = null;
59043
59153
  localWss = null;
59044
59154
  localClients = /* @__PURE__ */ new Set();
59045
59155
  serverConn = null;
59046
59156
  p2p = null;
59157
+ meshManager = null;
59047
59158
  screenshotController = null;
59048
59159
  statusReporter = null;
59049
59160
  topicSubscriptionTimer = null;
@@ -59627,6 +59738,12 @@ ${err?.stack || ""}`);
59627
59738
  }
59628
59739
  });
59629
59740
  this.p2p = new DaemonP2PSender(this.serverConn);
59741
+ const { DaemonMeshManager: DaemonMeshManager2 } = await Promise.resolve().then(() => (init_daemon_mesh_manager(), daemon_mesh_manager_exports));
59742
+ this.meshManager = new DaemonMeshManager2(this.serverConn);
59743
+ const meshRules = config2.meshRules;
59744
+ if (Array.isArray(meshRules) && meshRules.length > 0) {
59745
+ this.meshManager.setRules(meshRules);
59746
+ }
59630
59747
  if (this.p2p.isAvailable) {
59631
59748
  console.log(source_default2.green(" \u{1F517} P2P available (node-datachannel)"));
59632
59749
  this.p2p.onInput(async (event) => {
@@ -59965,6 +60082,16 @@ ${err?.stack || ""}`);
59965
60082
  if (cmdType.startsWith("git_")) {
59966
60083
  void this.flushP2PWorkspaceGitSubscriptions();
59967
60084
  }
60085
+ if (cmdType === "git_checkpoint" && routed.success && this.meshManager) {
60086
+ void this.meshManager.emit({
60087
+ trigger: "git_checkpoint_complete",
60088
+ context: {
60089
+ workspace: String(normalizedData.workspace ?? ""),
60090
+ checkpoint_message: routed.checkpoint?.message ?? String(normalizedData.message ?? ""),
60091
+ commit: routed.checkpoint?.commit ?? ""
60092
+ }
60093
+ });
60094
+ }
59968
60095
  return { ...routed, interactionId };
59969
60096
  } catch (e) {
59970
60097
  logCommand({ ts: (/* @__PURE__ */ new Date()).toISOString(), cmd: cmdType, source: "p2p", interactionId, success: false, error: e.message, durationMs: Date.now() - cmdStart });