@agntk/agent-harness 0.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.
Files changed (212) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +41 -0
  3. package/README.md +445 -0
  4. package/defaults/agents/summarizer.md +49 -0
  5. package/defaults/instincts/lead-with-answer.md +24 -0
  6. package/defaults/instincts/qualify-before-recommending.md +40 -0
  7. package/defaults/instincts/read-before-edit.md +23 -0
  8. package/defaults/instincts/search-before-create.md +23 -0
  9. package/defaults/playbooks/ship-feature.md +31 -0
  10. package/defaults/rules/ask-before-assuming.md +35 -0
  11. package/defaults/rules/operations.md +35 -0
  12. package/defaults/rules/respect-the-user.md +39 -0
  13. package/defaults/skills/business-analyst.md +181 -0
  14. package/defaults/skills/content-marketer.md +184 -0
  15. package/defaults/skills/research.md +34 -0
  16. package/defaults/tools/example-web-search.md +60 -0
  17. package/defaults/workflows/daily-reflection.md +54 -0
  18. package/dist/agent-framework-K4GUIICH.js +344 -0
  19. package/dist/agent-framework-K4GUIICH.js.map +1 -0
  20. package/dist/analytics-RPT73WNM.js +12 -0
  21. package/dist/analytics-RPT73WNM.js.map +1 -0
  22. package/dist/auto-processor-OLE45UI3.js +13 -0
  23. package/dist/auto-processor-OLE45UI3.js.map +1 -0
  24. package/dist/chunk-274RV3YO.js +162 -0
  25. package/dist/chunk-274RV3YO.js.map +1 -0
  26. package/dist/chunk-4CWAGBNS.js +168 -0
  27. package/dist/chunk-4CWAGBNS.js.map +1 -0
  28. package/dist/chunk-4FDUOGSZ.js +69 -0
  29. package/dist/chunk-4FDUOGSZ.js.map +1 -0
  30. package/dist/chunk-5H34JPMB.js +199 -0
  31. package/dist/chunk-5H34JPMB.js.map +1 -0
  32. package/dist/chunk-6EMOEYGU.js +102 -0
  33. package/dist/chunk-6EMOEYGU.js.map +1 -0
  34. package/dist/chunk-A7BJPQQ6.js +236 -0
  35. package/dist/chunk-A7BJPQQ6.js.map +1 -0
  36. package/dist/chunk-AGAAFJEO.js +76 -0
  37. package/dist/chunk-AGAAFJEO.js.map +1 -0
  38. package/dist/chunk-BSKDOFRT.js +65 -0
  39. package/dist/chunk-BSKDOFRT.js.map +1 -0
  40. package/dist/chunk-CHJ5GNZC.js +100 -0
  41. package/dist/chunk-CHJ5GNZC.js.map +1 -0
  42. package/dist/chunk-CSL3ERUI.js +307 -0
  43. package/dist/chunk-CSL3ERUI.js.map +1 -0
  44. package/dist/chunk-DA7IKHC4.js +229 -0
  45. package/dist/chunk-DA7IKHC4.js.map +1 -0
  46. package/dist/chunk-DGUM43GV.js +11 -0
  47. package/dist/chunk-DGUM43GV.js.map +1 -0
  48. package/dist/chunk-DTTXPHFW.js +211 -0
  49. package/dist/chunk-DTTXPHFW.js.map +1 -0
  50. package/dist/chunk-FD55B3IO.js +204 -0
  51. package/dist/chunk-FD55B3IO.js.map +1 -0
  52. package/dist/chunk-FLZU44SV.js +230 -0
  53. package/dist/chunk-FLZU44SV.js.map +1 -0
  54. package/dist/chunk-GJNNR2RA.js +200 -0
  55. package/dist/chunk-GJNNR2RA.js.map +1 -0
  56. package/dist/chunk-GNUSHD2Y.js +111 -0
  57. package/dist/chunk-GNUSHD2Y.js.map +1 -0
  58. package/dist/chunk-GUJTBGVS.js +2212 -0
  59. package/dist/chunk-GUJTBGVS.js.map +1 -0
  60. package/dist/chunk-IZ6UZ3ZL.js +207 -0
  61. package/dist/chunk-IZ6UZ3ZL.js.map +1 -0
  62. package/dist/chunk-JKMGYWXB.js +197 -0
  63. package/dist/chunk-JKMGYWXB.js.map +1 -0
  64. package/dist/chunk-KFX54TQM.js +165 -0
  65. package/dist/chunk-KFX54TQM.js.map +1 -0
  66. package/dist/chunk-M7NXUK55.js +199 -0
  67. package/dist/chunk-M7NXUK55.js.map +1 -0
  68. package/dist/chunk-MPZ3BPUI.js +374 -0
  69. package/dist/chunk-MPZ3BPUI.js.map +1 -0
  70. package/dist/chunk-OC6YSTDX.js +119 -0
  71. package/dist/chunk-OC6YSTDX.js.map +1 -0
  72. package/dist/chunk-RC6MEZB6.js +469 -0
  73. package/dist/chunk-RC6MEZB6.js.map +1 -0
  74. package/dist/chunk-RY3ZFII7.js +3440 -0
  75. package/dist/chunk-RY3ZFII7.js.map +1 -0
  76. package/dist/chunk-TAT6JU3X.js +167 -0
  77. package/dist/chunk-TAT6JU3X.js.map +1 -0
  78. package/dist/chunk-UDZIS2AQ.js +79 -0
  79. package/dist/chunk-UDZIS2AQ.js.map +1 -0
  80. package/dist/chunk-UPLBF4RZ.js +115 -0
  81. package/dist/chunk-UPLBF4RZ.js.map +1 -0
  82. package/dist/chunk-UWQTZMNI.js +154 -0
  83. package/dist/chunk-UWQTZMNI.js.map +1 -0
  84. package/dist/chunk-W4T7PGI2.js +346 -0
  85. package/dist/chunk-W4T7PGI2.js.map +1 -0
  86. package/dist/chunk-XTBKL5BI.js +111 -0
  87. package/dist/chunk-XTBKL5BI.js.map +1 -0
  88. package/dist/chunk-YIJY5DBV.js +399 -0
  89. package/dist/chunk-YIJY5DBV.js.map +1 -0
  90. package/dist/chunk-YUFNYN2H.js +242 -0
  91. package/dist/chunk-YUFNYN2H.js.map +1 -0
  92. package/dist/chunk-Z2PUCXTZ.js +94 -0
  93. package/dist/chunk-Z2PUCXTZ.js.map +1 -0
  94. package/dist/chunk-ZZJOFKAT.js +13 -0
  95. package/dist/chunk-ZZJOFKAT.js.map +1 -0
  96. package/dist/cli/index.js +3661 -0
  97. package/dist/cli/index.js.map +1 -0
  98. package/dist/config-WVMRUOCA.js +13 -0
  99. package/dist/config-WVMRUOCA.js.map +1 -0
  100. package/dist/context-loader-3ORBPMHJ.js +13 -0
  101. package/dist/context-loader-3ORBPMHJ.js.map +1 -0
  102. package/dist/conversation-QDEIDQPH.js +22 -0
  103. package/dist/conversation-QDEIDQPH.js.map +1 -0
  104. package/dist/cost-tracker-RS3W7SVY.js +24 -0
  105. package/dist/cost-tracker-RS3W7SVY.js.map +1 -0
  106. package/dist/delegate-VJCJLYEK.js +29 -0
  107. package/dist/delegate-VJCJLYEK.js.map +1 -0
  108. package/dist/emotional-state-VQVRA6ED.js +206 -0
  109. package/dist/emotional-state-VQVRA6ED.js.map +1 -0
  110. package/dist/env-discovery-2BLVMAIM.js +251 -0
  111. package/dist/env-discovery-2BLVMAIM.js.map +1 -0
  112. package/dist/export-6GCYHEHQ.js +165 -0
  113. package/dist/export-6GCYHEHQ.js.map +1 -0
  114. package/dist/graph-YUIPOSOO.js +14 -0
  115. package/dist/graph-YUIPOSOO.js.map +1 -0
  116. package/dist/harness-LCHA3DWP.js +10 -0
  117. package/dist/harness-LCHA3DWP.js.map +1 -0
  118. package/dist/harness-WE4SLCML.js +26 -0
  119. package/dist/harness-WE4SLCML.js.map +1 -0
  120. package/dist/health-NZ6WNIMV.js +23 -0
  121. package/dist/health-NZ6WNIMV.js.map +1 -0
  122. package/dist/index.d.ts +3612 -0
  123. package/dist/index.js +13501 -0
  124. package/dist/index.js.map +1 -0
  125. package/dist/indexer-LONANRRM.js +16 -0
  126. package/dist/indexer-LONANRRM.js.map +1 -0
  127. package/dist/instinct-learner-SRM72DHF.js +20 -0
  128. package/dist/instinct-learner-SRM72DHF.js.map +1 -0
  129. package/dist/intake-4M3HNU43.js +21 -0
  130. package/dist/intake-4M3HNU43.js.map +1 -0
  131. package/dist/intelligence-HJOCA4SJ.js +1081 -0
  132. package/dist/intelligence-HJOCA4SJ.js.map +1 -0
  133. package/dist/journal-WANJL3MI.js +24 -0
  134. package/dist/journal-WANJL3MI.js.map +1 -0
  135. package/dist/loader-C3TKIKZR.js +23 -0
  136. package/dist/loader-C3TKIKZR.js.map +1 -0
  137. package/dist/mcp-WTQJJZAO.js +15 -0
  138. package/dist/mcp-WTQJJZAO.js.map +1 -0
  139. package/dist/mcp-discovery-WPAQFL6S.js +377 -0
  140. package/dist/mcp-discovery-WPAQFL6S.js.map +1 -0
  141. package/dist/mcp-installer-6O2XXD3V.js +394 -0
  142. package/dist/mcp-installer-6O2XXD3V.js.map +1 -0
  143. package/dist/metrics-KXGNFAAB.js +20 -0
  144. package/dist/metrics-KXGNFAAB.js.map +1 -0
  145. package/dist/primitive-registry-I6VTIR4W.js +512 -0
  146. package/dist/primitive-registry-I6VTIR4W.js.map +1 -0
  147. package/dist/project-discovery-C4UMD7JI.js +246 -0
  148. package/dist/project-discovery-C4UMD7JI.js.map +1 -0
  149. package/dist/provider-LQHQX7Z7.js +26 -0
  150. package/dist/provider-LQHQX7Z7.js.map +1 -0
  151. package/dist/provider-SXPQZ74H.js +28 -0
  152. package/dist/provider-SXPQZ74H.js.map +1 -0
  153. package/dist/rate-limiter-RLRVM325.js +22 -0
  154. package/dist/rate-limiter-RLRVM325.js.map +1 -0
  155. package/dist/rule-engine-YGQ3RYZM.js +182 -0
  156. package/dist/rule-engine-YGQ3RYZM.js.map +1 -0
  157. package/dist/scaffold-A3VRRCBV.js +347 -0
  158. package/dist/scaffold-A3VRRCBV.js.map +1 -0
  159. package/dist/scheduler-XHHIVHRI.js +397 -0
  160. package/dist/scheduler-XHHIVHRI.js.map +1 -0
  161. package/dist/search-V3W5JMJG.js +75 -0
  162. package/dist/search-V3W5JMJG.js.map +1 -0
  163. package/dist/semantic-search-2DTOO5UX.js +241 -0
  164. package/dist/semantic-search-2DTOO5UX.js.map +1 -0
  165. package/dist/serve-DTQ3HENY.js +291 -0
  166. package/dist/serve-DTQ3HENY.js.map +1 -0
  167. package/dist/sessions-CZGVXKQE.js +21 -0
  168. package/dist/sessions-CZGVXKQE.js.map +1 -0
  169. package/dist/sources-RW5DT56F.js +32 -0
  170. package/dist/sources-RW5DT56F.js.map +1 -0
  171. package/dist/starter-packs-76YUVHEU.js +893 -0
  172. package/dist/starter-packs-76YUVHEU.js.map +1 -0
  173. package/dist/state-GMXILIHW.js +13 -0
  174. package/dist/state-GMXILIHW.js.map +1 -0
  175. package/dist/state-merge-NKO5FRBA.js +174 -0
  176. package/dist/state-merge-NKO5FRBA.js.map +1 -0
  177. package/dist/telemetry-UC6PBXC7.js +22 -0
  178. package/dist/telemetry-UC6PBXC7.js.map +1 -0
  179. package/dist/tool-executor-MJ7IG7PQ.js +28 -0
  180. package/dist/tool-executor-MJ7IG7PQ.js.map +1 -0
  181. package/dist/tools-DZ4KETET.js +20 -0
  182. package/dist/tools-DZ4KETET.js.map +1 -0
  183. package/dist/types-EW7AIB3R.js +18 -0
  184. package/dist/types-EW7AIB3R.js.map +1 -0
  185. package/dist/types-WGDLSPO6.js +16 -0
  186. package/dist/types-WGDLSPO6.js.map +1 -0
  187. package/dist/universal-installer-QGS4SJGX.js +578 -0
  188. package/dist/universal-installer-QGS4SJGX.js.map +1 -0
  189. package/dist/validator-7WXMDIHH.js +22 -0
  190. package/dist/validator-7WXMDIHH.js.map +1 -0
  191. package/dist/verification-gate-FYXUX6LH.js +246 -0
  192. package/dist/verification-gate-FYXUX6LH.js.map +1 -0
  193. package/dist/versioning-Z3XNE2Q2.js +271 -0
  194. package/dist/versioning-Z3XNE2Q2.js.map +1 -0
  195. package/dist/watcher-ISJC7YKL.js +109 -0
  196. package/dist/watcher-ISJC7YKL.js.map +1 -0
  197. package/dist/web-server-DD7ZOP46.js +28 -0
  198. package/dist/web-server-DD7ZOP46.js.map +1 -0
  199. package/package.json +76 -0
  200. package/sources.yaml +121 -0
  201. package/templates/assistant/CORE.md +24 -0
  202. package/templates/assistant/SYSTEM.md +24 -0
  203. package/templates/assistant/config.yaml +51 -0
  204. package/templates/base/CORE.md +17 -0
  205. package/templates/base/SYSTEM.md +24 -0
  206. package/templates/base/config.yaml +51 -0
  207. package/templates/claude-opus/config.yaml +51 -0
  208. package/templates/code-reviewer/CORE.md +25 -0
  209. package/templates/code-reviewer/SYSTEM.md +30 -0
  210. package/templates/code-reviewer/config.yaml +51 -0
  211. package/templates/gpt4/config.yaml +51 -0
  212. package/templates/local/config.yaml +51 -0
@@ -0,0 +1,578 @@
1
+ #!/usr/bin/env node
2
+
3
+ import {
4
+ discoverSources
5
+ } from "./chunk-RC6MEZB6.js";
6
+ import {
7
+ downloadCapability,
8
+ fixCapability,
9
+ installCapability
10
+ } from "./chunk-W4T7PGI2.js";
11
+ import "./chunk-4FDUOGSZ.js";
12
+ import "./chunk-Z2PUCXTZ.js";
13
+ import "./chunk-UPLBF4RZ.js";
14
+ import "./chunk-BSKDOFRT.js";
15
+ import "./chunk-4CWAGBNS.js";
16
+ import "./chunk-ZZJOFKAT.js";
17
+
18
+ // src/runtime/universal-installer.ts
19
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, copyFileSync } from "fs";
20
+ import { join, basename, extname } from "path";
21
+ import { tmpdir } from "os";
22
+ import matter from "gray-matter";
23
+ import { parse as parseYaml } from "yaml";
24
+ var VALID_TYPES = ["rule", "instinct", "skill", "playbook", "workflow", "tool", "agent"];
25
+ var TYPE_DIRS = {
26
+ rule: "rules",
27
+ instinct: "instincts",
28
+ skill: "skills",
29
+ playbook: "playbooks",
30
+ workflow: "workflows",
31
+ tool: "tools",
32
+ agent: "agents"
33
+ };
34
+ function detectFormat(content, filename) {
35
+ const ext = extname(filename).toLowerCase();
36
+ const reasons = [];
37
+ let format = "unknown";
38
+ let primitiveType = null;
39
+ let confidence = 0;
40
+ if (ext === ".sh" || ext === ".bash" || content.trimStart().startsWith("#!/")) {
41
+ format = "bash-hook";
42
+ primitiveType = "workflow";
43
+ confidence = 0.9;
44
+ reasons.push("Shell script detected (shebang or .sh extension)");
45
+ if (content.includes("hook") || content.includes("pre-commit") || content.includes("post-")) {
46
+ primitiveType = "workflow";
47
+ reasons.push("Hook pattern detected in content");
48
+ }
49
+ return { format, primitiveType, confidence, reasons };
50
+ }
51
+ if (ext === ".json") {
52
+ try {
53
+ const parsed = JSON.parse(content);
54
+ if (parsed.mcpServers || parsed.servers || parsed.command || parsed.args) {
55
+ format = "mcp-config";
56
+ primitiveType = "tool";
57
+ confidence = 0.9;
58
+ reasons.push("MCP configuration JSON detected");
59
+ return { format, primitiveType, confidence, reasons };
60
+ }
61
+ } catch {
62
+ }
63
+ }
64
+ if (ext === ".faf" || ext === ".yaml" || ext === ".yml") {
65
+ try {
66
+ const parsed = parseYaml(content);
67
+ if (parsed.type && parsed.content) {
68
+ format = "faf-yaml";
69
+ primitiveType = inferTypeFromFafType(String(parsed.type));
70
+ confidence = 0.9;
71
+ reasons.push(`.faf YAML format with type: ${parsed.type}`);
72
+ return { format, primitiveType, confidence, reasons };
73
+ }
74
+ if (parsed.mcpServers || parsed.servers) {
75
+ format = "mcp-config";
76
+ primitiveType = "tool";
77
+ confidence = 0.85;
78
+ reasons.push("MCP configuration YAML detected");
79
+ return { format, primitiveType, confidence, reasons };
80
+ }
81
+ } catch {
82
+ }
83
+ }
84
+ if (ext === ".md" || ext === "" || !ext) {
85
+ try {
86
+ const parsed = matter(content);
87
+ const data = parsed.data;
88
+ if (data.id && data.status) {
89
+ format = "harness";
90
+ confidence = 0.95;
91
+ reasons.push("Harness frontmatter detected (id + status fields)");
92
+ const tags = Array.isArray(data.tags) ? data.tags.map((t) => String(t).toLowerCase()) : [];
93
+ for (const type of VALID_TYPES) {
94
+ if (tags.includes(type)) {
95
+ primitiveType = type;
96
+ break;
97
+ }
98
+ }
99
+ return { format, primitiveType, confidence, reasons };
100
+ }
101
+ if (Object.keys(data).length > 0) {
102
+ format = "raw-markdown";
103
+ confidence = 0.7;
104
+ reasons.push("Markdown with non-harness frontmatter");
105
+ }
106
+ } catch {
107
+ }
108
+ if (format === "unknown" || format === "raw-markdown") {
109
+ const isClaudeSkill = detectClaudeSkillPattern(content, filename);
110
+ if (isClaudeSkill) {
111
+ format = "claude-skill";
112
+ primitiveType = "skill";
113
+ confidence = 0.8;
114
+ reasons.push("Claude Code SKILL.md pattern detected");
115
+ return { format, primitiveType, confidence, reasons };
116
+ }
117
+ }
118
+ if (format === "unknown") {
119
+ format = "raw-markdown";
120
+ confidence = 0.5;
121
+ reasons.push("Plain markdown without frontmatter");
122
+ }
123
+ if (!primitiveType) {
124
+ primitiveType = inferTypeFromContent(content, filename);
125
+ if (primitiveType) {
126
+ reasons.push(`Type inferred from content/filename: ${primitiveType}`);
127
+ }
128
+ }
129
+ return { format, primitiveType, confidence, reasons };
130
+ }
131
+ return { format, primitiveType, confidence, reasons };
132
+ }
133
+ function normalizeToHarness(content, filename, detection, options) {
134
+ const fixes = [];
135
+ const type = options?.type ?? detection.primitiveType;
136
+ switch (detection.format) {
137
+ case "harness":
138
+ return { content, filename, fixes: ["Already in harness format"] };
139
+ case "claude-skill":
140
+ return normalizeClaudeSkill(content, filename, type, options, fixes);
141
+ case "faf-yaml":
142
+ return normalizeFafYaml(content, filename, type, options, fixes);
143
+ case "raw-markdown":
144
+ return normalizeRawMarkdown(content, filename, type, options, fixes);
145
+ case "bash-hook":
146
+ return normalizeBashHook(content, filename, type, options, fixes);
147
+ case "mcp-config":
148
+ return normalizeMcpConfig(content, filename, options, fixes);
149
+ default:
150
+ return normalizeRawMarkdown(content, filename, type, options, fixes);
151
+ }
152
+ }
153
+ function normalizeClaudeSkill(content, filename, type, options, fixes) {
154
+ const id = options?.id ?? deriveId(filename);
155
+ const primitiveType = type ?? "skill";
156
+ const tags = [primitiveType, ...options?.tags ?? []];
157
+ const headingMatch = content.match(/^#\s+(.+)$/m);
158
+ const title = headingMatch ? headingMatch[1].trim() : id;
159
+ const frontmatter = {
160
+ id,
161
+ created: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
162
+ author: "human",
163
+ status: "active",
164
+ tags
165
+ };
166
+ const l0 = title.length > 120 ? title.slice(0, 117) + "..." : title;
167
+ const paragraphs = content.split(/\n{2,}/).filter((p) => {
168
+ const trimmed = p.trim();
169
+ return trimmed.length > 0 && !trimmed.startsWith("#") && !trimmed.startsWith("<!--");
170
+ });
171
+ const l1 = paragraphs.length > 0 ? paragraphs[0].replace(/\n/g, " ").trim().slice(0, 300) : "";
172
+ let body = `<!-- L0: ${l0} -->
173
+ `;
174
+ if (l1) {
175
+ body += `<!-- L1: ${l1} -->
176
+ `;
177
+ }
178
+ body += "\n" + content;
179
+ const result = matter.stringify(body, frontmatter);
180
+ fixes.push("Added harness frontmatter (id, status, tags)");
181
+ fixes.push(`Generated L0 from heading: "${l0}"`);
182
+ if (l1) fixes.push("Generated L1 from first paragraph");
183
+ const outFilename = ensureMdExtension(filename);
184
+ return { content: result, filename: outFilename, fixes };
185
+ }
186
+ function normalizeFafYaml(content, filename, type, options, fixes) {
187
+ let parsed;
188
+ try {
189
+ parsed = parseYaml(content);
190
+ } catch {
191
+ fixes.push("Failed to parse YAML \u2014 treating as raw markdown");
192
+ return normalizeRawMarkdown(content, filename, type, options, fixes);
193
+ }
194
+ const id = options?.id ?? String(parsed.id ?? deriveId(filename));
195
+ const fafType = String(parsed.type ?? "skill");
196
+ const primitiveType = type ?? inferTypeFromFafType(fafType) ?? "skill";
197
+ const title = String(parsed.title ?? parsed.name ?? id);
198
+ const description = String(parsed.description ?? "");
199
+ const fafContent = String(parsed.content ?? "");
200
+ const fafTags = Array.isArray(parsed.tags) ? parsed.tags.map(String) : [];
201
+ const tags = [primitiveType, ...fafTags, ...options?.tags ?? []];
202
+ const frontmatter = {
203
+ id,
204
+ created: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
205
+ author: "human",
206
+ status: "active",
207
+ tags: [...new Set(tags)]
208
+ };
209
+ const l0 = title.length > 120 ? title.slice(0, 117) + "..." : title;
210
+ const l1 = description.length > 300 ? description.slice(0, 297) + "..." : description;
211
+ let body = `<!-- L0: ${l0} -->
212
+ `;
213
+ if (l1) body += `<!-- L1: ${l1} -->
214
+ `;
215
+ body += `
216
+ # ${title}
217
+
218
+ `;
219
+ if (description) body += `${description}
220
+
221
+ `;
222
+ if (fafContent) body += fafContent + "\n";
223
+ const result = matter.stringify(body, frontmatter);
224
+ fixes.push("Converted .faf YAML to harness markdown");
225
+ fixes.push(`Added frontmatter (id: ${id}, type: ${primitiveType})`);
226
+ const outFilename = deriveId(filename) + ".md";
227
+ return { content: result, filename: outFilename, fixes };
228
+ }
229
+ function normalizeRawMarkdown(content, filename, type, options, fixes) {
230
+ const id = options?.id ?? deriveId(filename);
231
+ const primitiveType = type ?? "skill";
232
+ const tags = [primitiveType, ...options?.tags ?? []];
233
+ let parsed;
234
+ try {
235
+ parsed = matter(content);
236
+ } catch {
237
+ parsed = { data: {}, content, orig: "", excerpt: "", language: "", matter: "", stringify: () => "" };
238
+ }
239
+ const data = parsed.data;
240
+ if (options?.id || !data.id) {
241
+ data.id = id;
242
+ fixes.push(`Set id: "${id}"`);
243
+ }
244
+ if (!data.status) {
245
+ data.status = "active";
246
+ fixes.push('Added status: "active"');
247
+ }
248
+ if (!data.created) {
249
+ data.created = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
250
+ fixes.push("Added created date");
251
+ }
252
+ if (!data.author || !["human", "agent", "infrastructure"].includes(String(data.author))) {
253
+ data.author = "human";
254
+ fixes.push('Added author: "human"');
255
+ }
256
+ if (!Array.isArray(data.tags) || data.tags.length === 0) {
257
+ data.tags = [...new Set(tags)];
258
+ fixes.push(`Added tags: [${data.tags.join(", ")}]`);
259
+ }
260
+ let body = parsed.content;
261
+ const l0Regex = /<!--\s*L0:\s*(.*?)\s*-->/;
262
+ if (!l0Regex.test(body)) {
263
+ const headingMatch = body.match(/^#\s+(.+)$/m);
264
+ const firstLine = body.split("\n").find((line) => line.trim().length > 0);
265
+ const summary = headingMatch ? headingMatch[1].trim() : firstLine?.trim() ?? id;
266
+ const l0 = summary.length > 120 ? summary.slice(0, 117) + "..." : summary;
267
+ body = `<!-- L0: ${l0} -->
268
+ ${body}`;
269
+ fixes.push(`Generated L0: "${l0}"`);
270
+ }
271
+ const l1Regex = /<!--\s*L1:\s*([\s\S]*?)\s*-->/;
272
+ if (!l1Regex.test(body)) {
273
+ const paragraphs = body.split(/\n{2,}/).filter((p) => {
274
+ const trimmed = p.trim();
275
+ return trimmed.length > 0 && !trimmed.startsWith("<!--") && !trimmed.startsWith("#");
276
+ });
277
+ if (paragraphs.length > 0) {
278
+ const para = paragraphs[0].replace(/\n/g, " ").trim();
279
+ const l1 = para.length > 300 ? para.slice(0, 297) + "..." : para;
280
+ const l0Pos = body.indexOf("-->");
281
+ if (l0Pos !== -1) {
282
+ const insertPos = l0Pos + 3;
283
+ body = body.slice(0, insertPos) + `
284
+ <!-- L1: ${l1} -->` + body.slice(insertPos);
285
+ } else {
286
+ body = `<!-- L1: ${l1} -->
287
+ ${body}`;
288
+ }
289
+ fixes.push("Generated L1 from first paragraph");
290
+ }
291
+ }
292
+ const result = matter.stringify(body, data);
293
+ const outFilename = ensureMdExtension(filename);
294
+ return { content: result, filename: outFilename, fixes };
295
+ }
296
+ function normalizeBashHook(content, filename, type, options, fixes) {
297
+ const id = options?.id ?? deriveId(filename);
298
+ const primitiveType = type ?? "workflow";
299
+ const tags = [primitiveType, "hook", ...options?.tags ?? []];
300
+ const commentLines = content.split("\n").filter((line) => line.startsWith("#") && !line.startsWith("#!")).map((line) => line.replace(/^#\s?/, "").trim()).filter((line) => line.length > 0);
301
+ const description = commentLines.length > 0 ? commentLines.slice(0, 3).join(" ") : `Bash hook: ${id}`;
302
+ const frontmatter = {
303
+ id,
304
+ created: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
305
+ author: "human",
306
+ status: "active",
307
+ tags: [...new Set(tags)]
308
+ };
309
+ const l0 = description.length > 120 ? description.slice(0, 117) + "..." : description;
310
+ let body = `<!-- L0: ${l0} -->
311
+
312
+ `;
313
+ body += `# ${id}
314
+
315
+ `;
316
+ body += `${description}
317
+
318
+ `;
319
+ body += "```bash\n";
320
+ body += content;
321
+ if (!content.endsWith("\n")) body += "\n";
322
+ body += "```\n";
323
+ const result = matter.stringify(body, frontmatter);
324
+ fixes.push("Wrapped bash script in harness markdown");
325
+ fixes.push(`Added frontmatter (id: ${id}, type: ${primitiveType})`);
326
+ const outFilename = deriveId(filename) + ".md";
327
+ return { content: result, filename: outFilename, fixes };
328
+ }
329
+ function normalizeMcpConfig(content, filename, options, fixes) {
330
+ const id = options?.id ?? deriveId(filename);
331
+ const tags = ["tool", "mcp", ...options?.tags ?? []];
332
+ let config = {};
333
+ const ext = extname(filename).toLowerCase();
334
+ try {
335
+ if (ext === ".json") {
336
+ config = JSON.parse(content);
337
+ } else {
338
+ config = parseYaml(content);
339
+ }
340
+ } catch {
341
+ fixes.push("Failed to parse MCP config");
342
+ }
343
+ const serverName = String(config.name ?? config.command ?? id);
344
+ const description = String(config.description ?? `MCP server: ${serverName}`);
345
+ const frontmatter = {
346
+ id,
347
+ created: (/* @__PURE__ */ new Date()).toISOString().split("T")[0],
348
+ author: "human",
349
+ status: "active",
350
+ tags: [...new Set(tags)]
351
+ };
352
+ const l0 = description.length > 120 ? description.slice(0, 117) + "..." : description;
353
+ let body = `<!-- L0: ${l0} -->
354
+
355
+ `;
356
+ body += `# MCP Server: ${serverName}
357
+
358
+ `;
359
+ body += `${description}
360
+
361
+ `;
362
+ body += "## Configuration\n\n";
363
+ body += "```json\n";
364
+ body += JSON.stringify(config, null, 2);
365
+ body += "\n```\n";
366
+ const result = matter.stringify(body, frontmatter);
367
+ fixes.push("Converted MCP config to harness tool documentation");
368
+ fixes.push(`Added frontmatter (id: ${id})`);
369
+ const outFilename = deriveId(filename) + ".md";
370
+ return { content: result, filename: outFilename, fixes };
371
+ }
372
+ async function resolveSource(source, harnessDir) {
373
+ if (existsSync(source)) {
374
+ return { localPath: source, originalSource: source };
375
+ }
376
+ if (source.startsWith("https://") || source.startsWith("http://")) {
377
+ const rawUrl = convertToRawUrl(source);
378
+ const result = await downloadCapability(rawUrl);
379
+ if (result.downloaded) {
380
+ return { localPath: result.localPath, originalSource: source };
381
+ }
382
+ return { localPath: "", originalSource: source, error: result.error };
383
+ }
384
+ const results = discoverSources(harnessDir, source, { maxResults: 1 });
385
+ if (results.length > 0) {
386
+ const hit = results[0];
387
+ if (hit.source.type === "github") {
388
+ const rawUrl = convertToRawUrl(hit.url);
389
+ const result = await downloadCapability(rawUrl);
390
+ if (result.downloaded) {
391
+ return { localPath: result.localPath, originalSource: source };
392
+ }
393
+ return { localPath: "", originalSource: source, error: result.error };
394
+ }
395
+ return { localPath: "", originalSource: source, error: `Source "${hit.source.name}" is type "${hit.source.type}" \u2014 direct install not yet supported for this type` };
396
+ }
397
+ return { localPath: "", originalSource: source, error: `Could not resolve "${source}" \u2014 not a local file, URL, or known source` };
398
+ }
399
+ async function universalInstall(harnessDir, source, options) {
400
+ const result = {
401
+ installed: false,
402
+ source,
403
+ format: { format: "unknown", primitiveType: null, confidence: 0, reasons: [] },
404
+ destination: "",
405
+ fixes: [],
406
+ errors: [],
407
+ suggestedDependencies: []
408
+ };
409
+ const resolved = await resolveSource(source, harnessDir);
410
+ if (resolved.error || !resolved.localPath) {
411
+ result.errors.push(resolved.error ?? "Failed to resolve source");
412
+ return result;
413
+ }
414
+ let content;
415
+ try {
416
+ content = readFileSync(resolved.localPath, "utf-8");
417
+ } catch (err) {
418
+ result.errors.push(`Failed to read file: ${err instanceof Error ? err.message : String(err)}`);
419
+ return result;
420
+ }
421
+ if (content.trim().length === 0) {
422
+ result.errors.push("File is empty");
423
+ return result;
424
+ }
425
+ const filename = basename(resolved.localPath);
426
+ const detection = detectFormat(content, filename);
427
+ result.format = detection;
428
+ const normalized = normalizeToHarness(content, filename, detection, options);
429
+ result.fixes.push(...normalized.fixes);
430
+ const tempDir = join(tmpdir(), "harness-install");
431
+ mkdirSync(tempDir, { recursive: true });
432
+ const tempPath = join(tempDir, normalized.filename);
433
+ writeFileSync(tempPath, normalized.content, "utf-8");
434
+ if (!options?.skipFix) {
435
+ const fixResult = fixCapability(tempPath);
436
+ result.fixes.push(...fixResult.fixes_applied);
437
+ if (!fixResult.valid && !options?.force) {
438
+ result.errors.push(...fixResult.errors);
439
+ return result;
440
+ }
441
+ }
442
+ const installResult = installCapability(harnessDir, tempPath);
443
+ result.installed = installResult.installed;
444
+ result.destination = installResult.destination;
445
+ if (!installResult.installed) {
446
+ result.errors.push(...installResult.evalResult.errors);
447
+ if (options?.force && detection.primitiveType) {
448
+ const targetDir = join(harnessDir, TYPE_DIRS[detection.primitiveType] ?? "skills");
449
+ if (!existsSync(targetDir)) mkdirSync(targetDir, { recursive: true });
450
+ const dest = join(targetDir, normalized.filename);
451
+ copyFileSync(tempPath, dest);
452
+ result.installed = true;
453
+ result.destination = dest;
454
+ result.fixes.push("Force-installed despite validation errors");
455
+ }
456
+ }
457
+ result.suggestedDependencies = extractDependencyHints(normalized.content);
458
+ return result;
459
+ }
460
+ async function installFromUrl(harnessDir, url, options) {
461
+ return universalInstall(harnessDir, url, options);
462
+ }
463
+ async function installFromFile(harnessDir, filePath, options) {
464
+ return universalInstall(harnessDir, filePath, options);
465
+ }
466
+ function deriveId(filename) {
467
+ const base = basename(filename).replace(/\.(md|faf|yaml|yml|json|sh|bash)$/i, "");
468
+ return base.replace(/[^a-z0-9-]/gi, "-").toLowerCase();
469
+ }
470
+ function ensureMdExtension(filename) {
471
+ if (filename.endsWith(".md")) return filename;
472
+ return deriveId(filename) + ".md";
473
+ }
474
+ function convertToRawUrl(url) {
475
+ if (url.includes("raw.githubusercontent.com")) return url;
476
+ const blobMatch = url.match(
477
+ /^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/blob\/(.+)$/
478
+ );
479
+ if (blobMatch) {
480
+ const [, owner, repo, rest] = blobMatch;
481
+ return `https://raw.githubusercontent.com/${owner}/${repo}/${rest}`;
482
+ }
483
+ return url;
484
+ }
485
+ function detectClaudeSkillPattern(content, filename) {
486
+ const nameLower = filename.toLowerCase();
487
+ if (nameLower === "skill.md" || nameLower.endsWith("-skill.md") || nameLower.endsWith("_skill.md")) {
488
+ return true;
489
+ }
490
+ const patterns = [
491
+ /^#\s+.+skill/im,
492
+ /instructions?\s+for\s+/i,
493
+ /when\s+(the\s+)?user\s+(asks?|wants?|needs?|requests?)/i,
494
+ /you\s+(should|must|will)\s+/i
495
+ ];
496
+ let matches = 0;
497
+ for (const pattern of patterns) {
498
+ if (pattern.test(content)) matches++;
499
+ }
500
+ return matches >= 2 && !content.startsWith("---");
501
+ }
502
+ function inferTypeFromFafType(fafType) {
503
+ const typeMap = {
504
+ skill: "skill",
505
+ agent: "agent",
506
+ rule: "rule",
507
+ playbook: "playbook",
508
+ workflow: "workflow",
509
+ tool: "tool",
510
+ instinct: "instinct",
511
+ hook: "workflow",
512
+ template: "skill",
513
+ plugin: "skill"
514
+ };
515
+ return typeMap[fafType.toLowerCase()] ?? null;
516
+ }
517
+ function inferTypeFromContent(content, filename) {
518
+ const lower = content.toLowerCase();
519
+ const nameLower = filename.toLowerCase();
520
+ if (nameLower.includes("rule")) return "rule";
521
+ if (nameLower.includes("agent")) return "agent";
522
+ if (nameLower.includes("playbook")) return "playbook";
523
+ if (nameLower.includes("workflow")) return "workflow";
524
+ if (nameLower.includes("instinct")) return "instinct";
525
+ if (nameLower.includes("tool")) return "tool";
526
+ if (nameLower.includes("skill")) return "skill";
527
+ if (lower.includes("# rule:") || lower.includes("## rules")) return "rule";
528
+ if (lower.includes("# agent:") || lower.includes("## agent")) return "agent";
529
+ if (lower.includes("# playbook:") || lower.includes("## playbook")) return "playbook";
530
+ if (lower.includes("# skill:") || lower.includes("## skill")) return "skill";
531
+ if (lower.includes("# workflow:") || lower.includes("## workflow")) return "workflow";
532
+ if (lower.includes("# tool:") || lower.includes("## tool")) return "tool";
533
+ return null;
534
+ }
535
+ function extractDependencyHints(content) {
536
+ const hints = [];
537
+ const seen = /* @__PURE__ */ new Set();
538
+ try {
539
+ const parsed = matter(content);
540
+ const data = parsed.data;
541
+ if (Array.isArray(data.requires)) {
542
+ for (const dep of data.requires) {
543
+ if (!seen.has(dep)) {
544
+ hints.push(dep);
545
+ seen.add(dep);
546
+ }
547
+ }
548
+ }
549
+ if (Array.isArray(data.depends)) {
550
+ for (const dep of data.depends) {
551
+ if (!seen.has(dep)) {
552
+ hints.push(dep);
553
+ seen.add(dep);
554
+ }
555
+ }
556
+ }
557
+ if (Array.isArray(data.related)) {
558
+ for (const dep of data.related) {
559
+ if (!seen.has(dep)) {
560
+ hints.push(dep);
561
+ seen.add(dep);
562
+ }
563
+ }
564
+ }
565
+ } catch {
566
+ }
567
+ return hints;
568
+ }
569
+ export {
570
+ convertToRawUrl,
571
+ detectFormat,
572
+ installFromFile,
573
+ installFromUrl,
574
+ normalizeToHarness,
575
+ resolveSource,
576
+ universalInstall
577
+ };
578
+ //# sourceMappingURL=universal-installer-QGS4SJGX.js.map