@themoltnet/agent-daemon 0.21.0 → 0.22.1

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.
Files changed (2) hide show
  1. package/dist/main.js +44 -22
  2. package/package.json +5 -5
package/dist/main.js CHANGED
@@ -9123,7 +9123,7 @@ _Object_({
9123
9123
  //#region src/lib/help.ts
9124
9124
  var COMMON_REQUIRED_FLAGS = `\
9125
9125
  -a, --agent <name> MoltNet agent identity. Reads credentials
9126
- from <repo-root>/.moltnet/<name>/moltnet.json.
9126
+ from <agent-root>/.moltnet/<name>/moltnet.json.
9127
9127
  --profile <uuid|name> Remote runtime profile. Repeat for poll/drain
9128
9128
  to declare priority order. Provider, model,
9129
9129
  sandbox policy, prerequisites, and runtime
@@ -9131,6 +9131,8 @@ var COMMON_REQUIRED_FLAGS = `\
9131
9131
  var COMMON_OPTIONAL_FLAGS = `\
9132
9132
  --sandbox <path> Deprecated. Remote runtime profiles define
9133
9133
  sandbox policy.
9134
+ --agent-root <path> Directory that owns .moltnet/<agent>. Default:
9135
+ CWD, with git root fallback when available.
9134
9136
  --lease-ttl-sec <n> Sliding liveness window. Silence longer than
9135
9137
  this ends the attempt with lease_expired.
9136
9138
  Default: 300.
@@ -9170,7 +9172,7 @@ Commands:
9170
9172
  Run \`agent-daemon <command> --help\` for command-specific flags.
9171
9173
 
9172
9174
  Prerequisites (all subcommands):
9173
- - <repo-root>/.moltnet/<agent>/moltnet.json — credentials (see --agent)
9175
+ - <agent-root>/.moltnet/<agent>/moltnet.json — credentials (see --agent-root)
9174
9176
  - --profile — remote runtime profile supplies provider/model/sandbox
9175
9177
  policy and CWD is used as the VM mountPath.
9176
9178
 
@@ -9278,18 +9280,34 @@ function activatePiCodingAgentDir(path) {
9278
9280
  /**
9279
9281
  * Resolve the agent's MoltNet credentials directory and connect via SDK.
9280
9282
  *
9281
- * Looks under `<repo-root>/.moltnet/<agentName>/`. Fails fast if the dir
9282
- * is missing — credentials are required, the daemon never falls back to
9283
- * unauthenticated calls.
9283
+ * Looks under an explicit agent root first, then falls back to the git root
9284
+ * when available. Fails fast if the dir is missing — credentials are required,
9285
+ * the daemon never falls back to unauthenticated calls.
9284
9286
  */
9285
- async function resolveAgentContext(agentName) {
9287
+ async function resolveAgentContext(agentName, options = {}) {
9286
9288
  if (!/^[a-zA-Z0-9_-]+$/.test(agentName)) throw new Error(`Invalid agent name "${agentName}": must match /^[a-zA-Z0-9_-]+$/`);
9287
- const agentDir = join(execFileSync("git", ["rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim(), ".moltnet", agentName);
9288
- if (!existsSync(join(agentDir, "moltnet.json"))) throw new Error(`Missing credentials at ${agentDir}/moltnet.json. Run the agent onboarding flow first.`);
9289
- return {
9290
- agentDir,
9291
- agent: await connect({ configDir: agentDir })
9292
- };
9289
+ const roots = resolveCredentialRoots(options.agentRootDir);
9290
+ for (const rootDir of roots) {
9291
+ const agentDir = join(rootDir, ".moltnet", agentName);
9292
+ if (existsSync(join(agentDir, "moltnet.json"))) return {
9293
+ agentDir,
9294
+ agentRootDir: rootDir,
9295
+ agent: await connect({ configDir: agentDir })
9296
+ };
9297
+ }
9298
+ const tried = roots.map((root) => join(root, ".moltnet", agentName));
9299
+ throw new Error(`Missing credentials for ${agentName}. Checked ${tried.join(", ")}. Run the agent onboarding flow first.`);
9300
+ }
9301
+ function resolveCredentialRoots(agentRootDir) {
9302
+ const roots = agentRootDir ? [agentRootDir] : [];
9303
+ try {
9304
+ const gitRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
9305
+ encoding: "utf8",
9306
+ stdio: "pipe"
9307
+ }).trim();
9308
+ if (!roots.includes(gitRoot)) roots.push(gitRoot);
9309
+ } catch {}
9310
+ return roots;
9293
9311
  }
9294
9312
  //#endregion
9295
9313
  //#region src/lib/correlation.ts
@@ -9814,6 +9832,7 @@ function commonOptionDefs() {
9814
9832
  type: "string",
9815
9833
  short: "a"
9816
9834
  },
9835
+ "agent-root": { type: "string" },
9817
9836
  "lease-ttl-sec": { type: "string" },
9818
9837
  "heartbeat-interval-ms": { type: "string" },
9819
9838
  "max-batch-size": { type: "string" },
@@ -10165,7 +10184,8 @@ async function runPolling(opts) {
10165
10184
  }
10166
10185
  if (taskTypes.length === 0) console.error(`[${opts.modeLabel}] --task-types is empty — daemon will accept any registered type. Pass an explicit list to limit scope (e.g. --task-types fulfill_brief).`);
10167
10186
  const cfg = loadConfig();
10168
- const ctx = await resolveAgentContext(baseCommon.agent);
10187
+ const agentRootDir = resolve(process.cwd(), values["agent-root"] ?? process.cwd());
10188
+ const ctx = await resolveAgentContext(baseCommon.agent, { agentRootDir });
10169
10189
  const profiles = await resolveRuntimeProfiles({
10170
10190
  agent: ctx.agent,
10171
10191
  profiles: profileValues,
@@ -10174,7 +10194,6 @@ async function runPolling(opts) {
10174
10194
  });
10175
10195
  for (const profile of profiles) validateRuntimeProfilePrerequisites(profile, cfg.profilePrerequisiteEnv, cfg.profilePrerequisitePath);
10176
10196
  const slotRegistry = createApiRuntimeSlotStore({ agent: ctx.agent });
10177
- const mainRepo = findMainWorktree();
10178
10197
  const runtimes = /* @__PURE__ */ new Map();
10179
10198
  for (const profile of profiles) {
10180
10199
  const common = parseCommonOptions(values, { runtimeDefaults: {
@@ -10426,7 +10445,7 @@ async function runPolling(opts) {
10426
10445
  sessionDir: executionPlan.sessionPersistence.sessionDir,
10427
10446
  sessionPath: resolveLatestPiSessionPath(executionPlan.sessionPersistence.sessionDir),
10428
10447
  workspaceId: executionPlan.workspaceId,
10429
- worktreePath: resolveRecordedWorkspacePath$1(mainRepo, stateDirs.rootDir, executionPlan),
10448
+ worktreePath: resolveRecordedWorkspacePath$1(stateDirs.rootDir, executionPlan),
10430
10449
  worktreeBranch: executionPlan.worktreeBranch,
10431
10450
  workspaceKind: executionPlan.workspaceKind,
10432
10451
  lastTaskId: claimedTask.task.id,
@@ -10434,6 +10453,7 @@ async function runPolling(opts) {
10434
10453
  });
10435
10454
  const rawExecuteTask = createPiTaskExecutor({
10436
10455
  agentName: common.agent,
10456
+ agentRootDir: ctx.agentRootDir,
10437
10457
  mountPath: sandbox.rootDir,
10438
10458
  provider: profile.provider,
10439
10459
  model: profile.model,
@@ -10472,9 +10492,9 @@ async function runPolling(opts) {
10472
10492
  await shutdownLogger();
10473
10493
  }
10474
10494
  }
10475
- function resolveRecordedWorkspacePath$1(mainRepo, stateRootDir, executionPlan) {
10495
+ function resolveRecordedWorkspacePath$1(stateRootDir, executionPlan) {
10476
10496
  if (!executionPlan.workspaceId) return null;
10477
- return executionPlan.workspaceMode === "scratch_mount" ? join(stateRootDir, "task-workspaces", executionPlan.workspaceId) : join(mainRepo, ".worktrees", executionPlan.workspaceId);
10497
+ return executionPlan.workspaceMode === "scratch_mount" ? join(stateRootDir, "task-workspaces", executionPlan.workspaceId) : join(findMainWorktree(), ".worktrees", executionPlan.workspaceId);
10478
10498
  }
10479
10499
  function runtimeForClaimedTask(runtimes, claimedTask) {
10480
10500
  if (!claimedTask.profileId) throw new Error(`Claimed task ${claimedTask.task.id} did not include a selected runtime profile`);
@@ -10555,7 +10575,9 @@ async function runOnce(argv) {
10555
10575
  return 1;
10556
10576
  }
10557
10577
  const cfg = loadConfig();
10558
- const ctx = await resolveAgentContext(opts.agent);
10578
+ const initialOpts = opts;
10579
+ const agentRootDir = resolve(process.cwd(), values["agent-root"] ?? process.cwd());
10580
+ const ctx = await resolveAgentContext(initialOpts.agent, { agentRootDir });
10559
10581
  const profile = await resolveRuntimeProfile({
10560
10582
  agent: ctx.agent,
10561
10583
  profile: values.profile,
@@ -10582,7 +10604,6 @@ async function runOnce(argv) {
10582
10604
  agentName: opts.agent,
10583
10605
  runtimeProfileId: profile.id
10584
10606
  };
10585
- const mainRepo = findMainWorktree();
10586
10607
  const executionPlans = createExecutionPlanCache({
10587
10608
  stateDirs,
10588
10609
  slotIdentity,
@@ -10654,6 +10675,7 @@ async function runOnce(argv) {
10654
10675
  try {
10655
10676
  const rawExecuteTask = createPiTaskExecutor({
10656
10677
  agentName: opts.agent,
10678
+ agentRootDir: ctx.agentRootDir,
10657
10679
  mountPath: sandbox.rootDir,
10658
10680
  provider: profile.provider,
10659
10681
  model: profile.model,
@@ -10703,7 +10725,7 @@ async function runOnce(argv) {
10703
10725
  sessionDir: executionPlan.sessionPersistence.sessionDir,
10704
10726
  sessionPath: resolveLatestPiSessionPath(executionPlan.sessionPersistence.sessionDir),
10705
10727
  workspaceId: executionPlan.workspaceId,
10706
- worktreePath: resolveRecordedWorkspacePath(mainRepo, stateDirs.rootDir, executionPlan),
10728
+ worktreePath: resolveRecordedWorkspacePath(stateDirs.rootDir, executionPlan),
10707
10729
  worktreeBranch: executionPlan.worktreeBranch,
10708
10730
  workspaceKind: executionPlan.workspaceKind,
10709
10731
  lastTaskId: claimedTask.task.id,
@@ -10768,9 +10790,9 @@ async function runOnce(argv) {
10768
10790
  await shutdownLogger();
10769
10791
  }
10770
10792
  }
10771
- function resolveRecordedWorkspacePath(mainRepo, stateRootDir, executionPlan) {
10793
+ function resolveRecordedWorkspacePath(stateRootDir, executionPlan) {
10772
10794
  if (!executionPlan.workspaceId) return null;
10773
- return executionPlan.workspaceMode === "scratch_mount" ? join(stateRootDir, "task-workspaces", executionPlan.workspaceId) : join(mainRepo, ".worktrees", executionPlan.workspaceId);
10795
+ return executionPlan.workspaceMode === "scratch_mount" ? join(stateRootDir, "task-workspaces", executionPlan.workspaceId) : join(findMainWorktree(), ".worktrees", executionPlan.workspaceId);
10774
10796
  }
10775
10797
  //#endregion
10776
10798
  //#region src/cli/poll.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@themoltnet/agent-daemon",
3
- "version": "0.21.0",
3
+ "version": "0.22.1",
4
4
  "license": "AGPL-3.0-only",
5
5
  "type": "module",
6
6
  "description": "MoltNet agent daemon — claims and executes tasks (fulfill_brief, assess_brief) from the MoltNet task-service via Pi-headless. CLI: moltnet-agent.",
@@ -45,18 +45,18 @@
45
45
  "@opentelemetry/semantic-conventions": "^1.39.0",
46
46
  "pino": "^10.3.1",
47
47
  "pino-pretty": "^13.1.3",
48
- "@themoltnet/agent-runtime": "0.28.0",
49
- "@themoltnet/pi-extension": "0.26.2",
50
- "@themoltnet/sdk": "0.109.0"
48
+ "@themoltnet/agent-runtime": "0.28.1",
49
+ "@themoltnet/pi-extension": "0.26.4",
50
+ "@themoltnet/sdk": "0.110.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "tsx": "^4.7.0",
54
54
  "typescript": "~5.9.2",
55
55
  "vite": "^8.0.0",
56
56
  "vitest": "^3.0.0",
57
+ "@moltnet/bootstrap": "0.1.0",
57
58
  "@moltnet/crypto-service": "0.1.0",
58
59
  "@moltnet/observability": "0.1.0",
59
- "@moltnet/bootstrap": "0.1.0",
60
60
  "@moltnet/tasks": "0.1.0"
61
61
  },
62
62
  "nx": {