@ulpi/cli 0.1.4 → 0.1.6

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 (112) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{auth-PN7TMQHV-2W4ICG64.js → auth-FWM7MM4Q-VZC3U2XZ.js} +1 -1
  3. package/dist/{auth-ECQ3IB4E.js → auth-HDK7ECJL.js} +2 -1
  4. package/dist/{chunk-3SBPZRB5.js → chunk-3BCW6ABU.js} +402 -142
  5. package/dist/{chunk-JGBXM5NC.js → chunk-3WB5CXH4.js} +180 -5
  6. package/dist/{chunk-2HEE5OKX.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-76D3BYJD.js +221 -0
  12. package/dist/{chunk-ZLYRPD7I.js → chunk-AWOSRA5F.js} +1 -1
  13. package/dist/{chunk-PDR55ZNW.js → chunk-BFEKZZHM.js} +274 -57
  14. package/dist/chunk-C7CLUQI6.js +1286 -0
  15. package/dist/{chunk-7AL4DOEJ.js → chunk-E3B5NROU.js} +7 -7
  16. package/dist/chunk-EJ7TW77N.js +1418 -0
  17. package/dist/{chunk-5J6NLQUN.js → chunk-IV6MWETF.js} +383 -168
  18. package/dist/chunk-IZPJHSPX.js +1478 -0
  19. package/dist/chunk-JLHNLM3C.js +228 -0
  20. package/dist/{chunk-BZL5H4YQ.js → chunk-KYYI23AQ.js} +2 -2
  21. package/dist/{chunk-2CLNOKPA.js → chunk-RSFJ6QSR.js} +18 -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-JCJ273T6.js → chunk-TSLDGT5O.js} +73 -35
  26. package/dist/{chunk-SPOI23SB.js → chunk-UXHCHOWQ.js} +83 -62
  27. package/dist/chunk-V2H5D6Y3.js +146 -0
  28. package/dist/{chunk-QJ5GSMEC.js → chunk-VVEDXI7E.js} +2 -1
  29. package/dist/chunk-VXH5Y4FO.js +6761 -0
  30. package/dist/chunk-WED4LM5N.js +322 -0
  31. package/dist/{chunk-74WVVWJ4.js → chunk-YOKL7RB5.js} +184 -15
  32. package/dist/chunk-Z53CAR7G.js +298 -0
  33. package/dist/ci-X3U2W4HC.js +854 -0
  34. package/dist/cloud-2F3NLVHN.js +274 -0
  35. package/dist/{codemap-RKSD4MIE.js → codemap-XNGMAF3F.js} +37 -37
  36. package/dist/codex-MB5YTMRT.js +132 -0
  37. package/dist/{config-EGAXXCGL.js → config-OOELBYTH.js} +1 -1
  38. package/dist/dist-2BJYR5EI.js +59 -0
  39. package/dist/dist-2K7IEVTA.js +43 -0
  40. package/dist/dist-3EIQTZHT.js +1380 -0
  41. package/dist/{dist-YA2BWZB2.js → dist-4U5L2X2C.js} +2 -2
  42. package/dist/{dist-UKMCJBB2.js → dist-54KAMNLO.js} +16 -15
  43. package/dist/dist-6M4MZWZW.js +58 -0
  44. package/dist/dist-6X576SU2.js +27 -0
  45. package/dist/dist-7QOEYLFX.js +103 -0
  46. package/dist/dist-AYBGHEDY.js +2541 -0
  47. package/dist/dist-EK45QNEM.js +45 -0
  48. package/dist/{dist-CS2VKNYS.js → dist-FKFEJRPX.js} +16 -15
  49. package/dist/dist-GTEJUBBT.js +66 -0
  50. package/dist/dist-HA74OKJZ.js +40 -0
  51. package/dist/dist-HU5RZAON.js +48 -0
  52. package/dist/dist-IYE3OBRB.js +374 -0
  53. package/dist/{dist-GJYT2OQV.js → dist-JLU26AB6.js} +12 -9
  54. package/dist/{dist-6G7JC2RA.js → dist-KUCI6JFE.js} +49 -9
  55. package/dist/dist-NUEMFZFL.js +33 -0
  56. package/dist/{dist-RKOGLK7R.js → dist-NUXMDXZ3.js} +31 -3
  57. package/dist/{dist-QAU3LGJN.js → dist-YCNWHSLN.js} +15 -5
  58. package/dist/{dist-CB5D5LMO.js → dist-YFFG2ZD6.js} +9 -16
  59. package/dist/dist-ZG4OKCSR.js +15 -0
  60. package/dist/doctor-SI4LLLDZ.js +345 -0
  61. package/dist/{export-import-4A5MWLIA.js → export-import-JFQH4KSJ.js} +1 -1
  62. package/dist/{history-3MOBX4MA.js → history-5NE46ZAH.js} +7 -7
  63. package/dist/hooks-installer-UN5JZLDQ.js +19 -0
  64. package/dist/index.js +395 -619
  65. package/dist/{init-6CH4HV5T.js → init-5FK3VKRT.js} +79 -13
  66. package/dist/job-HIDMAFW2.js +376 -0
  67. package/dist/jobs.memory-PLMMSFHB-VBECCTHN.js +33 -0
  68. package/dist/kiro-VMUHDFGK.js +153 -0
  69. package/dist/{launchd-LF2QMSKZ.js → launchd-6AWT54HR.js} +9 -17
  70. package/dist/mcp-PDUD7SGP.js +249 -0
  71. package/dist/mcp-installer-PQU3XOGO.js +259 -0
  72. package/dist/mcp-setup-OA7IB3H3.js +263 -0
  73. package/dist/{memory-Y6OZTXJ2.js → memory-ZNAEAK3B.js} +17 -17
  74. package/dist/{ollama-3XCUZMZT-FYKHW4TZ.js → ollama-3XCUZMZT-4JMH6B7P.js} +1 -1
  75. package/dist/{openai-E7G2YAHU-UYY4ZWON.js → openai-E7G2YAHU-T3HMBPH7.js} +2 -2
  76. package/dist/portal-JYWVHXDU.js +210 -0
  77. package/dist/prd-Q4J5NVAR.js +408 -0
  78. package/dist/repos-WWZXNN3P.js +271 -0
  79. package/dist/review-integration-5WHEJU2A.js +14 -0
  80. package/dist/{rules-E427DKYJ.js → rules-Y4VSOY5Y.js} +3 -3
  81. package/dist/run-VPNXEIBY.js +687 -0
  82. package/dist/server-COL4AXKU-P7S7NNF6.js +11 -0
  83. package/dist/server-KKSETHDV-XSSLEENT.js +20 -0
  84. package/dist/{skills-CX73O3IV.js → skills-QEYU2N27.js} +4 -2
  85. package/dist/start-JYOEL7AJ.js +303 -0
  86. package/dist/{status-4DFHDJMN.js → status-BHQYYGAL.js} +2 -2
  87. package/dist/{templates-U7T6MARD.js → templates-CBRUJ66V.js} +4 -3
  88. package/dist/tui-DP7736EX.js +61 -0
  89. package/dist/ulpi-5EN6JCAS-LFE3WSL4.js +10 -0
  90. package/dist/{uninstall-6SW35IK4.js → uninstall-ICUV6DDV.js} +3 -3
  91. package/dist/{update-M6IBJNYP.js → update-7ZMAYRBH.js} +3 -3
  92. package/dist/{version-checker-Q6YTYAGP.js → version-checker-4ZFMZA7Y.js} +2 -2
  93. package/package.json +39 -31
  94. package/dist/chunk-2MZER6ND.js +0 -415
  95. package/dist/chunk-2VYFVYJL.js +0 -4273
  96. package/dist/chunk-6OCEY7JY.js +0 -422
  97. package/dist/chunk-7LXY5UVC.js +0 -330
  98. package/dist/chunk-B55DDP24.js +0 -136
  99. package/dist/chunk-JWUUVXIV.js +0 -13694
  100. package/dist/chunk-MIAQVCFW.js +0 -39
  101. package/dist/chunk-YM2HV4IA.js +0 -505
  102. package/dist/ci-STSL2LSP.js +0 -370
  103. package/dist/mcp-installer-NQCGKQ23.js +0 -124
  104. package/dist/projects-ATHDD3D6.js +0 -271
  105. package/dist/review-ADUPV3PN.js +0 -152
  106. package/dist/server-USLHY6GH-AEOJC5ST.js +0 -18
  107. package/dist/server-X5P6WH2M-7K2RY34N.js +0 -11
  108. package/dist/skills/ulpi-generate-guardian/SKILL.md +0 -750
  109. package/dist/skills/ulpi-generate-guardian/references/framework-rules.md +0 -849
  110. package/dist/skills/ulpi-generate-guardian/references/language-rules.md +0 -591
  111. package/dist/ui-OWXZ3YSR.js +0 -167
  112. package/dist/ui.html +0 -698
@@ -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-7LXY5UVC.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