@themoltnet/agent-daemon 0.10.6 → 0.11.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/README.md +2 -2
- package/dist/main.js +52 -18
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -250,7 +250,7 @@ Leave it running. It idles until a task lands in its queue.
|
|
|
250
250
|
|
|
251
251
|
In another terminal, with `.moltnet/local-dev/env` sourced. Pick the CLI
|
|
252
252
|
form (recommended — schema-validates locally, no Node dependency in the
|
|
253
|
-
|
|
253
|
+
proposer path) or the template-driven TS form (legacy path that supports
|
|
254
254
|
`{{placeholder}}` substitution via `--set`).
|
|
255
255
|
|
|
256
256
|
::: code-group
|
|
@@ -325,7 +325,7 @@ pnpm exec tsx tools/src/tasks/create-pr-review.ts \
|
|
|
325
325
|
--repo <owner/repo>
|
|
326
326
|
```
|
|
327
327
|
|
|
328
|
-
This helper stays
|
|
328
|
+
This helper stays proposer-only. It reads PR metadata, ensures the PR
|
|
329
329
|
correlation marker exists, loads the binary rubric, and creates the
|
|
330
330
|
`pr_review` task. The daemon-claimed LLM attempt remains responsible for
|
|
331
331
|
the review itself and for any requested outward action such as `gh pr comment`.
|
package/dist/main.js
CHANGED
|
@@ -2901,7 +2901,7 @@ var ContextBinding = Type$2.Union([
|
|
|
2901
2901
|
Type$2.Literal("user_inline")
|
|
2902
2902
|
], { $id: "ContextBinding" });
|
|
2903
2903
|
/**
|
|
2904
|
-
* One context entry. Bytes are inlined: the
|
|
2904
|
+
* One context entry. Bytes are inlined: the proposer chose them, and the
|
|
2905
2905
|
* task's `inputCid` already pins the entire input — including
|
|
2906
2906
|
* `context[]` — so we don't need a separate per-entry hash, fetcher, or
|
|
2907
2907
|
* flagged-content gate. Tasks reference rendered packs (or any other
|
|
@@ -3047,7 +3047,7 @@ function validateRubricWeights(rubric) {
|
|
|
3047
3047
|
//#endregion
|
|
3048
3048
|
//#region ../../libs/tasks/src/success-criteria.ts
|
|
3049
3049
|
/**
|
|
3050
|
-
* SuccessCriteria —
|
|
3050
|
+
* SuccessCriteria — proposer-stated acceptance criteria, evaluated in two
|
|
3051
3051
|
* complementary places.
|
|
3052
3052
|
*
|
|
3053
3053
|
* Before this envelope existed, criteria were scattered: a vestigial
|
|
@@ -3056,7 +3056,7 @@ function validateRubricWeights(rubric) {
|
|
|
3056
3056
|
* judgment-task inputs. None of those were machine-verifiable
|
|
3057
3057
|
* end-to-end.
|
|
3058
3058
|
*
|
|
3059
|
-
* This module defines a single, content-addressable envelope
|
|
3059
|
+
* This module defines a single, content-addressable envelope a proposer
|
|
3060
3060
|
* attaches to any task type. It has four orthogonal sections — pick
|
|
3061
3061
|
* whichever apply per task type:
|
|
3062
3062
|
*
|
|
@@ -3090,7 +3090,7 @@ function validateRubricWeights(rubric) {
|
|
|
3090
3090
|
* spec for the judge.
|
|
3091
3091
|
*
|
|
3092
3092
|
* The clean chain: producer task with `successCriteria` → producer
|
|
3093
|
-
* self-assesses honestly →
|
|
3093
|
+
* self-assesses honestly → proposer (or automation) creates a downstream
|
|
3094
3094
|
* judgment task that references the same `successCriteria` (or a
|
|
3095
3095
|
* stricter rubric) → judgment task delivers the binding verdict.
|
|
3096
3096
|
*
|
|
@@ -4093,8 +4093,9 @@ var AssessBriefOutput = Type$2.Object({
|
|
|
4093
4093
|
* - `targetTaskId` resolves to a real task the caller can see.
|
|
4094
4094
|
* - The target is a `fulfill_brief` (you cannot grade an arbitrary
|
|
4095
4095
|
* task type as if it were a brief fulfillment).
|
|
4096
|
-
* -
|
|
4097
|
-
* an
|
|
4096
|
+
* - Unless readiness checks are explicitly deferred, the target is
|
|
4097
|
+
* `completed` with an accepted attempt — grading an in-flight or
|
|
4098
|
+
* failed task would either race or grade nothing.
|
|
4098
4099
|
*
|
|
4099
4100
|
* Agent-distinctness ("assessor ≠ producer") is a runtime / auth-
|
|
4100
4101
|
* layer concern and intentionally NOT checked here. It belongs in
|
|
@@ -4115,7 +4116,7 @@ async function validateAssessBriefInputAsync(input, ctx) {
|
|
|
4115
4116
|
field: "targetTaskId",
|
|
4116
4117
|
message: `targetTaskId ${targetTaskId} is a ${target.taskType}, not a fulfill_brief`
|
|
4117
4118
|
});
|
|
4118
|
-
if (target.status !== "completed" || target.acceptedAttemptN === null) errors.push({
|
|
4119
|
+
if (!ctx.deferReadinessChecks && (target.status !== "completed" || target.acceptedAttemptN === null)) errors.push({
|
|
4119
4120
|
field: "targetTaskId",
|
|
4120
4121
|
message: `targetTaskId ${targetTaskId} is not completed with an accepted attempt (status=${target.status}, acceptedAttemptN=${target.acceptedAttemptN})`
|
|
4121
4122
|
});
|
|
@@ -4436,11 +4437,11 @@ async function validateJudgeEvalAttemptInputAsync(input, ctx) {
|
|
|
4436
4437
|
field: "targetTaskId",
|
|
4437
4438
|
message: `targetTaskId=${inp.targetTaskId} is a ${target.taskType}, not a run_eval`
|
|
4438
4439
|
});
|
|
4439
|
-
if (target.status !== "completed" || target.acceptedAttemptN === null) errors.push({
|
|
4440
|
+
if (!ctx.deferReadinessChecks && (target.status !== "completed" || target.acceptedAttemptN === null)) errors.push({
|
|
4440
4441
|
field: "targetTaskId",
|
|
4441
4442
|
message: `targetTaskId=${inp.targetTaskId} is not completed with an accepted attempt (status=${target.status}, acceptedAttemptN=${target.acceptedAttemptN})`
|
|
4442
4443
|
});
|
|
4443
|
-
else if (target.acceptedAttemptN !== inp.targetAttemptN) errors.push({
|
|
4444
|
+
else if (target.acceptedAttemptN !== null && target.acceptedAttemptN !== inp.targetAttemptN) errors.push({
|
|
4444
4445
|
field: "targetAttemptN",
|
|
4445
4446
|
message: `targetAttemptN=${inp.targetAttemptN} does not match the producer's acceptedAttemptN=${target.acceptedAttemptN}`
|
|
4446
4447
|
});
|
|
@@ -4451,6 +4452,7 @@ async function validateJudgeEvalAttemptInputAsync(input, ctx) {
|
|
|
4451
4452
|
if (errors.length > 0 || !target.correlationId) return errors;
|
|
4452
4453
|
const rubric = inp.successCriteria.rubric;
|
|
4453
4454
|
const duplicate = (await ctx.listTasksByCorrelation(target.correlationId)).find((task) => {
|
|
4455
|
+
if (task.id === ctx.currentTaskId) return false;
|
|
4454
4456
|
if (task.taskType !== "judge_eval_attempt") return false;
|
|
4455
4457
|
if (task.status === "failed" || task.status === "cancelled" || task.status === "expired") return false;
|
|
4456
4458
|
const existing = task.input;
|
|
@@ -5814,11 +5816,12 @@ function getTaskExecutionPolicy(taskType) {
|
|
|
5814
5816
|
*
|
|
5815
5817
|
* Identity rule:
|
|
5816
5818
|
* - claim/execute/sign → agent-only (`task_attempts.claimed_by_agent_id`)
|
|
5817
|
-
* -
|
|
5819
|
+
* - propose/cancel → agent XOR human (dual nullable FK + XOR check)
|
|
5818
5820
|
*
|
|
5819
5821
|
* See GH issue #852 for the full design snapshot.
|
|
5820
5822
|
*/
|
|
5821
5823
|
var TaskStatus = Type$2.Union([
|
|
5824
|
+
Type$2.Literal("waiting"),
|
|
5822
5825
|
Type$2.Literal("queued"),
|
|
5823
5826
|
Type$2.Literal("dispatched"),
|
|
5824
5827
|
Type$2.Literal("running"),
|
|
@@ -5861,6 +5864,36 @@ var TaskMessageKind = Type$2.Union([
|
|
|
5861
5864
|
var Uuid = Type$2.String({ format: "uuid" });
|
|
5862
5865
|
var Cid = Type$2.String({ minLength: 1 });
|
|
5863
5866
|
var IsoTimestamp = Type$2.String({ format: "date-time" });
|
|
5867
|
+
var MAX_CLAIM_CONDITION_BRANCHES = 8;
|
|
5868
|
+
var MAX_CLAIM_CONDITION_STATUSES = 8;
|
|
5869
|
+
var ClaimCondition = Type$2.Recursive((Self) => Type$2.Union([
|
|
5870
|
+
Type$2.Object({
|
|
5871
|
+
op: Type$2.Literal("all"),
|
|
5872
|
+
conditions: Type$2.Array(Self, {
|
|
5873
|
+
minItems: 1,
|
|
5874
|
+
maxItems: MAX_CLAIM_CONDITION_BRANCHES
|
|
5875
|
+
})
|
|
5876
|
+
}, { additionalProperties: false }),
|
|
5877
|
+
Type$2.Object({
|
|
5878
|
+
op: Type$2.Literal("any"),
|
|
5879
|
+
conditions: Type$2.Array(Self, {
|
|
5880
|
+
minItems: 1,
|
|
5881
|
+
maxItems: MAX_CLAIM_CONDITION_BRANCHES
|
|
5882
|
+
})
|
|
5883
|
+
}, { additionalProperties: false }),
|
|
5884
|
+
Type$2.Object({
|
|
5885
|
+
op: Type$2.Literal("task_status"),
|
|
5886
|
+
taskId: Uuid,
|
|
5887
|
+
statuses: Type$2.Array(Type$2.Ref(TaskStatus), {
|
|
5888
|
+
minItems: 1,
|
|
5889
|
+
maxItems: MAX_CLAIM_CONDITION_STATUSES
|
|
5890
|
+
})
|
|
5891
|
+
}, { additionalProperties: false }),
|
|
5892
|
+
Type$2.Object({
|
|
5893
|
+
op: Type$2.Literal("task_accepted"),
|
|
5894
|
+
taskId: Uuid
|
|
5895
|
+
}, { additionalProperties: false })
|
|
5896
|
+
]), { $id: "ClaimCondition" });
|
|
5864
5897
|
/**
|
|
5865
5898
|
* Reference to another task's output or an external artifact.
|
|
5866
5899
|
* Embedded in `tasks.references` JSONB array.
|
|
@@ -5937,9 +5970,10 @@ Type$2.Object({
|
|
|
5937
5970
|
inputCid: Cid,
|
|
5938
5971
|
references: Type$2.Array(TaskRef),
|
|
5939
5972
|
correlationId: Type$2.Union([Uuid, Type$2.Null()]),
|
|
5940
|
-
|
|
5941
|
-
|
|
5973
|
+
proposedByAgentId: Type$2.Union([Uuid, Type$2.Null()]),
|
|
5974
|
+
proposedByHumanId: Type$2.Union([Uuid, Type$2.Null()]),
|
|
5942
5975
|
acceptedAttemptN: Type$2.Union([Type$2.Number(), Type$2.Null()]),
|
|
5976
|
+
claimCondition: Type$2.Union([ClaimCondition, Type$2.Null()]),
|
|
5943
5977
|
requiredExecutorTrustLevel: ExecutorTrustLevel,
|
|
5944
5978
|
allowedExecutors: Type$2.Array(ExecutorRef, { maxItems: 16 }),
|
|
5945
5979
|
status: TaskStatus,
|
|
@@ -6199,7 +6233,7 @@ var PROMPT_SEPARATOR = "\n\n---\n\n";
|
|
|
6199
6233
|
* declared order, same separator.
|
|
6200
6234
|
*
|
|
6201
6235
|
* No fetching, no hashing — bytes are inlined in `ContextRef.content`,
|
|
6202
|
-
* and the task's `inputCid` already pins the entire input. The
|
|
6236
|
+
* and the task's `inputCid` already pins the entire input. The proposer
|
|
6203
6237
|
* chose these bytes; the resolver just dispatches them.
|
|
6204
6238
|
*
|
|
6205
6239
|
* The function is pure with respect to its arguments: file writes are
|
|
@@ -6622,7 +6656,7 @@ function buildCuratePackUserPrompt(input, ctx) {
|
|
|
6622
6656
|
"to defend it in the summary."
|
|
6623
6657
|
].join("\n");
|
|
6624
6658
|
const constraintsLines = [];
|
|
6625
|
-
if (entryTypesPinned) constraintsLines.push(`- Entry types pinned by
|
|
6659
|
+
if (entryTypesPinned) constraintsLines.push(`- Entry types pinned by proposer (do not widen): ${entryTypes.map((t) => `\`${t}\``).join(", ")}`);
|
|
6626
6660
|
else constraintsLines.push("- Entry types: **you choose**. The diary contains three kinds:", " - `episodic` — incident reports, \"what happened and how we fixed it\" narratives.", " - `semantic` — durable decisions, patterns, design rationale.", " - `procedural` — commit audit trails / changelog-style provenance.", " Pick the subset that fits the prompt. For \"failures and workarounds\"", " or \"decisions we made\" you generally do NOT want `procedural` — those", " entries are append-only commit logs and produce changelog-shaped packs.", " Include `procedural` only when the prompt explicitly asks for changelog-", " style content (e.g., \"what shipped this week\"). State your choice", " briefly in the final `summary`.");
|
|
6627
6661
|
constraintsLines.push(`- Recipe tag: \`${resolvedRecipe}\` (recorded on pack params)`);
|
|
6628
6662
|
constraintsLines.push(tokenBudget ? `- Token budget (soft cap on final pack): ${tokenBudget}. Pick entry count so the pack fits — estimate ~300 tok/entry as a starting heuristic, tighten after inspecting actual content lengths.` : "- No token budget — size the pack to match the prompt, not an arbitrary target.");
|
|
@@ -7858,7 +7892,7 @@ var ApiTaskReporter = class {
|
|
|
7858
7892
|
const response = await this.opts.tasks.heartbeat(this.taskId, this.attemptN, body);
|
|
7859
7893
|
if (response?.cancelled && !this.cancelController.signal.aborted) {
|
|
7860
7894
|
this.observedCancelReason = response.cancelReason ?? null;
|
|
7861
|
-
this.cancelController.abort(/* @__PURE__ */ new Error(`Task cancelled by
|
|
7895
|
+
this.cancelController.abort(/* @__PURE__ */ new Error(`Task cancelled by proposer${this.observedCancelReason ? `: ${this.observedCancelReason}` : ""}`));
|
|
7862
7896
|
if (this.heartbeatTimer) {
|
|
7863
7897
|
clearInterval(this.heartbeatTimer);
|
|
7864
7898
|
this.heartbeatTimer = null;
|
|
@@ -7935,7 +7969,7 @@ var AgentRuntime = class {
|
|
|
7935
7969
|
outputCid: null,
|
|
7936
7970
|
error: {
|
|
7937
7971
|
code: "task_cancelled",
|
|
7938
|
-
message: reporter.cancelReason ?? "Task cancelled by
|
|
7972
|
+
message: reporter.cancelReason ?? "Task cancelled by proposer while executor was running.",
|
|
7939
7973
|
retryable: false
|
|
7940
7974
|
}
|
|
7941
7975
|
};
|
|
@@ -10458,7 +10492,7 @@ var MoltNetError = class extends Error {
|
|
|
10458
10492
|
/**
|
|
10459
10493
|
* Populated when the server returned a `VALIDATION_FAILED` problem
|
|
10460
10494
|
* (status 400) with field-level errors. Empty / undefined for every
|
|
10461
|
-
* other problem kind.
|
|
10495
|
+
* other problem kind. Proposer scripts surface these to operators so
|
|
10462
10496
|
* they don't have to re-run with curl to see what was rejected.
|
|
10463
10497
|
*/
|
|
10464
10498
|
validationErrors;
|
|
@@ -17418,7 +17452,7 @@ async function executePiTask(claimedTask, reporter, opts) {
|
|
|
17418
17452
|
durationMs: Date.now() - startTime,
|
|
17419
17453
|
error: {
|
|
17420
17454
|
code: "task_cancelled",
|
|
17421
|
-
message: reporter.cancelReason ?? "Task cancelled by
|
|
17455
|
+
message: reporter.cancelReason ?? "Task cancelled by proposer while pi session was running.",
|
|
17422
17456
|
retryable: false
|
|
17423
17457
|
}
|
|
17424
17458
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@themoltnet/agent-daemon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
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/
|
|
37
|
-
"@themoltnet/agent-runtime": "0.
|
|
38
|
-
"@themoltnet/
|
|
36
|
+
"@themoltnet/pi-extension": "0.20.0",
|
|
37
|
+
"@themoltnet/agent-runtime": "0.19.0",
|
|
38
|
+
"@themoltnet/sdk": "0.106.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"tsx": "^4.7.0",
|
|
42
42
|
"typescript": "~5.9.2",
|
|
43
43
|
"vite": "^8.0.0",
|
|
44
44
|
"vitest": "^3.0.0",
|
|
45
|
-
"@moltnet/crypto-service": "0.1.0",
|
|
46
|
-
"@moltnet/database": "0.1.0",
|
|
47
45
|
"@moltnet/bootstrap": "0.1.0",
|
|
48
|
-
"@moltnet/tasks": "0.1.0"
|
|
46
|
+
"@moltnet/tasks": "0.1.0",
|
|
47
|
+
"@moltnet/crypto-service": "0.1.0",
|
|
48
|
+
"@moltnet/database": "0.1.0"
|
|
49
49
|
},
|
|
50
50
|
"nx": {
|
|
51
51
|
"tags": [
|