@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 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 type HarnessId = "claude-code" | "claude" | "claudish" | "nanoclaw" | "codex" | "opencode" | "kimi-code" | "kimi" | "pi" | "gemini" | "hermes" | "openclaw";
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` (after alias canonicalization: claude/claudish →
161
- * claude-code, kimi → kimi-code). `null` means the harness cannot receive
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
- return canonicalHarness(harness) !== "opencode";
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[canonicalHarness(harness)];
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` (after alias canonicalization: claude/claudish →
161
- * claude-code, kimi → kimi-code). `null` means the harness cannot receive
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
- return HARNESS_SKILL_DIRS[canonicalHarness(harness)];
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 = canonicalHarness(harness);
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
- switch (harness) {
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 = canonicalHarness(harness);
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: canonicalHarness(plan.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: canonicalHarness(plan.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 (canonicalHarness(harness)) {
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.7.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.32.0"
19
+ "@tangle-network/agent-interface": "0.34.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "25.6.0",