@tangle-network/agent-runtime 0.104.0 → 0.106.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +176 -42
- package/dist/activation-CRjVfOiy.js +203 -0
- package/dist/activation-CRjVfOiy.js.map +1 -0
- package/dist/activation-DyWB0K6E.d.ts +98 -0
- package/dist/agent.d.ts +216 -234
- package/dist/agent.js +615 -547
- package/dist/agent.js.map +1 -1
- package/dist/analyst-loop-DGdtVENg.js +517 -0
- package/dist/analyst-loop-DGdtVENg.js.map +1 -0
- package/dist/analyst-loop.d.ts +10 -43
- package/dist/analyst-loop.js +2 -11
- package/dist/backends-Dy8NujB4.js +713 -0
- package/dist/backends-Dy8NujB4.js.map +1 -0
- package/dist/candidate-execution/index.d.ts +4 -192
- package/dist/candidate-execution/index.js +5 -66
- package/dist/candidate-execution-DqMbv1rU.js +488 -0
- package/dist/candidate-execution-DqMbv1rU.js.map +1 -0
- package/dist/coder-yhVWbdWc.js +40 -0
- package/dist/coder-yhVWbdWc.js.map +1 -0
- package/dist/conversation-XucG_K3l.js +1265 -0
- package/dist/conversation-XucG_K3l.js.map +1 -0
- package/dist/conversation.d.ts +2 -804
- package/dist/conversation.js +2 -55
- package/dist/environment-provider-CfLUmKmf.js +1168 -0
- package/dist/environment-provider-CfLUmKmf.js.map +1 -0
- package/dist/environment-provider-IUGU3epE.d.ts +964 -0
- package/dist/environment-provider.d.ts +2 -78
- package/dist/environment-provider.js +2 -18
- package/dist/errors-DEAvWQPy.js +111 -0
- package/dist/errors-DEAvWQPy.js.map +1 -0
- package/dist/improvement-adapter-Cr5TBSji.d.ts +166 -0
- package/dist/improvement-cycle-C095kS_g.js +2624 -0
- package/dist/improvement-cycle-C095kS_g.js.map +1 -0
- package/dist/index-BGdxAwfO.d.ts +838 -0
- package/dist/index-C-FYUuFG.d.ts +193 -0
- package/dist/index-CbNM40xG.d.ts +140 -0
- package/dist/index-DruSKs3Z.d.ts +7224 -0
- package/dist/index-Efjb3nrQ.d.ts +671 -0
- package/dist/index.d.ts +14 -1134
- package/dist/index.js +2134 -1972
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +776 -888
- package/dist/intelligence.js +1466 -1410
- package/dist/intelligence.js.map +1 -1
- package/dist/{kb-gate-CwHO0vz6.d.ts → kb-gate-C8z2juK8.d.ts} +33 -31
- package/dist/kb-gate-DpaSwXVx.js +80 -0
- package/dist/kb-gate-DpaSwXVx.js.map +1 -0
- package/dist/knowledge-Ku-mPP4f.js +433 -0
- package/dist/knowledge-Ku-mPP4f.js.map +1 -0
- package/dist/knowledge.d.ts +2 -150
- package/dist/knowledge.js +2 -40
- package/dist/local-harness-Dh8PJ0ot.d.ts +455 -0
- package/dist/loop-runner-bin-BXsFEUcf.d.ts +162 -0
- package/dist/loop-runner-bin-BwjQ1NfH.js +268 -0
- package/dist/loop-runner-bin-BwjQ1NfH.js.map +1 -0
- package/dist/loop-runner-bin.d.ts +2 -17
- package/dist/loop-runner-bin.js +2 -24
- package/dist/loops.d.ts +5 -4164
- package/dist/loops.js +8 -419
- package/dist/mcp/bin.d.ts +1 -1
- package/dist/mcp/bin.js +116 -146
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +295 -437
- package/dist/mcp/index.js +1242 -1177
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/memory-bin.d.ts +1 -1
- package/dist/mcp/memory-bin.js +37 -16
- package/dist/mcp/memory-bin.js.map +1 -1
- package/dist/memory-server-DL6cE2Ag.js +234 -0
- package/dist/memory-server-DL6cE2Ag.js.map +1 -0
- package/dist/model-resolution-Btd9iIKV.js +98 -0
- package/dist/model-resolution-Btd9iIKV.js.map +1 -0
- package/dist/openai-tools-B68JaOCx.d.ts +24 -0
- package/dist/openai-tools-CKLy1C7M.js +44 -0
- package/dist/openai-tools-CKLy1C7M.js.map +1 -0
- package/dist/otel-export-D34IQW1C.js +843 -0
- package/dist/otel-export-D34IQW1C.js.map +1 -0
- package/dist/platform.d.ts +188 -185
- package/dist/platform.js +185 -218
- package/dist/platform.js.map +1 -1
- package/dist/prepare-B53sPV7M.js +4292 -0
- package/dist/prepare-B53sPV7M.js.map +1 -0
- package/dist/primeintellect/index.d.ts +150 -147
- package/dist/primeintellect/index.js +626 -1004
- package/dist/primeintellect/index.js.map +1 -1
- package/dist/profiles.d.ts +296 -490
- package/dist/profiles.js +722 -749
- package/dist/profiles.js.map +1 -1
- package/dist/protected-model-port-BLPH5VVv.js +722 -0
- package/dist/protected-model-port-BLPH5VVv.js.map +1 -0
- package/dist/protected-model-port-BP6Z4eau.d.ts +283 -0
- package/dist/protected-redaction--F3v1oo8.js +200 -0
- package/dist/protected-redaction--F3v1oo8.js.map +1 -0
- package/dist/redact-D-u-rrcn.js +82 -0
- package/dist/redact-D-u-rrcn.js.map +1 -0
- package/dist/redact-kbIOjfjM.d.ts +452 -0
- package/dist/researcher-CoVqNhfI.js +433 -0
- package/dist/researcher-CoVqNhfI.js.map +1 -0
- package/dist/runtime-BG0BziaP.js +5408 -0
- package/dist/runtime-BG0BziaP.js.map +1 -0
- package/dist/sandbox-events-DeI5xX8P.js +316 -0
- package/dist/sandbox-events-DeI5xX8P.js.map +1 -0
- package/dist/spawn-journal-CwPvKUTa.js +456 -0
- package/dist/spawn-journal-CwPvKUTa.js.map +1 -0
- package/dist/structural-rollout-IXUEplky.js +1445 -0
- package/dist/structural-rollout-IXUEplky.js.map +1 -0
- package/dist/substrate-B0TYNrXn.js +27 -0
- package/dist/substrate-B0TYNrXn.js.map +1 -0
- package/dist/{substrate-Dyiqmd3o.d.ts → substrate-BcnuSHXm.d.ts} +57 -54
- package/dist/supervise-BiRutHS9.js +7321 -0
- package/dist/supervise-BiRutHS9.js.map +1 -0
- package/dist/supervisor-DTKhF-RV.js +3826 -0
- package/dist/supervisor-DTKhF-RV.js.map +1 -0
- package/dist/testing.d.ts +4 -3
- package/dist/testing.js +2478 -2637
- package/dist/testing.js.map +1 -1
- package/dist/tool-server-RcWgLIsL.js +141 -0
- package/dist/tool-server-RcWgLIsL.js.map +1 -0
- package/dist/trace-propagation-CJJC7SVB.js +57 -0
- package/dist/trace-propagation-CJJC7SVB.js.map +1 -0
- package/dist/types-BaIpb0XT.d.ts +492 -0
- package/dist/types-BevOjfTY.d.ts +765 -0
- package/dist/types-C9j4qg6l.d.ts +500 -0
- package/dist/types-Cja5OTGh.d.ts +190 -0
- package/dist/util-MVgdwuIS.js +145 -0
- package/dist/util-MVgdwuIS.js.map +1 -0
- package/dist/workspace-archive-BosQiotA.js +575 -0
- package/dist/workspace-archive-BosQiotA.js.map +1 -0
- package/package.json +43 -55
- package/skills/build-with-agent-runtime/SKILL.md +16 -9
- package/skills/loop-writer/SKILL.md +1 -1
- package/dist/activation-Cm-9MMX1.d.ts +0 -69
- package/dist/analyst-loop.js.map +0 -1
- package/dist/backends-BO4Jqoe2.d.ts +0 -134
- package/dist/candidate-execution/index.js.map +0 -1
- package/dist/chunk-2KGAN2HM.js +0 -1256
- package/dist/chunk-2KGAN2HM.js.map +0 -1
- package/dist/chunk-2QJSNOGK.js +0 -48
- package/dist/chunk-2QJSNOGK.js.map +0 -1
- package/dist/chunk-2UABGGUB.js +0 -474
- package/dist/chunk-2UABGGUB.js.map +0 -1
- package/dist/chunk-2VZYRB55.js +0 -834
- package/dist/chunk-2VZYRB55.js.map +0 -1
- package/dist/chunk-2X65HYMI.js +0 -3526
- package/dist/chunk-2X65HYMI.js.map +0 -1
- package/dist/chunk-3MDZX7YU.js +0 -125
- package/dist/chunk-3MDZX7YU.js.map +0 -1
- package/dist/chunk-3PPVCS75.js +0 -199
- package/dist/chunk-3PPVCS75.js.map +0 -1
- package/dist/chunk-5HNDYWUT.js +0 -6424
- package/dist/chunk-5HNDYWUT.js.map +0 -1
- package/dist/chunk-5IBQAPVB.js +0 -29
- package/dist/chunk-5IBQAPVB.js.map +0 -1
- package/dist/chunk-5QOB7H74.js +0 -387
- package/dist/chunk-5QOB7H74.js.map +0 -1
- package/dist/chunk-ATDFUJYI.js +0 -4728
- package/dist/chunk-ATDFUJYI.js.map +0 -1
- package/dist/chunk-B7K7V22Y.js +0 -699
- package/dist/chunk-B7K7V22Y.js.map +0 -1
- package/dist/chunk-DPEUKJRO.js +0 -27
- package/dist/chunk-DPEUKJRO.js.map +0 -1
- package/dist/chunk-FD2MBMOH.js +0 -494
- package/dist/chunk-FD2MBMOH.js.map +0 -1
- package/dist/chunk-FJI3EXU3.js +0 -2402
- package/dist/chunk-FJI3EXU3.js.map +0 -1
- package/dist/chunk-HAO4CXHP.js +0 -200
- package/dist/chunk-HAO4CXHP.js.map +0 -1
- package/dist/chunk-ISPWRSEC.js +0 -408
- package/dist/chunk-ISPWRSEC.js.map +0 -1
- package/dist/chunk-KRBFHMV6.js +0 -1228
- package/dist/chunk-KRBFHMV6.js.map +0 -1
- package/dist/chunk-L5DST3QC.js +0 -351
- package/dist/chunk-L5DST3QC.js.map +0 -1
- package/dist/chunk-M22PL4GH.js +0 -171
- package/dist/chunk-M22PL4GH.js.map +0 -1
- package/dist/chunk-NURIQBJQ.js +0 -72
- package/dist/chunk-NURIQBJQ.js.map +0 -1
- package/dist/chunk-PZZKQVQV.js +0 -52
- package/dist/chunk-PZZKQVQV.js.map +0 -1
- package/dist/chunk-Q2JSAVQ3.js +0 -671
- package/dist/chunk-Q2JSAVQ3.js.map +0 -1
- package/dist/chunk-SBTWKPVR.js +0 -5576
- package/dist/chunk-SBTWKPVR.js.map +0 -1
- package/dist/chunk-SGKPNBXE.js +0 -60
- package/dist/chunk-SGKPNBXE.js.map +0 -1
- package/dist/chunk-SNSMRT6H.js +0 -680
- package/dist/chunk-SNSMRT6H.js.map +0 -1
- package/dist/chunk-STJEHM5F.js +0 -1338
- package/dist/chunk-STJEHM5F.js.map +0 -1
- package/dist/chunk-UPWGXKXB.js +0 -254
- package/dist/chunk-UPWGXKXB.js.map +0 -1
- package/dist/chunk-YEJR7IXO.js +0 -68
- package/dist/chunk-YEJR7IXO.js.map +0 -1
- package/dist/chunk-ZXICDSAK.js +0 -907
- package/dist/chunk-ZXICDSAK.js.map +0 -1
- package/dist/completion-gate-Bv47cOnn.d.ts +0 -256
- package/dist/conversation.js.map +0 -1
- package/dist/coordination-CxtzMxSM.d.ts +0 -2570
- package/dist/environment-provider.js.map +0 -1
- package/dist/improve--2A0gK1-.d.ts +0 -440
- package/dist/improvement-adapter-HAZz-7vK.d.ts +0 -203
- package/dist/knowledge.js.map +0 -1
- package/dist/local-harness-CtK9dSny.d.ts +0 -175
- package/dist/loop-runner-bin-DUOGtvOl.d.ts +0 -207
- package/dist/loop-runner-bin.js.map +0 -1
- package/dist/loops.js.map +0 -1
- package/dist/openai-tools-fnj6SRVg.d.ts +0 -46
- package/dist/protected-model-port-DzkUY3HQ.d.ts +0 -271
- package/dist/sanitize-DEbPNtyI.d.ts +0 -328
- package/dist/structural-rollout-C4mabf87.d.ts +0 -446
- package/dist/supervise-7q9F5brx.d.ts +0 -379
- package/dist/types-BCoemcXU.d.ts +0 -802
- package/dist/types-BwoZWq-i.d.ts +0 -510
- package/dist/types-Cbp72qyu.d.ts +0 -491
- package/dist/types-CmYCMbFT.d.ts +0 -203
- package/dist/types-CvNwMzQt.d.ts +0 -957
- package/dist/worktree-fanout-WsOzt8qu.d.ts +0 -999
package/dist/agent.js
CHANGED
|
@@ -1,598 +1,666 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
import "./
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
} from "
|
|
6
|
-
import "
|
|
7
|
-
import "
|
|
8
|
-
import "
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
import { u as ValidationError } from "./errors-DEAvWQPy.js";
|
|
2
|
+
import "./runtime-BG0BziaP.js";
|
|
3
|
+
import { r as mapSandboxEvent } from "./sandbox-events-DeI5xX8P.js";
|
|
4
|
+
import { Rt as createSandboxForSpec } from "./supervise-BiRutHS9.js";
|
|
5
|
+
import { createHash } from "node:crypto";
|
|
6
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
7
|
+
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
8
|
+
import { parseFindingSubject } from "@tangle-network/agent-eval/analyst";
|
|
9
|
+
//#region src/agent/surfaces.ts
|
|
10
|
+
/**
|
|
11
|
+
* `AgentSurfaces` — declarative map of the mutable file/directory paths
|
|
12
|
+
* the self-improvement loop can edit on behalf of an agent.
|
|
13
|
+
*
|
|
14
|
+
* The substrate uses this map to resolve every parsed `FindingSubject`
|
|
15
|
+
* (from agent-eval) to a real on-disk path. No per-vertical glue;
|
|
16
|
+
* no fabricated paths; no silent `existsSync(...)` skips that hide
|
|
17
|
+
* misconfiguration from the operator.
|
|
18
|
+
*
|
|
19
|
+
* Surfaces are validated at `defineAgent` time — missing paths fail
|
|
20
|
+
* loud with a list of every offender. A surface that's not needed
|
|
21
|
+
* (e.g. an agent with no RAG corpora) is simply omitted; the loop
|
|
22
|
+
* refuses to route those subjects rather than fabricating a target.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Resolve a parsed `FindingSubject` to the file path the substrate
|
|
26
|
+
* should edit (or create) on disk.
|
|
27
|
+
*
|
|
28
|
+
* Returns `null` when:
|
|
29
|
+
* - the subject targets a surface the agent didn't declare
|
|
30
|
+
* (e.g. `rag:*` when `surfaces.rag` is undefined), OR
|
|
31
|
+
* - the subject is a `cluster` (failure-mode emits these as evidence,
|
|
32
|
+
* not actionable mutations — they don't route to a file).
|
|
33
|
+
*
|
|
34
|
+
* Returns a `ResolvedSurface` with `intent: 'create-new'` when the
|
|
35
|
+
* subject names a path that doesn't yet exist (e.g. a new wiki page).
|
|
36
|
+
* The caller chooses whether to honour the create — for tightly-managed
|
|
37
|
+
* surfaces like `systemPrompt` it's usually a contract violation
|
|
38
|
+
* (the analyst named a section that doesn't exist); for `knowledge`
|
|
39
|
+
* it's the whole point.
|
|
40
|
+
*/
|
|
24
41
|
function resolveSubjectPath(subject, surfaces, repoRoot) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
const candidates = candidatePathsForSubject(subject, surfaces);
|
|
43
|
+
if (candidates.length === 0) return null;
|
|
44
|
+
for (const rel of candidates) {
|
|
45
|
+
const abs = isAbsolute(rel) ? rel : join(repoRoot, rel);
|
|
46
|
+
if (existsSync(abs)) return {
|
|
47
|
+
absolutePath: abs,
|
|
48
|
+
repoRelativePath: rel,
|
|
49
|
+
exists: true,
|
|
50
|
+
intent: "edit-existing"
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const fallback = candidates[0];
|
|
54
|
+
return {
|
|
55
|
+
absolutePath: isAbsolute(fallback) ? fallback : join(repoRoot, fallback),
|
|
56
|
+
repoRelativePath: fallback,
|
|
57
|
+
exists: false,
|
|
58
|
+
intent: "create-new"
|
|
59
|
+
};
|
|
41
60
|
}
|
|
42
61
|
function candidatePathsForSubject(subject, surfaces) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
case "code": {
|
|
107
|
-
if (!surfaces.code) return [];
|
|
108
|
-
const path = safeJoin(surfaces.code, subject.path);
|
|
109
|
-
return path ? [path] : [];
|
|
110
|
-
}
|
|
111
|
-
case "rag":
|
|
112
|
-
if (!surfaces.rag) return [];
|
|
113
|
-
return optionalPath(safeJoin(surfaces.rag, subject.corpus, `${subject.docId}.md`));
|
|
114
|
-
case "memory":
|
|
115
|
-
if (!surfaces.memory) return [];
|
|
116
|
-
return optionalPath(safeJoin(surfaces.memory, `${slugify(subject.key)}.json`));
|
|
117
|
-
case "scaffolding":
|
|
118
|
-
if (!surfaces.scaffolding) return [];
|
|
119
|
-
return optionalPath(safeJoin(surfaces.scaffolding, `${slugify(subject.concern)}.md`));
|
|
120
|
-
case "output-schema":
|
|
121
|
-
if (!surfaces.outputSchema) return [];
|
|
122
|
-
return [surfaces.outputSchema];
|
|
123
|
-
case "websearch.outdated":
|
|
124
|
-
case "prior-run-summary":
|
|
125
|
-
return [];
|
|
126
|
-
case "cluster":
|
|
127
|
-
return [];
|
|
128
|
-
}
|
|
62
|
+
switch (subject.kind) {
|
|
63
|
+
case "knowledge.wiki":
|
|
64
|
+
case "knowledge.stale": return optionalPath(safeJoin(surfaces.knowledge, `${subject.slug}.md`));
|
|
65
|
+
case "knowledge.claim": return optionalPath(safeJoin(surfaces.knowledge, "claims", `${slugify(subject.topic)}.md`));
|
|
66
|
+
case "knowledge.raw": return optionalPath(safeJoin(surfaces.knowledge, "raw", `${subject.sourceId}.md`));
|
|
67
|
+
case "system-prompt": {
|
|
68
|
+
const slug = slugify(subject.section);
|
|
69
|
+
return [
|
|
70
|
+
safeJoin(surfaces.systemPrompt, `${slug}.md`),
|
|
71
|
+
safeJoin(surfaces.systemPrompt, slug, "SKILL.md"),
|
|
72
|
+
safeJoin(surfaces.systemPrompt, slug, "index.md")
|
|
73
|
+
].filter((path) => path !== null);
|
|
74
|
+
}
|
|
75
|
+
case "skill":
|
|
76
|
+
if (!surfaces.skills) return [];
|
|
77
|
+
return [safeJoin(surfaces.skills, subject.name, "SKILL.md"), safeJoin(surfaces.skills, `${subject.name}.md`)].filter((path) => path !== null);
|
|
78
|
+
case "tool-doc":
|
|
79
|
+
if (subject.aspect) return optionalPath(safeJoin(surfaces.tools, subject.tool, `${slugify(subject.aspect)}.md`));
|
|
80
|
+
return [safeJoin(surfaces.tools, subject.tool, "README.md"), safeJoin(surfaces.tools, `${subject.tool}.md`)].filter((path) => path !== null);
|
|
81
|
+
case "new-tool": return optionalPath(safeJoin(surfaces.tools, subject.name, "README.md"));
|
|
82
|
+
case "mcp":
|
|
83
|
+
if (!surfaces.mcp) return [];
|
|
84
|
+
return subject.tool ? optionalPath(safeJoin(surfaces.mcp, subject.server, `${subject.tool}.md`)) : [safeJoin(surfaces.mcp, `${subject.server}.json`), safeJoin(surfaces.mcp, subject.server, "README.md")].filter((path) => path !== null);
|
|
85
|
+
case "hook":
|
|
86
|
+
if (!surfaces.hooks) return [];
|
|
87
|
+
return [safeJoin(surfaces.hooks, `${subject.name}.md`), safeJoin(surfaces.hooks, `${subject.name}.json`)].filter((path) => path !== null);
|
|
88
|
+
case "subagent":
|
|
89
|
+
if (!surfaces.subagents) return [];
|
|
90
|
+
return [
|
|
91
|
+
safeJoin(surfaces.subagents, `${subject.name}.md`),
|
|
92
|
+
safeJoin(surfaces.subagents, `${subject.name}.yaml`),
|
|
93
|
+
safeJoin(surfaces.subagents, `${subject.name}.json`)
|
|
94
|
+
].filter((path) => path !== null);
|
|
95
|
+
case "workflow":
|
|
96
|
+
if (!surfaces.workflows) return [];
|
|
97
|
+
return [
|
|
98
|
+
safeJoin(surfaces.workflows, `${subject.name}.md`),
|
|
99
|
+
safeJoin(surfaces.workflows, `${subject.name}.yaml`),
|
|
100
|
+
safeJoin(surfaces.workflows, `${subject.name}.json`)
|
|
101
|
+
].filter((path) => path !== null);
|
|
102
|
+
case "rollout-policy": return surfaces.rolloutPolicy ? [surfaces.rolloutPolicy] : [];
|
|
103
|
+
case "agent-profile": return surfaces.agentProfile ? [surfaces.agentProfile] : [];
|
|
104
|
+
case "code": {
|
|
105
|
+
if (!surfaces.code) return [];
|
|
106
|
+
const path = safeJoin(surfaces.code, subject.path);
|
|
107
|
+
return path ? [path] : [];
|
|
108
|
+
}
|
|
109
|
+
case "rag":
|
|
110
|
+
if (!surfaces.rag) return [];
|
|
111
|
+
return optionalPath(safeJoin(surfaces.rag, subject.corpus, `${subject.docId}.md`));
|
|
112
|
+
case "memory":
|
|
113
|
+
if (!surfaces.memory) return [];
|
|
114
|
+
return optionalPath(safeJoin(surfaces.memory, `${slugify(subject.key)}.json`));
|
|
115
|
+
case "scaffolding":
|
|
116
|
+
if (!surfaces.scaffolding) return [];
|
|
117
|
+
return optionalPath(safeJoin(surfaces.scaffolding, `${slugify(subject.concern)}.md`));
|
|
118
|
+
case "output-schema":
|
|
119
|
+
if (!surfaces.outputSchema) return [];
|
|
120
|
+
return [surfaces.outputSchema];
|
|
121
|
+
case "websearch.outdated":
|
|
122
|
+
case "prior-run-summary": return [];
|
|
123
|
+
case "cluster": return [];
|
|
124
|
+
}
|
|
129
125
|
}
|
|
130
126
|
function safeJoin(root, ...children) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return join(root, ...children);
|
|
127
|
+
if (children.some((child) => child.includes("\0") || isAbsolute(child))) return null;
|
|
128
|
+
const rootAbsolute = resolve(root);
|
|
129
|
+
const escaped = relative(rootAbsolute, resolve(rootAbsolute, ...children));
|
|
130
|
+
if (escaped === ".." || escaped.startsWith(`..${sep}`) || isAbsolute(escaped)) return null;
|
|
131
|
+
return join(root, ...children);
|
|
137
132
|
}
|
|
138
133
|
function optionalPath(path) {
|
|
139
|
-
|
|
134
|
+
return path ? [path] : [];
|
|
140
135
|
}
|
|
141
136
|
function slugify(s) {
|
|
142
|
-
|
|
137
|
+
return s.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 200) || "untitled";
|
|
143
138
|
}
|
|
139
|
+
/** Validate an `AgentSurfaces` map on disk — missing paths fail loud at `defineAgent` time instead of silently skipping self-improvement edits. */
|
|
144
140
|
function validateSurfaces(surfaces, repoRoot) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
141
|
+
const issues = [];
|
|
142
|
+
const dirSurfaces = [
|
|
143
|
+
"systemPrompt",
|
|
144
|
+
"tools",
|
|
145
|
+
"personas",
|
|
146
|
+
"knowledge"
|
|
147
|
+
];
|
|
148
|
+
const fileSurfaces = ["rubric"];
|
|
149
|
+
const optionalDirSurfaces = [
|
|
150
|
+
"scaffolding",
|
|
151
|
+
"memory",
|
|
152
|
+
"rag",
|
|
153
|
+
"skills",
|
|
154
|
+
"mcp",
|
|
155
|
+
"hooks",
|
|
156
|
+
"subagents",
|
|
157
|
+
"workflows",
|
|
158
|
+
"code"
|
|
159
|
+
];
|
|
160
|
+
const optionalFileSurfaces = [
|
|
161
|
+
"outputSchema",
|
|
162
|
+
"rolloutPolicy",
|
|
163
|
+
"agentProfile"
|
|
164
|
+
];
|
|
165
|
+
for (const key of dirSurfaces) {
|
|
166
|
+
const p = surfaces[key];
|
|
167
|
+
if (!p) {
|
|
168
|
+
issues.push({
|
|
169
|
+
surface: key,
|
|
170
|
+
path: "",
|
|
171
|
+
reason: "missing"
|
|
172
|
+
});
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const abs = isAbsolute(p) ? p : join(repoRoot, p);
|
|
176
|
+
if (!existsSync(abs)) issues.push({
|
|
177
|
+
surface: key,
|
|
178
|
+
path: p,
|
|
179
|
+
reason: "missing"
|
|
180
|
+
});
|
|
181
|
+
else if (!statSync(abs).isDirectory()) issues.push({
|
|
182
|
+
surface: key,
|
|
183
|
+
path: p,
|
|
184
|
+
reason: "not-directory"
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
for (const key of fileSurfaces) {
|
|
188
|
+
const p = surfaces[key];
|
|
189
|
+
if (!p) {
|
|
190
|
+
issues.push({
|
|
191
|
+
surface: key,
|
|
192
|
+
path: "",
|
|
193
|
+
reason: "missing"
|
|
194
|
+
});
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
const abs = isAbsolute(p) ? p : join(repoRoot, p);
|
|
198
|
+
if (!existsSync(abs)) issues.push({
|
|
199
|
+
surface: key,
|
|
200
|
+
path: p,
|
|
201
|
+
reason: "missing"
|
|
202
|
+
});
|
|
203
|
+
else if (!statSync(abs).isFile()) issues.push({
|
|
204
|
+
surface: key,
|
|
205
|
+
path: p,
|
|
206
|
+
reason: "not-file"
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
for (const key of [...optionalDirSurfaces, ...optionalFileSurfaces]) {
|
|
210
|
+
const p = surfaces[key];
|
|
211
|
+
if (p === void 0) continue;
|
|
212
|
+
const abs = isAbsolute(p) ? p : join(repoRoot, p);
|
|
213
|
+
if (!existsSync(abs)) {
|
|
214
|
+
issues.push({
|
|
215
|
+
surface: key,
|
|
216
|
+
path: p,
|
|
217
|
+
reason: "missing"
|
|
218
|
+
});
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const expectedDirectory = optionalDirSurfaces.includes(key);
|
|
222
|
+
if (expectedDirectory && !statSync(abs).isDirectory()) issues.push({
|
|
223
|
+
surface: key,
|
|
224
|
+
path: p,
|
|
225
|
+
reason: "not-directory"
|
|
226
|
+
});
|
|
227
|
+
else if (!expectedDirectory && !statSync(abs).isFile()) issues.push({
|
|
228
|
+
surface: key,
|
|
229
|
+
path: p,
|
|
230
|
+
reason: "not-file"
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
return issues;
|
|
211
234
|
}
|
|
235
|
+
/** Format a list of surface validation issues into a human-readable error string. */
|
|
212
236
|
function renderSurfaceIssues(issues, repoRoot) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
"surfaces rather than fabricating a path."
|
|
226
|
-
].join("\n");
|
|
237
|
+
if (issues.length === 0) return "";
|
|
238
|
+
const lines = issues.map((i) => ` - ${i.surface}: ${i.path ? `"${i.path}"` : "<not set>"} (${i.reason})`);
|
|
239
|
+
return [
|
|
240
|
+
`Agent surface validation failed against repoRoot=${repoRoot}:`,
|
|
241
|
+
...lines,
|
|
242
|
+
"",
|
|
243
|
+
"Fix the manifest: every required surface must point at an existing",
|
|
244
|
+
"directory (systemPrompt / tools / personas / knowledge) or file",
|
|
245
|
+
"(rubric). Optional surfaces (scaffolding / memory / rag / outputSchema)",
|
|
246
|
+
"may be omitted; the loop will reject findings targeting omitted",
|
|
247
|
+
"surfaces rather than fabricating a path."
|
|
248
|
+
].join("\n");
|
|
227
249
|
}
|
|
228
|
-
|
|
229
|
-
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/agent/define-agent.ts
|
|
252
|
+
/**
|
|
253
|
+
* Stub for agents whose `runtime.act` is not yet wired to the substrate's
|
|
254
|
+
* eval path. Preserves the streaming contract (empty event stream + a
|
|
255
|
+
* rejected `output` promise that tells the caller exactly what to fix).
|
|
256
|
+
*
|
|
257
|
+
* Per-vertical manifests usually start with this stub and replace it with
|
|
258
|
+
* the agent's real streaming runtime (`runChatTurn` or equivalent) once
|
|
259
|
+
* the eval path consumes the manifest end-to-end.
|
|
260
|
+
*/
|
|
230
261
|
function unimplementedAgentRun(reason = "AgentRuntime.act is not yet wired for this manifest") {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
};
|
|
262
|
+
return {
|
|
263
|
+
events: (async function* empty() {})(),
|
|
264
|
+
output: Promise.reject(new Error(reason))
|
|
265
|
+
};
|
|
236
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* Drain `act`'s `events` into an array AND await its `output`. Useful for
|
|
269
|
+
* eval / outcome-measurement code paths that don't care about live
|
|
270
|
+
* rendering. The events array is preserved so the substrate can inspect
|
|
271
|
+
* tool calls / readiness / questions retrospectively.
|
|
272
|
+
*
|
|
273
|
+
* IMPORTANT: chat-centric UX MUST NOT call this — it defeats streaming
|
|
274
|
+
* (no incremental render). Use `for await (const ev of invocation.events)`
|
|
275
|
+
* directly in the chat surface.
|
|
276
|
+
*/
|
|
237
277
|
async function collectAgentRun(invocation) {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
278
|
+
const events = [];
|
|
279
|
+
for await (const ev of invocation.events) events.push(ev);
|
|
280
|
+
return {
|
|
281
|
+
events,
|
|
282
|
+
output: await invocation.output
|
|
283
|
+
};
|
|
242
284
|
}
|
|
285
|
+
/** Thrown when `defineAgent` finds a required surface missing on disk. */
|
|
243
286
|
var AgentManifestError = class extends Error {
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
287
|
+
agentId;
|
|
288
|
+
issues;
|
|
289
|
+
constructor(message, agentId, issues = []) {
|
|
290
|
+
super(message);
|
|
291
|
+
this.agentId = agentId;
|
|
292
|
+
this.issues = issues;
|
|
293
|
+
this.name = "AgentManifestError";
|
|
294
|
+
}
|
|
252
295
|
};
|
|
296
|
+
/**
|
|
297
|
+
* Construct a validated agent manifest. Throws `AgentManifestError`
|
|
298
|
+
* if any required surface is missing on disk.
|
|
299
|
+
*
|
|
300
|
+
* Generics: pass your persona / output types if you want narrowed
|
|
301
|
+
* `runtime.act` signatures:
|
|
302
|
+
* `defineAgent<TaxPersona, TaxRunOutput>({ ... })`
|
|
303
|
+
*
|
|
304
|
+
* Most callers don't need the generics — the substrate operates on
|
|
305
|
+
* `unknown` payloads internally and the manifest's `score` /
|
|
306
|
+
* `runtime.act` see the typed shapes via TypeScript inference at
|
|
307
|
+
* the call site.
|
|
308
|
+
*/
|
|
253
309
|
function defineAgent(manifest) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
if (issues.length > 0) {
|
|
262
|
-
throw new AgentManifestError(
|
|
263
|
-
renderSurfaceIssues(issues, manifest.repoRoot),
|
|
264
|
-
manifest.id,
|
|
265
|
-
issues
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
const total = manifest.rubric.dimensions.reduce((acc, d) => acc + d.weight, 0);
|
|
269
|
-
if (manifest.rubric.dimensions.length > 0 && (total < 0.5 || total > 1.5)) {
|
|
270
|
-
throw new AgentManifestError(
|
|
271
|
-
`defineAgent(${manifest.id}): rubric dimension weights sum to ${total.toFixed(3)} \u2014 should be ~1.0`,
|
|
272
|
-
manifest.id
|
|
273
|
-
);
|
|
274
|
-
}
|
|
275
|
-
return manifest;
|
|
310
|
+
if (!manifest.id || manifest.id.trim().length === 0) throw new AgentManifestError("defineAgent: `id` is required", manifest.id ?? "");
|
|
311
|
+
if (!manifest.repoRoot || manifest.repoRoot.trim().length === 0) throw new AgentManifestError("defineAgent: `repoRoot` is required", manifest.id);
|
|
312
|
+
const issues = validateSurfaces(manifest.surfaces, manifest.repoRoot);
|
|
313
|
+
if (issues.length > 0) throw new AgentManifestError(renderSurfaceIssues(issues, manifest.repoRoot), manifest.id, issues);
|
|
314
|
+
const total = manifest.rubric.dimensions.reduce((acc, d) => acc + d.weight, 0);
|
|
315
|
+
if (manifest.rubric.dimensions.length > 0 && (total < .5 || total > 1.5)) throw new AgentManifestError(`defineAgent(${manifest.id}): rubric dimension weights sum to ${total.toFixed(3)} — should be ~1.0`, manifest.id);
|
|
316
|
+
return manifest;
|
|
276
317
|
}
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
318
|
+
//#endregion
|
|
319
|
+
//#region src/agent/improvement-adapter.ts
|
|
320
|
+
/**
|
|
321
|
+
* Surface improvement proposer — resolves analyst findings into LLM-drafted
|
|
322
|
+
* candidate patches without changing the caller's repository.
|
|
323
|
+
*
|
|
324
|
+
* The proposer parses each finding's `subject` via
|
|
325
|
+
* `parseFindingSubject` (agent-eval), resolves it to a real file path
|
|
326
|
+
* via the agent's `AgentSurfaces`, reads the current content, and asks
|
|
327
|
+
* an LLM to draft a unified-diff patch given the finding + current
|
|
328
|
+
* content + per-kind editing-discipline rules.
|
|
329
|
+
*
|
|
330
|
+
* Fail-loud rules:
|
|
331
|
+
* - Findings whose subject doesn't parse → counted in `errors`.
|
|
332
|
+
* - Findings whose subject targets an undeclared surface → counted in
|
|
333
|
+
* `errors` with the offending kind in the message.
|
|
334
|
+
* - Findings whose target path doesn't exist AND the kind isn't a
|
|
335
|
+
* create-new variant (`new-tool`, `knowledge.wiki`) → counted in
|
|
336
|
+
* `errors` with the resolved path in the message.
|
|
337
|
+
* - LLM drafts that fail JSON-schema validation → counted in
|
|
338
|
+
* `errors` with the schema issue.
|
|
339
|
+
*
|
|
340
|
+
* No silent skips. Every dropped finding has a recorded reason the
|
|
341
|
+
* loop's report surfaces.
|
|
342
|
+
*/
|
|
343
|
+
const DEFAULT_CREATE_KINDS = [
|
|
344
|
+
"knowledge.wiki",
|
|
345
|
+
"knowledge.claim",
|
|
346
|
+
"knowledge.raw",
|
|
347
|
+
"new-tool"
|
|
287
348
|
];
|
|
349
|
+
/** Resolve each finding to a real surface and draft a detached patch candidate. */
|
|
288
350
|
function createSurfaceImprovementProposer(opts) {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
351
|
+
const allowCreate = opts.allowCreateForKinds ?? DEFAULT_CREATE_KINDS;
|
|
352
|
+
return { async proposeFromFindings(findings) {
|
|
353
|
+
const edits = [];
|
|
354
|
+
const errors = [];
|
|
355
|
+
let skipped = 0;
|
|
356
|
+
for (const f of findings) {
|
|
357
|
+
const subject = parseFindingSubject(f.subject);
|
|
358
|
+
if (subject === null) {
|
|
359
|
+
if (f.subject !== void 0) errors.push({
|
|
360
|
+
findingId: f.finding_id,
|
|
361
|
+
subject: f.subject,
|
|
362
|
+
message: "subject does not parse against the finding-subject grammar"
|
|
363
|
+
});
|
|
364
|
+
else skipped += 1;
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (subject.kind === "cluster") {
|
|
368
|
+
skipped += 1;
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
if (subject.kind.startsWith("knowledge.")) {
|
|
372
|
+
skipped += 1;
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
const target = resolveSubjectPath(subject, opts.surfaces, opts.repoRoot);
|
|
376
|
+
if (target === null) {
|
|
377
|
+
errors.push({
|
|
378
|
+
findingId: f.finding_id,
|
|
379
|
+
subject: f.subject ?? "",
|
|
380
|
+
message: `subject kind "${subject.kind}" targets an undeclared surface; declare it in AgentSurfaces or stop emitting this subject`
|
|
381
|
+
});
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (target.intent === "create-new" && !allowCreate.includes(subject.kind)) {
|
|
385
|
+
errors.push({
|
|
386
|
+
findingId: f.finding_id,
|
|
387
|
+
subject: f.subject ?? "",
|
|
388
|
+
message: `target ${target.repoRelativePath} does not exist; the kind "${subject.kind}" requires an existing target (analyst named a section that isn't in the codebase)`
|
|
389
|
+
});
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
const currentContent = target.exists ? readFileSync(target.absolutePath, "utf-8") : "";
|
|
393
|
+
let draft;
|
|
394
|
+
try {
|
|
395
|
+
draft = await opts.draftPatch({
|
|
396
|
+
finding: f,
|
|
397
|
+
subject,
|
|
398
|
+
target,
|
|
399
|
+
currentContent
|
|
400
|
+
});
|
|
401
|
+
} catch (err) {
|
|
402
|
+
errors.push({
|
|
403
|
+
findingId: f.finding_id,
|
|
404
|
+
subject: f.subject ?? "",
|
|
405
|
+
message: `draftPatch threw: ${err instanceof Error ? err.message : String(err)}`
|
|
406
|
+
});
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
if (draft.patch.trim().length === 0) {
|
|
410
|
+
skipped += 1;
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
edits.push({
|
|
414
|
+
id: `imp-${f.finding_id}`,
|
|
415
|
+
sourceFindingId: f.finding_id,
|
|
416
|
+
subject,
|
|
417
|
+
target,
|
|
418
|
+
baseSha256: sha256(currentContent),
|
|
419
|
+
patch: draft.patch,
|
|
420
|
+
summary: draft.summary,
|
|
421
|
+
rationale: draft.rationale,
|
|
422
|
+
confidence: f.confidence,
|
|
423
|
+
severity: f.severity
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
edits,
|
|
428
|
+
skipped,
|
|
429
|
+
errors
|
|
430
|
+
};
|
|
431
|
+
} };
|
|
366
432
|
}
|
|
367
433
|
function sha256(s) {
|
|
368
|
-
|
|
434
|
+
return createHash("sha256").update(s, "utf-8").digest("hex");
|
|
369
435
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region src/agent/profile-materialization.ts
|
|
438
|
+
/** Known AgentProfile axes a run path may or may not carry into execution. */
|
|
439
|
+
const AGENT_PROFILE_MATERIALIZATION_AXES = [
|
|
440
|
+
"identity",
|
|
441
|
+
"name",
|
|
442
|
+
"model",
|
|
443
|
+
"prompt",
|
|
444
|
+
"systemPrompt",
|
|
445
|
+
"instructions",
|
|
446
|
+
"resources",
|
|
447
|
+
"files",
|
|
448
|
+
"resourceInstructions",
|
|
449
|
+
"skills",
|
|
450
|
+
"resourceTools",
|
|
451
|
+
"resourceAgents",
|
|
452
|
+
"commands",
|
|
453
|
+
"tools",
|
|
454
|
+
"permissions",
|
|
455
|
+
"mcp",
|
|
456
|
+
"mcpConnections",
|
|
457
|
+
"connections",
|
|
458
|
+
"subagents",
|
|
459
|
+
"hooks",
|
|
460
|
+
"modes",
|
|
461
|
+
"confidential",
|
|
462
|
+
"metadata",
|
|
463
|
+
"extensions"
|
|
397
464
|
];
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
465
|
+
const KNOWN_AXIS_SET = new Set(AGENT_PROFILE_MATERIALIZATION_AXES);
|
|
466
|
+
const AXIS_PARENTS = {
|
|
467
|
+
name: "identity",
|
|
468
|
+
systemPrompt: "prompt",
|
|
469
|
+
instructions: "prompt",
|
|
470
|
+
files: "resources",
|
|
471
|
+
resourceInstructions: "resources",
|
|
472
|
+
skills: "resources",
|
|
473
|
+
resourceTools: "resources",
|
|
474
|
+
resourceAgents: "resources",
|
|
475
|
+
commands: "resources",
|
|
476
|
+
mcpConnections: "mcp"
|
|
410
477
|
};
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
478
|
+
/** Materialization contract for `createSandboxAct`, which forwards the full AgentProfile. */
|
|
479
|
+
const sandboxActProfileMaterialization = defineProfileMaterializationContract({
|
|
480
|
+
name: "createSandboxAct",
|
|
481
|
+
axes: [
|
|
482
|
+
"identity",
|
|
483
|
+
"model",
|
|
484
|
+
"prompt",
|
|
485
|
+
"resources",
|
|
486
|
+
"tools",
|
|
487
|
+
"permissions",
|
|
488
|
+
"mcp",
|
|
489
|
+
"connections",
|
|
490
|
+
"subagents",
|
|
491
|
+
"hooks",
|
|
492
|
+
"modes",
|
|
493
|
+
"confidential",
|
|
494
|
+
"metadata",
|
|
495
|
+
"extensions"
|
|
496
|
+
]
|
|
429
497
|
});
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
498
|
+
/** Materialization contract for a run path that only injects prompt text. */
|
|
499
|
+
const promptOnlyProfileMaterialization = defineProfileMaterializationContract({
|
|
500
|
+
name: "prompt-only-message",
|
|
501
|
+
axes: ["prompt"]
|
|
433
502
|
});
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
503
|
+
/** Materialization contract for a run path that injects prompt text plus inline resources. */
|
|
504
|
+
const promptResourceProfileMaterialization = defineProfileMaterializationContract({
|
|
505
|
+
name: "prompt-resource-attachment",
|
|
506
|
+
axes: ["prompt", "resources"]
|
|
437
507
|
});
|
|
508
|
+
/** Define the profile axes a concrete run path actually carries into execution. */
|
|
438
509
|
function defineProfileMaterializationContract(options) {
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
axes: normalizeAxes(options.axes, `${name}.axes`)
|
|
446
|
-
};
|
|
510
|
+
const name = options.name.trim();
|
|
511
|
+
if (!name) throw new ValidationError("defineProfileMaterializationContract: name is required");
|
|
512
|
+
return {
|
|
513
|
+
name,
|
|
514
|
+
axes: normalizeAxes(options.axes, `${name}.axes`)
|
|
515
|
+
};
|
|
447
516
|
}
|
|
517
|
+
/** Return every changed profile axis that the selected run path would drop. */
|
|
448
518
|
function validateProfileMaterialization(options) {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
463
|
-
return issues;
|
|
519
|
+
const changedAxes = normalizeAxes(options.changedAxes, "changedAxes");
|
|
520
|
+
const supported = new Set(normalizeAxes(options.contract.axes, `${options.contract.name}.axes`));
|
|
521
|
+
const issues = [];
|
|
522
|
+
for (const axis of changedAxes) {
|
|
523
|
+
if (isAxisSupported(axis, supported)) continue;
|
|
524
|
+
issues.push({
|
|
525
|
+
contract: options.contract.name,
|
|
526
|
+
axis,
|
|
527
|
+
reason: "unsupported-axis",
|
|
528
|
+
supportedAxes: [...supported]
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
return issues;
|
|
464
532
|
}
|
|
533
|
+
/** Throw when a candidate changes axes the selected run path cannot carry. */
|
|
465
534
|
function assertProfileMaterialization(options) {
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
535
|
+
const issues = validateProfileMaterialization(options);
|
|
536
|
+
if (issues.length === 0) return;
|
|
537
|
+
throw new ValidationError(renderProfileMaterializationIssues(issues, options.context));
|
|
469
538
|
}
|
|
539
|
+
/** Format profile-axis drop issues into a concise operator-facing error. */
|
|
470
540
|
function renderProfileMaterializationIssues(issues, context) {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
541
|
+
if (issues.length === 0) return "";
|
|
542
|
+
const contract = issues[0]?.contract ?? "<unknown>";
|
|
543
|
+
const prefix = context ? `${context}: ` : "";
|
|
544
|
+
const droppedAxes = issues.map((issue) => issue.axis).join(", ");
|
|
545
|
+
const supportedAxes = issues[0]?.supportedAxes.join(", ") || "<none>";
|
|
546
|
+
return [
|
|
547
|
+
`${prefix}profile materialization would drop axis changes on "${contract}": ${droppedAxes}.`,
|
|
548
|
+
`Supported axes: ${supportedAxes}.`,
|
|
549
|
+
"Use a run path that carries those AgentProfile axes, or remove them from the candidate."
|
|
550
|
+
].join("\n");
|
|
481
551
|
}
|
|
482
552
|
function normalizeAxes(axes, label) {
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
553
|
+
const out = [];
|
|
554
|
+
const seen = /* @__PURE__ */ new Set();
|
|
555
|
+
for (const raw of axes) {
|
|
556
|
+
const axis = normalizeAxis(raw, label);
|
|
557
|
+
if (seen.has(axis)) continue;
|
|
558
|
+
seen.add(axis);
|
|
559
|
+
out.push(axis);
|
|
560
|
+
}
|
|
561
|
+
return out;
|
|
492
562
|
}
|
|
493
563
|
function normalizeAxis(raw, label) {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
throw new ValidationError(`${label}: profile axis must be non-empty`);
|
|
500
|
-
}
|
|
501
|
-
if (!KNOWN_AXIS_SET.has(axis) && !axis.startsWith("custom:")) {
|
|
502
|
-
throw new ValidationError(
|
|
503
|
-
`${label}: unknown profile axis "${axis}". Use a known axis or custom:<name>.`
|
|
504
|
-
);
|
|
505
|
-
}
|
|
506
|
-
return axis;
|
|
564
|
+
if (typeof raw !== "string") throw new ValidationError(`${label}: profile axis must be a string`);
|
|
565
|
+
const axis = raw.trim();
|
|
566
|
+
if (!axis) throw new ValidationError(`${label}: profile axis must be non-empty`);
|
|
567
|
+
if (!KNOWN_AXIS_SET.has(axis) && !axis.startsWith("custom:")) throw new ValidationError(`${label}: unknown profile axis "${axis}". Use a known axis or custom:<name>.`);
|
|
568
|
+
return axis;
|
|
507
569
|
}
|
|
508
570
|
function isAxisSupported(axis, supported) {
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
571
|
+
if (supported.has(axis)) return true;
|
|
572
|
+
let parent = AXIS_PARENTS[axis];
|
|
573
|
+
while (parent) {
|
|
574
|
+
if (supported.has(parent)) return true;
|
|
575
|
+
parent = AXIS_PARENTS[parent];
|
|
576
|
+
}
|
|
577
|
+
return false;
|
|
516
578
|
}
|
|
517
|
-
|
|
518
|
-
|
|
579
|
+
//#endregion
|
|
580
|
+
//#region src/agent/sandbox-act.ts
|
|
581
|
+
/**
|
|
582
|
+
* Build an `AgentRuntime.act` implementation backed by a single prod-profile
|
|
583
|
+
* sandbox run. The returned function honours the `act` contract: it returns
|
|
584
|
+
* synchronously with a live `events` iterator and an `output` promise that
|
|
585
|
+
* resolves only after the iterator drains.
|
|
586
|
+
*/
|
|
519
587
|
function createSandboxAct(options) {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
588
|
+
assertProfileMaterialization({
|
|
589
|
+
contract: sandboxActProfileMaterialization,
|
|
590
|
+
changedAxes: options.requiredProfileAxes ?? [],
|
|
591
|
+
context: "createSandboxAct"
|
|
592
|
+
});
|
|
593
|
+
const mapEvent = options.mapEvent ?? mapSandboxEvent;
|
|
594
|
+
return (persona, ctx) => {
|
|
595
|
+
const profile = applyComposeOverrides(options.baseProfile, options.compose?.(persona));
|
|
596
|
+
const agentRunName = options.name ?? profile.name ?? "agent";
|
|
597
|
+
const message = options.buildPrompt(persona);
|
|
598
|
+
const signal = ctx.signal ?? new AbortController().signal;
|
|
599
|
+
const raw = [];
|
|
600
|
+
let settle;
|
|
601
|
+
let fail;
|
|
602
|
+
const output = new Promise((resolve, reject) => {
|
|
603
|
+
settle = resolve;
|
|
604
|
+
fail = reject;
|
|
605
|
+
});
|
|
606
|
+
output.catch(() => {});
|
|
607
|
+
const spec = {
|
|
608
|
+
profile,
|
|
609
|
+
taskToPrompt: () => message,
|
|
610
|
+
name: agentRunName,
|
|
611
|
+
...options.sandboxOverrides ? { sandboxOverrides: options.sandboxOverrides } : {}
|
|
612
|
+
};
|
|
613
|
+
async function* events() {
|
|
614
|
+
try {
|
|
615
|
+
const box = await createSandboxForSpec(options.sandboxClient, spec, signal);
|
|
616
|
+
for await (const event of box.streamPrompt(message, { signal })) {
|
|
617
|
+
raw.push(event);
|
|
618
|
+
const mapped = mapEvent(event, { agentRunName });
|
|
619
|
+
if (mapped) yield mapped;
|
|
620
|
+
}
|
|
621
|
+
settle(options.output.parse(raw));
|
|
622
|
+
} catch (err) {
|
|
623
|
+
fail(err);
|
|
624
|
+
throw err;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return {
|
|
628
|
+
events: events(),
|
|
629
|
+
output
|
|
630
|
+
};
|
|
631
|
+
};
|
|
562
632
|
}
|
|
633
|
+
/** Overlay the per-persona overrides onto the base profile. Each slot merges over the base; an
|
|
634
|
+
* absent override leaves the base profile untouched. */
|
|
563
635
|
function applyComposeOverrides(base, overrides) {
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
636
|
+
if (!overrides) return base;
|
|
637
|
+
const prompt = overrides.systemPrompt ? {
|
|
638
|
+
...base.prompt,
|
|
639
|
+
systemPrompt: overrides.systemPrompt
|
|
640
|
+
} : base.prompt;
|
|
641
|
+
const mergedTools = overrides.tools ? {
|
|
642
|
+
...base.tools ?? {},
|
|
643
|
+
...overrides.tools
|
|
644
|
+
} : base.tools;
|
|
645
|
+
const mergedMcp = overrides.mcpConnections ? {
|
|
646
|
+
...base.mcp ?? {},
|
|
647
|
+
...overrides.mcpConnections
|
|
648
|
+
} : base.mcp;
|
|
649
|
+
const baseFiles = base.resources?.files ?? [];
|
|
650
|
+
const mergedFiles = overrides.extraFiles?.length ? [...baseFiles, ...overrides.extraFiles] : [...baseFiles];
|
|
651
|
+
return {
|
|
652
|
+
...base,
|
|
653
|
+
name: overrides.name ?? base.name,
|
|
654
|
+
prompt,
|
|
655
|
+
...mergedTools ? { tools: mergedTools } : {},
|
|
656
|
+
...mergedMcp ? { mcp: mergedMcp } : {},
|
|
657
|
+
resources: {
|
|
658
|
+
...base.resources,
|
|
659
|
+
files: mergedFiles
|
|
660
|
+
}
|
|
661
|
+
};
|
|
578
662
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
assertProfileMaterialization,
|
|
583
|
-
collectAgentRun,
|
|
584
|
-
createSandboxAct,
|
|
585
|
-
createSurfaceImprovementProposer,
|
|
586
|
-
defineAgent,
|
|
587
|
-
defineProfileMaterializationContract,
|
|
588
|
-
promptOnlyProfileMaterialization,
|
|
589
|
-
promptResourceProfileMaterialization,
|
|
590
|
-
renderProfileMaterializationIssues,
|
|
591
|
-
renderSurfaceIssues,
|
|
592
|
-
resolveSubjectPath,
|
|
593
|
-
sandboxActProfileMaterialization,
|
|
594
|
-
unimplementedAgentRun,
|
|
595
|
-
validateProfileMaterialization,
|
|
596
|
-
validateSurfaces
|
|
597
|
-
};
|
|
663
|
+
//#endregion
|
|
664
|
+
export { AGENT_PROFILE_MATERIALIZATION_AXES, AgentManifestError, assertProfileMaterialization, collectAgentRun, createSandboxAct, createSurfaceImprovementProposer, defineAgent, defineProfileMaterializationContract, promptOnlyProfileMaterialization, promptResourceProfileMaterialization, renderProfileMaterializationIssues, renderSurfaceIssues, resolveSubjectPath, sandboxActProfileMaterialization, unimplementedAgentRun, validateProfileMaterialization, validateSurfaces };
|
|
665
|
+
|
|
598
666
|
//# sourceMappingURL=agent.js.map
|