@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
@@ -1,39 +0,0 @@
1
- // ../api/dist/chunk-UOFEIZ6Y.js
2
- import { randomBytes } from "crypto";
3
- var apiSecret;
4
- function generateApiSecret() {
5
- return randomBytes(32).toString("hex");
6
- }
7
- function setApiSecret(secret) {
8
- apiSecret = secret;
9
- }
10
- function getApiSecret() {
11
- return apiSecret;
12
- }
13
- function validateLoopback(req) {
14
- const remoteAddr = req.socket.remoteAddress ?? "";
15
- return remoteAddr === "127.0.0.1" || remoteAddr === "::1" || remoteAddr === "::ffff:127.0.0.1";
16
- }
17
- function validateAuth(req) {
18
- if (!validateLoopback(req)) return false;
19
- if (apiSecret) {
20
- const headerSecret = req.headers["x-ulpi-secret"];
21
- if (headerSecret === apiSecret) return true;
22
- try {
23
- const url = new URL(req.url ?? "/", `http://${req.headers.host}`);
24
- const paramSecret = url.searchParams.get("secret");
25
- if (paramSecret === apiSecret) return true;
26
- } catch {
27
- }
28
- return false;
29
- }
30
- return true;
31
- }
32
-
33
- export {
34
- generateApiSecret,
35
- setApiSecret,
36
- getApiSecret,
37
- validateLoopback,
38
- validateAuth
39
- };
@@ -1,415 +0,0 @@
1
- import {
2
- extractSections,
3
- extractTitle,
4
- generateSlug,
5
- getNextVersionNumber,
6
- parseMarkdownToBlocks,
7
- savePlan,
8
- scorePlanQuality
9
- } from "./chunk-RJIRWQJD.js";
10
- import {
11
- API_LOCK_FILE,
12
- getApiHost,
13
- getApiPort
14
- } from "./chunk-DDRLI6JU.js";
15
-
16
- // ../../packages/review-runtime/dist/index.js
17
- import { basename } from "path";
18
- import { randomUUID } from "crypto";
19
- import * as fs from "fs";
20
- var ReviewHub = class _ReviewHub {
21
- sessions = /* @__PURE__ */ new Map();
22
- awaitWaiters = /* @__PURE__ */ new Map();
23
- decidedEvictionMs = 5 * 60 * 1e3;
24
- longPollTimeoutMs = 30 * 1e3;
25
- /** Maximum number of concurrent sessions to prevent unbounded memory growth. */
26
- static MAX_SESSIONS = 100;
27
- /** Sessions older than this TTL are automatically evicted. */
28
- static SESSION_TTL_MS = 30 * 60 * 1e3;
29
- // 30 minutes
30
- /**
31
- * Register a new review session.
32
- */
33
- async register(payload) {
34
- this.cleanupExpired();
35
- if (this.sessions.size >= _ReviewHub.MAX_SESSIONS) {
36
- const oldest = [...this.sessions.entries()].sort(([, a], [, b]) => a.registeredAt - b.registeredAt)[0];
37
- if (oldest) {
38
- this.sessions.delete(oldest[0]);
39
- this.awaitWaiters.delete(oldest[0]);
40
- }
41
- }
42
- const sessionId = randomUUID();
43
- const token = randomUUID();
44
- const projectSlug = basename(payload.projectPath);
45
- let resolveDecision;
46
- const decisionPromise = new Promise((resolve) => {
47
- resolveDecision = resolve;
48
- });
49
- const session = {
50
- id: sessionId,
51
- type: payload.type,
52
- projectPath: payload.projectPath,
53
- projectSlug,
54
- title: "",
55
- status: "pending",
56
- registeredAt: Date.now(),
57
- resolveDecision,
58
- token
59
- };
60
- if (payload.type === "plan" && payload.plan) {
61
- const blocks = parseMarkdownToBlocks(payload.plan);
62
- const sections = extractSections(blocks);
63
- const quality = scorePlanQuality(blocks, sections);
64
- const title = extractTitle(blocks);
65
- const slug = generateSlug(title);
66
- const versionNumber = await getNextVersionNumber(slug, payload.projectPath);
67
- const version = {
68
- id: randomUUID(),
69
- versionNumber,
70
- markdown: payload.plan,
71
- annotations: [],
72
- inlineEdits: [],
73
- instructions: [],
74
- priorities: [],
75
- risks: [],
76
- createdAt: Date.now()
77
- };
78
- try {
79
- await savePlan(payload.plan, version, slug, payload.projectPath);
80
- } catch (err) {
81
- console.error(`[review-hub] Failed to persist plan: ${err instanceof Error ? err.message : String(err)}`);
82
- }
83
- session.plan = payload.plan;
84
- session.blocks = blocks;
85
- session.sections = sections;
86
- session.quality = quality;
87
- session.version = version;
88
- session.slug = slug;
89
- session.title = title;
90
- } else if (payload.type === "code") {
91
- session.diff = payload.diff;
92
- session.commitMessage = payload.commitMessage;
93
- session.title = payload.commitMessage || "Code Review";
94
- }
95
- this.sessions.set(sessionId, session);
96
- decisionPromise.then((decision) => {
97
- const waiters = this.awaitWaiters.get(sessionId) || [];
98
- for (const resolve of waiters) {
99
- resolve(decision);
100
- }
101
- this.awaitWaiters.delete(sessionId);
102
- });
103
- return { session: this.toPublicSession(session), sessionId, token };
104
- }
105
- /**
106
- * Get a session by ID.
107
- */
108
- getSession(id) {
109
- const session = this.sessions.get(id);
110
- return session ? this.toPublicSession(session) : null;
111
- }
112
- /**
113
- * List all sessions, optionally filtered by type/status.
114
- */
115
- listSessions(opts) {
116
- let sessions = [...this.sessions.values()];
117
- if (opts?.type) sessions = sessions.filter((s) => s.type === opts.type);
118
- if (opts?.status) sessions = sessions.filter((s) => s.status === opts.status);
119
- sessions.sort((a, b) => a.registeredAt - b.registeredAt);
120
- return sessions.map((s) => this.toPublicSession(s));
121
- }
122
- /**
123
- * Verify a session token.
124
- */
125
- verifyToken(sessionId, token) {
126
- const session = this.sessions.get(sessionId);
127
- if (!session) return false;
128
- return session.token === token;
129
- }
130
- /**
131
- * Submit a decision for a session.
132
- * When token is provided, it must match the session token.
133
- */
134
- async submitDecision(sessionId, decision, token) {
135
- const session = this.sessions.get(sessionId);
136
- if (!session) return false;
137
- if (token !== void 0 && session.token !== token) return false;
138
- if (!isValidDecision(decision)) return false;
139
- try {
140
- if (session.type === "plan" && session.version && session.slug) {
141
- const planDecision = decision;
142
- const reviewedVersion = {
143
- ...session.version,
144
- annotations: planDecision.annotations || [],
145
- inlineEdits: planDecision.inlineEdits || [],
146
- instructions: planDecision.instructions || [],
147
- priorities: planDecision.priorities || [],
148
- risks: planDecision.risks || [],
149
- decision: {
150
- behavior: planDecision.behavior,
151
- message: planDecision.message,
152
- decidedAt: Date.now()
153
- }
154
- };
155
- await savePlan(session.plan, reviewedVersion, session.slug, session.projectPath);
156
- }
157
- } catch {
158
- }
159
- session.status = "decided";
160
- session.decidedAt = Date.now();
161
- session.decisionPayload = decision;
162
- session.resolveDecision(decision);
163
- const waiters = this.awaitWaiters.get(sessionId);
164
- if (waiters && waiters.length > 0) {
165
- for (const waiter of waiters) {
166
- waiter(decision);
167
- }
168
- this.awaitWaiters.delete(sessionId);
169
- }
170
- setTimeout(() => {
171
- this.sessions.delete(sessionId);
172
- this.awaitWaiters.delete(sessionId);
173
- }, this.decidedEvictionMs);
174
- return true;
175
- }
176
- /**
177
- * Long-poll waiting for a decision on a session.
178
- * Returns the decision or null on timeout.
179
- */
180
- awaitDecision(sessionId, timeoutMs) {
181
- const session = this.sessions.get(sessionId);
182
- if (!session) return Promise.resolve(null);
183
- if (session.status === "decided" && session.decisionPayload) {
184
- return Promise.resolve(session.decisionPayload);
185
- }
186
- const timeout = timeoutMs ?? this.longPollTimeoutMs;
187
- return new Promise((resolve) => {
188
- const waiters = this.awaitWaiters.get(sessionId) || [];
189
- const timer = setTimeout(() => {
190
- const idx = waiters.indexOf(onDecision);
191
- if (idx !== -1) waiters.splice(idx, 1);
192
- resolve(null);
193
- }, timeout);
194
- function onDecision(decision) {
195
- clearTimeout(timer);
196
- resolve(decision);
197
- }
198
- waiters.push(onDecision);
199
- this.awaitWaiters.set(sessionId, waiters);
200
- });
201
- }
202
- /**
203
- * Save annotations/version for a plan session.
204
- */
205
- async saveVersion(sessionId, data) {
206
- const session = this.sessions.get(sessionId);
207
- if (!session || session.type !== "plan" || !session.version || !session.slug) {
208
- return false;
209
- }
210
- const updatedVersion = {
211
- ...session.version,
212
- annotations: data.annotations || [],
213
- inlineEdits: data.inlineEdits || [],
214
- instructions: data.instructions || [],
215
- priorities: data.priorities || [],
216
- risks: data.risks || []
217
- };
218
- await savePlan(session.plan, updatedVersion, session.slug, session.projectPath);
219
- Object.assign(session.version, updatedVersion);
220
- return true;
221
- }
222
- /**
223
- * Get the session token (for loopback clients that need to pass it to the UI).
224
- */
225
- getSessionToken(id) {
226
- const session = this.sessions.get(id);
227
- return session?.token ?? null;
228
- }
229
- /**
230
- * Get the raw decision payload for a session (used by await endpoint).
231
- */
232
- getDecisionPayload(id) {
233
- const session = this.sessions.get(id);
234
- return session?.decisionPayload ?? null;
235
- }
236
- /**
237
- * Cleanup orphaned sessions (pending for over 1 hour).
238
- */
239
- cleanup() {
240
- const now = Date.now();
241
- for (const [id, session] of this.sessions) {
242
- if (session.status === "pending" && now - session.registeredAt > 60 * 60 * 1e3) {
243
- this.sessions.delete(id);
244
- this.awaitWaiters.delete(id);
245
- }
246
- }
247
- }
248
- /**
249
- * Remove sessions that have exceeded the TTL, regardless of status.
250
- */
251
- cleanupExpired() {
252
- const now = Date.now();
253
- for (const [id, session] of this.sessions) {
254
- if (now - session.registeredAt > _ReviewHub.SESSION_TTL_MS) {
255
- this.sessions.delete(id);
256
- this.awaitWaiters.delete(id);
257
- }
258
- }
259
- }
260
- toPublicSession(session) {
261
- const { resolveDecision, decisionPayload, token: _token, ...pub } = session;
262
- if (decisionPayload && !pub.decision) {
263
- if ("behavior" in decisionPayload) {
264
- pub.decision = {
265
- behavior: decisionPayload.behavior,
266
- message: decisionPayload.message,
267
- decidedAt: session.decidedAt ?? Date.now()
268
- };
269
- } else if ("approved" in decisionPayload) {
270
- pub.decision = {
271
- behavior: decisionPayload.approved ? "allow" : "deny",
272
- message: decisionPayload.message ?? decisionPayload.feedback,
273
- decidedAt: session.decidedAt ?? Date.now()
274
- };
275
- }
276
- }
277
- return pub;
278
- }
279
- };
280
- function isValidDecision(d) {
281
- if (!d || typeof d !== "object") return false;
282
- if ("behavior" in d) {
283
- return d.behavior === "allow" || d.behavior === "deny";
284
- }
285
- if ("approved" in d) {
286
- return typeof d.approved === "boolean";
287
- }
288
- return false;
289
- }
290
- var DISCOVERY_TIMEOUT_MS = 2e3;
291
- var MAX_PORTS_TO_PROBE = 5;
292
- function isProcessAlive(pid) {
293
- try {
294
- process.kill(pid, 0);
295
- return true;
296
- } catch {
297
- return false;
298
- }
299
- }
300
- function readLockFile() {
301
- try {
302
- const raw = fs.readFileSync(API_LOCK_FILE, "utf-8");
303
- const data = JSON.parse(raw);
304
- if (typeof data === "object" && data !== null && typeof data.port === "number" && typeof data.pid === "number") {
305
- const { port, pid, secret } = data;
306
- if (isProcessAlive(pid)) {
307
- return { port, secret };
308
- }
309
- try {
310
- fs.unlinkSync(API_LOCK_FILE);
311
- } catch {
312
- }
313
- }
314
- } catch {
315
- }
316
- return null;
317
- }
318
- async function healthCheck(host, port) {
319
- try {
320
- const controller = new AbortController();
321
- const timer = setTimeout(() => controller.abort(), DISCOVERY_TIMEOUT_MS);
322
- const res = await fetch(`http://${host}:${port}/api/health`, {
323
- signal: controller.signal
324
- });
325
- clearTimeout(timer);
326
- return res.ok;
327
- } catch {
328
- return false;
329
- }
330
- }
331
- async function discoverUlpiServer() {
332
- const host = getApiHost();
333
- const lockData = readLockFile();
334
- if (lockData !== null) {
335
- if (await healthCheck(host, lockData.port)) {
336
- return lockData;
337
- }
338
- }
339
- const configPort = getApiPort();
340
- const ports = [configPort, ...configPort !== 9800 ? [9800] : []].slice(0, MAX_PORTS_TO_PROBE);
341
- for (const port of ports) {
342
- if (port === lockData?.port) continue;
343
- if (await healthCheck(host, port)) {
344
- return { port };
345
- }
346
- }
347
- return null;
348
- }
349
- function buildHeaders(secret) {
350
- const headers = { "Content-Type": "application/json" };
351
- if (secret) headers["X-Ulpi-Secret"] = secret;
352
- return headers;
353
- }
354
- async function registerWithServer(port, payload, secret) {
355
- try {
356
- const host = getApiHost();
357
- const res = await fetch(`http://${host}:${port}/api/review/hub/register`, {
358
- method: "POST",
359
- headers: buildHeaders(secret),
360
- body: JSON.stringify(payload)
361
- });
362
- if (!res.ok) return null;
363
- const data = await res.json();
364
- return data;
365
- } catch {
366
- return null;
367
- }
368
- }
369
- async function waitForServerDecision(port, sessionId, timeoutMs = 3e4, maxWaitMs, token, secret) {
370
- const deadline = Date.now() + (maxWaitMs && maxWaitMs > 0 ? maxWaitMs : 10 * 60 * 1e3);
371
- const host = getApiHost();
372
- const tokenParam = token ? `?token=${encodeURIComponent(token)}` : "";
373
- const secretHeaders = secret ? { "X-Ulpi-Secret": secret } : {};
374
- while (Date.now() < deadline) {
375
- try {
376
- const controller = new AbortController();
377
- const timer = setTimeout(() => controller.abort(), timeoutMs + 5e3);
378
- const res = await fetch(
379
- `http://${host}:${port}/api/review/hub/session/${sessionId}/await${tokenParam}`,
380
- { signal: controller.signal, headers: secretHeaders }
381
- );
382
- clearTimeout(timer);
383
- if (res.status === 204) {
384
- continue;
385
- }
386
- if (res.ok) {
387
- const data = await res.json();
388
- return data.decision;
389
- }
390
- if (res.status === 410) {
391
- try {
392
- const data = await res.json();
393
- if (data.decision) return data.decision;
394
- } catch {
395
- }
396
- return null;
397
- }
398
- if (res.status >= 500) {
399
- await new Promise((resolve) => setTimeout(resolve, 2e3));
400
- continue;
401
- }
402
- return null;
403
- } catch {
404
- await new Promise((resolve) => setTimeout(resolve, 2e3));
405
- }
406
- }
407
- return null;
408
- }
409
-
410
- export {
411
- ReviewHub,
412
- discoverUlpiServer,
413
- registerWithServer,
414
- waitForServerDecision
415
- };
@@ -1,26 +0,0 @@
1
- import {
2
- JsonSessionStore,
3
- appendEvent,
4
- createEmptyState,
5
- createInitialState,
6
- detectNewCommit,
7
- nextPhase,
8
- projectDirToSlug,
9
- readEvents,
10
- updateStateFromInput,
11
- validateSessionId
12
- } from "./chunk-26LLDX2T.js";
13
- import "./chunk-DDRLI6JU.js";
14
- import "./chunk-4VNS5WPM.js";
15
- export {
16
- JsonSessionStore,
17
- appendEvent,
18
- createEmptyState,
19
- createInitialState,
20
- detectNewCommit,
21
- nextPhase,
22
- projectDirToSlug,
23
- readEvents,
24
- updateStateFromInput,
25
- validateSessionId
26
- };
@@ -1,124 +0,0 @@
1
- import {
2
- getBinaryPath
3
- } from "./chunk-DDRLI6JU.js";
4
- import "./chunk-4VNS5WPM.js";
5
-
6
- // src/mcp-installer.ts
7
- import * as fs from "fs";
8
- import * as path from "path";
9
- function installMcpServer(projectDir) {
10
- const settingsDir = path.join(projectDir, ".claude");
11
- const settingsPath = path.join(settingsDir, "settings.local.json");
12
- let settings = {};
13
- if (fs.existsSync(settingsPath)) {
14
- try {
15
- settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
16
- } catch {
17
- }
18
- }
19
- const mcpServers = settings.mcpServers ?? {};
20
- if (mcpServers["codemap"]) {
21
- return { installed: false, message: "CodeMap MCP server already registered" };
22
- }
23
- const binary = getBinaryPath();
24
- const parts = binary.split(" ");
25
- const command = parts[0];
26
- const baseArgs = parts.length > 1 ? [...parts.slice(1).map((a) => a.replace(/"/g, "")), "codemap", "serve"] : ["codemap", "serve"];
27
- mcpServers["codemap"] = {
28
- command,
29
- args: baseArgs
30
- };
31
- settings.mcpServers = mcpServers;
32
- fs.mkdirSync(settingsDir, { recursive: true });
33
- fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
34
- return { installed: true, message: "CodeMap MCP server registered in .claude/settings.local.json" };
35
- }
36
- function uninstallMcpServer(projectDir) {
37
- const settingsPath = path.join(projectDir, ".claude", "settings.local.json");
38
- if (!fs.existsSync(settingsPath)) return;
39
- try {
40
- const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
41
- const mcpServers = settings.mcpServers;
42
- if (mcpServers?.["codemap"]) {
43
- delete mcpServers["codemap"];
44
- if (Object.keys(mcpServers).length === 0) {
45
- delete settings.mcpServers;
46
- }
47
- fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
48
- }
49
- } catch {
50
- }
51
- }
52
- function isMcpServerInstalled(projectDir) {
53
- const settingsPath = path.join(projectDir, ".claude", "settings.local.json");
54
- if (!fs.existsSync(settingsPath)) return false;
55
- try {
56
- const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
57
- const mcpServers = settings.mcpServers;
58
- return !!mcpServers?.["codemap"];
59
- } catch {
60
- return false;
61
- }
62
- }
63
- function installMemoryMcpServer(projectDir) {
64
- const settingsDir = path.join(projectDir, ".claude");
65
- const settingsPath = path.join(settingsDir, "settings.local.json");
66
- let settings = {};
67
- if (fs.existsSync(settingsPath)) {
68
- try {
69
- settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
70
- } catch {
71
- }
72
- }
73
- const mcpServers = settings.mcpServers ?? {};
74
- if (mcpServers["memory"]) {
75
- return { installed: false, message: "Memory MCP server already registered" };
76
- }
77
- const binary = getBinaryPath();
78
- const parts = binary.split(" ");
79
- const command = parts[0];
80
- const baseArgs = parts.length > 1 ? [...parts.slice(1).map((a) => a.replace(/"/g, "")), "memory", "serve"] : ["memory", "serve"];
81
- mcpServers["memory"] = {
82
- command,
83
- args: baseArgs
84
- };
85
- settings.mcpServers = mcpServers;
86
- fs.mkdirSync(settingsDir, { recursive: true });
87
- fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
88
- return { installed: true, message: "Memory MCP server registered in .claude/settings.local.json" };
89
- }
90
- function uninstallMemoryMcpServer(projectDir) {
91
- const settingsPath = path.join(projectDir, ".claude", "settings.local.json");
92
- if (!fs.existsSync(settingsPath)) return;
93
- try {
94
- const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
95
- const mcpServers = settings.mcpServers;
96
- if (mcpServers?.["memory"]) {
97
- delete mcpServers["memory"];
98
- if (Object.keys(mcpServers).length === 0) {
99
- delete settings.mcpServers;
100
- }
101
- fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
102
- }
103
- } catch {
104
- }
105
- }
106
- function isMemoryMcpServerInstalled(projectDir) {
107
- const settingsPath = path.join(projectDir, ".claude", "settings.local.json");
108
- if (!fs.existsSync(settingsPath)) return false;
109
- try {
110
- const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
111
- const mcpServers = settings.mcpServers;
112
- return !!mcpServers?.["memory"];
113
- } catch {
114
- return false;
115
- }
116
- }
117
- export {
118
- installMcpServer,
119
- installMemoryMcpServer,
120
- isMcpServerInstalled,
121
- isMemoryMcpServerInstalled,
122
- uninstallMcpServer,
123
- uninstallMemoryMcpServer
124
- };