@themoltnet/agent-daemon 0.34.1 → 0.35.0

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/cli.js +43 -15
  2. package/package.json +6 -6
package/dist/cli.js CHANGED
@@ -5,10 +5,10 @@ import * as Format from "typebox/format";
5
5
  import { Type } from "typebox";
6
6
  import crypto from "crypto";
7
7
  import { Value } from "typebox/value";
8
- import { dirname, isAbsolute, join, relative, resolve } from "node:path";
8
+ import { dirname, join, resolve } from "node:path";
9
9
  import { parseArgs, promisify } from "node:util";
10
10
  import { AgentRuntime, ApiTaskReporter, ApiTaskSource, PollingApiTaskSource } from "@themoltnet/agent-runtime";
11
- import { createPiRetryTriage, findMainWorktree, normalizeRetryTriageResult, redactRetryTriageSecrets } from "@themoltnet/pi-runtime";
11
+ import { createPiRetryTriage, findMainWorktree, isResolvedPathInsideRoot, normalizeRetryTriageResult, redactRetryTriageSecrets } from "@themoltnet/pi-runtime";
12
12
  import { execFile, execFileSync } from "node:child_process";
13
13
  import { createReadStream, createWriteStream, existsSync, mkdirSync, readdirSync, realpathSync, rmSync } from "node:fs";
14
14
  import { AuthenticationError, MoltNetError, connect } from "@themoltnet/sdk";
@@ -251,6 +251,11 @@ Type.Object({
251
251
  var RUNTIME_PROFILE_CONTEXT_CATALOGUE = {
252
252
  version: 1,
253
253
  fragments: {
254
+ "artifact-planner-v1": {
255
+ binding: "prompt_prefix",
256
+ content: "# Bounded artifact planner\n\n- The typed task facts, embedded bounded manifest, exact bound artifact references, registered tools, and runtime capability section are the complete contract. Do not search diaries, inspect a mounted repository, enumerate unrelated tasks or artifacts, use shell commands, modify files, commit, branch, push, or contact GitHub.\n- Read only the exact artifact CIDs named by the task, and only when the embedded manifest does not provide enough evidence. Never paginate or discover artifacts speculatively.\n- Perform semantic classification and planning from supplied content and producer/consumer evidence. Do not substitute filename, directory, language, ecosystem, or repository-specific exclusion rules for evidence.\n- Return exactly the requested versioned structured plan through the registered submit-output tool. Do not emit a second prose or JSON representation.",
257
+ slug: "artifact-planner-v1"
258
+ },
254
259
  "accountable-delivery-v1": {
255
260
  binding: "prompt_prefix",
256
261
  content: "# Accountable delivery\n\n- Pair every commit made during this task with a signed diary entry created by the `moltnet_create_entry` custom tool. Put the returned id in a `MoltNet-Diary: <id>` commit trailer.\n- Keep commit signing enabled; do not bypass the agent git configuration.\n- Push a branch and open or update a pull request only when the task asks for it. For GitHub mutations, use the credential-bound `GH_TOKEN` command form required by the runtime kernel.\n- Keep changes, commits, and any requested pull request coherent enough to review independently.",
@@ -283,6 +288,10 @@ var RUNTIME_PROFILE_CONTEXT_CATALOGUE = {
283
288
  }
284
289
  },
285
290
  recipes: {
291
+ "artifact-planner@v1": {
292
+ description: "Minimal artifact-only context for bounded semantic classification and planning.",
293
+ fragments: ["artifact-planner-v1"]
294
+ },
286
295
  "run-eval-direct@v1": {
287
296
  description: "Minimal direct context for a short, isolated evaluation run.",
288
297
  fragments: ["run-eval-direct-v1"]
@@ -889,7 +898,11 @@ var ProblemDetailsSchema = Type.Object({
889
898
  }),
890
899
  code: ProblemCodeSchema,
891
900
  detail: Type.Optional(Type.String()),
892
- instance: Type.Optional(Type.String())
901
+ instance: Type.Optional(Type.String()),
902
+ retryAfter: Type.Optional(Type.Integer({
903
+ minimum: 0,
904
+ description: "Non-negative delay in seconds before retrying, matching the Retry-After response header when present."
905
+ }))
893
906
  }, {
894
907
  $id: "ProblemDetails",
895
908
  additionalProperties: true
@@ -1717,7 +1730,7 @@ var VerificationResult = Type.Object({
1717
1730
  var VerificationRecord = Type.Object({
1718
1731
  inputCid: Type.String({ minLength: 1 }),
1719
1732
  results: Type.Array(VerificationResult),
1720
- passed: Type.Boolean()
1733
+ passed: Type.Boolean({ description: "True iff every verification result has status \"pass\" or \"skip\"; false when any result has status \"fail\"." })
1721
1734
  }, {
1722
1735
  $id: "VerificationRecord",
1723
1736
  additionalProperties: false
@@ -3692,6 +3705,10 @@ Type.Object({
3692
3705
  taskId: Uuid,
3693
3706
  attemptN: Type.Number({ minimum: 1 }),
3694
3707
  claimedByAgentId: Uuid,
3708
+ leaseId: Type.Union([Uuid, Type.Null()]),
3709
+ runtimeProfileId: Type.Union([Uuid, Type.Null()]),
3710
+ runtimeProfileRevision: Type.Union([Type.Integer({ minimum: 1 }), Type.Null()]),
3711
+ policySnapshotHash: Type.Union([Type.String({ pattern: "^sha256:[0-9a-f]{64}$" }), Type.Null()]),
3695
3712
  runtimeId: Type.Union([Uuid, Type.Null()]),
3696
3713
  claimedAt: IsoTimestamp,
3697
3714
  startedAt: Type.Union([IsoTimestamp, Type.Null()]),
@@ -4227,7 +4244,7 @@ function buildDaemonTaskExecutionPlan(task, stateDirs, identity, warmSessionTtlS
4227
4244
  const slotKey = warmSessionTtlSec > 0 && descriptor.sessionKey ? buildRuntimeSlotKey(descriptor.sessionKey, identity.runtimeInstanceId) : null;
4228
4245
  const workspaceScope = slotKey !== null ? descriptor.policy.workspaceScope : "attempt";
4229
4246
  const slotId = slotKey ? buildDaemonSlotId(identity, slotKey) : null;
4230
- const sessionDir = slotId ? `${stateDirs.piSessionsDir}/${encodeURIComponent(slotId)}` : null;
4247
+ const sessionDir = slotId ? `${stateDirs.piSessionsDir}/${boundedKeyDirComponent(slotId)}` : null;
4231
4248
  const worktreeBranch = resolveTaskWorktreeBranch(task, workspaceMode);
4232
4249
  const workspaceId = workspaceMode !== "shared_mount" ? resolveTaskWorkspaceId(task, {
4233
4250
  sessionKey: slotId,
@@ -4315,8 +4332,27 @@ function isRuntimeProfileWorkspaceMode(value) {
4315
4332
  function toDaemonWorkspaceMode(mode) {
4316
4333
  return mode === "none" ? "scratch_mount" : mode;
4317
4334
  }
4335
+ /**
4336
+ * URL-encode a slot/session key for use as a single filesystem directory
4337
+ * component, bounded to stay under the 255-byte per-component filename limit.
4338
+ * A long key (e.g. `run_eval`'s custom key, which embeds the variant label +
4339
+ * agent name + worker id) otherwise crashes `mkdir` with `ENAMETOOLONG`.
4340
+ *
4341
+ * Additive by design: keys short enough today keep their exact encoded form (so
4342
+ * existing warm dirs are byte-identical), and only over-long keys get a readable
4343
+ * prefix + a collision-resistant sha256 suffix. The component is never decoded
4344
+ * back to the key anywhere, so hashing the tail is safe. Used for BOTH the
4345
+ * pi-sessions dir and the session workspace dir so the two names derive
4346
+ * consistently from the same slot id.
4347
+ */
4348
+ function boundedKeyDirComponent(key) {
4349
+ const encoded = encodeURIComponent(key);
4350
+ if (encoded.length <= 200) return encoded;
4351
+ const hash = createHash("sha256").update(key).digest("hex").slice(0, 16);
4352
+ return `${encoded.slice(0, 180)}-${hash}`;
4353
+ }
4318
4354
  function resolveTaskWorkspaceId(task, executionPlan) {
4319
- if (executionPlan.workspaceScope === "session" && executionPlan.sessionKey !== null) return `session-${encodeURIComponent(executionPlan.sessionKey)}`;
4355
+ if (executionPlan.workspaceScope === "session" && executionPlan.sessionKey !== null) return `session-${boundedKeyDirComponent(executionPlan.sessionKey)}`;
4320
4356
  return executionPlan.attemptN ? `daemon-task-${task.id}-attempt-${executionPlan.attemptN}` : `task-${task.id}`;
4321
4357
  }
4322
4358
  //#endregion
@@ -5395,15 +5431,11 @@ async function listRegisteredWorktrees(mainWorktree) {
5395
5431
  }
5396
5432
  function isRealPathInsideRoot(path, root) {
5397
5433
  try {
5398
- return isResolvedPathInsideRoot$1(realpathSync(path), realpathSync(root));
5434
+ return isResolvedPathInsideRoot(realpathSync(path), realpathSync(root));
5399
5435
  } catch {
5400
5436
  return false;
5401
5437
  }
5402
5438
  }
5403
- function isResolvedPathInsideRoot$1(path, root) {
5404
- const rel = relative(root, path);
5405
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
5406
- }
5407
5439
  function canonicalPath(path) {
5408
5440
  try {
5409
5441
  return realpathSync(path);
@@ -6774,10 +6806,6 @@ async function isPathInsideRoot(path, root) {
6774
6806
  }
6775
6807
  return isResolvedPathInsideRoot(realResolvedPath, realResolvedRoot);
6776
6808
  }
6777
- function isResolvedPathInsideRoot(path, root) {
6778
- const rel = relative(root, path);
6779
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
6780
- }
6781
6809
  async function computeCompressedSessionFingerprint(path) {
6782
6810
  const hash = createHash("sha256");
6783
6811
  let bytes = 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@themoltnet/agent-daemon",
3
- "version": "0.34.1",
3
+ "version": "0.35.0",
4
4
  "license": "AGPL-3.0-only",
5
5
  "type": "module",
6
6
  "description": "Universal MoltNet agent daemon host with a built-in Pi/Gondolin runtime and support for trusted operator-owned runtime modules. CLI: moltnet-agent.",
@@ -44,7 +44,7 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@earendil-works/gondolin": "^0.9.1",
47
- "@earendil-works/pi-ai": "0.74.0",
47
+ "@earendil-works/pi-ai": "0.79.4",
48
48
  "@earendil-works/pi-coding-agent": "0.79.4",
49
49
  "@opentelemetry/api": "^1.9.0",
50
50
  "@opentelemetry/exporter-trace-otlp-proto": "^0.212.0",
@@ -62,8 +62,8 @@
62
62
  "pino": "^10.3.1",
63
63
  "pino-pretty": "^13.1.3",
64
64
  "typebox": "^1.2.8",
65
- "@themoltnet/agent-runtime": "0.38.0",
66
- "@themoltnet/pi-runtime": "0.3.0",
65
+ "@themoltnet/agent-runtime": "0.39.1",
66
+ "@themoltnet/pi-runtime": "0.5.0",
67
67
  "@themoltnet/sdk": "0.128.0"
68
68
  },
69
69
  "devDependencies": {
@@ -73,9 +73,9 @@
73
73
  "vite-plugin-dts": "^4.5.4",
74
74
  "vitest": "^3.0.0",
75
75
  "@moltnet/bootstrap": "0.1.0",
76
- "@moltnet/tasks": "0.1.0",
77
76
  "@moltnet/crypto-service": "0.1.0",
78
- "@moltnet/observability": "0.1.0"
77
+ "@moltnet/observability": "0.1.0",
78
+ "@moltnet/tasks": "0.1.0"
79
79
  },
80
80
  "nx": {
81
81
  "projectType": "application",