@tangle-network/agent-profile-materialize 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1226 -29
- package/dist/index.js +4987 -23
- package/package.json +7 -5
- package/dist/candidate-types.d.ts +0 -36
- package/dist/candidate-types.js +0 -1
- package/dist/candidate.d.ts +0 -9
- package/dist/candidate.js +0 -283
- package/dist/commands.d.ts +0 -2
- package/dist/commands.js +0 -32
- package/dist/control-maps.d.ts +0 -58
- package/dist/control-maps.js +0 -277
- package/dist/execution-controls.d.ts +0 -5
- package/dist/execution-controls.js +0 -199
- package/dist/harness-prompt.d.ts +0 -22
- package/dist/harness-prompt.js +0 -64
- package/dist/harness.d.ts +0 -131
- package/dist/harness.js +0 -416
- package/dist/hooks.d.ts +0 -6
- package/dist/hooks.js +0 -250
- package/dist/managed-workspace-bind.d.ts +0 -4
- package/dist/managed-workspace-bind.js +0 -112
- package/dist/managed-workspace-stage.d.ts +0 -25
- package/dist/managed-workspace-stage.js +0 -199
- package/dist/managed-workspace-types.d.ts +0 -38
- package/dist/managed-workspace-types.js +0 -1
- package/dist/managed-workspace.d.ts +0 -37
- package/dist/managed-workspace.js +0 -290
- package/dist/mcp-config-ownership.d.ts +0 -13
- package/dist/mcp-config-ownership.js +0 -79
- package/dist/mcp-opencode.d.ts +0 -25
- package/dist/mcp-opencode.js +0 -52
- package/dist/mcp-timeouts.d.ts +0 -7
- package/dist/mcp-timeouts.js +0 -48
- package/dist/mcp.d.ts +0 -4
- package/dist/mcp.js +0 -246
- package/dist/model-id.d.ts +0 -55
- package/dist/model-id.js +0 -67
- package/dist/pi-models-config.d.ts +0 -32
- package/dist/pi-models-config.js +0 -65
- package/dist/plan-application.d.ts +0 -10
- package/dist/plan-application.js +0 -190
- package/dist/plan-digest.d.ts +0 -18
- package/dist/plan-digest.js +0 -116
- package/dist/plan-json.d.ts +0 -13
- package/dist/plan-json.js +0 -91
- package/dist/plan-normalize.d.ts +0 -12
- package/dist/plan-normalize.js +0 -168
- package/dist/plan-prompt.d.ts +0 -38
- package/dist/plan-prompt.js +0 -49
- package/dist/plan-support.d.ts +0 -9
- package/dist/plan-support.js +0 -22
- package/dist/plan-types.d.ts +0 -341
- package/dist/plan-types.js +0 -105
- package/dist/prime-agent-dir.d.ts +0 -64
- package/dist/prime-agent-dir.js +0 -173
- package/dist/prime-fork.d.ts +0 -155
- package/dist/prime-fork.js +0 -262
- package/dist/prime-profile.d.ts +0 -88
- package/dist/prime-profile.js +0 -297
- package/dist/profile-bundle-cache.d.ts +0 -37
- package/dist/profile-bundle-cache.js +0 -320
- package/dist/profile-bundle-key.d.ts +0 -69
- package/dist/profile-bundle-key.js +0 -62
- package/dist/profile-bundle-lru.d.ts +0 -56
- package/dist/profile-bundle-lru.js +0 -220
- package/dist/profile-materializer.d.ts +0 -24
- package/dist/profile-materializer.js +0 -114
- package/dist/profile-plan.d.ts +0 -16
- package/dist/profile-plan.js +0 -90
- package/dist/profile-prompt.d.ts +0 -4
- package/dist/profile-prompt.js +0 -107
- package/dist/profile-support.d.ts +0 -8
- package/dist/profile-support.js +0 -6
- package/dist/resource-lowering.d.ts +0 -6
- package/dist/resource-lowering.js +0 -103
- package/dist/resource-resolution.d.ts +0 -27
- package/dist/resource-resolution.js +0 -265
- package/dist/secret-concurrent-revision.d.ts +0 -30
- package/dist/secret-concurrent-revision.js +0 -291
- package/dist/secret-session-view.d.ts +0 -36
- package/dist/secret-session-view.js +0 -179
- package/dist/subagents.d.ts +0 -6
- package/dist/subagents.js +0 -137
- package/dist/tool-bin-path.d.ts +0 -23
- package/dist/tool-bin-path.js +0 -61
- package/dist/workspace-apply-files.d.ts +0 -57
- package/dist/workspace-apply-files.js +0 -193
- package/dist/workspace-apply-publish.d.ts +0 -22
- package/dist/workspace-apply-publish.js +0 -178
- package/dist/workspace-apply.d.ts +0 -11
- package/dist/workspace-apply.js +0 -124
- package/dist/workspace-files.d.ts +0 -8
- package/dist/workspace-files.js +0 -46
- package/dist/workspace-launch.d.ts +0 -3
- package/dist/workspace-launch.js +0 -13
package/dist/index.d.ts
CHANGED
|
@@ -1,29 +1,1226 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
import { AgentCandidateConfigValue, AgentCandidateProfile, AgentCandidateProfileActivation, AgentCandidateProfileApplication, AgentCandidateProfilePlanEvidence, AgentCandidateProfilePlanMaterial, AgentProfile, AgentProfileConfigValue, AgentProfileFileMount, AgentProfileMcpServer, AgentProfileSecretProvider, AgentProfileSecretRef, AgentRuntimeAttachments, Sha256Digest } from "@tangle-network/agent-interface";
|
|
2
|
+
|
|
3
|
+
//#region src/harness.d.ts
|
|
4
|
+
declare const MATERIALIZER_HARNESSES: readonly ["claude-code", "nanoclaw", "codex", "opencode", "kimi-code", "pi", "prime", "gemini", "hermes", "openclaw"];
|
|
5
|
+
type HarnessId = (typeof MATERIALIZER_HARNESSES)[number];
|
|
6
|
+
declare function isMaterializerHarness(harness: string): harness is HarnessId;
|
|
7
|
+
/** Whether the shared materializer may place its context file in the harness agent directory. */
|
|
8
|
+
declare function harnessAutoLoadsAgentContextFile(harness: HarnessId): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* The context files this package owns by MARKER rather than by name:
|
|
11
|
+
* `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `HERMES.md`.
|
|
12
|
+
*
|
|
13
|
+
* Each is a documented name a repository can already carry, so the name proves
|
|
14
|
+
* nothing. A generated one carries the line {@link markMaterializerContextFile}
|
|
15
|
+
* writes, and only that line lets the next materialization replace it.
|
|
16
|
+
*
|
|
17
|
+
* opencode's context file is absent because it is a RESERVED name this package
|
|
18
|
+
* invented, already owned by the name alone.
|
|
19
|
+
*/
|
|
20
|
+
declare const MATERIALIZER_CONTEXT_PATHS: ReadonlySet<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Mark one generated context file so the NEXT materialization can prove this
|
|
23
|
+
* package wrote the bytes it is about to replace.
|
|
24
|
+
*
|
|
25
|
+
* The marker is an HTML comment on line 1. CommonMark closes an HTML block at
|
|
26
|
+
* the line holding `-->`, so every instruction below it parses exactly as it
|
|
27
|
+
* did without the line, and the line itself states no instruction. It is one
|
|
28
|
+
* more line this package composes into a file it already composes: it goes on
|
|
29
|
+
* a context file, which carries `prompt.instructions`, and NEVER on a
|
|
30
|
+
* system-prompt REPLACEMENT, whose bytes are the caller's exact text
|
|
31
|
+
* (`.gemini/system.md`; `.codex/system-prompt.md` is a reserved name this
|
|
32
|
+
* package invented and needs no marker to be owned).
|
|
33
|
+
*
|
|
34
|
+
* It carries the digest of the generated body below it, which the subagent
|
|
35
|
+
* marker does not need. `CLAUDE.md` is claude-code's own memory file and the
|
|
36
|
+
* agent appends to it mid-session, so a bare marker would still sit on line 1
|
|
37
|
+
* of a file the agent has since rewritten. The digest tells which leading bytes
|
|
38
|
+
* are still this package's own: the next materialization replaces exactly
|
|
39
|
+
* those and keeps what the agent appended below them
|
|
40
|
+
* ({@link generatedContextAppendix}). The marker's wording is part of every
|
|
41
|
+
* marker already written into live workspaces, so it stays as it is.
|
|
42
|
+
*
|
|
43
|
+
* A reserved context path — opencode's invented instruction file — is returned
|
|
44
|
+
* unchanged: its NAME already proves the provenance, and nothing else may mount
|
|
45
|
+
* there.
|
|
46
|
+
*/
|
|
47
|
+
declare function markMaterializerContextFile(relPath: string, content: string): string;
|
|
48
|
+
/**
|
|
49
|
+
* cwd-relative native skill dir per harness, or null if the harness has no
|
|
50
|
+
* cwd skill primitive (skills live in a user/global dir the workspace plan
|
|
51
|
+
* cannot reach). Public so consumers composing a profile can (a) render the
|
|
52
|
+
* exact path the platform will mount a skill at into their prompts instead
|
|
53
|
+
* of hardcoding `~/.claude/skills/...`, and (b) branch on skill support
|
|
54
|
+
* ahead of materialization instead of catching the materialize-time throw.
|
|
55
|
+
*/
|
|
56
|
+
declare const HARNESS_SKILL_DIRS: Readonly<Record<HarnessId, string | null>>;
|
|
57
|
+
/**
|
|
58
|
+
* Resolve the cwd-relative directory `resources.skills` refs materialize
|
|
59
|
+
* into on `harness`. `null` means the harness cannot receive cwd skills, the
|
|
60
|
+
* same condition that surfaces as an `unsupported`
|
|
61
|
+
* "skills" entry (and an {@link assertWorkspacePlanSupported} throw) at
|
|
62
|
+
* materialize time, exposed here as branchable data.
|
|
63
|
+
*/
|
|
64
|
+
declare function skillDirForHarness(harness: HarnessId): string | null;
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/plan-types.d.ts
|
|
67
|
+
/** The executor-owned root that receives a materialized file. */
|
|
68
|
+
type PlanFileRoot = "workspace" | "agent";
|
|
69
|
+
interface PlanFile {
|
|
70
|
+
relPath: string;
|
|
71
|
+
content: string;
|
|
72
|
+
/** Defaults to the run workspace. `agent` is the harness's private agent directory. */
|
|
73
|
+
root?: PlanFileRoot;
|
|
74
|
+
/** chmod mode (e.g. 0o755 for hook scripts); default 0o644. */
|
|
75
|
+
mode?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Provenance of this entry. `"generated"` = the materializer synthesized the
|
|
78
|
+
* content itself (native harness config, merged settings, lowered prompt/MCP/
|
|
79
|
+
* hooks/subagents). `"user"` = the exact bytes of a profile-declared resource
|
|
80
|
+
* ref (`resources.files`/`tools`/`agents`/`skills`/`commands`), passed through
|
|
81
|
+
* verbatim at the path the profile author chose.
|
|
82
|
+
*
|
|
83
|
+
* A consumer that needs to reinterpret a SPECIFIC generated file (e.g. parse
|
|
84
|
+
* `opencode.json` as the synthetic native config) MUST gate on
|
|
85
|
+
* `source === "generated"` at that relPath — matching by relPath alone cannot
|
|
86
|
+
* tell a harness-authored config apart from a user resource mount that
|
|
87
|
+
* happens to share the same conventional path, and treating arbitrary user
|
|
88
|
+
* content as trusted generated config is a fail-open bug, not a fallback.
|
|
89
|
+
*
|
|
90
|
+
* Optional: callers that hand-construct a {@link WorkspacePlan} directly for
|
|
91
|
+
* {@link applyWorkspacePlan} (tests, ad hoc writes) are not materializer
|
|
92
|
+
* output and have no provenance to report. `materializeProfile` always sets
|
|
93
|
+
* this on every file it emits.
|
|
94
|
+
*/
|
|
95
|
+
source?: "user" | "generated";
|
|
96
|
+
/**
|
|
97
|
+
* Who owns the PATH — which decides whether an existing file there may be
|
|
98
|
+
* replaced.
|
|
99
|
+
*
|
|
100
|
+
* `"materializer"` = a path whose generated content is wholly this
|
|
101
|
+
* package's output: a name this package invented, the generated context file
|
|
102
|
+
* (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `HERMES.md`), or `opencode.json`,
|
|
103
|
+
* which carries only the registrations generated from the profile. A file
|
|
104
|
+
* already there is this materializer's own output from an earlier application
|
|
105
|
+
* into the same workspace, and replacing it is how turn two of a resumed
|
|
106
|
+
* session — or the first turn of a branched one — gets the current profile
|
|
107
|
+
* instead of the previous one. Application replaces it only when the existing
|
|
108
|
+
* bytes prove that provenance — by the name for an invented path, by a marker
|
|
109
|
+
* line committing to the body digest for a context file, by the content for
|
|
110
|
+
* `opencode.json`.
|
|
111
|
+
*
|
|
112
|
+
* `"shared"` (the default, and every other file) = a path the user or the
|
|
113
|
+
* harness also owns. `.gemini/system.md` is a documented, user-authorable
|
|
114
|
+
* name whose content this package cannot tell from its own, and so is a
|
|
115
|
+
* context file mounted as an explicit profile resource rather than generated.
|
|
116
|
+
* An existing file there may be the caller's own work, so it is never
|
|
117
|
+
* replaced.
|
|
118
|
+
*
|
|
119
|
+
* Optional because hand-constructed plans have no path provenance to report;
|
|
120
|
+
* absent reads as `"shared"`, the safe answer.
|
|
121
|
+
*/
|
|
122
|
+
ownership?: "materializer" | "shared";
|
|
123
|
+
/**
|
|
124
|
+
* Secret leaves in a generated JSON document. `content` contains `null` at
|
|
125
|
+
* each path until the private executor resolves the named reference. The
|
|
126
|
+
* public plan, its digest, and its receipt retain only these references.
|
|
127
|
+
*/
|
|
128
|
+
secretSlots?: PlanFileSecretSlot[];
|
|
129
|
+
}
|
|
130
|
+
interface PlanFileSecretSlot {
|
|
131
|
+
path: Array<string | number>;
|
|
132
|
+
ref: AgentProfileSecretRef;
|
|
133
|
+
}
|
|
134
|
+
interface WorkspacePlanSecretSegment {
|
|
135
|
+
kind: "secret";
|
|
136
|
+
ref: AgentProfileSecretRef;
|
|
137
|
+
/** Encoding applied after private resolution. */
|
|
138
|
+
encoding: "raw" | "json-string";
|
|
139
|
+
}
|
|
140
|
+
/** A launch argument whose private leaves are resolved immediately before spawn. */
|
|
141
|
+
interface WorkspacePlanArgumentTemplate {
|
|
142
|
+
kind: "workspace-plan-argument-template";
|
|
143
|
+
segments: Array<string | WorkspacePlanSecretSegment>;
|
|
144
|
+
}
|
|
145
|
+
type WorkspacePlanArgument = string | WorkspacePlanArgumentTemplate;
|
|
146
|
+
/** Public bytes stay strings; secret references stay opaque until application. */
|
|
147
|
+
type WorkspacePlanConfigValue = string | AgentProfileSecretRef;
|
|
148
|
+
interface Unsupported {
|
|
149
|
+
dimension: "files" | "skills" | "mcp" | "hooks" | "subagents" | "commands" | "instructions" | "systemPrompt" | "appendSystemPrompt" | "connections" | "confidential" | "permissions" | "tools" | "modes" | "extensions";
|
|
150
|
+
reason: string;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The subset of {@link BINDABLE_LAUNCH_CONTROLS} the plan HANDS OVER rather than
|
|
154
|
+
* executes: controls a caller reaches only by composing the harness's own
|
|
155
|
+
* configuration, so no file, flag or env var the plan writes can touch them.
|
|
156
|
+
*
|
|
157
|
+
* - `opencode.agent-prompt` — opencode's `agent.<name>.prompt` config field,
|
|
158
|
+
* the one control that replaces its built-in provider prompt. It binds to a
|
|
159
|
+
* SINGLE agent, and the agent is chosen at launch. A caller that builds
|
|
160
|
+
* opencode's config itself and picks the agent there reads neither
|
|
161
|
+
* `plan.files` nor `plan.flags`, so for that one the plan names the control
|
|
162
|
+
* and hands over the text in {@link WorkspacePlan.systemPromptBinding}.
|
|
163
|
+
*
|
|
164
|
+
* Every other bindable control names a capability the plan still lowers itself
|
|
165
|
+
* once the caller has declared the plan's launch inputs really reach the spawn.
|
|
166
|
+
*/
|
|
167
|
+
declare const EXECUTOR_SYSTEM_PROMPT_BINDINGS: readonly ["opencode.agent-prompt"];
|
|
168
|
+
type ExecutorSystemPromptBinding = (typeof EXECUTOR_SYSTEM_PROMPT_BINDINGS)[number];
|
|
169
|
+
/**
|
|
170
|
+
* A system-prompt intent handed to the launcher that declared it owns the
|
|
171
|
+
* control, instead of being lowered into the workspace.
|
|
172
|
+
*
|
|
173
|
+
* Distinct from {@link WorkspacePlan.systemPrompt} — a launch ARGUMENT the
|
|
174
|
+
* executor hands to a harness flag — and from the file/flag/env lowerings the
|
|
175
|
+
* plan performs on its own. This names the exact control that must receive the
|
|
176
|
+
* text and which of the two intents it is, so the launcher cannot apply it to
|
|
177
|
+
* the wrong channel. Never written into an additive channel and never dropped:
|
|
178
|
+
* a caller that has not declared it owns `control` gets the plan's own lowering
|
|
179
|
+
* (or a refusal where the harness has no control at all) instead of this field.
|
|
180
|
+
*/
|
|
181
|
+
interface WorkspacePlanSystemPromptBinding {
|
|
182
|
+
/** Which of the two prompt intents this is — never inferred from presence. */
|
|
183
|
+
intent: "replace";
|
|
184
|
+
/** The exact launcher control that must receive `systemPrompt`. */
|
|
185
|
+
control: ExecutorSystemPromptBinding;
|
|
186
|
+
/** Exact text the control receives. */
|
|
187
|
+
systemPrompt: string;
|
|
188
|
+
}
|
|
189
|
+
/** One file applied by a plan, with the executor root kept explicit. */
|
|
190
|
+
interface WorkspacePlanWrittenFile {
|
|
191
|
+
root: PlanFileRoot;
|
|
192
|
+
relPath: string;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The dimensions `materializeProfile`'s `skip` option honors.
|
|
196
|
+
*
|
|
197
|
+
* Every other dimension is materialized unconditionally: generated plan files are pushed through
|
|
198
|
+
* a single site that carries no dimension tag, so there is nothing to gate them on. Naming the
|
|
199
|
+
* honored set keeps `skip: ["hooks"]` a loud rejection instead of a silent no-op.
|
|
200
|
+
*/
|
|
201
|
+
declare const SKIPPABLE_DIMENSIONS: readonly ["mcp", "extensions"];
|
|
202
|
+
type SkippableDimension = (typeof SKIPPABLE_DIMENSIONS)[number];
|
|
203
|
+
declare function isSkippableDimension(value: string): value is SkippableDimension;
|
|
204
|
+
/**
|
|
205
|
+
* Launcher controls an executor can declare it OWNS via `materializeProfile`'s
|
|
206
|
+
* `binds` option.
|
|
207
|
+
*
|
|
208
|
+
* Some harness controls live outside any workspace: opencode's exact
|
|
209
|
+
* system-prompt replacement (`agent.<name>.prompt`) binds to the ONE agent
|
|
210
|
+
* whoever starts the process selects, which a plan-forwarding executor cannot
|
|
211
|
+
* guarantee — so the plan refuses the intent (harnessSystemPromptIntents in
|
|
212
|
+
* @tangle-network/agent-interface answers `replace: false` for opencode).
|
|
213
|
+
*
|
|
214
|
+
* The replacement declarations describe the executor shapes that can reach it;
|
|
215
|
+
* each gets the lowering it can apply. Codex launchers separately declare
|
|
216
|
+
* `codex.developer-instructions` to consume ordinary instructions as additive
|
|
217
|
+
* context; undeclared callers retain workspace files:
|
|
218
|
+
*
|
|
219
|
+
* - `systemPrompt` — the executor applies the plan's launch flags to the
|
|
220
|
+
* spawn it owns, so the plan writes the generated `mode: primary` agent and
|
|
221
|
+
* selects it with `--agent`.
|
|
222
|
+
* - `opencode.agent-prompt` — the executor composes opencode's own config and
|
|
223
|
+
* picks the agent there, reading neither plan files nor plan flags, so the
|
|
224
|
+
* plan hands the text over in {@link WorkspacePlan.systemPromptBinding}
|
|
225
|
+
* instead of writing a workspace agent that would never be selected.
|
|
226
|
+
*
|
|
227
|
+
* The replacement declarations are mutually exclusive: declaring both is a
|
|
228
|
+
* caller bug, not a broader capability.
|
|
229
|
+
*/
|
|
230
|
+
declare const BINDABLE_LAUNCH_CONTROLS: readonly ["systemPrompt", "codex.developer-instructions", "opencode.agent-prompt"];
|
|
231
|
+
type BindableLaunchControl = (typeof BINDABLE_LAUNCH_CONTROLS)[number];
|
|
232
|
+
/** The plan a caller writes into the run cwd, then applies to the spawn. */
|
|
233
|
+
interface WorkspacePlan {
|
|
234
|
+
harness: HarnessId;
|
|
235
|
+
/** Files to write relative to the run workspace (cwd). */
|
|
236
|
+
files: PlanFile[];
|
|
237
|
+
/** Env vars to set on the spawned process (for harnesses needing them). */
|
|
238
|
+
env: Record<string, WorkspacePlanConfigValue>;
|
|
239
|
+
/** Extra CLI flags to pass (e.g. claude --mcp-config <path>). */
|
|
240
|
+
flags: WorkspacePlanArgument[];
|
|
241
|
+
/**
|
|
242
|
+
* Exact text that REPLACES the harness's own system prompt, for harnesses
|
|
243
|
+
* whose replacement control takes it as a launch argument the executor
|
|
244
|
+
* supplies (claude-code `--system-prompt`, pi `--system-prompt`).
|
|
245
|
+
*
|
|
246
|
+
* Absent does NOT mean "no replacement was requested": a harness whose
|
|
247
|
+
* control reads a file (codex, gemini) carries the replacement in
|
|
248
|
+
* {@link WorkspacePlan.files} plus a flag or env var instead. Present means
|
|
249
|
+
* the executor MUST bind it to that harness's replacement control — never to
|
|
250
|
+
* an additive one, which would leave the built-in prompt in force.
|
|
251
|
+
*/
|
|
252
|
+
systemPrompt?: string;
|
|
253
|
+
/**
|
|
254
|
+
* Text added to the harness context; its own system prompt stays intact.
|
|
255
|
+
*
|
|
256
|
+
* Claude Code and Pi bind their additive system-prompt control. Codex binds
|
|
257
|
+
* ordinary profile instructions to developer_instructions, composed once
|
|
258
|
+
* with host context; this is not a privileged system-prompt append. Authored
|
|
259
|
+
* Codex appendSystemPrompt remains unsupported. Never fold this into an exact
|
|
260
|
+
* system-prompt replacement, which carries the caller's unchanged bytes.
|
|
261
|
+
*/
|
|
262
|
+
appendSystemPrompt?: string;
|
|
263
|
+
/**
|
|
264
|
+
* A prompt intent no workspace file, flag, or env var can execute, addressed
|
|
265
|
+
* to the launcher control that can — see
|
|
266
|
+
* {@link WorkspacePlanSystemPromptBinding}.
|
|
267
|
+
*
|
|
268
|
+
* Present ONLY when the caller declared it owns the named control, so a plan
|
|
269
|
+
* built by a caller that forwards it to someone else's launcher never carries
|
|
270
|
+
* one; that caller gets the intent in {@link WorkspacePlan.unsupported}
|
|
271
|
+
* instead. Whoever reads it must bind it or throw — {@link
|
|
272
|
+
* takeSystemPromptBinding} does both.
|
|
273
|
+
*/
|
|
274
|
+
systemPromptBinding?: WorkspacePlanSystemPromptBinding;
|
|
275
|
+
/** Dimensions requested but with NO cwd path on this harness — fail-closed record. */
|
|
276
|
+
unsupported: Unsupported[];
|
|
277
|
+
/**
|
|
278
|
+
* Prerequisites the workspace files CANNOT establish on their own.
|
|
279
|
+
*
|
|
280
|
+
* A plan is a set of files, an env map, and flags. Some harness capabilities need more than
|
|
281
|
+
* that to actually function: pi's MCP support is not built in, it arrives from an extension
|
|
282
|
+
* that must be installed into the harness's own package directory and permitted to load. No
|
|
283
|
+
* file written into a run workspace can make either true.
|
|
284
|
+
*
|
|
285
|
+
* Writing the config anyway and hoping is the failure this field exists to prevent: the
|
|
286
|
+
* harness starts, silently has no MCP, and the agent runs without the tools it was configured
|
|
287
|
+
* with while nothing reports a problem. So the plan states the requirement and the executor —
|
|
288
|
+
* which knows where its harness is installed and how it spawns — verifies or refuses it.
|
|
289
|
+
*
|
|
290
|
+
* Optional because this is an additive field on a published type: a plan built before it
|
|
291
|
+
* existed, or by a caller that does not construct one, is still a valid plan with no
|
|
292
|
+
* prerequisites. Every plan this package builds sets it.
|
|
293
|
+
*/
|
|
294
|
+
requires?: PlanRequirement[];
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* One prerequisite a {@link WorkspacePlan} depends on but cannot create.
|
|
298
|
+
*
|
|
299
|
+
* Declarative on purpose: this package builds plans and never probes a filesystem, spawns a
|
|
300
|
+
* process, or reaches the network. The executor holds that context and does the checking.
|
|
301
|
+
*/
|
|
302
|
+
interface PlanRequirement {
|
|
303
|
+
/** The only kind so far: a harness extension/plugin that must be loaded for a dimension to work. */
|
|
304
|
+
kind: "harness-extension";
|
|
305
|
+
/** Dimension that produced the requirement, so a refusal can name what will not work. */
|
|
306
|
+
dimension: Unsupported["dimension"];
|
|
307
|
+
/** Package spec in the harness's own vocabulary, e.g. `npm:pi-mcp-adapter`. */
|
|
308
|
+
id: string;
|
|
309
|
+
/** Why the plan needs it — goes verbatim into the executor's refusal message. */
|
|
310
|
+
reason: string;
|
|
311
|
+
/** The exact command that satisfies it, so a failure is actionable without a doc lookup. */
|
|
312
|
+
remedy: string;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Proof of the profile workspace inputs applied before a harness is spawned.
|
|
316
|
+
* `workspacePlanDigest` covers only the {@link WorkspacePlan}; it is not an
|
|
317
|
+
* execution-plan digest and does not attest unrelated files in `workspaceDir`.
|
|
318
|
+
*/
|
|
319
|
+
interface WorkspacePlanReceipt {
|
|
320
|
+
workspacePlanDigest: string;
|
|
321
|
+
/** Public launch identity only; secret values never enter this receipt. */
|
|
322
|
+
env: Record<string, WorkspacePlanConfigValue>;
|
|
323
|
+
/** Public launch identity only; templates retain opaque secret references. */
|
|
324
|
+
flags: WorkspacePlanArgument[];
|
|
325
|
+
systemPrompt?: string;
|
|
326
|
+
appendSystemPrompt?: string;
|
|
327
|
+
/** The launcher-bound intent, so a receipt says which control owed the work. */
|
|
328
|
+
systemPromptBinding?: WorkspacePlanSystemPromptBinding;
|
|
329
|
+
unsupported: Unsupported[];
|
|
330
|
+
/**
|
|
331
|
+
* Workspace-root paths, for consumers that mount the workspace only.
|
|
332
|
+
* Agent-root files are available in `writtenFiles` and are never encoded as
|
|
333
|
+
* an `agent:` path because that spelling is legal in the workspace root.
|
|
334
|
+
*/
|
|
335
|
+
written: string[];
|
|
336
|
+
/** Every applied file, including its executor-owned root. */
|
|
337
|
+
writtenFiles: WorkspacePlanWrittenFile[];
|
|
338
|
+
}
|
|
339
|
+
/** Private values handed directly to the provider spawn, never to receipts. */
|
|
340
|
+
interface WorkspacePlanSpawnInputs {
|
|
341
|
+
env: Record<string, string>;
|
|
342
|
+
flags: string[];
|
|
343
|
+
systemPrompt?: string;
|
|
344
|
+
appendSystemPrompt?: string;
|
|
345
|
+
/** Read it with {@link takeSystemPromptBinding}, which refuses a foreign control. */
|
|
346
|
+
systemPromptBinding?: WorkspacePlanSystemPromptBinding;
|
|
347
|
+
/**
|
|
348
|
+
* Absolute dirs of the profile's declared executable `reference/` tools in
|
|
349
|
+
* the immutable revision the launch runs from. The provider puts them on
|
|
350
|
+
* the launch PATH in place of the app's own tool dirs (bindLaunchToolBinDirs),
|
|
351
|
+
* so a profile names its CLI bare.
|
|
352
|
+
*/
|
|
353
|
+
toolBinDirs?: string[];
|
|
354
|
+
}
|
|
355
|
+
/** Result of applying a public plan at the private executor boundary. */
|
|
356
|
+
interface WorkspacePlanApplication {
|
|
357
|
+
receipt: WorkspacePlanReceipt;
|
|
358
|
+
spawn: WorkspacePlanSpawnInputs;
|
|
359
|
+
/** Resolved generated files intentionally consumed in memory by the runtime. */
|
|
360
|
+
runtimeOnlyFiles: Record<string, string>;
|
|
361
|
+
}
|
|
362
|
+
/** The plan was applied, but one or more private staging files remain. */
|
|
363
|
+
declare class WorkspacePlanCleanupError extends AggregateError {
|
|
364
|
+
readonly receipt: WorkspacePlanReceipt;
|
|
365
|
+
readonly temporaryPaths: readonly string[];
|
|
366
|
+
constructor(errors: readonly unknown[], receipt: WorkspacePlanReceipt, temporaryPaths: readonly string[]);
|
|
367
|
+
}
|
|
368
|
+
interface ApplyWorkspacePlanOptions {
|
|
369
|
+
/** Plan files consumed in memory by the runtime and never persisted to cwd. */
|
|
370
|
+
runtimeOnlyFiles?: readonly string[];
|
|
371
|
+
/** Absolute private agent directory required by files whose root is `agent`. */
|
|
372
|
+
agentDir?: string;
|
|
373
|
+
/** Own newly written workspace files as the process that will read them. */
|
|
374
|
+
ownership?: {
|
|
375
|
+
uid: number;
|
|
376
|
+
gid: number;
|
|
377
|
+
};
|
|
378
|
+
/** Existing workspace paths are either exact idempotent inputs or forbidden. */
|
|
379
|
+
existingFiles?: "allow-identical" | "reject";
|
|
380
|
+
/**
|
|
381
|
+
* `workspacePlanDigest` of a plan a prior call already applied into this
|
|
382
|
+
* workspace. When it equals this plan's digest, application changes no file
|
|
383
|
+
* content. It can repair ownership on unchanged materializer-owned files.
|
|
384
|
+
* A file the agent edited or removed stays exactly as the agent left it.
|
|
385
|
+
* Env, flags, prompt intents, and the receipt are still produced. A different
|
|
386
|
+
* digest applies normally, so a changed plan still meets the existing-file
|
|
387
|
+
* refusal.
|
|
388
|
+
*/
|
|
389
|
+
appliedPlanDigest?: string;
|
|
390
|
+
/**
|
|
391
|
+
* Write every JSON file secret slot as an `{env:NAME}` reference (OpenCode
|
|
392
|
+
* config substitution) and never its value, so file bytes and every digest
|
|
393
|
+
* over them stay identical when only a secret's value changes. The value
|
|
394
|
+
* lands here under NAME for the executor alone: never put it in the launch
|
|
395
|
+
* environment, argv or any file the native process reads, because that
|
|
396
|
+
* process hands everything it holds to every tool it runs. A value that
|
|
397
|
+
* could not be substituted safely is refused.
|
|
398
|
+
*/
|
|
399
|
+
secretFileSlotReferences?: Record<string, string>;
|
|
400
|
+
}
|
|
401
|
+
//#endregion
|
|
402
|
+
//#region src/candidate-types.d.ts
|
|
403
|
+
interface AgentCandidateWorkspacePlan {
|
|
404
|
+
sourceProfileDigest: Sha256Digest;
|
|
405
|
+
harness: HarnessId;
|
|
406
|
+
files: PlanFile[];
|
|
407
|
+
env: Record<string, AgentCandidateConfigValue>;
|
|
408
|
+
flags: AgentCandidateConfigValue[];
|
|
409
|
+
systemPrompt?: AgentCandidateConfigValue;
|
|
410
|
+
appendSystemPrompt?: AgentCandidateConfigValue;
|
|
411
|
+
unsupported: Unsupported[];
|
|
412
|
+
}
|
|
413
|
+
interface AgentCandidateWorkspacePlanReceipt {
|
|
414
|
+
profileActivation: AgentCandidateProfileActivation;
|
|
415
|
+
application: AgentCandidateProfileApplication;
|
|
416
|
+
env: Record<string, AgentCandidateConfigValue>;
|
|
417
|
+
flags: AgentCandidateConfigValue[];
|
|
418
|
+
systemPrompt?: AgentCandidateConfigValue;
|
|
419
|
+
appendSystemPrompt?: AgentCandidateConfigValue;
|
|
420
|
+
unsupported: Unsupported[];
|
|
421
|
+
}
|
|
422
|
+
interface ApplyAgentCandidateWorkspacePlanOptions {
|
|
423
|
+
/** Absolute private agent directory required by agent-root plan files. */
|
|
424
|
+
agentDir?: string;
|
|
425
|
+
}
|
|
426
|
+
interface MaterializeCandidateProfileOptions {
|
|
427
|
+
/** Exact text fetched from pinned resource refs, keyed by declared SHA-256. */
|
|
428
|
+
resolvedResources?: ReadonlyMap<Sha256Digest, string>;
|
|
429
|
+
/**
|
|
430
|
+
* Launcher controls this caller owns and will bind itself. The declaration
|
|
431
|
+
* is forwarded to the classic materializer so candidate execution uses the
|
|
432
|
+
* same lowering as ordinary profile execution.
|
|
433
|
+
*/
|
|
434
|
+
binds?: readonly BindableLaunchControl[];
|
|
435
|
+
}
|
|
436
|
+
//#endregion
|
|
437
|
+
//#region src/candidate.d.ts
|
|
438
|
+
declare function materializeCandidateProfile(profile: AgentCandidateProfile, harness: HarnessId, opts?: MaterializeCandidateProfileOptions): AgentCandidateWorkspacePlan;
|
|
439
|
+
/**
|
|
440
|
+
* Apply a candidate plan and return its spawn values together with captured
|
|
441
|
+
* canonical evidence. No caller needs to re-serialize or reinterpret the plan.
|
|
442
|
+
*/
|
|
443
|
+
declare function applyAgentCandidateWorkspacePlan(plan: AgentCandidateWorkspacePlan, workspaceDir: string, targetWorkspace: AgentCandidateProfileApplication["targetWorkspace"], options?: ApplyAgentCandidateWorkspacePlanOptions): AgentCandidateWorkspacePlanReceipt;
|
|
444
|
+
//#endregion
|
|
445
|
+
//#region src/control-maps.d.ts
|
|
446
|
+
/** Tool IDs reported by the OpenCode binary shipped in the Sandbox image. */
|
|
447
|
+
declare const OPENCODE_NATIVE_TOOL_IDS: readonly ["apply_patch", "bash", "codesearch", "edit", "glob", "grep", "question", "read", "skill", "task", "todowrite", "webfetch", "websearch", "write"];
|
|
448
|
+
/** Resolve portable and legacy profile names to current OpenCode tool IDs. */
|
|
449
|
+
declare function openCodeNativeToolId(name: string): string | undefined;
|
|
450
|
+
//#endregion
|
|
451
|
+
//#region src/harness-prompt.d.ts
|
|
452
|
+
/** Keep controlled Codex launches on declared tools, not account apps or plugins. */
|
|
453
|
+
declare const CODEX_DISABLED_FEATURE_ARGS: readonly string[];
|
|
454
|
+
/**
|
|
455
|
+
* Whether a run keeps the harness's own system prompt, so that a host's
|
|
456
|
+
* environment context joins the profile's addition instead of replacing the
|
|
457
|
+
* harness prompt.
|
|
458
|
+
*
|
|
459
|
+
* A profile that declares prompt intent (`prompt.instructions` or
|
|
460
|
+
* `prompt.appendSystemPrompt`) without `prompt.systemPrompt` asked for the
|
|
461
|
+
* harness prompt to stay in force: that is what `appendSystemPrompt` means.
|
|
462
|
+
* A host that replaced it with its own template would delete exactly what the
|
|
463
|
+
* profile kept. Every Discovery research director ran under the
|
|
464
|
+
* sandbox's app-builder template this way: claude-code through
|
|
465
|
+
* `--system-prompt`, opencode through a generated primary agent.
|
|
466
|
+
*/
|
|
467
|
+
declare function keepsHarnessSystemPrompt(profile: AgentProfile | undefined, harness: HarnessId | string | undefined): boolean;
|
|
468
|
+
/** Join prompt additions in order, skipping empty ones. */
|
|
469
|
+
declare function joinSystemPromptAdditions(...additions: Array<string | undefined>): string | undefined;
|
|
470
|
+
/** Native inline context has a bounded argument; long context belongs in resources.files. */
|
|
471
|
+
declare function codexDeveloperInstructionArgs(value: string | undefined, flags?: readonly string[]): string[];
|
|
472
|
+
//#endregion
|
|
473
|
+
//#region src/managed-workspace-types.d.ts
|
|
474
|
+
interface ManagedWorkspaceFileDigest {
|
|
475
|
+
root: PlanFileRoot;
|
|
476
|
+
relPath: string;
|
|
477
|
+
source: PlanFile["source"];
|
|
478
|
+
ownership: PlanFile["ownership"];
|
|
479
|
+
size: number;
|
|
480
|
+
mode: number;
|
|
481
|
+
/** The host view exposes only visible entries for this pinned turn. */
|
|
482
|
+
visible: boolean;
|
|
483
|
+
/** A side copy of this original path, when a user file won the collision. */
|
|
484
|
+
relocatedFrom?: string;
|
|
485
|
+
/** Digest of the actual staged bytes, including resolved secret leaves. Private. */
|
|
486
|
+
sha256: string;
|
|
487
|
+
}
|
|
488
|
+
/** Private executor inventory; never expose hashes of resolved credentials. */
|
|
489
|
+
interface ManagedWorkspaceManifest {
|
|
490
|
+
workspacePlanDigest: string;
|
|
491
|
+
/** Hashes the resolved stage inventory and launch inputs, not only public refs. */
|
|
492
|
+
materializedDigest: string;
|
|
493
|
+
files: ManagedWorkspaceFileDigest[];
|
|
494
|
+
/** User-owned path stays in place; profile bytes are staged beside it. */
|
|
495
|
+
conflicts: Array<{
|
|
496
|
+
relPath: string;
|
|
497
|
+
copyRelPath: string;
|
|
498
|
+
reason: "existing" | "symlink";
|
|
499
|
+
}>;
|
|
500
|
+
/** Resolved for the runtime but intentionally absent from the visible tree. */
|
|
501
|
+
runtimeOnlyFiles: Array<{
|
|
502
|
+
name: string;
|
|
503
|
+
size: number;
|
|
504
|
+
sha256: string;
|
|
505
|
+
}>;
|
|
506
|
+
/** Private digest of resolved spawn controls, including secret-bearing env. */
|
|
507
|
+
spawnDigest: string;
|
|
508
|
+
/** Exact native spawn controls after absolute revision paths are bound. */
|
|
509
|
+
launchDigest?: string;
|
|
510
|
+
}
|
|
511
|
+
//#endregion
|
|
512
|
+
//#region src/managed-workspace.d.ts
|
|
513
|
+
interface ConcurrentProfileRevision {
|
|
514
|
+
directory: string;
|
|
515
|
+
manifest: ManagedWorkspaceManifest;
|
|
516
|
+
application: WorkspacePlanApplication;
|
|
517
|
+
}
|
|
518
|
+
declare function ensurePublicConcurrentProfileRoots(base: string): {
|
|
519
|
+
managedRoot: string;
|
|
520
|
+
launchRoot: string;
|
|
521
|
+
};
|
|
522
|
+
declare function preparePublicConcurrentProfileRevision(input: {
|
|
523
|
+
plan: WorkspacePlan;
|
|
524
|
+
managedRoot: string;
|
|
525
|
+
launchRoot: string;
|
|
526
|
+
sharedWorkspaceDir: string;
|
|
527
|
+
ownerId: string;
|
|
528
|
+
secretProvider: AgentProfileSecretProvider;
|
|
529
|
+
options?: Pick<ApplyWorkspacePlanOptions, "ownership" | "runtimeOnlyFiles">;
|
|
530
|
+
}): Promise<ConcurrentProfileRevision>;
|
|
531
|
+
//#endregion
|
|
532
|
+
//#region src/mcp-config-ownership.d.ts
|
|
533
|
+
/**
|
|
534
|
+
* Harness MCP config files this package generates wholesale from
|
|
535
|
+
* `profile.mcp`: exactly one `mcpServers` object whose entries carry only
|
|
536
|
+
* the fields the generators write. Recognizable by that shape alone (no
|
|
537
|
+
* schema id to key on), so an existing file holding ONLY those registrations
|
|
538
|
+
* is this package's earlier output and a new plan replaces it — a per-turn
|
|
539
|
+
* profile changes these bytes routinely (physim's MCP env carries turn
|
|
540
|
+
* state). Anything else at the path (a user's own keys, extra fields) still
|
|
541
|
+
* refuses: the name alone proves nothing, same rule as `opencode.json`.
|
|
542
|
+
*/
|
|
543
|
+
/** Whether the existing file at `relPath` is this package's own earlier MCP
|
|
544
|
+
* config output (shape rule above). `undefined` content = no regular file. */
|
|
545
|
+
declare function isMaterializerMcpConfig(relPath: string, content: () => string | undefined): boolean;
|
|
546
|
+
//#endregion
|
|
547
|
+
//#region src/mcp-opencode.d.ts
|
|
548
|
+
/** OpenCode-native MCP configuration used by workspace and startup paths. */
|
|
549
|
+
type OpenCodeMcpConfig = Record<string, {
|
|
550
|
+
type: "remote";
|
|
551
|
+
url: string;
|
|
552
|
+
enabled: boolean;
|
|
553
|
+
headers?: Record<string, AgentProfileConfigValue>; /** Milliseconds; OpenCode bounds this server's connect, tool listing and tool calls by it. */
|
|
554
|
+
timeout?: number; /** `false` turns off OpenCode's OAuth discovery for this server. */
|
|
555
|
+
oauth?: false;
|
|
556
|
+
} | {
|
|
557
|
+
type: "local";
|
|
558
|
+
command: Array<string | AgentProfileConfigValue>;
|
|
559
|
+
enabled: boolean;
|
|
560
|
+
environment?: Record<string, AgentProfileConfigValue>;
|
|
561
|
+
timeout?: number;
|
|
562
|
+
}>;
|
|
563
|
+
/**
|
|
564
|
+
* Lower canonical MCP definitions to OpenCode's native startup configuration.
|
|
565
|
+
* `toolTimeouts` holds the validated `metadata.toolTimeoutMs` of each server
|
|
566
|
+
* that declared one; without it OpenCode applies the MCP SDK's 60 s default to
|
|
567
|
+
* every tool call.
|
|
568
|
+
*/
|
|
569
|
+
declare function openCodeMcpConfig(mcp: Record<string, AgentProfileMcpServer>, toolTimeouts?: ReadonlyMap<string, number>): OpenCodeMcpConfig;
|
|
570
|
+
//#endregion
|
|
571
|
+
//#region src/model-id.d.ts
|
|
572
|
+
/**
|
|
573
|
+
* The one canonicalization of a model id, shared by everything that writes a
|
|
574
|
+
* model id into an {@link AgentProfile} and everything that later compares one
|
|
575
|
+
* against it.
|
|
576
|
+
*
|
|
577
|
+
* A model id is qualified by prepending provider segments, and the same model
|
|
578
|
+
* is legitimately spelled at more than one qualification level as it travels:
|
|
579
|
+
* the caller sends `{ provider: "openai-compat", model: "deepseek/deepseek-v4-flash" }`,
|
|
580
|
+
* the profile records the qualified `openai-compat/deepseek/deepseek-v4-flash`,
|
|
581
|
+
* and the CLI is spawned with that qualified form. Two spellings, one model.
|
|
582
|
+
*
|
|
583
|
+
* Every writer and every reader must run both sides through here, so a
|
|
584
|
+
* comparison cannot mistake two spellings of one model for a conflict. Two
|
|
585
|
+
* independent copies of this rule are exactly how that bug arises.
|
|
586
|
+
*/
|
|
587
|
+
/**
|
|
588
|
+
* Qualify `modelId` with `provider` — the canonical form of a model id.
|
|
589
|
+
*
|
|
590
|
+
* The already-qualified check is prefix-SPECIFIC rather than "already contains
|
|
591
|
+
* a slash": a router slug legitimately carries an upstream segment of its own
|
|
592
|
+
* (`deepseek/deepseek-v4-flash`, `zai/glm-4.7`), so a generic slash test would
|
|
593
|
+
* leave those unqualified, while an unconditional prefix would double-qualify
|
|
594
|
+
* an id that has already been through here.
|
|
595
|
+
*
|
|
596
|
+
* Idempotent by construction:
|
|
597
|
+
* `qualifyModelId(p, qualifyModelId(p, m)) === qualifyModelId(p, m)`.
|
|
598
|
+
*/
|
|
599
|
+
declare function qualifyModelId<T extends string | undefined>(provider: string | undefined, modelId: T): T;
|
|
600
|
+
/**
|
|
601
|
+
* Remove one exact `provider/` qualification from `modelId`.
|
|
602
|
+
*
|
|
603
|
+
* This is the inverse operation for a model id that was qualified by this
|
|
604
|
+
* provider. It removes only the known outer prefix and preserves upstream
|
|
605
|
+
* segments such as `zai/glm-4.7`.
|
|
606
|
+
*
|
|
607
|
+
* The helper removes one outer qualification per call. It leaves missing
|
|
608
|
+
* providers and model ids unchanged.
|
|
609
|
+
*/
|
|
610
|
+
declare function unqualifyModelId(provider: string | undefined, modelId: string): string;
|
|
611
|
+
declare function unqualifyModelId(provider: string | undefined, modelId: undefined): undefined;
|
|
612
|
+
declare function unqualifyModelId(provider: string | undefined, modelId: string | undefined): string | undefined;
|
|
613
|
+
/**
|
|
614
|
+
* Do two model ids name the same model?
|
|
615
|
+
*
|
|
616
|
+
* Both operands are qualified by `provider` before comparison, so the
|
|
617
|
+
* qualification level a caller happened to use is not a difference. Two
|
|
618
|
+
* different model names are still different — this narrows a comparison to the
|
|
619
|
+
* model's identity, it does not make the comparison permissive.
|
|
620
|
+
*
|
|
621
|
+
* `provider` is optional because a profile may carry a `model.default` that was
|
|
622
|
+
* qualified by a writer which did not also record `model.provider`. With no
|
|
623
|
+
* provider to qualify by, a bare id and its single-segment-qualified spelling
|
|
624
|
+
* are still the same model, which is the only tolerance the undeclared case gets.
|
|
625
|
+
*/
|
|
626
|
+
declare function modelIdsMatch(a: string | undefined, b: string | undefined, provider?: string): boolean;
|
|
627
|
+
//#endregion
|
|
628
|
+
//#region src/pi-models-config.d.ts
|
|
629
|
+
interface PiModelsConfigInput {
|
|
630
|
+
/** Provider key in models.json and the matching `--provider` value. */
|
|
631
|
+
providerName: string;
|
|
632
|
+
/** Model id in models.json and the matching `--model` value. */
|
|
633
|
+
modelId: string;
|
|
634
|
+
/** Provider endpoint. OpenAI-compatible endpoints include `/v1`. */
|
|
635
|
+
baseUrl: string;
|
|
636
|
+
/** Literal in-box credential or an environment reference. */
|
|
637
|
+
apiKey: string;
|
|
638
|
+
/** Pi wire protocol. */
|
|
639
|
+
api?: "anthropic-messages" | "google-generative-ai" | "openai-completions" | "openai-responses";
|
|
640
|
+
contextWindow?: number;
|
|
641
|
+
maxTokens?: number;
|
|
642
|
+
reasoning?: boolean;
|
|
643
|
+
/** OpenAI-compatible completions may reject the optional store field. */
|
|
644
|
+
supportsStore?: boolean;
|
|
645
|
+
}
|
|
646
|
+
interface PiModelsConfigFile {
|
|
647
|
+
path: string;
|
|
648
|
+
content: string;
|
|
649
|
+
mode: number;
|
|
650
|
+
}
|
|
651
|
+
declare const PI_MODELS_CONFIG_PATH = ".pi/agent/models.json";
|
|
652
|
+
interface PiRuntimePaths {
|
|
653
|
+
agentDir: string;
|
|
654
|
+
sessionDir: string;
|
|
655
|
+
}
|
|
656
|
+
/** Resolve Pi's private roots from the one runtime HOME supplied to Pi. */
|
|
657
|
+
declare function resolvePiRuntimePaths(runtimeHome: string): PiRuntimePaths;
|
|
658
|
+
declare function buildPiModelsConfig(input: PiModelsConfigInput): Record<string, unknown>;
|
|
659
|
+
/** Build the owner-only Pi file used by headless and interactive processes. */
|
|
660
|
+
declare function buildPiModelsConfigFile(input: PiModelsConfigInput): PiModelsConfigFile;
|
|
661
|
+
//#endregion
|
|
662
|
+
//#region src/plan-application.d.ts
|
|
663
|
+
declare function applyWorkspacePlan(plan: WorkspacePlan, workspaceDir: string, options?: ApplyWorkspacePlanOptions): WorkspacePlanReceipt;
|
|
664
|
+
/**
|
|
665
|
+
* Resolve opaque profile references through an executor-owned provider, then
|
|
666
|
+
* apply the resulting private native files and launch inputs. Resolution
|
|
667
|
+
* completes before any workspace write, and resolved values never enter the
|
|
668
|
+
* public plan, digest, receipt, logs, or error messages.
|
|
669
|
+
*/
|
|
670
|
+
declare function applyWorkspacePlanWithSecretProvider(plan: WorkspacePlan, workspaceDir: string, secretProvider: AgentProfileSecretProvider, options?: ApplyWorkspacePlanOptions): Promise<WorkspacePlanApplication>;
|
|
671
|
+
//#endregion
|
|
672
|
+
//#region src/plan-digest.d.ts
|
|
673
|
+
declare function hashWorkspacePlan(plan: WorkspacePlan): string;
|
|
674
|
+
/** Build the exact digest-free identity document required by agent-interface. */
|
|
675
|
+
declare function agentCandidateProfilePlanMaterial(plan: AgentCandidateWorkspacePlan): AgentCandidateProfilePlanMaterial;
|
|
676
|
+
/**
|
|
677
|
+
* Return the RFC 8785 UTF-8 bytes and SHA-256 identity of a candidate profile
|
|
678
|
+
* plan. The returned bytes are the exact bytes embedded in receipt evidence.
|
|
679
|
+
*/
|
|
680
|
+
declare function canonicalizeAgentCandidateProfilePlan(plan: AgentCandidateWorkspacePlan): {
|
|
681
|
+
material: AgentCandidateProfilePlanMaterial;
|
|
682
|
+
bytes: Uint8Array;
|
|
683
|
+
digest: Sha256Digest;
|
|
684
|
+
};
|
|
685
|
+
/** Capture portable evidence of the exact canonical profile-plan bytes. */
|
|
686
|
+
declare function captureAgentCandidateProfilePlan(plan: AgentCandidateWorkspacePlan): AgentCandidateProfilePlanEvidence;
|
|
687
|
+
//#endregion
|
|
688
|
+
//#region src/plan-prompt.d.ts
|
|
689
|
+
/**
|
|
690
|
+
* The replacement text this launcher must bind to `control`, or `undefined`
|
|
691
|
+
* when the plan carries no launcher-bound intent.
|
|
692
|
+
*
|
|
693
|
+
* Throws for a binding addressed to a DIFFERENT control: the reader cannot
|
|
694
|
+
* execute it, and answering `undefined` would start the agent with the
|
|
695
|
+
* harness's own prompt still in force while nothing reported a problem — the
|
|
696
|
+
* silent downgrade the binding exists to prevent. This is the seam where an
|
|
697
|
+
* executor that cannot bind an intent says so, by name, instead of running a
|
|
698
|
+
* profile whose prompt never took effect.
|
|
699
|
+
*/
|
|
700
|
+
declare function takeSystemPromptBinding(spawn: Pick<WorkspacePlanSpawnInputs, "systemPromptBinding">, control: ExecutorSystemPromptBinding): string | undefined;
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region src/plan-support.d.ts
|
|
703
|
+
/** Fail when a profile asks for controls the chosen harness cannot execute. */
|
|
704
|
+
declare function assertWorkspacePlanSupported(plan: Pick<WorkspacePlan, "unsupported">): void;
|
|
705
|
+
/**
|
|
706
|
+
* Enforce supportability under the profile's failOnError policy.
|
|
707
|
+
* Strict mode throws; best-effort mode returns visible warnings.
|
|
708
|
+
*/
|
|
709
|
+
declare function enforceWorkspacePlanSupport(plan: Pick<WorkspacePlan, "unsupported">, failOnError: boolean | undefined): string[];
|
|
710
|
+
//#endregion
|
|
711
|
+
//#region src/prime-profile.d.ts
|
|
712
|
+
interface PrimeProfileSkill {
|
|
713
|
+
name: string;
|
|
714
|
+
content: string;
|
|
715
|
+
}
|
|
716
|
+
interface PrimeProfileSubagent {
|
|
717
|
+
name: string;
|
|
718
|
+
description?: string;
|
|
719
|
+
prompt?: string;
|
|
720
|
+
metadata?: Record<string, unknown>;
|
|
721
|
+
}
|
|
722
|
+
/** Validated, materialization-ready view of the profile controls prime applies. */
|
|
723
|
+
interface PrimeProfileControls {
|
|
724
|
+
systemPrompt?: string;
|
|
725
|
+
appendSystemPrompt?: string;
|
|
726
|
+
/** Composed caller instructions, lowered to the agent dir's AGENTS.md. */
|
|
727
|
+
instructions?: string;
|
|
728
|
+
skills: PrimeProfileSkill[];
|
|
729
|
+
subagents: PrimeProfileSubagent[];
|
|
730
|
+
}
|
|
731
|
+
/** True when the controls materialize anything at all. */
|
|
732
|
+
declare function hasPrimeProfileMaterial(controls: PrimeProfileControls): boolean;
|
|
733
|
+
/**
|
|
734
|
+
* True when the controls must WRITE INTO the agent dir itself.
|
|
735
|
+
*
|
|
736
|
+
* Prompt files and skill dirs are named by a flag, so they can live anywhere
|
|
737
|
+
* the agent can read (`--system-prompt` / `--append-system-prompt` resolve a
|
|
738
|
+
* path when it exists, fork resource-loader.ts:41-56; `--skill` takes an
|
|
739
|
+
* arbitrary dir, :437-442). The context file and the continual-harness store
|
|
740
|
+
* are located BY the agent dir and have no flag, so they cannot move.
|
|
741
|
+
*
|
|
742
|
+
* An executor pointed at an agent dir it does not own (an operator's shared
|
|
743
|
+
* dir) uses this to refuse exactly the controls it would have to write there,
|
|
744
|
+
* while still binding the ones it can materialize elsewhere.
|
|
745
|
+
*/
|
|
746
|
+
declare function primeProfileNeedsAgentDir(controls: PrimeProfileControls): boolean;
|
|
747
|
+
/**
|
|
748
|
+
* Validate and extract the profile controls the prime agent-dir lowering
|
|
749
|
+
* materializes. Throws {@link PrimeProfileError} on any control (or control
|
|
750
|
+
* facet) the fork has no verified read path for — partial acceptance would
|
|
751
|
+
* silently drop the rest.
|
|
752
|
+
*/
|
|
753
|
+
declare function readPrimeProfileControls(profile: AgentProfile | undefined): PrimeProfileControls;
|
|
754
|
+
/**
|
|
755
|
+
* Refuse a run whose selected model disagrees with the profile's own.
|
|
756
|
+
*
|
|
757
|
+
* One authority per run: a profile names the model it was written and scored
|
|
758
|
+
* against, so running it on a different one silently scores a different agent.
|
|
759
|
+
* Both sides go through {@link modelIdsMatch}, so the qualification level a
|
|
760
|
+
* caller happened to use is not a conflict.
|
|
761
|
+
*
|
|
762
|
+
* `provider` is the executor's PROVIDER SELECTION, and is compared only when
|
|
763
|
+
* the executor's provider is part of model identity. An executor whose
|
|
764
|
+
* provider key is merely a namespace inside the agent dir passes it as
|
|
765
|
+
* undefined and gets the model-name comparison alone.
|
|
766
|
+
*/
|
|
767
|
+
declare function assertPrimeModelAgreement(profile: AgentProfile | undefined, selected: {
|
|
768
|
+
provider?: string;
|
|
769
|
+
model: string;
|
|
770
|
+
}): void;
|
|
771
|
+
/** Deterministic harness-state entry id for a profile subagent name. */
|
|
772
|
+
declare function primeSubagentEntryId(name: string): string;
|
|
773
|
+
//#endregion
|
|
774
|
+
//#region src/prime-agent-dir.d.ts
|
|
775
|
+
declare function writePrimeAgentFile(path: string, data: string, mode?: number): void;
|
|
776
|
+
/**
|
|
777
|
+
* File access on a prime agent dir. The default reads and writes the local
|
|
778
|
+
* filesystem as the calling process. An executor whose agent dir belongs to
|
|
779
|
+
* another user (a root sidecar that demotes prime-agent) passes reads it took
|
|
780
|
+
* as that user and replays the writes as that user, so it never touches the
|
|
781
|
+
* agent's files with its own rights.
|
|
782
|
+
*/
|
|
783
|
+
interface PrimeAgentDirIo {
|
|
784
|
+
/** The file's text, or undefined when it does not exist. */
|
|
785
|
+
read(path: string): string | undefined;
|
|
786
|
+
/** Replace the whole file: atomic and owner-only. */
|
|
787
|
+
write(path: string, data: string): void;
|
|
788
|
+
}
|
|
789
|
+
/** The fork's continual-harness store, the only agent-dir file a materialization reads. */
|
|
790
|
+
declare function primeHarnessStatePath(agentDir: string): string;
|
|
791
|
+
interface PrimeMaterializeOptions {
|
|
792
|
+
/**
|
|
793
|
+
* Where the FLAG-NAMED files go — the prompt files and the skills root.
|
|
794
|
+
* Defaults to `agentDir`. An executor that does not own the agent dir points
|
|
795
|
+
* this at a per-run directory of its own, so binding a profile's prompts and
|
|
796
|
+
* skills writes nothing into a dir it must not modify. The context file and
|
|
797
|
+
* the harness store have no flag and always land in `agentDir`; refuse those
|
|
798
|
+
* with {@link primeProfileNeedsAgentDir} instead.
|
|
799
|
+
*/
|
|
800
|
+
flagFileRoot?: string;
|
|
801
|
+
/**
|
|
802
|
+
* Reports state the executor should see but that does not fail the run
|
|
803
|
+
* (currently: adopting entries a pre-shared executor left behind).
|
|
804
|
+
*/
|
|
805
|
+
warn?: (msg: string, meta?: Record<string, unknown>) => void;
|
|
806
|
+
/** Agent-dir file access; the local filesystem when omitted. */
|
|
807
|
+
io?: PrimeAgentDirIo;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Materialize the validated controls and return the extra spawn args that bind
|
|
811
|
+
* them. Runs before every spawn (same place models.json is materialized), so a
|
|
812
|
+
* continual agent dir is re-pinned to the current profile on each fresh prime
|
|
813
|
+
* process.
|
|
814
|
+
*/
|
|
815
|
+
declare function materializePrimeProfileControls(agentDir: string, controls: PrimeProfileControls, options?: PrimeMaterializeOptions): string[];
|
|
816
|
+
/**
|
|
817
|
+
* Remove the files a PREVIOUS materialization of this lowering wrote, so a
|
|
818
|
+
* profile that shrank cannot leave a stale instruction file or skill behind for
|
|
819
|
+
* the next run against the same dirs.
|
|
820
|
+
*
|
|
821
|
+
* Only the paths this lowering NAMES are removed. There is deliberately no
|
|
822
|
+
* manifest: a manifest would live where the agent can write it, and reading a
|
|
823
|
+
* delete list out of agent-writable state turns pruning into an arbitrary-path
|
|
824
|
+
* delete.
|
|
825
|
+
*/
|
|
826
|
+
declare function prunePrimeProfileMaterial(agentDir: string, options?: Pick<PrimeMaterializeOptions, "flagFileRoot">): void;
|
|
827
|
+
/**
|
|
828
|
+
* Upsert profile subagent specs into the fork's global continual-harness
|
|
829
|
+
* store and remove profile-sourced entries the current profile no longer
|
|
830
|
+
* declares. Agent-written entries (`source: "agent"`) — and every top-level
|
|
831
|
+
* key this lowering does not manage — are preserved untouched.
|
|
832
|
+
*
|
|
833
|
+
* A store that exists but no longer parses raises
|
|
834
|
+
* {@link PrimeHarnessStateError}: the file is the agent's own self-modification
|
|
835
|
+
* state, and overwriting it destroys what the run was supposed to observe.
|
|
836
|
+
*/
|
|
837
|
+
declare function seedPrimeProfileSubagents(agentDir: string, subagents: PrimeProfileSubagent[], warn?: (msg: string, meta?: Record<string, unknown>) => void, io?: PrimeAgentDirIo): void;
|
|
838
|
+
//#endregion
|
|
839
|
+
//#region src/prime-fork.d.ts
|
|
840
|
+
/**
|
|
841
|
+
* Fork FACTS for prime-agent (PrimeIntellect-ai/prime-agent) — the constants,
|
|
842
|
+
* dialects and refusal reasons every executor that drives the fork needs, with
|
|
843
|
+
* no `node:fs` and no executor assumptions. The agent-dir MATERIALIZATION that
|
|
844
|
+
* consumes them lives in `./index.ts`; both consumers (cli-bridge's host-spawn
|
|
845
|
+
* backend on `--mode rpc`, sdk-provider-prime's in-sandbox adapter on
|
|
846
|
+
* `--mode acp`) read these instead of each keeping a private copy, because a
|
|
847
|
+
* fork bump must move one file, not two repositories.
|
|
848
|
+
*
|
|
849
|
+
* Every value here was read from PrimeIntellect-ai/prime-agent 0.7.0
|
|
850
|
+
* (be9e2fa0); a fork bump re-reads them against the new clone.
|
|
851
|
+
*/
|
|
852
|
+
/**
|
|
853
|
+
* Env vars the agent resolves its config dir from, most-specific first.
|
|
854
|
+
*
|
|
855
|
+
* The fork derives the name from its own package identity —
|
|
856
|
+
* `ENV_AGENT_DIR = \`${envPrefix}_CODING_AGENT_DIR\`` where `envPrefix` comes
|
|
857
|
+
* from `package.json` `piConfig.name` (config.ts:485-498) — so the fork reads
|
|
858
|
+
* `PRIME_AGENT_CODING_AGENT_DIR` and upstream pi reads `PI_CODING_AGENT_DIR`.
|
|
859
|
+
* An executor that sets only the fork's name has its isolation SILENTLY
|
|
860
|
+
* disabled when the binary on PATH turns out to be upstream pi: `getAgentDir()`
|
|
861
|
+
* falls back to `homedir()/<CONFIG_DIR_NAME>` (config.ts:520-527), one shared
|
|
862
|
+
* dir — and therefore one shared self-modifying `harness_state.json` — for
|
|
863
|
+
* every session on the box. Setting BOTH names costs nothing and keeps the
|
|
864
|
+
* isolation fail-closed under either binary.
|
|
865
|
+
*/
|
|
866
|
+
declare const PRIME_AGENT_DIR_ENV_VARS: readonly ["PRIME_AGENT_CODING_AGENT_DIR", "PI_CODING_AGENT_DIR"];
|
|
867
|
+
/** Canonical agent-dir env var for the fork itself (config.ts:498). */
|
|
868
|
+
declare const PRIME_AGENT_DIR_ENV_VAR: "PRIME_AGENT_CODING_AGENT_DIR";
|
|
869
|
+
/** Pin `agentDir` under every name the agent could resolve its config dir from. */
|
|
870
|
+
declare function primeAgentDirEnv(agentDir: string): Record<string, string>;
|
|
871
|
+
/**
|
|
872
|
+
* Operator knobs an executor forwards into the agent when they are set.
|
|
873
|
+
*
|
|
874
|
+
* `PRIME_AGENT_KERNEL_VENV` is load-bearing for any executor that also pins
|
|
875
|
+
* HOME: the kernel venv defaults under `homedir()/.prime/agent/kernel-venv`
|
|
876
|
+
* (kernel/bootstrap.ts:331-342), so a fresh HOME re-bootstraps it through uv on
|
|
877
|
+
* every run unless the operator's venv path is forwarded
|
|
878
|
+
* (bootstrap.ts:340 override, :358 branch).
|
|
879
|
+
*/
|
|
880
|
+
declare const PRIME_KERNEL_ENV_PASSTHROUGH: readonly ["PRIME_AGENT_INSTALL_UV", "PRIME_AGENT_KERNEL_PYTHON", "PRIME_AGENT_KERNEL_VENV"];
|
|
881
|
+
/**
|
|
882
|
+
* Env vars an executor must NEVER forward from its own environment.
|
|
883
|
+
*
|
|
884
|
+
* These re-point the self-modifying continual-harness store OUTSIDE the agent
|
|
885
|
+
* dir (agent-session.ts:8805 hands the kernel its store location), which
|
|
886
|
+
* defeats per-session isolation without changing anything an executor inspects.
|
|
887
|
+
* Isolation is the fail-closed default; sharing state is an explicit opt-in
|
|
888
|
+
* that names a directory, never an inherited env var.
|
|
889
|
+
*/
|
|
890
|
+
declare const PRIME_HARNESS_STATE_ENV_DENYLIST: readonly ["RLM_GLOBAL_HARNESS_STATE_DIR", "RLM_HARNESS_STATE_DIR"];
|
|
891
|
+
/**
|
|
892
|
+
* A prime-agent IPython kernel that dies is never re-provisioned headlessly —
|
|
893
|
+
* every later `ipython` call fails with one of these markers until the process
|
|
894
|
+
* is replaced. An executor that cannot recognize them either reports a generic
|
|
895
|
+
* turn failure or burns its whole timeout against a permanently dead tool.
|
|
896
|
+
*
|
|
897
|
+
* Verified in `core/kernel/index.ts`: :723 ("forked kernel exited
|
|
898
|
+
* unexpectedly"), :750 ("Kernel exited before resolving ports"), :779 ("Kernel
|
|
899
|
+
* exited during startup"), :820/:837/:1172/:1295 ("Kernel has been shut down").
|
|
900
|
+
*/
|
|
901
|
+
declare const PRIME_KERNEL_DEAD_MARKERS: readonly string[];
|
|
902
|
+
/** The first kernel-death marker present in `text`, or undefined. */
|
|
903
|
+
declare function matchPrimeKernelDeadMarker(text: string): string | undefined;
|
|
904
|
+
/**
|
|
905
|
+
* `--thinking` rungs the fork's argument parser accepts
|
|
906
|
+
* (cli/args.ts:62 `VALID_THINKING_LEVELS`, rejected at :175). Read from the
|
|
907
|
+
* fork itself rather than borrowed from upstream pi's measured table: the two
|
|
908
|
+
* agreeing today is a coincidence this module must not depend on.
|
|
909
|
+
*/
|
|
910
|
+
declare const PRIME_THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
911
|
+
type PrimeThinkingLevel = (typeof PRIME_THINKING_LEVELS)[number];
|
|
912
|
+
/**
|
|
913
|
+
* Map the portable reasoning ladder onto the fork's `--thinking` value.
|
|
914
|
+
*
|
|
915
|
+
* Throws on an effort with no rung instead of returning undefined: omitting the
|
|
916
|
+
* flag runs the agent at its default thinking level while the caller believes
|
|
917
|
+
* the requested effort is in force, which is a silently dropped control.
|
|
918
|
+
*/
|
|
919
|
+
declare function primeThinkingLevel(effort: string | null | undefined): PrimeThinkingLevel | undefined;
|
|
920
|
+
/**
|
|
921
|
+
* Why `profile.mcp` (and any hub connection that resolves to MCP) is refused.
|
|
922
|
+
*
|
|
923
|
+
* The fork's `mcpServers` settings surface IS read at startup
|
|
924
|
+
* (settings-manager.ts:98-120,219) but a user-declared server never becomes
|
|
925
|
+
* model-visible: the host McpManager registers OAuth providers and serves
|
|
926
|
+
* mcp.config/refresh host-requests only (core/mcp/mcp-manager.ts:62-124),
|
|
927
|
+
* skips stdio servers entirely (mcp-manager.ts:73), and nothing generates a
|
|
928
|
+
* skill or prompt section for one. Model-visible MCP is exactly the built-in
|
|
929
|
+
* catalog skills, which are hand-written Python `McpIntegration` subclasses
|
|
930
|
+
* (prime-agent-runtime/src/rlm/mcp_base.py:112-125; only linear and notion
|
|
931
|
+
* ship). Materializing a per-run entry would run the agent WITHOUT the
|
|
932
|
+
* requested tools while the config on disk says otherwise.
|
|
933
|
+
*/
|
|
934
|
+
declare const PRIME_MCP_UNSUPPORTED_REASON: string;
|
|
935
|
+
/** Which half of a profile refusal this is: a fork limit, or a bad declaration. */
|
|
936
|
+
type PrimeProfileErrorKind = "unsupported" | "invalid";
|
|
937
|
+
/**
|
|
938
|
+
* Refusal raised by the shared prime lowering, carrying the control and the
|
|
939
|
+
* reason separately so each executor can render them in its own error contract
|
|
940
|
+
* (an HTTP backend's typed `BackendError`, an SDK adapter's plain `Error`)
|
|
941
|
+
* without the reason text — which is where the fork evidence lives — being
|
|
942
|
+
* rewritten per repository.
|
|
943
|
+
*/
|
|
944
|
+
declare class PrimeProfileError extends Error {
|
|
945
|
+
readonly kind: PrimeProfileErrorKind;
|
|
946
|
+
readonly control: string;
|
|
947
|
+
readonly reason: string;
|
|
948
|
+
constructor(kind: PrimeProfileErrorKind, control: string, reason: string);
|
|
949
|
+
}
|
|
950
|
+
/**
|
|
951
|
+
* The fork's continual-harness store exists but no longer parses.
|
|
952
|
+
*
|
|
953
|
+
* The store is the agent's own self-modification state — refinements, learned
|
|
954
|
+
* prompts, subagents it created mid-session — so an executor that reseeds it
|
|
955
|
+
* from empty destroys evidence and silently mutates the thing under study. The
|
|
956
|
+
* turn is failed instead; the file is the operator's to repair or remove.
|
|
957
|
+
*/
|
|
958
|
+
declare class PrimeHarnessStateError extends Error {
|
|
959
|
+
readonly statePath: string;
|
|
960
|
+
constructor(statePath: string, detail: string);
|
|
961
|
+
}
|
|
962
|
+
/**
|
|
963
|
+
* Strip `//` line comments and trailing commas, leaving string literals
|
|
964
|
+
* untouched — byte-for-byte the fork's own `stripJsonComments`
|
|
965
|
+
* (core/model-registry.ts), so a models.json the agent accepts is never refused
|
|
966
|
+
* by an executor and vice versa.
|
|
967
|
+
*/
|
|
968
|
+
declare function stripPrimeJsonComments(input: string): string;
|
|
969
|
+
/**
|
|
970
|
+
* Parse a models.json with the fork's own laxness and assert the one structural
|
|
971
|
+
* invariant it requires (a `providers` object). Throws naming `sourcePath`.
|
|
972
|
+
*
|
|
973
|
+
* This is the SHAPE and DIALECT only. Producing the file is deliberately not
|
|
974
|
+
* shared: an executor holding real operator credentials copies an
|
|
975
|
+
* operator-authored file and forwards only the env var names its `apiKey`
|
|
976
|
+
* entries reference, while an in-sandbox executor synthesizes a one-provider
|
|
977
|
+
* entry with a literal key that is a proxy dummy. Same schema, opposite threat
|
|
978
|
+
* models.
|
|
979
|
+
*/
|
|
980
|
+
declare function parsePrimeModelsJson(text: string, sourcePath: string): Record<string, unknown>;
|
|
981
|
+
/**
|
|
982
|
+
* Environment variables a models.json names as `apiKey` sources.
|
|
983
|
+
*
|
|
984
|
+
* prime resolves an `apiKey` value env-var first and LITERAL second
|
|
985
|
+
* (core/resolve-config-value.ts), so an executor that forwards exactly the
|
|
986
|
+
* named variables lets an operator keep secrets out of the file — and an
|
|
987
|
+
* executor that forwards NONE of them silently turns the variable name itself
|
|
988
|
+
* into the credential string.
|
|
989
|
+
*/
|
|
990
|
+
declare function primeApiKeyEnvNames(modelsConfig: Record<string, unknown>): string[];
|
|
991
|
+
//#endregion
|
|
992
|
+
//#region src/profile-bundle-key.d.ts
|
|
993
|
+
declare const PROFILE_BUNDLE_SCHEMA = "agent-profile-bundle/v1";
|
|
994
|
+
declare const PROFILE_BUNDLE_MAX_FILES = 512;
|
|
995
|
+
declare const PROFILE_BUNDLE_MAX_BYTES: number;
|
|
996
|
+
declare const PROFILE_BUNDLE_MAX_FILE_BYTES: number;
|
|
997
|
+
declare const PROFILE_BUNDLE_DEFAULT_MAX_BYTES: number;
|
|
998
|
+
interface ProfileBundleFileEntry {
|
|
999
|
+
/** Logical workspace-relative mount path, exactly as declared on the profile. */
|
|
1000
|
+
mountPath: string;
|
|
1001
|
+
/** SHA-256 of the content bytes as lowercase hex, WITHOUT the `sha256:` prefix. */
|
|
1002
|
+
sha256: string;
|
|
1003
|
+
/** Full file mode (0o644 default, 0o755 for executable mounts). */
|
|
1004
|
+
mode: number;
|
|
1005
|
+
}
|
|
1006
|
+
interface ProfileBundleManifest {
|
|
1007
|
+
schema: string;
|
|
1008
|
+
/** Raw bundle key (e.g. `sha256:<hex>`); also recoverable from the filename. */
|
|
1009
|
+
bundle: string;
|
|
1010
|
+
createdAt: string;
|
|
1011
|
+
sizeBytes: number;
|
|
1012
|
+
files: Array<ProfileBundleFileEntry & {
|
|
1013
|
+
target: string;
|
|
1014
|
+
}>;
|
|
1015
|
+
}
|
|
1016
|
+
interface ProfileBundleClaim {
|
|
1017
|
+
bundle: string;
|
|
1018
|
+
files: Array<{
|
|
1019
|
+
mountPath: string;
|
|
1020
|
+
sha256: string;
|
|
1021
|
+
}>;
|
|
1022
|
+
}
|
|
1023
|
+
type ProfileBundleClaimResult = {
|
|
1024
|
+
status: "hit";
|
|
1025
|
+
linked: string[];
|
|
1026
|
+
} | {
|
|
1027
|
+
status: "miss";
|
|
1028
|
+
missing: string[];
|
|
1029
|
+
};
|
|
1030
|
+
interface ProfileBundleCache {
|
|
1031
|
+
root: string;
|
|
1032
|
+
maxBytes: number;
|
|
1033
|
+
admit(manifest: ProfileBundleManifest, readObject: (sha256: string) => Promise<Uint8Array> | Uint8Array): Promise<void>;
|
|
1034
|
+
evict(): Promise<void>;
|
|
1035
|
+
sweep(): Promise<void>;
|
|
1036
|
+
}
|
|
1037
|
+
/**
|
|
1038
|
+
* Derive the canonical bundle file entry for one inline mount. The sha256 is
|
|
1039
|
+
* computed over the exact inline content bytes and the mode mirrors the SDK's
|
|
1040
|
+
* `profileFileMode`/`isExecutableProfileFile`: `mount.executable` wins when
|
|
1041
|
+
* present, otherwise a path under a `bin/` or `sbin/` directory is executable.
|
|
1042
|
+
* A mount whose resource is not inline is a caller bug and throws, matching
|
|
1043
|
+
* the fail-closed discipline of {@link resolveInlineRef}.
|
|
1044
|
+
*/
|
|
1045
|
+
declare function profileBundleFileEntry(mount: AgentProfileFileMount): ProfileBundleFileEntry;
|
|
1046
|
+
/**
|
|
1047
|
+
* The canonical file table: one entry per mount, sorted by (mountPath, sha256)
|
|
1048
|
+
* so any array order of the same mounts produces the same table.
|
|
1049
|
+
*/
|
|
1050
|
+
declare function profileBundleFileTable(mounts: readonly AgentProfileFileMount[]): ProfileBundleFileEntry[];
|
|
1051
|
+
/**
|
|
1052
|
+
* The content-addressed bundle key. The digest covers EXACTLY the schema
|
|
1053
|
+
* version and, per file, the logical mount path, the sha256 of the content
|
|
1054
|
+
* bytes, and the full file mode — the same image-content-hash discipline as
|
|
1055
|
+
* scripts/ci/image-content-hash.mjs: hash exactly the inputs that determine
|
|
1056
|
+
* the cached bytes (and their placement semantics), nothing more. Any profile
|
|
1057
|
+
* change — content, path, or mode — produces a new key; anything else
|
|
1058
|
+
* (mount order, transport-only target paths, timestamps) does not.
|
|
1059
|
+
*/
|
|
1060
|
+
declare function profileFileBundleKey(mounts: readonly AgentProfileFileMount[]): string;
|
|
1061
|
+
//#endregion
|
|
1062
|
+
//#region src/profile-bundle-lru.d.ts
|
|
1063
|
+
/**
|
|
1064
|
+
* Bundle keys come from `canonicalCandidateDigest` as `sha256:<hex>`; the `:`
|
|
1065
|
+
* is encoded so the key is a safe single path segment on any host filesystem.
|
|
1066
|
+
* The raw key is always recoverable from the manifest's `bundle` field.
|
|
1067
|
+
*/
|
|
1068
|
+
declare function profileBundleManifestPath(root: string, bundle: string): string;
|
|
1069
|
+
/** Sweep only while holding the per-root lock; active admissions own incoming/. */
|
|
1070
|
+
declare function sweepProfileBundleCache(root: string): Promise<void>;
|
|
1071
|
+
/**
|
|
1072
|
+
* Evict least-recently-used objects until total object bytes are within
|
|
1073
|
+
* `maxBytes`. Unreferenced objects go first (they reclaim space with no
|
|
1074
|
+
* bundle impact); if the cap still does not hold, referenced objects are
|
|
1075
|
+
* evicted oldest-first, which makes their bundles partial — claims then miss
|
|
1076
|
+
* and re-deliver, so eviction can never serve wrong bytes. Bundle manifests
|
|
1077
|
+
* referencing no existing objects are removed. Mid-admit `incoming/` dirs are
|
|
1078
|
+
* never touched.
|
|
1079
|
+
*/
|
|
1080
|
+
declare function evictProfileBundles(root: string, maxBytes: number): Promise<void>;
|
|
1081
|
+
//#endregion
|
|
1082
|
+
//#region src/profile-bundle-cache.d.ts
|
|
1083
|
+
/**
|
|
1084
|
+
* Admit a just-delivered bundle to the host cache, all-or-nothing. Every
|
|
1085
|
+
* object's bytes are verified against its content hash BEFORE anything is
|
|
1086
|
+
* renamed into place; a mismatch throws with nothing published. Objects
|
|
1087
|
+
* already present are re-verified against the incoming bytes, then the temp
|
|
1088
|
+
* copy is dropped — the existing object was verified when it was admitted.
|
|
1089
|
+
* The manifest is written LAST as the commit point, followed by lru update
|
|
1090
|
+
* and eviction down to the default cap.
|
|
1091
|
+
*/
|
|
1092
|
+
declare function admitProfileBundle(root: string, manifest: ProfileBundleManifest, readObject: (sha256: string) => Promise<Uint8Array> | Uint8Array): Promise<void>;
|
|
1093
|
+
/**
|
|
1094
|
+
* Claim a bundle from a (possibly read-only mounted) cache. Verify-on-read:
|
|
1095
|
+
* every object's bytes are re-hashed and compared to BOTH the manifest entry
|
|
1096
|
+
* and the claim's expected sha256 before `linkFile` is called — a read-only
|
|
1097
|
+
* mount must never serve unverified bytes. `linkFile` returning false sends
|
|
1098
|
+
* the file to `missing` (the caller delivers it normally). Status is "hit"
|
|
1099
|
+
* only when nothing is missing; a partial bundle is NEVER a hit. The only
|
|
1100
|
+
* write is a best-effort lru touch, wrapped so EROFS on a read-only mount is
|
|
1101
|
+
* harmless.
|
|
1102
|
+
*/
|
|
1103
|
+
declare function claimProfileBundle(root: string, claim: ProfileBundleClaim, linkFile: (objectPath: string, entry: {
|
|
1104
|
+
mountPath: string;
|
|
1105
|
+
target: string;
|
|
1106
|
+
sha256: string;
|
|
1107
|
+
mode: number;
|
|
1108
|
+
}) => Promise<boolean>): Promise<ProfileBundleClaimResult>;
|
|
1109
|
+
/**
|
|
1110
|
+
* Open a host-side cache handle over `root`, creating the layout and sweeping
|
|
1111
|
+
* stale `incoming/` residue synchronously when the root is idle. A busy root
|
|
1112
|
+
* leaves cleanup to its serialized admissions and sweeps.
|
|
1113
|
+
*/
|
|
1114
|
+
declare function openProfileBundleCache(root: string, options?: {
|
|
1115
|
+
maxBytes?: number;
|
|
1116
|
+
}): ProfileBundleCache;
|
|
1117
|
+
//#endregion
|
|
1118
|
+
//#region src/profile-materializer.d.ts
|
|
1119
|
+
declare const UNAVAILABLE_AGENT_PROFILE_SECRET_PROVIDER: AgentProfileSecretProvider;
|
|
1120
|
+
/**
|
|
1121
|
+
* Why a profile's tool and permission controls cannot reach one native policy
|
|
1122
|
+
* on this harness, or undefined when they can.
|
|
1123
|
+
*
|
|
1124
|
+
* Admission boundaries (profile save, Sandbox create) call this so a
|
|
1125
|
+
* contradictory control set is refused when it is submitted, not when a
|
|
1126
|
+
* user's turn materializes it. Controls a harness cannot enforce are not
|
|
1127
|
+
* contradictions: `resources.failOnError` decides those per turn.
|
|
1128
|
+
*/
|
|
1129
|
+
declare function executionControlConflict(profile: Pick<AgentProfile, "tools" | "permissions" | "mcp">, harness: HarnessId): string | undefined;
|
|
1130
|
+
/**
|
|
1131
|
+
* Build a pure workspace plan for one canonical harness.
|
|
1132
|
+
* The caller applies files, environment, and flags at its process boundary.
|
|
1133
|
+
*/
|
|
1134
|
+
declare function materializeProfile(inputProfile: AgentProfile, harness: HarnessId, opts?: {
|
|
1135
|
+
skip?: SkippableDimension[];
|
|
1136
|
+
binds?: readonly BindableLaunchControl[];
|
|
1137
|
+
instructionsRoot?: PlanFileRoot;
|
|
1138
|
+
runtimeAttachments?: AgentRuntimeAttachments;
|
|
1139
|
+
}): WorkspacePlan;
|
|
1140
|
+
//#endregion
|
|
1141
|
+
//#region src/resource-resolution.d.ts
|
|
1142
|
+
interface ResolveAgentProfileResourcesOptions {
|
|
1143
|
+
/** Repository used when a GitHub resource omits its own `repository`. */
|
|
1144
|
+
repository?: string;
|
|
1145
|
+
fetch?: typeof globalThis.fetch;
|
|
1146
|
+
timeoutMs?: number;
|
|
1147
|
+
}
|
|
1148
|
+
/**
|
|
1149
|
+
* Resolve every GitHub resource to exact inline bytes before materialization.
|
|
1150
|
+
* The profile's default harness does not affect resource resolution.
|
|
1151
|
+
*/
|
|
1152
|
+
declare function resolveAgentProfileResources(inputProfile: AgentProfile, options?: ResolveAgentProfileResourcesOptions): Promise<AgentProfile>;
|
|
1153
|
+
/** Normalize any skill markdown (VB frontmatter `skill:`/`description:`, or raw) into a
|
|
1154
|
+
* harness SKILL.md with `name:`/`description:` frontmatter the harnesses require. */
|
|
1155
|
+
declare function normalizeSkillMd(name: string, raw: string): string;
|
|
1156
|
+
//#endregion
|
|
1157
|
+
//#region src/secret-concurrent-revision.d.ts
|
|
1158
|
+
/**
|
|
1159
|
+
* Publish a resolved revision for exactly one native subprocess UID. The
|
|
1160
|
+
* executor-owned naming key hides low-entropy credential guesses from paths;
|
|
1161
|
+
* the resolved digest and manifest never leave this server-side result.
|
|
1162
|
+
*/
|
|
1163
|
+
declare function prepareSecretConcurrentProfileRevision(input: {
|
|
1164
|
+
plan: WorkspacePlan; /** Trusted executor transport only; never read from the mutable native HOME. */
|
|
1165
|
+
providerConfig?: Record<string, unknown>;
|
|
1166
|
+
managedRoot: string;
|
|
1167
|
+
launchRoot: string;
|
|
1168
|
+
sharedWorkspaceDir: string;
|
|
1169
|
+
ownerId: string;
|
|
1170
|
+
subprocessUid: number;
|
|
1171
|
+
namingKey: Uint8Array;
|
|
1172
|
+
secretProvider: AgentProfileSecretProvider;
|
|
1173
|
+
options?: Pick<ApplyWorkspacePlanOptions, "runtimeOnlyFiles">;
|
|
1174
|
+
}): Promise<ConcurrentProfileRevision & {
|
|
1175
|
+
/**
|
|
1176
|
+
* The value behind each `{env:NAME}` reference in the revision's config,
|
|
1177
|
+
* for the executor alone: the launch never receives them. An executor
|
|
1178
|
+
* that serves a referencing MCP server through its own loopback proxy
|
|
1179
|
+
* resolves the server's headers here.
|
|
1180
|
+
*/
|
|
1181
|
+
secretReferences: Readonly<Record<string, string>>;
|
|
1182
|
+
}>;
|
|
1183
|
+
//#endregion
|
|
1184
|
+
//#region src/secret-session-view.d.ts
|
|
1185
|
+
/** Stable native cwd binds workspace, session and UID across turn revisions. */
|
|
1186
|
+
declare function secretSessionViewWorkspace(input: {
|
|
1187
|
+
launchRoot: string;
|
|
1188
|
+
sharedWorkspaceDir: string;
|
|
1189
|
+
sessionId: string;
|
|
1190
|
+
subprocessUid: number;
|
|
1191
|
+
}): string;
|
|
1192
|
+
/** Bind published read-only resources at literal paths; generated config stays outside cwd.
|
|
1193
|
+
* Callers serialize turns and bind before spawning, never while a native process reads it. */
|
|
1194
|
+
declare function bindSecretSessionView(input: {
|
|
1195
|
+
launchRoot: string;
|
|
1196
|
+
viewWorkspaceDir: string;
|
|
1197
|
+
revisionWorkspaceDir: string;
|
|
1198
|
+
subprocessUid: number;
|
|
1199
|
+
}): void;
|
|
1200
|
+
//#endregion
|
|
1201
|
+
//#region src/tool-bin-path.d.ts
|
|
1202
|
+
/** The colon-separated, absolute CLI bin dirs a sandbox app mounts for its tools. */
|
|
1203
|
+
declare const SANDBOX_TOOL_BIN_DIRS_ENV = "SANDBOX_TOOL_BIN_DIRS";
|
|
1204
|
+
/**
|
|
1205
|
+
* The tool bin dirs a `SANDBOX_TOOL_BIN_DIRS` value names, or `[]` when it is
|
|
1206
|
+
* unset or blank.
|
|
1207
|
+
*
|
|
1208
|
+
* Fail loud, never silently degrade: a malformed value (a relative segment,
|
|
1209
|
+
* or an empty segment from a stray/leading/trailing colon) throws rather than
|
|
1210
|
+
* silently dropping a tool dir from PATH or admitting a relative path that
|
|
1211
|
+
* resolves against whatever the process cwd happens to be.
|
|
1212
|
+
*/
|
|
1213
|
+
declare function parseSandboxToolBinDirs(value: string | undefined): string[];
|
|
1214
|
+
/**
|
|
1215
|
+
* A launch environment whose tool bin dirs are `toolBinDirs`, at the TAIL of
|
|
1216
|
+
* PATH after every Nix, npm, image and system entry, so a tool never shadows
|
|
1217
|
+
* a platform-owned binary of the same name.
|
|
1218
|
+
*
|
|
1219
|
+
* They replace `appToolBinDirs` (by default the dirs the environment's own
|
|
1220
|
+
* `SANDBOX_TOOL_BIN_DIRS` names) wherever those sit in PATH, so an app's older
|
|
1221
|
+
* copy of the same tool cannot win by PATH order. Relative PATH entries are
|
|
1222
|
+
* dropped too: they resolve against whatever cwd the turn moves to.
|
|
1223
|
+
*/
|
|
1224
|
+
declare function bindLaunchToolBinDirs(env: Readonly<Record<string, string | undefined>>, toolBinDirs: readonly string[], appToolBinDirs?: readonly string[]): Record<string, string | undefined>;
|
|
1225
|
+
//#endregion
|
|
1226
|
+
export { type AgentCandidateWorkspacePlan, type AgentCandidateWorkspacePlanReceipt, type ApplyAgentCandidateWorkspacePlanOptions, type ApplyWorkspacePlanOptions, BINDABLE_LAUNCH_CONTROLS, type BindableLaunchControl, CODEX_DISABLED_FEATURE_ARGS, type ConcurrentProfileRevision, EXECUTOR_SYSTEM_PROMPT_BINDINGS, type ExecutorSystemPromptBinding, HARNESS_SKILL_DIRS, type HarnessId, MATERIALIZER_CONTEXT_PATHS, MATERIALIZER_HARNESSES, type ManagedWorkspaceFileDigest, type ManagedWorkspaceManifest, type MaterializeCandidateProfileOptions, OPENCODE_NATIVE_TOOL_IDS, type OpenCodeMcpConfig, PI_MODELS_CONFIG_PATH, PRIME_AGENT_DIR_ENV_VAR, PRIME_AGENT_DIR_ENV_VARS, PRIME_HARNESS_STATE_ENV_DENYLIST, PRIME_KERNEL_DEAD_MARKERS, PRIME_KERNEL_ENV_PASSTHROUGH, PRIME_MCP_UNSUPPORTED_REASON, PRIME_THINKING_LEVELS, PROFILE_BUNDLE_DEFAULT_MAX_BYTES, PROFILE_BUNDLE_MAX_BYTES, PROFILE_BUNDLE_MAX_FILES, PROFILE_BUNDLE_MAX_FILE_BYTES, PROFILE_BUNDLE_SCHEMA, type PiModelsConfigFile, type PiModelsConfigInput, type PiRuntimePaths, type PlanFile, type PlanFileRoot, type PlanFileSecretSlot, type PlanRequirement, PrimeHarnessStateError, type PrimeMaterializeOptions, type PrimeProfileControls, PrimeProfileError, type PrimeProfileErrorKind, type PrimeProfileSkill, type PrimeProfileSubagent, type PrimeThinkingLevel, ProfileBundleCache, ProfileBundleClaim, ProfileBundleClaimResult, ProfileBundleFileEntry, ProfileBundleManifest, type ResolveAgentProfileResourcesOptions, SANDBOX_TOOL_BIN_DIRS_ENV, SKIPPABLE_DIMENSIONS, type SkippableDimension, UNAVAILABLE_AGENT_PROFILE_SECRET_PROVIDER, type Unsupported, type WorkspacePlan, type WorkspacePlanApplication, type WorkspacePlanArgument, type WorkspacePlanArgumentTemplate, WorkspacePlanCleanupError, type WorkspacePlanConfigValue, type WorkspacePlanReceipt, type WorkspacePlanSecretSegment, type WorkspacePlanSpawnInputs, type WorkspacePlanSystemPromptBinding, type WorkspacePlanWrittenFile, admitProfileBundle, agentCandidateProfilePlanMaterial, applyAgentCandidateWorkspacePlan, applyWorkspacePlan, applyWorkspacePlanWithSecretProvider, assertPrimeModelAgreement, assertWorkspacePlanSupported, bindLaunchToolBinDirs, bindSecretSessionView, buildPiModelsConfig, buildPiModelsConfigFile, canonicalizeAgentCandidateProfilePlan, captureAgentCandidateProfilePlan, claimProfileBundle, codexDeveloperInstructionArgs, enforceWorkspacePlanSupport, ensurePublicConcurrentProfileRoots, evictProfileBundles, executionControlConflict, harnessAutoLoadsAgentContextFile, hasPrimeProfileMaterial, hashWorkspacePlan, isMaterializerHarness, isMaterializerMcpConfig, isSkippableDimension, joinSystemPromptAdditions, keepsHarnessSystemPrompt, markMaterializerContextFile, matchPrimeKernelDeadMarker, materializeCandidateProfile, materializePrimeProfileControls, materializeProfile, modelIdsMatch, normalizeSkillMd, openCodeMcpConfig, openCodeNativeToolId, openProfileBundleCache, parsePrimeModelsJson, parseSandboxToolBinDirs, preparePublicConcurrentProfileRevision, prepareSecretConcurrentProfileRevision, primeAgentDirEnv, primeApiKeyEnvNames, primeHarnessStatePath, primeProfileNeedsAgentDir, primeSubagentEntryId, primeThinkingLevel, profileBundleFileEntry, profileBundleFileTable, profileBundleManifestPath, profileFileBundleKey, prunePrimeProfileMaterial, qualifyModelId, readPrimeProfileControls, resolveAgentProfileResources, resolvePiRuntimePaths, secretSessionViewWorkspace, seedPrimeProfileSubagents, skillDirForHarness, stripPrimeJsonComments, sweepProfileBundleCache, takeSystemPromptBinding, unqualifyModelId, writePrimeAgentFile };
|