@tangle-network/agent-runtime 0.259.1 → 0.262.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/{activation-Btw2npV2.js → activation-C0AoYRgS.js} +3 -3
- package/dist/{activation-Btw2npV2.js.map → activation-C0AoYRgS.js.map} +1 -1
- package/dist/{activation-Cus2oZaT.d.ts → activation-CozZXBTg.d.ts} +2 -2
- package/dist/agent.d.ts +2 -2
- package/dist/agent.js +2 -2
- package/dist/{bundle-DXrBPEFw.js → bundle-CvLGRVO-.js} +2 -2
- package/dist/{bundle-DXrBPEFw.js.map → bundle-CvLGRVO-.js.map} +1 -1
- package/dist/candidate-execution/index.js +5 -4
- package/dist/candidate-execution/index.js.map +1 -1
- package/dist/{coordination-driver-BmtrkNPu.js → coordination-driver-COGC8FK2.js} +377 -32
- package/dist/coordination-driver-COGC8FK2.js.map +1 -0
- package/dist/{delegate-DJgmZZKH.js → delegate-BC7Au73v.js} +2 -2
- package/dist/{delegate-DJgmZZKH.js.map → delegate-BC7Au73v.js.map} +1 -1
- package/dist/durable.d.ts +285 -57
- package/dist/durable.js +637 -108
- package/dist/durable.js.map +1 -1
- package/dist/{graph-BKRvWzHx.js → graph-DgODOGWN.js} +4 -3
- package/dist/graph-DgODOGWN.js.map +1 -0
- package/dist/{improvement-cycle-D0Os0Hg_.js → improvement-cycle-DirqO-fX.js} +8 -7
- package/dist/improvement-cycle-DirqO-fX.js.map +1 -0
- package/dist/{index-sGOO254Q.d.ts → index-B8tXCisZ.d.ts} +251 -293
- package/dist/index.d.ts +6 -6
- package/dist/index.js +9 -9
- package/dist/intelligence.d.ts +3 -3
- package/dist/intelligence.js +7 -6
- package/dist/intelligence.js.map +1 -1
- package/dist/kernel.d.ts +4 -4
- package/dist/kernel.js +9 -9
- package/dist/{loop-runner-bin-DAU4rNIL.d.ts → loop-runner-bin-BaZd1XIm.d.ts} +3 -3
- package/dist/{loop-runner-bin-pRlDgm1i.js → loop-runner-bin-C9P1ELVv.js} +3 -3
- package/dist/{loop-runner-bin-pRlDgm1i.js.map → loop-runner-bin-C9P1ELVv.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +6 -6
- package/dist/mcp/index.js +4 -4
- package/dist/{openai-tools-BsqD1_Zr.d.ts → openai-tools-CHwN_S24.d.ts} +2 -2
- package/dist/{prepare-RuaAclli.js → prepare-oHUQdC5-.js} +22 -452
- package/dist/prepare-oHUQdC5-.js.map +1 -0
- package/dist/profile-D3eXNBQV.js +438 -0
- package/dist/profile-D3eXNBQV.js.map +1 -0
- package/dist/profiles.d.ts +2 -2
- package/dist/{protected-model-port-BFhSgMAy.js → protected-model-port-DqF0qDU6.js} +4 -3
- package/dist/{protected-model-port-BFhSgMAy.js.map → protected-model-port-DqF0qDU6.js.map} +1 -1
- package/dist/{provision-supervisor-B9tf4soF.js → provision-supervisor-9FMwo-Es.js} +3 -3
- package/dist/{provision-supervisor-B9tf4soF.js.map → provision-supervisor-9FMwo-Es.js.map} +1 -1
- package/dist/{runtime-DKiucqGX.js → runtime-BXWVW51r.js} +218 -20
- package/dist/runtime-BXWVW51r.js.map +1 -0
- package/dist/{server-DIsiQ6mu.js → server-6g6KFwUC.js} +3 -3
- package/dist/{server-DIsiQ6mu.js.map → server-6g6KFwUC.js.map} +1 -1
- package/dist/{stream-agent-turn-DRTFLphI.d.ts → stream-agent-turn-u28hoxuR.d.ts} +2 -2
- package/dist/{structural-rollout-BIBxgW64.js → structural-rollout-WEfWpjub.js} +2 -2
- package/dist/{structural-rollout-BIBxgW64.js.map → structural-rollout-WEfWpjub.js.map} +1 -1
- package/dist/{substrate-BToFBpfh.d.ts → substrate-BeQiXkpa.d.ts} +2 -2
- package/dist/{supervise-DsQjhLN-.js → supervise-BeAI8-On.js} +295 -51
- package/dist/supervise-BeAI8-On.js.map +1 -0
- package/dist/{supervisor-CJyzUjc7.js → supervisor-BGGvnXvV.js} +243 -24
- package/dist/{supervisor-CJyzUjc7.js.map → supervisor-BGGvnXvV.js.map} +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +14 -14
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/dist/{types-ChewVlpE.d.ts → types-CP3iQ8Ji.d.ts} +376 -4
- package/dist/{workspace-archive-DQGFwvM6.js → workspace-archive-C9lgf77y.js} +11 -11
- package/dist/workspace-archive-C9lgf77y.js.map +1 -0
- package/package.json +5 -5
- package/dist/coordination-driver-BmtrkNPu.js.map +0 -1
- package/dist/graph-BKRvWzHx.js.map +0 -1
- package/dist/improvement-cycle-D0Os0Hg_.js.map +0 -1
- package/dist/prepare-RuaAclli.js.map +0 -1
- package/dist/runtime-DKiucqGX.js.map +0 -1
- package/dist/supervise-DsQjhLN-.js.map +0 -1
- package/dist/workspace-archive-DQGFwvM6.js.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as ConfigError } from "./errors-DodWX-cb.js";
|
|
2
|
-
import { r as supervise } from "./supervise-
|
|
2
|
+
import { r as supervise } from "./supervise-BeAI8-On.js";
|
|
3
3
|
import { agentProfileSchema } from "@tangle-network/agent-interface";
|
|
4
4
|
import { computeFindingId, makeFinding } from "@tangle-network/agent-eval";
|
|
5
5
|
//#region src/runtime/supervise/authoring.ts
|
|
@@ -207,4 +207,4 @@ async function delegate(intent, opts) {
|
|
|
207
207
|
//#endregion
|
|
208
208
|
export { defaultProfileRichnessThresholds as a, assessAuthoredProfile as i, delegate as n, profileRichnessFinding as o, asAuthoredProfile as r, supervisorInstructions as s, defaultDelegateBudget as t };
|
|
209
209
|
|
|
210
|
-
//# sourceMappingURL=delegate-
|
|
210
|
+
//# sourceMappingURL=delegate-BC7Au73v.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delegate-DJgmZZKH.js","names":[],"sources":["../src/runtime/supervise/authoring.ts","../src/runtime/supervise/delegate.ts"],"sourcesContent":["/**\n *\n * The supervisor's intelligence is AUTHORING the agents it spawns — not pressing buttons.\n *\n * Every agent here is three things: instructions (system prompt), tools, and a model — its\n * `AgentProfile`. The supervisor's job is to WRITE those profiles: read the task, decompose it,\n * and for each sub-task author a tailored worker recipe. `supervisorInstructions` is the how-to the\n * supervisor reads; canonical Runtime executors materialize the resulting profile.\n *\n * The skill is the single OPTIMIZABLE surface: edit it → the supervisor designs better agents.\n * That is the self-improvement lever (the prompt/skill lever), not the execution plumbing.\n *\n * @experimental\n */\n\nimport { type AnalystFinding, computeFindingId, makeFinding } from '@tangle-network/agent-eval'\nimport {\n type AgentProfile,\n type AgentProfilePrompt,\n agentProfileSchema,\n} from '@tangle-network/agent-interface'\n\n/** What the supervisor AUTHORS per sub-task: one complete canonical profile whose name and\n * task-specific system prompt are present. Every other `AgentProfile` axis is preserved exactly. */\nexport type AuthoredProfile = AgentProfile & {\n readonly name: string\n readonly prompt: AgentProfilePrompt & { readonly systemPrompt: string }\n}\n\n/** Narrow an untyped `spawn_worker` profile argument to an `AuthoredProfile`, or null if the\n * supervisor failed to author one (empty/placeholder profile — a skill violation worth catching). */\nexport function asAuthoredProfile(raw: unknown): AuthoredProfile | null {\n const parsed = agentProfileSchema.safeParse(raw)\n if (!parsed.success) return null\n const systemPrompt = parsed.data.prompt?.systemPrompt\n if (typeof systemPrompt !== 'string' || systemPrompt.trim().length === 0) return null\n return {\n ...parsed.data,\n name:\n typeof parsed.data.name === 'string' && parsed.data.name.length > 0\n ? parsed.data.name\n : 'worker',\n prompt: { ...parsed.data.prompt, systemPrompt },\n }\n}\n\n/** The supervisor skill: an explicit profile-authoring instruction, never an implicit Runtime\n * policy. Editing this text changes how a profile designs the descendants it spawns. */\nexport function supervisorInstructions(opts?: { goal?: string }): string {\n return [\n 'Your delegation craft is AUTHORING: a spawned worker is exactly as good as the profile you write.',\n '',\n 'For the task you are given:',\n '1. DECOMPOSE it into the smallest set of sub-tasks a single focused worker can each deliver.',\n '2. For EACH sub-task, AUTHOR a worker by calling spawn_worker with a COMPLETE `profile`:',\n ' • name and description: who this specialist is and why it exists.',\n ' • prompt.systemPrompt: rich instructions for THIS sub-task — exact output, process, evidence, and what \"done\" means.',\n ' • model.default, model.reasoningEffort, and harness: choose the execution system deliberately when the task benefits from it.',\n ' • tools, mcp, resources.skills/files/instructions, hooks, subagents, permissions, and modes: grant or attach every capability the worker needs; omit an axis only when it is intentionally unnecessary.',\n ' • tools.agent_runtime_coordination_spawn_worker: true ONLY when this child should author and drive descendants. Add only the other agent_runtime_coordination_<verb> tools it will call, such as await_event or steer_agent.',\n ' • A child with spawn_worker MUST carry this complete profile-authoring instruction as an immutable resources.skills entry with resources.failOnError: true, so it can author its own descendants from the same contract.',\n ' • metadata may describe the work, but it never grants recursion or selects a Runtime execution path.',\n ' NEVER spawn a worker with an empty profile. The quality of the worker IS the quality of the profile you write.',\n \"3. await_event (kinds:['settled']) to collect each worker. Its result says valid:true only if the deployable check passed.\",\n '4. If a worker did NOT deliver, AUTHOR A NEW profile whose prompt.systemPrompt names the SPECIFIC failure and how to fix it — never just retry the same profile.',\n \"5. read_journal to re-read YOUR OWN record before you decide the next move: every spawn you made, every settle, every question and answer, every steer, every analyst finding — oldest first, this node only, including what you did before a restart. Use it to see what you already tried instead of trying it again. It is paged: pass the returned nextRow as the next call's sinceRow, narrow with kinds, and raise limit/maxBytes only as far as you will actually read. A truncated:true page means a bound cut it short — keep paging before you conclude you have read everything.\",\n '6. AUTHOR YOUR OWN LENS when the questions you can already ask of a settled trace do not cover the failure you are chasing: define_analyst takes an id, a description, an area, the question in your own words, the instructions for answering it with trace evidence, and the smallest toolGroup that can answer it (model is the seat it runs on; omit it for the run default). It is DATA, never code. Then run_analyst it on any settled worker like a lens the run shipped with, and read the finding. list_analysts shows what you have. Define a lens when you need a different question asked — not a second copy of a question already on the menu.',\n '7. EVERY refusal you get back carries a `reason` naming the exact unmet condition. Read it and change that condition — a spawn refused for max-live-workers needs an await_event, an invalid-profile needs the named field fixed, a submit_result refused because the check THREW is a broken check to report, not a result to resubmit. Never repeat a call that was refused without changing what it was refused for.',\n '8. ask_parent ONLY when you genuinely cannot decide, and then READ ITS OUTCOME. \"queued-for-parent\" means an inbox above you now holds the question. \"no-parent\" means no inbox above you is configured to receive it: the question is still on the run record for anyone watching, but nothing will route an answer back to you, so do not block. Decide it with answer_question, or answer_question with deferReason to record that it stays open, and carry on — a blocking question left undecided also refuses your stop.',\n '9. Stop (reply with no tool call) once the work is delivered.',\n ...(opts?.goal ? ['', `The goal: ${opts.goal}`] : []),\n ].join('\\n')\n}\n\n// ── Profile-richness gate ────────────────────────────────────────────────────\n//\n// The supervisor's product is the worker PROFILE it authors. The failure mode the existing\n// gates miss: `asAuthoredProfile` / `local-harness` only reject a FULLY EMPTY system prompt —\n// a two-sentence stub passes. `assessAuthoredProfile` OBSERVES the authored artifact (it reads\n// no judge verdict, so it steers cleanly past `assertTraceDerivedFindings`) and flags THIN:\n// a short/few-line system prompt, OR no tools, OR no skills, OR no MCP when the task needs one.\n// It emits a real `AnalystFinding` so it rides the SAME coordination bus the driver pulls via\n// `await_event({kinds:['finding']})` — the supervisor can self-correct and re-author richer.\n\n/** Thresholds below which a system prompt is treated as a thin stub. Tunable per call. */\nexport interface ProfileRichnessThresholds {\n /** A prompt shorter than this many characters is thin (default 600). */\n readonly minSystemPromptChars: number\n /** A prompt with fewer than this many non-blank lines is thin (default 6). */\n readonly minSystemPromptLines: number\n}\n\n/** Default thresholds for `ProfileRichnessThresholds` — 600 chars / 6 lines minimum system prompt. */\nexport const defaultProfileRichnessThresholds: ProfileRichnessThresholds = {\n minSystemPromptChars: 600,\n minSystemPromptLines: 6,\n}\n\n/** Per-field verdict on one authored profile — the raw material the bench renders + scores. */\nexport interface ProfileRichness {\n readonly name: string\n /** The resolved system prompt (canonical `prompt.systemPrompt`, the sandbox `prompt.system`\n * convention, or a bare-string prompt — whichever the author used). */\n readonly systemPrompt: string\n readonly systemPromptChars: number\n readonly systemPromptLines: number\n readonly sentenceCount: number\n readonly hasDescription: boolean\n readonly hasTools: boolean\n readonly hasSkills: boolean\n readonly hasMcp: boolean\n readonly hasSubagents: boolean\n /** 0..1 — fraction of richness signals present (prompt-depth + the four levers). */\n readonly richness: number\n /** True when the supervisor authored a stub instead of a real profile. */\n readonly thin: boolean\n /** The specific reasons it is thin (empty when rich) — used in the finding's action. */\n readonly reasons: string[]\n}\n\n/** Read the system prompt from any authored shape: canonical `prompt.systemPrompt`, the sandbox\n * `prompt.system` convention, or a bare-string `prompt`. */\nfunction resolveSystemPrompt(profile: AgentProfile): string {\n const pr = (profile as { prompt?: unknown }).prompt\n if (typeof pr === 'string') return pr\n if (pr && typeof pr === 'object') {\n const o = pr as { systemPrompt?: unknown; system?: unknown }\n if (typeof o.systemPrompt === 'string') return o.systemPrompt\n if (typeof o.system === 'string') return o.system\n }\n return ''\n}\n\n/** OBSERVE one authored `AgentProfile` and score its richness (no judge verdict is read). The task\n * context (`needsMcp`) lets a domain say \"this work needs a data/tool MCP\" so a missing MCP counts. */\nexport function assessAuthoredProfile(\n profile: AgentProfile,\n opts?: { needsMcp?: boolean; thresholds?: Partial<ProfileRichnessThresholds> },\n): ProfileRichness {\n const th = { ...defaultProfileRichnessThresholds, ...(opts?.thresholds ?? {}) }\n const systemPrompt = resolveSystemPrompt(profile)\n const trimmed = systemPrompt.trim()\n const systemPromptChars = trimmed.length\n const systemPromptLines = trimmed\n ? trimmed.split('\\n').filter((l) => l.trim().length > 0).length\n : 0\n const sentenceCount = trimmed\n ? (trimmed.match(/[.!?](\\s|$)/g) ?? []).length || (trimmed ? 1 : 0)\n : 0\n const hasDescription =\n typeof profile.description === 'string' && profile.description.trim().length > 0\n const tools = (profile as { tools?: Record<string, unknown> }).tools\n const hasTools = !!tools && Object.keys(tools).length > 0\n const skills = (profile.resources as { skills?: unknown[] } | undefined)?.skills\n const hasSkills = Array.isArray(skills) && skills.length > 0\n const mcp = (profile as { mcp?: Record<string, unknown> }).mcp\n const hasMcp = !!mcp && Object.keys(mcp).length > 0\n const subagents = (profile as { subagents?: Record<string, unknown> }).subagents\n const hasSubagents = !!subagents && Object.keys(subagents).length > 0\n\n const reasons: string[] = []\n const promptThin =\n systemPromptChars < th.minSystemPromptChars || systemPromptLines < th.minSystemPromptLines\n if (promptThin)\n reasons.push(\n `system prompt is thin (${systemPromptChars} chars, ${systemPromptLines} lines; need ≥${th.minSystemPromptChars} chars and ≥${th.minSystemPromptLines} lines)`,\n )\n if (!hasTools)\n reasons.push('no tools granted (a worker can only act through the tools you grant it)')\n if (!hasSkills) reasons.push('no skills attached (no reusable how-to notes injected)')\n if (opts?.needsMcp && !hasMcp) reasons.push('no MCP server, but the task needs data/tool access')\n\n // Richness = fraction of signals present. Prompt-depth is one signal; the four levers are the rest.\n const signals = [!promptThin, hasTools, hasSkills, hasDescription, opts?.needsMcp ? hasMcp : true]\n const richness = signals.filter(Boolean).length / signals.length\n // THIN ⟺ the prompt is a stub OR the worker has no levers at all (no tools AND no skills AND no mcp).\n const thin = promptThin || (!hasTools && !hasSkills && !hasMcp)\n\n return {\n name: profile.name ?? 'worker',\n systemPrompt,\n systemPromptChars,\n systemPromptLines,\n sentenceCount,\n hasDescription,\n hasTools,\n hasSkills,\n hasMcp,\n hasSubagents,\n richness,\n thin,\n reasons,\n }\n}\n\n/** Turn a {@link ProfileRichness} verdict into a bus-routable `AnalystFinding` (area `profile-quality`).\n * Severity scales with thinness; the recommended action names the MISSING lever so the supervisor can\n * re-author. `subject` = the worker name so per-worker findings diff cleanly across re-authors. */\nexport function profileRichnessFinding(\n richness: ProfileRichness,\n opts?: { analystId?: string; runId?: string },\n): AnalystFinding {\n const analyst_id = opts?.analystId ?? 'profile-richness'\n const subject = richness.name\n const claim = richness.thin\n ? `Worker \"${richness.name}\" was authored as a THIN profile: ${richness.reasons.join('; ')}.`\n : `Worker \"${richness.name}\" was authored as a rich profile (richness ${(richness.richness * 100).toFixed(0)}%).`\n const severity: AnalystFinding['severity'] = richness.thin\n ? richness.richness < 0.25\n ? 'high'\n : 'medium'\n : 'info'\n return makeFinding({\n analyst_id,\n severity,\n area: 'profile-quality',\n claim,\n subject,\n confidence: 0.9,\n evidence_refs: [\n {\n kind: 'metric',\n uri: `profile:${subject}`,\n excerpt: `chars=${richness.systemPromptChars} lines=${richness.systemPromptLines} tools=${richness.hasTools} skills=${richness.hasSkills} mcp=${richness.hasMcp} richness=${richness.richness.toFixed(2)}`,\n },\n ],\n ...(richness.thin\n ? { recommended_action: `Re-author \"${richness.name}\" with: ${richness.reasons.join('; ')}.` }\n : {}),\n id_basis: computeFindingId({\n analyst_id,\n area: 'profile-quality',\n subject,\n claim: `richness:${richness.thin ? 'thin' : 'rich'}`,\n }),\n })\n}\n","/**\n *\n * `delegate` — the one generic delegation verb. You hand it an INTENT (what you want done) and it\n * hands that intent to a default AUTHORING supervisor: a router-brained supervisor whose standing\n * instruction is `supervisorInstructions()` (the authoring-agent-profiles skill). The supervisor\n * DECOMPOSES the intent and AUTHORS the worker profile it needs per sub-task — there is NO hardcoded\n * coder/researcher profile here. That is the whole point: `delegate('fix the failing test', …)` and\n * `delegate('research X and cite sources', …)` route through the SAME front door; the supervisor\n * writes a code-shaped or research-shaped worker on its own.\n *\n * It is a thin wrapper over `supervise()` — the one front door — so the conserved-budget pool, the\n * completion oracle (`deliverable`), the coordination toolbox, and equal-compute accounting all come\n * for free; nothing is hand-rolled. The result is `supervise()`'s `SupervisedResult` returned\n * UNCHANGED, so its `spentTotal` (`{ iterations, tokens, usd, ms }`) rides straight back to the\n * caller on BOTH paths — a `winner` carries the delivered worker's spend, a `no-winner` carries the\n * spend incurred before it failed. That cost channel means a `delegate()` caller always learns what\n * the delegation actually spent.\n *\n * @experimental\n */\n\nimport { ConfigError } from '../../errors'\nimport type { RouterTransportConfig } from '../router-client'\nimport type { DeliverableSpec } from './completion-gate'\nimport type { ExecutorConfig } from './runtime'\nimport { supervise } from './supervise'\nimport type { SupervisorProfile } from './supervisor-agent'\nimport type { Budget, SupervisedResult } from './types'\n\n/** The conserved pool a `delegate()` call applies when the caller does not pass its own `budget`.\n * A modest token ceiling + a small iteration ceiling — generous enough for a few-worker decompose,\n * bounded enough that an unsupervised intent cannot run away. Callers override via `opts.budget`. */\nexport const defaultDelegateBudget: Budget = { maxIterations: 50, maxTokens: 200_000 }\n\n/** Inputs to {@link delegate}. The intent is the first positional arg; everything here is optional\n * with explicit execution identity, so the common call names one exact supervisor profile. */\nexport interface DelegateOptions<Out = unknown> {\n /** The completion oracle (settled ⟺ delivered) the authored workers settle against. Strongly\n * recommended — without it the supervisor trusts a worker's self-report. For a code intent,\n * `patchDelivered()` is the canonical example; for a free-form answer, a content check. */\n readonly deliverable?: DeliverableSpec<Out>\n /** WHERE the authored workers run — the worker-execution backend (`router-tools` / `sandbox` /\n * `cli-worktree` / …). The supervisor authors the worker PROFILE; this is the substrate it runs\n * on. Provide this OR `makeWorkerAgent`-style wiring through `supervise()` is unavailable. */\n readonly backend?: ExecutorConfig\n /** The conserved compute pool for the whole delegation. Defaults to {@link defaultDelegateBudget}. */\n readonly budget?: Budget\n /** Exact executable authoring supervisor. Model, prompt, harness, and provider live here. */\n readonly supervisorProfile: SupervisorProfile\n /** Router endpoint/auth for a `cli-base` supervisor; contains no behavioral settings. */\n readonly router: RouterTransportConfig\n /** Restrict the run to this subset of models (forwarded to `supervise()`). */\n readonly allowedModels?: readonly string[]\n readonly runId?: string\n}\n\n/**\n * Delegate an INTENT to a default authoring supervisor and return its `SupervisedResult` unchanged.\n *\n * The supervisor authors + spawns whatever worker the intent needs over the conserved-budget pool;\n * `result.spentTotal` reports what the whole delegation actually cost. A `winner` result carries the\n * authored worker's delivered output; a `no-winner` result names why (never a fabricated success).\n */\nexport async function delegate<Out = unknown>(\n intent: string,\n opts: DelegateOptions<Out>,\n): Promise<SupervisedResult<Out>> {\n if (typeof intent !== 'string' || intent.trim().length === 0) {\n throw new ConfigError('delegate: `intent` must be a non-empty string')\n }\n return supervise(opts.supervisorProfile, intent, {\n budget: opts.budget ?? defaultDelegateBudget,\n ...(opts.backend ? { backend: opts.backend } : {}),\n ...(opts.deliverable ? { deliverable: opts.deliverable as DeliverableSpec<unknown> } : {}),\n router: opts.router,\n ...(opts.allowedModels ? { allowedModels: opts.allowedModels } : {}),\n ...(opts.runId ? { runId: opts.runId } : {}),\n }) as Promise<SupervisedResult<Out>>\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"delegate-BC7Au73v.js","names":[],"sources":["../src/runtime/supervise/authoring.ts","../src/runtime/supervise/delegate.ts"],"sourcesContent":["/**\n *\n * The supervisor's intelligence is AUTHORING the agents it spawns — not pressing buttons.\n *\n * Every agent here is three things: instructions (system prompt), tools, and a model — its\n * `AgentProfile`. The supervisor's job is to WRITE those profiles: read the task, decompose it,\n * and for each sub-task author a tailored worker recipe. `supervisorInstructions` is the how-to the\n * supervisor reads; canonical Runtime executors materialize the resulting profile.\n *\n * The skill is the single OPTIMIZABLE surface: edit it → the supervisor designs better agents.\n * That is the self-improvement lever (the prompt/skill lever), not the execution plumbing.\n *\n * @experimental\n */\n\nimport { type AnalystFinding, computeFindingId, makeFinding } from '@tangle-network/agent-eval'\nimport {\n type AgentProfile,\n type AgentProfilePrompt,\n agentProfileSchema,\n} from '@tangle-network/agent-interface'\n\n/** What the supervisor AUTHORS per sub-task: one complete canonical profile whose name and\n * task-specific system prompt are present. Every other `AgentProfile` axis is preserved exactly. */\nexport type AuthoredProfile = AgentProfile & {\n readonly name: string\n readonly prompt: AgentProfilePrompt & { readonly systemPrompt: string }\n}\n\n/** Narrow an untyped `spawn_worker` profile argument to an `AuthoredProfile`, or null if the\n * supervisor failed to author one (empty/placeholder profile — a skill violation worth catching). */\nexport function asAuthoredProfile(raw: unknown): AuthoredProfile | null {\n const parsed = agentProfileSchema.safeParse(raw)\n if (!parsed.success) return null\n const systemPrompt = parsed.data.prompt?.systemPrompt\n if (typeof systemPrompt !== 'string' || systemPrompt.trim().length === 0) return null\n return {\n ...parsed.data,\n name:\n typeof parsed.data.name === 'string' && parsed.data.name.length > 0\n ? parsed.data.name\n : 'worker',\n prompt: { ...parsed.data.prompt, systemPrompt },\n }\n}\n\n/** The supervisor skill: an explicit profile-authoring instruction, never an implicit Runtime\n * policy. Editing this text changes how a profile designs the descendants it spawns. */\nexport function supervisorInstructions(opts?: { goal?: string }): string {\n return [\n 'Your delegation craft is AUTHORING: a spawned worker is exactly as good as the profile you write.',\n '',\n 'For the task you are given:',\n '1. DECOMPOSE it into the smallest set of sub-tasks a single focused worker can each deliver.',\n '2. For EACH sub-task, AUTHOR a worker by calling spawn_worker with a COMPLETE `profile`:',\n ' • name and description: who this specialist is and why it exists.',\n ' • prompt.systemPrompt: rich instructions for THIS sub-task — exact output, process, evidence, and what \"done\" means.',\n ' • model.default, model.reasoningEffort, and harness: choose the execution system deliberately when the task benefits from it.',\n ' • tools, mcp, resources.skills/files/instructions, hooks, subagents, permissions, and modes: grant or attach every capability the worker needs; omit an axis only when it is intentionally unnecessary.',\n ' • tools.agent_runtime_coordination_spawn_worker: true ONLY when this child should author and drive descendants. Add only the other agent_runtime_coordination_<verb> tools it will call, such as await_event or steer_agent.',\n ' • A child with spawn_worker MUST carry this complete profile-authoring instruction as an immutable resources.skills entry with resources.failOnError: true, so it can author its own descendants from the same contract.',\n ' • metadata may describe the work, but it never grants recursion or selects a Runtime execution path.',\n ' NEVER spawn a worker with an empty profile. The quality of the worker IS the quality of the profile you write.',\n \"3. await_event (kinds:['settled']) to collect each worker. Its result says valid:true only if the deployable check passed.\",\n '4. If a worker did NOT deliver, AUTHOR A NEW profile whose prompt.systemPrompt names the SPECIFIC failure and how to fix it — never just retry the same profile.',\n \"5. read_journal to re-read YOUR OWN record before you decide the next move: every spawn you made, every settle, every question and answer, every steer, every analyst finding — oldest first, this node only, including what you did before a restart. Use it to see what you already tried instead of trying it again. It is paged: pass the returned nextRow as the next call's sinceRow, narrow with kinds, and raise limit/maxBytes only as far as you will actually read. A truncated:true page means a bound cut it short — keep paging before you conclude you have read everything.\",\n '6. AUTHOR YOUR OWN LENS when the questions you can already ask of a settled trace do not cover the failure you are chasing: define_analyst takes an id, a description, an area, the question in your own words, the instructions for answering it with trace evidence, and the smallest toolGroup that can answer it (model is the seat it runs on; omit it for the run default). It is DATA, never code. Then run_analyst it on any settled worker like a lens the run shipped with, and read the finding. list_analysts shows what you have. Define a lens when you need a different question asked — not a second copy of a question already on the menu.',\n '7. EVERY refusal you get back carries a `reason` naming the exact unmet condition. Read it and change that condition — a spawn refused for max-live-workers needs an await_event, an invalid-profile needs the named field fixed, a submit_result refused because the check THREW is a broken check to report, not a result to resubmit. Never repeat a call that was refused without changing what it was refused for.',\n '8. ask_parent ONLY when you genuinely cannot decide, and then READ ITS OUTCOME. \"queued-for-parent\" means an inbox above you now holds the question. \"no-parent\" means no inbox above you is configured to receive it: the question is still on the run record for anyone watching, but nothing will route an answer back to you, so do not block. Decide it with answer_question, or answer_question with deferReason to record that it stays open, and carry on — a blocking question left undecided also refuses your stop.',\n '9. Stop (reply with no tool call) once the work is delivered.',\n ...(opts?.goal ? ['', `The goal: ${opts.goal}`] : []),\n ].join('\\n')\n}\n\n// ── Profile-richness gate ────────────────────────────────────────────────────\n//\n// The supervisor's product is the worker PROFILE it authors. The failure mode the existing\n// gates miss: `asAuthoredProfile` / `local-harness` only reject a FULLY EMPTY system prompt —\n// a two-sentence stub passes. `assessAuthoredProfile` OBSERVES the authored artifact (it reads\n// no judge verdict, so it steers cleanly past `assertTraceDerivedFindings`) and flags THIN:\n// a short/few-line system prompt, OR no tools, OR no skills, OR no MCP when the task needs one.\n// It emits a real `AnalystFinding` so it rides the SAME coordination bus the driver pulls via\n// `await_event({kinds:['finding']})` — the supervisor can self-correct and re-author richer.\n\n/** Thresholds below which a system prompt is treated as a thin stub. Tunable per call. */\nexport interface ProfileRichnessThresholds {\n /** A prompt shorter than this many characters is thin (default 600). */\n readonly minSystemPromptChars: number\n /** A prompt with fewer than this many non-blank lines is thin (default 6). */\n readonly minSystemPromptLines: number\n}\n\n/** Default thresholds for `ProfileRichnessThresholds` — 600 chars / 6 lines minimum system prompt. */\nexport const defaultProfileRichnessThresholds: ProfileRichnessThresholds = {\n minSystemPromptChars: 600,\n minSystemPromptLines: 6,\n}\n\n/** Per-field verdict on one authored profile — the raw material the bench renders + scores. */\nexport interface ProfileRichness {\n readonly name: string\n /** The resolved system prompt (canonical `prompt.systemPrompt`, the sandbox `prompt.system`\n * convention, or a bare-string prompt — whichever the author used). */\n readonly systemPrompt: string\n readonly systemPromptChars: number\n readonly systemPromptLines: number\n readonly sentenceCount: number\n readonly hasDescription: boolean\n readonly hasTools: boolean\n readonly hasSkills: boolean\n readonly hasMcp: boolean\n readonly hasSubagents: boolean\n /** 0..1 — fraction of richness signals present (prompt-depth + the four levers). */\n readonly richness: number\n /** True when the supervisor authored a stub instead of a real profile. */\n readonly thin: boolean\n /** The specific reasons it is thin (empty when rich) — used in the finding's action. */\n readonly reasons: string[]\n}\n\n/** Read the system prompt from any authored shape: canonical `prompt.systemPrompt`, the sandbox\n * `prompt.system` convention, or a bare-string `prompt`. */\nfunction resolveSystemPrompt(profile: AgentProfile): string {\n const pr = (profile as { prompt?: unknown }).prompt\n if (typeof pr === 'string') return pr\n if (pr && typeof pr === 'object') {\n const o = pr as { systemPrompt?: unknown; system?: unknown }\n if (typeof o.systemPrompt === 'string') return o.systemPrompt\n if (typeof o.system === 'string') return o.system\n }\n return ''\n}\n\n/** OBSERVE one authored `AgentProfile` and score its richness (no judge verdict is read). The task\n * context (`needsMcp`) lets a domain say \"this work needs a data/tool MCP\" so a missing MCP counts. */\nexport function assessAuthoredProfile(\n profile: AgentProfile,\n opts?: { needsMcp?: boolean; thresholds?: Partial<ProfileRichnessThresholds> },\n): ProfileRichness {\n const th = { ...defaultProfileRichnessThresholds, ...(opts?.thresholds ?? {}) }\n const systemPrompt = resolveSystemPrompt(profile)\n const trimmed = systemPrompt.trim()\n const systemPromptChars = trimmed.length\n const systemPromptLines = trimmed\n ? trimmed.split('\\n').filter((l) => l.trim().length > 0).length\n : 0\n const sentenceCount = trimmed\n ? (trimmed.match(/[.!?](\\s|$)/g) ?? []).length || (trimmed ? 1 : 0)\n : 0\n const hasDescription =\n typeof profile.description === 'string' && profile.description.trim().length > 0\n const tools = (profile as { tools?: Record<string, unknown> }).tools\n const hasTools = !!tools && Object.keys(tools).length > 0\n const skills = (profile.resources as { skills?: unknown[] } | undefined)?.skills\n const hasSkills = Array.isArray(skills) && skills.length > 0\n const mcp = (profile as { mcp?: Record<string, unknown> }).mcp\n const hasMcp = !!mcp && Object.keys(mcp).length > 0\n const subagents = (profile as { subagents?: Record<string, unknown> }).subagents\n const hasSubagents = !!subagents && Object.keys(subagents).length > 0\n\n const reasons: string[] = []\n const promptThin =\n systemPromptChars < th.minSystemPromptChars || systemPromptLines < th.minSystemPromptLines\n if (promptThin)\n reasons.push(\n `system prompt is thin (${systemPromptChars} chars, ${systemPromptLines} lines; need ≥${th.minSystemPromptChars} chars and ≥${th.minSystemPromptLines} lines)`,\n )\n if (!hasTools)\n reasons.push('no tools granted (a worker can only act through the tools you grant it)')\n if (!hasSkills) reasons.push('no skills attached (no reusable how-to notes injected)')\n if (opts?.needsMcp && !hasMcp) reasons.push('no MCP server, but the task needs data/tool access')\n\n // Richness = fraction of signals present. Prompt-depth is one signal; the four levers are the rest.\n const signals = [!promptThin, hasTools, hasSkills, hasDescription, opts?.needsMcp ? hasMcp : true]\n const richness = signals.filter(Boolean).length / signals.length\n // THIN ⟺ the prompt is a stub OR the worker has no levers at all (no tools AND no skills AND no mcp).\n const thin = promptThin || (!hasTools && !hasSkills && !hasMcp)\n\n return {\n name: profile.name ?? 'worker',\n systemPrompt,\n systemPromptChars,\n systemPromptLines,\n sentenceCount,\n hasDescription,\n hasTools,\n hasSkills,\n hasMcp,\n hasSubagents,\n richness,\n thin,\n reasons,\n }\n}\n\n/** Turn a {@link ProfileRichness} verdict into a bus-routable `AnalystFinding` (area `profile-quality`).\n * Severity scales with thinness; the recommended action names the MISSING lever so the supervisor can\n * re-author. `subject` = the worker name so per-worker findings diff cleanly across re-authors. */\nexport function profileRichnessFinding(\n richness: ProfileRichness,\n opts?: { analystId?: string; runId?: string },\n): AnalystFinding {\n const analyst_id = opts?.analystId ?? 'profile-richness'\n const subject = richness.name\n const claim = richness.thin\n ? `Worker \"${richness.name}\" was authored as a THIN profile: ${richness.reasons.join('; ')}.`\n : `Worker \"${richness.name}\" was authored as a rich profile (richness ${(richness.richness * 100).toFixed(0)}%).`\n const severity: AnalystFinding['severity'] = richness.thin\n ? richness.richness < 0.25\n ? 'high'\n : 'medium'\n : 'info'\n return makeFinding({\n analyst_id,\n severity,\n area: 'profile-quality',\n claim,\n subject,\n confidence: 0.9,\n evidence_refs: [\n {\n kind: 'metric',\n uri: `profile:${subject}`,\n excerpt: `chars=${richness.systemPromptChars} lines=${richness.systemPromptLines} tools=${richness.hasTools} skills=${richness.hasSkills} mcp=${richness.hasMcp} richness=${richness.richness.toFixed(2)}`,\n },\n ],\n ...(richness.thin\n ? { recommended_action: `Re-author \"${richness.name}\" with: ${richness.reasons.join('; ')}.` }\n : {}),\n id_basis: computeFindingId({\n analyst_id,\n area: 'profile-quality',\n subject,\n claim: `richness:${richness.thin ? 'thin' : 'rich'}`,\n }),\n })\n}\n","/**\n *\n * `delegate` — the one generic delegation verb. You hand it an INTENT (what you want done) and it\n * hands that intent to a default AUTHORING supervisor: a router-brained supervisor whose standing\n * instruction is `supervisorInstructions()` (the authoring-agent-profiles skill). The supervisor\n * DECOMPOSES the intent and AUTHORS the worker profile it needs per sub-task — there is NO hardcoded\n * coder/researcher profile here. That is the whole point: `delegate('fix the failing test', …)` and\n * `delegate('research X and cite sources', …)` route through the SAME front door; the supervisor\n * writes a code-shaped or research-shaped worker on its own.\n *\n * It is a thin wrapper over `supervise()` — the one front door — so the conserved-budget pool, the\n * completion oracle (`deliverable`), the coordination toolbox, and equal-compute accounting all come\n * for free; nothing is hand-rolled. The result is `supervise()`'s `SupervisedResult` returned\n * UNCHANGED, so its `spentTotal` (`{ iterations, tokens, usd, ms }`) rides straight back to the\n * caller on BOTH paths — a `winner` carries the delivered worker's spend, a `no-winner` carries the\n * spend incurred before it failed. That cost channel means a `delegate()` caller always learns what\n * the delegation actually spent.\n *\n * @experimental\n */\n\nimport { ConfigError } from '../../errors'\nimport type { RouterTransportConfig } from '../router-client'\nimport type { DeliverableSpec } from './completion-gate'\nimport type { ExecutorConfig } from './runtime'\nimport { supervise } from './supervise'\nimport type { SupervisorProfile } from './supervisor-agent'\nimport type { Budget, SupervisedResult } from './types'\n\n/** The conserved pool a `delegate()` call applies when the caller does not pass its own `budget`.\n * A modest token ceiling + a small iteration ceiling — generous enough for a few-worker decompose,\n * bounded enough that an unsupervised intent cannot run away. Callers override via `opts.budget`. */\nexport const defaultDelegateBudget: Budget = { maxIterations: 50, maxTokens: 200_000 }\n\n/** Inputs to {@link delegate}. The intent is the first positional arg; everything here is optional\n * with explicit execution identity, so the common call names one exact supervisor profile. */\nexport interface DelegateOptions<Out = unknown> {\n /** The completion oracle (settled ⟺ delivered) the authored workers settle against. Strongly\n * recommended — without it the supervisor trusts a worker's self-report. For a code intent,\n * `patchDelivered()` is the canonical example; for a free-form answer, a content check. */\n readonly deliverable?: DeliverableSpec<Out>\n /** WHERE the authored workers run — the worker-execution backend (`router-tools` / `sandbox` /\n * `cli-worktree` / …). The supervisor authors the worker PROFILE; this is the substrate it runs\n * on. Provide this OR `makeWorkerAgent`-style wiring through `supervise()` is unavailable. */\n readonly backend?: ExecutorConfig\n /** The conserved compute pool for the whole delegation. Defaults to {@link defaultDelegateBudget}. */\n readonly budget?: Budget\n /** Exact executable authoring supervisor. Model, prompt, harness, and provider live here. */\n readonly supervisorProfile: SupervisorProfile\n /** Router endpoint/auth for a `cli-base` supervisor; contains no behavioral settings. */\n readonly router: RouterTransportConfig\n /** Restrict the run to this subset of models (forwarded to `supervise()`). */\n readonly allowedModels?: readonly string[]\n readonly runId?: string\n}\n\n/**\n * Delegate an INTENT to a default authoring supervisor and return its `SupervisedResult` unchanged.\n *\n * The supervisor authors + spawns whatever worker the intent needs over the conserved-budget pool;\n * `result.spentTotal` reports what the whole delegation actually cost. A `winner` result carries the\n * authored worker's delivered output; a `no-winner` result names why (never a fabricated success).\n */\nexport async function delegate<Out = unknown>(\n intent: string,\n opts: DelegateOptions<Out>,\n): Promise<SupervisedResult<Out>> {\n if (typeof intent !== 'string' || intent.trim().length === 0) {\n throw new ConfigError('delegate: `intent` must be a non-empty string')\n }\n return supervise(opts.supervisorProfile, intent, {\n budget: opts.budget ?? defaultDelegateBudget,\n ...(opts.backend ? { backend: opts.backend } : {}),\n ...(opts.deliverable ? { deliverable: opts.deliverable as DeliverableSpec<unknown> } : {}),\n router: opts.router,\n ...(opts.allowedModels ? { allowedModels: opts.allowedModels } : {}),\n ...(opts.runId ? { runId: opts.runId } : {}),\n }) as Promise<SupervisedResult<Out>>\n}\n"],"mappings":"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"}
|
package/dist/durable.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Xa as SuperviseOptions, eo as supervise, wo as SupervisorProfile } from "./index-
|
|
1
|
+
import { I as ProviderModelExecutionEvidence, J as RootStreamReceipt, Mn as RetainedPendingCause, P as ProfileMaterializationReceipt, U as RetainedExecutionState, at as SpendGap, i as Budget, j as NodeId, l as ExecutionBindingReceipt, n as AgentExecutionRef, o as BudgetViolation, rt as Spend, st as SupervisedResult, y as ExecutorProgressEvent, yt as WorkerTraceEvidence } from "./types-CP3iQ8Ji.js";
|
|
2
|
+
import { Xa as SuperviseOptions, eo as supervise, wo as SupervisorProfile } from "./index-B8tXCisZ.js";
|
|
3
3
|
import { l as RuntimeHooks, o as RuntimeHookEvent, r as RuntimeDecisionPoint } from "./runtime-hooks-Bj6wJHlH.js";
|
|
4
|
+
import { AgentCandidateLineage, AgentProfile, AgentProfileDiff, Sha256Digest } from "@tangle-network/agent-interface";
|
|
4
5
|
//#region src/runtime/supervise/root-stream.d.ts
|
|
5
6
|
/** The root stream: one JSONL line per progress event the root's executor observed. */
|
|
6
7
|
declare const ROOT_STREAM_FILE = "root-stream.jsonl";
|
|
@@ -356,6 +357,9 @@ interface PursuitNodeProjection {
|
|
|
356
357
|
readonly runtime?: string;
|
|
357
358
|
readonly depth?: number;
|
|
358
359
|
readonly assignmentId?: string;
|
|
360
|
+
/** The settled sibling this node replaced, as its manager's spawn named it. Absent on a node
|
|
361
|
+
* that replaced nothing. */
|
|
362
|
+
readonly successorOf?: string;
|
|
359
363
|
readonly identity?: unknown;
|
|
360
364
|
readonly budget?: unknown;
|
|
361
365
|
readonly status: PursuitStatus;
|
|
@@ -451,6 +455,284 @@ interface PursuitProjection {
|
|
|
451
455
|
*/
|
|
452
456
|
declare function projectPursuit(records: readonly ObserverRecord[]): PursuitProjection;
|
|
453
457
|
//#endregion
|
|
458
|
+
//#region src/durable/run-fork.d.ts
|
|
459
|
+
/**
|
|
460
|
+
* Start a run as a version of a settled run: the parent's recorded root inputs plus one change.
|
|
461
|
+
*
|
|
462
|
+
* The call's `profile`, `task` and `budget` must be the parent's, byte for byte, as its sealed
|
|
463
|
+
* journal records them. Runtime applies `change` to that profile and runs the result in a new
|
|
464
|
+
* run directory. The parent directory is read and never written.
|
|
465
|
+
*/
|
|
466
|
+
interface PursuitFork {
|
|
467
|
+
/** The settled parent's run directory. */
|
|
468
|
+
readonly runDir: string;
|
|
469
|
+
/** The sha256 of the parent's `result.json` bytes: the sealed point the fork starts from. */
|
|
470
|
+
readonly settleDigest: Sha256Digest;
|
|
471
|
+
/** The one change, applied to the parent's root profile. Its `id` is recorded. */
|
|
472
|
+
readonly change: AgentProfileDiff;
|
|
473
|
+
/**
|
|
474
|
+
* Fork a parent whose journal holds a node without a terminal record, an unbegun owned tree, an
|
|
475
|
+
* unconfirmed teardown, or work in flight. Such a node may still act, and a fork never replays
|
|
476
|
+
* the parent's children, so it can only duplicate work outside the fork's tree. The root then
|
|
477
|
+
* records those node ids as `forkParentUncertainNodes`. Omit it to refuse such a parent.
|
|
478
|
+
*/
|
|
479
|
+
readonly acceptUncertain?: boolean;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* The `execution.correlation` keys a fork records on its root. Runtime writes them; a caller that
|
|
483
|
+
* supplies one is refused. `lineageRootRunId` is the first run of the chain of parents, so the
|
|
484
|
+
* spend of every version of one lineage groups under one id.
|
|
485
|
+
*/
|
|
486
|
+
declare const RUN_FORK_CORRELATION_KEYS: readonly ["forkParentRunId", "forkParentSettleDigest", "forkProfileDiffId", "lineageRootRunId"];
|
|
487
|
+
/** The correlation key an accepted uncertain parent adds: its uncertain node ids, comma-joined. */
|
|
488
|
+
declare const FORK_PARENT_UNCERTAIN_NODES_KEY = "forkParentUncertainNodes";
|
|
489
|
+
//#endregion
|
|
490
|
+
//#region src/durable/supervise-pursuit.d.ts
|
|
491
|
+
interface SupervisePursuitOptions extends SuperviseOptions {
|
|
492
|
+
/** Stable objective identity spanning concrete Runtime runs. */
|
|
493
|
+
readonly pursuitId: string;
|
|
494
|
+
/**
|
|
495
|
+
* One concrete Runtime execution owns one durable directory and observer journal.
|
|
496
|
+
* A pursuit spanning several runs reuses `pursuitId` across distinct `runDir`s;
|
|
497
|
+
* Intelligence joins those isolated projections without a shared write head.
|
|
498
|
+
*/
|
|
499
|
+
readonly runDir: string;
|
|
500
|
+
/**
|
|
501
|
+
* Always `'release'`. The settle record refuses re-entry, so no later call resumes a settled
|
|
502
|
+
* pursuit and nothing else would release the provider environments its retained children hold.
|
|
503
|
+
* `'keep'` is refused rather than ignored.
|
|
504
|
+
*/
|
|
505
|
+
readonly retainedAtSettlement?: 'release';
|
|
506
|
+
/**
|
|
507
|
+
* Run this pursuit as a version of a settled run: `profile`, `task` and `budget` must equal the
|
|
508
|
+
* parent's recorded root, and Runtime executes the parent's profile with `fork.change` applied.
|
|
509
|
+
* The root's `execution.correlation` records the parent, its sealed digest, the change and the
|
|
510
|
+
* lineage (`RUN_FORK_CORRELATION_KEYS`). The fork's `runDir` must lie outside the parent's, and
|
|
511
|
+
* the parent's outside it. The parent's directory is never written, and a refused fork, such as
|
|
512
|
+
* one whose parent has an uncertain node, writes nothing.
|
|
513
|
+
*/
|
|
514
|
+
readonly fork?: PursuitFork;
|
|
515
|
+
/**
|
|
516
|
+
* Continue this pursuit across versions. The first version runs at `runDir` as usual, or is
|
|
517
|
+
* read back when that directory already settled. After each version settles, `versions.judge`
|
|
518
|
+
* scores it from outside its tree; unless `versions.stop` ends the chain, the next version forks
|
|
519
|
+
* from the best version so far with the change `versions.next` returns, at `<runDir>.v<n>` with
|
|
520
|
+
* run id `<runId>.v<n>`. `<runDir>.versions/versions.jsonl` records every version, its parent,
|
|
521
|
+
* its change, its verdict and its dollars, and the stop. A call on a chain that stopped reads
|
|
522
|
+
* that record back; a call on a chain that did not resumes it without re-running or re-judging a
|
|
523
|
+
* settled version. The call returns the best version's result with the chain's record.
|
|
524
|
+
*/
|
|
525
|
+
readonly versions?: PursuitVersions;
|
|
526
|
+
/** Supervise's name tables, plus the version judges and changes `versions` may name. */
|
|
527
|
+
readonly registry?: SuperviseOptions['registry'] & PursuitVersionRegistry;
|
|
528
|
+
}
|
|
529
|
+
interface SupervisedPursuitResult<Result> {
|
|
530
|
+
readonly result: Result;
|
|
531
|
+
readonly pursuit: PursuitProjection;
|
|
532
|
+
readonly observerPath: string;
|
|
533
|
+
/** `runDir/result.json`: `result` as canonical JSON, written once at settle. */
|
|
534
|
+
readonly settlePath: string;
|
|
535
|
+
/** The version chain's record, when the call set `versions`. */
|
|
536
|
+
readonly versions?: PursuitVersionsRecord;
|
|
537
|
+
}
|
|
538
|
+
/** A failed Runtime execution whose complete third-person projection was retained. */
|
|
539
|
+
declare class SupervisePursuitError extends Error {
|
|
540
|
+
readonly pursuit: PursuitProjection;
|
|
541
|
+
readonly observerPath: string;
|
|
542
|
+
/** `runDir/failure.json`: the record of this throw. */
|
|
543
|
+
readonly failurePath: string;
|
|
544
|
+
constructor(cause: unknown, pursuit: PursuitProjection, observerPath: string, failurePath: string);
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* One-call durable pursuit execution over the canonical `supervise()` kernel.
|
|
548
|
+
*
|
|
549
|
+
* This is an adapter, not a second executor: it composes a durable third-person
|
|
550
|
+
* observer into Runtime's existing recursive hook stream and then rebuilds the
|
|
551
|
+
* operator projection after the same `supervise()` call settles. Agents never
|
|
552
|
+
* receive the observer path or projection and their behavior does not depend on it.
|
|
553
|
+
*
|
|
554
|
+
* Every concrete execution writes only inside its own `runDir`. Cross-run pursuit
|
|
555
|
+
* aggregation is therefore lock-free at the observer layer: reuse `pursuitId` across
|
|
556
|
+
* run directories and let Intelligence join the independently verified projections.
|
|
557
|
+
*
|
|
558
|
+
* The directory's terminal state is recorded beside `observer.jsonl`: `result.json` holds the
|
|
559
|
+
* returned result once the run settles and `failure.json` the most recent throw. A directory
|
|
560
|
+
* whose `result.json` exists refuses re-entry before any compute; a failure record alone does
|
|
561
|
+
* not, because a caller can correct its input and drive the same run again. For the life of the
|
|
562
|
+
* call the directory is held by `supervise.lock`, so a second process on the same directory
|
|
563
|
+
* refuses and names the holder instead of sharing one journal.
|
|
564
|
+
* An abandoned `supervise.lock.guard` requires removal after confirming no lock mutation is active.
|
|
565
|
+
*/
|
|
566
|
+
declare function supervisePursuit(profile: SupervisorProfile, task: unknown, opts: SupervisePursuitOptions): Promise<SupervisedPursuitResult<Awaited<ReturnType<typeof supervise>>>>;
|
|
567
|
+
//#endregion
|
|
568
|
+
//#region src/durable/pursuit-versions.d.ts
|
|
569
|
+
/**
|
|
570
|
+
* Continue a pursuit across versions: after each version settles, an outside judge scores it, and
|
|
571
|
+
* the next version forks from the best version so far with one change, until the stop rule ends
|
|
572
|
+
* the chain. Each version is one `supervisePursuit` run in its own directory; the fork records its
|
|
573
|
+
* parent, the parent's seal, the change and the lineage root on the version's root.
|
|
574
|
+
*/
|
|
575
|
+
interface PursuitVersions {
|
|
576
|
+
/** Scores each settled version from outside its tree. A string names `registry.versionJudges`. */
|
|
577
|
+
readonly judge: VersionJudge | string;
|
|
578
|
+
/** The change the next version applies to the best version's profile. A string names
|
|
579
|
+
* `registry.nextVersions`. */
|
|
580
|
+
readonly next: NextPursuitVersion | string;
|
|
581
|
+
/** When the chain stops. Every cap is required: a chain without one is refused. */
|
|
582
|
+
readonly stop: PursuitVersionStop;
|
|
583
|
+
/**
|
|
584
|
+
* Where a later version executes. Omit it to run each version in this process through
|
|
585
|
+
* `supervisePursuit({ fork })`, the same placement as the first. A caller that places versions
|
|
586
|
+
* elsewhere executes exactly `version.profile` on `version.task` under `version.budget`, with
|
|
587
|
+
* `version.execution` as the root's attribution, and returns once `version.runDir` holds the
|
|
588
|
+
* version's settle record and observer journal. It is called again for the same version after
|
|
589
|
+
* a restart, so it must attach to a version it already started rather than start a second one.
|
|
590
|
+
*/
|
|
591
|
+
readonly run?: RunPursuitVersion;
|
|
592
|
+
/**
|
|
593
|
+
* A version's dollars as the caller measured them, such as the provider's charge to the keys the
|
|
594
|
+
* version used. Omit it to use the version's settled `spentTotal.usd`, which is an estimate
|
|
595
|
+
* when `usdKnown` is false. `null` means unknown, and stops the chain.
|
|
596
|
+
*/
|
|
597
|
+
readonly usd?: (version: SettledPursuitVersion, signal: AbortSignal) => Promise<number | null>;
|
|
598
|
+
}
|
|
599
|
+
/** The chain's stop rule. The chain never starts a version once any cap is reached. */
|
|
600
|
+
interface PursuitVersionStop {
|
|
601
|
+
/** Stop after this many consecutive versions that did not improve on the best score. */
|
|
602
|
+
readonly patience: number;
|
|
603
|
+
/** At most this many versions, the first included. */
|
|
604
|
+
readonly maxVersions: number;
|
|
605
|
+
/**
|
|
606
|
+
* The chain's total dollars, the first version included, summed from each version's settled
|
|
607
|
+
* `spentTotal.usd`. The chain checks it between versions; a version's own budget, or the
|
|
608
|
+
* caller's spend watcher, bounds that version in flight. A version whose dollars are not a
|
|
609
|
+
* number stops the chain, since the chain can no longer prove it is under the cap.
|
|
610
|
+
*/
|
|
611
|
+
readonly maxUsd: number;
|
|
612
|
+
/** The chain's wall clock, from its first version's start. A running version is aborted at it. */
|
|
613
|
+
readonly deadlineMs: number;
|
|
614
|
+
/** A version improves when its score exceeds the best by more than this. Default 0. */
|
|
615
|
+
readonly minImprovement?: number;
|
|
616
|
+
}
|
|
617
|
+
/** An outside judge. Runtime calls it after a version's settle record exists, never inside the
|
|
618
|
+
* version's tree, and gives it no handle into that tree. Place it where you like, such as its own
|
|
619
|
+
* sandbox through `runIsolatedCheck({ box })`. */
|
|
620
|
+
interface VersionJudge {
|
|
621
|
+
/** The sha256 of the judge's code and configuration. Every verdict must carry it, and a chain
|
|
622
|
+
* whose ledger was judged under another digest is refused. */
|
|
623
|
+
readonly digest: Sha256Digest;
|
|
624
|
+
judge(version: SettledPursuitVersion, signal: AbortSignal): Promise<VersionVerdict>;
|
|
625
|
+
}
|
|
626
|
+
interface VersionVerdict {
|
|
627
|
+
/** Higher is better. `null` when the judge could not score the version, which never counts as
|
|
628
|
+
* an improvement. */
|
|
629
|
+
readonly score: number | null;
|
|
630
|
+
/** Must equal `VersionJudge.digest`. */
|
|
631
|
+
readonly judgeDigest: Sha256Digest;
|
|
632
|
+
/** What the judge measured, retained verbatim in the ledger. JSON values only. */
|
|
633
|
+
readonly detail?: unknown;
|
|
634
|
+
}
|
|
635
|
+
/** A settled version, as the judge and `next` read it. */
|
|
636
|
+
interface SettledPursuitVersion {
|
|
637
|
+
/** 1 for the first version. */
|
|
638
|
+
readonly version: number;
|
|
639
|
+
readonly runId: string;
|
|
640
|
+
readonly runDir: string;
|
|
641
|
+
/** The sha256 of the version's `result.json` bytes. */
|
|
642
|
+
readonly settleDigest: Sha256Digest;
|
|
643
|
+
readonly result: SupervisedResult<unknown>;
|
|
644
|
+
/** The profile the version executed: the first version's, or its parent's plus its change. */
|
|
645
|
+
readonly profile: AgentProfile;
|
|
646
|
+
readonly parent?: PursuitVersionParent;
|
|
647
|
+
readonly change?: AgentProfileDiff;
|
|
648
|
+
}
|
|
649
|
+
interface PursuitVersionParent {
|
|
650
|
+
readonly version: number;
|
|
651
|
+
readonly runId: string;
|
|
652
|
+
readonly settleDigest: Sha256Digest;
|
|
653
|
+
}
|
|
654
|
+
interface JudgedPursuitVersion extends SettledPursuitVersion {
|
|
655
|
+
readonly verdict: VersionVerdict;
|
|
656
|
+
/** Whether its score beat every earlier version's by more than `minImprovement`. */
|
|
657
|
+
readonly improved: boolean;
|
|
658
|
+
/** The version's dollars: `versions.usd`'s measurement, or its settled `spentTotal.usd`;
|
|
659
|
+
* `null` when that is not a number. */
|
|
660
|
+
readonly usd: number | null;
|
|
661
|
+
/** False when the figure is Runtime's estimate or unknown. */
|
|
662
|
+
readonly usdKnown: boolean;
|
|
663
|
+
/** Who measured `usd`: the caller's `versions.usd`, or Runtime's settled `spentTotal`. */
|
|
664
|
+
readonly usdSource: 'caller' | 'runtime';
|
|
665
|
+
/** Where the version came from: its parent run and its change. Absent for a first version that
|
|
666
|
+
* is not a fork. */
|
|
667
|
+
readonly lineage?: AgentCandidateLineage;
|
|
668
|
+
}
|
|
669
|
+
interface NextPursuitVersionInput {
|
|
670
|
+
/** The version the next one forks from: the highest score, the earliest on a tie. */
|
|
671
|
+
readonly best: JudgedPursuitVersion;
|
|
672
|
+
readonly last: JudgedPursuitVersion;
|
|
673
|
+
readonly versions: readonly JudgedPursuitVersion[];
|
|
674
|
+
}
|
|
675
|
+
/** Build the one change the next version applies to `best.profile`. Its `id` must be non-empty. */
|
|
676
|
+
type NextPursuitVersion = (input: NextPursuitVersionInput, signal: AbortSignal) => AgentProfileDiff | Promise<AgentProfileDiff>;
|
|
677
|
+
/** One version, ready to execute. */
|
|
678
|
+
interface PreparedPursuitVersion {
|
|
679
|
+
readonly version: number;
|
|
680
|
+
readonly runId: string;
|
|
681
|
+
readonly runDir: string;
|
|
682
|
+
readonly pursuitId: string;
|
|
683
|
+
/** The profile to execute, the change already applied. */
|
|
684
|
+
readonly profile: AgentProfile;
|
|
685
|
+
readonly task: unknown;
|
|
686
|
+
readonly budget: Budget;
|
|
687
|
+
/** The root's attribution, with the fork's parent, seal, change and lineage root. */
|
|
688
|
+
readonly execution: AgentExecutionRef;
|
|
689
|
+
/** The fork Runtime verified, for a placement that runs `supervisePursuit({ fork })` itself
|
|
690
|
+
* with the parent's profile, `parentProfile`. */
|
|
691
|
+
readonly fork: PursuitFork;
|
|
692
|
+
readonly parentProfile: AgentProfile;
|
|
693
|
+
}
|
|
694
|
+
type RunPursuitVersion = (version: PreparedPursuitVersion, signal: AbortSignal) => Promise<void>;
|
|
695
|
+
type PursuitVersionStopReason = 'no-improvement' | 'max-versions' | 'max-usd' | 'spend-unknown' | 'deadline' | 'aborted';
|
|
696
|
+
/** The chain's record, returned beside the best version's result and kept in `versions.jsonl`. */
|
|
697
|
+
interface PursuitVersionsRecord {
|
|
698
|
+
/** `<runDir>.versions`, beside the first version's directory. */
|
|
699
|
+
readonly lineageDir: string;
|
|
700
|
+
readonly judgeDigest: Sha256Digest;
|
|
701
|
+
readonly stop: PursuitVersionStop;
|
|
702
|
+
/** ISO instant the first version started. */
|
|
703
|
+
readonly startedAt: string;
|
|
704
|
+
readonly versions: readonly JudgedPursuitVersion[];
|
|
705
|
+
/** The best version's number. */
|
|
706
|
+
readonly best: number;
|
|
707
|
+
/** Sum of the versions' `usd`; a floor when any version's dollars are unknown. */
|
|
708
|
+
readonly spentUsd: number;
|
|
709
|
+
readonly stopped: {
|
|
710
|
+
readonly reason: PursuitVersionStopReason;
|
|
711
|
+
readonly at: string;
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
/** The registry tables `versions.judge` and `versions.next` resolve a name against. */
|
|
715
|
+
interface PursuitVersionRegistry {
|
|
716
|
+
readonly versionJudges?: {
|
|
717
|
+
resolve(name: string): VersionJudge | undefined;
|
|
718
|
+
};
|
|
719
|
+
readonly nextVersions?: {
|
|
720
|
+
resolve(name: string): NextPursuitVersion | undefined;
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
/** The ledger file inside the lineage directory. */
|
|
724
|
+
declare const PURSUIT_VERSIONS_FILE = "versions.jsonl";
|
|
725
|
+
/** The `<runDir>.v<n>` directory and `<runId>.v<n>` id of version `n`, beside the first. */
|
|
726
|
+
declare function pursuitVersionRun(runDir: string, runId: string, version: number): {
|
|
727
|
+
runDir: string;
|
|
728
|
+
runId: string;
|
|
729
|
+
};
|
|
730
|
+
/**
|
|
731
|
+
* Validate a `versions` option before any compute. The same check runs inside `supervisePursuit`;
|
|
732
|
+
* a caller that records the option as data can run it at preflight.
|
|
733
|
+
*/
|
|
734
|
+
declare function assertPursuitVersions(versions: unknown): asserts versions is PursuitVersions;
|
|
735
|
+
//#endregion
|
|
454
736
|
//#region src/durable/run-lock.d.ts
|
|
455
737
|
/** The lock file `supervisePursuit` holds inside a run directory for the life of one call. */
|
|
456
738
|
declare const RUN_DIRECTORY_LOCK_FILE = "supervise.lock";
|
|
@@ -554,60 +836,6 @@ declare function readSettleRecord(runDir: string): Promise<SupervisedResult<unkn
|
|
|
554
836
|
/** Read the most recent failure record, or `undefined` when the directory holds none. */
|
|
555
837
|
declare function readFailureRecord(runDir: string): Promise<DurableFailureRecord | undefined>;
|
|
556
838
|
//#endregion
|
|
557
|
-
//#region src/durable/supervise-pursuit.d.ts
|
|
558
|
-
interface SupervisePursuitOptions extends SuperviseOptions {
|
|
559
|
-
/** Stable objective identity spanning concrete Runtime runs. */
|
|
560
|
-
readonly pursuitId: string;
|
|
561
|
-
/**
|
|
562
|
-
* One concrete Runtime execution owns one durable directory and observer journal.
|
|
563
|
-
* A pursuit spanning several runs reuses `pursuitId` across distinct `runDir`s;
|
|
564
|
-
* Intelligence joins those isolated projections without a shared write head.
|
|
565
|
-
*/
|
|
566
|
-
readonly runDir: string;
|
|
567
|
-
/**
|
|
568
|
-
* Always `'release'`. The settle record refuses re-entry, so no later call resumes a settled
|
|
569
|
-
* pursuit and nothing else would release the provider environments its retained children hold.
|
|
570
|
-
* `'keep'` is refused rather than ignored.
|
|
571
|
-
*/
|
|
572
|
-
readonly retainedAtSettlement?: 'release';
|
|
573
|
-
}
|
|
574
|
-
interface SupervisedPursuitResult<Result> {
|
|
575
|
-
readonly result: Result;
|
|
576
|
-
readonly pursuit: PursuitProjection;
|
|
577
|
-
readonly observerPath: string;
|
|
578
|
-
/** `runDir/result.json`: `result` as canonical JSON, written once at settle. */
|
|
579
|
-
readonly settlePath: string;
|
|
580
|
-
}
|
|
581
|
-
/** A failed Runtime execution whose complete third-person projection was retained. */
|
|
582
|
-
declare class SupervisePursuitError extends Error {
|
|
583
|
-
readonly pursuit: PursuitProjection;
|
|
584
|
-
readonly observerPath: string;
|
|
585
|
-
/** `runDir/failure.json`: the record of this throw. */
|
|
586
|
-
readonly failurePath: string;
|
|
587
|
-
constructor(cause: unknown, pursuit: PursuitProjection, observerPath: string, failurePath: string);
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* One-call durable pursuit execution over the canonical `supervise()` kernel.
|
|
591
|
-
*
|
|
592
|
-
* This is an adapter, not a second executor: it composes a durable third-person
|
|
593
|
-
* observer into Runtime's existing recursive hook stream and then rebuilds the
|
|
594
|
-
* operator projection after the same `supervise()` call settles. Agents never
|
|
595
|
-
* receive the observer path or projection and their behavior does not depend on it.
|
|
596
|
-
*
|
|
597
|
-
* Every concrete execution writes only inside its own `runDir`. Cross-run pursuit
|
|
598
|
-
* aggregation is therefore lock-free at the observer layer: reuse `pursuitId` across
|
|
599
|
-
* run directories and let Intelligence join the independently verified projections.
|
|
600
|
-
*
|
|
601
|
-
* The directory's terminal state is recorded beside `observer.jsonl`: `result.json` holds the
|
|
602
|
-
* returned result once the run settles and `failure.json` the most recent throw. A directory
|
|
603
|
-
* whose `result.json` exists refuses re-entry before any compute; a failure record alone does
|
|
604
|
-
* not, because a caller can correct its input and drive the same run again. For the life of the
|
|
605
|
-
* call the directory is held by `supervise.lock`, so a second process on the same directory
|
|
606
|
-
* refuses and names the holder instead of sharing one journal.
|
|
607
|
-
* An abandoned `supervise.lock.guard` requires removal after confirming no lock mutation is active.
|
|
608
|
-
*/
|
|
609
|
-
declare function supervisePursuit(profile: SupervisorProfile, task: unknown, opts: SupervisePursuitOptions): Promise<SupervisedPursuitResult<Awaited<ReturnType<typeof supervise>>>>;
|
|
610
|
-
//#endregion
|
|
611
839
|
//#region src/durable/supervision-discovery.d.ts
|
|
612
840
|
interface DurableCoordinationStreamIdentity {
|
|
613
841
|
readonly runId: string;
|
|
@@ -642,5 +870,5 @@ interface DurableSupervisionDiscovery {
|
|
|
642
870
|
*/
|
|
643
871
|
declare function discoverDurableSupervisionRun(runDir: string): Promise<DurableSupervisionDiscovery>;
|
|
644
872
|
//#endregion
|
|
645
|
-
export { type ChatStreamEvent, type ChatTurnHooks, type ChatTurnIdentity, type ChatTurnProducer, type ChatTurnResult, type DurableCoordinationStreamIdentity, type DurableFailureRecord, type DurableSupervisionDiscovery, FAILURE_RECORD_FILE, FileObserverJournal, type ObserverJournal, type ObserverRecord, type ObserverRecordKind, type PursuitCostProvenance, type PursuitNodeCost, type PursuitNodePlacement, type PursuitNodePlatform, type PursuitNodeProjection, type PursuitNodeTiming, type PursuitNodeUsage, type PursuitProjection, type PursuitRunProjection, type PursuitRunTotals, type PursuitStatus, ROOT_STREAM_FILE, RUN_DIRECTORY_LOCK_FILE, type RootStreamReceipt, type RootStreamRecord, type RunChatTurnInput, type RunDirectoryHolderLiveness, type RunDirectoryLock, type RunDirectoryLockHolder, RunDirectoryLockedError, SETTLE_RECORD_FILE, SettledRunDirectoryError, SupervisePursuitError, type SupervisePursuitOptions, type SupervisedPursuitResult, acquireRunDirectoryLock, createFileObserverHooks, deriveExecutionId, discoverDurableSupervisionRun, handleChatTurn, observerRecordDigest, projectPursuit, readFailureRecord, readRootStream, readRootStreamReceipt, readRunDirectoryLock, readSettleRecord, runDirectoryHolderIsLive, settleRecordJson, supervisePursuit, verifyObserverRecords };
|
|
873
|
+
export { type ChatStreamEvent, type ChatTurnHooks, type ChatTurnIdentity, type ChatTurnProducer, type ChatTurnResult, type DurableCoordinationStreamIdentity, type DurableFailureRecord, type DurableSupervisionDiscovery, FAILURE_RECORD_FILE, FORK_PARENT_UNCERTAIN_NODES_KEY, FileObserverJournal, type JudgedPursuitVersion, type NextPursuitVersion, type NextPursuitVersionInput, type ObserverJournal, type ObserverRecord, type ObserverRecordKind, PURSUIT_VERSIONS_FILE, type PreparedPursuitVersion, type PursuitCostProvenance, type PursuitFork, type PursuitNodeCost, type PursuitNodePlacement, type PursuitNodePlatform, type PursuitNodeProjection, type PursuitNodeTiming, type PursuitNodeUsage, type PursuitProjection, type PursuitRunProjection, type PursuitRunTotals, type PursuitStatus, type PursuitVersionParent, type PursuitVersionRegistry, type PursuitVersionStop, type PursuitVersionStopReason, type PursuitVersions, type PursuitVersionsRecord, ROOT_STREAM_FILE, RUN_DIRECTORY_LOCK_FILE, RUN_FORK_CORRELATION_KEYS, type RootStreamReceipt, type RootStreamRecord, type RunChatTurnInput, type RunDirectoryHolderLiveness, type RunDirectoryLock, type RunDirectoryLockHolder, RunDirectoryLockedError, type RunPursuitVersion, SETTLE_RECORD_FILE, type SettledPursuitVersion, SettledRunDirectoryError, SupervisePursuitError, type SupervisePursuitOptions, type SupervisedPursuitResult, type VersionJudge, type VersionVerdict, acquireRunDirectoryLock, assertPursuitVersions, createFileObserverHooks, deriveExecutionId, discoverDurableSupervisionRun, handleChatTurn, observerRecordDigest, projectPursuit, pursuitVersionRun, readFailureRecord, readRootStream, readRootStreamReceipt, readRunDirectoryLock, readSettleRecord, runDirectoryHolderIsLive, settleRecordJson, supervisePursuit, verifyObserverRecords };
|
|
646
874
|
//# sourceMappingURL=durable.d.ts.map
|