@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.
Files changed (109) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{auth-PN7TMQHV-2W4ICG64.js → auth-FWM7MM4Q-VZC3U2XZ.js} +1 -1
  3. package/dist/{auth-BFFBUJUC.js → auth-HDK7ECJL.js} +2 -1
  4. package/dist/{chunk-RJIRWQJD.js → chunk-3BCW6ABU.js} +402 -142
  5. package/dist/{chunk-L3PWNHSA.js → chunk-3WB5CXH4.js} +180 -5
  6. package/dist/{chunk-K4OVPFY2.js → chunk-4UCJIAOU.js} +2 -2
  7. package/dist/chunk-4XTHZVDS.js +109 -0
  8. package/dist/chunk-4ZPOZULQ.js +6522 -0
  9. package/dist/{chunk-SIAQVRKG.js → chunk-5MI5GIXM.js} +48 -2
  10. package/dist/{chunk-KLEASXUR.js → chunk-6ZL6NXMV.js} +1 -1
  11. package/dist/{chunk-AV5RB3N2.js → chunk-76D3BYJD.js} +48 -0
  12. package/dist/{chunk-DOIKS6C5.js → chunk-AWOSRA5F.js} +1 -1
  13. package/dist/{chunk-UCMT5OKP.js → chunk-BFEKZZHM.js} +274 -57
  14. package/dist/chunk-C7CLUQI6.js +1286 -0
  15. package/dist/{chunk-ELTGWMDE.js → chunk-E3B5NROU.js} +7 -7
  16. package/dist/chunk-EJ7TW77N.js +1418 -0
  17. package/dist/{chunk-6OURRFP7.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-P2RESJRN.js → chunk-KYYI23AQ.js} +2 -2
  21. package/dist/chunk-S6ANCSYO.js +1271 -0
  22. package/dist/chunk-SEU7WWNQ.js +1251 -0
  23. package/dist/chunk-SNQ7NAIS.js +453 -0
  24. package/dist/{ulpi-RMMCUAGP-EWYUE7RU.js → chunk-TSLDGT5O.js} +73 -35
  25. package/dist/{chunk-EIWYSP3A.js → chunk-UXHCHOWQ.js} +83 -62
  26. package/dist/chunk-V2H5D6Y3.js +146 -0
  27. package/dist/{chunk-5SCG7UYM.js → chunk-VVEDXI7E.js} +1 -1
  28. package/dist/chunk-VXH5Y4FO.js +6761 -0
  29. package/dist/chunk-WED4LM5N.js +322 -0
  30. package/dist/{chunk-74WVVWJ4.js → chunk-YOKL7RB5.js} +184 -15
  31. package/dist/chunk-Z53CAR7G.js +298 -0
  32. package/dist/{ci-JQ56YIKC.js → ci-X3U2W4HC.js} +124 -26
  33. package/dist/cloud-2F3NLVHN.js +274 -0
  34. package/dist/{codemap-HMYBXJL2.js → codemap-XNGMAF3F.js} +37 -37
  35. package/dist/codex-MB5YTMRT.js +132 -0
  36. package/dist/{config-YYWEN7U2.js → config-OOELBYTH.js} +1 -1
  37. package/dist/dist-2BJYR5EI.js +59 -0
  38. package/dist/dist-3EIQTZHT.js +1380 -0
  39. package/dist/{dist-WAMAQVPK.js → dist-4U5L2X2C.js} +2 -2
  40. package/dist/{dist-4XTJ6HLM.js → dist-54KAMNLO.js} +16 -15
  41. package/dist/dist-6M4MZWZW.js +58 -0
  42. package/dist/dist-6X576SU2.js +27 -0
  43. package/dist/dist-7QOEYLFX.js +103 -0
  44. package/dist/dist-AYBGHEDY.js +2541 -0
  45. package/dist/dist-EK45QNEM.js +45 -0
  46. package/dist/{dist-U7ZIJMZD.js → dist-FKFEJRPX.js} +16 -15
  47. package/dist/dist-GTEJUBBT.js +66 -0
  48. package/dist/dist-HA74OKJZ.js +40 -0
  49. package/dist/{dist-XG2GG5SD.js → dist-HU5RZAON.js} +14 -2
  50. package/dist/dist-IYE3OBRB.js +374 -0
  51. package/dist/{dist-7WLLPWWB.js → dist-JLU26AB6.js} +12 -9
  52. package/dist/{dist-6G7JC2RA.js → dist-KUCI6JFE.js} +49 -9
  53. package/dist/dist-NUEMFZFL.js +33 -0
  54. package/dist/{dist-GWGTAHNM.js → dist-NUXMDXZ3.js} +31 -3
  55. package/dist/{dist-5R4RYNQO.js → dist-YCNWHSLN.js} +15 -5
  56. package/dist/{dist-6MFVWIFF.js → dist-YFFG2ZD6.js} +9 -16
  57. package/dist/dist-ZG4OKCSR.js +15 -0
  58. package/dist/doctor-SI4LLLDZ.js +345 -0
  59. package/dist/{export-import-4A5MWLIA.js → export-import-JFQH4KSJ.js} +1 -1
  60. package/dist/{history-RNUWO4JZ.js → history-5NE46ZAH.js} +7 -7
  61. package/dist/{hooks-installer-K2JXEBNN.js → hooks-installer-UN5JZLDQ.js} +2 -2
  62. package/dist/index.js +394 -618
  63. package/dist/{init-NQWFZPKO.js → init-5FK3VKRT.js} +76 -10
  64. package/dist/job-HIDMAFW2.js +376 -0
  65. package/dist/jobs.memory-PLMMSFHB-VBECCTHN.js +33 -0
  66. package/dist/kiro-VMUHDFGK.js +153 -0
  67. package/dist/{launchd-OYXUAVW6.js → launchd-6AWT54HR.js} +9 -17
  68. package/dist/mcp-PDUD7SGP.js +249 -0
  69. package/dist/mcp-installer-PQU3XOGO.js +259 -0
  70. package/dist/mcp-setup-OA7IB3H3.js +263 -0
  71. package/dist/{memory-D6ZFFCI2.js → memory-ZNAEAK3B.js} +17 -17
  72. package/dist/{ollama-3XCUZMZT-FYKHW4TZ.js → ollama-3XCUZMZT-4JMH6B7P.js} +1 -1
  73. package/dist/{openai-E7G2YAHU-IG33BFYF.js → openai-E7G2YAHU-T3HMBPH7.js} +2 -2
  74. package/dist/portal-JYWVHXDU.js +210 -0
  75. package/dist/prd-Q4J5NVAR.js +408 -0
  76. package/dist/repos-WWZXNN3P.js +271 -0
  77. package/dist/review-integration-5WHEJU2A.js +14 -0
  78. package/dist/{rules-3OFGWHP4.js → rules-Y4VSOY5Y.js} +3 -3
  79. package/dist/run-VPNXEIBY.js +687 -0
  80. package/dist/server-COL4AXKU-P7S7NNF6.js +11 -0
  81. package/dist/server-KKSETHDV-XSSLEENT.js +20 -0
  82. package/dist/{skills-GY2CTPWN.js → skills-QEYU2N27.js} +4 -2
  83. package/dist/start-JYOEL7AJ.js +303 -0
  84. package/dist/{status-SE43TIFJ.js → status-BHQYYGAL.js} +2 -2
  85. package/dist/{templates-O2XDKB5R.js → templates-CBRUJ66V.js} +6 -5
  86. package/dist/tui-DP7736EX.js +61 -0
  87. package/dist/ulpi-5EN6JCAS-LFE3WSL4.js +10 -0
  88. package/dist/{uninstall-KWGSGZTI.js → uninstall-ICUV6DDV.js} +3 -3
  89. package/dist/{update-QYZA4D23.js → update-7ZMAYRBH.js} +3 -3
  90. package/dist/{version-checker-MVB74DEX.js → version-checker-4ZFMZA7Y.js} +2 -2
  91. package/package.json +39 -31
  92. package/dist/chunk-26LLDX2T.js +0 -553
  93. package/dist/chunk-DDRLI6JU.js +0 -331
  94. package/dist/chunk-IFATANHR.js +0 -453
  95. package/dist/chunk-JWUUVXIV.js +0 -13694
  96. package/dist/chunk-LD52XG3X.js +0 -4273
  97. package/dist/chunk-MIAQVCFW.js +0 -39
  98. package/dist/chunk-YYZOFYS6.js +0 -415
  99. package/dist/dist-XD4YI27T.js +0 -26
  100. package/dist/mcp-installer-TOYDP77X.js +0 -124
  101. package/dist/projects-COUJP4ZC.js +0 -271
  102. package/dist/review-KMGP2S25.js +0 -152
  103. package/dist/server-USLHY6GH-F4JSXCWA.js +0 -18
  104. package/dist/server-X5P6WH2M-ULZF5WHZ.js +0 -11
  105. package/dist/skills/ulpi-generate-guardian/SKILL.md +0 -750
  106. package/dist/skills/ulpi-generate-guardian/references/framework-rules.md +0 -849
  107. package/dist/skills/ulpi-generate-guardian/references/language-rules.md +0 -591
  108. package/dist/ui-4SM2SUI6.js +0 -167
  109. 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-7WLLPWWB.js");
54
- const { projectMemoryDir } = await import("./dist-GWGTAHNM.js");
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-TOYDP77X.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-U7ZIJMZD.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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-7WLLPWWB.js");
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;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  OllamaEmbedder
3
- } from "./chunk-KLEASXUR.js";
3
+ } from "./chunk-6ZL6NXMV.js";
4
4
  import "./chunk-4VNS5WPM.js";
5
5
  export {
6
6
  OllamaEmbedder
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  OpenAIEmbedder
3
- } from "./chunk-K4OVPFY2.js";
4
- import "./chunk-DDRLI6JU.js";
3
+ } from "./chunk-4UCJIAOU.js";
4
+ import "./chunk-C7CLUQI6.js";
5
5
  import "./chunk-4VNS5WPM.js";
6
6
  export {
7
7
  OpenAIEmbedder
@@ -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
+ };