@themoltnet/pi-extension 0.32.1 → 0.33.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/dist/index.d.ts +8 -11
- package/dist/index.js +305 -184
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -308,6 +308,12 @@ export declare interface ExecutePiTaskOptions {
|
|
|
308
308
|
sandboxConfig?: SandboxConfig;
|
|
309
309
|
/** Host environment variable names to forward into the Pi VM. */
|
|
310
310
|
forwardEnv?: string[];
|
|
311
|
+
/**
|
|
312
|
+
* Runtime profile context defaults. Merged with task.input.context at
|
|
313
|
+
* execution time because the selected runtime profile is known only after
|
|
314
|
+
* claim. Task entries override profile entries with the same slug.
|
|
315
|
+
*/
|
|
316
|
+
runtimeProfileContext?: readonly ContextRef[];
|
|
311
317
|
/**
|
|
312
318
|
* Forwarded to `buildTaskUserPrompt` for per-type builders. Static
|
|
313
319
|
* across tasks. Today no built-in builder needs per-task `extras` —
|
|
@@ -480,14 +486,14 @@ export declare interface InjectedTaskContext {
|
|
|
480
486
|
}
|
|
481
487
|
|
|
482
488
|
/**
|
|
483
|
-
* Resolve
|
|
489
|
+
* Resolve effective runtime context and inject the side effects Pi
|
|
484
490
|
* needs. Safe to call with an empty array — returns an inert result.
|
|
485
491
|
*/
|
|
486
492
|
export declare function injectTaskContext(args: InjectTaskContextArgs): Promise<InjectedTaskContext>;
|
|
487
493
|
|
|
488
494
|
export declare interface InjectTaskContextArgs {
|
|
489
495
|
/** Empty array (the default for any non-eval task) is a no-op. */
|
|
490
|
-
context:
|
|
496
|
+
context: readonly ContextRef[];
|
|
491
497
|
/** Guest filesystem handle. In production this is `managed.vm.fs`. */
|
|
492
498
|
fs: VmFsForContext;
|
|
493
499
|
/** Guest path where the active host workspace is mounted. */
|
|
@@ -922,15 +928,6 @@ declare const Task: Type.TObject<{
|
|
|
922
928
|
|
|
923
929
|
declare type Task = Static<typeof Task>;
|
|
924
930
|
|
|
925
|
-
/** Reusable input fragment for any task type. Soft cap at 5 items. */
|
|
926
|
-
declare const TaskContext: Type.TArray<Type.TObject<{
|
|
927
|
-
slug: Type.TString;
|
|
928
|
-
binding: Type.TUnion<[Type.TLiteral<"skill">, Type.TLiteral<"context_inline">, Type.TLiteral<"prompt_prefix">, Type.TLiteral<"user_inline">]>;
|
|
929
|
-
content: Type.TString;
|
|
930
|
-
}>>;
|
|
931
|
-
|
|
932
|
-
declare type TaskContext = Static<typeof TaskContext>;
|
|
933
|
-
|
|
934
931
|
declare const TaskMessage: Type.TObject<{
|
|
935
932
|
taskId: Type.TString;
|
|
936
933
|
attemptN: Type.TNumber;
|
package/dist/index.js
CHANGED
|
@@ -1965,7 +1965,7 @@ var findLatestRuntimeSlotForAttempt = (options) => (options.client ?? client).ge
|
|
|
1965
1965
|
...options
|
|
1966
1966
|
});
|
|
1967
1967
|
/**
|
|
1968
|
-
* Queue asynchronous deletion of terminal tasks in bulk. By default,
|
|
1968
|
+
* Queue asynchronous deletion of waiting, queued, and terminal tasks in bulk. By default, dispatched, running, unauthorized, missing, and protected tasks are skipped. Set force: true with a reason to delete protected terminal tasks.
|
|
1969
1969
|
*/
|
|
1970
1970
|
var batchDeleteTasks = (options) => (options.client ?? client).delete({
|
|
1971
1971
|
security: [
|
|
@@ -10030,7 +10030,7 @@ _Object_({
|
|
|
10030
10030
|
* (server-side schema check). Self-assessment is a truthful self-rating,
|
|
10031
10031
|
* NOT enforcement — `verification.passed=false` does not block /complete
|
|
10032
10032
|
* and does not affect `acceptedAttemptN`. See
|
|
10033
|
-
* `docs/
|
|
10033
|
+
* `docs/use/tasks-and-runtime.md` for the full producer/judge flow.
|
|
10034
10034
|
*
|
|
10035
10035
|
* **Binding evaluation** (judgment tasks: `assess_brief`, `judge_pack`).
|
|
10036
10036
|
* A separate task whose IS the application of `successCriteria` to
|
|
@@ -18037,7 +18037,7 @@ function createMoltNetTools(config) {
|
|
|
18037
18037
|
const searchEntries = defineTool({
|
|
18038
18038
|
name: "moltnet_search_entries",
|
|
18039
18039
|
label: "Search MoltNet Diary Entries",
|
|
18040
|
-
description: "Hybrid (semantic + lexical) search over diary entries. Optional tags / excludeTags / entryTypes filters AND with the query; the taskFilter shorthand expands into task:* provenance tags so `taskFilter: { taskType: \"fulfill_brief\" }` returns only entries from fulfill_brief attempts. Filters apply server-side before ranking.",
|
|
18040
|
+
description: "Hybrid (semantic + lexical) search over diary entries. Use proactively before non-trivial investigation, code changes, review, or episodic incident capture so prior decisions and recurring failures surface before you act. Do not search randomly: pass taskFilter for task/correlation-local searches and tags or entryTypes for broader prior-knowledge searches. Optional tags / excludeTags / entryTypes filters AND with the query; the taskFilter shorthand expands into task:* provenance tags so `taskFilter: { taskType: \"fulfill_brief\" }` returns only entries from fulfill_brief attempts. Filters apply server-side before ranking.",
|
|
18041
18041
|
parameters: Type.Object({
|
|
18042
18042
|
query: Type.String({ description: "Natural language search query" }),
|
|
18043
18043
|
limit: Type.Optional(Type.Number({ description: "Max results (default 5)" })),
|
|
@@ -18096,12 +18096,18 @@ function createMoltNetTools(config) {
|
|
|
18096
18096
|
const createEntry = defineTool({
|
|
18097
18097
|
name: "moltnet_create_entry",
|
|
18098
18098
|
label: "Create MoltNet Diary Entry",
|
|
18099
|
-
description: "Create a new diary entry to record decisions, findings, incidents, or reflections. During an active task, the entry is forced into the task diary and tagged with the task:* provenance namespace (task:id:<id>, task:type:<type>, task:attempt:<n>, plus task:correlation:<id> when set); an explicit diaryId mismatching the task diary is rejected. Use this tool — NOT `moltnet entry create` / `moltnet entry create-signed` via bash. The CLI path bypasses task-tag auto-injection and leaves entries invisible to taskFilter queries.",
|
|
18099
|
+
description: "Create a new diary entry to record decisions, findings, incidents, or reflections. Before creating an episodic incident entry, first call moltnet_search_entries with the title/root-cause/error/watch-for terms plus taskFilter, tags, or entryTypes filters, then reference close matches instead of creating an isolated duplicate. During an active task, the entry is forced into the task diary and tagged with the task:* provenance namespace (task:id:<id>, task:type:<type>, task:attempt:<n>, plus task:correlation:<id> when set); an explicit diaryId mismatching the task diary is rejected. Use this tool — NOT `moltnet entry create` / `moltnet entry create-signed` via bash. The CLI path bypasses task-tag auto-injection and leaves entries invisible to taskFilter queries.",
|
|
18100
18100
|
parameters: Type.Object({
|
|
18101
18101
|
title: Type.String({ description: "Entry title (concise, descriptive)" }),
|
|
18102
18102
|
content: Type.String({ description: "Entry content (markdown)" }),
|
|
18103
18103
|
tags: Type.Optional(Type.Array(Type.String(), { description: "Tags for categorization" })),
|
|
18104
18104
|
importance: Type.Optional(Type.Number({ description: "Importance 1-10 (default 5)" })),
|
|
18105
|
+
entryType: Type.Optional(Type.Union([
|
|
18106
|
+
Type.Literal("episodic"),
|
|
18107
|
+
Type.Literal("semantic"),
|
|
18108
|
+
Type.Literal("procedural"),
|
|
18109
|
+
Type.Literal("reflection")
|
|
18110
|
+
], { description: "Entry type. Use episodic for incidents, workarounds, bugs, or recurrence evidence; defaults to semantic." })),
|
|
18105
18111
|
diaryId: Type.Optional(Type.String({ description: "Explicit diary id. During an active task, must match the task diary or the call is rejected. Outside a task, overrides the env-derived diary." }))
|
|
18106
18112
|
}),
|
|
18107
18113
|
async execute(_id, params) {
|
|
@@ -18125,7 +18131,8 @@ function createMoltNetTools(config) {
|
|
|
18125
18131
|
title: params.title,
|
|
18126
18132
|
content: params.content,
|
|
18127
18133
|
tags: mergedTags,
|
|
18128
|
-
importance: params.importance ?? 5
|
|
18134
|
+
importance: params.importance ?? 5,
|
|
18135
|
+
...params.entryType ? { entryType: params.entryType } : {}
|
|
18129
18136
|
});
|
|
18130
18137
|
return {
|
|
18131
18138
|
content: [{
|
|
@@ -18135,6 +18142,8 @@ function createMoltNetTools(config) {
|
|
|
18135
18142
|
title: entry.title,
|
|
18136
18143
|
createdAt: entry.createdAt,
|
|
18137
18144
|
diaryId: targetDiaryId,
|
|
18145
|
+
entryType: entry.entryType,
|
|
18146
|
+
importance: entry.importance,
|
|
18138
18147
|
tags: mergedTags
|
|
18139
18148
|
}, null, 2)
|
|
18140
18149
|
}],
|
|
@@ -18514,6 +18523,29 @@ function buildRuntimeInstructor(ctx) {
|
|
|
18514
18523
|
" requires human approval and is unavailable in headless task runs;",
|
|
18515
18524
|
" never use it for routine git/gh.",
|
|
18516
18525
|
"",
|
|
18526
|
+
"## Proactive memory use",
|
|
18527
|
+
"",
|
|
18528
|
+
"- Before non-trivial investigation, debugging, code changes, or review,",
|
|
18529
|
+
" check the task diary for relevant prior knowledge instead of waiting",
|
|
18530
|
+
" for a human to ask. Use `moltnet_diary_tags` for cheap reconnaissance,",
|
|
18531
|
+
" `moltnet_list_entries` when tags or task provenance are known, and",
|
|
18532
|
+
" `moltnet_search_entries` for semantic similarity. Do not search",
|
|
18533
|
+
" randomly: pass `taskFilter` for task-local or correlation-local",
|
|
18534
|
+
" queries, and pass `tags` / `entryTypes` for broader prior-knowledge",
|
|
18535
|
+
" queries using known tags such as `incident`, `decision`, or",
|
|
18536
|
+
" `scope:<area>`. Broaden only after constrained searches miss.",
|
|
18537
|
+
"- Before creating an `episodic` incident entry, you MUST search for",
|
|
18538
|
+
" similar incidents using the proposed title, root cause, error text,",
|
|
18539
|
+
" affected subsystem, and watch-for terms, filtered by `entryTypes:",
|
|
18540
|
+
" [\"episodic\", \"semantic\"]` and any known `scope:*` / task provenance",
|
|
18541
|
+
" tags. If a close prior match exists, do not create an isolated",
|
|
18542
|
+
" duplicate: reference the prior entry in your response or diary content,",
|
|
18543
|
+
" update/link it when the new occurrence adds material evidence, or",
|
|
18544
|
+
" create a new recurrence entry only when the recurrence itself is",
|
|
18545
|
+
" important signal.",
|
|
18546
|
+
"- When you create a recurrence entry, include the prior matching entry",
|
|
18547
|
+
" id(s) in the content and explain what is new about this occurrence.",
|
|
18548
|
+
"",
|
|
18517
18549
|
"## Diary discipline",
|
|
18518
18550
|
"",
|
|
18519
18551
|
`- During this task, every diary entry MUST land in \`${ctx.diaryId}\``,
|
|
@@ -19905,8 +19937,19 @@ async function resolvePersistentSessionManager(args) {
|
|
|
19905
19937
|
//#endregion
|
|
19906
19938
|
//#region ../agent-runtime/src/context-bindings.ts
|
|
19907
19939
|
var PROMPT_SEPARATOR = "\n\n---\n\n";
|
|
19940
|
+
var MAX_MERGED_RUNTIME_CONTEXT_ENTRIES = 10;
|
|
19941
|
+
/**
|
|
19942
|
+
* Merge runtime-profile context defaults with task-scoped context. Profile
|
|
19943
|
+
* entries are defaults; task entries with the same slug override them.
|
|
19944
|
+
*/
|
|
19945
|
+
function mergeRuntimeProfileContext(profileContext, taskContext) {
|
|
19946
|
+
const taskSlugs = new Set(taskContext.map((ref) => ref.slug));
|
|
19947
|
+
const merged = [...profileContext.filter((ref) => !taskSlugs.has(ref.slug)), ...taskContext];
|
|
19948
|
+
if (merged.length > MAX_MERGED_RUNTIME_CONTEXT_ENTRIES) throw new Error(`merged runtime context has ${merged.length} entries; maximum is ${MAX_MERGED_RUNTIME_CONTEXT_ENTRIES}`);
|
|
19949
|
+
return merged;
|
|
19950
|
+
}
|
|
19908
19951
|
/**
|
|
19909
|
-
* Resolve
|
|
19952
|
+
* Resolve runtime context entries into delivered side-effects (skills
|
|
19910
19953
|
* persisted via `deliver.skill`) and prompt fragments
|
|
19911
19954
|
* (`systemPromptPrefix`, `userInlineSuffix`) the caller weaves into the
|
|
19912
19955
|
* built prompt.
|
|
@@ -19926,9 +19969,10 @@ var PROMPT_SEPARATOR = "\n\n---\n\n";
|
|
|
19926
19969
|
* - `user_inline` → content appended to `userInlineSuffix` in
|
|
19927
19970
|
* declared order, same separator.
|
|
19928
19971
|
*
|
|
19929
|
-
* No fetching, no hashing — bytes are inlined in `ContextRef.content
|
|
19930
|
-
*
|
|
19931
|
-
*
|
|
19972
|
+
* No fetching, no hashing — bytes are inlined in `ContextRef.content`.
|
|
19973
|
+
* Task-scoped entries are pinned by the task's `inputCid`; profile-scoped
|
|
19974
|
+
* entries are pinned by the runtime profile revision/source the daemon
|
|
19975
|
+
* resolved. The resolver just dispatches already-selected bytes.
|
|
19932
19976
|
*
|
|
19933
19977
|
* The function is pure with respect to its arguments: file writes are
|
|
19934
19978
|
* confined to the injected `deliver` callback, which makes the
|
|
@@ -19974,12 +20018,13 @@ function formatInlineContextBlock(slug, content) {
|
|
|
19974
20018
|
"### Injected Task Context",
|
|
19975
20019
|
"",
|
|
19976
20020
|
`Context id: \`${slug}\``,
|
|
19977
|
-
"The following raw context was
|
|
19978
|
-
"as task-relevant background that may
|
|
19979
|
-
"when it contains repo- or
|
|
20021
|
+
"The following raw context was selected for this task by its task input",
|
|
20022
|
+
"or runtime profile. Treat it as task-relevant background that may",
|
|
20023
|
+
"override generic coding instincts when it contains repo- or",
|
|
20024
|
+
"workflow-specific constraints.",
|
|
19980
20025
|
"The same content may also be materialized by the runtime under",
|
|
19981
20026
|
"`/moltnet-task-context/context` for tool-based inspection. Do not",
|
|
19982
|
-
"create or rely on workspace mirror files for this
|
|
20027
|
+
"create or rely on workspace mirror files for this runtime context.",
|
|
19983
20028
|
"",
|
|
19984
20029
|
"<context>",
|
|
19985
20030
|
content,
|
|
@@ -20114,6 +20159,22 @@ function buildFinalOutputBlock(opts) {
|
|
|
20114
20159
|
return lines.join("\n");
|
|
20115
20160
|
}
|
|
20116
20161
|
//#endregion
|
|
20162
|
+
//#region ../agent-runtime/src/prompts/proactive-memory.ts
|
|
20163
|
+
function buildProactiveMemoryWorkflowBlock() {
|
|
20164
|
+
return [
|
|
20165
|
+
"Before material work, apply the runtime instructor's proactive memory",
|
|
20166
|
+
"rules instead of waiting for a human prompt. Start with constrained",
|
|
20167
|
+
"diary context: inspect tags/list entries when task provenance or scope",
|
|
20168
|
+
"tags are known, then use `moltnet_search_entries` with `taskFilter`,",
|
|
20169
|
+
"`entryTypes`, and tags. Do not run broad unfiltered searches before",
|
|
20170
|
+
"constrained searches miss.",
|
|
20171
|
+
"",
|
|
20172
|
+
"For incident capture, follow the runtime instructor exactly: search",
|
|
20173
|
+
"for similar episodic/semantic entries first, reference close matches,",
|
|
20174
|
+
"and create a recurrence entry only when the repeat is useful signal."
|
|
20175
|
+
].join("\n");
|
|
20176
|
+
}
|
|
20177
|
+
//#endregion
|
|
20117
20178
|
//#region ../agent-runtime/src/prompts/rubric-common.ts
|
|
20118
20179
|
function renderRubricCriteriaList(rubric) {
|
|
20119
20180
|
return rubric.criteria.map((c, i) => `${i + 1}. **${c.id}** (weight ${c.weight}, scoring: \`${c.scoring}\`) — ${c.description}`).join("\n");
|
|
@@ -20215,6 +20276,12 @@ function buildAssessBriefUserPrompt(input, ctx) {
|
|
|
20215
20276
|
header: "Querying the producer's diary entries",
|
|
20216
20277
|
body: diaryQuery
|
|
20217
20278
|
},
|
|
20279
|
+
{
|
|
20280
|
+
id: "assess_brief.proactive_memory",
|
|
20281
|
+
source: "discipline",
|
|
20282
|
+
header: "Proactive memory use",
|
|
20283
|
+
body: buildProactiveMemoryWorkflowBlock()
|
|
20284
|
+
},
|
|
20218
20285
|
{
|
|
20219
20286
|
id: "assess_brief.workspace",
|
|
20220
20287
|
source: "workspace",
|
|
@@ -20542,11 +20609,13 @@ function buildFreeformUserPrompt(input, ctx) {
|
|
|
20542
20609
|
const suggestedTaskType = input.suggestedTaskType ? [`The proposer suggested task type \`${input.suggestedTaskType}\`.`, "Use it as a hint, not as a contract."].join("\n") : "";
|
|
20543
20610
|
const workflow = [
|
|
20544
20611
|
"1. Clarify the real objective from the brief before acting.",
|
|
20545
|
-
"2.
|
|
20546
|
-
"
|
|
20547
|
-
"
|
|
20612
|
+
"2. Search MoltNet diary memory for prior decisions, incidents, and",
|
|
20613
|
+
" recurring traps relevant to the brief.",
|
|
20614
|
+
"3. Gather enough context to avoid guessing.",
|
|
20615
|
+
"4. Complete the requested work when it is safe and bounded.",
|
|
20616
|
+
"5. If the request reveals a recurring task shape, include a",
|
|
20548
20617
|
" `proposedTaskType` in the final output with a concise rationale.",
|
|
20549
|
-
"
|
|
20618
|
+
"6. If you changed code on a branch, include that branch in",
|
|
20550
20619
|
" `branch` so future continuations can recover git context."
|
|
20551
20620
|
].join("\n");
|
|
20552
20621
|
const sections = [
|
|
@@ -20585,6 +20654,12 @@ function buildFreeformUserPrompt(input, ctx) {
|
|
|
20585
20654
|
header: "Workflow",
|
|
20586
20655
|
body: workflow
|
|
20587
20656
|
},
|
|
20657
|
+
{
|
|
20658
|
+
id: "freeform.proactive_memory",
|
|
20659
|
+
source: "discipline",
|
|
20660
|
+
header: "Proactive memory use",
|
|
20661
|
+
body: buildProactiveMemoryWorkflowBlock()
|
|
20662
|
+
},
|
|
20588
20663
|
{
|
|
20589
20664
|
id: "freeform.verification",
|
|
20590
20665
|
source: "verification",
|
|
@@ -20661,13 +20736,15 @@ function buildFulfillBriefUserPrompt(input, ctx) {
|
|
|
20661
20736
|
].join("\n") : "";
|
|
20662
20737
|
const workflow = [
|
|
20663
20738
|
ctx.workspace?.mode === "dedicated_worktree" ? `1. Use the already-provisioned dedicated worktree branch${ctx.workspace.branch ? ` (\`${ctx.workspace.branch}\`)` : ""}; do not create or switch the primary checkout.` : `1. Create a feature branch (starting prefix suggestion: \`${branchSlug}<short-slug>\`).`,
|
|
20664
|
-
"2.
|
|
20665
|
-
"
|
|
20666
|
-
"
|
|
20667
|
-
"
|
|
20739
|
+
"2. Search MoltNet diary memory for prior decisions, incidents, and",
|
|
20740
|
+
" recurring traps relevant to the brief before changing code.",
|
|
20741
|
+
"3. Understand the problem — read relevant code; do not speculate.",
|
|
20742
|
+
"4. Implement the change. Keep commits small and coherent.",
|
|
20743
|
+
"5. Add tests if applicable.",
|
|
20744
|
+
"6. For every commit, create a signed diary entry first via",
|
|
20668
20745
|
" `moltnet_create_entry` and embed its id in the commit trailer",
|
|
20669
20746
|
" `MoltNet-Diary: <id>` (per the runtime instructor).",
|
|
20670
|
-
"
|
|
20747
|
+
"7. Push the branch and open a PR — run `git push` and `gh pr create`",
|
|
20671
20748
|
" IN the VM with your normal `bash` tool (use the",
|
|
20672
20749
|
" `GH_TOKEN=$(moltnet github token …) gh …` form from the runtime",
|
|
20673
20750
|
" instructor). Do NOT use `moltnet_host_exec` for this; it needs human",
|
|
@@ -20709,6 +20786,12 @@ function buildFulfillBriefUserPrompt(input, ctx) {
|
|
|
20709
20786
|
header: "Workflow",
|
|
20710
20787
|
body: workflow
|
|
20711
20788
|
},
|
|
20789
|
+
{
|
|
20790
|
+
id: "fulfill_brief.proactive_memory",
|
|
20791
|
+
source: "discipline",
|
|
20792
|
+
header: "Proactive memory use",
|
|
20793
|
+
body: buildProactiveMemoryWorkflowBlock()
|
|
20794
|
+
},
|
|
20712
20795
|
{
|
|
20713
20796
|
id: "fulfill_brief.verification",
|
|
20714
20797
|
source: "verification",
|
|
@@ -21024,13 +21107,15 @@ function buildPrReviewUserPrompt(input, ctx) {
|
|
|
21024
21107
|
const workflow = [
|
|
21025
21108
|
"1. Read the subject summary, resources, inspection hints, and any",
|
|
21026
21109
|
" task-specific instructions before scoring.",
|
|
21027
|
-
"2.
|
|
21110
|
+
"2. Search MoltNet diary memory for prior decisions, incidents, and",
|
|
21111
|
+
" recurring review traps relevant to the subject.",
|
|
21112
|
+
"3. Inspect the target artefact directly using the tools and resources the",
|
|
21028
21113
|
" task makes available.",
|
|
21029
|
-
"
|
|
21114
|
+
"4. If you are in a dedicated disposable worktree and need the review target",
|
|
21030
21115
|
" checked out locally, do that work inside this disposable workspace only.",
|
|
21031
|
-
"
|
|
21116
|
+
"5. Apply the rubric strictly. This task is about complexity and",
|
|
21032
21117
|
" reviewability, not correctness or feature desirability.",
|
|
21033
|
-
"
|
|
21118
|
+
"6. Perform any required outward action before emitting the final",
|
|
21034
21119
|
" structured output."
|
|
21035
21120
|
].join("\n");
|
|
21036
21121
|
const taskPromptSection = input.taskPrompt ?? "";
|
|
@@ -21087,6 +21172,12 @@ function buildPrReviewUserPrompt(input, ctx) {
|
|
|
21087
21172
|
header: "Review workflow",
|
|
21088
21173
|
body: workflow
|
|
21089
21174
|
},
|
|
21175
|
+
{
|
|
21176
|
+
id: "pr_review.proactive_memory",
|
|
21177
|
+
source: "discipline",
|
|
21178
|
+
header: "Proactive memory use",
|
|
21179
|
+
body: buildProactiveMemoryWorkflowBlock()
|
|
21180
|
+
},
|
|
21090
21181
|
{
|
|
21091
21182
|
id: "pr_review.task_prompt",
|
|
21092
21183
|
source: "task_input",
|
|
@@ -21256,11 +21347,11 @@ function buildRenderPackUserPrompt(input, ctx) {
|
|
|
21256
21347
|
* `judge_eval_attempt` task(s) grade against their own hidden rubric.
|
|
21257
21348
|
*
|
|
21258
21349
|
* Context delivery is handled by `resolveTaskContext` (see
|
|
21259
|
-
* libs/agent-runtime/src/context-bindings.ts) and
|
|
21260
|
-
* prompt is rendered
|
|
21261
|
-
*
|
|
21262
|
-
*
|
|
21263
|
-
*
|
|
21350
|
+
* libs/agent-runtime/src/context-bindings.ts) and is selected BEFORE this
|
|
21351
|
+
* prompt is rendered. Task-scoped context lives in `input.context`; runtime
|
|
21352
|
+
* profile defaults arrive as `ctx.effectiveRuntimeContext` after the runtime
|
|
21353
|
+
* merges them with task context. This builder only renders context
|
|
21354
|
+
* discipline; it does NOT inline context bytes itself.
|
|
21264
21355
|
*
|
|
21265
21356
|
* Prompt-shape notes (issue #1175, area 1):
|
|
21266
21357
|
* - No `Correlation` section: the agent never acts on it. The id is
|
|
@@ -21278,12 +21369,13 @@ function buildRenderPackUserPrompt(input, ctx) {
|
|
|
21278
21369
|
*/
|
|
21279
21370
|
function buildRunEvalUserPrompt(input, ctx) {
|
|
21280
21371
|
const { scenario, variantLabel, successCriteria } = input;
|
|
21281
|
-
const
|
|
21282
|
-
const
|
|
21372
|
+
const effectiveRuntimeContext = ctx.effectiveRuntimeContext ?? input.context;
|
|
21373
|
+
const hasContext = effectiveRuntimeContext.length > 0;
|
|
21374
|
+
const hasInlineContext = effectiveRuntimeContext.some((entry) => entry.binding === "context_inline");
|
|
21283
21375
|
const header = `# Run Eval Agent\n\nYou are running an evaluation scenario as variant \`${variantLabel}\`.\nTask id: \`${ctx.taskId}\``;
|
|
21284
21376
|
const contextDiscipline = hasContext ? [
|
|
21285
21377
|
"This task includes Injected Task Context supplied by the task",
|
|
21286
|
-
"
|
|
21378
|
+
"input or runtime profile. You MUST inspect it BEFORE you write solution files or",
|
|
21287
21379
|
"draft your final answer — not after.",
|
|
21288
21380
|
"",
|
|
21289
21381
|
"Reconcile every constraint from that context **into the code path",
|
|
@@ -21456,7 +21548,8 @@ function buildTaskUserPrompt(task, ctx) {
|
|
|
21456
21548
|
return buildRunEvalUserPrompt(task.input, {
|
|
21457
21549
|
diaryId: ctx.diaryId,
|
|
21458
21550
|
taskId: ctx.taskId,
|
|
21459
|
-
correlationId: task.correlationId
|
|
21551
|
+
correlationId: task.correlationId,
|
|
21552
|
+
effectiveRuntimeContext: ctx.effectiveRuntimeContext
|
|
21460
21553
|
});
|
|
21461
21554
|
default: throw new Error(`No prompt builder registered for taskType="${task.taskType}"`);
|
|
21462
21555
|
}
|
|
@@ -24929,119 +25022,6 @@ var require_multistream = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
24929
25022
|
module.exports.pino = pino;
|
|
24930
25023
|
})))();
|
|
24931
25024
|
//#endregion
|
|
24932
|
-
//#region src/runtime/inject-task-context.ts
|
|
24933
|
-
/**
|
|
24934
|
-
* Slice 1.5 of #943 — wire the agent-runtime resolver into the
|
|
24935
|
-
* pi-extension execution path.
|
|
24936
|
-
*
|
|
24937
|
-
* `resolveTaskContext` is a pure dispatcher; this module provides the
|
|
24938
|
-
* Gondolin-aware deliverer and the post-resolution shape the
|
|
24939
|
-
* `execute-pi-task` caller needs to splice into pi's setup:
|
|
24940
|
-
*
|
|
24941
|
-
* - `systemPromptPrefix` → fed into `appendSystemPrompt` alongside
|
|
24942
|
-
* the runtime instructor (it IS a system-prompt fragment).
|
|
24943
|
-
* - `userInlineSuffix` → appended to the `buildTaskUserPrompt`
|
|
24944
|
-
* output BEFORE `session.prompt(text)`.
|
|
24945
|
-
* - `skills` → spliced into the `skillsOverride` callback's
|
|
24946
|
-
* return value. pi includes them in `<available_skills>` in the
|
|
24947
|
-
* system prompt; the agent fetches the body on demand via the
|
|
24948
|
-
* Read tool.
|
|
24949
|
-
*
|
|
24950
|
-
* Task-context files are written into a memory-backed VM mount. pi only reads
|
|
24951
|
-
* `<available_skills>` metadata (name, description, location), never the skill
|
|
24952
|
-
* body, so we construct synthetic `Skill` objects pointing at the in-VM path
|
|
24953
|
-
* without ever materialising the file on the host.
|
|
24954
|
-
*/
|
|
24955
|
-
/**
|
|
24956
|
-
* Where in the VM we write task-context bodies — the memory-backed mount
|
|
24957
|
-
* declared in `vm-manager.ts`. See the comment on
|
|
24958
|
-
* `GUEST_TASK_CONTEXT_MOUNT` there for the full rationale (ephemeral by
|
|
24959
|
-
* intent + the worktree symlink interaction with Gondolin's sandbox-escape
|
|
24960
|
-
* protection). The agent's Gondolin Read tool accepts paths under this mount
|
|
24961
|
-
* via `toGuestPath` in `tool-operations.ts`.
|
|
24962
|
-
*/
|
|
24963
|
-
var SKILL_ROOT_IN_VM = `${GUEST_TASK_CONTEXT_MOUNT}/skills`;
|
|
24964
|
-
var INLINE_CONTEXT_ROOT_IN_VM = `${GUEST_TASK_CONTEXT_MOUNT}/context`;
|
|
24965
|
-
/** Bounds borrowed from pi's skill validation; conservative caps so a
|
|
24966
|
-
* malformed SKILL.md doesn't bloat the system prompt. */
|
|
24967
|
-
var MAX_SKILL_NAME = 64;
|
|
24968
|
-
var MAX_SKILL_DESCRIPTION = 1024;
|
|
24969
|
-
/**
|
|
24970
|
-
* Resolve a task's `input.context[]` and inject the side effects pi
|
|
24971
|
-
* needs. Safe to call with an empty array — returns an inert result.
|
|
24972
|
-
*/
|
|
24973
|
-
async function injectTaskContext(args) {
|
|
24974
|
-
const skills = [];
|
|
24975
|
-
args.guestWorkspace;
|
|
24976
|
-
const resolved = await resolveTaskContext({
|
|
24977
|
-
context: args.context,
|
|
24978
|
-
deliver: {
|
|
24979
|
-
skill: async ({ slug, content }) => {
|
|
24980
|
-
const dir = `${SKILL_ROOT_IN_VM}/${slug}`;
|
|
24981
|
-
const filePath = `${dir}/SKILL.md`;
|
|
24982
|
-
await args.fs.mkdir(dir, { recursive: true });
|
|
24983
|
-
await args.fs.writeFile(filePath, content, { mode: 420 });
|
|
24984
|
-
skills.push(buildSyntheticSkill({
|
|
24985
|
-
slug,
|
|
24986
|
-
content,
|
|
24987
|
-
filePath,
|
|
24988
|
-
dir
|
|
24989
|
-
}));
|
|
24990
|
-
},
|
|
24991
|
-
contextFile: async ({ suggestedFileName, content }) => {
|
|
24992
|
-
await args.fs.mkdir(INLINE_CONTEXT_ROOT_IN_VM, { recursive: true });
|
|
24993
|
-
const filePath = `${INLINE_CONTEXT_ROOT_IN_VM}/${suggestedFileName}`;
|
|
24994
|
-
await args.fs.writeFile(filePath, content, { mode: 420 });
|
|
24995
|
-
}
|
|
24996
|
-
}
|
|
24997
|
-
});
|
|
24998
|
-
return {
|
|
24999
|
-
injected: resolved.injected,
|
|
25000
|
-
skills,
|
|
25001
|
-
systemPromptPrefix: resolved.systemPromptPrefix,
|
|
25002
|
-
userInlineSuffix: resolved.userInlineSuffix
|
|
25003
|
-
};
|
|
25004
|
-
}
|
|
25005
|
-
/**
|
|
25006
|
-
* Build a `Skill` object pi will faithfully render in
|
|
25007
|
-
* `<available_skills>`. We extract `name` and `description` from the
|
|
25008
|
-
* skill content's YAML frontmatter using pi's own `parseFrontmatter`
|
|
25009
|
-
* helper (proper YAML, not a regex hack) and fall back to the slug +
|
|
25010
|
-
* a generic description so a SKILL.md without frontmatter still
|
|
25011
|
-
* renders something meaningful.
|
|
25012
|
-
*
|
|
25013
|
-
* Frontmatter parsing is best-effort: a malformed YAML block is
|
|
25014
|
-
* optional metadata, not a reason to fail the task. We swallow parser
|
|
25015
|
-
* errors and fall back to the slug-derived metadata; the skill body
|
|
25016
|
-
* is unaffected.
|
|
25017
|
-
*
|
|
25018
|
-
* pi's `formatSkillsForPrompt` only reads `name`, `description`, and
|
|
25019
|
-
* `filePath` — `sourceInfo`/`baseDir` exist on the type but never
|
|
25020
|
-
* surface in the prompt, so a synthetic `SourceInfo` is enough.
|
|
25021
|
-
*/
|
|
25022
|
-
function buildSyntheticSkill(args) {
|
|
25023
|
-
let fm = {};
|
|
25024
|
-
try {
|
|
25025
|
-
fm = parseFrontmatter(args.content).frontmatter;
|
|
25026
|
-
} catch {}
|
|
25027
|
-
return {
|
|
25028
|
-
name: clip(typeof fm.name === "string" && fm.name.trim().length > 0 ? fm.name.trim() : args.slug, MAX_SKILL_NAME),
|
|
25029
|
-
description: clip(typeof fm.description === "string" && fm.description.trim().length > 0 ? fm.description.trim() : `Task-injected context skill (${args.slug})`, MAX_SKILL_DESCRIPTION),
|
|
25030
|
-
filePath: args.filePath,
|
|
25031
|
-
baseDir: args.dir,
|
|
25032
|
-
sourceInfo: createSyntheticSourceInfo(args.filePath, {
|
|
25033
|
-
source: "moltnet:task-context",
|
|
25034
|
-
scope: "temporary",
|
|
25035
|
-
origin: "top-level",
|
|
25036
|
-
baseDir: args.dir
|
|
25037
|
-
}),
|
|
25038
|
-
disableModelInvocation: fm["disable-model-invocation"] === true
|
|
25039
|
-
};
|
|
25040
|
-
}
|
|
25041
|
-
function clip(s, max) {
|
|
25042
|
-
return s.length > max ? s.slice(0, max) : s;
|
|
25043
|
-
}
|
|
25044
|
-
//#endregion
|
|
25045
25025
|
//#region src/runtime/resolve-prior-context.ts
|
|
25046
25026
|
/**
|
|
25047
25027
|
* Fetch the named attempt's output and project it into the prompt's
|
|
@@ -25228,6 +25208,113 @@ async function withTimeout(promise, timeoutMs, onTimeout) {
|
|
|
25228
25208
|
}
|
|
25229
25209
|
}
|
|
25230
25210
|
//#endregion
|
|
25211
|
+
//#region src/runtime/runtime-context.ts
|
|
25212
|
+
/**
|
|
25213
|
+
* Pi-specific runtime context handling.
|
|
25214
|
+
*
|
|
25215
|
+
* `@themoltnet/agent-runtime` owns generic context semantics: merge profile
|
|
25216
|
+
* defaults with task context, resolve bindings, and produce prompt fragments.
|
|
25217
|
+
* This module owns the Pi/Gondolin boundary: validate effective context for an
|
|
25218
|
+
* attempt, write skill/context files into the VM, and build synthetic Pi Skill
|
|
25219
|
+
* metadata for injected skill bindings.
|
|
25220
|
+
*/
|
|
25221
|
+
/**
|
|
25222
|
+
* Where in the VM we write runtime-context bodies — the memory-backed mount
|
|
25223
|
+
* declared in `vm-manager.ts`. See the comment on
|
|
25224
|
+
* `GUEST_TASK_CONTEXT_MOUNT` there for the full rationale (ephemeral by
|
|
25225
|
+
* intent + the worktree symlink interaction with Gondolin's sandbox-escape
|
|
25226
|
+
* protection). The agent's Gondolin Read tool accepts paths under this mount
|
|
25227
|
+
* via `toGuestPath` in `tool-operations.ts`.
|
|
25228
|
+
*/
|
|
25229
|
+
var SKILL_ROOT_IN_VM = `${GUEST_TASK_CONTEXT_MOUNT}/skills`;
|
|
25230
|
+
var INLINE_CONTEXT_ROOT_IN_VM = `${GUEST_TASK_CONTEXT_MOUNT}/context`;
|
|
25231
|
+
/** Bounds borrowed from pi's skill validation; conservative caps so a
|
|
25232
|
+
* malformed SKILL.md doesn't bloat the system prompt. */
|
|
25233
|
+
var MAX_SKILL_NAME = 64;
|
|
25234
|
+
var MAX_SKILL_DESCRIPTION = 1024;
|
|
25235
|
+
function resolveEffectiveRuntimeContext(args) {
|
|
25236
|
+
const taskContext = args.rawTaskContext === void 0 ? [] : args.rawTaskContext;
|
|
25237
|
+
if (!Check(TaskContext, taskContext)) throw new Error(`task.input.context failed TaskContext validation: ${JSON.stringify([...Errors(TaskContext, taskContext)].slice(0, 3))}`);
|
|
25238
|
+
const profileContext = args.runtimeProfileContext ?? [];
|
|
25239
|
+
if (!Check(TaskContext, profileContext)) throw new Error(`runtime profile context failed TaskContext validation: ${JSON.stringify([...Errors(TaskContext, profileContext)].slice(0, 3))}`);
|
|
25240
|
+
return mergeRuntimeProfileContext(profileContext, taskContext);
|
|
25241
|
+
}
|
|
25242
|
+
/**
|
|
25243
|
+
* Resolve effective runtime context and inject the side effects Pi
|
|
25244
|
+
* needs. Safe to call with an empty array — returns an inert result.
|
|
25245
|
+
*/
|
|
25246
|
+
async function injectRuntimeContext(args) {
|
|
25247
|
+
const skills = [];
|
|
25248
|
+
args.guestWorkspace;
|
|
25249
|
+
const resolved = await resolveTaskContext({
|
|
25250
|
+
context: args.context,
|
|
25251
|
+
deliver: {
|
|
25252
|
+
skill: async ({ slug, content }) => {
|
|
25253
|
+
const dir = `${SKILL_ROOT_IN_VM}/${slug}`;
|
|
25254
|
+
const filePath = `${dir}/SKILL.md`;
|
|
25255
|
+
await args.fs.mkdir(dir, { recursive: true });
|
|
25256
|
+
await args.fs.writeFile(filePath, content, { mode: 420 });
|
|
25257
|
+
skills.push(buildSyntheticSkill({
|
|
25258
|
+
slug,
|
|
25259
|
+
content,
|
|
25260
|
+
filePath,
|
|
25261
|
+
dir
|
|
25262
|
+
}));
|
|
25263
|
+
},
|
|
25264
|
+
contextFile: async ({ suggestedFileName, content }) => {
|
|
25265
|
+
await args.fs.mkdir(INLINE_CONTEXT_ROOT_IN_VM, { recursive: true });
|
|
25266
|
+
const filePath = `${INLINE_CONTEXT_ROOT_IN_VM}/${suggestedFileName}`;
|
|
25267
|
+
await args.fs.writeFile(filePath, content, { mode: 420 });
|
|
25268
|
+
}
|
|
25269
|
+
}
|
|
25270
|
+
});
|
|
25271
|
+
return {
|
|
25272
|
+
injected: resolved.injected,
|
|
25273
|
+
skills,
|
|
25274
|
+
systemPromptPrefix: resolved.systemPromptPrefix,
|
|
25275
|
+
userInlineSuffix: resolved.userInlineSuffix
|
|
25276
|
+
};
|
|
25277
|
+
}
|
|
25278
|
+
/**
|
|
25279
|
+
* Build a `Skill` object pi will faithfully render in
|
|
25280
|
+
* `<available_skills>`. We extract `name` and `description` from the
|
|
25281
|
+
* skill content's YAML frontmatter using pi's own `parseFrontmatter`
|
|
25282
|
+
* helper (proper YAML, not a regex hack) and fall back to the slug +
|
|
25283
|
+
* a generic description so a SKILL.md without frontmatter still
|
|
25284
|
+
* renders something meaningful.
|
|
25285
|
+
*
|
|
25286
|
+
* Frontmatter parsing is best-effort: a malformed YAML block is
|
|
25287
|
+
* optional metadata, not a reason to fail the task. We swallow parser
|
|
25288
|
+
* errors and fall back to the slug-derived metadata; the skill body
|
|
25289
|
+
* is unaffected.
|
|
25290
|
+
*
|
|
25291
|
+
* pi's `formatSkillsForPrompt` only reads `name`, `description`, and
|
|
25292
|
+
* `filePath` — `sourceInfo`/`baseDir` exist on the type but never
|
|
25293
|
+
* surface in the prompt, so a synthetic `SourceInfo` is enough.
|
|
25294
|
+
*/
|
|
25295
|
+
function buildSyntheticSkill(args) {
|
|
25296
|
+
let fm = {};
|
|
25297
|
+
try {
|
|
25298
|
+
fm = parseFrontmatter(args.content).frontmatter;
|
|
25299
|
+
} catch {}
|
|
25300
|
+
return {
|
|
25301
|
+
name: clip(typeof fm.name === "string" && fm.name.trim().length > 0 ? fm.name.trim() : args.slug, MAX_SKILL_NAME),
|
|
25302
|
+
description: clip(typeof fm.description === "string" && fm.description.trim().length > 0 ? fm.description.trim() : `Runtime-injected context skill (${args.slug})`, MAX_SKILL_DESCRIPTION),
|
|
25303
|
+
filePath: args.filePath,
|
|
25304
|
+
baseDir: args.dir,
|
|
25305
|
+
sourceInfo: createSyntheticSourceInfo(args.filePath, {
|
|
25306
|
+
source: "moltnet:runtime-context",
|
|
25307
|
+
scope: "temporary",
|
|
25308
|
+
origin: "top-level",
|
|
25309
|
+
baseDir: args.dir
|
|
25310
|
+
}),
|
|
25311
|
+
disableModelInvocation: fm["disable-model-invocation"] === true
|
|
25312
|
+
};
|
|
25313
|
+
}
|
|
25314
|
+
function clip(s, max) {
|
|
25315
|
+
return s.length > max ? s.slice(0, max) : s;
|
|
25316
|
+
}
|
|
25317
|
+
//#endregion
|
|
25231
25318
|
//#region src/runtime/subagent-tool.ts
|
|
25232
25319
|
var SUBAGENT_SUBMIT_TOOL_NAME = "submit_subagent_output";
|
|
25233
25320
|
var DEFAULT_SUBAGENT_SUBMIT_VALIDATION_RETRIES = 2;
|
|
@@ -25763,6 +25850,46 @@ function resolveSubmitTools(taskType, opts = {}) {
|
|
|
25763
25850
|
};
|
|
25764
25851
|
}
|
|
25765
25852
|
//#endregion
|
|
25853
|
+
//#region src/runtime/task-event-emitter.ts
|
|
25854
|
+
var LOG_TRUNCATE_LIMIT = 4 * 1024;
|
|
25855
|
+
async function emitTaskEvent(input) {
|
|
25856
|
+
try {
|
|
25857
|
+
input.onTurnEvent(input.kind, summarizePayloadForLog(input.kind, input.payload));
|
|
25858
|
+
} catch (err) {
|
|
25859
|
+
process.stderr.write(`[emit] onTurnEvent threw for kind="${input.kind}": ${err instanceof Error ? err.message : String(err)}\n`);
|
|
25860
|
+
}
|
|
25861
|
+
try {
|
|
25862
|
+
await input.reporter.record({
|
|
25863
|
+
kind: input.kind,
|
|
25864
|
+
payload: input.payload
|
|
25865
|
+
});
|
|
25866
|
+
} catch (err) {
|
|
25867
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
25868
|
+
input.log(`executePiTask: reporter.record() failed for task ${input.taskId} attempt ${input.attemptN} kind="${input.kind}": ${detail}`);
|
|
25869
|
+
}
|
|
25870
|
+
}
|
|
25871
|
+
function summarizePayloadForLog(kind, payload) {
|
|
25872
|
+
switch (kind) {
|
|
25873
|
+
case "text_delta": {
|
|
25874
|
+
const delta = payload.delta;
|
|
25875
|
+
return { chars: typeof delta === "string" ? delta.length : 0 };
|
|
25876
|
+
}
|
|
25877
|
+
case "tool_call_start": return { tool: payload.tool_name };
|
|
25878
|
+
case "tool_call_end": return {
|
|
25879
|
+
tool: payload.tool_name,
|
|
25880
|
+
is_error: payload.is_error === true,
|
|
25881
|
+
...payload.is_error === true && payload.result !== void 0 ? { result: payload.result } : {}
|
|
25882
|
+
};
|
|
25883
|
+
case "turn_end": return { stop_reason: payload.stop_reason };
|
|
25884
|
+
case "error": return {
|
|
25885
|
+
phase: payload.phase,
|
|
25886
|
+
message: typeof payload.message === "string" ? payload.message.slice(0, LOG_TRUNCATE_LIMIT) : payload.message
|
|
25887
|
+
};
|
|
25888
|
+
case "info": return Object.fromEntries(Object.entries(payload).map(([k, v]) => [k, typeof v === "string" ? v.slice(0, LOG_TRUNCATE_LIMIT) : v]));
|
|
25889
|
+
default: return payload;
|
|
25890
|
+
}
|
|
25891
|
+
}
|
|
25892
|
+
//#endregion
|
|
25766
25893
|
//#region src/runtime/task-workspace.ts
|
|
25767
25894
|
function prepareTaskWorkspace(task, requestedMountPath, executionPlan) {
|
|
25768
25895
|
const branch = executionPlan?.worktreeBranch ?? null;
|
|
@@ -26131,15 +26258,17 @@ async function executePiTask(claimedTask, reporter, opts) {
|
|
|
26131
26258
|
onTurnEvent = noopTurnEventHandler;
|
|
26132
26259
|
}
|
|
26133
26260
|
else onTurnEvent = opts.onTurnEvent ?? noopTurnEventHandler;
|
|
26134
|
-
const emit = (kind, payload) => {
|
|
26135
|
-
|
|
26136
|
-
onTurnEvent(kind, summarizePayloadForLog(kind, payload));
|
|
26137
|
-
} catch (err) {
|
|
26138
|
-
process.stderr.write(`[emit] onTurnEvent threw for kind="${kind}": ${err instanceof Error ? err.message : String(err)}\n`);
|
|
26139
|
-
}
|
|
26140
|
-
return reporter.record({
|
|
26261
|
+
const emit = async (kind, payload) => {
|
|
26262
|
+
await emitTaskEvent({
|
|
26141
26263
|
kind,
|
|
26142
|
-
payload
|
|
26264
|
+
payload,
|
|
26265
|
+
onTurnEvent,
|
|
26266
|
+
reporter,
|
|
26267
|
+
taskId: task.id,
|
|
26268
|
+
attemptN,
|
|
26269
|
+
log: (message) => {
|
|
26270
|
+
process.stderr.write(`${message}\n`);
|
|
26271
|
+
}
|
|
26143
26272
|
});
|
|
26144
26273
|
};
|
|
26145
26274
|
const emitError = async (phase, message, extra = {}) => {
|
|
@@ -26243,6 +26372,21 @@ async function executePiTask(claimedTask, reporter, opts) {
|
|
|
26243
26372
|
message
|
|
26244
26373
|
});
|
|
26245
26374
|
}
|
|
26375
|
+
const rawContext = task.input.context;
|
|
26376
|
+
let effectiveRuntimeContext;
|
|
26377
|
+
try {
|
|
26378
|
+
effectiveRuntimeContext = resolveEffectiveRuntimeContext({
|
|
26379
|
+
rawTaskContext: rawContext,
|
|
26380
|
+
runtimeProfileContext: opts.runtimeProfileContext
|
|
26381
|
+
});
|
|
26382
|
+
} catch (err) {
|
|
26383
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
26384
|
+
await emit("error", {
|
|
26385
|
+
message,
|
|
26386
|
+
phase: "context_resolution"
|
|
26387
|
+
});
|
|
26388
|
+
return makeFailedOutput("context_resolution_failed", message);
|
|
26389
|
+
}
|
|
26246
26390
|
let taskPrompt;
|
|
26247
26391
|
try {
|
|
26248
26392
|
const assembled = buildTaskUserPrompt(task, {
|
|
@@ -26255,7 +26399,8 @@ async function executePiTask(claimedTask, reporter, opts) {
|
|
|
26255
26399
|
source: executionPlan?.workspaceSeed?.source === "producer" ? "producer_copy" : executionPlan?.workspaceAttachment !== void 0 ? "producer_attachment" : void 0
|
|
26256
26400
|
},
|
|
26257
26401
|
extras: opts.promptExtras,
|
|
26258
|
-
priorContext: resolvedPriorContext
|
|
26402
|
+
priorContext: resolvedPriorContext,
|
|
26403
|
+
effectiveRuntimeContext
|
|
26259
26404
|
});
|
|
26260
26405
|
taskPrompt = assembled.text;
|
|
26261
26406
|
await emit("info", {
|
|
@@ -26272,13 +26417,10 @@ async function executePiTask(claimedTask, reporter, opts) {
|
|
|
26272
26417
|
});
|
|
26273
26418
|
return makeFailedOutput("prompt_build_failed", message);
|
|
26274
26419
|
}
|
|
26275
|
-
const rawContext = task.input.context;
|
|
26276
26420
|
let injectedContext;
|
|
26277
26421
|
try {
|
|
26278
|
-
|
|
26279
|
-
|
|
26280
|
-
injectedContext = await injectTaskContext({
|
|
26281
|
-
context: contextArray,
|
|
26422
|
+
injectedContext = await injectRuntimeContext({
|
|
26423
|
+
context: effectiveRuntimeContext,
|
|
26282
26424
|
fs: managed.vm.fs,
|
|
26283
26425
|
guestWorkspace: managed.guestWorkspace
|
|
26284
26426
|
});
|
|
@@ -26870,27 +27012,6 @@ function wireSessionAbort(cancelSignal, session) {
|
|
|
26870
27012
|
* `task_messages.payload` row. Bodies above 4 KiB are replaced with a
|
|
26871
27013
|
* `{ truncated, original_size }` marker so the JSONL/DB size stays bounded.
|
|
26872
27014
|
*/
|
|
26873
|
-
function summarizePayloadForLog(kind, payload) {
|
|
26874
|
-
switch (kind) {
|
|
26875
|
-
case "text_delta": {
|
|
26876
|
-
const delta = payload.delta;
|
|
26877
|
-
return { chars: typeof delta === "string" ? delta.length : 0 };
|
|
26878
|
-
}
|
|
26879
|
-
case "tool_call_start": return { tool: payload.tool_name };
|
|
26880
|
-
case "tool_call_end": return {
|
|
26881
|
-
tool: payload.tool_name,
|
|
26882
|
-
is_error: payload.is_error === true,
|
|
26883
|
-
...payload.is_error === true && payload.result !== void 0 ? { result: payload.result } : {}
|
|
26884
|
-
};
|
|
26885
|
-
case "turn_end": return { stop_reason: payload.stop_reason };
|
|
26886
|
-
case "error": return {
|
|
26887
|
-
phase: payload.phase,
|
|
26888
|
-
message: typeof payload.message === "string" ? payload.message.slice(0, TRUNCATE_LIMIT) : payload.message
|
|
26889
|
-
};
|
|
26890
|
-
case "info": return Object.fromEntries(Object.entries(payload).map(([k, v]) => [k, typeof v === "string" ? v.slice(0, TRUNCATE_LIMIT) : v]));
|
|
26891
|
-
default: return payload;
|
|
26892
|
-
}
|
|
26893
|
-
}
|
|
26894
27015
|
/**
|
|
26895
27016
|
* Classify a `tool_execution_end` event for telemetry purposes.
|
|
26896
27017
|
*
|
|
@@ -27487,4 +27608,4 @@ function moltnetExtension(pi) {
|
|
|
27487
27608
|
registerMoltnetReflectCommand(pi, state);
|
|
27488
27609
|
}
|
|
27489
27610
|
//#endregion
|
|
27490
|
-
export { HOST_EXEC_DEFAULT_BASE_ENV, activateAgentEnv, buildAgentSession, createGondolinBashOps, createGondolinEditOps, createGondolinReadOps, createGondolinWriteOps, createMoltNetTools, createPiOtelExtension, createPiProviderErrorRetryUi, createPiRetryTriage, createPiTaskExecutor, createSubagentTool, moltnetExtension as default, ensureSnapshot, executePiTask, findMainWorktree, injectTaskContext, loadCredentials, normalizeRetryTriageResult, redactRetryTriageSecrets, resolveTaskWorktreePath, resumeVm, toGuestPath };
|
|
27611
|
+
export { HOST_EXEC_DEFAULT_BASE_ENV, activateAgentEnv, buildAgentSession, createGondolinBashOps, createGondolinEditOps, createGondolinReadOps, createGondolinWriteOps, createMoltNetTools, createPiOtelExtension, createPiProviderErrorRetryUi, createPiRetryTriage, createPiTaskExecutor, createSubagentTool, moltnetExtension as default, ensureSnapshot, executePiTask, findMainWorktree, injectRuntimeContext as injectTaskContext, loadCredentials, normalizeRetryTriageResult, redactRetryTriageSecrets, resolveTaskWorktreePath, resumeVm, toGuestPath };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@themoltnet/pi-extension",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "MoltNet pi extension — sandboxed tool execution in Gondolin VMs with MoltNet identity and persistent memory",
|
|
6
6
|
"keywords": [
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"@earendil-works/gondolin": "^0.9.1",
|
|
37
37
|
"@opentelemetry/api": "^1.9.0",
|
|
38
38
|
"typebox": "^1.2.8",
|
|
39
|
-
"@themoltnet/
|
|
40
|
-
"@themoltnet/
|
|
39
|
+
"@themoltnet/agent-runtime": "0.35.1",
|
|
40
|
+
"@themoltnet/sdk": "0.119.0"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@earendil-works/pi-coding-agent": ">=0.74.0",
|