@tangle-network/agent-profile-materialize 0.7.0 → 0.9.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.
- package/dist/index.d.ts +5 -4
- package/dist/index.js +36 -32
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
* cli-bridge and agent-dev-container — this is the single source those re-export.
|
|
23
23
|
*/
|
|
24
24
|
import type { AgentCandidateConfigValue, AgentCandidateProfile, AgentCandidateProfileActivation, AgentCandidateProfileApplication, AgentCandidateProfilePlanEvidence, AgentCandidateProfilePlanMaterial, AgentProfile, AgentProfileMcpServer, Sha256Digest } from "@tangle-network/agent-interface";
|
|
25
|
-
export
|
|
25
|
+
export declare const MATERIALIZER_HARNESSES: readonly ["claude-code", "nanoclaw", "codex", "opencode", "kimi-code", "pi", "gemini", "hermes", "openclaw"];
|
|
26
|
+
export type HarnessId = (typeof MATERIALIZER_HARNESSES)[number];
|
|
27
|
+
export declare function isMaterializerHarness(harness: string): harness is HarnessId;
|
|
26
28
|
export interface PlanFile {
|
|
27
29
|
relPath: string;
|
|
28
30
|
content: string;
|
|
@@ -157,9 +159,8 @@ export declare function harnessContextFile(harness: HarnessId): string;
|
|
|
157
159
|
export declare const HARNESS_SKILL_DIRS: Readonly<Record<HarnessId, string | null>>;
|
|
158
160
|
/**
|
|
159
161
|
* Resolve the cwd-relative directory `resources.skills` refs materialize
|
|
160
|
-
* into on `harness`
|
|
161
|
-
*
|
|
162
|
-
* cwd skills — the same condition that surfaces as an `unsupported`
|
|
162
|
+
* into on `harness`. `null` means the harness cannot receive cwd skills, the
|
|
163
|
+
* same condition that surfaces as an `unsupported`
|
|
163
164
|
* "skills" entry (and an {@link assertWorkspacePlanSupported} throw) at
|
|
164
165
|
* materialize time, exposed here as branchable data.
|
|
165
166
|
*/
|
package/dist/index.js
CHANGED
|
@@ -54,6 +54,26 @@ function resolveInlineRef(ref) {
|
|
|
54
54
|
}
|
|
55
55
|
return null; // github / unresolved
|
|
56
56
|
}
|
|
57
|
+
export const MATERIALIZER_HARNESSES = [
|
|
58
|
+
"claude-code",
|
|
59
|
+
"nanoclaw",
|
|
60
|
+
"codex",
|
|
61
|
+
"opencode",
|
|
62
|
+
"kimi-code",
|
|
63
|
+
"pi",
|
|
64
|
+
"gemini",
|
|
65
|
+
"hermes",
|
|
66
|
+
"openclaw",
|
|
67
|
+
];
|
|
68
|
+
const MATERIALIZER_HARNESS_SET = new Set(MATERIALIZER_HARNESSES);
|
|
69
|
+
export function isMaterializerHarness(harness) {
|
|
70
|
+
return MATERIALIZER_HARNESS_SET.has(harness);
|
|
71
|
+
}
|
|
72
|
+
function assertMaterializerHarness(harness) {
|
|
73
|
+
if (!isMaterializerHarness(harness)) {
|
|
74
|
+
throw new Error(`Unsupported profile materialization harness "${harness}"`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
57
77
|
/** The plan was applied, but one or more private staging files remain. */
|
|
58
78
|
export class WorkspacePlanCleanupError extends AggregateError {
|
|
59
79
|
receipt;
|
|
@@ -97,7 +117,8 @@ export function enforceWorkspacePlanSupport(plan, failOnError) {
|
|
|
97
117
|
* lowering below, and the interactive TUI's persona fold.
|
|
98
118
|
*/
|
|
99
119
|
export function harnessAutoLoadsContextFile(harness) {
|
|
100
|
-
|
|
120
|
+
assertMaterializerHarness(harness);
|
|
121
|
+
return harness !== "opencode";
|
|
101
122
|
}
|
|
102
123
|
/**
|
|
103
124
|
* The project context file this harness reads from cwd — its stable, documented
|
|
@@ -107,11 +128,12 @@ export function harnessAutoLoadsContextFile(harness) {
|
|
|
107
128
|
* of this per-harness map.
|
|
108
129
|
*/
|
|
109
130
|
export function harnessContextFile(harness) {
|
|
131
|
+
assertMaterializerHarness(harness);
|
|
110
132
|
// The map is keyed by HarnessId, but callers reach this from runtime strings
|
|
111
133
|
// (a registry spec name, a request field). A miss would otherwise return
|
|
112
134
|
// undefined behind a `string` return type and surface as an undefined write
|
|
113
135
|
// path much later.
|
|
114
|
-
const path = CONTEXT_FILE[
|
|
136
|
+
const path = CONTEXT_FILE[harness];
|
|
115
137
|
if (!path) {
|
|
116
138
|
throw new Error(`No project context file is known for harness "${harness}"`);
|
|
117
139
|
}
|
|
@@ -120,13 +142,10 @@ export function harnessContextFile(harness) {
|
|
|
120
142
|
/** Project context file each harness actually reads from cwd. NEVER a constant. */
|
|
121
143
|
const CONTEXT_FILE = {
|
|
122
144
|
"claude-code": "CLAUDE.md",
|
|
123
|
-
claude: "CLAUDE.md",
|
|
124
|
-
claudish: "CLAUDE.md",
|
|
125
145
|
nanoclaw: "CLAUDE.md",
|
|
126
146
|
codex: "AGENTS.md",
|
|
127
147
|
opencode: ".opencode/profile-instructions.md",
|
|
128
148
|
"kimi-code": "AGENTS.md",
|
|
129
|
-
kimi: "AGENTS.md",
|
|
130
149
|
pi: "AGENTS.md",
|
|
131
150
|
gemini: "GEMINI.md", // current default; AGENTS.md only via .gemini/settings.json context.fileName
|
|
132
151
|
hermes: "HERMES.md", // highest-priority native name; only ONE context loads (first match)
|
|
@@ -142,13 +161,10 @@ const CONTEXT_FILE = {
|
|
|
142
161
|
*/
|
|
143
162
|
export const HARNESS_SKILL_DIRS = {
|
|
144
163
|
"claude-code": ".claude/skills",
|
|
145
|
-
claude: ".claude/skills",
|
|
146
|
-
claudish: ".claude/skills",
|
|
147
164
|
nanoclaw: ".claude/skills",
|
|
148
165
|
codex: ".codex/skills",
|
|
149
166
|
opencode: ".opencode/skills",
|
|
150
167
|
"kimi-code": ".kimi/skills",
|
|
151
|
-
kimi: ".kimi/skills",
|
|
152
168
|
pi: ".pi/skills",
|
|
153
169
|
gemini: ".gemini/skills",
|
|
154
170
|
hermes: null, // skills are ~/.hermes/skills (user) only — no cwd discovery
|
|
@@ -157,21 +173,14 @@ export const HARNESS_SKILL_DIRS = {
|
|
|
157
173
|
const SKILL_DIR = HARNESS_SKILL_DIRS;
|
|
158
174
|
/**
|
|
159
175
|
* Resolve the cwd-relative directory `resources.skills` refs materialize
|
|
160
|
-
* into on `harness`
|
|
161
|
-
*
|
|
162
|
-
* cwd skills — the same condition that surfaces as an `unsupported`
|
|
176
|
+
* into on `harness`. `null` means the harness cannot receive cwd skills, the
|
|
177
|
+
* same condition that surfaces as an `unsupported`
|
|
163
178
|
* "skills" entry (and an {@link assertWorkspacePlanSupported} throw) at
|
|
164
179
|
* materialize time, exposed here as branchable data.
|
|
165
180
|
*/
|
|
166
181
|
export function skillDirForHarness(harness) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
function canonicalHarness(h) {
|
|
170
|
-
if (h === "claude" || h === "claudish")
|
|
171
|
-
return "claude-code";
|
|
172
|
-
if (h === "kimi")
|
|
173
|
-
return "kimi-code";
|
|
174
|
-
return h;
|
|
182
|
+
assertMaterializerHarness(harness);
|
|
183
|
+
return HARNESS_SKILL_DIRS[harness];
|
|
175
184
|
}
|
|
176
185
|
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
177
186
|
const FRONTMATTER_RE = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/;
|
|
@@ -431,8 +440,9 @@ const tomlStr = (s) => JSON.stringify(s); // valid TOML basic string
|
|
|
431
440
|
* writes plan.files into the run cwd and applies plan.env/plan.flags to the spawn.
|
|
432
441
|
*/
|
|
433
442
|
export function materializeProfile(inputProfile, harness, opts = {}) {
|
|
443
|
+
assertMaterializerHarness(harness);
|
|
434
444
|
const profile = agentProfileSchema.parse(inputProfile);
|
|
435
|
-
const h =
|
|
445
|
+
const h = harness;
|
|
436
446
|
const skip = new Set(opts.skip ?? []);
|
|
437
447
|
const plan = {
|
|
438
448
|
harness: h,
|
|
@@ -637,14 +647,7 @@ function activeMcpServers(servers) {
|
|
|
637
647
|
return Object.fromEntries(Object.entries(servers ?? {}).filter((entry) => entry[1].enabled !== false));
|
|
638
648
|
}
|
|
639
649
|
function extensionNamespaces(harness) {
|
|
640
|
-
|
|
641
|
-
case "claude-code":
|
|
642
|
-
return ["claude-code", "claude"];
|
|
643
|
-
case "kimi-code":
|
|
644
|
-
return ["kimi-code", "kimi"];
|
|
645
|
-
default:
|
|
646
|
-
return [harness];
|
|
647
|
-
}
|
|
650
|
+
return [harness];
|
|
648
651
|
}
|
|
649
652
|
/**
|
|
650
653
|
* Materialize a sealed candidate profile without weakening its process values.
|
|
@@ -652,6 +655,7 @@ function extensionNamespaces(harness) {
|
|
|
652
655
|
* argv, and environment values separately. Other hook formats fail closed.
|
|
653
656
|
*/
|
|
654
657
|
export function materializeCandidateProfile(profile, harness, opts = {}) {
|
|
658
|
+
assertMaterializerHarness(harness);
|
|
655
659
|
const candidate = agentCandidateProfileSchema.parse(profile);
|
|
656
660
|
verifyCandidateInlineResources(candidate);
|
|
657
661
|
const hookLowering = lowerCandidateHooks(candidate.hooks, harness);
|
|
@@ -692,7 +696,7 @@ export function materializeCandidateProfile(profile, harness, opts = {}) {
|
|
|
692
696
|
function lowerCandidateHooks(hooks, harness) {
|
|
693
697
|
if (!hooks || Object.keys(hooks).length === 0)
|
|
694
698
|
return { wrapperFiles: [] };
|
|
695
|
-
const nativeHarness =
|
|
699
|
+
const nativeHarness = harness;
|
|
696
700
|
if (nativeHarness !== "codex" && nativeHarness !== "claude-code") {
|
|
697
701
|
return {
|
|
698
702
|
wrapperFiles: [],
|
|
@@ -939,7 +943,7 @@ export function hashWorkspacePlan(plan) {
|
|
|
939
943
|
const env = Object.fromEntries(Object.entries(plan.env).sort(([a], [b]) => compareStrings(a, b)));
|
|
940
944
|
const unsupported = [...plan.unsupported].sort((a, b) => compareStrings(`${a.dimension}\0${a.reason}`, `${b.dimension}\0${b.reason}`));
|
|
941
945
|
const canonical = JSON.stringify({
|
|
942
|
-
harness:
|
|
946
|
+
harness: plan.harness,
|
|
943
947
|
files,
|
|
944
948
|
env,
|
|
945
949
|
flags: [...plan.flags],
|
|
@@ -954,7 +958,7 @@ export function hashWorkspacePlan(plan) {
|
|
|
954
958
|
export function agentCandidateProfilePlanMaterial(plan) {
|
|
955
959
|
const material = {
|
|
956
960
|
sourceProfileDigest: plan.sourceProfileDigest,
|
|
957
|
-
harness:
|
|
961
|
+
harness: plan.harness,
|
|
958
962
|
files: normalizePlanFiles(plan.files).map((file) => ({
|
|
959
963
|
relPath: file.relPath,
|
|
960
964
|
mode: file.mode,
|
|
@@ -1884,7 +1888,7 @@ const GEMINI_HOOK_EVENTS = new Set([
|
|
|
1884
1888
|
"SessionStart",
|
|
1885
1889
|
]);
|
|
1886
1890
|
function hookEventSupported(harness, event) {
|
|
1887
|
-
switch (
|
|
1891
|
+
switch (harness) {
|
|
1888
1892
|
case "claude-code":
|
|
1889
1893
|
return CLAUDE_HOOK_EVENTS.has(event);
|
|
1890
1894
|
case "codex":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-profile-materialize",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Materialize an AgentProfile into the native per-harness workspace files (the one shared materializer for cli-bridge, agent-dev-container, and VB).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@tangle-network/agent-interface": "0.
|
|
19
|
+
"@tangle-network/agent-interface": "0.34.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "25.6.0",
|