@ulpi/cli 0.1.5 → 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.
- package/LICENSE +21 -0
- 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-6OURRFP7.js → chunk-IV6MWETF.js} +383 -168
- package/dist/chunk-IZPJHSPX.js +1478 -0
- package/dist/chunk-JLHNLM3C.js +228 -0
- package/dist/{chunk-P2RESJRN.js → chunk-KYYI23AQ.js} +2 -2
- 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-V2H5D6Y3.js +146 -0
- package/dist/{chunk-5SCG7UYM.js → chunk-VVEDXI7E.js} +1 -1
- package/dist/chunk-VXH5Y4FO.js +6761 -0
- package/dist/chunk-WED4LM5N.js +322 -0
- package/dist/{chunk-74WVVWJ4.js → chunk-YOKL7RB5.js} +184 -15
- package/dist/chunk-Z53CAR7G.js +298 -0
- package/dist/{ci-JQ56YIKC.js → ci-X3U2W4HC.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-SI4LLLDZ.js +345 -0
- package/dist/{export-import-4A5MWLIA.js → export-import-JFQH4KSJ.js} +1 -1
- package/dist/{history-RNUWO4JZ.js → history-5NE46ZAH.js} +7 -7
- package/dist/{hooks-installer-K2JXEBNN.js → hooks-installer-UN5JZLDQ.js} +2 -2
- package/dist/index.js +394 -618
- package/dist/{init-NQWFZPKO.js → init-5FK3VKRT.js} +76 -10
- 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-6AWT54HR.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-5WHEJU2A.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-KKSETHDV-XSSLEENT.js +20 -0
- package/dist/{skills-GY2CTPWN.js → skills-QEYU2N27.js} +4 -2
- package/dist/start-JYOEL7AJ.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-ICUV6DDV.js} +3 -3
- package/dist/{update-QYZA4D23.js → update-7ZMAYRBH.js} +3 -3
- package/dist/{version-checker-MVB74DEX.js → version-checker-4ZFMZA7Y.js} +2 -2
- package/package.json +39 -31
- 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/skills/ulpi-generate-guardian/SKILL.md +0 -750
- package/dist/skills/ulpi-generate-guardian/references/framework-rules.md +0 -849
- package/dist/skills/ulpi-generate-guardian/references/language-rules.md +0 -591
- package/dist/ui-4SM2SUI6.js +0 -167
- package/dist/ui.html +0 -698
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import "./chunk-4VNS5WPM.js";
|
|
2
|
+
|
|
3
|
+
// src/commands/mcp-setup.ts
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
import * as path from "path";
|
|
6
|
+
import * as os from "os";
|
|
7
|
+
import { execFileSync } from "child_process";
|
|
8
|
+
import chalk from "chalk";
|
|
9
|
+
function isCommandAvailable(command) {
|
|
10
|
+
try {
|
|
11
|
+
execFileSync("which", [command], { encoding: "utf-8", timeout: 5e3 });
|
|
12
|
+
return true;
|
|
13
|
+
} catch {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function detectAgents() {
|
|
18
|
+
const agents = [];
|
|
19
|
+
const home = os.homedir();
|
|
20
|
+
if (isCommandAvailable("claude")) {
|
|
21
|
+
agents.push({
|
|
22
|
+
name: "Claude Code",
|
|
23
|
+
binary: "claude",
|
|
24
|
+
configPath: path.join(home, ".claude", "settings.json"),
|
|
25
|
+
format: "json"
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
if (isCommandAvailable("opencode")) {
|
|
29
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME ?? path.join(home, ".config");
|
|
30
|
+
const opencodePath = path.join(xdgConfig, "opencode", "config.json");
|
|
31
|
+
agents.push({
|
|
32
|
+
name: "OpenCode",
|
|
33
|
+
binary: "opencode",
|
|
34
|
+
configPath: opencodePath,
|
|
35
|
+
format: "json"
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (isCommandAvailable("gemini")) {
|
|
39
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME ?? path.join(home, ".config");
|
|
40
|
+
agents.push({
|
|
41
|
+
name: "Gemini CLI",
|
|
42
|
+
binary: "gemini",
|
|
43
|
+
configPath: path.join(xdgConfig, "gemini", "settings.json"),
|
|
44
|
+
format: "json"
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (isCommandAvailable("codex")) {
|
|
48
|
+
agents.push({
|
|
49
|
+
name: "Codex",
|
|
50
|
+
binary: "codex",
|
|
51
|
+
configPath: path.join(home, ".codex", "config.json"),
|
|
52
|
+
format: "json"
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (isCommandAvailable("kiro")) {
|
|
56
|
+
agents.push({
|
|
57
|
+
name: "Kiro",
|
|
58
|
+
binary: "kiro",
|
|
59
|
+
configPath: path.join(home, ".kiro", "settings", "mcp.json"),
|
|
60
|
+
format: "json-nested"
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (isCommandAvailable("droid")) {
|
|
64
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME ?? path.join(home, ".config");
|
|
65
|
+
agents.push({
|
|
66
|
+
name: "Droid",
|
|
67
|
+
binary: "droid",
|
|
68
|
+
configPath: path.join(xdgConfig, "droid", "mcp.json"),
|
|
69
|
+
format: "json"
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return agents;
|
|
73
|
+
}
|
|
74
|
+
function buildMcpEntries() {
|
|
75
|
+
return {
|
|
76
|
+
codemap: {
|
|
77
|
+
command: "ulpi",
|
|
78
|
+
args: ["codemap", "serve"]
|
|
79
|
+
},
|
|
80
|
+
memory: {
|
|
81
|
+
command: "ulpi",
|
|
82
|
+
args: ["memory", "serve"]
|
|
83
|
+
},
|
|
84
|
+
gateway: {
|
|
85
|
+
command: "ulpi",
|
|
86
|
+
args: ["mcp", "gateway"]
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function writeJsonMcpConfig(configPath, agentName) {
|
|
91
|
+
const entries = [];
|
|
92
|
+
const mcpEntries = buildMcpEntries();
|
|
93
|
+
let config = {};
|
|
94
|
+
if (fs.existsSync(configPath)) {
|
|
95
|
+
try {
|
|
96
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
97
|
+
} catch {
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const mcpServers = config.mcpServers ?? {};
|
|
101
|
+
let changed = false;
|
|
102
|
+
if (!mcpServers["ulpi-codemap"]) {
|
|
103
|
+
mcpServers["ulpi-codemap"] = mcpEntries.codemap;
|
|
104
|
+
entries.push("ulpi-codemap");
|
|
105
|
+
changed = true;
|
|
106
|
+
}
|
|
107
|
+
if (!mcpServers["ulpi-memory"]) {
|
|
108
|
+
mcpServers["ulpi-memory"] = mcpEntries.memory;
|
|
109
|
+
entries.push("ulpi-memory");
|
|
110
|
+
changed = true;
|
|
111
|
+
}
|
|
112
|
+
if (!mcpServers["tools"]) {
|
|
113
|
+
mcpServers["tools"] = mcpEntries.gateway;
|
|
114
|
+
entries.push("tools");
|
|
115
|
+
changed = true;
|
|
116
|
+
}
|
|
117
|
+
if (changed) {
|
|
118
|
+
config.mcpServers = mcpServers;
|
|
119
|
+
const dir = path.dirname(configPath);
|
|
120
|
+
if (!fs.existsSync(dir)) {
|
|
121
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
122
|
+
}
|
|
123
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
124
|
+
}
|
|
125
|
+
return { written: changed, entries };
|
|
126
|
+
}
|
|
127
|
+
function writeKiroMcpConfig(configPath) {
|
|
128
|
+
const entries = [];
|
|
129
|
+
const mcpEntries = buildMcpEntries();
|
|
130
|
+
let config = {};
|
|
131
|
+
if (fs.existsSync(configPath)) {
|
|
132
|
+
try {
|
|
133
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
134
|
+
} catch {
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const mcpServers = config.mcpServers ?? {};
|
|
138
|
+
let changed = false;
|
|
139
|
+
if (!mcpServers["ulpi-codemap"]) {
|
|
140
|
+
mcpServers["ulpi-codemap"] = {
|
|
141
|
+
command: mcpEntries.codemap.command,
|
|
142
|
+
args: mcpEntries.codemap.args,
|
|
143
|
+
transportType: "stdio"
|
|
144
|
+
};
|
|
145
|
+
entries.push("ulpi-codemap");
|
|
146
|
+
changed = true;
|
|
147
|
+
}
|
|
148
|
+
if (!mcpServers["ulpi-memory"]) {
|
|
149
|
+
mcpServers["ulpi-memory"] = {
|
|
150
|
+
command: mcpEntries.memory.command,
|
|
151
|
+
args: mcpEntries.memory.args,
|
|
152
|
+
transportType: "stdio"
|
|
153
|
+
};
|
|
154
|
+
entries.push("ulpi-memory");
|
|
155
|
+
changed = true;
|
|
156
|
+
}
|
|
157
|
+
if (!mcpServers["tools"]) {
|
|
158
|
+
mcpServers["tools"] = {
|
|
159
|
+
command: mcpEntries.gateway.command,
|
|
160
|
+
args: mcpEntries.gateway.args,
|
|
161
|
+
transportType: "stdio"
|
|
162
|
+
};
|
|
163
|
+
entries.push("tools");
|
|
164
|
+
changed = true;
|
|
165
|
+
}
|
|
166
|
+
if (changed) {
|
|
167
|
+
config.mcpServers = mcpServers;
|
|
168
|
+
const dir = path.dirname(configPath);
|
|
169
|
+
if (!fs.existsSync(dir)) {
|
|
170
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
171
|
+
}
|
|
172
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
173
|
+
}
|
|
174
|
+
return { written: changed, entries };
|
|
175
|
+
}
|
|
176
|
+
function suggestAdditionalMcpServers(projectDir) {
|
|
177
|
+
const suggestions = [];
|
|
178
|
+
suggestions.push(
|
|
179
|
+
`${chalk.cyan("context7")} - Library documentation lookup (npx -y @upstash/context7-mcp@latest)`
|
|
180
|
+
);
|
|
181
|
+
const claudeSettingsPath = path.join(projectDir, ".claude", "settings.local.json");
|
|
182
|
+
if (fs.existsSync(claudeSettingsPath)) {
|
|
183
|
+
try {
|
|
184
|
+
const settings = JSON.parse(fs.readFileSync(claudeSettingsPath, "utf-8"));
|
|
185
|
+
const mcpServers = settings.mcpServers;
|
|
186
|
+
if (mcpServers) {
|
|
187
|
+
const projectServers = Object.keys(mcpServers).filter(
|
|
188
|
+
(k) => !k.startsWith("ulpi-") && k !== "codemap" && k !== "memory"
|
|
189
|
+
);
|
|
190
|
+
if (projectServers.length > 0) {
|
|
191
|
+
suggestions.push(
|
|
192
|
+
`${chalk.dim("Project MCP servers detected:")} ${projectServers.join(", ")}`
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
} catch {
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (suggestions.length > 0) {
|
|
200
|
+
console.log(chalk.bold("\nSuggested additional MCP servers:"));
|
|
201
|
+
for (const suggestion of suggestions) {
|
|
202
|
+
console.log(` ${suggestion}`);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
async function runMcpSetup(projectDir) {
|
|
207
|
+
console.log(chalk.bold("\nULPI MCP Setup\n"));
|
|
208
|
+
const agents = detectAgents();
|
|
209
|
+
if (agents.length === 0) {
|
|
210
|
+
console.log(chalk.yellow("No supported agent CLIs detected on PATH."));
|
|
211
|
+
console.log(chalk.dim("\nSupported agents: claude, opencode, gemini, codex, kiro, droid"));
|
|
212
|
+
console.log(chalk.dim("Install one and run this command again."));
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
console.log(`Detected ${chalk.cyan(String(agents.length))} agent CLI(s):
|
|
216
|
+
`);
|
|
217
|
+
let totalWritten = 0;
|
|
218
|
+
let totalSkipped = 0;
|
|
219
|
+
for (const agent of agents) {
|
|
220
|
+
console.log(` ${chalk.bold(agent.name)} (${chalk.dim(agent.binary)})`);
|
|
221
|
+
console.log(` Config: ${chalk.dim(agent.configPath)}`);
|
|
222
|
+
let result;
|
|
223
|
+
if (agent.format === "json-nested") {
|
|
224
|
+
result = writeKiroMcpConfig(agent.configPath);
|
|
225
|
+
} else {
|
|
226
|
+
result = writeJsonMcpConfig(agent.configPath, agent.name);
|
|
227
|
+
}
|
|
228
|
+
if (result.written) {
|
|
229
|
+
console.log(
|
|
230
|
+
` ${chalk.green("Added:")} ${result.entries.join(", ")}`
|
|
231
|
+
);
|
|
232
|
+
totalWritten += result.entries.length;
|
|
233
|
+
} else {
|
|
234
|
+
console.log(` ${chalk.dim("Already configured")}`);
|
|
235
|
+
totalSkipped++;
|
|
236
|
+
}
|
|
237
|
+
console.log("");
|
|
238
|
+
}
|
|
239
|
+
if (totalWritten > 0) {
|
|
240
|
+
console.log(
|
|
241
|
+
chalk.green(`Registered ${totalWritten} MCP server(s) across ${agents.length} agent(s).`)
|
|
242
|
+
);
|
|
243
|
+
} else if (totalSkipped > 0) {
|
|
244
|
+
console.log(chalk.dim("All agents already have ULPI MCP servers configured."));
|
|
245
|
+
}
|
|
246
|
+
try {
|
|
247
|
+
const { installMcpForAllClis } = await import("./mcp-installer-PQU3XOGO.js");
|
|
248
|
+
const cliResults = installMcpForAllClis(projectDir);
|
|
249
|
+
if (cliResults.length > 0) {
|
|
250
|
+
console.log(chalk.bold("Project-level MCP configs:\n"));
|
|
251
|
+
for (const result of cliResults) {
|
|
252
|
+
console.log(` ${chalk.green("\u2713")} ${result.cli} \u2014 ${result.file} (${result.servers.join(", ")})`);
|
|
253
|
+
}
|
|
254
|
+
console.log("");
|
|
255
|
+
}
|
|
256
|
+
} catch {
|
|
257
|
+
}
|
|
258
|
+
suggestAdditionalMcpServers(projectDir);
|
|
259
|
+
console.log("");
|
|
260
|
+
}
|
|
261
|
+
export {
|
|
262
|
+
runMcpSetup
|
|
263
|
+
};
|
|
@@ -50,8 +50,8 @@ Subcommands:
|
|
|
50
50
|
}
|
|
51
51
|
async function initSubcommand(projectDir) {
|
|
52
52
|
console.log(chalk.bold("\nAgent Memory -- Initialize\n"));
|
|
53
|
-
const { isMemoryInitialized, saveMemoryConfig, DEFAULT_MEMORY_CONFIG } = await import("./dist-
|
|
54
|
-
const { projectMemoryDir } = await import("./dist-
|
|
53
|
+
const { isMemoryInitialized, saveMemoryConfig, DEFAULT_MEMORY_CONFIG } = await import("./dist-JLU26AB6.js");
|
|
54
|
+
const { projectMemoryDir } = await import("./dist-NUXMDXZ3.js");
|
|
55
55
|
const fs = await import("fs");
|
|
56
56
|
if (isMemoryInitialized(projectDir)) {
|
|
57
57
|
console.log(chalk.yellow("Memory is already initialized for this project."));
|
|
@@ -67,7 +67,7 @@ async function initSubcommand(projectDir) {
|
|
|
67
67
|
console.log(chalk.dim(` Capture mode: ${config.captureMode}`));
|
|
68
68
|
console.log(chalk.dim(` Classifier: ${config.classifier.enabled ? "enabled" : "disabled"}`));
|
|
69
69
|
console.log(chalk.dim(` Surface: ${config.surfaceOnStart ? `on start (limit ${config.surfaceLimit})` : "disabled"}`));
|
|
70
|
-
const { installMemoryMcpServer } = await import("./mcp-installer-
|
|
70
|
+
const { installMemoryMcpServer } = await import("./mcp-installer-PQU3XOGO.js");
|
|
71
71
|
const mcp = installMemoryMcpServer(projectDir);
|
|
72
72
|
if (mcp.installed) {
|
|
73
73
|
console.log(chalk.green("\u2713 MCP server registered"));
|
|
@@ -104,7 +104,7 @@ async function searchSubcommand(args, projectDir) {
|
|
|
104
104
|
const ora = (await import("ora")).default;
|
|
105
105
|
const spinner = ora("Searching memories...").start();
|
|
106
106
|
try {
|
|
107
|
-
const { searchMemory, isMemoryInitialized } = await import("./dist-
|
|
107
|
+
const { searchMemory, isMemoryInitialized } = await import("./dist-JLU26AB6.js");
|
|
108
108
|
if (!isMemoryInitialized(projectDir)) {
|
|
109
109
|
spinner.fail("Memory not initialized");
|
|
110
110
|
console.log(chalk.dim("Run 'ulpi memory init' first."));
|
|
@@ -170,7 +170,7 @@ async function rememberSubcommand(args, projectDir) {
|
|
|
170
170
|
console.log(chalk.dim('\nExample: ulpi memory remember "Always run tests before committing" --type PREFERENCE --importance high'));
|
|
171
171
|
return;
|
|
172
172
|
}
|
|
173
|
-
const { isMemoryInitialized } = await import("./dist-
|
|
173
|
+
const { isMemoryInitialized } = await import("./dist-JLU26AB6.js");
|
|
174
174
|
if (!isMemoryInitialized(projectDir)) {
|
|
175
175
|
console.log(chalk.red("Error: Memory not initialized. Run 'ulpi memory init' first."));
|
|
176
176
|
return;
|
|
@@ -190,7 +190,7 @@ async function rememberSubcommand(args, projectDir) {
|
|
|
190
190
|
const ora = (await import("ora")).default;
|
|
191
191
|
const spinner = ora("Storing memory...").start();
|
|
192
192
|
try {
|
|
193
|
-
const { generateMemoryId, rememberMemory } = await import("./dist-
|
|
193
|
+
const { generateMemoryId, rememberMemory } = await import("./dist-JLU26AB6.js");
|
|
194
194
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
195
195
|
const entry = {
|
|
196
196
|
id: generateMemoryId(memType, text),
|
|
@@ -216,7 +216,7 @@ async function rememberSubcommand(args, projectDir) {
|
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
async function statusSubcommand(projectDir) {
|
|
219
|
-
const { isMemoryInitialized, getMemoryStats, isMemoryEnabled, loadMemoryConfig } = await import("./dist-
|
|
219
|
+
const { isMemoryInitialized, getMemoryStats, isMemoryEnabled, loadMemoryConfig } = await import("./dist-JLU26AB6.js");
|
|
220
220
|
console.log(chalk.bold("\nAgent Memory Status\n"));
|
|
221
221
|
if (!isMemoryInitialized(projectDir)) {
|
|
222
222
|
console.log(chalk.yellow(" Not initialized"));
|
|
@@ -257,7 +257,7 @@ async function statusSubcommand(projectDir) {
|
|
|
257
257
|
}
|
|
258
258
|
async function exportSubcommand(projectDir) {
|
|
259
259
|
console.log(chalk.bold("\nAgent Memory -- Export\n"));
|
|
260
|
-
const { isMemoryInitialized, exportMemories } = await import("./dist-
|
|
260
|
+
const { isMemoryInitialized, exportMemories } = await import("./dist-JLU26AB6.js");
|
|
261
261
|
if (!isMemoryInitialized(projectDir)) {
|
|
262
262
|
console.log(chalk.red("Error: Memory not initialized. Run 'ulpi memory init' first."));
|
|
263
263
|
return;
|
|
@@ -277,7 +277,7 @@ async function exportSubcommand(projectDir) {
|
|
|
277
277
|
}
|
|
278
278
|
async function importSubcommand(projectDir) {
|
|
279
279
|
console.log(chalk.bold("\nAgent Memory -- Import\n"));
|
|
280
|
-
const { importMemories } = await import("./dist-
|
|
280
|
+
const { importMemories } = await import("./dist-JLU26AB6.js");
|
|
281
281
|
try {
|
|
282
282
|
const result = await importMemories(projectDir);
|
|
283
283
|
if (!result.success) {
|
|
@@ -295,18 +295,18 @@ async function importSubcommand(projectDir) {
|
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
297
|
async function serveSubcommand(projectDir) {
|
|
298
|
-
const { isMemoryInitialized } = await import("./dist-
|
|
298
|
+
const { isMemoryInitialized } = await import("./dist-JLU26AB6.js");
|
|
299
299
|
if (!isMemoryInitialized(projectDir)) {
|
|
300
300
|
console.error(chalk.red("Error: Memory not initialized. Run 'ulpi memory init' first."));
|
|
301
301
|
process.exit(1);
|
|
302
302
|
}
|
|
303
303
|
console.error(chalk.dim("[memory-mcp] Starting MCP server..."));
|
|
304
304
|
console.error(chalk.dim(`[memory-mcp] Project: ${projectDir}`));
|
|
305
|
-
const { startMemoryMcpServer } = await import("./dist-
|
|
305
|
+
const { startMemoryMcpServer } = await import("./dist-FKFEJRPX.js");
|
|
306
306
|
await startMemoryMcpServer({ projectDir });
|
|
307
307
|
}
|
|
308
308
|
async function classifySubcommand(args, projectDir) {
|
|
309
|
-
const { isMemoryInitialized, listCapturedSessions, classifySession, loadWatermark, writeClassifyBatchProgress, clearClassifyBatchProgress } = await import("./dist-
|
|
309
|
+
const { isMemoryInitialized, listCapturedSessions, classifySession, loadWatermark, writeClassifyBatchProgress, clearClassifyBatchProgress } = await import("./dist-JLU26AB6.js");
|
|
310
310
|
if (!isMemoryInitialized(projectDir)) {
|
|
311
311
|
console.log(chalk.red("Error: Memory not initialized. Run 'ulpi memory init' first."));
|
|
312
312
|
return;
|
|
@@ -341,7 +341,7 @@ async function classifySubcommand(args, projectDir) {
|
|
|
341
341
|
}
|
|
342
342
|
if (doExport) {
|
|
343
343
|
try {
|
|
344
|
-
const { exportMemories } = await import("./dist-
|
|
344
|
+
const { exportMemories } = await import("./dist-JLU26AB6.js");
|
|
345
345
|
await exportMemories(projectDir);
|
|
346
346
|
} catch {
|
|
347
347
|
}
|
|
@@ -351,7 +351,7 @@ async function classifySubcommand(args, projectDir) {
|
|
|
351
351
|
await classifySingleSession(projectDir, sessionId, classifySession);
|
|
352
352
|
if (doExport) {
|
|
353
353
|
try {
|
|
354
|
-
const { exportMemories } = await import("./dist-
|
|
354
|
+
const { exportMemories } = await import("./dist-JLU26AB6.js");
|
|
355
355
|
const result = await exportMemories(projectDir);
|
|
356
356
|
console.log(chalk.green(`\u2713 Exported ${result.memoriesExported} memories to ${result.branchName}`));
|
|
357
357
|
} catch (err) {
|
|
@@ -526,7 +526,7 @@ Agent Memory -- Classify Session
|
|
|
526
526
|
}
|
|
527
527
|
}
|
|
528
528
|
async function enableSubcommand(projectDir) {
|
|
529
|
-
const { loadMemoryConfig, saveMemoryConfig, isMemoryInitialized } = await import("./dist-
|
|
529
|
+
const { loadMemoryConfig, saveMemoryConfig, isMemoryInitialized } = await import("./dist-JLU26AB6.js");
|
|
530
530
|
if (!isMemoryInitialized(projectDir)) {
|
|
531
531
|
console.log(chalk.red("Error: Memory not initialized. Run 'ulpi memory init' first."));
|
|
532
532
|
return;
|
|
@@ -537,7 +537,7 @@ async function enableSubcommand(projectDir) {
|
|
|
537
537
|
console.log(chalk.green("\u2713 Memory capture enabled"));
|
|
538
538
|
}
|
|
539
539
|
async function disableSubcommand(projectDir) {
|
|
540
|
-
const { loadMemoryConfig, saveMemoryConfig, isMemoryInitialized } = await import("./dist-
|
|
540
|
+
const { loadMemoryConfig, saveMemoryConfig, isMemoryInitialized } = await import("./dist-JLU26AB6.js");
|
|
541
541
|
if (!isMemoryInitialized(projectDir)) {
|
|
542
542
|
console.log(chalk.red("Error: Memory not initialized. Run 'ulpi memory init' first."));
|
|
543
543
|
return;
|
|
@@ -548,7 +548,7 @@ async function disableSubcommand(projectDir) {
|
|
|
548
548
|
console.log(chalk.yellow("\u2713 Memory capture disabled"));
|
|
549
549
|
}
|
|
550
550
|
async function reindexSubcommand(projectDir) {
|
|
551
|
-
const { isMemoryInitialized, reindexMemories } = await import("./dist-
|
|
551
|
+
const { isMemoryInitialized, reindexMemories } = await import("./dist-JLU26AB6.js");
|
|
552
552
|
if (!isMemoryInitialized(projectDir)) {
|
|
553
553
|
console.log(chalk.red("Error: Memory not initialized. Run 'ulpi memory init' first."));
|
|
554
554
|
return;
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import {
|
|
2
|
+
API_LOCK_FILE,
|
|
3
|
+
ULPI_GLOBAL_DIR
|
|
4
|
+
} from "./chunk-C7CLUQI6.js";
|
|
5
|
+
import "./chunk-4VNS5WPM.js";
|
|
6
|
+
|
|
7
|
+
// src/commands/portal.ts
|
|
8
|
+
import * as fs from "fs";
|
|
9
|
+
import * as path from "path";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
import { execFileSync, spawn } from "child_process";
|
|
12
|
+
import chalk from "chalk";
|
|
13
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
var __dirname = path.dirname(__filename);
|
|
15
|
+
var PID_FILE = path.join(ULPI_GLOBAL_DIR, "portal.pid");
|
|
16
|
+
function findNextBinary(portalDir) {
|
|
17
|
+
const localNext = path.join(portalDir, "node_modules", ".bin", "next");
|
|
18
|
+
if (fs.existsSync(localNext)) return localNext;
|
|
19
|
+
try {
|
|
20
|
+
const whichResult = execFileSync("which", ["next"], {
|
|
21
|
+
encoding: "utf-8",
|
|
22
|
+
timeout: 5e3
|
|
23
|
+
}).trim();
|
|
24
|
+
if (whichResult) return whichResult;
|
|
25
|
+
} catch {
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
function findPortalDir() {
|
|
30
|
+
const candidates = [
|
|
31
|
+
// apps/cli/dist/ → ../../portal (sibling app in apps/)
|
|
32
|
+
path.resolve(__dirname, "..", "..", "portal"),
|
|
33
|
+
// From cwd
|
|
34
|
+
path.join(process.cwd(), "apps", "portal")
|
|
35
|
+
];
|
|
36
|
+
for (const candidate of candidates) {
|
|
37
|
+
if (fs.existsSync(path.join(candidate, "package.json")) && fs.existsSync(path.join(candidate, "src"))) {
|
|
38
|
+
try {
|
|
39
|
+
const pkg = JSON.parse(
|
|
40
|
+
fs.readFileSync(path.join(candidate, "package.json"), "utf-8")
|
|
41
|
+
);
|
|
42
|
+
if (pkg.name === "@ulpi/portal") return candidate;
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
function writePidFile(pid) {
|
|
50
|
+
fs.mkdirSync(path.dirname(PID_FILE), { recursive: true });
|
|
51
|
+
fs.writeFileSync(PID_FILE, String(pid), "utf-8");
|
|
52
|
+
}
|
|
53
|
+
function readPidFile() {
|
|
54
|
+
try {
|
|
55
|
+
const content = fs.readFileSync(PID_FILE, "utf-8").trim();
|
|
56
|
+
const pid = parseInt(content, 10);
|
|
57
|
+
if (isNaN(pid)) return null;
|
|
58
|
+
try {
|
|
59
|
+
process.kill(pid, 0);
|
|
60
|
+
return pid;
|
|
61
|
+
} catch {
|
|
62
|
+
fs.unlinkSync(PID_FILE);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function removePidFile() {
|
|
70
|
+
try {
|
|
71
|
+
fs.unlinkSync(PID_FILE);
|
|
72
|
+
} catch {
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function startPortal(args, projectDir) {
|
|
76
|
+
const portIndex = args.indexOf("--port");
|
|
77
|
+
let port = 9801;
|
|
78
|
+
if (portIndex !== -1 && args[portIndex + 1]) {
|
|
79
|
+
const parsed = parseInt(args[portIndex + 1], 10);
|
|
80
|
+
if (isNaN(parsed) || parsed < 1 || parsed > 65535) {
|
|
81
|
+
console.log(chalk.red("Invalid port number. Must be between 1 and 65535."));
|
|
82
|
+
process.exit(1);
|
|
83
|
+
}
|
|
84
|
+
port = parsed;
|
|
85
|
+
}
|
|
86
|
+
const devMode = args.includes("--dev");
|
|
87
|
+
const existingPid = readPidFile();
|
|
88
|
+
if (existingPid) {
|
|
89
|
+
console.log(chalk.yellow(`Portal is already running (PID ${existingPid}).`));
|
|
90
|
+
console.log(chalk.dim("Run 'ulpi portal stop' to stop it first."));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const portalDir = findPortalDir();
|
|
94
|
+
if (!portalDir) {
|
|
95
|
+
console.log(chalk.red("Could not find the @ulpi/portal app directory."));
|
|
96
|
+
console.log(chalk.dim("Make sure you are in the ULPI monorepo, or the portal package is installed."));
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
const nextBin = findNextBinary(portalDir);
|
|
100
|
+
if (!nextBin) {
|
|
101
|
+
console.log(chalk.red("Could not find the 'next' binary."));
|
|
102
|
+
console.log(chalk.dim(`Install dependencies: cd ${portalDir} && pnpm install`));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
const hasBuild = fs.existsSync(path.join(portalDir, ".next"));
|
|
106
|
+
if (!devMode && !hasBuild) {
|
|
107
|
+
console.log(chalk.yellow("No build output found. Starting in dev mode."));
|
|
108
|
+
console.log(chalk.dim(`Build first with: pnpm --filter @ulpi/portal build`));
|
|
109
|
+
console.log("");
|
|
110
|
+
}
|
|
111
|
+
const useDevMode = devMode || !hasBuild;
|
|
112
|
+
const nextCommand = useDevMode ? "dev" : "start";
|
|
113
|
+
let apiSecret = "";
|
|
114
|
+
let apiPort = 9800;
|
|
115
|
+
try {
|
|
116
|
+
const lock = JSON.parse(fs.readFileSync(API_LOCK_FILE, "utf-8"));
|
|
117
|
+
if (lock.secret) apiSecret = lock.secret;
|
|
118
|
+
if (lock.port) apiPort = lock.port;
|
|
119
|
+
} catch {
|
|
120
|
+
console.log(chalk.yellow("Warning: API server not running or lock file missing."));
|
|
121
|
+
console.log(chalk.dim("Start the API server first: ulpi ui\n"));
|
|
122
|
+
}
|
|
123
|
+
console.log(chalk.bold("\nULPI Portal \u2014 Local Mode\n"));
|
|
124
|
+
console.log(` Mode: ${useDevMode ? chalk.yellow("development") : chalk.green("production")}`);
|
|
125
|
+
console.log(` Port: ${chalk.cyan(String(port))}`);
|
|
126
|
+
console.log(` API: ${chalk.cyan(`http://localhost:${apiPort}`)}`);
|
|
127
|
+
console.log(` Portal: ${chalk.cyan(`apps/portal`)}`);
|
|
128
|
+
console.log("");
|
|
129
|
+
const env = {
|
|
130
|
+
...process.env,
|
|
131
|
+
ULPI_MODE: "local",
|
|
132
|
+
NEXT_PUBLIC_ULPI_MODE: "local",
|
|
133
|
+
NEXT_PUBLIC_API_URL: `http://localhost:${apiPort}`,
|
|
134
|
+
NEXT_PUBLIC_ULPI_API_SECRET: apiSecret,
|
|
135
|
+
PORT: String(port)
|
|
136
|
+
};
|
|
137
|
+
const child = spawn(nextBin, [nextCommand, "--port", String(port)], {
|
|
138
|
+
cwd: portalDir,
|
|
139
|
+
env,
|
|
140
|
+
stdio: "inherit"
|
|
141
|
+
});
|
|
142
|
+
if (child.pid) {
|
|
143
|
+
writePidFile(child.pid);
|
|
144
|
+
}
|
|
145
|
+
const cleanup = () => {
|
|
146
|
+
removePidFile();
|
|
147
|
+
child.kill("SIGTERM");
|
|
148
|
+
};
|
|
149
|
+
process.on("SIGINT", cleanup);
|
|
150
|
+
process.on("SIGTERM", cleanup);
|
|
151
|
+
child.on("error", (err) => {
|
|
152
|
+
console.error(chalk.red(`Failed to start portal: ${err.message}`));
|
|
153
|
+
removePidFile();
|
|
154
|
+
process.exit(1);
|
|
155
|
+
});
|
|
156
|
+
child.on("close", (code) => {
|
|
157
|
+
removePidFile();
|
|
158
|
+
if (code !== 0 && code !== null) {
|
|
159
|
+
console.error(chalk.red(`Portal exited with code ${code}`));
|
|
160
|
+
process.exit(code);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
console.log(chalk.green(`Portal starting at http://localhost:${port}`));
|
|
164
|
+
console.log(chalk.dim("Press Ctrl+C to stop.\n"));
|
|
165
|
+
}
|
|
166
|
+
function stopPortal() {
|
|
167
|
+
const pid = readPidFile();
|
|
168
|
+
if (!pid) {
|
|
169
|
+
console.log(chalk.yellow("No running portal instance found."));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
process.kill(pid, "SIGTERM");
|
|
174
|
+
removePidFile();
|
|
175
|
+
console.log(chalk.green(`Portal stopped (PID ${pid}).`));
|
|
176
|
+
} catch (err) {
|
|
177
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
178
|
+
console.log(chalk.red(`Failed to stop portal: ${message}`));
|
|
179
|
+
removePidFile();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
function runPortalCommand(args, projectDir) {
|
|
183
|
+
const subcommand = args[0];
|
|
184
|
+
switch (subcommand) {
|
|
185
|
+
case "stop":
|
|
186
|
+
return stopPortal();
|
|
187
|
+
case "start":
|
|
188
|
+
return startPortal(args.slice(1), projectDir);
|
|
189
|
+
case void 0:
|
|
190
|
+
return startPortal(args, projectDir);
|
|
191
|
+
default:
|
|
192
|
+
if (subcommand?.startsWith("--")) {
|
|
193
|
+
return startPortal(args, projectDir);
|
|
194
|
+
}
|
|
195
|
+
console.log(`
|
|
196
|
+
Usage: ulpi portal [subcommand] [options]
|
|
197
|
+
|
|
198
|
+
Subcommands:
|
|
199
|
+
start Start Portal in local mode (default)
|
|
200
|
+
stop Stop running Portal instance
|
|
201
|
+
|
|
202
|
+
Options:
|
|
203
|
+
--port <number> Port to run on (default: 3000)
|
|
204
|
+
--dev Force development mode
|
|
205
|
+
`.trim());
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
export {
|
|
209
|
+
runPortalCommand
|
|
210
|
+
};
|