@themoltnet/agent-daemon 0.6.0 → 0.6.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.
- package/README.md +19 -0
- package/dist/main.js +21 -5
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -66,6 +66,25 @@ To use an alternate auth-file path: `PI_AUTH_PATH=/abs/path/to/auth.json`.
|
|
|
66
66
|
| `MOLTNET_OTEL_ENDPOINT` | unset | OTLP traces endpoint. Empty = disabled. |
|
|
67
67
|
| `LOG_LEVEL` | `info` | Pino log level override. |
|
|
68
68
|
|
|
69
|
+
### Host command auto-approval
|
|
70
|
+
|
|
71
|
+
The daemon reads `sandbox.json` through `--sandbox` or by searching up from the
|
|
72
|
+
current directory. Configure host-side auto-approval there, not in task data:
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"hostExec": {
|
|
77
|
+
"autoApprove": [
|
|
78
|
+
{ "argsPrefix": ["push"], "executable": "git" },
|
|
79
|
+
{ "argsPrefix": ["pr", "create"], "executable": "gh" }
|
|
80
|
+
]
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Set `"autoApprove": true` only for isolated hosts where every built-in
|
|
86
|
+
host-exec command is safe to run without a dialog.
|
|
87
|
+
|
|
69
88
|
## Correlation anchors
|
|
70
89
|
|
|
71
90
|
When a `fulfill_brief` task carries a non-null `correlationId`, the daemon
|
package/dist/main.js
CHANGED
|
@@ -13954,6 +13954,7 @@ function renderPhase6Markdown(pack) {
|
|
|
13954
13954
|
* These tools run on the host (not in the VM) via the MoltNet SDK,
|
|
13955
13955
|
* so agent credentials never touch the VM filesystem.
|
|
13956
13956
|
*/
|
|
13957
|
+
var DIARY_TAG_MAX_LENGTH = 128;
|
|
13957
13958
|
/**
|
|
13958
13959
|
* Baseline env keys forwarded to host-exec child processes.
|
|
13959
13960
|
* Callers can extend this set at sandbox startup via `MoltNetToolsConfig.hostExecBaseEnv`.
|
|
@@ -13982,6 +13983,19 @@ function ensureConnected(config) {
|
|
|
13982
13983
|
teamId: config.getTeamId() ?? ""
|
|
13983
13984
|
};
|
|
13984
13985
|
}
|
|
13986
|
+
function hostExecMatchesAutoApproveRule(params, rule) {
|
|
13987
|
+
if (params.executable !== rule.executable) return false;
|
|
13988
|
+
if (rule.argsExcludes?.some((arg) => params.args.includes(arg))) return false;
|
|
13989
|
+
if (rule.argsPrefix && !rule.argsPrefix.every((arg, index) => params.args[index] === arg)) return false;
|
|
13990
|
+
if (rule.argsContains && !rule.argsContains.every((arg) => params.args.includes(arg))) return false;
|
|
13991
|
+
return true;
|
|
13992
|
+
}
|
|
13993
|
+
function shouldAutoApproveHostExec(params, config) {
|
|
13994
|
+
const policy = config.autoApproveHostExec === true ? true : config.hostExecAutoApprove ?? false;
|
|
13995
|
+
if (policy === true) return true;
|
|
13996
|
+
if (!Array.isArray(policy)) return false;
|
|
13997
|
+
return policy.some((rule) => hostExecMatchesAutoApproveRule(params, rule));
|
|
13998
|
+
}
|
|
13985
13999
|
/**
|
|
13986
14000
|
* Expand the `taskFilter` shorthand on the diary list/search tools into
|
|
13987
14001
|
* the matching `task:*` provenance tags emitted by `moltnet_create_entry`
|
|
@@ -14200,14 +14214,14 @@ function createMoltNetTools(config) {
|
|
|
14200
14214
|
limit: Type.Optional(Type.Number({ description: "Max entries to return (default 10)" })),
|
|
14201
14215
|
tags: Type.Optional(Type.Array(Type.String({
|
|
14202
14216
|
minLength: 1,
|
|
14203
|
-
maxLength:
|
|
14217
|
+
maxLength: DIARY_TAG_MAX_LENGTH
|
|
14204
14218
|
}), {
|
|
14205
14219
|
description: "Tags filter — entry must have ALL listed tags (AND). Max 20.",
|
|
14206
14220
|
maxItems: 20
|
|
14207
14221
|
})),
|
|
14208
14222
|
excludeTags: Type.Optional(Type.Array(Type.String({
|
|
14209
14223
|
minLength: 1,
|
|
14210
|
-
maxLength:
|
|
14224
|
+
maxLength: DIARY_TAG_MAX_LENGTH
|
|
14211
14225
|
}), {
|
|
14212
14226
|
description: "Tags to exclude — entry must have NONE of these. Max 20.",
|
|
14213
14227
|
maxItems: 20
|
|
@@ -14300,14 +14314,14 @@ function createMoltNetTools(config) {
|
|
|
14300
14314
|
limit: Type.Optional(Type.Number({ description: "Max results (default 5)" })),
|
|
14301
14315
|
tags: Type.Optional(Type.Array(Type.String({
|
|
14302
14316
|
minLength: 1,
|
|
14303
|
-
maxLength:
|
|
14317
|
+
maxLength: DIARY_TAG_MAX_LENGTH
|
|
14304
14318
|
}), {
|
|
14305
14319
|
description: "Entry must have ALL listed tags (AND). Max 20.",
|
|
14306
14320
|
maxItems: 20
|
|
14307
14321
|
})),
|
|
14308
14322
|
excludeTags: Type.Optional(Type.Array(Type.String({
|
|
14309
14323
|
minLength: 1,
|
|
14310
|
-
maxLength:
|
|
14324
|
+
maxLength: DIARY_TAG_MAX_LENGTH
|
|
14311
14325
|
}), {
|
|
14312
14326
|
description: "Entry must have NONE of these tags. Max 20.",
|
|
14313
14327
|
maxItems: 20
|
|
@@ -14493,7 +14507,7 @@ function createMoltNetTools(config) {
|
|
|
14493
14507
|
}),
|
|
14494
14508
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
14495
14509
|
if (!HOST_EXEC_ALLOWED.has(params.executable)) throw new Error(`host_exec: '${params.executable}' is not in the allowed list (${[...HOST_EXEC_ALLOWED].join(", ")}). Extend HOST_EXEC_ALLOWED only after explicit security review.`);
|
|
14496
|
-
if (ctx?.ui) {
|
|
14510
|
+
if (ctx?.ui && !shouldAutoApproveHostExec(params, config)) {
|
|
14497
14511
|
const cmdDisplay = [params.executable, ...params.args].join(" ");
|
|
14498
14512
|
if (!await ctx.ui.confirm("Allow host command?", `The agent wants to run on your machine:\n\n ${cmdDisplay}\n\nAllow?`)) throw new Error(`host_exec: user declined approval for: ${cmdDisplay}`);
|
|
14499
14513
|
}
|
|
@@ -16133,6 +16147,7 @@ async function executePiTask(claimedTask, reporter, opts) {
|
|
|
16133
16147
|
clearSessionErrors: () => {},
|
|
16134
16148
|
getHostCwd: () => mountPath,
|
|
16135
16149
|
hostExecBaseEnv: new Set([...HOST_EXEC_DEFAULT_BASE_ENV, ...Object.keys(managed.credentials.agentEnv)]),
|
|
16150
|
+
hostExecAutoApprove: opts.hostExecAutoApprove ?? opts.sandboxConfig?.hostExec?.autoApprove ?? false,
|
|
16136
16151
|
getTaskContext: () => ({
|
|
16137
16152
|
taskId: task.id,
|
|
16138
16153
|
taskType: task.taskType,
|
|
@@ -16629,6 +16644,7 @@ async function finalizeTask(agent, output, ctx = {}) {
|
|
|
16629
16644
|
message: "Task execution failed before producing a valid output.",
|
|
16630
16645
|
retryable: false
|
|
16631
16646
|
};
|
|
16647
|
+
if ((await agent.tasks.heartbeat(output.taskId, output.attemptN, {})).cancelled) return;
|
|
16632
16648
|
await agent.tasks.fail(output.taskId, output.attemptN, { error });
|
|
16633
16649
|
}
|
|
16634
16650
|
async function maybeWriteAnchors(output, ctx) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@themoltnet/agent-daemon",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.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.",
|
|
@@ -33,19 +33,19 @@
|
|
|
33
33
|
"@opentelemetry/semantic-conventions": "^1.39.0",
|
|
34
34
|
"pino": "^10.3.1",
|
|
35
35
|
"pino-pretty": "^13.1.3",
|
|
36
|
-
"@themoltnet/agent-runtime": "0.15.0",
|
|
37
36
|
"@themoltnet/sdk": "0.102.0",
|
|
38
|
-
"@themoltnet/pi-extension": "0.16.
|
|
37
|
+
"@themoltnet/pi-extension": "0.16.1",
|
|
38
|
+
"@themoltnet/agent-runtime": "0.15.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"tsx": "^4.7.0",
|
|
42
42
|
"typescript": "^5.3.3",
|
|
43
43
|
"vite": "^8.0.0",
|
|
44
44
|
"vitest": "^3.0.0",
|
|
45
|
-
"@moltnet/bootstrap": "0.1.0",
|
|
46
45
|
"@moltnet/crypto-service": "0.1.0",
|
|
47
46
|
"@moltnet/tasks": "0.1.0",
|
|
48
|
-
"@moltnet/database": "0.1.0"
|
|
47
|
+
"@moltnet/database": "0.1.0",
|
|
48
|
+
"@moltnet/bootstrap": "0.1.0"
|
|
49
49
|
},
|
|
50
50
|
"nx": {
|
|
51
51
|
"tags": [
|