@ulpi/cli 0.1.5 → 0.1.7

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 (109) hide show
  1. package/README.md +143 -214
  2. package/dist/{auth-PN7TMQHV-2W4ICG64.js → auth-FWM7MM4Q-VZC3U2XZ.js} +1 -1
  3. package/dist/{auth-BFFBUJUC.js → auth-HDK7ECJL.js} +2 -1
  4. package/dist/{chunk-RJIRWQJD.js → chunk-3BCW6ABU.js} +402 -142
  5. package/dist/{chunk-L3PWNHSA.js → chunk-3WB5CXH4.js} +180 -5
  6. package/dist/{chunk-K4OVPFY2.js → chunk-4UCJIAOU.js} +2 -2
  7. package/dist/chunk-4XTHZVDS.js +109 -0
  8. package/dist/chunk-4ZPOZULQ.js +6522 -0
  9. package/dist/{chunk-SIAQVRKG.js → chunk-5MI5GIXM.js} +48 -2
  10. package/dist/{chunk-KLEASXUR.js → chunk-6ZL6NXMV.js} +1 -1
  11. package/dist/{chunk-AV5RB3N2.js → chunk-76D3BYJD.js} +48 -0
  12. package/dist/{chunk-DOIKS6C5.js → chunk-AWOSRA5F.js} +1 -1
  13. package/dist/{chunk-UCMT5OKP.js → chunk-BFEKZZHM.js} +274 -57
  14. package/dist/chunk-C7CLUQI6.js +1286 -0
  15. package/dist/{chunk-ELTGWMDE.js → chunk-E3B5NROU.js} +7 -7
  16. package/dist/chunk-EJ7TW77N.js +1418 -0
  17. package/dist/{chunk-P2RESJRN.js → chunk-EWLYVXQ4.js} +2 -2
  18. package/dist/{chunk-6OURRFP7.js → chunk-IV6MWETF.js} +383 -168
  19. package/dist/chunk-IZPJHSPX.js +1478 -0
  20. package/dist/chunk-JLHNLM3C.js +228 -0
  21. package/dist/chunk-PO4NUZUU.js +147 -0
  22. package/dist/chunk-S6ANCSYO.js +1271 -0
  23. package/dist/chunk-SEU7WWNQ.js +1251 -0
  24. package/dist/chunk-SNQ7NAIS.js +453 -0
  25. package/dist/{ulpi-RMMCUAGP-EWYUE7RU.js → chunk-TSLDGT5O.js} +73 -35
  26. package/dist/{chunk-EIWYSP3A.js → chunk-UXHCHOWQ.js} +83 -62
  27. package/dist/chunk-WED4LM5N.js +322 -0
  28. package/dist/chunk-WVOZE25N.js +6757 -0
  29. package/dist/{chunk-5SCG7UYM.js → chunk-XKF4DPUM.js} +7 -7
  30. package/dist/{chunk-74WVVWJ4.js → chunk-YOKL7RB5.js} +184 -15
  31. package/dist/chunk-Z53CAR7G.js +298 -0
  32. package/dist/{ci-JQ56YIKC.js → ci-COZRTPGQ.js} +124 -26
  33. package/dist/cloud-2F3NLVHN.js +274 -0
  34. package/dist/{codemap-HMYBXJL2.js → codemap-XNGMAF3F.js} +37 -37
  35. package/dist/codex-MB5YTMRT.js +132 -0
  36. package/dist/{config-YYWEN7U2.js → config-OOELBYTH.js} +1 -1
  37. package/dist/dist-2BJYR5EI.js +59 -0
  38. package/dist/dist-3EIQTZHT.js +1380 -0
  39. package/dist/{dist-WAMAQVPK.js → dist-4U5L2X2C.js} +2 -2
  40. package/dist/{dist-4XTJ6HLM.js → dist-54KAMNLO.js} +16 -15
  41. package/dist/dist-6M4MZWZW.js +58 -0
  42. package/dist/dist-6X576SU2.js +27 -0
  43. package/dist/dist-7QOEYLFX.js +103 -0
  44. package/dist/dist-AYBGHEDY.js +2541 -0
  45. package/dist/dist-EK45QNEM.js +45 -0
  46. package/dist/{dist-U7ZIJMZD.js → dist-FKFEJRPX.js} +16 -15
  47. package/dist/dist-GTEJUBBT.js +66 -0
  48. package/dist/dist-HA74OKJZ.js +40 -0
  49. package/dist/{dist-XG2GG5SD.js → dist-HU5RZAON.js} +14 -2
  50. package/dist/dist-IYE3OBRB.js +374 -0
  51. package/dist/{dist-7WLLPWWB.js → dist-JLU26AB6.js} +12 -9
  52. package/dist/{dist-6G7JC2RA.js → dist-KUCI6JFE.js} +49 -9
  53. package/dist/dist-NUEMFZFL.js +33 -0
  54. package/dist/{dist-GWGTAHNM.js → dist-NUXMDXZ3.js} +31 -3
  55. package/dist/{dist-5R4RYNQO.js → dist-YCNWHSLN.js} +15 -5
  56. package/dist/{dist-6MFVWIFF.js → dist-YFFG2ZD6.js} +9 -16
  57. package/dist/dist-ZG4OKCSR.js +15 -0
  58. package/dist/doctor-FKYSIHER.js +345 -0
  59. package/dist/{export-import-4A5MWLIA.js → export-import-JFQH4KSJ.js} +1 -1
  60. package/dist/{history-RNUWO4JZ.js → history-UMGQNQQ7.js} +7 -7
  61. package/dist/{hooks-installer-K2JXEBNN.js → hooks-installer-YEYTYA6Q.js} +2 -2
  62. package/dist/index.js +398 -622
  63. package/dist/{init-NQWFZPKO.js → init-TJYW5ROZ.js} +78 -12
  64. package/dist/job-HIDMAFW2.js +376 -0
  65. package/dist/jobs.memory-PLMMSFHB-VBECCTHN.js +33 -0
  66. package/dist/kiro-VMUHDFGK.js +153 -0
  67. package/dist/{launchd-OYXUAVW6.js → launchd-U3MSWBRH.js} +9 -17
  68. package/dist/mcp-PDUD7SGP.js +249 -0
  69. package/dist/mcp-installer-PQU3XOGO.js +259 -0
  70. package/dist/mcp-setup-OA7IB3H3.js +263 -0
  71. package/dist/{memory-D6ZFFCI2.js → memory-ZNAEAK3B.js} +17 -17
  72. package/dist/{ollama-3XCUZMZT-FYKHW4TZ.js → ollama-3XCUZMZT-4JMH6B7P.js} +1 -1
  73. package/dist/{openai-E7G2YAHU-IG33BFYF.js → openai-E7G2YAHU-T3HMBPH7.js} +2 -2
  74. package/dist/portal-JYWVHXDU.js +210 -0
  75. package/dist/prd-Q4J5NVAR.js +408 -0
  76. package/dist/repos-WWZXNN3P.js +271 -0
  77. package/dist/review-integration-RQE4KMAV.js +14 -0
  78. package/dist/{rules-3OFGWHP4.js → rules-Y4VSOY5Y.js} +3 -3
  79. package/dist/run-VPNXEIBY.js +687 -0
  80. package/dist/server-COL4AXKU-P7S7NNF6.js +11 -0
  81. package/dist/server-U7PQ6FTS-MG4MJPTS.js +20 -0
  82. package/dist/{skills-GY2CTPWN.js → skills-QEYU2N27.js} +4 -2
  83. package/dist/start-IJKY5RVT.js +303 -0
  84. package/dist/{status-SE43TIFJ.js → status-BHQYYGAL.js} +2 -2
  85. package/dist/{templates-O2XDKB5R.js → templates-CBRUJ66V.js} +6 -5
  86. package/dist/tui-DP7736EX.js +61 -0
  87. package/dist/ulpi-5EN6JCAS-LFE3WSL4.js +10 -0
  88. package/dist/{uninstall-KWGSGZTI.js → uninstall-BX6FOV77.js} +3 -3
  89. package/dist/{update-QYZA4D23.js → update-AQKTHFVQ.js} +3 -3
  90. package/dist/{version-checker-MVB74DEX.js → version-checker-5L5PUOEX.js} +2 -2
  91. package/package.json +13 -4
  92. package/dist/chunk-26LLDX2T.js +0 -553
  93. package/dist/chunk-DDRLI6JU.js +0 -331
  94. package/dist/chunk-IFATANHR.js +0 -453
  95. package/dist/chunk-JWUUVXIV.js +0 -13694
  96. package/dist/chunk-LD52XG3X.js +0 -4273
  97. package/dist/chunk-MIAQVCFW.js +0 -39
  98. package/dist/chunk-YYZOFYS6.js +0 -415
  99. package/dist/dist-XD4YI27T.js +0 -26
  100. package/dist/mcp-installer-TOYDP77X.js +0 -124
  101. package/dist/projects-COUJP4ZC.js +0 -271
  102. package/dist/review-KMGP2S25.js +0 -152
  103. package/dist/server-USLHY6GH-F4JSXCWA.js +0 -18
  104. package/dist/server-X5P6WH2M-ULZF5WHZ.js +0 -11
  105. package/dist/ui-4SM2SUI6.js +0 -167
  106. package/dist/ui.html +0 -698
  107. /package/dist/skills/{ulpi-generate-guardian → ulpi-generate-guards}/SKILL.md +0 -0
  108. /package/dist/skills/{ulpi-generate-guardian → ulpi-generate-guards}/references/framework-rules.md +0 -0
  109. /package/dist/skills/{ulpi-generate-guardian → ulpi-generate-guards}/references/language-rules.md +0 -0
@@ -0,0 +1,453 @@
1
+ import {
2
+ getBinaryPath
3
+ } from "./chunk-C7CLUQI6.js";
4
+
5
+ // ../../packages/agent-converter/dist/index.js
6
+ import * as fs from "fs";
7
+ import * as path from "path";
8
+ import * as fs2 from "fs";
9
+ import * as path2 from "path";
10
+ import * as fs4 from "fs";
11
+ import * as path4 from "path";
12
+ import * as fs3 from "fs";
13
+ import * as path3 from "path";
14
+ var CLAUDE_ONLY_SKILLS = /* @__PURE__ */ new Set([
15
+ "update-claude-settings",
16
+ "update-skill-learnings",
17
+ "update-agent-learnings"
18
+ ]);
19
+ var ADAPTABLE_SKILLS = /* @__PURE__ */ new Set([
20
+ "start",
21
+ "update-claude-learnings",
22
+ "update-claude-md-after-install",
23
+ "update-claude-md-after-install-monorepo"
24
+ ]);
25
+ function parseClaudeAgentFrontmatter(content) {
26
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
27
+ if (!fmMatch) {
28
+ return { name: "", description: "", tools: [], model: "", body: content };
29
+ }
30
+ const yaml = fmMatch[1];
31
+ const body = fmMatch[2];
32
+ const getField = (key) => {
33
+ const m = yaml.match(new RegExp(`^${key}:\\s*(.+)$`, "m"));
34
+ return m ? m[1].trim() : "";
35
+ };
36
+ const toolsRaw = getField("tools");
37
+ const tools = toolsRaw ? toolsRaw.split(",").map((t) => t.trim()).filter(Boolean) : [];
38
+ return {
39
+ name: getField("name"),
40
+ description: getField("description"),
41
+ tools,
42
+ model: getField("model"),
43
+ body
44
+ };
45
+ }
46
+ function copyDirRecursive(src, dest) {
47
+ fs.mkdirSync(dest, { recursive: true });
48
+ const entries = fs.readdirSync(src, { withFileTypes: true });
49
+ for (const entry of entries) {
50
+ const srcPath = path.join(src, entry.name);
51
+ const destPath = path.join(dest, entry.name);
52
+ if (entry.isDirectory()) {
53
+ copyDirRecursive(srcPath, destPath);
54
+ } else {
55
+ fs.copyFileSync(srcPath, destPath);
56
+ }
57
+ }
58
+ }
59
+ function adaptContentForKiro(content, skillName) {
60
+ let out = content;
61
+ out = out.replace(/\.claude\/skills\//g, ".kiro/skills/");
62
+ out = out.replace(/\.claude\/claude-md-refs\//g, ".kiro/docs/");
63
+ out = out.replace(/\.claude\/plans\//g, ".kiro/plans/");
64
+ out = out.replace(/\.claude\/agents\//g, ".kiro/agents/");
65
+ out = out.replace(/`\.claude\//g, "`.kiro/");
66
+ out = out.replace(/@\.claude\//g, ".kiro/");
67
+ out = out.replace(/CLAUDE\.md/g, "KIRO.md");
68
+ out = out.replace(/claude-md-refs/g, "kiro-docs");
69
+ out = out.replace(
70
+ /[Uu]se the Skill tool to (?:invoke|read|run|load) (?:it|the skill(?: file)?)/g,
71
+ "Read the skill from .kiro/skills/"
72
+ );
73
+ out = out.replace(/\bSkill tool\b/g, "skill resources");
74
+ out = out.replace(/\bTodoWrite\b/g, "task tracking");
75
+ out = out.replace(/\bAskUserQuestion\b/g, "user prompting");
76
+ out = out.replace(
77
+ /Use the Task tool with `subagent_type=\[([^\]]+)\]`/g,
78
+ "Delegate to the $1 specialist"
79
+ );
80
+ out = out.replace(/\bTask tool\b/g, "agent delegation");
81
+ out = out.replace(/@imports?\b/g, "file imports");
82
+ out = out.replace(/Claude Code/g, "Kiro");
83
+ out = out.replace(/\bClaude\b/g, "Kiro");
84
+ out = out.replace(/\/update-claude-learnings/g, "/update-kiro-learnings");
85
+ out = out.replace(/\/update-claude-md-after-install-monorepo/g, "/update-kiro-docs-monorepo");
86
+ out = out.replace(/\/update-claude-md-after-install/g, "/update-kiro-docs-after-install");
87
+ out = out.replace(/`update-claude-learnings`/g, "`update-kiro-learnings`");
88
+ out = out.replace(/`update-claude-md-after-install-monorepo`/g, "`update-kiro-docs-monorepo`");
89
+ out = out.replace(/`update-claude-md-after-install`/g, "`update-kiro-docs-after-install`");
90
+ if (skillName === "update-claude-md-after-install") {
91
+ out = out.replace(
92
+ /^(---\nname: )update-claude-md-after-install$/m,
93
+ "$1update-kiro-docs-after-install"
94
+ );
95
+ } else if (skillName === "update-claude-md-after-install-monorepo") {
96
+ out = out.replace(
97
+ /^(---\nname: )update-claude-md-after-install-monorepo$/m,
98
+ "$1update-kiro-docs-monorepo"
99
+ );
100
+ } else if (skillName === "update-claude-learnings") {
101
+ out = out.replace(
102
+ /^(---\nname: )update-claude-learnings$/m,
103
+ "$1update-kiro-learnings"
104
+ );
105
+ }
106
+ return out;
107
+ }
108
+ function adaptContentForCodex(content) {
109
+ let out = content;
110
+ out = out.replace(/\.claude\/skills\//g, ".codex/skills/");
111
+ out = out.replace(/\.claude\/claude-md-refs\//g, ".codex/docs/");
112
+ out = out.replace(/\.claude\/plans\//g, ".codex/plans/");
113
+ out = out.replace(/\.claude\/agents\//g, ".codex/agents/");
114
+ out = out.replace(/`\.claude\//g, "`.codex/");
115
+ out = out.replace(/@\.claude\//g, ".codex/");
116
+ out = out.replace(/CLAUDE\.md/g, "AGENTS.md");
117
+ out = out.replace(/claude-md-refs/g, "codex-docs");
118
+ out = out.replace(
119
+ /[Uu]se the Skill tool to (?:invoke|read|run|load) (?:it|the skill(?: file)?)/g,
120
+ "Read the skill from .codex/skills/"
121
+ );
122
+ out = out.replace(/\bSkill tool\b/g, "skill resources");
123
+ out = out.replace(/\bTodoWrite\b/g, "task tracking");
124
+ out = out.replace(/\bAskUserQuestion\b/g, "user prompting");
125
+ out = out.replace(
126
+ /Use the Task tool with `subagent_type=\[([^\]]+)\]`/g,
127
+ "Delegate to the $1 specialist"
128
+ );
129
+ out = out.replace(/\bTask tool\b/g, "agent delegation");
130
+ out = out.replace(/@imports?\b/g, "file imports");
131
+ out = out.replace(/Claude Code/g, "Codex");
132
+ out = out.replace(/\bClaude\b/g, "Codex");
133
+ out = out.replace(/\/update-claude-learnings/g, "/update-codex-learnings");
134
+ out = out.replace(/\/update-claude-md-after-install-monorepo/g, "/update-codex-docs-monorepo");
135
+ out = out.replace(/\/update-claude-md-after-install/g, "/update-codex-docs-after-install");
136
+ out = out.replace(/`update-claude-learnings`/g, "`update-codex-learnings`");
137
+ out = out.replace(/`update-claude-md-after-install-monorepo`/g, "`update-codex-docs-monorepo`");
138
+ out = out.replace(/`update-claude-md-after-install`/g, "`update-codex-docs-after-install`");
139
+ return out;
140
+ }
141
+ function kiroSkillsDir(projectDir) {
142
+ return path2.join(projectDir, ".kiro", "skills");
143
+ }
144
+ function buildHooks() {
145
+ const binary = getBinaryPath();
146
+ return {
147
+ agentSpawn: [{ command: `${binary} session-start` }],
148
+ preToolUse: [{ matcher: "*", command: `${binary} pre-tool` }],
149
+ postToolUse: [{ matcher: "*", command: `${binary} post-tool` }],
150
+ stop: [{ command: `${binary} stop` }]
151
+ };
152
+ }
153
+ function buildMcpServers() {
154
+ const binary = getBinaryPath();
155
+ return {
156
+ "ulpi-codemap": {
157
+ command: binary,
158
+ args: ["codemap", "serve"],
159
+ transportType: "stdio"
160
+ },
161
+ "ulpi-memory": {
162
+ command: binary,
163
+ args: ["memory", "serve"],
164
+ transportType: "stdio"
165
+ }
166
+ };
167
+ }
168
+ function mapClaudeToolsToKiro(tools) {
169
+ const TOOL_MAP = {
170
+ Read: "read",
171
+ Glob: "read",
172
+ Grep: "read",
173
+ Write: "write",
174
+ Edit: "write",
175
+ Bash: "shell",
176
+ BashOutput: "shell",
177
+ KillShell: "shell",
178
+ WebFetch: "browser",
179
+ WebSearch: "browser"
180
+ };
181
+ const kiroTools = /* @__PURE__ */ new Set();
182
+ for (const tool of tools) {
183
+ const mapped = TOOL_MAP[tool];
184
+ if (mapped) kiroTools.add(mapped);
185
+ }
186
+ return [...kiroTools];
187
+ }
188
+ function extractKiroMcpServers(tools) {
189
+ const mcpTools = tools.filter((t) => t.startsWith("mcp__"));
190
+ if (mcpTools.length === 0) return {};
191
+ const serverNames = /* @__PURE__ */ new Set();
192
+ for (const tool of mcpTools) {
193
+ const parts = tool.split("__");
194
+ if (parts.length >= 2) serverNames.add(parts[1]);
195
+ }
196
+ const KNOWN_SERVERS2 = {
197
+ context7: {
198
+ command: "npx",
199
+ args: ["-y", "@anthropic-ai/context7-mcp@latest"],
200
+ transportType: "stdio"
201
+ }
202
+ };
203
+ const result = {};
204
+ for (const name of serverNames) {
205
+ if (name === "codemap" || name === "memory") continue;
206
+ if (KNOWN_SERVERS2[name]) {
207
+ result[name] = KNOWN_SERVERS2[name];
208
+ }
209
+ }
210
+ return result;
211
+ }
212
+ function convertClaudeSkillsToKiro(projectDir) {
213
+ const claudeSkillsDir = path2.join(projectDir, ".claude", "skills");
214
+ if (!fs2.existsSync(claudeSkillsDir)) return 0;
215
+ const destDir = kiroSkillsDir(projectDir);
216
+ let count = 0;
217
+ const entries = fs2.readdirSync(claudeSkillsDir, { withFileTypes: true });
218
+ for (const entry of entries) {
219
+ if (!entry.isDirectory()) continue;
220
+ if (CLAUDE_ONLY_SKILLS.has(entry.name)) continue;
221
+ const srcSkillDir = path2.join(claudeSkillsDir, entry.name);
222
+ const srcSkillMd = path2.join(srcSkillDir, "SKILL.md");
223
+ if (!fs2.existsSync(srcSkillMd)) continue;
224
+ const destSkillDir = path2.join(destDir, entry.name);
225
+ const destSkillMd = path2.join(destSkillDir, "SKILL.md");
226
+ if (fs2.existsSync(destSkillMd)) continue;
227
+ fs2.mkdirSync(destSkillDir, { recursive: true });
228
+ if (ADAPTABLE_SKILLS.has(entry.name)) {
229
+ const raw = fs2.readFileSync(srcSkillMd, "utf-8");
230
+ const adapted = adaptContentForKiro(raw, entry.name);
231
+ fs2.writeFileSync(destSkillMd, adapted, "utf-8");
232
+ } else {
233
+ fs2.copyFileSync(srcSkillMd, destSkillMd);
234
+ }
235
+ const srcRefs = path2.join(srcSkillDir, "references");
236
+ if (fs2.existsSync(srcRefs) && fs2.statSync(srcRefs).isDirectory()) {
237
+ const destRefs = path2.join(destSkillDir, "references");
238
+ copyDirRecursive(srcRefs, destRefs);
239
+ }
240
+ count++;
241
+ }
242
+ return count;
243
+ }
244
+ function convertClaudeAgentsToKiro(projectDir) {
245
+ const claudeAgentsDir = path2.join(projectDir, ".claude", "agents");
246
+ if (!fs2.existsSync(claudeAgentsDir)) return 0;
247
+ const kiroAgentsBase = path2.join(projectDir, ".kiro", "agents");
248
+ let count = 0;
249
+ const entries = fs2.readdirSync(claudeAgentsDir, { withFileTypes: true });
250
+ for (const entry of entries) {
251
+ if (entry.isDirectory()) continue;
252
+ if (!entry.name.endsWith(".md")) continue;
253
+ const agentName = entry.name.replace(/\.md$/, "");
254
+ const kiroAgentJson = path2.join(kiroAgentsBase, `${agentName}.json`);
255
+ if (fs2.existsSync(kiroAgentJson)) continue;
256
+ const raw = fs2.readFileSync(path2.join(claudeAgentsDir, entry.name), "utf-8");
257
+ const parsed = parseClaudeAgentFrontmatter(raw);
258
+ if (!parsed.name) continue;
259
+ const kiroTools = mapClaudeToolsToKiro(parsed.tools);
260
+ const externalMcps = extractKiroMcpServers(parsed.tools);
261
+ const adaptedBody = adaptContentForKiro(parsed.body, agentName);
262
+ const agentConfig = {
263
+ name: parsed.name,
264
+ description: parsed.description,
265
+ tools: kiroTools.length > 0 ? kiroTools : ["read", "write", "shell"],
266
+ allowedTools: ["read"],
267
+ hooks: buildHooks(),
268
+ resources: [
269
+ `file://.kiro/agents/${agentName}/prompt.md`,
270
+ "skill://.kiro/skills/*/SKILL.md",
271
+ "file://.ulpi/guards.yml"
272
+ ],
273
+ mcpServers: { ...buildMcpServers(), ...externalMcps }
274
+ };
275
+ fs2.mkdirSync(kiroAgentsBase, { recursive: true });
276
+ fs2.writeFileSync(kiroAgentJson, JSON.stringify(agentConfig, null, 2) + "\n", "utf-8");
277
+ const promptDir = path2.join(kiroAgentsBase, agentName);
278
+ fs2.mkdirSync(promptDir, { recursive: true });
279
+ fs2.writeFileSync(path2.join(promptDir, "prompt.md"), adaptedBody, "utf-8");
280
+ count++;
281
+ }
282
+ return count;
283
+ }
284
+ function serializeTomlTable(data) {
285
+ const lines = [];
286
+ for (const [key, value] of Object.entries(data)) {
287
+ if (Array.isArray(value)) {
288
+ const items = value.map((v) => `"${v}"`).join(", ");
289
+ lines.push(`${key} = [${items}]`);
290
+ } else if (typeof value === "string") {
291
+ lines.push(`${key} = "${value}"`);
292
+ } else {
293
+ lines.push(`${key} = ${value}`);
294
+ }
295
+ }
296
+ return lines.join("\n");
297
+ }
298
+ function appendTomlSection(filePath, sectionHeader, data) {
299
+ let content = "";
300
+ if (fs3.existsSync(filePath)) {
301
+ content = fs3.readFileSync(filePath, "utf-8");
302
+ }
303
+ if (content.includes(`[${sectionHeader}]`)) {
304
+ return false;
305
+ }
306
+ const section = `
307
+ [${sectionHeader}]
308
+ ${serializeTomlTable(data)}
309
+ `;
310
+ content += section;
311
+ const dir = path3.dirname(filePath);
312
+ fs3.mkdirSync(dir, { recursive: true });
313
+ fs3.writeFileSync(filePath, content, "utf-8");
314
+ return true;
315
+ }
316
+ function mapClaudeModelToCodex(model) {
317
+ switch (model.toLowerCase()) {
318
+ case "opus":
319
+ return { model: "gpt-5.3-codex", effort: "high" };
320
+ case "sonnet":
321
+ return { model: "gpt-5.3-codex", effort: "medium" };
322
+ case "haiku":
323
+ return { model: "gpt-5-codex-mini", effort: "medium" };
324
+ default:
325
+ return { model: "gpt-5.3-codex", effort: "medium" };
326
+ }
327
+ }
328
+ function inferSandboxMode(tools) {
329
+ const hasWrite = tools.some((t) => ["Write", "Edit", "Bash", "BashOutput", "KillShell"].includes(t));
330
+ if (!hasWrite) {
331
+ const hasRead = tools.some((t) => ["Read", "Glob", "Grep"].includes(t));
332
+ if (hasRead) return "read-only";
333
+ }
334
+ return "workspace-write";
335
+ }
336
+ var KNOWN_SERVERS = {
337
+ context7: { command: "npx", args: ["-y", "@anthropic-ai/context7-mcp@latest"] }
338
+ };
339
+ function extractCodexMcpServers(tools) {
340
+ const mcpTools = tools.filter((t) => t.startsWith("mcp__"));
341
+ if (mcpTools.length === 0) return {};
342
+ const serverNames = /* @__PURE__ */ new Set();
343
+ for (const tool of mcpTools) {
344
+ const parts = tool.split("__");
345
+ if (parts.length >= 2) serverNames.add(parts[1]);
346
+ }
347
+ const result = {};
348
+ for (const name of serverNames) {
349
+ if (name === "codemap" || name === "memory") continue;
350
+ if (KNOWN_SERVERS[name]) {
351
+ result[name] = KNOWN_SERVERS[name];
352
+ }
353
+ }
354
+ return result;
355
+ }
356
+ function convertClaudeAgentsToCodex(projectDir) {
357
+ const claudeAgentsDir = path4.join(projectDir, ".claude", "agents");
358
+ if (!fs4.existsSync(claudeAgentsDir)) return 0;
359
+ const codexAgentsBase = path4.join(projectDir, ".codex", "agents");
360
+ const configToml = path4.join(projectDir, ".codex", "config.toml");
361
+ let count = 0;
362
+ const entries = fs4.readdirSync(claudeAgentsDir, { withFileTypes: true });
363
+ for (const entry of entries) {
364
+ if (entry.isDirectory()) continue;
365
+ if (!entry.name.endsWith(".md")) continue;
366
+ const agentName = entry.name.replace(/\.md$/, "");
367
+ const codexAgentToml = path4.join(codexAgentsBase, `${agentName}.toml`);
368
+ if (fs4.existsSync(codexAgentToml)) continue;
369
+ const raw = fs4.readFileSync(path4.join(claudeAgentsDir, entry.name), "utf-8");
370
+ const parsed = parseClaudeAgentFrontmatter(raw);
371
+ if (!parsed.name) continue;
372
+ const { model, effort } = mapClaudeModelToCodex(parsed.model);
373
+ const sandbox = inferSandboxMode(parsed.tools);
374
+ const adaptedBody = adaptContentForCodex(parsed.body);
375
+ fs4.mkdirSync(codexAgentsBase, { recursive: true });
376
+ const agentTomlContent = [
377
+ `model = "${model}"`,
378
+ `model_reasoning_effort = "${effort}"`,
379
+ `sandbox_mode = "${sandbox}"`,
380
+ `model_instructions_file = "agents/${agentName}/instructions.md"`,
381
+ ""
382
+ ].join("\n");
383
+ fs4.writeFileSync(codexAgentToml, agentTomlContent, "utf-8");
384
+ const instructionsDir = path4.join(codexAgentsBase, agentName);
385
+ fs4.mkdirSync(instructionsDir, { recursive: true });
386
+ fs4.writeFileSync(path4.join(instructionsDir, "instructions.md"), adaptedBody, "utf-8");
387
+ appendTomlSection(configToml, `agents.${agentName}`, {
388
+ description: parsed.description,
389
+ config_file: `agents/${agentName}.toml`
390
+ });
391
+ const externalMcps = extractCodexMcpServers(parsed.tools);
392
+ for (const [name, mcpEntry] of Object.entries(externalMcps)) {
393
+ appendTomlSection(configToml, `mcp_servers.${name}`, {
394
+ command: mcpEntry.command,
395
+ args: mcpEntry.args
396
+ });
397
+ }
398
+ count++;
399
+ }
400
+ return count;
401
+ }
402
+ function convertClaudeSkillsToCodex(projectDir) {
403
+ const claudeSkillsDir = path4.join(projectDir, ".claude", "skills");
404
+ if (!fs4.existsSync(claudeSkillsDir)) return 0;
405
+ const destDir = path4.join(projectDir, ".codex", "skills");
406
+ let count = 0;
407
+ const entries = fs4.readdirSync(claudeSkillsDir, { withFileTypes: true });
408
+ for (const entry of entries) {
409
+ if (!entry.isDirectory()) continue;
410
+ if (CLAUDE_ONLY_SKILLS.has(entry.name)) continue;
411
+ const srcSkillDir = path4.join(claudeSkillsDir, entry.name);
412
+ const srcSkillMd = path4.join(srcSkillDir, "SKILL.md");
413
+ if (!fs4.existsSync(srcSkillMd)) continue;
414
+ const destSkillDir = path4.join(destDir, entry.name);
415
+ const destSkillMd = path4.join(destSkillDir, "SKILL.md");
416
+ if (fs4.existsSync(destSkillMd)) continue;
417
+ fs4.mkdirSync(destSkillDir, { recursive: true });
418
+ if (ADAPTABLE_SKILLS.has(entry.name)) {
419
+ const raw = fs4.readFileSync(srcSkillMd, "utf-8");
420
+ const adapted = adaptContentForCodex(raw);
421
+ fs4.writeFileSync(destSkillMd, adapted, "utf-8");
422
+ } else {
423
+ fs4.copyFileSync(srcSkillMd, destSkillMd);
424
+ }
425
+ const srcRefs = path4.join(srcSkillDir, "references");
426
+ if (fs4.existsSync(srcRefs) && fs4.statSync(srcRefs).isDirectory()) {
427
+ const destRefs = path4.join(destSkillDir, "references");
428
+ copyDirRecursive(srcRefs, destRefs);
429
+ }
430
+ count++;
431
+ }
432
+ return count;
433
+ }
434
+
435
+ export {
436
+ CLAUDE_ONLY_SKILLS,
437
+ ADAPTABLE_SKILLS,
438
+ parseClaudeAgentFrontmatter,
439
+ copyDirRecursive,
440
+ adaptContentForKiro,
441
+ adaptContentForCodex,
442
+ mapClaudeToolsToKiro,
443
+ extractKiroMcpServers,
444
+ convertClaudeSkillsToKiro,
445
+ convertClaudeAgentsToKiro,
446
+ serializeTomlTable,
447
+ appendTomlSection,
448
+ mapClaudeModelToCodex,
449
+ inferSandboxMode,
450
+ extractCodexMcpServers,
451
+ convertClaudeAgentsToCodex,
452
+ convertClaudeSkillsToCodex
453
+ };
@@ -1,10 +1,9 @@
1
1
  import {
2
2
  resolveApiKey,
3
3
  resolveUlpiUrl
4
- } from "./chunk-DDRLI6JU.js";
5
- import "./chunk-4VNS5WPM.js";
4
+ } from "./chunk-C7CLUQI6.js";
6
5
 
7
- // ../../packages/codemap-engine/dist/ulpi-RMMCUAGP.js
6
+ // ../../packages/embed-engine/dist/chunk-EW7O4NSJ.js
8
7
  var MAX_RETRIES = 3;
9
8
  var RETRY_BASE_MS = 1e3;
10
9
  var BATCH_POLL_INTERVAL_MS = 2e3;
@@ -39,7 +38,8 @@ var UlpiEmbedder = class {
39
38
  const response = await fetch(`${this.baseUrl}/api/v1/embeddings`, {
40
39
  method: "POST",
41
40
  headers: this.headers,
42
- body: JSON.stringify(body)
41
+ body: JSON.stringify(body),
42
+ redirect: "error"
43
43
  });
44
44
  if (!response.ok) {
45
45
  lastError = await this.handleErrorResponse(response);
@@ -49,7 +49,12 @@ var UlpiEmbedder = class {
49
49
  }
50
50
  throw lastError;
51
51
  }
52
- const data = await response.json();
52
+ const data = await this.safeJson(response);
53
+ if (!Array.isArray(data.data)) {
54
+ throw new Error(
55
+ `ULPI embedding API error (${response.status}): ${JSON.stringify(data)}`
56
+ );
57
+ }
53
58
  const sorted = data.data.sort((a, b) => a.index - b.index);
54
59
  return sorted.map((item) => item.embedding);
55
60
  } catch (err) {
@@ -83,17 +88,30 @@ var UlpiEmbedder = class {
83
88
  console.error(
84
89
  `[ulpi-embedder] submitBatch: ${texts.length} texts, payload=${(payload.length / 1024).toFixed(0)}KB, chars: total=${totalChars} avg=${avgChars} max=${maxChars}, model=${this.model}, url=${this.baseUrl}/api/v1/embeddings/batch`
85
90
  );
86
- const response = await fetch(`${this.baseUrl}/api/v1/embeddings/batch`, {
87
- method: "POST",
88
- headers: this.headers,
89
- body: payload
90
- });
91
- if (!response.ok) {
92
- throw await this.handleErrorResponse(response);
91
+ const controller = new AbortController();
92
+ const timeoutId = setTimeout(() => controller.abort(), 6e4);
93
+ try {
94
+ const response = await fetch(`${this.baseUrl}/api/v1/embeddings/batch`, {
95
+ method: "POST",
96
+ headers: this.headers,
97
+ body: payload,
98
+ redirect: "error",
99
+ signal: controller.signal
100
+ });
101
+ if (!response.ok) {
102
+ throw await this.handleErrorResponse(response);
103
+ }
104
+ const result = await this.safeJson(response);
105
+ if (!result.data?.id) {
106
+ throw new Error(
107
+ `ULPI batch API error (${response.status}): ${JSON.stringify(result)}`
108
+ );
109
+ }
110
+ console.error(`[ulpi-embedder] submitBatch: got batchId=${result.data.id}`);
111
+ return result.data.id;
112
+ } finally {
113
+ clearTimeout(timeoutId);
93
114
  }
94
- const result = await response.json();
95
- console.error(`[ulpi-embedder] submitBatch: got batchId=${result.data.id}`);
96
- return result.data.id;
97
115
  }
98
116
  /**
99
117
  * Poll the status of an async batch.
@@ -102,28 +120,47 @@ var UlpiEmbedder = class {
102
120
  * as they arrive rather than waiting for full batch completion.
103
121
  */
104
122
  async pollBatch(batchId) {
105
- const response = await fetch(
106
- `${this.baseUrl}/api/v1/embeddings/batch/${encodeURIComponent(batchId)}`,
107
- { headers: this.headers }
108
- );
109
- if (!response.ok) {
110
- throw await this.handleErrorResponse(response);
123
+ const controller = new AbortController();
124
+ const timeoutId = setTimeout(() => controller.abort(), 3e4);
125
+ try {
126
+ const response = await fetch(
127
+ `${this.baseUrl}/api/v1/embeddings/batch/${encodeURIComponent(batchId)}`,
128
+ { headers: this.headers, redirect: "error", signal: controller.signal }
129
+ );
130
+ if (!response.ok) {
131
+ throw await this.handleErrorResponse(response);
132
+ }
133
+ const json = await this.safeJson(response);
134
+ const batch = json.data;
135
+ let results;
136
+ if (json.results?.data && json.results.data.length > 0) {
137
+ const sorted = json.results.data.sort((a, b) => a.index - b.index);
138
+ results = sorted.map((item) => item.embedding);
139
+ }
140
+ const allProcessed = batch.processed_inputs >= batch.total_inputs;
141
+ return {
142
+ id: batch.id,
143
+ status: allProcessed && batch.status !== "failed" ? "completed" : batch.status,
144
+ totalInputs: batch.total_inputs,
145
+ processedInputs: batch.processed_inputs,
146
+ results
147
+ };
148
+ } finally {
149
+ clearTimeout(timeoutId);
111
150
  }
112
- const json = await response.json();
113
- const batch = json.data;
114
- let results;
115
- if (json.results?.data && json.results.data.length > 0) {
116
- const sorted = json.results.data.sort((a, b) => a.index - b.index);
117
- results = sorted.map((item) => item.embedding);
151
+ }
152
+ /**
153
+ * Parse JSON from response, guarding against HTML error pages.
154
+ */
155
+ async safeJson(response) {
156
+ const ct = response.headers.get("content-type") ?? "";
157
+ if (ct.includes("text/html")) {
158
+ const snippet = (await response.text()).slice(0, 200);
159
+ throw new Error(
160
+ `ULPI embedding API returned HTML instead of JSON (${response.status}). The endpoint may be misconfigured. Response: ${snippet}`
161
+ );
118
162
  }
119
- const allProcessed = batch.processed_inputs >= batch.total_inputs;
120
- return {
121
- id: batch.id,
122
- status: allProcessed && batch.status !== "failed" ? "completed" : batch.status,
123
- totalInputs: batch.total_inputs,
124
- processedInputs: batch.processed_inputs,
125
- results
126
- };
163
+ return await response.json();
127
164
  }
128
165
  async handleErrorResponse(response) {
129
166
  const errorText = await response.text();
@@ -155,6 +192,7 @@ var UlpiEmbedder = class {
155
192
  function sleep(ms) {
156
193
  return new Promise((resolve) => setTimeout(resolve, ms));
157
194
  }
195
+
158
196
  export {
159
197
  BATCH_POLL_INTERVAL_MS,
160
198
  UlpiEmbedder