@tangle-network/agent-profile-materialize 0.15.2 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/candidate-types.d.ts +32 -0
  2. package/dist/candidate-types.js +1 -0
  3. package/dist/candidate.d.ts +9 -0
  4. package/dist/candidate.js +279 -0
  5. package/dist/commands.d.ts +2 -0
  6. package/dist/commands.js +32 -0
  7. package/dist/control-maps.d.ts +34 -0
  8. package/dist/control-maps.js +185 -0
  9. package/dist/execution-controls.d.ts +5 -0
  10. package/dist/execution-controls.js +186 -0
  11. package/dist/harness.d.ts +81 -0
  12. package/dist/harness.js +167 -0
  13. package/dist/hooks.d.ts +6 -0
  14. package/dist/hooks.js +261 -0
  15. package/dist/index.d.ts +23 -623
  16. package/dist/index.js +14 -3733
  17. package/dist/mcp.d.ts +22 -0
  18. package/dist/mcp.js +244 -0
  19. package/dist/plan-application.d.ts +10 -0
  20. package/dist/plan-application.js +152 -0
  21. package/dist/plan-digest.d.ts +18 -0
  22. package/dist/plan-digest.js +90 -0
  23. package/dist/plan-json.d.ts +18 -0
  24. package/dist/plan-json.js +91 -0
  25. package/dist/plan-normalize.d.ts +13 -0
  26. package/dist/plan-normalize.js +156 -0
  27. package/dist/plan-prompt.d.ts +38 -0
  28. package/dist/plan-prompt.js +49 -0
  29. package/dist/plan-support.d.ts +9 -0
  30. package/dist/plan-support.js +22 -0
  31. package/dist/plan-types.d.ts +294 -0
  32. package/dist/plan-types.js +106 -0
  33. package/dist/prime-agent-dir.d.ts +47 -0
  34. package/dist/prime-agent-dir.js +164 -0
  35. package/dist/prime-profile.d.ts +88 -0
  36. package/dist/prime-profile.js +284 -0
  37. package/dist/profile-materializer.d.ts +12 -0
  38. package/dist/profile-materializer.js +59 -0
  39. package/dist/profile-plan.d.ts +14 -0
  40. package/dist/profile-plan.js +86 -0
  41. package/dist/profile-prompt.d.ts +4 -0
  42. package/dist/profile-prompt.js +105 -0
  43. package/dist/profile-support.d.ts +8 -0
  44. package/dist/profile-support.js +6 -0
  45. package/dist/resource-lowering.d.ts +7 -0
  46. package/dist/resource-lowering.js +103 -0
  47. package/dist/resource-resolution.d.ts +27 -0
  48. package/dist/resource-resolution.js +241 -0
  49. package/dist/subagents.d.ts +6 -0
  50. package/dist/subagents.js +133 -0
  51. package/dist/workspace-apply.d.ts +12 -0
  52. package/dist/workspace-apply.js +334 -0
  53. package/dist/workspace-files.d.ts +8 -0
  54. package/dist/workspace-files.js +46 -0
  55. package/package.json +3 -3
@@ -0,0 +1,106 @@
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
+ const EXECUTOR_SYSTEM_PROMPT_BINDING_SET = new Set(EXECUTOR_SYSTEM_PROMPT_BINDINGS);
20
+ export function isExecutorSystemPromptBinding(value) {
21
+ return EXECUTOR_SYSTEM_PROMPT_BINDING_SET.has(value);
22
+ }
23
+ /**
24
+ * The dimensions `materializeProfile`'s `skip` option honors.
25
+ *
26
+ * Every other dimension is materialized unconditionally: generated plan files are pushed through
27
+ * a single site that carries no dimension tag, so there is nothing to gate them on. Naming the
28
+ * honored set keeps `skip: ["hooks"]` a loud rejection instead of a silent no-op.
29
+ */
30
+ export const SKIPPABLE_DIMENSIONS = [
31
+ "mcp",
32
+ "extensions",
33
+ ];
34
+ const SKIPPABLE_DIMENSION_SET = new Set(SKIPPABLE_DIMENSIONS);
35
+ export function isSkippableDimension(value) {
36
+ return SKIPPABLE_DIMENSION_SET.has(value);
37
+ }
38
+ /** Reject a dimension `materializeProfile` would not actually skip, rather than ignoring it. */
39
+ export function assertSkippableDimensions(skip) {
40
+ if (!skip)
41
+ return [];
42
+ const unsupportedSkips = skip.filter((dimension) => !isSkippableDimension(dimension));
43
+ if (unsupportedSkips.length > 0) {
44
+ throw new Error(`materializeProfile: cannot skip ${unsupportedSkips.join(", ")}. ` +
45
+ `Skippable dimensions are: ${SKIPPABLE_DIMENSIONS.join(", ")}.`);
46
+ }
47
+ return skip;
48
+ }
49
+ /**
50
+ * Launcher controls an executor can declare it OWNS via `materializeProfile`'s
51
+ * `binds` option.
52
+ *
53
+ * Some harness controls live outside any workspace: opencode's exact
54
+ * system-prompt replacement (`agent.<name>.prompt`) binds to the ONE agent
55
+ * whoever starts the process selects, which a plan-forwarding executor cannot
56
+ * guarantee — so the plan refuses the intent (harnessSystemPromptIntents in
57
+ * @tangle-network/agent-interface answers `replace: false` for opencode).
58
+ *
59
+ * The two declarations describe the two executor shapes that CAN reach it, and
60
+ * each gets the lowering it can actually apply:
61
+ *
62
+ * - `systemPrompt` — the executor applies the plan's launch flags to the
63
+ * spawn it owns, so the plan writes the generated `mode: primary` agent and
64
+ * selects it with `--agent`.
65
+ * - `opencode.agent-prompt` — the executor composes opencode's own config and
66
+ * picks the agent there, reading neither plan files nor plan flags, so the
67
+ * plan hands the text over in {@link WorkspacePlan.systemPromptBinding}
68
+ * instead of writing a workspace agent that would never be selected.
69
+ *
70
+ * They are mutually exclusive claims about the same caller: declaring both is a
71
+ * caller bug, not a broader capability.
72
+ */
73
+ export const BINDABLE_LAUNCH_CONTROLS = [
74
+ "systemPrompt",
75
+ ...EXECUTOR_SYSTEM_PROMPT_BINDINGS,
76
+ ];
77
+ const BINDABLE_LAUNCH_CONTROL_SET = new Set(BINDABLE_LAUNCH_CONTROLS);
78
+ /** Reject a binding declaration this materializer has no lowering for, rather than ignoring it. */
79
+ export function assertBindableLaunchControls(binds) {
80
+ if (!binds)
81
+ return new Set();
82
+ const unknown = binds.filter((control) => !BINDABLE_LAUNCH_CONTROL_SET.has(control));
83
+ if (unknown.length > 0) {
84
+ throw new Error(`materializeProfile: cannot bind ${unknown.join(", ")}. ` +
85
+ `Bindable launch controls are: ${BINDABLE_LAUNCH_CONTROLS.join(", ")}.`);
86
+ }
87
+ const declared = new Set(binds);
88
+ const handedOver = [...EXECUTOR_SYSTEM_PROMPT_BINDINGS].filter((control) => declared.has(control));
89
+ if (declared.has("systemPrompt") && handedOver.length > 0) {
90
+ throw new Error(`materializeProfile: cannot bind systemPrompt together with ${handedOver.join(", ")}. ` +
91
+ "The first says the plan's launch flags reach the spawn; the second says " +
92
+ "the caller composes the harness config itself and reads neither.");
93
+ }
94
+ return declared;
95
+ }
96
+ /** The plan was applied, but one or more private staging files remain. */
97
+ export class WorkspacePlanCleanupError extends AggregateError {
98
+ receipt;
99
+ temporaryPaths;
100
+ constructor(errors, receipt, temporaryPaths) {
101
+ super(errors, "Applied workspace plan but failed to remove temporary files");
102
+ this.name = "WorkspacePlanCleanupError";
103
+ this.receipt = receipt;
104
+ this.temporaryPaths = Object.freeze([...temporaryPaths]);
105
+ }
106
+ }
@@ -0,0 +1,47 @@
1
+ export declare function writePrimeAgentFile(path: string, data: string, mode?: number): void;
2
+ export interface PrimeMaterializeOptions {
3
+ /**
4
+ * Where the FLAG-NAMED files go — the prompt files and the skills root.
5
+ * Defaults to `agentDir`. An executor that does not own the agent dir points
6
+ * this at a per-run directory of its own, so binding a profile's prompts and
7
+ * skills writes nothing into a dir it must not modify. The context file and
8
+ * the harness store have no flag and always land in `agentDir`; refuse those
9
+ * with {@link primeProfileNeedsAgentDir} instead.
10
+ */
11
+ flagFileRoot?: string;
12
+ /**
13
+ * Reports state the executor should see but that does not fail the run
14
+ * (currently: adopting entries a pre-shared executor left behind).
15
+ */
16
+ warn?: (msg: string, meta?: Record<string, unknown>) => void;
17
+ }
18
+ /**
19
+ * Materialize the validated controls and return the extra spawn args that bind
20
+ * them. Runs before every spawn (same place models.json is materialized), so a
21
+ * continual agent dir is re-pinned to the current profile on each fresh prime
22
+ * process.
23
+ */
24
+ export declare function materializePrimeProfileControls(agentDir: string, controls: PrimeProfileControls, options?: PrimeMaterializeOptions): string[];
25
+ /**
26
+ * Remove the files a PREVIOUS materialization of this lowering wrote, so a
27
+ * profile that shrank cannot leave a stale instruction file or skill behind for
28
+ * the next run against the same dirs.
29
+ *
30
+ * Only the paths this lowering NAMES are removed. There is deliberately no
31
+ * manifest: a manifest would live where the agent can write it, and reading a
32
+ * delete list out of agent-writable state turns pruning into an arbitrary-path
33
+ * delete.
34
+ */
35
+ export declare function prunePrimeProfileMaterial(agentDir: string, options?: Pick<PrimeMaterializeOptions, "flagFileRoot">): void;
36
+ /**
37
+ * Upsert profile subagent specs into the fork's global continual-harness
38
+ * store and remove profile-sourced entries the current profile no longer
39
+ * declares. Agent-written entries (`source: "agent"`) — and every top-level
40
+ * key this lowering does not manage — are preserved untouched.
41
+ *
42
+ * A store that exists but no longer parses raises
43
+ * {@link PrimeHarnessStateError}: the file is the agent's own self-modification
44
+ * state, and overwriting it destroys what the run was supposed to observe.
45
+ */
46
+ export declare function seedPrimeProfileSubagents(agentDir: string, subagents: PrimeProfileSubagent[], warn?: (msg: string, meta?: Record<string, unknown>) => void): void;
47
+ import type { PrimeProfileControls, PrimeProfileSubagent } from "./prime-profile.js";
@@ -0,0 +1,164 @@
1
+ export function writePrimeAgentFile(path, data, mode = 0o600) {
2
+ mkdirSync(dirname(path), { recursive: true });
3
+ const temp = `${path}.${process.pid}.${randomUUID()}.tmp`;
4
+ writeFileSync(temp, data, { mode });
5
+ renameSync(temp, path);
6
+ }
7
+ /**
8
+ * Materialize the validated controls and return the extra spawn args that bind
9
+ * them. Runs before every spawn (same place models.json is materialized), so a
10
+ * continual agent dir is re-pinned to the current profile on each fresh prime
11
+ * process.
12
+ */
13
+ export function materializePrimeProfileControls(agentDir, controls, options = {}) {
14
+ const { flagFileRoot = agentDir, warn } = options;
15
+ const args = [];
16
+ const profileDir = join(flagFileRoot, PRIME_PROFILE_DIR_NAME);
17
+ if (controls.systemPrompt !== undefined) {
18
+ const promptPath = join(profileDir, PRIME_SYSTEM_PROMPT_FILE);
19
+ writePrimeAgentFile(promptPath, controls.systemPrompt);
20
+ args.push("--system-prompt", promptPath);
21
+ }
22
+ if (controls.appendSystemPrompt !== undefined) {
23
+ const appendPath = join(profileDir, PRIME_APPEND_SYSTEM_PROMPT_FILE);
24
+ writePrimeAgentFile(appendPath, controls.appendSystemPrompt);
25
+ args.push("--append-system-prompt", appendPath);
26
+ }
27
+ if (controls.instructions !== undefined) {
28
+ writePrimeAgentFile(join(agentDir, PRIME_CONTEXT_FILE), `${controls.instructions}\n`);
29
+ }
30
+ if (controls.skills.length > 0) {
31
+ const skillsRoot = join(profileDir, PRIME_SKILLS_DIR_NAME);
32
+ for (const skill of controls.skills) {
33
+ writePrimeAgentFile(join(skillsRoot, skill.name, "SKILL.md"), normalizeSkillMd(skill.name, skill.content));
34
+ }
35
+ args.push("--skill", skillsRoot);
36
+ }
37
+ seedPrimeProfileSubagents(agentDir, controls.subagents, warn);
38
+ return args;
39
+ }
40
+ /**
41
+ * Remove the files a PREVIOUS materialization of this lowering wrote, so a
42
+ * profile that shrank cannot leave a stale instruction file or skill behind for
43
+ * the next run against the same dirs.
44
+ *
45
+ * Only the paths this lowering NAMES are removed. There is deliberately no
46
+ * manifest: a manifest would live where the agent can write it, and reading a
47
+ * delete list out of agent-writable state turns pruning into an arbitrary-path
48
+ * delete.
49
+ */
50
+ export function prunePrimeProfileMaterial(agentDir, options = {}) {
51
+ const { flagFileRoot = agentDir } = options;
52
+ rmSync(join(flagFileRoot, PRIME_PROFILE_DIR_NAME), {
53
+ recursive: true,
54
+ force: true,
55
+ });
56
+ rmSync(join(agentDir, PRIME_CONTEXT_FILE), { force: true });
57
+ }
58
+ /**
59
+ * Upsert profile subagent specs into the fork's global continual-harness
60
+ * store and remove profile-sourced entries the current profile no longer
61
+ * declares. Agent-written entries (`source: "agent"`) — and every top-level
62
+ * key this lowering does not manage — are preserved untouched.
63
+ *
64
+ * A store that exists but no longer parses raises
65
+ * {@link PrimeHarnessStateError}: the file is the agent's own self-modification
66
+ * state, and overwriting it destroys what the run was supposed to observe.
67
+ */
68
+ export function seedPrimeProfileSubagents(agentDir, subagents, warn) {
69
+ const statePath = join(agentDir, PRIME_HARNESS_DIR_NAME, PRIME_HARNESS_STATE_FILE);
70
+ let state = {};
71
+ if (existsSync(statePath)) {
72
+ let parsed;
73
+ try {
74
+ parsed = JSON.parse(readFileSync(statePath, "utf8"));
75
+ }
76
+ catch (err) {
77
+ throw new PrimeHarnessStateError(statePath, err instanceof Error ? err.message : String(err));
78
+ }
79
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
80
+ throw new PrimeHarnessStateError(statePath, "the store is not a JSON object");
81
+ }
82
+ state = parsed;
83
+ }
84
+ else if (subagents.length === 0) {
85
+ // Nothing to pin and nothing stale to remove.
86
+ return;
87
+ }
88
+ const rawEntries = state.entries;
89
+ const entries = rawEntries && typeof rawEntries === "object" && !Array.isArray(rawEntries)
90
+ ? rawEntries
91
+ : {};
92
+ for (const kind of PRIME_HARNESS_KINDS) {
93
+ const records = entries[kind];
94
+ if (!records || typeof records !== "object" || Array.isArray(records)) {
95
+ entries[kind] = {};
96
+ }
97
+ }
98
+ const existing = entries.subagent;
99
+ const desiredIds = new Set(subagents.map((s) => primeSubagentEntryId(s.name)));
100
+ let changed = false;
101
+ for (const [id, entry] of Object.entries(existing)) {
102
+ const source = entry?.source;
103
+ const isLegacy = typeof source === "string" &&
104
+ PRIME_LEGACY_PROFILE_ENTRY_SOURCES.includes(source);
105
+ if (isLegacy) {
106
+ warn?.("prime: adopting a subagent entry left by a pre-shared executor", {
107
+ statePath,
108
+ id,
109
+ source,
110
+ });
111
+ }
112
+ if ((source === PRIME_PROFILE_ENTRY_SOURCE || isLegacy) &&
113
+ !desiredIds.has(id)) {
114
+ delete existing[id];
115
+ changed = true;
116
+ }
117
+ }
118
+ const now = new Date().toISOString();
119
+ for (const spec of subagents) {
120
+ const id = primeSubagentEntryId(spec.name);
121
+ const content = [spec.description?.trim(), spec.prompt?.trim()]
122
+ .filter((part) => !!part)
123
+ .join("\n\n");
124
+ const previous = existing[id];
125
+ if (previous &&
126
+ previous.source === PRIME_PROFILE_ENTRY_SOURCE &&
127
+ previous.title === spec.name &&
128
+ previous.content === content) {
129
+ continue;
130
+ }
131
+ existing[id] = {
132
+ id,
133
+ kind: "subagent",
134
+ title: spec.name,
135
+ content,
136
+ path: PRIME_PROFILE_ENTRY_SOURCE,
137
+ scope: "global",
138
+ reference: {},
139
+ arguments: {},
140
+ metadata: spec.metadata ?? {},
141
+ source: PRIME_PROFILE_ENTRY_SOURCE,
142
+ created_at: previous?.created_at ?? now,
143
+ updated_at: now,
144
+ version: previous && typeof previous.version === "number"
145
+ ? previous.version + 1
146
+ : 1,
147
+ };
148
+ changed = true;
149
+ }
150
+ if (!changed)
151
+ return;
152
+ writePrimeAgentFile(statePath, `${JSON.stringify({
153
+ ...state,
154
+ schema: typeof state.schema === "number" ? state.schema : 1,
155
+ entries,
156
+ refinements: Array.isArray(state.refinements) ? state.refinements : [],
157
+ }, null, 2)}\n`);
158
+ }
159
+ import { randomUUID } from "node:crypto";
160
+ import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
161
+ import { dirname, join } from "node:path";
162
+ import { PrimeHarnessStateError } from "./prime-fork.js";
163
+ import { PRIME_APPEND_SYSTEM_PROMPT_FILE, PRIME_CONTEXT_FILE, PRIME_HARNESS_DIR_NAME, PRIME_HARNESS_KINDS, PRIME_HARNESS_STATE_FILE, PRIME_LEGACY_PROFILE_ENTRY_SOURCES, PRIME_PROFILE_DIR_NAME, PRIME_PROFILE_ENTRY_SOURCE, PRIME_SKILLS_DIR_NAME, PRIME_SYSTEM_PROMPT_FILE, primeSubagentEntryId, } from "./prime-profile.js";
164
+ import { normalizeSkillMd } from "./resource-resolution.js";
@@ -0,0 +1,88 @@
1
+ export declare const PRIME_PROFILE_DIR_NAME = "profile";
2
+ export declare const PRIME_SKILLS_DIR_NAME = "skills";
3
+ export declare const PRIME_SYSTEM_PROMPT_FILE = "system-prompt.md";
4
+ export declare const PRIME_APPEND_SYSTEM_PROMPT_FILE = "append-system-prompt.md";
5
+ /** Agent-dir global context file the fork reads (resource-loader.ts:59,86). */
6
+ export declare const PRIME_CONTEXT_FILE = "AGENTS.md";
7
+ /** Fork continual-harness store location under the agent dir (refinement.ts:269-279). */
8
+ export declare const PRIME_HARNESS_DIR_NAME = "harness";
9
+ export declare const PRIME_HARNESS_STATE_FILE = "harness_state.json";
10
+ export declare const PRIME_HARNESS_KINDS: readonly ["prompt", "memory", "skill", "subagent"];
11
+ /**
12
+ * Provenance marker for entries pinned from the profile. Stale removal keys on
13
+ * it, so agent-written (`source: "agent"`) and user-written entries are never
14
+ * touched.
15
+ */
16
+ export declare const PRIME_PROFILE_ENTRY_SOURCE = "profile";
17
+ /**
18
+ * Provenance markers written by executors that predate this shared lowering.
19
+ *
20
+ * Pruning keys on the source tag, so an executor that switches to the shared
21
+ * implementation would otherwise leave its own earlier entries behind forever:
22
+ * they match no current profile and no current source, and the model's
23
+ * spawnable roster silently accumulates duplicates of every subagent. They are
24
+ * adopted (pruned or replaced) on the first shared run instead.
25
+ */
26
+ export declare const PRIME_LEGACY_PROFILE_ENTRY_SOURCES: readonly string[];
27
+ export interface PrimeProfileSkill {
28
+ name: string;
29
+ content: string;
30
+ }
31
+ export interface PrimeProfileSubagent {
32
+ name: string;
33
+ description?: string;
34
+ prompt?: string;
35
+ metadata?: Record<string, unknown>;
36
+ }
37
+ /** Validated, materialization-ready view of the profile controls prime applies. */
38
+ export interface PrimeProfileControls {
39
+ systemPrompt?: string;
40
+ appendSystemPrompt?: string;
41
+ /** Composed caller instructions, lowered to the agent dir's AGENTS.md. */
42
+ instructions?: string;
43
+ skills: PrimeProfileSkill[];
44
+ subagents: PrimeProfileSubagent[];
45
+ }
46
+ /** True when the controls materialize anything at all. */
47
+ export declare function hasPrimeProfileMaterial(controls: PrimeProfileControls): boolean;
48
+ /**
49
+ * True when the controls must WRITE INTO the agent dir itself.
50
+ *
51
+ * Prompt files and skill dirs are named by a flag, so they can live anywhere
52
+ * the agent can read (`--system-prompt` / `--append-system-prompt` resolve a
53
+ * path when it exists, fork resource-loader.ts:41-56; `--skill` takes an
54
+ * arbitrary dir, :437-442). The context file and the continual-harness store
55
+ * are located BY the agent dir and have no flag, so they cannot move.
56
+ *
57
+ * An executor pointed at an agent dir it does not own (an operator's shared
58
+ * dir) uses this to refuse exactly the controls it would have to write there,
59
+ * while still binding the ones it can materialize elsewhere.
60
+ */
61
+ export declare function primeProfileNeedsAgentDir(controls: PrimeProfileControls): boolean;
62
+ /**
63
+ * Validate and extract the profile controls the prime agent-dir lowering
64
+ * materializes. Throws {@link PrimeProfileError} on any control (or control
65
+ * facet) the fork has no verified read path for — partial acceptance would
66
+ * silently drop the rest.
67
+ */
68
+ export declare function readPrimeProfileControls(profile: AgentProfile | undefined): PrimeProfileControls;
69
+ /**
70
+ * Refuse a run whose selected model disagrees with the profile's own.
71
+ *
72
+ * One authority per run: a profile names the model it was written and scored
73
+ * against, so running it on a different one silently scores a different agent.
74
+ * Both sides go through {@link modelIdsMatch}, so the qualification level a
75
+ * caller happened to use is not a conflict.
76
+ *
77
+ * `provider` is the executor's PROVIDER SELECTION, and is compared only when
78
+ * the executor's provider is part of model identity. An executor whose
79
+ * provider key is merely a namespace inside the agent dir passes it as
80
+ * undefined and gets the model-name comparison alone.
81
+ */
82
+ export declare function assertPrimeModelAgreement(profile: AgentProfile | undefined, selected: {
83
+ provider?: string;
84
+ model: string;
85
+ }): void;
86
+ /** Deterministic harness-state entry id for a profile subagent name. */
87
+ export declare function primeSubagentEntryId(name: string): string;
88
+ import type { AgentProfile } from "@tangle-network/agent-interface";