@themoltnet/agent-daemon 0.34.2 → 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.
- package/dist/cli.js +34 -14
- 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,
|
|
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"]
|
|
@@ -1721,7 +1730,7 @@ var VerificationResult = Type.Object({
|
|
|
1721
1730
|
var VerificationRecord = Type.Object({
|
|
1722
1731
|
inputCid: Type.String({ minLength: 1 }),
|
|
1723
1732
|
results: Type.Array(VerificationResult),
|
|
1724
|
-
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\"." })
|
|
1725
1734
|
}, {
|
|
1726
1735
|
$id: "VerificationRecord",
|
|
1727
1736
|
additionalProperties: false
|
|
@@ -4235,7 +4244,7 @@ function buildDaemonTaskExecutionPlan(task, stateDirs, identity, warmSessionTtlS
|
|
|
4235
4244
|
const slotKey = warmSessionTtlSec > 0 && descriptor.sessionKey ? buildRuntimeSlotKey(descriptor.sessionKey, identity.runtimeInstanceId) : null;
|
|
4236
4245
|
const workspaceScope = slotKey !== null ? descriptor.policy.workspaceScope : "attempt";
|
|
4237
4246
|
const slotId = slotKey ? buildDaemonSlotId(identity, slotKey) : null;
|
|
4238
|
-
const sessionDir = slotId ? `${stateDirs.piSessionsDir}/${
|
|
4247
|
+
const sessionDir = slotId ? `${stateDirs.piSessionsDir}/${boundedKeyDirComponent(slotId)}` : null;
|
|
4239
4248
|
const worktreeBranch = resolveTaskWorktreeBranch(task, workspaceMode);
|
|
4240
4249
|
const workspaceId = workspaceMode !== "shared_mount" ? resolveTaskWorkspaceId(task, {
|
|
4241
4250
|
sessionKey: slotId,
|
|
@@ -4323,8 +4332,27 @@ function isRuntimeProfileWorkspaceMode(value) {
|
|
|
4323
4332
|
function toDaemonWorkspaceMode(mode) {
|
|
4324
4333
|
return mode === "none" ? "scratch_mount" : mode;
|
|
4325
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
|
+
}
|
|
4326
4354
|
function resolveTaskWorkspaceId(task, executionPlan) {
|
|
4327
|
-
if (executionPlan.workspaceScope === "session" && executionPlan.sessionKey !== null) return `session-${
|
|
4355
|
+
if (executionPlan.workspaceScope === "session" && executionPlan.sessionKey !== null) return `session-${boundedKeyDirComponent(executionPlan.sessionKey)}`;
|
|
4328
4356
|
return executionPlan.attemptN ? `daemon-task-${task.id}-attempt-${executionPlan.attemptN}` : `task-${task.id}`;
|
|
4329
4357
|
}
|
|
4330
4358
|
//#endregion
|
|
@@ -5403,15 +5431,11 @@ async function listRegisteredWorktrees(mainWorktree) {
|
|
|
5403
5431
|
}
|
|
5404
5432
|
function isRealPathInsideRoot(path, root) {
|
|
5405
5433
|
try {
|
|
5406
|
-
return isResolvedPathInsideRoot
|
|
5434
|
+
return isResolvedPathInsideRoot(realpathSync(path), realpathSync(root));
|
|
5407
5435
|
} catch {
|
|
5408
5436
|
return false;
|
|
5409
5437
|
}
|
|
5410
5438
|
}
|
|
5411
|
-
function isResolvedPathInsideRoot$1(path, root) {
|
|
5412
|
-
const rel = relative(root, path);
|
|
5413
|
-
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
5414
|
-
}
|
|
5415
5439
|
function canonicalPath(path) {
|
|
5416
5440
|
try {
|
|
5417
5441
|
return realpathSync(path);
|
|
@@ -6782,10 +6806,6 @@ async function isPathInsideRoot(path, root) {
|
|
|
6782
6806
|
}
|
|
6783
6807
|
return isResolvedPathInsideRoot(realResolvedPath, realResolvedRoot);
|
|
6784
6808
|
}
|
|
6785
|
-
function isResolvedPathInsideRoot(path, root) {
|
|
6786
|
-
const rel = relative(root, path);
|
|
6787
|
-
return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
|
|
6788
|
-
}
|
|
6789
6809
|
async function computeCompressedSessionFingerprint(path) {
|
|
6790
6810
|
const hash = createHash("sha256");
|
|
6791
6811
|
let bytes = 0;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@themoltnet/agent-daemon",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
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,9 +62,9 @@
|
|
|
62
62
|
"pino": "^10.3.1",
|
|
63
63
|
"pino-pretty": "^13.1.3",
|
|
64
64
|
"typebox": "^1.2.8",
|
|
65
|
-
"@themoltnet/
|
|
66
|
-
"@themoltnet/
|
|
67
|
-
"@themoltnet/
|
|
65
|
+
"@themoltnet/agent-runtime": "0.39.1",
|
|
66
|
+
"@themoltnet/pi-runtime": "0.5.0",
|
|
67
|
+
"@themoltnet/sdk": "0.128.0"
|
|
68
68
|
},
|
|
69
69
|
"devDependencies": {
|
|
70
70
|
"tsx": "^4.7.0",
|
|
@@ -72,8 +72,8 @@
|
|
|
72
72
|
"vite": "^8.0.0",
|
|
73
73
|
"vite-plugin-dts": "^4.5.4",
|
|
74
74
|
"vitest": "^3.0.0",
|
|
75
|
-
"@moltnet/crypto-service": "0.1.0",
|
|
76
75
|
"@moltnet/bootstrap": "0.1.0",
|
|
76
|
+
"@moltnet/crypto-service": "0.1.0",
|
|
77
77
|
"@moltnet/observability": "0.1.0",
|
|
78
78
|
"@moltnet/tasks": "0.1.0"
|
|
79
79
|
},
|