@tangle-network/agent-profile-materialize 1.1.7 → 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 -106
- 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 -31
- package/dist/managed-workspace.js +0 -271
- 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 -249
- package/dist/secret-session-view.d.ts +0 -25
- package/dist/secret-session-view.js +0 -166
- 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/plan-types.d.ts
DELETED
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
export type { HarnessId } from "./harness.js";
|
|
2
|
-
/** The executor-owned root that receives a materialized file. */
|
|
3
|
-
export type PlanFileRoot = "workspace" | "agent";
|
|
4
|
-
export interface PlanFile {
|
|
5
|
-
relPath: string;
|
|
6
|
-
content: string;
|
|
7
|
-
/** Defaults to the run workspace. `agent` is the harness's private agent directory. */
|
|
8
|
-
root?: PlanFileRoot;
|
|
9
|
-
/** chmod mode (e.g. 0o755 for hook scripts); default 0o644. */
|
|
10
|
-
mode?: number;
|
|
11
|
-
/**
|
|
12
|
-
* Provenance of this entry. `"generated"` = the materializer synthesized the
|
|
13
|
-
* content itself (native harness config, merged settings, lowered prompt/MCP/
|
|
14
|
-
* hooks/subagents). `"user"` = the exact bytes of a profile-declared resource
|
|
15
|
-
* ref (`resources.files`/`tools`/`agents`/`skills`/`commands`), passed through
|
|
16
|
-
* verbatim at the path the profile author chose.
|
|
17
|
-
*
|
|
18
|
-
* A consumer that needs to reinterpret a SPECIFIC generated file (e.g. parse
|
|
19
|
-
* `opencode.json` as the synthetic native config) MUST gate on
|
|
20
|
-
* `source === "generated"` at that relPath — matching by relPath alone cannot
|
|
21
|
-
* tell a harness-authored config apart from a user resource mount that
|
|
22
|
-
* happens to share the same conventional path, and treating arbitrary user
|
|
23
|
-
* content as trusted generated config is a fail-open bug, not a fallback.
|
|
24
|
-
*
|
|
25
|
-
* Optional: callers that hand-construct a {@link WorkspacePlan} directly for
|
|
26
|
-
* {@link applyWorkspacePlan} (tests, ad hoc writes) are not materializer
|
|
27
|
-
* output and have no provenance to report. `materializeProfile` always sets
|
|
28
|
-
* this on every file it emits.
|
|
29
|
-
*/
|
|
30
|
-
source?: "user" | "generated";
|
|
31
|
-
/**
|
|
32
|
-
* Who owns the PATH — which decides whether an existing file there may be
|
|
33
|
-
* replaced.
|
|
34
|
-
*
|
|
35
|
-
* `"materializer"` = a path whose generated content is wholly this
|
|
36
|
-
* package's output: a name this package invented, the generated context file
|
|
37
|
-
* (`CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `HERMES.md`), or `opencode.json`,
|
|
38
|
-
* which carries only the registrations generated from the profile. A file
|
|
39
|
-
* already there is this materializer's own output from an earlier application
|
|
40
|
-
* into the same workspace, and replacing it is how turn two of a resumed
|
|
41
|
-
* session — or the first turn of a branched one — gets the current profile
|
|
42
|
-
* instead of the previous one. Application replaces it only when the existing
|
|
43
|
-
* bytes prove that provenance — by the name for an invented path, by a marker
|
|
44
|
-
* line committing to the body digest for a context file, by the content for
|
|
45
|
-
* `opencode.json`.
|
|
46
|
-
*
|
|
47
|
-
* `"shared"` (the default, and every other file) = a path the user or the
|
|
48
|
-
* harness also owns. `.gemini/system.md` is a documented, user-authorable
|
|
49
|
-
* name whose content this package cannot tell from its own, and so is a
|
|
50
|
-
* context file mounted as an explicit profile resource rather than generated.
|
|
51
|
-
* An existing file there may be the caller's own work, so it is never
|
|
52
|
-
* replaced.
|
|
53
|
-
*
|
|
54
|
-
* Optional because hand-constructed plans have no path provenance to report;
|
|
55
|
-
* absent reads as `"shared"`, the safe answer.
|
|
56
|
-
*/
|
|
57
|
-
ownership?: "materializer" | "shared";
|
|
58
|
-
/**
|
|
59
|
-
* Secret leaves in a generated JSON document. `content` contains `null` at
|
|
60
|
-
* each path until the private executor resolves the named reference. The
|
|
61
|
-
* public plan, its digest, and its receipt retain only these references.
|
|
62
|
-
*/
|
|
63
|
-
secretSlots?: PlanFileSecretSlot[];
|
|
64
|
-
}
|
|
65
|
-
export interface PlanFileSecretSlot {
|
|
66
|
-
path: Array<string | number>;
|
|
67
|
-
ref: AgentProfileSecretRef;
|
|
68
|
-
}
|
|
69
|
-
export interface WorkspacePlanSecretSegment {
|
|
70
|
-
kind: "secret";
|
|
71
|
-
ref: AgentProfileSecretRef;
|
|
72
|
-
/** Encoding applied after private resolution. */
|
|
73
|
-
encoding: "raw" | "json-string";
|
|
74
|
-
}
|
|
75
|
-
/** A launch argument whose private leaves are resolved immediately before spawn. */
|
|
76
|
-
export interface WorkspacePlanArgumentTemplate {
|
|
77
|
-
kind: "workspace-plan-argument-template";
|
|
78
|
-
segments: Array<string | WorkspacePlanSecretSegment>;
|
|
79
|
-
}
|
|
80
|
-
export type WorkspacePlanArgument = string | WorkspacePlanArgumentTemplate;
|
|
81
|
-
/** Public bytes stay strings; secret references stay opaque until application. */
|
|
82
|
-
export type WorkspacePlanConfigValue = string | AgentProfileSecretRef;
|
|
83
|
-
export interface Unsupported {
|
|
84
|
-
dimension: "files" | "skills" | "mcp" | "hooks" | "subagents" | "commands" | "instructions" | "systemPrompt" | "appendSystemPrompt" | "connections" | "confidential" | "permissions" | "tools" | "modes" | "extensions";
|
|
85
|
-
reason: string;
|
|
86
|
-
}
|
|
87
|
-
/**
|
|
88
|
-
* The subset of {@link BINDABLE_LAUNCH_CONTROLS} the plan HANDS OVER rather than
|
|
89
|
-
* executes: controls a caller reaches only by composing the harness's own
|
|
90
|
-
* configuration, so no file, flag or env var the plan writes can touch them.
|
|
91
|
-
*
|
|
92
|
-
* - `opencode.agent-prompt` — opencode's `agent.<name>.prompt` config field,
|
|
93
|
-
* the one control that replaces its built-in provider prompt. It binds to a
|
|
94
|
-
* SINGLE agent, and the agent is chosen at launch. A caller that builds
|
|
95
|
-
* opencode's config itself and picks the agent there reads neither
|
|
96
|
-
* `plan.files` nor `plan.flags`, so for that one the plan names the control
|
|
97
|
-
* and hands over the text in {@link WorkspacePlan.systemPromptBinding}.
|
|
98
|
-
*
|
|
99
|
-
* Every other bindable control names a capability the plan still lowers itself
|
|
100
|
-
* once the caller has declared the plan's launch inputs really reach the spawn.
|
|
101
|
-
*/
|
|
102
|
-
export declare const EXECUTOR_SYSTEM_PROMPT_BINDINGS: readonly ["opencode.agent-prompt"];
|
|
103
|
-
export type ExecutorSystemPromptBinding = (typeof EXECUTOR_SYSTEM_PROMPT_BINDINGS)[number];
|
|
104
|
-
/**
|
|
105
|
-
* A system-prompt intent handed to the launcher that declared it owns the
|
|
106
|
-
* control, instead of being lowered into the workspace.
|
|
107
|
-
*
|
|
108
|
-
* Distinct from {@link WorkspacePlan.systemPrompt} — a launch ARGUMENT the
|
|
109
|
-
* executor hands to a harness flag — and from the file/flag/env lowerings the
|
|
110
|
-
* plan performs on its own. This names the exact control that must receive the
|
|
111
|
-
* text and which of the two intents it is, so the launcher cannot apply it to
|
|
112
|
-
* the wrong channel. Never written into an additive channel and never dropped:
|
|
113
|
-
* a caller that has not declared it owns `control` gets the plan's own lowering
|
|
114
|
-
* (or a refusal where the harness has no control at all) instead of this field.
|
|
115
|
-
*/
|
|
116
|
-
export interface WorkspacePlanSystemPromptBinding {
|
|
117
|
-
/** Which of the two prompt intents this is — never inferred from presence. */
|
|
118
|
-
intent: "replace";
|
|
119
|
-
/** The exact launcher control that must receive `systemPrompt`. */
|
|
120
|
-
control: ExecutorSystemPromptBinding;
|
|
121
|
-
/** Exact text the control receives. */
|
|
122
|
-
systemPrompt: string;
|
|
123
|
-
}
|
|
124
|
-
/** One file applied by a plan, with the executor root kept explicit. */
|
|
125
|
-
export interface WorkspacePlanWrittenFile {
|
|
126
|
-
root: PlanFileRoot;
|
|
127
|
-
relPath: string;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* The dimensions `materializeProfile`'s `skip` option honors.
|
|
131
|
-
*
|
|
132
|
-
* Every other dimension is materialized unconditionally: generated plan files are pushed through
|
|
133
|
-
* a single site that carries no dimension tag, so there is nothing to gate them on. Naming the
|
|
134
|
-
* honored set keeps `skip: ["hooks"]` a loud rejection instead of a silent no-op.
|
|
135
|
-
*/
|
|
136
|
-
export declare const SKIPPABLE_DIMENSIONS: readonly ["mcp", "extensions"];
|
|
137
|
-
export type SkippableDimension = (typeof SKIPPABLE_DIMENSIONS)[number];
|
|
138
|
-
export declare function isSkippableDimension(value: string): value is SkippableDimension;
|
|
139
|
-
/** Reject a dimension `materializeProfile` would not actually skip, rather than ignoring it. */
|
|
140
|
-
export declare function assertSkippableDimensions(skip: readonly string[] | undefined): readonly SkippableDimension[];
|
|
141
|
-
/**
|
|
142
|
-
* Launcher controls an executor can declare it OWNS via `materializeProfile`'s
|
|
143
|
-
* `binds` option.
|
|
144
|
-
*
|
|
145
|
-
* Some harness controls live outside any workspace: opencode's exact
|
|
146
|
-
* system-prompt replacement (`agent.<name>.prompt`) binds to the ONE agent
|
|
147
|
-
* whoever starts the process selects, which a plan-forwarding executor cannot
|
|
148
|
-
* guarantee — so the plan refuses the intent (harnessSystemPromptIntents in
|
|
149
|
-
* @tangle-network/agent-interface answers `replace: false` for opencode).
|
|
150
|
-
*
|
|
151
|
-
* The replacement declarations describe the executor shapes that can reach it;
|
|
152
|
-
* each gets the lowering it can apply. Codex launchers separately declare
|
|
153
|
-
* `codex.developer-instructions` to consume ordinary instructions as additive
|
|
154
|
-
* context; undeclared callers retain workspace files:
|
|
155
|
-
*
|
|
156
|
-
* - `systemPrompt` — the executor applies the plan's launch flags to the
|
|
157
|
-
* spawn it owns, so the plan writes the generated `mode: primary` agent and
|
|
158
|
-
* selects it with `--agent`.
|
|
159
|
-
* - `opencode.agent-prompt` — the executor composes opencode's own config and
|
|
160
|
-
* picks the agent there, reading neither plan files nor plan flags, so the
|
|
161
|
-
* plan hands the text over in {@link WorkspacePlan.systemPromptBinding}
|
|
162
|
-
* instead of writing a workspace agent that would never be selected.
|
|
163
|
-
*
|
|
164
|
-
* The replacement declarations are mutually exclusive: declaring both is a
|
|
165
|
-
* caller bug, not a broader capability.
|
|
166
|
-
*/
|
|
167
|
-
export declare const BINDABLE_LAUNCH_CONTROLS: readonly ["systemPrompt", "codex.developer-instructions", "opencode.agent-prompt"];
|
|
168
|
-
export type BindableLaunchControl = (typeof BINDABLE_LAUNCH_CONTROLS)[number];
|
|
169
|
-
/** Reject a binding declaration this materializer has no lowering for, rather than ignoring it. */
|
|
170
|
-
export declare function assertBindableLaunchControls(binds: readonly string[] | undefined): ReadonlySet<BindableLaunchControl>;
|
|
171
|
-
/** The plan a caller writes into the run cwd, then applies to the spawn. */
|
|
172
|
-
export interface WorkspacePlan {
|
|
173
|
-
harness: HarnessId;
|
|
174
|
-
/** Files to write relative to the run workspace (cwd). */
|
|
175
|
-
files: PlanFile[];
|
|
176
|
-
/** Env vars to set on the spawned process (for harnesses needing them). */
|
|
177
|
-
env: Record<string, WorkspacePlanConfigValue>;
|
|
178
|
-
/** Extra CLI flags to pass (e.g. claude --mcp-config <path>). */
|
|
179
|
-
flags: WorkspacePlanArgument[];
|
|
180
|
-
/**
|
|
181
|
-
* Exact text that REPLACES the harness's own system prompt, for harnesses
|
|
182
|
-
* whose replacement control takes it as a launch argument the executor
|
|
183
|
-
* supplies (claude-code `--system-prompt`, pi `--system-prompt`).
|
|
184
|
-
*
|
|
185
|
-
* Absent does NOT mean "no replacement was requested": a harness whose
|
|
186
|
-
* control reads a file (codex, gemini) carries the replacement in
|
|
187
|
-
* {@link WorkspacePlan.files} plus a flag or env var instead. Present means
|
|
188
|
-
* the executor MUST bind it to that harness's replacement control — never to
|
|
189
|
-
* an additive one, which would leave the built-in prompt in force.
|
|
190
|
-
*/
|
|
191
|
-
systemPrompt?: string;
|
|
192
|
-
/**
|
|
193
|
-
* Text added to the harness context; its own system prompt stays intact.
|
|
194
|
-
*
|
|
195
|
-
* Claude Code and Pi bind their additive system-prompt control. Codex binds
|
|
196
|
-
* ordinary profile instructions to developer_instructions, composed once
|
|
197
|
-
* with host context; this is not a privileged system-prompt append. Authored
|
|
198
|
-
* Codex appendSystemPrompt remains unsupported. Never fold this into an exact
|
|
199
|
-
* system-prompt replacement, which carries the caller's unchanged bytes.
|
|
200
|
-
*/
|
|
201
|
-
appendSystemPrompt?: string;
|
|
202
|
-
/**
|
|
203
|
-
* A prompt intent no workspace file, flag, or env var can execute, addressed
|
|
204
|
-
* to the launcher control that can — see
|
|
205
|
-
* {@link WorkspacePlanSystemPromptBinding}.
|
|
206
|
-
*
|
|
207
|
-
* Present ONLY when the caller declared it owns the named control, so a plan
|
|
208
|
-
* built by a caller that forwards it to someone else's launcher never carries
|
|
209
|
-
* one; that caller gets the intent in {@link WorkspacePlan.unsupported}
|
|
210
|
-
* instead. Whoever reads it must bind it or throw — {@link
|
|
211
|
-
* takeSystemPromptBinding} does both.
|
|
212
|
-
*/
|
|
213
|
-
systemPromptBinding?: WorkspacePlanSystemPromptBinding;
|
|
214
|
-
/** Dimensions requested but with NO cwd path on this harness — fail-closed record. */
|
|
215
|
-
unsupported: Unsupported[];
|
|
216
|
-
/**
|
|
217
|
-
* Prerequisites the workspace files CANNOT establish on their own.
|
|
218
|
-
*
|
|
219
|
-
* A plan is a set of files, an env map, and flags. Some harness capabilities need more than
|
|
220
|
-
* that to actually function: pi's MCP support is not built in, it arrives from an extension
|
|
221
|
-
* that must be installed into the harness's own package directory and permitted to load. No
|
|
222
|
-
* file written into a run workspace can make either true.
|
|
223
|
-
*
|
|
224
|
-
* Writing the config anyway and hoping is the failure this field exists to prevent: the
|
|
225
|
-
* harness starts, silently has no MCP, and the agent runs without the tools it was configured
|
|
226
|
-
* with while nothing reports a problem. So the plan states the requirement and the executor —
|
|
227
|
-
* which knows where its harness is installed and how it spawns — verifies or refuses it.
|
|
228
|
-
*
|
|
229
|
-
* Optional because this is an additive field on a published type: a plan built before it
|
|
230
|
-
* existed, or by a caller that does not construct one, is still a valid plan with no
|
|
231
|
-
* prerequisites. Every plan this package builds sets it.
|
|
232
|
-
*/
|
|
233
|
-
requires?: PlanRequirement[];
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* One prerequisite a {@link WorkspacePlan} depends on but cannot create.
|
|
237
|
-
*
|
|
238
|
-
* Declarative on purpose: this package builds plans and never probes a filesystem, spawns a
|
|
239
|
-
* process, or reaches the network. The executor holds that context and does the checking.
|
|
240
|
-
*/
|
|
241
|
-
export interface PlanRequirement {
|
|
242
|
-
/** The only kind so far: a harness extension/plugin that must be loaded for a dimension to work. */
|
|
243
|
-
kind: "harness-extension";
|
|
244
|
-
/** Dimension that produced the requirement, so a refusal can name what will not work. */
|
|
245
|
-
dimension: Unsupported["dimension"];
|
|
246
|
-
/** Package spec in the harness's own vocabulary, e.g. `npm:pi-mcp-adapter`. */
|
|
247
|
-
id: string;
|
|
248
|
-
/** Why the plan needs it — goes verbatim into the executor's refusal message. */
|
|
249
|
-
reason: string;
|
|
250
|
-
/** The exact command that satisfies it, so a failure is actionable without a doc lookup. */
|
|
251
|
-
remedy: string;
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* Proof of the profile workspace inputs applied before a harness is spawned.
|
|
255
|
-
* `workspacePlanDigest` covers only the {@link WorkspacePlan}; it is not an
|
|
256
|
-
* execution-plan digest and does not attest unrelated files in `workspaceDir`.
|
|
257
|
-
*/
|
|
258
|
-
export interface WorkspacePlanReceipt {
|
|
259
|
-
workspacePlanDigest: string;
|
|
260
|
-
/** Public launch identity only; secret values never enter this receipt. */
|
|
261
|
-
env: Record<string, WorkspacePlanConfigValue>;
|
|
262
|
-
/** Public launch identity only; templates retain opaque secret references. */
|
|
263
|
-
flags: WorkspacePlanArgument[];
|
|
264
|
-
systemPrompt?: string;
|
|
265
|
-
appendSystemPrompt?: string;
|
|
266
|
-
/** The launcher-bound intent, so a receipt says which control owed the work. */
|
|
267
|
-
systemPromptBinding?: WorkspacePlanSystemPromptBinding;
|
|
268
|
-
unsupported: Unsupported[];
|
|
269
|
-
/**
|
|
270
|
-
* Workspace-root paths, for consumers that mount the workspace only.
|
|
271
|
-
* Agent-root files are available in `writtenFiles` and are never encoded as
|
|
272
|
-
* an `agent:` path because that spelling is legal in the workspace root.
|
|
273
|
-
*/
|
|
274
|
-
written: string[];
|
|
275
|
-
/** Every applied file, including its executor-owned root. */
|
|
276
|
-
writtenFiles: WorkspacePlanWrittenFile[];
|
|
277
|
-
}
|
|
278
|
-
/** Private values handed directly to the provider spawn, never to receipts. */
|
|
279
|
-
export interface WorkspacePlanSpawnInputs {
|
|
280
|
-
env: Record<string, string>;
|
|
281
|
-
flags: string[];
|
|
282
|
-
systemPrompt?: string;
|
|
283
|
-
appendSystemPrompt?: string;
|
|
284
|
-
/** Read it with {@link takeSystemPromptBinding}, which refuses a foreign control. */
|
|
285
|
-
systemPromptBinding?: WorkspacePlanSystemPromptBinding;
|
|
286
|
-
/**
|
|
287
|
-
* Absolute dirs of the profile's declared executable `reference/` tools in
|
|
288
|
-
* the immutable revision the launch runs from. The provider puts them on
|
|
289
|
-
* the launch PATH in place of the app's own tool dirs (bindLaunchToolBinDirs),
|
|
290
|
-
* so a profile names its CLI bare.
|
|
291
|
-
*/
|
|
292
|
-
toolBinDirs?: string[];
|
|
293
|
-
}
|
|
294
|
-
/** Result of applying a public plan at the private executor boundary. */
|
|
295
|
-
export interface WorkspacePlanApplication {
|
|
296
|
-
receipt: WorkspacePlanReceipt;
|
|
297
|
-
spawn: WorkspacePlanSpawnInputs;
|
|
298
|
-
/** Resolved generated files intentionally consumed in memory by the runtime. */
|
|
299
|
-
runtimeOnlyFiles: Record<string, string>;
|
|
300
|
-
}
|
|
301
|
-
/** The plan was applied, but one or more private staging files remain. */
|
|
302
|
-
export declare class WorkspacePlanCleanupError extends AggregateError {
|
|
303
|
-
readonly receipt: WorkspacePlanReceipt;
|
|
304
|
-
readonly temporaryPaths: readonly string[];
|
|
305
|
-
constructor(errors: readonly unknown[], receipt: WorkspacePlanReceipt, temporaryPaths: readonly string[]);
|
|
306
|
-
}
|
|
307
|
-
export interface ApplyWorkspacePlanOptions {
|
|
308
|
-
/** Plan files consumed in memory by the runtime and never persisted to cwd. */
|
|
309
|
-
runtimeOnlyFiles?: readonly string[];
|
|
310
|
-
/** Absolute private agent directory required by files whose root is `agent`. */
|
|
311
|
-
agentDir?: string;
|
|
312
|
-
/** Own newly written workspace files as the process that will read them. */
|
|
313
|
-
ownership?: {
|
|
314
|
-
uid: number;
|
|
315
|
-
gid: number;
|
|
316
|
-
};
|
|
317
|
-
/** Existing workspace paths are either exact idempotent inputs or forbidden. */
|
|
318
|
-
existingFiles?: "allow-identical" | "reject";
|
|
319
|
-
/**
|
|
320
|
-
* `workspacePlanDigest` of a plan a prior call already applied into this
|
|
321
|
-
* workspace. When it equals this plan's digest, application changes no file
|
|
322
|
-
* content. It can repair ownership on unchanged materializer-owned files.
|
|
323
|
-
* A file the agent edited or removed stays exactly as the agent left it.
|
|
324
|
-
* Env, flags, prompt intents, and the receipt are still produced. A different
|
|
325
|
-
* digest applies normally, so a changed plan still meets the existing-file
|
|
326
|
-
* refusal.
|
|
327
|
-
*/
|
|
328
|
-
appliedPlanDigest?: string;
|
|
329
|
-
/**
|
|
330
|
-
* Write every JSON file secret slot as an `{env:NAME}` reference (OpenCode
|
|
331
|
-
* config substitution) and never its value, so file bytes and every digest
|
|
332
|
-
* over them stay identical when only a secret's value changes. The value
|
|
333
|
-
* lands here under NAME for the executor alone: never put it in the launch
|
|
334
|
-
* environment, argv or any file the native process reads, because that
|
|
335
|
-
* process hands everything it holds to every tool it runs. A value that
|
|
336
|
-
* could not be substituted safely is refused.
|
|
337
|
-
*/
|
|
338
|
-
secretFileSlotReferences?: Record<string, string>;
|
|
339
|
-
}
|
|
340
|
-
import type { AgentProfileSecretRef } from "@tangle-network/agent-interface";
|
|
341
|
-
import type { HarnessId } from "./harness.js";
|
package/dist/plan-types.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The subset of {@link BINDABLE_LAUNCH_CONTROLS} the plan HANDS OVER rather than
|
|
3
|
-
* executes: controls a caller reaches only by composing the harness's own
|
|
4
|
-
* configuration, so no file, flag or env var the plan writes can touch them.
|
|
5
|
-
*
|
|
6
|
-
* - `opencode.agent-prompt` — opencode's `agent.<name>.prompt` config field,
|
|
7
|
-
* the one control that replaces its built-in provider prompt. It binds to a
|
|
8
|
-
* SINGLE agent, and the agent is chosen at launch. A caller that builds
|
|
9
|
-
* opencode's config itself and picks the agent there reads neither
|
|
10
|
-
* `plan.files` nor `plan.flags`, so for that one the plan names the control
|
|
11
|
-
* and hands over the text in {@link WorkspacePlan.systemPromptBinding}.
|
|
12
|
-
*
|
|
13
|
-
* Every other bindable control names a capability the plan still lowers itself
|
|
14
|
-
* once the caller has declared the plan's launch inputs really reach the spawn.
|
|
15
|
-
*/
|
|
16
|
-
export const EXECUTOR_SYSTEM_PROMPT_BINDINGS = [
|
|
17
|
-
"opencode.agent-prompt",
|
|
18
|
-
];
|
|
19
|
-
/**
|
|
20
|
-
* The dimensions `materializeProfile`'s `skip` option honors.
|
|
21
|
-
*
|
|
22
|
-
* Every other dimension is materialized unconditionally: generated plan files are pushed through
|
|
23
|
-
* a single site that carries no dimension tag, so there is nothing to gate them on. Naming the
|
|
24
|
-
* honored set keeps `skip: ["hooks"]` a loud rejection instead of a silent no-op.
|
|
25
|
-
*/
|
|
26
|
-
export const SKIPPABLE_DIMENSIONS = [
|
|
27
|
-
"mcp",
|
|
28
|
-
"extensions",
|
|
29
|
-
];
|
|
30
|
-
const SKIPPABLE_DIMENSION_SET = new Set(SKIPPABLE_DIMENSIONS);
|
|
31
|
-
export function isSkippableDimension(value) {
|
|
32
|
-
return SKIPPABLE_DIMENSION_SET.has(value);
|
|
33
|
-
}
|
|
34
|
-
/** Reject a dimension `materializeProfile` would not actually skip, rather than ignoring it. */
|
|
35
|
-
export function assertSkippableDimensions(skip) {
|
|
36
|
-
if (!skip)
|
|
37
|
-
return [];
|
|
38
|
-
const unsupportedSkips = skip.filter((dimension) => !isSkippableDimension(dimension));
|
|
39
|
-
if (unsupportedSkips.length > 0) {
|
|
40
|
-
throw new Error(`materializeProfile: cannot skip ${unsupportedSkips.join(", ")}. ` +
|
|
41
|
-
`Skippable dimensions are: ${SKIPPABLE_DIMENSIONS.join(", ")}.`);
|
|
42
|
-
}
|
|
43
|
-
return skip;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Launcher controls an executor can declare it OWNS via `materializeProfile`'s
|
|
47
|
-
* `binds` option.
|
|
48
|
-
*
|
|
49
|
-
* Some harness controls live outside any workspace: opencode's exact
|
|
50
|
-
* system-prompt replacement (`agent.<name>.prompt`) binds to the ONE agent
|
|
51
|
-
* whoever starts the process selects, which a plan-forwarding executor cannot
|
|
52
|
-
* guarantee — so the plan refuses the intent (harnessSystemPromptIntents in
|
|
53
|
-
* @tangle-network/agent-interface answers `replace: false` for opencode).
|
|
54
|
-
*
|
|
55
|
-
* The replacement declarations describe the executor shapes that can reach it;
|
|
56
|
-
* each gets the lowering it can apply. Codex launchers separately declare
|
|
57
|
-
* `codex.developer-instructions` to consume ordinary instructions as additive
|
|
58
|
-
* context; undeclared callers retain workspace files:
|
|
59
|
-
*
|
|
60
|
-
* - `systemPrompt` — the executor applies the plan's launch flags to the
|
|
61
|
-
* spawn it owns, so the plan writes the generated `mode: primary` agent and
|
|
62
|
-
* selects it with `--agent`.
|
|
63
|
-
* - `opencode.agent-prompt` — the executor composes opencode's own config and
|
|
64
|
-
* picks the agent there, reading neither plan files nor plan flags, so the
|
|
65
|
-
* plan hands the text over in {@link WorkspacePlan.systemPromptBinding}
|
|
66
|
-
* instead of writing a workspace agent that would never be selected.
|
|
67
|
-
*
|
|
68
|
-
* The replacement declarations are mutually exclusive: declaring both is a
|
|
69
|
-
* caller bug, not a broader capability.
|
|
70
|
-
*/
|
|
71
|
-
export const BINDABLE_LAUNCH_CONTROLS = [
|
|
72
|
-
"systemPrompt",
|
|
73
|
-
"codex.developer-instructions",
|
|
74
|
-
...EXECUTOR_SYSTEM_PROMPT_BINDINGS,
|
|
75
|
-
];
|
|
76
|
-
const BINDABLE_LAUNCH_CONTROL_SET = new Set(BINDABLE_LAUNCH_CONTROLS);
|
|
77
|
-
/** Reject a binding declaration this materializer has no lowering for, rather than ignoring it. */
|
|
78
|
-
export function assertBindableLaunchControls(binds) {
|
|
79
|
-
if (!binds)
|
|
80
|
-
return new Set();
|
|
81
|
-
const unknown = binds.filter((control) => !BINDABLE_LAUNCH_CONTROL_SET.has(control));
|
|
82
|
-
if (unknown.length > 0) {
|
|
83
|
-
throw new Error(`materializeProfile: cannot bind ${unknown.join(", ")}. ` +
|
|
84
|
-
`Bindable launch controls are: ${BINDABLE_LAUNCH_CONTROLS.join(", ")}.`);
|
|
85
|
-
}
|
|
86
|
-
const declared = new Set(binds);
|
|
87
|
-
const handedOver = [...EXECUTOR_SYSTEM_PROMPT_BINDINGS].filter((control) => declared.has(control));
|
|
88
|
-
if (declared.has("systemPrompt") && handedOver.length > 0) {
|
|
89
|
-
throw new Error(`materializeProfile: cannot bind systemPrompt together with ${handedOver.join(", ")}. ` +
|
|
90
|
-
"The first says the plan's launch flags reach the spawn; the second says " +
|
|
91
|
-
"the caller composes the harness config itself and reads neither.");
|
|
92
|
-
}
|
|
93
|
-
return declared;
|
|
94
|
-
}
|
|
95
|
-
/** The plan was applied, but one or more private staging files remain. */
|
|
96
|
-
export class WorkspacePlanCleanupError extends AggregateError {
|
|
97
|
-
receipt;
|
|
98
|
-
temporaryPaths;
|
|
99
|
-
constructor(errors, receipt, temporaryPaths) {
|
|
100
|
-
super(errors, "Applied workspace plan but failed to remove temporary files");
|
|
101
|
-
this.name = "WorkspacePlanCleanupError";
|
|
102
|
-
this.receipt = receipt;
|
|
103
|
-
this.temporaryPaths = Object.freeze([...temporaryPaths]);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
export declare function writePrimeAgentFile(path: string, data: string, mode?: number): void;
|
|
2
|
-
/**
|
|
3
|
-
* File access on a prime agent dir. The default reads and writes the local
|
|
4
|
-
* filesystem as the calling process. An executor whose agent dir belongs to
|
|
5
|
-
* another user (a root sidecar that demotes prime-agent) passes reads it took
|
|
6
|
-
* as that user and replays the writes as that user, so it never touches the
|
|
7
|
-
* agent's files with its own rights.
|
|
8
|
-
*/
|
|
9
|
-
export interface PrimeAgentDirIo {
|
|
10
|
-
/** The file's text, or undefined when it does not exist. */
|
|
11
|
-
read(path: string): string | undefined;
|
|
12
|
-
/** Replace the whole file: atomic and owner-only. */
|
|
13
|
-
write(path: string, data: string): void;
|
|
14
|
-
}
|
|
15
|
-
/** The fork's continual-harness store, the only agent-dir file a materialization reads. */
|
|
16
|
-
export declare function primeHarnessStatePath(agentDir: string): string;
|
|
17
|
-
export interface PrimeMaterializeOptions {
|
|
18
|
-
/**
|
|
19
|
-
* Where the FLAG-NAMED files go — the prompt files and the skills root.
|
|
20
|
-
* Defaults to `agentDir`. An executor that does not own the agent dir points
|
|
21
|
-
* this at a per-run directory of its own, so binding a profile's prompts and
|
|
22
|
-
* skills writes nothing into a dir it must not modify. The context file and
|
|
23
|
-
* the harness store have no flag and always land in `agentDir`; refuse those
|
|
24
|
-
* with {@link primeProfileNeedsAgentDir} instead.
|
|
25
|
-
*/
|
|
26
|
-
flagFileRoot?: string;
|
|
27
|
-
/**
|
|
28
|
-
* Reports state the executor should see but that does not fail the run
|
|
29
|
-
* (currently: adopting entries a pre-shared executor left behind).
|
|
30
|
-
*/
|
|
31
|
-
warn?: (msg: string, meta?: Record<string, unknown>) => void;
|
|
32
|
-
/** Agent-dir file access; the local filesystem when omitted. */
|
|
33
|
-
io?: PrimeAgentDirIo;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Materialize the validated controls and return the extra spawn args that bind
|
|
37
|
-
* them. Runs before every spawn (same place models.json is materialized), so a
|
|
38
|
-
* continual agent dir is re-pinned to the current profile on each fresh prime
|
|
39
|
-
* process.
|
|
40
|
-
*/
|
|
41
|
-
export declare function materializePrimeProfileControls(agentDir: string, controls: PrimeProfileControls, options?: PrimeMaterializeOptions): string[];
|
|
42
|
-
/**
|
|
43
|
-
* Remove the files a PREVIOUS materialization of this lowering wrote, so a
|
|
44
|
-
* profile that shrank cannot leave a stale instruction file or skill behind for
|
|
45
|
-
* the next run against the same dirs.
|
|
46
|
-
*
|
|
47
|
-
* Only the paths this lowering NAMES are removed. There is deliberately no
|
|
48
|
-
* manifest: a manifest would live where the agent can write it, and reading a
|
|
49
|
-
* delete list out of agent-writable state turns pruning into an arbitrary-path
|
|
50
|
-
* delete.
|
|
51
|
-
*/
|
|
52
|
-
export declare function prunePrimeProfileMaterial(agentDir: string, options?: Pick<PrimeMaterializeOptions, "flagFileRoot">): void;
|
|
53
|
-
/**
|
|
54
|
-
* Upsert profile subagent specs into the fork's global continual-harness
|
|
55
|
-
* store and remove profile-sourced entries the current profile no longer
|
|
56
|
-
* declares. Agent-written entries (`source: "agent"`) — and every top-level
|
|
57
|
-
* key this lowering does not manage — are preserved untouched.
|
|
58
|
-
*
|
|
59
|
-
* A store that exists but no longer parses raises
|
|
60
|
-
* {@link PrimeHarnessStateError}: the file is the agent's own self-modification
|
|
61
|
-
* state, and overwriting it destroys what the run was supposed to observe.
|
|
62
|
-
*/
|
|
63
|
-
export declare function seedPrimeProfileSubagents(agentDir: string, subagents: PrimeProfileSubagent[], warn?: (msg: string, meta?: Record<string, unknown>) => void, io?: PrimeAgentDirIo): void;
|
|
64
|
-
import type { PrimeProfileControls, PrimeProfileSubagent } from "./prime-profile.js";
|