@tangle-network/agent-profile-materialize 1.0.2 → 1.1.1

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.
@@ -16,3 +16,5 @@ import type { HarnessId } from "./harness.js";
16
16
  export declare function keepsHarnessSystemPrompt(profile: AgentProfile | undefined, harness: HarnessId | string | undefined): boolean;
17
17
  /** Join prompt additions in order, skipping empty ones. */
18
18
  export declare function joinSystemPromptAdditions(...additions: Array<string | undefined>): string | undefined;
19
+ /** Native inline context has a bounded argument; long context belongs in resources.files. */
20
+ export declare function codexDeveloperInstructionArgs(value: string | undefined, flags?: readonly string[]): string[];
@@ -27,13 +27,12 @@ const HARNESSES_WITH_ADDITIVE_HOST_PROMPT = new Set(["claude-code", "pi", "openc
27
27
  */
28
28
  export function keepsHarnessSystemPrompt(profile, harness) {
29
29
  const prompt = profile?.prompt;
30
- if (!prompt || prompt.systemPrompt !== undefined)
30
+ if (!profile || prompt?.systemPrompt !== undefined)
31
31
  return false;
32
- const declaresIntent = (prompt.instructions?.length ?? 0) > 0 ||
33
- prompt.appendSystemPrompt !== undefined;
34
- return (declaresIntent &&
35
- harness !== undefined &&
36
- HARNESSES_WITH_ADDITIVE_HOST_PROMPT.has(harness));
32
+ return (HARNESSES_WITH_ADDITIVE_HOST_PROMPT.has(harness ?? "") &&
33
+ ((prompt?.instructions?.length ?? 0) > 0 ||
34
+ prompt?.appendSystemPrompt !== undefined ||
35
+ (harness === "codex" && profile.resources?.instructions !== undefined)));
37
36
  }
38
37
  /** Join prompt additions in order, skipping empty ones. */
39
38
  export function joinSystemPromptAdditions(...additions) {
@@ -42,3 +41,21 @@ export function joinSystemPromptAdditions(...additions) {
42
41
  .filter((addition) => Boolean(addition));
43
42
  return parts.length > 0 ? parts.join("\n\n") : undefined;
44
43
  }
44
+ /** Native inline context has a bounded argument; long context belongs in resources.files. */
45
+ export function codexDeveloperInstructionArgs(value, flags = []) {
46
+ if (value === undefined)
47
+ return [];
48
+ if (flags.some((flag, index) => {
49
+ const selector = ["-c", "--config"].includes(flags[index - 1] ?? "")
50
+ ? flag
51
+ : /^(?:--config=|-c=?)(.+)$/su.exec(flag)?.[1];
52
+ return (selector &&
53
+ /^(?:developer_instructions\s*=|["'])/u.test(selector.trimStart()));
54
+ }))
55
+ throw new Error("Codex context conflicts with a caller configuration override; put developer_instructions in the AgentProfile and use unquoted configuration keys");
56
+ const encoded = `developer_instructions=${JSON.stringify(value)}`;
57
+ // This is the adapter's portable inline budget, not an OS capacity claim.
58
+ if (Buffer.byteLength(encoded, "utf8") > 64 * 1024)
59
+ throw new Error("Codex inline context is too large; move long context into profile.resources.files and keep prompt.instructions short");
60
+ return ["-c", encoded];
61
+ }
@@ -148,8 +148,10 @@ export declare function assertSkippableDimensions(skip: readonly string[] | unde
148
148
  * guarantee — so the plan refuses the intent (harnessSystemPromptIntents in
149
149
  * @tangle-network/agent-interface answers `replace: false` for opencode).
150
150
  *
151
- * The two declarations describe the two executor shapes that CAN reach it, and
152
- * each gets the lowering it can actually apply:
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:
153
155
  *
154
156
  * - `systemPrompt` — the executor applies the plan's launch flags to the
155
157
  * spawn it owns, so the plan writes the generated `mode: primary` agent and
@@ -159,10 +161,10 @@ export declare function assertSkippableDimensions(skip: readonly string[] | unde
159
161
  * plan hands the text over in {@link WorkspacePlan.systemPromptBinding}
160
162
  * instead of writing a workspace agent that would never be selected.
161
163
  *
162
- * They are mutually exclusive claims about the same caller: declaring both is a
164
+ * The replacement declarations are mutually exclusive: declaring both is a
163
165
  * caller bug, not a broader capability.
164
166
  */
165
- export declare const BINDABLE_LAUNCH_CONTROLS: readonly ["systemPrompt", "opencode.agent-prompt"];
167
+ export declare const BINDABLE_LAUNCH_CONTROLS: readonly ["systemPrompt", "codex.developer-instructions", "opencode.agent-prompt"];
166
168
  export type BindableLaunchControl = (typeof BINDABLE_LAUNCH_CONTROLS)[number];
167
169
  /** Reject a binding declaration this materializer has no lowering for, rather than ignoring it. */
168
170
  export declare function assertBindableLaunchControls(binds: readonly string[] | undefined): ReadonlySet<BindableLaunchControl>;
@@ -188,15 +190,13 @@ export interface WorkspacePlan {
188
190
  */
189
191
  systemPrompt?: string;
190
192
  /**
191
- * Exact text ADDED to the harness's own system prompt, which stays intact.
193
+ * Text added to the harness context; its own system prompt stays intact.
192
194
  *
193
- * Separate from {@link WorkspacePlan.systemPrompt} because the two are
194
- * different intents against the same channel, and every harness that has one
195
- * control may lack the other. An executor binds this ONLY to an additive
196
- * control (claude-code `--append-system-prompt`, pi
197
- * `--append-system-prompt`); there is no harness for which folding it into
198
- * the replacement is correct, because that would delete the built-in prompt
199
- * the caller asked to keep.
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
200
  */
201
201
  appendSystemPrompt?: string;
202
202
  /**
@@ -52,8 +52,10 @@ export function assertSkippableDimensions(skip) {
52
52
  * guarantee — so the plan refuses the intent (harnessSystemPromptIntents in
53
53
  * @tangle-network/agent-interface answers `replace: false` for opencode).
54
54
  *
55
- * The two declarations describe the two executor shapes that CAN reach it, and
56
- * each gets the lowering it can actually apply:
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:
57
59
  *
58
60
  * - `systemPrompt` — the executor applies the plan's launch flags to the
59
61
  * spawn it owns, so the plan writes the generated `mode: primary` agent and
@@ -63,11 +65,12 @@ export function assertSkippableDimensions(skip) {
63
65
  * plan hands the text over in {@link WorkspacePlan.systemPromptBinding}
64
66
  * instead of writing a workspace agent that would never be selected.
65
67
  *
66
- * They are mutually exclusive claims about the same caller: declaring both is a
68
+ * The replacement declarations are mutually exclusive: declaring both is a
67
69
  * caller bug, not a broader capability.
68
70
  */
69
71
  export const BINDABLE_LAUNCH_CONTROLS = [
70
72
  "systemPrompt",
73
+ "codex.developer-instructions",
71
74
  ...EXECUTOR_SYSTEM_PROMPT_BINDINGS,
72
75
  ];
73
76
  const BINDABLE_LAUNCH_CONTROL_SET = new Set(BINDABLE_LAUNCH_CONTROLS);
@@ -70,10 +70,7 @@ export function lowerProfilePrompt(profile, harness, binds, instructionsRoot, bu
70
70
  unsupported("appendSystemPrompt", appendSystemPromptRefusal(harness));
71
71
  }
72
72
  }
73
- const instructions = [];
74
- if (profile.prompt?.instructions?.length) {
75
- instructions.push(...profile.prompt.instructions);
76
- }
73
+ const instructions = [...(profile.prompt?.instructions ?? [])];
77
74
  const resourceInstructions = profile.resources?.instructions;
78
75
  if (typeof resourceInstructions === "string") {
79
76
  instructions.push(resourceInstructions);
@@ -85,7 +82,12 @@ export function lowerProfilePrompt(profile, harness, binds, instructionsRoot, bu
85
82
  unsupported("instructions", "instruction ref is not inline (github refs need async pre-resolution)");
86
83
  }
87
84
  if (instructions.length) {
88
- if (openCodeConfigUnreachable) {
85
+ if (harness === "codex" && binds.has("codex.developer-instructions")) {
86
+ // Codex's developer channel composes profile context without replacing
87
+ // repository AGENTS.md or the harness's own system instructions.
88
+ plan.appendSystemPrompt = instructions.join("\n\n");
89
+ }
90
+ else if (openCodeConfigUnreachable) {
89
91
  unsupported("instructions", "opencode: the launcher that binds opencode.agent-prompt composes opencode's config itself and loads no workspace opencode.json, so an instruction file registered there would never reach the model; compose it into the launcher's own instructions[]");
90
92
  }
91
93
  else {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-profile-materialize",
3
- "version": "1.0.2",
3
+ "version": "1.1.1",
4
4
  "description": "Materialize an AgentProfile into the native per-harness workspace files (the one shared materializer for cli-bridge, agent-container, and VB).",
5
5
  "type": "module",
6
6
  "repository": {
@@ -35,8 +35,8 @@
35
35
  "@tangle-network/agent-interface": "^3.0.0 || ^4.0.0 || ^5.0.0"
36
36
  },
37
37
  "tangleRelease": {
38
- "sourceSha": "0f6ba1deca15d9e117553eae67ff01cae6425004",
39
- "mergedAt": "2026-10-27T04:36:51-06:00"
38
+ "sourceSha": "978d63826f9678b70d7e77f21742d4d99b91e580",
39
+ "mergedAt": "2026-10-27T06:00:15-06:00"
40
40
  },
41
41
  "scripts": {
42
42
  "build": "tsc -p tsconfig.json",