@tangle-network/agent-profile-materialize 1.1.7 → 1.1.9

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 (95) hide show
  1. package/dist/index.d.ts +1226 -29
  2. package/dist/index.js +4987 -23
  3. package/package.json +7 -5
  4. package/dist/candidate-types.d.ts +0 -36
  5. package/dist/candidate-types.js +0 -1
  6. package/dist/candidate.d.ts +0 -9
  7. package/dist/candidate.js +0 -283
  8. package/dist/commands.d.ts +0 -2
  9. package/dist/commands.js +0 -32
  10. package/dist/control-maps.d.ts +0 -58
  11. package/dist/control-maps.js +0 -277
  12. package/dist/execution-controls.d.ts +0 -5
  13. package/dist/execution-controls.js +0 -199
  14. package/dist/harness-prompt.d.ts +0 -22
  15. package/dist/harness-prompt.js +0 -64
  16. package/dist/harness.d.ts +0 -131
  17. package/dist/harness.js +0 -416
  18. package/dist/hooks.d.ts +0 -6
  19. package/dist/hooks.js +0 -250
  20. package/dist/managed-workspace-bind.d.ts +0 -4
  21. package/dist/managed-workspace-bind.js +0 -106
  22. package/dist/managed-workspace-stage.d.ts +0 -25
  23. package/dist/managed-workspace-stage.js +0 -199
  24. package/dist/managed-workspace-types.d.ts +0 -38
  25. package/dist/managed-workspace-types.js +0 -1
  26. package/dist/managed-workspace.d.ts +0 -31
  27. package/dist/managed-workspace.js +0 -271
  28. package/dist/mcp-config-ownership.d.ts +0 -13
  29. package/dist/mcp-config-ownership.js +0 -79
  30. package/dist/mcp-opencode.d.ts +0 -25
  31. package/dist/mcp-opencode.js +0 -52
  32. package/dist/mcp-timeouts.d.ts +0 -7
  33. package/dist/mcp-timeouts.js +0 -48
  34. package/dist/mcp.d.ts +0 -4
  35. package/dist/mcp.js +0 -246
  36. package/dist/model-id.d.ts +0 -55
  37. package/dist/model-id.js +0 -67
  38. package/dist/pi-models-config.d.ts +0 -32
  39. package/dist/pi-models-config.js +0 -65
  40. package/dist/plan-application.d.ts +0 -10
  41. package/dist/plan-application.js +0 -190
  42. package/dist/plan-digest.d.ts +0 -18
  43. package/dist/plan-digest.js +0 -116
  44. package/dist/plan-json.d.ts +0 -13
  45. package/dist/plan-json.js +0 -91
  46. package/dist/plan-normalize.d.ts +0 -12
  47. package/dist/plan-normalize.js +0 -168
  48. package/dist/plan-prompt.d.ts +0 -38
  49. package/dist/plan-prompt.js +0 -49
  50. package/dist/plan-support.d.ts +0 -9
  51. package/dist/plan-support.js +0 -22
  52. package/dist/plan-types.d.ts +0 -341
  53. package/dist/plan-types.js +0 -105
  54. package/dist/prime-agent-dir.d.ts +0 -64
  55. package/dist/prime-agent-dir.js +0 -173
  56. package/dist/prime-fork.d.ts +0 -155
  57. package/dist/prime-fork.js +0 -262
  58. package/dist/prime-profile.d.ts +0 -88
  59. package/dist/prime-profile.js +0 -297
  60. package/dist/profile-bundle-cache.d.ts +0 -37
  61. package/dist/profile-bundle-cache.js +0 -320
  62. package/dist/profile-bundle-key.d.ts +0 -69
  63. package/dist/profile-bundle-key.js +0 -62
  64. package/dist/profile-bundle-lru.d.ts +0 -56
  65. package/dist/profile-bundle-lru.js +0 -220
  66. package/dist/profile-materializer.d.ts +0 -24
  67. package/dist/profile-materializer.js +0 -114
  68. package/dist/profile-plan.d.ts +0 -16
  69. package/dist/profile-plan.js +0 -90
  70. package/dist/profile-prompt.d.ts +0 -4
  71. package/dist/profile-prompt.js +0 -107
  72. package/dist/profile-support.d.ts +0 -8
  73. package/dist/profile-support.js +0 -6
  74. package/dist/resource-lowering.d.ts +0 -6
  75. package/dist/resource-lowering.js +0 -103
  76. package/dist/resource-resolution.d.ts +0 -27
  77. package/dist/resource-resolution.js +0 -265
  78. package/dist/secret-concurrent-revision.d.ts +0 -30
  79. package/dist/secret-concurrent-revision.js +0 -249
  80. package/dist/secret-session-view.d.ts +0 -25
  81. package/dist/secret-session-view.js +0 -166
  82. package/dist/subagents.d.ts +0 -6
  83. package/dist/subagents.js +0 -137
  84. package/dist/tool-bin-path.d.ts +0 -23
  85. package/dist/tool-bin-path.js +0 -61
  86. package/dist/workspace-apply-files.d.ts +0 -57
  87. package/dist/workspace-apply-files.js +0 -193
  88. package/dist/workspace-apply-publish.d.ts +0 -22
  89. package/dist/workspace-apply-publish.js +0 -178
  90. package/dist/workspace-apply.d.ts +0 -11
  91. package/dist/workspace-apply.js +0 -124
  92. package/dist/workspace-files.d.ts +0 -8
  93. package/dist/workspace-files.js +0 -46
  94. package/dist/workspace-launch.d.ts +0 -3
  95. package/dist/workspace-launch.js +0 -13
@@ -1,173 +0,0 @@
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
- const localPrimeAgentDirIo = {
8
- read: (path) => (existsSync(path) ? readFileSync(path, "utf8") : undefined),
9
- write: (path, data) => writePrimeAgentFile(path, data),
10
- };
11
- /** The fork's continual-harness store, the only agent-dir file a materialization reads. */
12
- export function primeHarnessStatePath(agentDir) {
13
- return join(agentDir, PRIME_HARNESS_DIR_NAME, PRIME_HARNESS_STATE_FILE);
14
- }
15
- /**
16
- * Materialize the validated controls and return the extra spawn args that bind
17
- * them. Runs before every spawn (same place models.json is materialized), so a
18
- * continual agent dir is re-pinned to the current profile on each fresh prime
19
- * process.
20
- */
21
- export function materializePrimeProfileControls(agentDir, controls, options = {}) {
22
- const { flagFileRoot = agentDir, warn, io = localPrimeAgentDirIo } = options;
23
- const args = [];
24
- const profileDir = join(flagFileRoot, PRIME_PROFILE_DIR_NAME);
25
- if (controls.systemPrompt !== undefined) {
26
- const promptPath = join(profileDir, PRIME_SYSTEM_PROMPT_FILE);
27
- io.write(promptPath, controls.systemPrompt);
28
- args.push("--system-prompt", promptPath);
29
- }
30
- if (controls.appendSystemPrompt !== undefined) {
31
- const appendPath = join(profileDir, PRIME_APPEND_SYSTEM_PROMPT_FILE);
32
- io.write(appendPath, controls.appendSystemPrompt);
33
- args.push("--append-system-prompt", appendPath);
34
- }
35
- if (controls.instructions !== undefined) {
36
- io.write(join(agentDir, PRIME_CONTEXT_FILE), `${controls.instructions}\n`);
37
- }
38
- if (controls.skills.length > 0) {
39
- const skillsRoot = join(profileDir, PRIME_SKILLS_DIR_NAME);
40
- for (const skill of controls.skills) {
41
- io.write(join(skillsRoot, skill.name, "SKILL.md"), normalizeSkillMd(skill.name, skill.content));
42
- }
43
- args.push("--skill", skillsRoot);
44
- }
45
- seedPrimeProfileSubagents(agentDir, controls.subagents, warn, io);
46
- return args;
47
- }
48
- /**
49
- * Remove the files a PREVIOUS materialization of this lowering wrote, so a
50
- * profile that shrank cannot leave a stale instruction file or skill behind for
51
- * the next run against the same dirs.
52
- *
53
- * Only the paths this lowering NAMES are removed. There is deliberately no
54
- * manifest: a manifest would live where the agent can write it, and reading a
55
- * delete list out of agent-writable state turns pruning into an arbitrary-path
56
- * delete.
57
- */
58
- export function prunePrimeProfileMaterial(agentDir, options = {}) {
59
- const { flagFileRoot = agentDir } = options;
60
- rmSync(join(flagFileRoot, PRIME_PROFILE_DIR_NAME), {
61
- recursive: true,
62
- force: true,
63
- });
64
- rmSync(join(agentDir, PRIME_CONTEXT_FILE), { force: true });
65
- }
66
- /**
67
- * Upsert profile subagent specs into the fork's global continual-harness
68
- * store and remove profile-sourced entries the current profile no longer
69
- * declares. Agent-written entries (`source: "agent"`) — and every top-level
70
- * key this lowering does not manage — are preserved untouched.
71
- *
72
- * A store that exists but no longer parses raises
73
- * {@link PrimeHarnessStateError}: the file is the agent's own self-modification
74
- * state, and overwriting it destroys what the run was supposed to observe.
75
- */
76
- export function seedPrimeProfileSubagents(agentDir, subagents, warn, io = localPrimeAgentDirIo) {
77
- const statePath = primeHarnessStatePath(agentDir);
78
- let state = {};
79
- const stored = io.read(statePath);
80
- if (stored !== undefined) {
81
- let parsed;
82
- try {
83
- parsed = JSON.parse(stored);
84
- }
85
- catch (err) {
86
- throw new PrimeHarnessStateError(statePath, err instanceof Error ? err.message : String(err));
87
- }
88
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
89
- throw new PrimeHarnessStateError(statePath, "the store is not a JSON object");
90
- }
91
- state = parsed;
92
- }
93
- else if (subagents.length === 0) {
94
- // Nothing to pin and nothing stale to remove.
95
- return;
96
- }
97
- const rawEntries = state.entries;
98
- const entries = rawEntries && typeof rawEntries === "object" && !Array.isArray(rawEntries)
99
- ? rawEntries
100
- : {};
101
- for (const kind of PRIME_HARNESS_KINDS) {
102
- const records = entries[kind];
103
- if (!records || typeof records !== "object" || Array.isArray(records)) {
104
- entries[kind] = {};
105
- }
106
- }
107
- const existing = entries.subagent;
108
- const desiredIds = new Set(subagents.map((s) => primeSubagentEntryId(s.name)));
109
- let changed = false;
110
- for (const [id, entry] of Object.entries(existing)) {
111
- const source = entry?.source;
112
- const isLegacy = typeof source === "string" &&
113
- PRIME_LEGACY_PROFILE_ENTRY_SOURCES.includes(source);
114
- if (isLegacy) {
115
- warn?.("prime: adopting a subagent entry left by a pre-shared executor", {
116
- statePath,
117
- id,
118
- source,
119
- });
120
- }
121
- if ((source === PRIME_PROFILE_ENTRY_SOURCE || isLegacy) &&
122
- !desiredIds.has(id)) {
123
- delete existing[id];
124
- changed = true;
125
- }
126
- }
127
- const now = new Date().toISOString();
128
- for (const spec of subagents) {
129
- const id = primeSubagentEntryId(spec.name);
130
- const content = [spec.description?.trim(), spec.prompt?.trim()]
131
- .filter((part) => !!part)
132
- .join("\n\n");
133
- const previous = existing[id];
134
- if (previous &&
135
- previous.source === PRIME_PROFILE_ENTRY_SOURCE &&
136
- previous.title === spec.name &&
137
- previous.content === content) {
138
- continue;
139
- }
140
- existing[id] = {
141
- id,
142
- kind: "subagent",
143
- title: spec.name,
144
- content,
145
- path: PRIME_PROFILE_ENTRY_SOURCE,
146
- scope: "global",
147
- reference: {},
148
- arguments: {},
149
- metadata: spec.metadata ?? {},
150
- source: PRIME_PROFILE_ENTRY_SOURCE,
151
- created_at: previous?.created_at ?? now,
152
- updated_at: now,
153
- version: previous && typeof previous.version === "number"
154
- ? previous.version + 1
155
- : 1,
156
- };
157
- changed = true;
158
- }
159
- if (!changed)
160
- return;
161
- io.write(statePath, `${JSON.stringify({
162
- ...state,
163
- schema: typeof state.schema === "number" ? state.schema : 1,
164
- entries,
165
- refinements: Array.isArray(state.refinements) ? state.refinements : [],
166
- }, null, 2)}\n`);
167
- }
168
- import { randomUUID } from "node:crypto";
169
- import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
170
- import { dirname, join } from "node:path";
171
- import { PrimeHarnessStateError } from "./prime-fork.js";
172
- 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";
173
- import { normalizeSkillMd } from "./resource-resolution.js";
@@ -1,155 +0,0 @@
1
- /**
2
- * Fork FACTS for prime-agent (PrimeIntellect-ai/prime-agent) — the constants,
3
- * dialects and refusal reasons every executor that drives the fork needs, with
4
- * no `node:fs` and no executor assumptions. The agent-dir MATERIALIZATION that
5
- * consumes them lives in `./index.ts`; both consumers (cli-bridge's host-spawn
6
- * backend on `--mode rpc`, sdk-provider-prime's in-sandbox adapter on
7
- * `--mode acp`) read these instead of each keeping a private copy, because a
8
- * fork bump must move one file, not two repositories.
9
- *
10
- * Every value here was read from PrimeIntellect-ai/prime-agent 0.7.0
11
- * (be9e2fa0); a fork bump re-reads them against the new clone.
12
- */
13
- /**
14
- * Env vars the agent resolves its config dir from, most-specific first.
15
- *
16
- * The fork derives the name from its own package identity —
17
- * `ENV_AGENT_DIR = \`${envPrefix}_CODING_AGENT_DIR\`` where `envPrefix` comes
18
- * from `package.json` `piConfig.name` (config.ts:485-498) — so the fork reads
19
- * `PRIME_AGENT_CODING_AGENT_DIR` and upstream pi reads `PI_CODING_AGENT_DIR`.
20
- * An executor that sets only the fork's name has its isolation SILENTLY
21
- * disabled when the binary on PATH turns out to be upstream pi: `getAgentDir()`
22
- * falls back to `homedir()/<CONFIG_DIR_NAME>` (config.ts:520-527), one shared
23
- * dir — and therefore one shared self-modifying `harness_state.json` — for
24
- * every session on the box. Setting BOTH names costs nothing and keeps the
25
- * isolation fail-closed under either binary.
26
- */
27
- export declare const PRIME_AGENT_DIR_ENV_VARS: readonly ["PRIME_AGENT_CODING_AGENT_DIR", "PI_CODING_AGENT_DIR"];
28
- /** Canonical agent-dir env var for the fork itself (config.ts:498). */
29
- export declare const PRIME_AGENT_DIR_ENV_VAR: "PRIME_AGENT_CODING_AGENT_DIR";
30
- /** Pin `agentDir` under every name the agent could resolve its config dir from. */
31
- export declare function primeAgentDirEnv(agentDir: string): Record<string, string>;
32
- /**
33
- * Operator knobs an executor forwards into the agent when they are set.
34
- *
35
- * `PRIME_AGENT_KERNEL_VENV` is load-bearing for any executor that also pins
36
- * HOME: the kernel venv defaults under `homedir()/.prime/agent/kernel-venv`
37
- * (kernel/bootstrap.ts:331-342), so a fresh HOME re-bootstraps it through uv on
38
- * every run unless the operator's venv path is forwarded
39
- * (bootstrap.ts:340 override, :358 branch).
40
- */
41
- export declare const PRIME_KERNEL_ENV_PASSTHROUGH: readonly ["PRIME_AGENT_INSTALL_UV", "PRIME_AGENT_KERNEL_PYTHON", "PRIME_AGENT_KERNEL_VENV"];
42
- /**
43
- * Env vars an executor must NEVER forward from its own environment.
44
- *
45
- * These re-point the self-modifying continual-harness store OUTSIDE the agent
46
- * dir (agent-session.ts:8805 hands the kernel its store location), which
47
- * defeats per-session isolation without changing anything an executor inspects.
48
- * Isolation is the fail-closed default; sharing state is an explicit opt-in
49
- * that names a directory, never an inherited env var.
50
- */
51
- export declare const PRIME_HARNESS_STATE_ENV_DENYLIST: readonly ["RLM_GLOBAL_HARNESS_STATE_DIR", "RLM_HARNESS_STATE_DIR"];
52
- /**
53
- * A prime-agent IPython kernel that dies is never re-provisioned headlessly —
54
- * every later `ipython` call fails with one of these markers until the process
55
- * is replaced. An executor that cannot recognize them either reports a generic
56
- * turn failure or burns its whole timeout against a permanently dead tool.
57
- *
58
- * Verified in `core/kernel/index.ts`: :723 ("forked kernel exited
59
- * unexpectedly"), :750 ("Kernel exited before resolving ports"), :779 ("Kernel
60
- * exited during startup"), :820/:837/:1172/:1295 ("Kernel has been shut down").
61
- */
62
- export declare const PRIME_KERNEL_DEAD_MARKERS: readonly string[];
63
- /** The first kernel-death marker present in `text`, or undefined. */
64
- export declare function matchPrimeKernelDeadMarker(text: string): string | undefined;
65
- /**
66
- * `--thinking` rungs the fork's argument parser accepts
67
- * (cli/args.ts:62 `VALID_THINKING_LEVELS`, rejected at :175). Read from the
68
- * fork itself rather than borrowed from upstream pi's measured table: the two
69
- * agreeing today is a coincidence this module must not depend on.
70
- */
71
- export declare const PRIME_THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
72
- export type PrimeThinkingLevel = (typeof PRIME_THINKING_LEVELS)[number];
73
- /**
74
- * Map the portable reasoning ladder onto the fork's `--thinking` value.
75
- *
76
- * Throws on an effort with no rung instead of returning undefined: omitting the
77
- * flag runs the agent at its default thinking level while the caller believes
78
- * the requested effort is in force, which is a silently dropped control.
79
- */
80
- export declare function primeThinkingLevel(effort: string | null | undefined): PrimeThinkingLevel | undefined;
81
- /**
82
- * Why `profile.mcp` (and any hub connection that resolves to MCP) is refused.
83
- *
84
- * The fork's `mcpServers` settings surface IS read at startup
85
- * (settings-manager.ts:98-120,219) but a user-declared server never becomes
86
- * model-visible: the host McpManager registers OAuth providers and serves
87
- * mcp.config/refresh host-requests only (core/mcp/mcp-manager.ts:62-124),
88
- * skips stdio servers entirely (mcp-manager.ts:73), and nothing generates a
89
- * skill or prompt section for one. Model-visible MCP is exactly the built-in
90
- * catalog skills, which are hand-written Python `McpIntegration` subclasses
91
- * (prime-agent-runtime/src/rlm/mcp_base.py:112-125; only linear and notion
92
- * ship). Materializing a per-run entry would run the agent WITHOUT the
93
- * requested tools while the config on disk says otherwise.
94
- */
95
- export declare const PRIME_MCP_UNSUPPORTED_REASON: string;
96
- /** Which half of a profile refusal this is: a fork limit, or a bad declaration. */
97
- export type PrimeProfileErrorKind = "unsupported" | "invalid";
98
- /**
99
- * Refusal raised by the shared prime lowering, carrying the control and the
100
- * reason separately so each executor can render them in its own error contract
101
- * (an HTTP backend's typed `BackendError`, an SDK adapter's plain `Error`)
102
- * without the reason text — which is where the fork evidence lives — being
103
- * rewritten per repository.
104
- */
105
- export declare class PrimeProfileError extends Error {
106
- readonly kind: PrimeProfileErrorKind;
107
- readonly control: string;
108
- readonly reason: string;
109
- constructor(kind: PrimeProfileErrorKind, control: string, reason: string);
110
- }
111
- /** Raise the "the fork cannot honor this control" half of the refusal. */
112
- export declare function rejectPrimeControl(control: string, reason: string): never;
113
- /** Raise the "this declaration is malformed" half of the refusal. */
114
- export declare function rejectPrimeDeclaration(control: string, reason: string): never;
115
- /**
116
- * The fork's continual-harness store exists but no longer parses.
117
- *
118
- * The store is the agent's own self-modification state — refinements, learned
119
- * prompts, subagents it created mid-session — so an executor that reseeds it
120
- * from empty destroys evidence and silently mutates the thing under study. The
121
- * turn is failed instead; the file is the operator's to repair or remove.
122
- */
123
- export declare class PrimeHarnessStateError extends Error {
124
- readonly statePath: string;
125
- constructor(statePath: string, detail: string);
126
- }
127
- /**
128
- * Strip `//` line comments and trailing commas, leaving string literals
129
- * untouched — byte-for-byte the fork's own `stripJsonComments`
130
- * (core/model-registry.ts), so a models.json the agent accepts is never refused
131
- * by an executor and vice versa.
132
- */
133
- export declare function stripPrimeJsonComments(input: string): string;
134
- /**
135
- * Parse a models.json with the fork's own laxness and assert the one structural
136
- * invariant it requires (a `providers` object). Throws naming `sourcePath`.
137
- *
138
- * This is the SHAPE and DIALECT only. Producing the file is deliberately not
139
- * shared: an executor holding real operator credentials copies an
140
- * operator-authored file and forwards only the env var names its `apiKey`
141
- * entries reference, while an in-sandbox executor synthesizes a one-provider
142
- * entry with a literal key that is a proxy dummy. Same schema, opposite threat
143
- * models.
144
- */
145
- export declare function parsePrimeModelsJson(text: string, sourcePath: string): Record<string, unknown>;
146
- /**
147
- * Environment variables a models.json names as `apiKey` sources.
148
- *
149
- * prime resolves an `apiKey` value env-var first and LITERAL second
150
- * (core/resolve-config-value.ts), so an executor that forwards exactly the
151
- * named variables lets an operator keep secrets out of the file — and an
152
- * executor that forwards NONE of them silently turns the variable name itself
153
- * into the credential string.
154
- */
155
- export declare function primeApiKeyEnvNames(modelsConfig: Record<string, unknown>): string[];
@@ -1,262 +0,0 @@
1
- /**
2
- * Fork FACTS for prime-agent (PrimeIntellect-ai/prime-agent) — the constants,
3
- * dialects and refusal reasons every executor that drives the fork needs, with
4
- * no `node:fs` and no executor assumptions. The agent-dir MATERIALIZATION that
5
- * consumes them lives in `./index.ts`; both consumers (cli-bridge's host-spawn
6
- * backend on `--mode rpc`, sdk-provider-prime's in-sandbox adapter on
7
- * `--mode acp`) read these instead of each keeping a private copy, because a
8
- * fork bump must move one file, not two repositories.
9
- *
10
- * Every value here was read from PrimeIntellect-ai/prime-agent 0.7.0
11
- * (be9e2fa0); a fork bump re-reads them against the new clone.
12
- */
13
- /**
14
- * Env vars the agent resolves its config dir from, most-specific first.
15
- *
16
- * The fork derives the name from its own package identity —
17
- * `ENV_AGENT_DIR = \`${envPrefix}_CODING_AGENT_DIR\`` where `envPrefix` comes
18
- * from `package.json` `piConfig.name` (config.ts:485-498) — so the fork reads
19
- * `PRIME_AGENT_CODING_AGENT_DIR` and upstream pi reads `PI_CODING_AGENT_DIR`.
20
- * An executor that sets only the fork's name has its isolation SILENTLY
21
- * disabled when the binary on PATH turns out to be upstream pi: `getAgentDir()`
22
- * falls back to `homedir()/<CONFIG_DIR_NAME>` (config.ts:520-527), one shared
23
- * dir — and therefore one shared self-modifying `harness_state.json` — for
24
- * every session on the box. Setting BOTH names costs nothing and keeps the
25
- * isolation fail-closed under either binary.
26
- */
27
- export const PRIME_AGENT_DIR_ENV_VARS = [
28
- "PRIME_AGENT_CODING_AGENT_DIR",
29
- "PI_CODING_AGENT_DIR",
30
- ];
31
- /** Canonical agent-dir env var for the fork itself (config.ts:498). */
32
- export const PRIME_AGENT_DIR_ENV_VAR = PRIME_AGENT_DIR_ENV_VARS[0];
33
- /** Pin `agentDir` under every name the agent could resolve its config dir from. */
34
- export function primeAgentDirEnv(agentDir) {
35
- const env = {};
36
- for (const name of PRIME_AGENT_DIR_ENV_VARS)
37
- env[name] = agentDir;
38
- return env;
39
- }
40
- /**
41
- * Operator knobs an executor forwards into the agent when they are set.
42
- *
43
- * `PRIME_AGENT_KERNEL_VENV` is load-bearing for any executor that also pins
44
- * HOME: the kernel venv defaults under `homedir()/.prime/agent/kernel-venv`
45
- * (kernel/bootstrap.ts:331-342), so a fresh HOME re-bootstraps it through uv on
46
- * every run unless the operator's venv path is forwarded
47
- * (bootstrap.ts:340 override, :358 branch).
48
- */
49
- export const PRIME_KERNEL_ENV_PASSTHROUGH = [
50
- /** "1" lets a headless first run install uv itself; "0" forbids it. */
51
- "PRIME_AGENT_INSTALL_UV",
52
- /** Offline escape hatch: pin the kernel venv python instead of uv-provisioning. */
53
- "PRIME_AGENT_KERNEL_PYTHON",
54
- /** Reuse an operator-provisioned kernel venv instead of re-bootstrapping it. */
55
- "PRIME_AGENT_KERNEL_VENV",
56
- ];
57
- /**
58
- * Env vars an executor must NEVER forward from its own environment.
59
- *
60
- * These re-point the self-modifying continual-harness store OUTSIDE the agent
61
- * dir (agent-session.ts:8805 hands the kernel its store location), which
62
- * defeats per-session isolation without changing anything an executor inspects.
63
- * Isolation is the fail-closed default; sharing state is an explicit opt-in
64
- * that names a directory, never an inherited env var.
65
- */
66
- export const PRIME_HARNESS_STATE_ENV_DENYLIST = [
67
- "RLM_GLOBAL_HARNESS_STATE_DIR",
68
- "RLM_HARNESS_STATE_DIR",
69
- ];
70
- /**
71
- * A prime-agent IPython kernel that dies is never re-provisioned headlessly —
72
- * every later `ipython` call fails with one of these markers until the process
73
- * is replaced. An executor that cannot recognize them either reports a generic
74
- * turn failure or burns its whole timeout against a permanently dead tool.
75
- *
76
- * Verified in `core/kernel/index.ts`: :723 ("forked kernel exited
77
- * unexpectedly"), :750 ("Kernel exited before resolving ports"), :779 ("Kernel
78
- * exited during startup"), :820/:837/:1172/:1295 ("Kernel has been shut down").
79
- */
80
- export const PRIME_KERNEL_DEAD_MARKERS = [
81
- "Kernel has been shut down",
82
- "Kernel exited before resolving ports",
83
- "Kernel exited during startup",
84
- "forked kernel exited unexpectedly",
85
- ];
86
- /** The first kernel-death marker present in `text`, or undefined. */
87
- export function matchPrimeKernelDeadMarker(text) {
88
- return PRIME_KERNEL_DEAD_MARKERS.find((marker) => text.includes(marker));
89
- }
90
- /**
91
- * `--thinking` rungs the fork's argument parser accepts
92
- * (cli/args.ts:62 `VALID_THINKING_LEVELS`, rejected at :175). Read from the
93
- * fork itself rather than borrowed from upstream pi's measured table: the two
94
- * agreeing today is a coincidence this module must not depend on.
95
- */
96
- export const PRIME_THINKING_LEVELS = [
97
- "off",
98
- "minimal",
99
- "low",
100
- "medium",
101
- "high",
102
- "xhigh",
103
- "max",
104
- ];
105
- /** Canonical portable effort → fork `--thinking` rung. */
106
- const PRIME_THINKING_BY_EFFORT = {
107
- none: "off",
108
- minimal: "minimal",
109
- low: "low",
110
- medium: "medium",
111
- high: "high",
112
- xhigh: "xhigh",
113
- // The fork carries `max` above `xhigh`, so the ceiling level reaches it.
114
- ultracode: "max",
115
- };
116
- /**
117
- * Map the portable reasoning ladder onto the fork's `--thinking` value.
118
- *
119
- * Throws on an effort with no rung instead of returning undefined: omitting the
120
- * flag runs the agent at its default thinking level while the caller believes
121
- * the requested effort is in force, which is a silently dropped control.
122
- */
123
- export function primeThinkingLevel(effort) {
124
- if (effort === undefined || effort === null || effort === "")
125
- return undefined;
126
- const level = PRIME_THINKING_BY_EFFORT[effort];
127
- if (level === undefined) {
128
- throw new PrimeProfileError("invalid", "model.reasoningEffort", `prime-agent has no --thinking rung for ${JSON.stringify(effort)} ` +
129
- `(fork cli/args.ts:62 accepts ${PRIME_THINKING_LEVELS.join(", ")}).`);
130
- }
131
- return level;
132
- }
133
- /**
134
- * Why `profile.mcp` (and any hub connection that resolves to MCP) is refused.
135
- *
136
- * The fork's `mcpServers` settings surface IS read at startup
137
- * (settings-manager.ts:98-120,219) but a user-declared server never becomes
138
- * model-visible: the host McpManager registers OAuth providers and serves
139
- * mcp.config/refresh host-requests only (core/mcp/mcp-manager.ts:62-124),
140
- * skips stdio servers entirely (mcp-manager.ts:73), and nothing generates a
141
- * skill or prompt section for one. Model-visible MCP is exactly the built-in
142
- * catalog skills, which are hand-written Python `McpIntegration` subclasses
143
- * (prime-agent-runtime/src/rlm/mcp_base.py:112-125; only linear and notion
144
- * ship). Materializing a per-run entry would run the agent WITHOUT the
145
- * requested tools while the config on disk says otherwise.
146
- */
147
- export const PRIME_MCP_UNSUPPORTED_REASON = "a user-declared mcpServers entry is read from the fork's settings.json at startup but never " +
148
- "becomes model-visible: the host only registers OAuth/config for it (fork core/mcp/" +
149
- "mcp-manager.ts:62-124), skips stdio servers entirely (mcp-manager.ts:73), and generates no " +
150
- "skill or prompt section for it. Model-visible MCP is exactly the built-in Python " +
151
- "McpIntegration catalog skills (prime-agent-runtime/src/rlm/mcp_base.py:112-125), which no " +
152
- "per-run configuration creates — so materializing it would be a silently dropped control.";
153
- /**
154
- * Refusal raised by the shared prime lowering, carrying the control and the
155
- * reason separately so each executor can render them in its own error contract
156
- * (an HTTP backend's typed `BackendError`, an SDK adapter's plain `Error`)
157
- * without the reason text — which is where the fork evidence lives — being
158
- * rewritten per repository.
159
- */
160
- export class PrimeProfileError extends Error {
161
- kind;
162
- control;
163
- reason;
164
- constructor(kind, control, reason) {
165
- super(kind === "unsupported"
166
- ? `prime does not support AgentProfile ${control}: ${reason}`
167
- : `prime cannot accept AgentProfile ${control}: ${reason}`);
168
- this.name = "PrimeProfileError";
169
- this.kind = kind;
170
- this.control = control;
171
- this.reason = reason;
172
- }
173
- }
174
- /** Raise the "the fork cannot honor this control" half of the refusal. */
175
- export function rejectPrimeControl(control, reason) {
176
- throw new PrimeProfileError("unsupported", control, reason);
177
- }
178
- /** Raise the "this declaration is malformed" half of the refusal. */
179
- export function rejectPrimeDeclaration(control, reason) {
180
- throw new PrimeProfileError("invalid", control, reason);
181
- }
182
- /**
183
- * The fork's continual-harness store exists but no longer parses.
184
- *
185
- * The store is the agent's own self-modification state — refinements, learned
186
- * prompts, subagents it created mid-session — so an executor that reseeds it
187
- * from empty destroys evidence and silently mutates the thing under study. The
188
- * turn is failed instead; the file is the operator's to repair or remove.
189
- */
190
- export class PrimeHarnessStateError extends Error {
191
- statePath;
192
- constructor(statePath, detail) {
193
- super(`prime harness state ${statePath} is not valid JSON and may hold agent self-modification ` +
194
- `state; refusing to overwrite it — repair or remove the file to continue (${detail})`);
195
- this.name = "PrimeHarnessStateError";
196
- this.statePath = statePath;
197
- }
198
- }
199
- /**
200
- * Strip `//` line comments and trailing commas, leaving string literals
201
- * untouched — byte-for-byte the fork's own `stripJsonComments`
202
- * (core/model-registry.ts), so a models.json the agent accepts is never refused
203
- * by an executor and vice versa.
204
- */
205
- export function stripPrimeJsonComments(input) {
206
- return input
207
- .replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g, (m) => (m[0] === '"' ? m : ""))
208
- .replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (m, tail) => tail !== undefined ? tail : m[0] === '"' ? m : "");
209
- }
210
- /**
211
- * Parse a models.json with the fork's own laxness and assert the one structural
212
- * invariant it requires (a `providers` object). Throws naming `sourcePath`.
213
- *
214
- * This is the SHAPE and DIALECT only. Producing the file is deliberately not
215
- * shared: an executor holding real operator credentials copies an
216
- * operator-authored file and forwards only the env var names its `apiKey`
217
- * entries reference, while an in-sandbox executor synthesizes a one-provider
218
- * entry with a literal key that is a proxy dummy. Same schema, opposite threat
219
- * models.
220
- */
221
- export function parsePrimeModelsJson(text, sourcePath) {
222
- let parsed;
223
- try {
224
- parsed = JSON.parse(stripPrimeJsonComments(text));
225
- }
226
- catch (err) {
227
- throw new Error(`prime models.json ${sourcePath} is not valid JSON: ${err.message}`);
228
- }
229
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
230
- throw new Error(`prime models.json ${sourcePath} must be a JSON object`);
231
- }
232
- const providers = parsed.providers;
233
- if (!providers || typeof providers !== "object" || Array.isArray(providers)) {
234
- throw new Error(`prime models.json ${sourcePath} must carry a "providers" object (prime's models.json schema)`);
235
- }
236
- return parsed;
237
- }
238
- /**
239
- * Environment variables a models.json names as `apiKey` sources.
240
- *
241
- * prime resolves an `apiKey` value env-var first and LITERAL second
242
- * (core/resolve-config-value.ts), so an executor that forwards exactly the
243
- * named variables lets an operator keep secrets out of the file — and an
244
- * executor that forwards NONE of them silently turns the variable name itself
245
- * into the credential string.
246
- */
247
- export function primeApiKeyEnvNames(modelsConfig) {
248
- const names = [];
249
- const providers = modelsConfig.providers;
250
- if (!providers || typeof providers !== "object")
251
- return names;
252
- for (const provider of Object.values(providers)) {
253
- if (!provider || typeof provider !== "object")
254
- continue;
255
- const key = provider.apiKey;
256
- if (typeof key !== "string" || !/^[A-Z_][A-Z0-9_]*$/.test(key))
257
- continue;
258
- if (!names.includes(key))
259
- names.push(key);
260
- }
261
- return names;
262
- }
@@ -1,88 +0,0 @@
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";