@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.
- package/README.md +143 -214
- package/dist/{auth-PN7TMQHV-2W4ICG64.js → auth-FWM7MM4Q-VZC3U2XZ.js} +1 -1
- package/dist/{auth-BFFBUJUC.js → auth-HDK7ECJL.js} +2 -1
- package/dist/{chunk-RJIRWQJD.js → chunk-3BCW6ABU.js} +402 -142
- package/dist/{chunk-L3PWNHSA.js → chunk-3WB5CXH4.js} +180 -5
- package/dist/{chunk-K4OVPFY2.js → chunk-4UCJIAOU.js} +2 -2
- package/dist/chunk-4XTHZVDS.js +109 -0
- package/dist/chunk-4ZPOZULQ.js +6522 -0
- package/dist/{chunk-SIAQVRKG.js → chunk-5MI5GIXM.js} +48 -2
- package/dist/{chunk-KLEASXUR.js → chunk-6ZL6NXMV.js} +1 -1
- package/dist/{chunk-AV5RB3N2.js → chunk-76D3BYJD.js} +48 -0
- package/dist/{chunk-DOIKS6C5.js → chunk-AWOSRA5F.js} +1 -1
- package/dist/{chunk-UCMT5OKP.js → chunk-BFEKZZHM.js} +274 -57
- package/dist/chunk-C7CLUQI6.js +1286 -0
- package/dist/{chunk-ELTGWMDE.js → chunk-E3B5NROU.js} +7 -7
- package/dist/chunk-EJ7TW77N.js +1418 -0
- package/dist/{chunk-P2RESJRN.js → chunk-EWLYVXQ4.js} +2 -2
- package/dist/{chunk-6OURRFP7.js → chunk-IV6MWETF.js} +383 -168
- package/dist/chunk-IZPJHSPX.js +1478 -0
- package/dist/chunk-JLHNLM3C.js +228 -0
- package/dist/chunk-PO4NUZUU.js +147 -0
- package/dist/chunk-S6ANCSYO.js +1271 -0
- package/dist/chunk-SEU7WWNQ.js +1251 -0
- package/dist/chunk-SNQ7NAIS.js +453 -0
- package/dist/{ulpi-RMMCUAGP-EWYUE7RU.js → chunk-TSLDGT5O.js} +73 -35
- package/dist/{chunk-EIWYSP3A.js → chunk-UXHCHOWQ.js} +83 -62
- package/dist/chunk-WED4LM5N.js +322 -0
- package/dist/chunk-WVOZE25N.js +6757 -0
- package/dist/{chunk-5SCG7UYM.js → chunk-XKF4DPUM.js} +7 -7
- package/dist/{chunk-74WVVWJ4.js → chunk-YOKL7RB5.js} +184 -15
- package/dist/chunk-Z53CAR7G.js +298 -0
- package/dist/{ci-JQ56YIKC.js → ci-COZRTPGQ.js} +124 -26
- package/dist/cloud-2F3NLVHN.js +274 -0
- package/dist/{codemap-HMYBXJL2.js → codemap-XNGMAF3F.js} +37 -37
- package/dist/codex-MB5YTMRT.js +132 -0
- package/dist/{config-YYWEN7U2.js → config-OOELBYTH.js} +1 -1
- package/dist/dist-2BJYR5EI.js +59 -0
- package/dist/dist-3EIQTZHT.js +1380 -0
- package/dist/{dist-WAMAQVPK.js → dist-4U5L2X2C.js} +2 -2
- package/dist/{dist-4XTJ6HLM.js → dist-54KAMNLO.js} +16 -15
- package/dist/dist-6M4MZWZW.js +58 -0
- package/dist/dist-6X576SU2.js +27 -0
- package/dist/dist-7QOEYLFX.js +103 -0
- package/dist/dist-AYBGHEDY.js +2541 -0
- package/dist/dist-EK45QNEM.js +45 -0
- package/dist/{dist-U7ZIJMZD.js → dist-FKFEJRPX.js} +16 -15
- package/dist/dist-GTEJUBBT.js +66 -0
- package/dist/dist-HA74OKJZ.js +40 -0
- package/dist/{dist-XG2GG5SD.js → dist-HU5RZAON.js} +14 -2
- package/dist/dist-IYE3OBRB.js +374 -0
- package/dist/{dist-7WLLPWWB.js → dist-JLU26AB6.js} +12 -9
- package/dist/{dist-6G7JC2RA.js → dist-KUCI6JFE.js} +49 -9
- package/dist/dist-NUEMFZFL.js +33 -0
- package/dist/{dist-GWGTAHNM.js → dist-NUXMDXZ3.js} +31 -3
- package/dist/{dist-5R4RYNQO.js → dist-YCNWHSLN.js} +15 -5
- package/dist/{dist-6MFVWIFF.js → dist-YFFG2ZD6.js} +9 -16
- package/dist/dist-ZG4OKCSR.js +15 -0
- package/dist/doctor-FKYSIHER.js +345 -0
- package/dist/{export-import-4A5MWLIA.js → export-import-JFQH4KSJ.js} +1 -1
- package/dist/{history-RNUWO4JZ.js → history-UMGQNQQ7.js} +7 -7
- package/dist/{hooks-installer-K2JXEBNN.js → hooks-installer-YEYTYA6Q.js} +2 -2
- package/dist/index.js +398 -622
- package/dist/{init-NQWFZPKO.js → init-TJYW5ROZ.js} +78 -12
- package/dist/job-HIDMAFW2.js +376 -0
- package/dist/jobs.memory-PLMMSFHB-VBECCTHN.js +33 -0
- package/dist/kiro-VMUHDFGK.js +153 -0
- package/dist/{launchd-OYXUAVW6.js → launchd-U3MSWBRH.js} +9 -17
- package/dist/mcp-PDUD7SGP.js +249 -0
- package/dist/mcp-installer-PQU3XOGO.js +259 -0
- package/dist/mcp-setup-OA7IB3H3.js +263 -0
- package/dist/{memory-D6ZFFCI2.js → memory-ZNAEAK3B.js} +17 -17
- package/dist/{ollama-3XCUZMZT-FYKHW4TZ.js → ollama-3XCUZMZT-4JMH6B7P.js} +1 -1
- package/dist/{openai-E7G2YAHU-IG33BFYF.js → openai-E7G2YAHU-T3HMBPH7.js} +2 -2
- package/dist/portal-JYWVHXDU.js +210 -0
- package/dist/prd-Q4J5NVAR.js +408 -0
- package/dist/repos-WWZXNN3P.js +271 -0
- package/dist/review-integration-RQE4KMAV.js +14 -0
- package/dist/{rules-3OFGWHP4.js → rules-Y4VSOY5Y.js} +3 -3
- package/dist/run-VPNXEIBY.js +687 -0
- package/dist/server-COL4AXKU-P7S7NNF6.js +11 -0
- package/dist/server-U7PQ6FTS-MG4MJPTS.js +20 -0
- package/dist/{skills-GY2CTPWN.js → skills-QEYU2N27.js} +4 -2
- package/dist/start-IJKY5RVT.js +303 -0
- package/dist/{status-SE43TIFJ.js → status-BHQYYGAL.js} +2 -2
- package/dist/{templates-O2XDKB5R.js → templates-CBRUJ66V.js} +6 -5
- package/dist/tui-DP7736EX.js +61 -0
- package/dist/ulpi-5EN6JCAS-LFE3WSL4.js +10 -0
- package/dist/{uninstall-KWGSGZTI.js → uninstall-BX6FOV77.js} +3 -3
- package/dist/{update-QYZA4D23.js → update-AQKTHFVQ.js} +3 -3
- package/dist/{version-checker-MVB74DEX.js → version-checker-5L5PUOEX.js} +2 -2
- package/package.json +13 -4
- package/dist/chunk-26LLDX2T.js +0 -553
- package/dist/chunk-DDRLI6JU.js +0 -331
- package/dist/chunk-IFATANHR.js +0 -453
- package/dist/chunk-JWUUVXIV.js +0 -13694
- package/dist/chunk-LD52XG3X.js +0 -4273
- package/dist/chunk-MIAQVCFW.js +0 -39
- package/dist/chunk-YYZOFYS6.js +0 -415
- package/dist/dist-XD4YI27T.js +0 -26
- package/dist/mcp-installer-TOYDP77X.js +0 -124
- package/dist/projects-COUJP4ZC.js +0 -271
- package/dist/review-KMGP2S25.js +0 -152
- package/dist/server-USLHY6GH-F4JSXCWA.js +0 -18
- package/dist/server-X5P6WH2M-ULZF5WHZ.js +0 -11
- package/dist/ui-4SM2SUI6.js +0 -167
- package/dist/ui.html +0 -698
- /package/dist/skills/{ulpi-generate-guardian → ulpi-generate-guards}/SKILL.md +0 -0
- /package/dist/skills/{ulpi-generate-guardian → ulpi-generate-guards}/references/framework-rules.md +0 -0
- /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-
|
|
5
|
-
import "./chunk-4VNS5WPM.js";
|
|
4
|
+
} from "./chunk-C7CLUQI6.js";
|
|
6
5
|
|
|
7
|
-
// ../../packages/
|
|
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
|
|
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
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
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
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
-
|
|
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
|