openkitt 0.2.5 → 0.2.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/dist/cli.js +922 -896
- package/package.json +1 -2
package/dist/cli.js
CHANGED
|
@@ -2192,8 +2192,66 @@ var require_picocolors = __commonJS((exports, module) => {
|
|
|
2192
2192
|
module.exports.createColors = createColors;
|
|
2193
2193
|
});
|
|
2194
2194
|
|
|
2195
|
+
// node_modules/sisteransi/src/index.js
|
|
2196
|
+
var require_src = __commonJS((exports, module) => {
|
|
2197
|
+
var ESC = "\x1B";
|
|
2198
|
+
var CSI = `${ESC}[`;
|
|
2199
|
+
var beep = "\x07";
|
|
2200
|
+
var cursor = {
|
|
2201
|
+
to(x, y) {
|
|
2202
|
+
if (!y)
|
|
2203
|
+
return `${CSI}${x + 1}G`;
|
|
2204
|
+
return `${CSI}${y + 1};${x + 1}H`;
|
|
2205
|
+
},
|
|
2206
|
+
move(x, y) {
|
|
2207
|
+
let ret = "";
|
|
2208
|
+
if (x < 0)
|
|
2209
|
+
ret += `${CSI}${-x}D`;
|
|
2210
|
+
else if (x > 0)
|
|
2211
|
+
ret += `${CSI}${x}C`;
|
|
2212
|
+
if (y < 0)
|
|
2213
|
+
ret += `${CSI}${-y}A`;
|
|
2214
|
+
else if (y > 0)
|
|
2215
|
+
ret += `${CSI}${y}B`;
|
|
2216
|
+
return ret;
|
|
2217
|
+
},
|
|
2218
|
+
up: (count = 1) => `${CSI}${count}A`,
|
|
2219
|
+
down: (count = 1) => `${CSI}${count}B`,
|
|
2220
|
+
forward: (count = 1) => `${CSI}${count}C`,
|
|
2221
|
+
backward: (count = 1) => `${CSI}${count}D`,
|
|
2222
|
+
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
|
2223
|
+
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
|
2224
|
+
left: `${CSI}G`,
|
|
2225
|
+
hide: `${CSI}?25l`,
|
|
2226
|
+
show: `${CSI}?25h`,
|
|
2227
|
+
save: `${ESC}7`,
|
|
2228
|
+
restore: `${ESC}8`
|
|
2229
|
+
};
|
|
2230
|
+
var scroll = {
|
|
2231
|
+
up: (count = 1) => `${CSI}S`.repeat(count),
|
|
2232
|
+
down: (count = 1) => `${CSI}T`.repeat(count)
|
|
2233
|
+
};
|
|
2234
|
+
var erase = {
|
|
2235
|
+
screen: `${CSI}2J`,
|
|
2236
|
+
up: (count = 1) => `${CSI}1J`.repeat(count),
|
|
2237
|
+
down: (count = 1) => `${CSI}J`.repeat(count),
|
|
2238
|
+
line: `${CSI}2K`,
|
|
2239
|
+
lineEnd: `${CSI}K`,
|
|
2240
|
+
lineStart: `${CSI}1K`,
|
|
2241
|
+
lines(count) {
|
|
2242
|
+
let clear = "";
|
|
2243
|
+
for (let i = 0;i < count; i++)
|
|
2244
|
+
clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
2245
|
+
if (count)
|
|
2246
|
+
clear += cursor.left;
|
|
2247
|
+
return clear;
|
|
2248
|
+
}
|
|
2249
|
+
};
|
|
2250
|
+
module.exports = { cursor, scroll, erase, beep };
|
|
2251
|
+
});
|
|
2252
|
+
|
|
2195
2253
|
// src/credentials/encryption.ts
|
|
2196
|
-
import { execSync } from "node:child_process";
|
|
2254
|
+
import { execSync as execSync2 } from "node:child_process";
|
|
2197
2255
|
import {
|
|
2198
2256
|
createCipheriv,
|
|
2199
2257
|
createDecipheriv,
|
|
@@ -2209,7 +2267,7 @@ function getMachineId() {
|
|
|
2209
2267
|
const currentPlatform = platform();
|
|
2210
2268
|
if (currentPlatform === "darwin") {
|
|
2211
2269
|
try {
|
|
2212
|
-
const output =
|
|
2270
|
+
const output = execSync2("ioreg -rd1 -c IOPlatformExpertDevice", {
|
|
2213
2271
|
encoding: "utf-8",
|
|
2214
2272
|
stdio: "pipe"
|
|
2215
2273
|
});
|
|
@@ -2231,7 +2289,7 @@ function getMachineId() {
|
|
|
2231
2289
|
}
|
|
2232
2290
|
if (currentPlatform === "win32") {
|
|
2233
2291
|
try {
|
|
2234
|
-
const output =
|
|
2292
|
+
const output = execSync2('reg query "HKLM\\SOFTWARE\\Microsoft\\Cryptography" /v MachineGuid', {
|
|
2235
2293
|
encoding: "utf-8",
|
|
2236
2294
|
stdio: "pipe"
|
|
2237
2295
|
});
|
|
@@ -2298,17 +2356,17 @@ function isNotFoundError(errorMessage) {
|
|
|
2298
2356
|
const normalized = errorMessage.toLowerCase();
|
|
2299
2357
|
return normalized.includes("could not be found") || normalized.includes("item not found") || normalized.includes("not found") || normalized.includes("element not found");
|
|
2300
2358
|
}
|
|
2301
|
-
function getErrorMessage(
|
|
2302
|
-
if (
|
|
2303
|
-
const maybeStderr =
|
|
2359
|
+
function getErrorMessage(error2) {
|
|
2360
|
+
if (error2 instanceof Error) {
|
|
2361
|
+
const maybeStderr = error2.stderr;
|
|
2304
2362
|
if (typeof maybeStderr === "string" && maybeStderr.trim().length > 0) {
|
|
2305
2363
|
return maybeStderr.trim();
|
|
2306
2364
|
}
|
|
2307
2365
|
if (Buffer.isBuffer(maybeStderr) && maybeStderr.length > 0) {
|
|
2308
2366
|
return maybeStderr.toString("utf-8").trim();
|
|
2309
2367
|
}
|
|
2310
|
-
if (
|
|
2311
|
-
return
|
|
2368
|
+
if (error2.message.trim().length > 0) {
|
|
2369
|
+
return error2.message.trim();
|
|
2312
2370
|
}
|
|
2313
2371
|
}
|
|
2314
2372
|
return "Unknown keychain error";
|
|
@@ -2450,8 +2508,8 @@ async function setKeychainValue(key, value) {
|
|
|
2450
2508
|
default:
|
|
2451
2509
|
return { success: false, error: "Unsupported platform" };
|
|
2452
2510
|
}
|
|
2453
|
-
} catch (
|
|
2454
|
-
return { success: false, error: getErrorMessage(
|
|
2511
|
+
} catch (error2) {
|
|
2512
|
+
return { success: false, error: getErrorMessage(error2) };
|
|
2455
2513
|
}
|
|
2456
2514
|
}
|
|
2457
2515
|
async function getKeychainValue(key) {
|
|
@@ -2476,8 +2534,8 @@ async function getKeychainValue(key) {
|
|
|
2476
2534
|
default:
|
|
2477
2535
|
return null;
|
|
2478
2536
|
}
|
|
2479
|
-
} catch (
|
|
2480
|
-
const errorMessage = getErrorMessage(
|
|
2537
|
+
} catch (error2) {
|
|
2538
|
+
const errorMessage = getErrorMessage(error2);
|
|
2481
2539
|
if (isNotFoundError(errorMessage)) {
|
|
2482
2540
|
return null;
|
|
2483
2541
|
}
|
|
@@ -2509,8 +2567,8 @@ async function deleteKeychainValue(key) {
|
|
|
2509
2567
|
default:
|
|
2510
2568
|
return { success: false, error: "Unsupported platform" };
|
|
2511
2569
|
}
|
|
2512
|
-
} catch (
|
|
2513
|
-
const errorMessage = getErrorMessage(
|
|
2570
|
+
} catch (error2) {
|
|
2571
|
+
const errorMessage = getErrorMessage(error2);
|
|
2514
2572
|
if (isNotFoundError(errorMessage)) {
|
|
2515
2573
|
return { success: true };
|
|
2516
2574
|
}
|
|
@@ -2530,9 +2588,9 @@ __export(exports_config, {
|
|
|
2530
2588
|
getLlmApiKey: () => getLlmApiKey,
|
|
2531
2589
|
clearLlmCredentials: () => clearLlmCredentials
|
|
2532
2590
|
});
|
|
2533
|
-
import { chmodSync, existsSync, mkdirSync, readFileSync as readFileSync2, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2591
|
+
import { chmodSync, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2, statSync as statSync2, unlinkSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
2534
2592
|
import { homedir, platform as platform2 } from "node:os";
|
|
2535
|
-
import { join } from "node:path";
|
|
2593
|
+
import { join as join3 } from "node:path";
|
|
2536
2594
|
function isWindows() {
|
|
2537
2595
|
return platform2() === "win32";
|
|
2538
2596
|
}
|
|
@@ -2541,18 +2599,18 @@ function hasExtraPermissionBits(actualMode, allowedMode) {
|
|
|
2541
2599
|
return (activeBits & ~allowedMode) !== 0;
|
|
2542
2600
|
}
|
|
2543
2601
|
function ensurePermissions(path, mode) {
|
|
2544
|
-
if (isWindows() || !
|
|
2602
|
+
if (isWindows() || !existsSync3(path)) {
|
|
2545
2603
|
return;
|
|
2546
2604
|
}
|
|
2547
|
-
const currentMode =
|
|
2605
|
+
const currentMode = statSync2(path).mode;
|
|
2548
2606
|
if (hasExtraPermissionBits(currentMode, mode)) {
|
|
2549
2607
|
console.warn(`[kitt] Detected permissive config permissions for ${path}. Auto-fixing.`);
|
|
2550
2608
|
chmodSync(path, mode);
|
|
2551
2609
|
}
|
|
2552
2610
|
}
|
|
2553
2611
|
function ensureConfigDir() {
|
|
2554
|
-
if (!
|
|
2555
|
-
|
|
2612
|
+
if (!existsSync3(CONFIG_DIR)) {
|
|
2613
|
+
mkdirSync2(CONFIG_DIR, { recursive: true, mode: DIR_MODE });
|
|
2556
2614
|
}
|
|
2557
2615
|
if (!isWindows()) {
|
|
2558
2616
|
ensurePermissions(CONFIG_DIR, DIR_MODE);
|
|
@@ -2560,7 +2618,7 @@ function ensureConfigDir() {
|
|
|
2560
2618
|
}
|
|
2561
2619
|
function readConfig() {
|
|
2562
2620
|
ensureConfigDir();
|
|
2563
|
-
if (!
|
|
2621
|
+
if (!existsSync3(CONFIG_FILE)) {
|
|
2564
2622
|
return {};
|
|
2565
2623
|
}
|
|
2566
2624
|
if (!isWindows()) {
|
|
@@ -2582,19 +2640,19 @@ function writeConfig(config) {
|
|
|
2582
2640
|
const payload = `${JSON.stringify(config, null, 2)}
|
|
2583
2641
|
`;
|
|
2584
2642
|
try {
|
|
2585
|
-
|
|
2643
|
+
writeFileSync2(tempFile, payload, { encoding: "utf-8", mode: FILE_MODE });
|
|
2586
2644
|
if (!isWindows()) {
|
|
2587
2645
|
chmodSync(tempFile, FILE_MODE);
|
|
2588
2646
|
}
|
|
2589
|
-
|
|
2647
|
+
renameSync2(tempFile, CONFIG_FILE);
|
|
2590
2648
|
if (!isWindows()) {
|
|
2591
2649
|
chmodSync(CONFIG_FILE, FILE_MODE);
|
|
2592
2650
|
}
|
|
2593
|
-
} catch (
|
|
2594
|
-
if (
|
|
2651
|
+
} catch (error2) {
|
|
2652
|
+
if (existsSync3(tempFile)) {
|
|
2595
2653
|
unlinkSync(tempFile);
|
|
2596
2654
|
}
|
|
2597
|
-
throw
|
|
2655
|
+
throw error2;
|
|
2598
2656
|
}
|
|
2599
2657
|
}
|
|
2600
2658
|
function isStoredProvider(value) {
|
|
@@ -2718,66 +2776,8 @@ var CONFIG_DIR, CONFIG_FILE, KEYCHAIN_API_KEY = "llm-api-key", DIR_MODE = 448, F
|
|
|
2718
2776
|
var init_config = __esm(() => {
|
|
2719
2777
|
init_encryption();
|
|
2720
2778
|
init_keychain();
|
|
2721
|
-
CONFIG_DIR =
|
|
2722
|
-
CONFIG_FILE =
|
|
2723
|
-
});
|
|
2724
|
-
|
|
2725
|
-
// node_modules/sisteransi/src/index.js
|
|
2726
|
-
var require_src = __commonJS((exports, module) => {
|
|
2727
|
-
var ESC = "\x1B";
|
|
2728
|
-
var CSI = `${ESC}[`;
|
|
2729
|
-
var beep = "\x07";
|
|
2730
|
-
var cursor = {
|
|
2731
|
-
to(x, y) {
|
|
2732
|
-
if (!y)
|
|
2733
|
-
return `${CSI}${x + 1}G`;
|
|
2734
|
-
return `${CSI}${y + 1};${x + 1}H`;
|
|
2735
|
-
},
|
|
2736
|
-
move(x, y) {
|
|
2737
|
-
let ret = "";
|
|
2738
|
-
if (x < 0)
|
|
2739
|
-
ret += `${CSI}${-x}D`;
|
|
2740
|
-
else if (x > 0)
|
|
2741
|
-
ret += `${CSI}${x}C`;
|
|
2742
|
-
if (y < 0)
|
|
2743
|
-
ret += `${CSI}${-y}A`;
|
|
2744
|
-
else if (y > 0)
|
|
2745
|
-
ret += `${CSI}${y}B`;
|
|
2746
|
-
return ret;
|
|
2747
|
-
},
|
|
2748
|
-
up: (count = 1) => `${CSI}${count}A`,
|
|
2749
|
-
down: (count = 1) => `${CSI}${count}B`,
|
|
2750
|
-
forward: (count = 1) => `${CSI}${count}C`,
|
|
2751
|
-
backward: (count = 1) => `${CSI}${count}D`,
|
|
2752
|
-
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
|
2753
|
-
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
|
2754
|
-
left: `${CSI}G`,
|
|
2755
|
-
hide: `${CSI}?25l`,
|
|
2756
|
-
show: `${CSI}?25h`,
|
|
2757
|
-
save: `${ESC}7`,
|
|
2758
|
-
restore: `${ESC}8`
|
|
2759
|
-
};
|
|
2760
|
-
var scroll = {
|
|
2761
|
-
up: (count = 1) => `${CSI}S`.repeat(count),
|
|
2762
|
-
down: (count = 1) => `${CSI}T`.repeat(count)
|
|
2763
|
-
};
|
|
2764
|
-
var erase = {
|
|
2765
|
-
screen: `${CSI}2J`,
|
|
2766
|
-
up: (count = 1) => `${CSI}1J`.repeat(count),
|
|
2767
|
-
down: (count = 1) => `${CSI}J`.repeat(count),
|
|
2768
|
-
line: `${CSI}2K`,
|
|
2769
|
-
lineEnd: `${CSI}K`,
|
|
2770
|
-
lineStart: `${CSI}1K`,
|
|
2771
|
-
lines(count) {
|
|
2772
|
-
let clear = "";
|
|
2773
|
-
for (let i = 0;i < count; i++)
|
|
2774
|
-
clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
2775
|
-
if (count)
|
|
2776
|
-
clear += cursor.left;
|
|
2777
|
-
return clear;
|
|
2778
|
-
}
|
|
2779
|
-
};
|
|
2780
|
-
module.exports = { cursor, scroll, erase, beep };
|
|
2779
|
+
CONFIG_DIR = join3(homedir(), ".kitt");
|
|
2780
|
+
CONFIG_FILE = join3(CONFIG_DIR, "config.json");
|
|
2781
2781
|
});
|
|
2782
2782
|
|
|
2783
2783
|
// node_modules/@anthropic-ai/sdk/internal/tslib.mjs
|
|
@@ -185957,7 +185957,7 @@ var require_path_browserify = __commonJS((exports, module) => {
|
|
|
185957
185957
|
_makeLong: function _makeLong(path3) {
|
|
185958
185958
|
return path3;
|
|
185959
185959
|
},
|
|
185960
|
-
dirname: function
|
|
185960
|
+
dirname: function dirname4(path3) {
|
|
185961
185961
|
assertPath(path3);
|
|
185962
185962
|
if (path3.length === 0)
|
|
185963
185963
|
return ".";
|
|
@@ -255595,497 +255595,118 @@ var {
|
|
|
255595
255595
|
var import_picocolors12 = __toESM(require_picocolors(), 1);
|
|
255596
255596
|
import { createInterface, emitKeypressEvents } from "node:readline";
|
|
255597
255597
|
import { stdin as input, stdout as output } from "node:process";
|
|
255598
|
-
import { existsSync as
|
|
255598
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync13, writeFileSync as writeFileSync15, realpathSync } from "node:fs";
|
|
255599
255599
|
import { homedir as homedir4 } from "node:os";
|
|
255600
|
-
import { join as join23, resolve as resolve6, dirname as
|
|
255600
|
+
import { join as join23, resolve as resolve6, dirname as dirname5 } from "node:path";
|
|
255601
255601
|
import { pathToFileURL } from "node:url";
|
|
255602
255602
|
|
|
255603
255603
|
// src/utils/prerequisites.ts
|
|
255604
|
-
|
|
255605
|
-
import { execSync as execSync2 } from "node:child_process";
|
|
255606
|
-
function getNodeVersion() {
|
|
255607
|
-
try {
|
|
255608
|
-
const output = execSync2("node --version", {
|
|
255609
|
-
encoding: "utf-8",
|
|
255610
|
-
stdio: "pipe"
|
|
255611
|
-
}).trim();
|
|
255612
|
-
return output.replace(/^v/, "");
|
|
255613
|
-
} catch {
|
|
255614
|
-
return "";
|
|
255615
|
-
}
|
|
255616
|
-
}
|
|
255617
|
-
function getBunVersion() {
|
|
255618
|
-
try {
|
|
255619
|
-
const output = execSync2("bun --version", {
|
|
255620
|
-
encoding: "utf-8",
|
|
255621
|
-
stdio: "pipe"
|
|
255622
|
-
}).trim();
|
|
255623
|
-
return output;
|
|
255624
|
-
} catch {
|
|
255625
|
-
return null;
|
|
255626
|
-
}
|
|
255627
|
-
}
|
|
255628
|
-
function getRailwayVersion() {
|
|
255629
|
-
try {
|
|
255630
|
-
const output = execSync2("railway --version", {
|
|
255631
|
-
encoding: "utf-8",
|
|
255632
|
-
stdio: "pipe"
|
|
255633
|
-
}).trim();
|
|
255634
|
-
return output || null;
|
|
255635
|
-
} catch {
|
|
255636
|
-
return null;
|
|
255637
|
-
}
|
|
255638
|
-
}
|
|
255639
|
-
async function checkPrerequisites() {
|
|
255640
|
-
const nodeVersion = getNodeVersion();
|
|
255641
|
-
const bunVersion = getBunVersion();
|
|
255642
|
-
const railwayVersion = getRailwayVersion();
|
|
255643
|
-
return [
|
|
255644
|
-
{
|
|
255645
|
-
name: "Node.js",
|
|
255646
|
-
found: !!nodeVersion,
|
|
255647
|
-
version: nodeVersion || undefined
|
|
255648
|
-
},
|
|
255649
|
-
{
|
|
255650
|
-
name: "Bun",
|
|
255651
|
-
found: !!bunVersion,
|
|
255652
|
-
version: bunVersion || undefined,
|
|
255653
|
-
installUrl: bunVersion ? undefined : "https://bun.sh"
|
|
255654
|
-
},
|
|
255655
|
-
{
|
|
255656
|
-
name: "Railway CLI",
|
|
255657
|
-
found: !!railwayVersion,
|
|
255658
|
-
version: railwayVersion || undefined,
|
|
255659
|
-
installUrl: railwayVersion ? undefined : "https://docs.railway.com/cli"
|
|
255660
|
-
}
|
|
255661
|
-
];
|
|
255662
|
-
}
|
|
255663
|
-
function displayPrerequisites(statuses) {
|
|
255664
|
-
for (const status of statuses) {
|
|
255665
|
-
if (status.found) {
|
|
255666
|
-
const version = status.version ? `v${status.version}` : "";
|
|
255667
|
-
const paddedName = status.name.padEnd(12);
|
|
255668
|
-
console.log(` ${import_picocolors.default.green("✓")} ${paddedName} ${version}`);
|
|
255669
|
-
} else {
|
|
255670
|
-
const paddedName = status.name.padEnd(12);
|
|
255671
|
-
const installMsg = status.installUrl ? `not found. Install: ${status.installUrl}` : "not found";
|
|
255672
|
-
console.log(` ${import_picocolors.default.red("✗")} ${paddedName} ${installMsg}`);
|
|
255673
|
-
}
|
|
255674
|
-
}
|
|
255675
|
-
}
|
|
255676
|
-
async function displayLlmStatus() {
|
|
255677
|
-
const paddedName = "LLM".padEnd(12);
|
|
255678
|
-
try {
|
|
255679
|
-
const { isLlmConfigured: isLlmConfigured2, getLlmConfig: getLlmConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
255680
|
-
const [configured, config] = await Promise.all([isLlmConfigured2(), getLlmConfig2()]);
|
|
255681
|
-
if (configured && config) {
|
|
255682
|
-
const label = `${config.provider[0].toUpperCase()}${config.provider.slice(1)} (${config.model})`;
|
|
255683
|
-
console.log(` ${import_picocolors.default.green("✓")} ${paddedName} ${label}`);
|
|
255684
|
-
} else {
|
|
255685
|
-
console.log(` ${import_picocolors.default.yellow("!")} ${paddedName} not configured`);
|
|
255686
|
-
}
|
|
255687
|
-
} catch {
|
|
255688
|
-
console.log(` ${import_picocolors.default.yellow("!")} ${paddedName} not configured`);
|
|
255689
|
-
}
|
|
255690
|
-
}
|
|
255691
|
-
|
|
255692
|
-
// src/manifest/reader.ts
|
|
255693
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
|
|
255694
|
-
import { join as join4, dirname as dirname2, resolve } from "node:path";
|
|
255604
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
255695
255605
|
|
|
255696
|
-
// src/
|
|
255697
|
-
import {
|
|
255698
|
-
import {
|
|
255606
|
+
// src/mcp/lifecycle.ts
|
|
255607
|
+
import { spawn, execSync } from "node:child_process";
|
|
255608
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
255699
255609
|
import { join as join2 } from "node:path";
|
|
255700
|
-
function getGlobalConfigPath() {
|
|
255701
|
-
return join2(homedir2(), ".kitt", "workspace.json");
|
|
255702
|
-
}
|
|
255703
|
-
function readGlobalConfig() {
|
|
255704
|
-
const configPath = getGlobalConfigPath();
|
|
255705
|
-
if (!existsSync2(configPath)) {
|
|
255706
|
-
return {};
|
|
255707
|
-
}
|
|
255708
|
-
try {
|
|
255709
|
-
const raw = readFileSync3(configPath, "utf-8").trim();
|
|
255710
|
-
if (!raw)
|
|
255711
|
-
return {};
|
|
255712
|
-
const parsed = JSON.parse(raw);
|
|
255713
|
-
if (typeof parsed === "object" && parsed !== null) {
|
|
255714
|
-
return parsed;
|
|
255715
|
-
}
|
|
255716
|
-
return {};
|
|
255717
|
-
} catch {
|
|
255718
|
-
return {};
|
|
255719
|
-
}
|
|
255720
|
-
}
|
|
255721
|
-
function writeGlobalConfig(config) {
|
|
255722
|
-
const configPath = getGlobalConfigPath();
|
|
255723
|
-
const configDir = join2(homedir2(), ".kitt");
|
|
255724
|
-
mkdirSync2(configDir, { recursive: true });
|
|
255725
|
-
writeFileSync2(configPath, JSON.stringify(config, null, 2) + `
|
|
255726
|
-
`, "utf-8");
|
|
255727
|
-
}
|
|
255728
|
-
function setGlobalWorkspacePath(workspacePath) {
|
|
255729
|
-
const existing = readGlobalConfig();
|
|
255730
|
-
writeGlobalConfig({ ...existing, workspacePath });
|
|
255731
|
-
}
|
|
255732
|
-
function getGlobalWorkspacePath() {
|
|
255733
|
-
return readGlobalConfig().workspacePath ?? null;
|
|
255734
|
-
}
|
|
255735
255610
|
|
|
255736
|
-
// src/
|
|
255737
|
-
import {
|
|
255738
|
-
|
|
255739
|
-
|
|
255740
|
-
|
|
255741
|
-
|
|
255742
|
-
|
|
255743
|
-
|
|
255744
|
-
|
|
255745
|
-
}
|
|
255746
|
-
|
|
255747
|
-
|
|
255748
|
-
|
|
255749
|
-
|
|
255750
|
-
|
|
255751
|
-
|
|
255752
|
-
|
|
255753
|
-
}
|
|
255754
|
-
}
|
|
255755
|
-
function writeManifest(workspaceDir, manifest) {
|
|
255756
|
-
const manifestPath = getManifestPath(workspaceDir);
|
|
255757
|
-
const manifestDir = dirname(manifestPath);
|
|
255758
|
-
const tempFile = join3(manifestDir, `manifest.json.tmp-${process.pid}-${Date.now()}`);
|
|
255759
|
-
const payload = `${JSON.stringify(manifest, null, 2)}
|
|
255611
|
+
// src/audit/logger.ts
|
|
255612
|
+
import {
|
|
255613
|
+
appendFileSync,
|
|
255614
|
+
existsSync,
|
|
255615
|
+
mkdirSync,
|
|
255616
|
+
renameSync,
|
|
255617
|
+
rmSync,
|
|
255618
|
+
statSync,
|
|
255619
|
+
writeFileSync
|
|
255620
|
+
} from "node:fs";
|
|
255621
|
+
import { join } from "node:path";
|
|
255622
|
+
var AUDIT_DIR_NAME = ".kitt";
|
|
255623
|
+
var AUDIT_FILE_NAME = "audit.log";
|
|
255624
|
+
var ROTATED_LOG_1 = "audit.log.1";
|
|
255625
|
+
var ROTATED_LOG_2 = "audit.log.2";
|
|
255626
|
+
var MAX_LOG_SIZE_BYTES = 10 * 1024 * 1024;
|
|
255627
|
+
function formatLine(type, message) {
|
|
255628
|
+
return `[${new Date().toISOString()}] ${type} ${message}
|
|
255760
255629
|
`;
|
|
255761
|
-
ensureKittDir(manifestPath);
|
|
255762
|
-
try {
|
|
255763
|
-
writeFileSync3(tempFile, payload, { encoding: "utf-8", mode: FILE_MODE2 });
|
|
255764
|
-
if (!isWindows2()) {
|
|
255765
|
-
chmodSync2(tempFile, FILE_MODE2);
|
|
255766
|
-
}
|
|
255767
|
-
renameSync2(tempFile, manifestPath);
|
|
255768
|
-
if (!isWindows2()) {
|
|
255769
|
-
chmodSync2(manifestPath, FILE_MODE2);
|
|
255770
|
-
}
|
|
255771
|
-
} catch (error) {
|
|
255772
|
-
if (existsSync3(tempFile)) {
|
|
255773
|
-
unlinkSync2(tempFile);
|
|
255774
|
-
}
|
|
255775
|
-
throw error;
|
|
255776
|
-
}
|
|
255777
|
-
}
|
|
255778
|
-
function createInitialManifest(workspaceName, packageManager, railway) {
|
|
255779
|
-
return {
|
|
255780
|
-
version: MANIFEST_VERSION,
|
|
255781
|
-
workspace: {
|
|
255782
|
-
name: workspaceName,
|
|
255783
|
-
packageManager,
|
|
255784
|
-
...railway ? { railway } : {}
|
|
255785
|
-
},
|
|
255786
|
-
settings: {},
|
|
255787
|
-
apps: {},
|
|
255788
|
-
packages: {}
|
|
255789
|
-
};
|
|
255790
255630
|
}
|
|
255791
|
-
function
|
|
255792
|
-
|
|
255793
|
-
|
|
255794
|
-
apps: {
|
|
255795
|
-
...manifest.apps,
|
|
255796
|
-
[name]: app
|
|
255797
|
-
}
|
|
255798
|
-
};
|
|
255799
|
-
}
|
|
255800
|
-
function removeApp(manifest, name) {
|
|
255801
|
-
const nextApps = { ...manifest.apps };
|
|
255802
|
-
delete nextApps[name];
|
|
255803
|
-
const nextPackages = {};
|
|
255804
|
-
for (const [packageName, pkg] of Object.entries(manifest.packages)) {
|
|
255805
|
-
nextPackages[packageName] = {
|
|
255806
|
-
...pkg,
|
|
255807
|
-
consumers: pkg.consumers.filter((consumer) => consumer !== name)
|
|
255808
|
-
};
|
|
255809
|
-
}
|
|
255810
|
-
return {
|
|
255811
|
-
...manifest,
|
|
255812
|
-
apps: nextApps,
|
|
255813
|
-
packages: nextPackages
|
|
255814
|
-
};
|
|
255815
|
-
}
|
|
255816
|
-
function addPackage(manifest, name, pkg) {
|
|
255817
|
-
return {
|
|
255818
|
-
...manifest,
|
|
255819
|
-
packages: {
|
|
255820
|
-
...manifest.packages,
|
|
255821
|
-
[name]: pkg
|
|
255822
|
-
}
|
|
255823
|
-
};
|
|
255824
|
-
}
|
|
255825
|
-
function addConsumer(manifest, packageName, appName) {
|
|
255826
|
-
const pkg = manifest.packages[packageName];
|
|
255827
|
-
if (!pkg) {
|
|
255828
|
-
return {
|
|
255829
|
-
...manifest,
|
|
255830
|
-
packages: {
|
|
255831
|
-
...manifest.packages
|
|
255832
|
-
}
|
|
255833
|
-
};
|
|
255834
|
-
}
|
|
255835
|
-
const consumers = pkg.consumers.includes(appName) ? [...pkg.consumers] : [...pkg.consumers, appName];
|
|
255836
|
-
return {
|
|
255837
|
-
...manifest,
|
|
255838
|
-
packages: {
|
|
255839
|
-
...manifest.packages,
|
|
255840
|
-
[packageName]: {
|
|
255841
|
-
...pkg,
|
|
255842
|
-
consumers
|
|
255843
|
-
}
|
|
255844
|
-
}
|
|
255845
|
-
};
|
|
255846
|
-
}
|
|
255847
|
-
|
|
255848
|
-
// src/manifest/reader.ts
|
|
255849
|
-
function isObjectRecord(value) {
|
|
255850
|
-
return typeof value === "object" && value !== null;
|
|
255851
|
-
}
|
|
255852
|
-
function isValidWorkspaceManifest(value) {
|
|
255853
|
-
if (!isObjectRecord(value)) {
|
|
255854
|
-
return false;
|
|
255855
|
-
}
|
|
255856
|
-
if (typeof value.version !== "string") {
|
|
255857
|
-
return false;
|
|
255858
|
-
}
|
|
255859
|
-
if (!isObjectRecord(value.workspace)) {
|
|
255860
|
-
return false;
|
|
255861
|
-
}
|
|
255862
|
-
if (typeof value.workspace.name !== "string") {
|
|
255863
|
-
return false;
|
|
255864
|
-
}
|
|
255865
|
-
const packageManager = value.workspace.packageManager;
|
|
255866
|
-
if (packageManager !== "bun" && packageManager !== "npm" && packageManager !== "pnpm" && packageManager !== "yarn") {
|
|
255867
|
-
return false;
|
|
255868
|
-
}
|
|
255869
|
-
if (!isObjectRecord(value.apps)) {
|
|
255870
|
-
return false;
|
|
255871
|
-
}
|
|
255872
|
-
if (!isObjectRecord(value.packages)) {
|
|
255873
|
-
return false;
|
|
255874
|
-
}
|
|
255875
|
-
if (!isObjectRecord(value.settings)) {
|
|
255876
|
-
return false;
|
|
255877
|
-
}
|
|
255878
|
-
return true;
|
|
255879
|
-
}
|
|
255880
|
-
function getManifestPath(workspaceDir) {
|
|
255881
|
-
return join4(workspaceDir, ".kitt", "manifest.json");
|
|
255882
|
-
}
|
|
255883
|
-
function isKittWorkspace(dir) {
|
|
255884
|
-
return existsSync4(getManifestPath(dir));
|
|
255885
|
-
}
|
|
255886
|
-
function findWorkspaceRoot(startDir) {
|
|
255887
|
-
let current = resolve(startDir);
|
|
255888
|
-
while (true) {
|
|
255889
|
-
if (isKittWorkspace(current))
|
|
255890
|
-
return current;
|
|
255891
|
-
const parent = dirname2(current);
|
|
255892
|
-
if (parent === current)
|
|
255893
|
-
break;
|
|
255894
|
-
current = parent;
|
|
255895
|
-
}
|
|
255896
|
-
const globalPath = getGlobalWorkspacePath();
|
|
255897
|
-
if (globalPath && isKittWorkspace(globalPath))
|
|
255898
|
-
return globalPath;
|
|
255899
|
-
return null;
|
|
255900
|
-
}
|
|
255901
|
-
function findWorkspaceRootStrict(startDir) {
|
|
255902
|
-
let current = resolve(startDir);
|
|
255903
|
-
while (true) {
|
|
255904
|
-
if (isKittWorkspace(current))
|
|
255905
|
-
return current;
|
|
255906
|
-
const parent = dirname2(current);
|
|
255907
|
-
if (parent === current)
|
|
255908
|
-
break;
|
|
255909
|
-
current = parent;
|
|
255910
|
-
}
|
|
255911
|
-
return null;
|
|
255912
|
-
}
|
|
255913
|
-
function readManifest(workspaceDir) {
|
|
255914
|
-
const manifestPath = getManifestPath(workspaceDir);
|
|
255915
|
-
if (!existsSync4(manifestPath)) {
|
|
255916
|
-
return null;
|
|
255917
|
-
}
|
|
255918
|
-
try {
|
|
255919
|
-
const raw = readFileSync4(manifestPath, "utf-8").trim();
|
|
255920
|
-
if (raw.length === 0) {
|
|
255921
|
-
return null;
|
|
255922
|
-
}
|
|
255923
|
-
const parsed = JSON.parse(raw);
|
|
255924
|
-
if (!isValidWorkspaceManifest(parsed)) {
|
|
255925
|
-
return null;
|
|
255926
|
-
}
|
|
255927
|
-
return parsed;
|
|
255928
|
-
} catch {
|
|
255929
|
-
return null;
|
|
255930
|
-
}
|
|
255931
|
-
}
|
|
255932
|
-
function reconcileManifest(workspaceDir) {
|
|
255933
|
-
const manifest = readManifest(workspaceDir);
|
|
255934
|
-
if (!manifest)
|
|
255935
|
-
return null;
|
|
255936
|
-
const staleApps = Object.keys(manifest.apps).filter((name) => !existsSync4(join4(workspaceDir, "apps", name)));
|
|
255937
|
-
if (staleApps.length === 0)
|
|
255938
|
-
return manifest;
|
|
255939
|
-
let cleaned = manifest;
|
|
255940
|
-
for (const name of staleApps) {
|
|
255941
|
-
cleaned = removeApp(cleaned, name);
|
|
255631
|
+
function ensureAuditDir(auditDir) {
|
|
255632
|
+
if (existsSync(auditDir)) {
|
|
255633
|
+
return;
|
|
255942
255634
|
}
|
|
255943
|
-
|
|
255944
|
-
return cleaned;
|
|
255635
|
+
mkdirSync(auditDir, { recursive: true, mode: 448 });
|
|
255945
255636
|
}
|
|
255946
|
-
|
|
255947
|
-
|
|
255948
|
-
|
|
255949
|
-
|
|
255950
|
-
// src/credentials/railway.ts
|
|
255951
|
-
import { execSync as execSync3 } from "node:child_process";
|
|
255952
|
-
async function isRailwayInstalled() {
|
|
255953
|
-
try {
|
|
255954
|
-
execSync3("railway --version", {
|
|
255955
|
-
encoding: "utf-8",
|
|
255956
|
-
stdio: "pipe"
|
|
255957
|
-
});
|
|
255958
|
-
return true;
|
|
255959
|
-
} catch {
|
|
255960
|
-
return false;
|
|
255637
|
+
function rotateLogIfNeeded(logPath, log1Path, log2Path) {
|
|
255638
|
+
if (!existsSync(logPath)) {
|
|
255639
|
+
return;
|
|
255961
255640
|
}
|
|
255962
|
-
|
|
255963
|
-
|
|
255964
|
-
|
|
255965
|
-
if (!installed) {
|
|
255966
|
-
return {
|
|
255967
|
-
authenticated: false,
|
|
255968
|
-
error: "Railway CLI not installed"
|
|
255969
|
-
};
|
|
255641
|
+
const stats = statSync(logPath);
|
|
255642
|
+
if (stats.size < MAX_LOG_SIZE_BYTES) {
|
|
255643
|
+
return;
|
|
255970
255644
|
}
|
|
255971
|
-
|
|
255972
|
-
|
|
255973
|
-
encoding: "utf-8",
|
|
255974
|
-
stdio: "pipe"
|
|
255975
|
-
}).trim();
|
|
255976
|
-
if (output && output.length > 0) {
|
|
255977
|
-
return {
|
|
255978
|
-
authenticated: true,
|
|
255979
|
-
username: output
|
|
255980
|
-
};
|
|
255981
|
-
}
|
|
255982
|
-
return {
|
|
255983
|
-
authenticated: false
|
|
255984
|
-
};
|
|
255985
|
-
} catch {
|
|
255986
|
-
return {
|
|
255987
|
-
authenticated: false
|
|
255988
|
-
};
|
|
255645
|
+
if (existsSync(log2Path)) {
|
|
255646
|
+
rmSync(log2Path, { force: true });
|
|
255989
255647
|
}
|
|
255990
|
-
|
|
255991
|
-
|
|
255992
|
-
try {
|
|
255993
|
-
execSync3("railway login", {
|
|
255994
|
-
stdio: "inherit"
|
|
255995
|
-
});
|
|
255996
|
-
return await checkRailwayAuth();
|
|
255997
|
-
} catch {
|
|
255998
|
-
return {
|
|
255999
|
-
authenticated: false,
|
|
256000
|
-
error: "Failed to complete Railway login"
|
|
256001
|
-
};
|
|
255648
|
+
if (existsSync(log1Path)) {
|
|
255649
|
+
renameSync(log1Path, log2Path);
|
|
256002
255650
|
}
|
|
255651
|
+
renameSync(logPath, log1Path);
|
|
255652
|
+
writeFileSync(logPath, "", { encoding: "utf8", mode: 384 });
|
|
256003
255653
|
}
|
|
256004
|
-
|
|
255654
|
+
function writeAuditLine(logPath, log1Path, log2Path, type, message) {
|
|
256005
255655
|
try {
|
|
256006
|
-
|
|
256007
|
-
|
|
256008
|
-
stdio: "pipe"
|
|
256009
|
-
});
|
|
256010
|
-
return true;
|
|
255656
|
+
rotateLogIfNeeded(logPath, log1Path, log2Path);
|
|
255657
|
+
appendFileSync(logPath, formatLine(type, message), { encoding: "utf8", mode: 384 });
|
|
256011
255658
|
} catch {
|
|
256012
|
-
return
|
|
255659
|
+
return;
|
|
256013
255660
|
}
|
|
256014
255661
|
}
|
|
256015
|
-
|
|
256016
|
-
|
|
256017
|
-
|
|
256018
|
-
|
|
256019
|
-
|
|
256020
|
-
|
|
256021
|
-
|
|
256022
|
-
|
|
256023
|
-
|
|
256024
|
-
|
|
256025
|
-
|
|
256026
|
-
|
|
256027
|
-
|
|
256028
|
-
|
|
256029
|
-
|
|
256030
|
-
|
|
256031
|
-
|
|
256032
|
-
|
|
256033
|
-
|
|
256034
|
-
|
|
256035
|
-
|
|
256036
|
-
|
|
256037
|
-
|
|
256038
|
-
|
|
256039
|
-
|
|
256040
|
-
|
|
256041
|
-
|
|
256042
|
-
|
|
256043
|
-
|
|
256044
|
-
|
|
256045
|
-
|
|
256046
|
-
|
|
256047
|
-
|
|
256048
|
-
|
|
256049
|
-
}
|
|
256050
|
-
|
|
256051
|
-
|
|
256052
|
-
|
|
256053
|
-
|
|
256054
|
-
|
|
256055
|
-
allowed: false,
|
|
256056
|
-
message: "No KITT workspace found. Run /init to initialize one."
|
|
256057
|
-
};
|
|
256058
|
-
}
|
|
256059
|
-
}
|
|
256060
|
-
const requirement = COMMAND_AUTH[commandKey];
|
|
256061
|
-
if (!requirement || requirement === "none") {
|
|
256062
|
-
return { allowed: true };
|
|
256063
|
-
}
|
|
256064
|
-
if (requirement === "llm" || requirement === "both") {
|
|
256065
|
-
const llmConfigured = await isLlmConfigured();
|
|
256066
|
-
if (!llmConfigured) {
|
|
256067
|
-
return {
|
|
256068
|
-
allowed: false,
|
|
256069
|
-
message: "LLM API key required. Run /login llm to configure."
|
|
256070
|
-
};
|
|
256071
|
-
}
|
|
256072
|
-
}
|
|
256073
|
-
if (requirement === "railway" || requirement === "both") {
|
|
256074
|
-
const railwayStatus = await checkRailwayAuth();
|
|
256075
|
-
if (!railwayStatus.authenticated) {
|
|
256076
|
-
return {
|
|
256077
|
-
allowed: false,
|
|
256078
|
-
message: "Railway authentication required. Run /login railway to authenticate."
|
|
256079
|
-
};
|
|
255662
|
+
function createAuditLogger(workspaceDir) {
|
|
255663
|
+
const auditDir = join(workspaceDir, AUDIT_DIR_NAME);
|
|
255664
|
+
const logPath = join(auditDir, AUDIT_FILE_NAME);
|
|
255665
|
+
const log1Path = join(auditDir, ROTATED_LOG_1);
|
|
255666
|
+
const log2Path = join(auditDir, ROTATED_LOG_2);
|
|
255667
|
+
return {
|
|
255668
|
+
log(type, message) {
|
|
255669
|
+
try {
|
|
255670
|
+
ensureAuditDir(auditDir);
|
|
255671
|
+
} catch {
|
|
255672
|
+
return;
|
|
255673
|
+
}
|
|
255674
|
+
writeAuditLine(logPath, log1Path, log2Path, type, message);
|
|
255675
|
+
},
|
|
255676
|
+
cmd(command, status, detail) {
|
|
255677
|
+
const suffix = detail ? ` (${detail})` : "";
|
|
255678
|
+
this.log("CMD", `${command} → ${status}${suffix}`);
|
|
255679
|
+
},
|
|
255680
|
+
cmdExec(command, status) {
|
|
255681
|
+
this.log("CMD_EXEC", `${command} → ${status}`);
|
|
255682
|
+
},
|
|
255683
|
+
mcp(tool, params, status, detail) {
|
|
255684
|
+
const suffix = detail ? ` (${detail})` : "";
|
|
255685
|
+
this.log("MCP", `${tool} (${params}) → ${status}${suffix}`);
|
|
255686
|
+
},
|
|
255687
|
+
llmCall(provider, model, promptVersion, estimatedTokens, status) {
|
|
255688
|
+
this.log("LLM_CALL", `${provider}/${model} (prompt: ${promptVersion}, est. ${estimatedTokens} tokens) → ${status}`);
|
|
255689
|
+
},
|
|
255690
|
+
fileWrite(path, hash) {
|
|
255691
|
+
const suffix = hash ? ` (SHA-256: ${hash})` : "";
|
|
255692
|
+
this.log("FILE_WRITE", `${path}${suffix}`);
|
|
255693
|
+
},
|
|
255694
|
+
staged(path, detail) {
|
|
255695
|
+
this.log("STAGED", `${path} (${detail})`);
|
|
255696
|
+
},
|
|
255697
|
+
userConfirmed() {
|
|
255698
|
+
this.log("USER_CONFIRMED", "staged changes");
|
|
255699
|
+
},
|
|
255700
|
+
security(action, message) {
|
|
255701
|
+
this.log("SECURITY", `${action} ${message}`);
|
|
256080
255702
|
}
|
|
256081
|
-
}
|
|
256082
|
-
return { allowed: true };
|
|
255703
|
+
};
|
|
256083
255704
|
}
|
|
256084
255705
|
|
|
256085
255706
|
// node_modules/@clack/core/dist/index.mjs
|
|
256086
255707
|
var import_sisteransi = __toESM(require_src(), 1);
|
|
256087
255708
|
import { stdin as j, stdout as M } from "node:process";
|
|
256088
|
-
var
|
|
255709
|
+
var import_picocolors = __toESM(require_picocolors(), 1);
|
|
256089
255710
|
import O from "node:readline";
|
|
256090
255711
|
import { Writable as X } from "node:stream";
|
|
256091
255712
|
function DD({ onlyFirst: e = false } = {}) {
|
|
@@ -256481,10 +256102,10 @@ class MD extends x {
|
|
|
256481
256102
|
this.valueWithCursor = this.masked;
|
|
256482
256103
|
}), this.on("value", () => {
|
|
256483
256104
|
if (this.cursor >= this.value.length)
|
|
256484
|
-
this.valueWithCursor = `${this.masked}${
|
|
256105
|
+
this.valueWithCursor = `${this.masked}${import_picocolors.default.inverse(import_picocolors.default.hidden("_"))}`;
|
|
256485
256106
|
else {
|
|
256486
256107
|
const F = this.masked.slice(0, this.cursor), s = this.masked.slice(this.cursor);
|
|
256487
|
-
this.valueWithCursor = `${F}${
|
|
256108
|
+
this.valueWithCursor = `${F}${import_picocolors.default.inverse(s[0])}${s.slice(1)}`;
|
|
256488
256109
|
}
|
|
256489
256110
|
});
|
|
256490
256111
|
}
|
|
@@ -256529,7 +256150,7 @@ class RD extends x {
|
|
|
256529
256150
|
if (this.cursor >= this.value.length)
|
|
256530
256151
|
return `${this.value}█`;
|
|
256531
256152
|
const u = this.value.slice(0, this.cursor), [t, ...F] = this.value.slice(this.cursor);
|
|
256532
|
-
return `${u}${
|
|
256153
|
+
return `${u}${import_picocolors.default.inverse(t)}${F.join("")}`;
|
|
256533
256154
|
}
|
|
256534
256155
|
get cursor() {
|
|
256535
256156
|
return this._cursor;
|
|
@@ -256542,7 +256163,7 @@ class RD extends x {
|
|
|
256542
256163
|
}
|
|
256543
256164
|
|
|
256544
256165
|
// node_modules/@clack/prompts/dist/index.mjs
|
|
256545
|
-
var
|
|
256166
|
+
var import_picocolors2 = __toESM(require_picocolors(), 1);
|
|
256546
256167
|
var import_sisteransi2 = __toESM(require_src(), 1);
|
|
256547
256168
|
import y2 from "node:process";
|
|
256548
256169
|
function ce() {
|
|
@@ -256575,13 +256196,13 @@ var b2 = (t) => {
|
|
|
256575
256196
|
switch (t) {
|
|
256576
256197
|
case "initial":
|
|
256577
256198
|
case "active":
|
|
256578
|
-
return
|
|
256199
|
+
return import_picocolors2.default.cyan(le);
|
|
256579
256200
|
case "cancel":
|
|
256580
|
-
return
|
|
256201
|
+
return import_picocolors2.default.red(L2);
|
|
256581
256202
|
case "error":
|
|
256582
|
-
return
|
|
256203
|
+
return import_picocolors2.default.yellow(W2);
|
|
256583
256204
|
case "submit":
|
|
256584
|
-
return
|
|
256205
|
+
return import_picocolors2.default.green(C);
|
|
256585
256206
|
}
|
|
256586
256207
|
};
|
|
256587
256208
|
var G2 = (t) => {
|
|
@@ -256591,66 +256212,66 @@ var G2 = (t) => {
|
|
|
256591
256212
|
const $2 = a < r2.length && l2 > 0, g = a < r2.length && l2 + a < r2.length;
|
|
256592
256213
|
return r2.slice(l2, l2 + a).map((p2, v2, f) => {
|
|
256593
256214
|
const j2 = v2 === 0 && $2, E = v2 === f.length - 1 && g;
|
|
256594
|
-
return j2 || E ?
|
|
256215
|
+
return j2 || E ? import_picocolors2.default.dim("...") : i(p2, v2 + l2 === n);
|
|
256595
256216
|
});
|
|
256596
256217
|
};
|
|
256597
256218
|
var he = (t) => new RD({ validate: t.validate, placeholder: t.placeholder, defaultValue: t.defaultValue, initialValue: t.initialValue, render() {
|
|
256598
|
-
const n = `${
|
|
256219
|
+
const n = `${import_picocolors2.default.gray(o)}
|
|
256599
256220
|
${b2(this.state)} ${t.message}
|
|
256600
|
-
`, r2 = t.placeholder ?
|
|
256221
|
+
`, r2 = t.placeholder ? import_picocolors2.default.inverse(t.placeholder[0]) + import_picocolors2.default.dim(t.placeholder.slice(1)) : import_picocolors2.default.inverse(import_picocolors2.default.hidden("_")), i = this.value ? this.valueWithCursor : r2;
|
|
256601
256222
|
switch (this.state) {
|
|
256602
256223
|
case "error":
|
|
256603
256224
|
return `${n.trim()}
|
|
256604
|
-
${
|
|
256605
|
-
${
|
|
256225
|
+
${import_picocolors2.default.yellow(o)} ${i}
|
|
256226
|
+
${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(this.error)}
|
|
256606
256227
|
`;
|
|
256607
256228
|
case "submit":
|
|
256608
|
-
return `${n}${
|
|
256229
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(this.value || t.placeholder)}`;
|
|
256609
256230
|
case "cancel":
|
|
256610
|
-
return `${n}${
|
|
256611
|
-
${
|
|
256231
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(this.value ?? ""))}${this.value?.trim() ? `
|
|
256232
|
+
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
256612
256233
|
default:
|
|
256613
|
-
return `${n}${
|
|
256614
|
-
${
|
|
256234
|
+
return `${n}${import_picocolors2.default.cyan(o)} ${i}
|
|
256235
|
+
${import_picocolors2.default.cyan(d2)}
|
|
256615
256236
|
`;
|
|
256616
256237
|
}
|
|
256617
256238
|
} }).prompt();
|
|
256618
256239
|
var ge = (t) => new MD({ validate: t.validate, mask: t.mask ?? $e, render() {
|
|
256619
|
-
const n = `${
|
|
256240
|
+
const n = `${import_picocolors2.default.gray(o)}
|
|
256620
256241
|
${b2(this.state)} ${t.message}
|
|
256621
256242
|
`, r2 = this.valueWithCursor, i = this.masked;
|
|
256622
256243
|
switch (this.state) {
|
|
256623
256244
|
case "error":
|
|
256624
256245
|
return `${n.trim()}
|
|
256625
|
-
${
|
|
256626
|
-
${
|
|
256246
|
+
${import_picocolors2.default.yellow(o)} ${i}
|
|
256247
|
+
${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(this.error)}
|
|
256627
256248
|
`;
|
|
256628
256249
|
case "submit":
|
|
256629
|
-
return `${n}${
|
|
256250
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(i)}`;
|
|
256630
256251
|
case "cancel":
|
|
256631
|
-
return `${n}${
|
|
256632
|
-
${
|
|
256252
|
+
return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(i ?? ""))}${i ? `
|
|
256253
|
+
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
256633
256254
|
default:
|
|
256634
|
-
return `${n}${
|
|
256635
|
-
${
|
|
256255
|
+
return `${n}${import_picocolors2.default.cyan(o)} ${r2}
|
|
256256
|
+
${import_picocolors2.default.cyan(d2)}
|
|
256636
256257
|
`;
|
|
256637
256258
|
}
|
|
256638
256259
|
} }).prompt();
|
|
256639
256260
|
var ye = (t) => {
|
|
256640
256261
|
const n = t.active ?? "Yes", r2 = t.inactive ?? "No";
|
|
256641
256262
|
return new dD({ active: n, inactive: r2, initialValue: t.initialValue ?? true, render() {
|
|
256642
|
-
const i = `${
|
|
256263
|
+
const i = `${import_picocolors2.default.gray(o)}
|
|
256643
256264
|
${b2(this.state)} ${t.message}
|
|
256644
256265
|
`, s = this.value ? n : r2;
|
|
256645
256266
|
switch (this.state) {
|
|
256646
256267
|
case "submit":
|
|
256647
|
-
return `${i}${
|
|
256268
|
+
return `${i}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(s)}`;
|
|
256648
256269
|
case "cancel":
|
|
256649
|
-
return `${i}${
|
|
256650
|
-
${
|
|
256270
|
+
return `${i}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}
|
|
256271
|
+
${import_picocolors2.default.gray(o)}`;
|
|
256651
256272
|
default:
|
|
256652
|
-
return `${i}${
|
|
256653
|
-
${
|
|
256273
|
+
return `${i}${import_picocolors2.default.cyan(o)} ${this.value ? `${import_picocolors2.default.green(k2)} ${n}` : `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(r2)}` : `${import_picocolors2.default.green(k2)} ${r2}`}
|
|
256274
|
+
${import_picocolors2.default.cyan(d2)}
|
|
256654
256275
|
`;
|
|
256655
256276
|
}
|
|
256656
256277
|
} }).prompt();
|
|
@@ -256660,29 +256281,29 @@ var ve = (t) => {
|
|
|
256660
256281
|
const s = r2.label ?? String(r2.value);
|
|
256661
256282
|
switch (i) {
|
|
256662
256283
|
case "selected":
|
|
256663
|
-
return `${
|
|
256284
|
+
return `${import_picocolors2.default.dim(s)}`;
|
|
256664
256285
|
case "active":
|
|
256665
|
-
return `${
|
|
256286
|
+
return `${import_picocolors2.default.green(k2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}`;
|
|
256666
256287
|
case "cancelled":
|
|
256667
|
-
return `${
|
|
256288
|
+
return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}`;
|
|
256668
256289
|
default:
|
|
256669
|
-
return `${
|
|
256290
|
+
return `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(s)}`;
|
|
256670
256291
|
}
|
|
256671
256292
|
};
|
|
256672
256293
|
return new LD({ options: t.options, initialValue: t.initialValue, render() {
|
|
256673
|
-
const r2 = `${
|
|
256294
|
+
const r2 = `${import_picocolors2.default.gray(o)}
|
|
256674
256295
|
${b2(this.state)} ${t.message}
|
|
256675
256296
|
`;
|
|
256676
256297
|
switch (this.state) {
|
|
256677
256298
|
case "submit":
|
|
256678
|
-
return `${r2}${
|
|
256299
|
+
return `${r2}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
|
|
256679
256300
|
case "cancel":
|
|
256680
|
-
return `${r2}${
|
|
256681
|
-
${
|
|
256301
|
+
return `${r2}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
|
|
256302
|
+
${import_picocolors2.default.gray(o)}`;
|
|
256682
256303
|
default:
|
|
256683
|
-
return `${r2}${
|
|
256684
|
-
${
|
|
256685
|
-
${
|
|
256304
|
+
return `${r2}${import_picocolors2.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i, s) => n(i, s ? "active" : "inactive") }).join(`
|
|
256305
|
+
${import_picocolors2.default.cyan(o)} `)}
|
|
256306
|
+
${import_picocolors2.default.cyan(d2)}
|
|
256686
256307
|
`;
|
|
256687
256308
|
}
|
|
256688
256309
|
} }).prompt();
|
|
@@ -256690,14 +256311,14 @@ ${import_picocolors3.default.cyan(d2)}
|
|
|
256690
256311
|
var fe = (t) => {
|
|
256691
256312
|
const n = (r2, i) => {
|
|
256692
256313
|
const s = r2.label ?? String(r2.value);
|
|
256693
|
-
return i === "active" ? `${
|
|
256314
|
+
return i === "active" ? `${import_picocolors2.default.cyan(A2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(T)} ${import_picocolors2.default.dim(s)} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}` : i === "active-selected" ? `${import_picocolors2.default.green(T)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(s)}` : `${import_picocolors2.default.dim(F)} ${import_picocolors2.default.dim(s)}`;
|
|
256694
256315
|
};
|
|
256695
256316
|
return new SD({ options: t.options, initialValues: t.initialValues, required: t.required ?? true, cursorAt: t.cursorAt, validate(r2) {
|
|
256696
256317
|
if (this.required && r2.length === 0)
|
|
256697
256318
|
return `Please select at least one option.
|
|
256698
|
-
${
|
|
256319
|
+
${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
|
|
256699
256320
|
}, render() {
|
|
256700
|
-
const r2 = `${
|
|
256321
|
+
const r2 = `${import_picocolors2.default.gray(o)}
|
|
256701
256322
|
${b2(this.state)} ${t.message}
|
|
256702
256323
|
`, i = (s, c) => {
|
|
256703
256324
|
const a = this.value.includes(s.value);
|
|
@@ -256705,44 +256326,44 @@ ${b2(this.state)} ${t.message}
|
|
|
256705
256326
|
};
|
|
256706
256327
|
switch (this.state) {
|
|
256707
256328
|
case "submit":
|
|
256708
|
-
return `${r2}${
|
|
256329
|
+
return `${r2}${import_picocolors2.default.gray(o)} ${this.options.filter(({ value: s }) => this.value.includes(s)).map((s) => n(s, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
|
|
256709
256330
|
case "cancel": {
|
|
256710
|
-
const s = this.options.filter(({ value: c }) => this.value.includes(c)).map((c) => n(c, "cancelled")).join(
|
|
256711
|
-
return `${r2}${
|
|
256712
|
-
${
|
|
256331
|
+
const s = this.options.filter(({ value: c }) => this.value.includes(c)).map((c) => n(c, "cancelled")).join(import_picocolors2.default.dim(", "));
|
|
256332
|
+
return `${r2}${import_picocolors2.default.gray(o)} ${s.trim() ? `${s}
|
|
256333
|
+
${import_picocolors2.default.gray(o)}` : ""}`;
|
|
256713
256334
|
}
|
|
256714
256335
|
case "error": {
|
|
256715
256336
|
const s = this.error.split(`
|
|
256716
|
-
`).map((c, a) => a === 0 ? `${
|
|
256337
|
+
`).map((c, a) => a === 0 ? `${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(c)}` : ` ${c}`).join(`
|
|
256717
256338
|
`);
|
|
256718
|
-
return `${r2 +
|
|
256719
|
-
${
|
|
256339
|
+
return `${r2 + import_picocolors2.default.yellow(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
|
|
256340
|
+
${import_picocolors2.default.yellow(o)} `)}
|
|
256720
256341
|
${s}
|
|
256721
256342
|
`;
|
|
256722
256343
|
}
|
|
256723
256344
|
default:
|
|
256724
|
-
return `${r2}${
|
|
256725
|
-
${
|
|
256726
|
-
${
|
|
256345
|
+
return `${r2}${import_picocolors2.default.cyan(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
|
|
256346
|
+
${import_picocolors2.default.cyan(o)} `)}
|
|
256347
|
+
${import_picocolors2.default.cyan(d2)}
|
|
256727
256348
|
`;
|
|
256728
256349
|
}
|
|
256729
256350
|
} }).prompt();
|
|
256730
256351
|
};
|
|
256731
|
-
var J2 = `${
|
|
256352
|
+
var J2 = `${import_picocolors2.default.gray(o)} `;
|
|
256732
256353
|
|
|
256733
256354
|
// src/utils/display.ts
|
|
256734
|
-
var
|
|
256355
|
+
var import_picocolors3 = __toESM(require_picocolors(), 1);
|
|
256735
256356
|
function success(message) {
|
|
256736
|
-
console.log(`${
|
|
256357
|
+
console.log(`${import_picocolors3.default.green("✓")} ${message}`);
|
|
256737
256358
|
}
|
|
256738
256359
|
function error(message) {
|
|
256739
|
-
console.log(`${
|
|
256360
|
+
console.log(`${import_picocolors3.default.red("✗")} ${message}`);
|
|
256740
256361
|
}
|
|
256741
256362
|
function warn(message) {
|
|
256742
|
-
console.log(`${
|
|
256363
|
+
console.log(`${import_picocolors3.default.yellow("⚠")} ${message}`);
|
|
256743
256364
|
}
|
|
256744
256365
|
function info(message) {
|
|
256745
|
-
console.log(`${
|
|
256366
|
+
console.log(`${import_picocolors3.default.blue("ℹ")} ${message}`);
|
|
256746
256367
|
}
|
|
256747
256368
|
var MODEL_PRICING = {
|
|
256748
256369
|
"claude-opus-4-5": [15, 75],
|
|
@@ -256784,135 +256405,665 @@ function renderContextBanner(params) {
|
|
|
256784
256405
|
const costUsd = pricing ? inputTokens / 1e6 * pricing[0] + outputTokens / 1e6 * pricing[1] : null;
|
|
256785
256406
|
const providerLabel = provider.charAt(0).toUpperCase() + provider.slice(1);
|
|
256786
256407
|
const width = 36;
|
|
256787
|
-
const border =
|
|
256408
|
+
const border = import_picocolors3.default.dim("─".repeat(width));
|
|
256788
256409
|
console.log("");
|
|
256789
|
-
console.log(` ${
|
|
256790
|
-
console.log(` ${
|
|
256791
|
-
console.log(` ${
|
|
256792
|
-
console.log(` ${
|
|
256410
|
+
console.log(` ${import_picocolors3.default.dim(border)}`);
|
|
256411
|
+
console.log(` ${import_picocolors3.default.dim("│")} ${import_picocolors3.default.bold("Context")}${" ".repeat(width - 9)}${import_picocolors3.default.dim("│")}`);
|
|
256412
|
+
console.log(` ${import_picocolors3.default.dim("│")} ${import_picocolors3.default.cyan(totalTokens.toLocaleString())} ${import_picocolors3.default.dim("tokens")}${" ".repeat(Math.max(0, width - 2 - totalTokens.toLocaleString().length - 7))}${import_picocolors3.default.dim("│")}`);
|
|
256413
|
+
console.log(` ${import_picocolors3.default.dim("│")} ${import_picocolors3.default.yellow(`${pctUsed}%`)} ${import_picocolors3.default.dim("of context window used")}${" ".repeat(Math.max(0, width - 2 - String(pctUsed).length - 1 - 22))}${import_picocolors3.default.dim("│")}`);
|
|
256793
256414
|
if (costUsd !== null) {
|
|
256794
256415
|
const costStr = formatCost(costUsd);
|
|
256795
|
-
console.log(` ${
|
|
256416
|
+
console.log(` ${import_picocolors3.default.dim("│")} ${import_picocolors3.default.green(costStr)} ${import_picocolors3.default.dim("spent")}${" ".repeat(Math.max(0, width - 2 - costStr.length - 6))}${import_picocolors3.default.dim("│")}`);
|
|
256796
256417
|
}
|
|
256797
|
-
console.log(` ${
|
|
256798
|
-
console.log(` ${
|
|
256418
|
+
console.log(` ${import_picocolors3.default.dim("│")} ${import_picocolors3.default.dim(`${providerLabel} · ${model}`)}${" ".repeat(Math.max(0, width - 2 - providerLabel.length - 3 - model.length))}${import_picocolors3.default.dim("│")}`);
|
|
256419
|
+
console.log(` ${import_picocolors3.default.dim(border)}`);
|
|
256799
256420
|
console.log("");
|
|
256800
256421
|
}
|
|
256801
256422
|
|
|
256802
|
-
// src/
|
|
256803
|
-
|
|
256804
|
-
|
|
256805
|
-
|
|
256806
|
-
|
|
256807
|
-
|
|
256808
|
-
|
|
256809
|
-
|
|
256810
|
-
|
|
256811
|
-
|
|
256812
|
-
}
|
|
256813
|
-
|
|
256814
|
-
import { dirname as dirname3, join as join6, relative } from "node:path";
|
|
256815
|
-
|
|
256816
|
-
// src/audit/logger.ts
|
|
256817
|
-
import {
|
|
256818
|
-
appendFileSync,
|
|
256819
|
-
existsSync as existsSync5,
|
|
256820
|
-
mkdirSync as mkdirSync4,
|
|
256821
|
-
renameSync as renameSync3,
|
|
256822
|
-
rmSync,
|
|
256823
|
-
statSync as statSync2,
|
|
256824
|
-
writeFileSync as writeFileSync4
|
|
256825
|
-
} from "node:fs";
|
|
256826
|
-
import { join as join5 } from "node:path";
|
|
256827
|
-
var AUDIT_DIR_NAME = ".kitt";
|
|
256828
|
-
var AUDIT_FILE_NAME = "audit.log";
|
|
256829
|
-
var ROTATED_LOG_1 = "audit.log.1";
|
|
256830
|
-
var ROTATED_LOG_2 = "audit.log.2";
|
|
256831
|
-
var MAX_LOG_SIZE_BYTES = 10 * 1024 * 1024;
|
|
256832
|
-
function formatLine(type, message) {
|
|
256833
|
-
return `[${new Date().toISOString()}] ${type} ${message}
|
|
256834
|
-
`;
|
|
256423
|
+
// src/mcp/lifecycle.ts
|
|
256424
|
+
var MCP_START_FAILURE_MESSAGE = "Railway MCP Server not found. Install it: npm install -g @railway/mcp-server";
|
|
256425
|
+
var SHUTDOWN_TIMEOUT_MS = 5000;
|
|
256426
|
+
var auditLogger = createAuditLogger(".");
|
|
256427
|
+
function findMcpEntryPoint() {
|
|
256428
|
+
try {
|
|
256429
|
+
const globalRoot = execSync("npm root -g", { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
256430
|
+
const candidate = join2(globalRoot, "@railway", "mcp-server", "dist", "index.js");
|
|
256431
|
+
if (existsSync2(candidate))
|
|
256432
|
+
return candidate;
|
|
256433
|
+
} catch {}
|
|
256434
|
+
return null;
|
|
256835
256435
|
}
|
|
256836
|
-
|
|
256837
|
-
|
|
256838
|
-
|
|
256436
|
+
var activeServer = null;
|
|
256437
|
+
var pendingSpawn = null;
|
|
256438
|
+
var shouldLogRespawn = false;
|
|
256439
|
+
var intentionallyShuttingDown = new WeakSet;
|
|
256440
|
+
function formatExitDetail(code, signal) {
|
|
256441
|
+
const codeLabel = code === null ? "null" : String(code);
|
|
256442
|
+
const signalLabel = signal ?? "null";
|
|
256443
|
+
return `code=${codeLabel}, signal=${signalLabel}`;
|
|
256444
|
+
}
|
|
256445
|
+
function isChildRunning(child) {
|
|
256446
|
+
return child.exitCode === null && !child.killed;
|
|
256447
|
+
}
|
|
256448
|
+
function buildServerProcess(child) {
|
|
256449
|
+
if (!child.stdin || !child.stdout) {
|
|
256450
|
+
throw new Error("MCP server stdio was not created");
|
|
256839
256451
|
}
|
|
256840
|
-
|
|
256452
|
+
return {
|
|
256453
|
+
process: child,
|
|
256454
|
+
stdin: child.stdin,
|
|
256455
|
+
stdout: child.stdout,
|
|
256456
|
+
pid: child.pid ?? -1
|
|
256457
|
+
};
|
|
256841
256458
|
}
|
|
256842
|
-
function
|
|
256843
|
-
|
|
256459
|
+
function attachLifecycleListeners(child) {
|
|
256460
|
+
child.stderr?.on("data", (chunk) => {
|
|
256461
|
+
const message = String(chunk).trim();
|
|
256462
|
+
if (!message) {
|
|
256463
|
+
return;
|
|
256464
|
+
}
|
|
256465
|
+
auditLogger.mcp("server-lifecycle", "stderr", "FAILED", message);
|
|
256466
|
+
});
|
|
256467
|
+
child.on("exit", (code, signal) => {
|
|
256468
|
+
const detail = formatExitDetail(code, signal);
|
|
256469
|
+
if (activeServer?.process === child) {
|
|
256470
|
+
activeServer = null;
|
|
256471
|
+
}
|
|
256472
|
+
if (intentionallyShuttingDown.has(child)) {
|
|
256473
|
+
return;
|
|
256474
|
+
}
|
|
256475
|
+
shouldLogRespawn = true;
|
|
256476
|
+
auditLogger.mcp("server-lifecycle", "crash", "FAILED", detail);
|
|
256477
|
+
});
|
|
256478
|
+
}
|
|
256479
|
+
function displaySpawnFailure(reason) {
|
|
256480
|
+
error(MCP_START_FAILURE_MESSAGE);
|
|
256481
|
+
auditLogger.mcp("server-lifecycle", "spawn", "FAILED", reason);
|
|
256482
|
+
}
|
|
256483
|
+
async function spawnMcpServer() {
|
|
256484
|
+
if (activeServer && isChildRunning(activeServer.process)) {
|
|
256485
|
+
return activeServer;
|
|
256486
|
+
}
|
|
256487
|
+
if (pendingSpawn) {
|
|
256488
|
+
return pendingSpawn;
|
|
256489
|
+
}
|
|
256490
|
+
const entryPoint = findMcpEntryPoint();
|
|
256491
|
+
if (!entryPoint) {
|
|
256492
|
+
throw new Error(MCP_START_FAILURE_MESSAGE);
|
|
256493
|
+
}
|
|
256494
|
+
const respawn = shouldLogRespawn;
|
|
256495
|
+
const child = spawn("node", [entryPoint], {
|
|
256496
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
256497
|
+
});
|
|
256498
|
+
attachLifecycleListeners(child);
|
|
256499
|
+
pendingSpawn = new Promise((resolve, reject) => {
|
|
256500
|
+
const handleError = (spawnError) => {
|
|
256501
|
+
child.off("spawn", handleSpawn);
|
|
256502
|
+
if (activeServer?.process === child) {
|
|
256503
|
+
activeServer = null;
|
|
256504
|
+
}
|
|
256505
|
+
displaySpawnFailure(spawnError.message);
|
|
256506
|
+
reject(spawnError);
|
|
256507
|
+
};
|
|
256508
|
+
const handleSpawn = () => {
|
|
256509
|
+
child.off("error", handleError);
|
|
256510
|
+
let serverProcess;
|
|
256511
|
+
try {
|
|
256512
|
+
serverProcess = buildServerProcess(child);
|
|
256513
|
+
} catch (buildError) {
|
|
256514
|
+
const err = buildError instanceof Error ? buildError : new Error(String(buildError));
|
|
256515
|
+
displaySpawnFailure(err.message);
|
|
256516
|
+
reject(err);
|
|
256517
|
+
return;
|
|
256518
|
+
}
|
|
256519
|
+
activeServer = serverProcess;
|
|
256520
|
+
shouldLogRespawn = false;
|
|
256521
|
+
if (respawn) {
|
|
256522
|
+
auditLogger.mcp("server-lifecycle", "respawn", "SUCCESS", `pid=${serverProcess.pid}`);
|
|
256523
|
+
} else {
|
|
256524
|
+
auditLogger.mcp("server-lifecycle", "spawn", "SUCCESS", `pid=${serverProcess.pid}`);
|
|
256525
|
+
}
|
|
256526
|
+
resolve(serverProcess);
|
|
256527
|
+
};
|
|
256528
|
+
child.once("error", handleError);
|
|
256529
|
+
child.once("spawn", handleSpawn);
|
|
256530
|
+
}).finally(() => {
|
|
256531
|
+
pendingSpawn = null;
|
|
256532
|
+
});
|
|
256533
|
+
return pendingSpawn;
|
|
256534
|
+
}
|
|
256535
|
+
async function shutdownMcpServer() {
|
|
256536
|
+
if (!activeServer) {
|
|
256844
256537
|
return;
|
|
256845
256538
|
}
|
|
256846
|
-
const
|
|
256847
|
-
|
|
256539
|
+
const child = activeServer.process;
|
|
256540
|
+
intentionallyShuttingDown.add(child);
|
|
256541
|
+
if (!isChildRunning(child)) {
|
|
256542
|
+
activeServer = null;
|
|
256848
256543
|
return;
|
|
256849
256544
|
}
|
|
256850
|
-
|
|
256851
|
-
|
|
256545
|
+
const exitPromise = new Promise((resolve) => {
|
|
256546
|
+
child.once("exit", (code, signal) => {
|
|
256547
|
+
resolve({ code, signal });
|
|
256548
|
+
});
|
|
256549
|
+
});
|
|
256550
|
+
child.kill("SIGTERM");
|
|
256551
|
+
let forcedKill = false;
|
|
256552
|
+
const timeoutHandle = setTimeout(() => {
|
|
256553
|
+
forcedKill = true;
|
|
256554
|
+
child.kill("SIGKILL");
|
|
256555
|
+
}, SHUTDOWN_TIMEOUT_MS);
|
|
256556
|
+
const exitResult = await exitPromise;
|
|
256557
|
+
clearTimeout(timeoutHandle);
|
|
256558
|
+
activeServer = null;
|
|
256559
|
+
const detail = forcedKill ? `forced after timeout (${formatExitDetail(exitResult.code, exitResult.signal)})` : formatExitDetail(exitResult.code, exitResult.signal);
|
|
256560
|
+
auditLogger.mcp("server-lifecycle", "shutdown", "SUCCESS", detail);
|
|
256561
|
+
}
|
|
256562
|
+
|
|
256563
|
+
// src/utils/prerequisites.ts
|
|
256564
|
+
var import_picocolors4 = __toESM(require_picocolors(), 1);
|
|
256565
|
+
function getNodeVersion() {
|
|
256566
|
+
try {
|
|
256567
|
+
const output = execSync3("node --version", {
|
|
256568
|
+
encoding: "utf-8",
|
|
256569
|
+
stdio: "pipe"
|
|
256570
|
+
}).trim();
|
|
256571
|
+
return output.replace(/^v/, "");
|
|
256572
|
+
} catch {
|
|
256573
|
+
return "";
|
|
256852
256574
|
}
|
|
256853
|
-
|
|
256854
|
-
|
|
256575
|
+
}
|
|
256576
|
+
function getBunVersion() {
|
|
256577
|
+
try {
|
|
256578
|
+
const output = execSync3("bun --version", {
|
|
256579
|
+
encoding: "utf-8",
|
|
256580
|
+
stdio: "pipe"
|
|
256581
|
+
}).trim();
|
|
256582
|
+
return output;
|
|
256583
|
+
} catch {
|
|
256584
|
+
return null;
|
|
256855
256585
|
}
|
|
256856
|
-
renameSync3(logPath, log1Path);
|
|
256857
|
-
writeFileSync4(logPath, "", { encoding: "utf8", mode: 384 });
|
|
256858
256586
|
}
|
|
256859
|
-
function
|
|
256587
|
+
function getRailwayVersion() {
|
|
256860
256588
|
try {
|
|
256861
|
-
|
|
256862
|
-
|
|
256589
|
+
const output = execSync3("railway --version", {
|
|
256590
|
+
encoding: "utf-8",
|
|
256591
|
+
stdio: "pipe"
|
|
256592
|
+
}).trim();
|
|
256593
|
+
return output || null;
|
|
256863
256594
|
} catch {
|
|
256864
|
-
return;
|
|
256595
|
+
return null;
|
|
256865
256596
|
}
|
|
256866
256597
|
}
|
|
256867
|
-
function
|
|
256868
|
-
const
|
|
256869
|
-
const
|
|
256870
|
-
const
|
|
256871
|
-
const
|
|
256872
|
-
return
|
|
256873
|
-
|
|
256874
|
-
|
|
256875
|
-
|
|
256876
|
-
|
|
256877
|
-
return;
|
|
256878
|
-
}
|
|
256879
|
-
writeAuditLine(logPath, log1Path, log2Path, type, message);
|
|
256880
|
-
},
|
|
256881
|
-
cmd(command, status, detail) {
|
|
256882
|
-
const suffix = detail ? ` (${detail})` : "";
|
|
256883
|
-
this.log("CMD", `${command} → ${status}${suffix}`);
|
|
256884
|
-
},
|
|
256885
|
-
cmdExec(command, status) {
|
|
256886
|
-
this.log("CMD_EXEC", `${command} → ${status}`);
|
|
256887
|
-
},
|
|
256888
|
-
mcp(tool, params, status, detail) {
|
|
256889
|
-
const suffix = detail ? ` (${detail})` : "";
|
|
256890
|
-
this.log("MCP", `${tool} (${params}) → ${status}${suffix}`);
|
|
256891
|
-
},
|
|
256892
|
-
llmCall(provider, model, promptVersion, estimatedTokens, status) {
|
|
256893
|
-
this.log("LLM_CALL", `${provider}/${model} (prompt: ${promptVersion}, est. ${estimatedTokens} tokens) → ${status}`);
|
|
256598
|
+
async function checkPrerequisites() {
|
|
256599
|
+
const nodeVersion = getNodeVersion();
|
|
256600
|
+
const bunVersion = getBunVersion();
|
|
256601
|
+
const railwayVersion = getRailwayVersion();
|
|
256602
|
+
const mcpFound = findMcpEntryPoint() !== null;
|
|
256603
|
+
return [
|
|
256604
|
+
{
|
|
256605
|
+
name: "Node.js",
|
|
256606
|
+
found: !!nodeVersion,
|
|
256607
|
+
version: nodeVersion || undefined
|
|
256894
256608
|
},
|
|
256895
|
-
|
|
256896
|
-
|
|
256897
|
-
|
|
256609
|
+
{
|
|
256610
|
+
name: "Bun",
|
|
256611
|
+
found: !!bunVersion,
|
|
256612
|
+
version: bunVersion || undefined,
|
|
256613
|
+
installUrl: bunVersion ? undefined : "https://bun.sh"
|
|
256898
256614
|
},
|
|
256899
|
-
|
|
256900
|
-
|
|
256615
|
+
{
|
|
256616
|
+
name: "Railway CLI",
|
|
256617
|
+
found: !!railwayVersion,
|
|
256618
|
+
version: railwayVersion || undefined,
|
|
256619
|
+
installUrl: railwayVersion ? undefined : "https://docs.railway.com/cli"
|
|
256901
256620
|
},
|
|
256902
|
-
|
|
256903
|
-
|
|
256621
|
+
{
|
|
256622
|
+
name: "Railway MCP",
|
|
256623
|
+
found: mcpFound,
|
|
256624
|
+
installUrl: mcpFound ? undefined : "npm install -g @railway/mcp-server"
|
|
256625
|
+
}
|
|
256626
|
+
];
|
|
256627
|
+
}
|
|
256628
|
+
function displayPrerequisites(statuses) {
|
|
256629
|
+
for (const status of statuses) {
|
|
256630
|
+
if (status.found) {
|
|
256631
|
+
const version = status.version ? `v${status.version}` : "";
|
|
256632
|
+
const paddedName = status.name.padEnd(12);
|
|
256633
|
+
console.log(` ${import_picocolors4.default.green("✓")} ${paddedName} ${version}`);
|
|
256634
|
+
} else {
|
|
256635
|
+
const paddedName = status.name.padEnd(12);
|
|
256636
|
+
const installMsg = status.installUrl ? `not found. Install: ${status.installUrl}` : "not found";
|
|
256637
|
+
console.log(` ${import_picocolors4.default.red("✗")} ${paddedName} ${installMsg}`);
|
|
256638
|
+
}
|
|
256639
|
+
}
|
|
256640
|
+
}
|
|
256641
|
+
async function displayLlmStatus() {
|
|
256642
|
+
const paddedName = "LLM".padEnd(12);
|
|
256643
|
+
try {
|
|
256644
|
+
const { isLlmConfigured: isLlmConfigured2, getLlmConfig: getLlmConfig2 } = await Promise.resolve().then(() => (init_config(), exports_config));
|
|
256645
|
+
const [configured, config] = await Promise.all([isLlmConfigured2(), getLlmConfig2()]);
|
|
256646
|
+
if (configured && config) {
|
|
256647
|
+
const label = `${config.provider[0].toUpperCase()}${config.provider.slice(1)} (${config.model})`;
|
|
256648
|
+
console.log(` ${import_picocolors4.default.green("✓")} ${paddedName} ${label}`);
|
|
256649
|
+
} else {
|
|
256650
|
+
console.log(` ${import_picocolors4.default.yellow("!")} ${paddedName} not configured`);
|
|
256651
|
+
}
|
|
256652
|
+
} catch {
|
|
256653
|
+
console.log(` ${import_picocolors4.default.yellow("!")} ${paddedName} not configured`);
|
|
256654
|
+
}
|
|
256655
|
+
}
|
|
256656
|
+
|
|
256657
|
+
// src/manifest/reader.ts
|
|
256658
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "node:fs";
|
|
256659
|
+
import { join as join6, dirname as dirname2, resolve } from "node:path";
|
|
256660
|
+
|
|
256661
|
+
// src/utils/global-config.ts
|
|
256662
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
|
|
256663
|
+
import { homedir as homedir2 } from "node:os";
|
|
256664
|
+
import { join as join4 } from "node:path";
|
|
256665
|
+
function getGlobalConfigPath() {
|
|
256666
|
+
return join4(homedir2(), ".kitt", "workspace.json");
|
|
256667
|
+
}
|
|
256668
|
+
function readGlobalConfig() {
|
|
256669
|
+
const configPath = getGlobalConfigPath();
|
|
256670
|
+
if (!existsSync4(configPath)) {
|
|
256671
|
+
return {};
|
|
256672
|
+
}
|
|
256673
|
+
try {
|
|
256674
|
+
const raw = readFileSync3(configPath, "utf-8").trim();
|
|
256675
|
+
if (!raw)
|
|
256676
|
+
return {};
|
|
256677
|
+
const parsed = JSON.parse(raw);
|
|
256678
|
+
if (typeof parsed === "object" && parsed !== null) {
|
|
256679
|
+
return parsed;
|
|
256680
|
+
}
|
|
256681
|
+
return {};
|
|
256682
|
+
} catch {
|
|
256683
|
+
return {};
|
|
256684
|
+
}
|
|
256685
|
+
}
|
|
256686
|
+
function writeGlobalConfig(config) {
|
|
256687
|
+
const configPath = getGlobalConfigPath();
|
|
256688
|
+
const configDir = join4(homedir2(), ".kitt");
|
|
256689
|
+
mkdirSync3(configDir, { recursive: true });
|
|
256690
|
+
writeFileSync3(configPath, JSON.stringify(config, null, 2) + `
|
|
256691
|
+
`, "utf-8");
|
|
256692
|
+
}
|
|
256693
|
+
function setGlobalWorkspacePath(workspacePath) {
|
|
256694
|
+
const existing = readGlobalConfig();
|
|
256695
|
+
writeGlobalConfig({ ...existing, workspacePath });
|
|
256696
|
+
}
|
|
256697
|
+
function getGlobalWorkspacePath() {
|
|
256698
|
+
return readGlobalConfig().workspacePath ?? null;
|
|
256699
|
+
}
|
|
256700
|
+
|
|
256701
|
+
// src/manifest/writer.ts
|
|
256702
|
+
import { chmodSync as chmodSync2, existsSync as existsSync5, mkdirSync as mkdirSync4, renameSync as renameSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync4 } from "node:fs";
|
|
256703
|
+
import { platform as platform3 } from "node:os";
|
|
256704
|
+
import { dirname, join as join5 } from "node:path";
|
|
256705
|
+
var DIR_MODE2 = 448;
|
|
256706
|
+
var FILE_MODE2 = 384;
|
|
256707
|
+
var MANIFEST_VERSION = "0.1.0";
|
|
256708
|
+
function isWindows2() {
|
|
256709
|
+
return platform3() === "win32";
|
|
256710
|
+
}
|
|
256711
|
+
function ensureKittDir(manifestPath) {
|
|
256712
|
+
const kittDir = dirname(manifestPath);
|
|
256713
|
+
if (!existsSync5(kittDir)) {
|
|
256714
|
+
mkdirSync4(kittDir, { recursive: true, mode: DIR_MODE2 });
|
|
256715
|
+
}
|
|
256716
|
+
if (!isWindows2()) {
|
|
256717
|
+
chmodSync2(kittDir, DIR_MODE2);
|
|
256718
|
+
}
|
|
256719
|
+
}
|
|
256720
|
+
function writeManifest(workspaceDir, manifest) {
|
|
256721
|
+
const manifestPath = getManifestPath(workspaceDir);
|
|
256722
|
+
const manifestDir = dirname(manifestPath);
|
|
256723
|
+
const tempFile = join5(manifestDir, `manifest.json.tmp-${process.pid}-${Date.now()}`);
|
|
256724
|
+
const payload = `${JSON.stringify(manifest, null, 2)}
|
|
256725
|
+
`;
|
|
256726
|
+
ensureKittDir(manifestPath);
|
|
256727
|
+
try {
|
|
256728
|
+
writeFileSync4(tempFile, payload, { encoding: "utf-8", mode: FILE_MODE2 });
|
|
256729
|
+
if (!isWindows2()) {
|
|
256730
|
+
chmodSync2(tempFile, FILE_MODE2);
|
|
256731
|
+
}
|
|
256732
|
+
renameSync3(tempFile, manifestPath);
|
|
256733
|
+
if (!isWindows2()) {
|
|
256734
|
+
chmodSync2(manifestPath, FILE_MODE2);
|
|
256735
|
+
}
|
|
256736
|
+
} catch (error2) {
|
|
256737
|
+
if (existsSync5(tempFile)) {
|
|
256738
|
+
unlinkSync2(tempFile);
|
|
256739
|
+
}
|
|
256740
|
+
throw error2;
|
|
256741
|
+
}
|
|
256742
|
+
}
|
|
256743
|
+
function createInitialManifest(workspaceName, packageManager, railway) {
|
|
256744
|
+
return {
|
|
256745
|
+
version: MANIFEST_VERSION,
|
|
256746
|
+
workspace: {
|
|
256747
|
+
name: workspaceName,
|
|
256748
|
+
packageManager,
|
|
256749
|
+
...railway ? { railway } : {}
|
|
256904
256750
|
},
|
|
256905
|
-
|
|
256906
|
-
|
|
256751
|
+
settings: {},
|
|
256752
|
+
apps: {},
|
|
256753
|
+
packages: {}
|
|
256754
|
+
};
|
|
256755
|
+
}
|
|
256756
|
+
function addApp(manifest, name, app) {
|
|
256757
|
+
return {
|
|
256758
|
+
...manifest,
|
|
256759
|
+
apps: {
|
|
256760
|
+
...manifest.apps,
|
|
256761
|
+
[name]: app
|
|
256762
|
+
}
|
|
256763
|
+
};
|
|
256764
|
+
}
|
|
256765
|
+
function removeApp(manifest, name) {
|
|
256766
|
+
const nextApps = { ...manifest.apps };
|
|
256767
|
+
delete nextApps[name];
|
|
256768
|
+
const nextPackages = {};
|
|
256769
|
+
for (const [packageName, pkg] of Object.entries(manifest.packages)) {
|
|
256770
|
+
nextPackages[packageName] = {
|
|
256771
|
+
...pkg,
|
|
256772
|
+
consumers: pkg.consumers.filter((consumer) => consumer !== name)
|
|
256773
|
+
};
|
|
256774
|
+
}
|
|
256775
|
+
return {
|
|
256776
|
+
...manifest,
|
|
256777
|
+
apps: nextApps,
|
|
256778
|
+
packages: nextPackages
|
|
256779
|
+
};
|
|
256780
|
+
}
|
|
256781
|
+
function addPackage(manifest, name, pkg) {
|
|
256782
|
+
return {
|
|
256783
|
+
...manifest,
|
|
256784
|
+
packages: {
|
|
256785
|
+
...manifest.packages,
|
|
256786
|
+
[name]: pkg
|
|
256787
|
+
}
|
|
256788
|
+
};
|
|
256789
|
+
}
|
|
256790
|
+
function addConsumer(manifest, packageName, appName) {
|
|
256791
|
+
const pkg = manifest.packages[packageName];
|
|
256792
|
+
if (!pkg) {
|
|
256793
|
+
return {
|
|
256794
|
+
...manifest,
|
|
256795
|
+
packages: {
|
|
256796
|
+
...manifest.packages
|
|
256797
|
+
}
|
|
256798
|
+
};
|
|
256799
|
+
}
|
|
256800
|
+
const consumers = pkg.consumers.includes(appName) ? [...pkg.consumers] : [...pkg.consumers, appName];
|
|
256801
|
+
return {
|
|
256802
|
+
...manifest,
|
|
256803
|
+
packages: {
|
|
256804
|
+
...manifest.packages,
|
|
256805
|
+
[packageName]: {
|
|
256806
|
+
...pkg,
|
|
256807
|
+
consumers
|
|
256808
|
+
}
|
|
256907
256809
|
}
|
|
256908
256810
|
};
|
|
256909
256811
|
}
|
|
256910
256812
|
|
|
256813
|
+
// src/manifest/reader.ts
|
|
256814
|
+
function isObjectRecord(value) {
|
|
256815
|
+
return typeof value === "object" && value !== null;
|
|
256816
|
+
}
|
|
256817
|
+
function isValidWorkspaceManifest(value) {
|
|
256818
|
+
if (!isObjectRecord(value)) {
|
|
256819
|
+
return false;
|
|
256820
|
+
}
|
|
256821
|
+
if (typeof value.version !== "string") {
|
|
256822
|
+
return false;
|
|
256823
|
+
}
|
|
256824
|
+
if (!isObjectRecord(value.workspace)) {
|
|
256825
|
+
return false;
|
|
256826
|
+
}
|
|
256827
|
+
if (typeof value.workspace.name !== "string") {
|
|
256828
|
+
return false;
|
|
256829
|
+
}
|
|
256830
|
+
const packageManager = value.workspace.packageManager;
|
|
256831
|
+
if (packageManager !== "bun" && packageManager !== "npm" && packageManager !== "pnpm" && packageManager !== "yarn") {
|
|
256832
|
+
return false;
|
|
256833
|
+
}
|
|
256834
|
+
if (!isObjectRecord(value.apps)) {
|
|
256835
|
+
return false;
|
|
256836
|
+
}
|
|
256837
|
+
if (!isObjectRecord(value.packages)) {
|
|
256838
|
+
return false;
|
|
256839
|
+
}
|
|
256840
|
+
if (!isObjectRecord(value.settings)) {
|
|
256841
|
+
return false;
|
|
256842
|
+
}
|
|
256843
|
+
return true;
|
|
256844
|
+
}
|
|
256845
|
+
function getManifestPath(workspaceDir) {
|
|
256846
|
+
return join6(workspaceDir, ".kitt", "manifest.json");
|
|
256847
|
+
}
|
|
256848
|
+
function isKittWorkspace(dir) {
|
|
256849
|
+
return existsSync6(getManifestPath(dir));
|
|
256850
|
+
}
|
|
256851
|
+
function findWorkspaceRoot(startDir) {
|
|
256852
|
+
let current = resolve(startDir);
|
|
256853
|
+
while (true) {
|
|
256854
|
+
if (isKittWorkspace(current))
|
|
256855
|
+
return current;
|
|
256856
|
+
const parent = dirname2(current);
|
|
256857
|
+
if (parent === current)
|
|
256858
|
+
break;
|
|
256859
|
+
current = parent;
|
|
256860
|
+
}
|
|
256861
|
+
const globalPath = getGlobalWorkspacePath();
|
|
256862
|
+
if (globalPath && isKittWorkspace(globalPath))
|
|
256863
|
+
return globalPath;
|
|
256864
|
+
return null;
|
|
256865
|
+
}
|
|
256866
|
+
function findWorkspaceRootStrict(startDir) {
|
|
256867
|
+
let current = resolve(startDir);
|
|
256868
|
+
while (true) {
|
|
256869
|
+
if (isKittWorkspace(current))
|
|
256870
|
+
return current;
|
|
256871
|
+
const parent = dirname2(current);
|
|
256872
|
+
if (parent === current)
|
|
256873
|
+
break;
|
|
256874
|
+
current = parent;
|
|
256875
|
+
}
|
|
256876
|
+
return null;
|
|
256877
|
+
}
|
|
256878
|
+
function readManifest(workspaceDir) {
|
|
256879
|
+
const manifestPath = getManifestPath(workspaceDir);
|
|
256880
|
+
if (!existsSync6(manifestPath)) {
|
|
256881
|
+
return null;
|
|
256882
|
+
}
|
|
256883
|
+
try {
|
|
256884
|
+
const raw = readFileSync4(manifestPath, "utf-8").trim();
|
|
256885
|
+
if (raw.length === 0) {
|
|
256886
|
+
return null;
|
|
256887
|
+
}
|
|
256888
|
+
const parsed = JSON.parse(raw);
|
|
256889
|
+
if (!isValidWorkspaceManifest(parsed)) {
|
|
256890
|
+
return null;
|
|
256891
|
+
}
|
|
256892
|
+
return parsed;
|
|
256893
|
+
} catch {
|
|
256894
|
+
return null;
|
|
256895
|
+
}
|
|
256896
|
+
}
|
|
256897
|
+
function reconcileManifest(workspaceDir) {
|
|
256898
|
+
const manifest = readManifest(workspaceDir);
|
|
256899
|
+
if (!manifest)
|
|
256900
|
+
return null;
|
|
256901
|
+
const staleApps = Object.keys(manifest.apps).filter((name) => !existsSync6(join6(workspaceDir, "apps", name)));
|
|
256902
|
+
if (staleApps.length === 0)
|
|
256903
|
+
return manifest;
|
|
256904
|
+
let cleaned = manifest;
|
|
256905
|
+
for (const name of staleApps) {
|
|
256906
|
+
cleaned = removeApp(cleaned, name);
|
|
256907
|
+
}
|
|
256908
|
+
writeManifest(workspaceDir, cleaned);
|
|
256909
|
+
return cleaned;
|
|
256910
|
+
}
|
|
256911
|
+
|
|
256912
|
+
// src/utils/auth-guard.ts
|
|
256913
|
+
init_config();
|
|
256914
|
+
|
|
256915
|
+
// src/credentials/railway.ts
|
|
256916
|
+
import { execSync as execSync4 } from "node:child_process";
|
|
256917
|
+
async function isRailwayInstalled() {
|
|
256918
|
+
try {
|
|
256919
|
+
execSync4("railway --version", {
|
|
256920
|
+
encoding: "utf-8",
|
|
256921
|
+
stdio: "pipe"
|
|
256922
|
+
});
|
|
256923
|
+
return true;
|
|
256924
|
+
} catch {
|
|
256925
|
+
return false;
|
|
256926
|
+
}
|
|
256927
|
+
}
|
|
256928
|
+
async function checkRailwayAuth() {
|
|
256929
|
+
const installed = await isRailwayInstalled();
|
|
256930
|
+
if (!installed) {
|
|
256931
|
+
return {
|
|
256932
|
+
authenticated: false,
|
|
256933
|
+
error: "Railway CLI not installed"
|
|
256934
|
+
};
|
|
256935
|
+
}
|
|
256936
|
+
try {
|
|
256937
|
+
const output = execSync4("railway whoami", {
|
|
256938
|
+
encoding: "utf-8",
|
|
256939
|
+
stdio: "pipe"
|
|
256940
|
+
}).trim();
|
|
256941
|
+
if (output && output.length > 0) {
|
|
256942
|
+
return {
|
|
256943
|
+
authenticated: true,
|
|
256944
|
+
username: output
|
|
256945
|
+
};
|
|
256946
|
+
}
|
|
256947
|
+
return {
|
|
256948
|
+
authenticated: false
|
|
256949
|
+
};
|
|
256950
|
+
} catch {
|
|
256951
|
+
return {
|
|
256952
|
+
authenticated: false
|
|
256953
|
+
};
|
|
256954
|
+
}
|
|
256955
|
+
}
|
|
256956
|
+
async function railwayLogin() {
|
|
256957
|
+
try {
|
|
256958
|
+
execSync4("railway login", {
|
|
256959
|
+
stdio: "inherit"
|
|
256960
|
+
});
|
|
256961
|
+
return await checkRailwayAuth();
|
|
256962
|
+
} catch {
|
|
256963
|
+
return {
|
|
256964
|
+
authenticated: false,
|
|
256965
|
+
error: "Failed to complete Railway login"
|
|
256966
|
+
};
|
|
256967
|
+
}
|
|
256968
|
+
}
|
|
256969
|
+
async function railwayLogout() {
|
|
256970
|
+
try {
|
|
256971
|
+
execSync4("railway logout", {
|
|
256972
|
+
encoding: "utf-8",
|
|
256973
|
+
stdio: "pipe"
|
|
256974
|
+
});
|
|
256975
|
+
return true;
|
|
256976
|
+
} catch {
|
|
256977
|
+
return false;
|
|
256978
|
+
}
|
|
256979
|
+
}
|
|
256980
|
+
|
|
256981
|
+
// src/utils/auth-guard.ts
|
|
256982
|
+
var WORKSPACE_REQUIRED = new Set([
|
|
256983
|
+
"create",
|
|
256984
|
+
"delete",
|
|
256985
|
+
"list",
|
|
256986
|
+
"run",
|
|
256987
|
+
"deploy",
|
|
256988
|
+
"deploy:template",
|
|
256989
|
+
"env:create",
|
|
256990
|
+
"env:vars",
|
|
256991
|
+
"domain",
|
|
256992
|
+
"logs",
|
|
256993
|
+
"status",
|
|
256994
|
+
"versions"
|
|
256995
|
+
]);
|
|
256996
|
+
var COMMAND_AUTH = {
|
|
256997
|
+
login: "none",
|
|
256998
|
+
logout: "none",
|
|
256999
|
+
help: "none",
|
|
257000
|
+
settings: "none",
|
|
257001
|
+
list: "none",
|
|
257002
|
+
versions: "none",
|
|
257003
|
+
exit: "none",
|
|
257004
|
+
init: "both",
|
|
257005
|
+
create: "both",
|
|
257006
|
+
delete: "both",
|
|
257007
|
+
deploy: "both",
|
|
257008
|
+
"deploy:template": "both",
|
|
257009
|
+
"env:create": "both",
|
|
257010
|
+
"env:vars": "both",
|
|
257011
|
+
domain: "both",
|
|
257012
|
+
logs: "both",
|
|
257013
|
+
status: "both"
|
|
257014
|
+
};
|
|
257015
|
+
async function checkAuthGuard(commandKey) {
|
|
257016
|
+
if (WORKSPACE_REQUIRED.has(commandKey)) {
|
|
257017
|
+
const workspaceRoot = findWorkspaceRootStrict(process.cwd());
|
|
257018
|
+
if (!workspaceRoot) {
|
|
257019
|
+
return {
|
|
257020
|
+
allowed: false,
|
|
257021
|
+
message: "No KITT workspace found. Run /init to initialize one."
|
|
257022
|
+
};
|
|
257023
|
+
}
|
|
257024
|
+
}
|
|
257025
|
+
const requirement = COMMAND_AUTH[commandKey];
|
|
257026
|
+
if (!requirement || requirement === "none") {
|
|
257027
|
+
return { allowed: true };
|
|
257028
|
+
}
|
|
257029
|
+
if (requirement === "llm" || requirement === "both") {
|
|
257030
|
+
const llmConfigured = await isLlmConfigured();
|
|
257031
|
+
if (!llmConfigured) {
|
|
257032
|
+
return {
|
|
257033
|
+
allowed: false,
|
|
257034
|
+
message: "LLM API key required. Run /login llm to configure."
|
|
257035
|
+
};
|
|
257036
|
+
}
|
|
257037
|
+
}
|
|
257038
|
+
if (requirement === "railway" || requirement === "both") {
|
|
257039
|
+
const railwayStatus = await checkRailwayAuth();
|
|
257040
|
+
if (!railwayStatus.authenticated) {
|
|
257041
|
+
return {
|
|
257042
|
+
allowed: false,
|
|
257043
|
+
message: "Railway authentication required. Run /login railway to authenticate."
|
|
257044
|
+
};
|
|
257045
|
+
}
|
|
257046
|
+
}
|
|
257047
|
+
return { allowed: true };
|
|
257048
|
+
}
|
|
257049
|
+
|
|
256911
257050
|
// src/sandbox/staging.ts
|
|
257051
|
+
import {
|
|
257052
|
+
copyFileSync,
|
|
257053
|
+
existsSync as existsSync7,
|
|
257054
|
+
mkdirSync as mkdirSync5,
|
|
257055
|
+
readdirSync,
|
|
257056
|
+
readFileSync as readFileSync5,
|
|
257057
|
+
rmSync as rmSync2,
|
|
257058
|
+
statSync as statSync3,
|
|
257059
|
+
writeFileSync as writeFileSync5
|
|
257060
|
+
} from "node:fs";
|
|
257061
|
+
import { createHash } from "node:crypto";
|
|
257062
|
+
import { dirname as dirname3, join as join7, relative } from "node:path";
|
|
256912
257063
|
var KITT_DIR = ".kitt";
|
|
256913
257064
|
var STAGING_DIR = "staging";
|
|
256914
257065
|
function getStagingDir(workspaceDir) {
|
|
256915
|
-
return
|
|
257066
|
+
return join7(workspaceDir, KITT_DIR, STAGING_DIR);
|
|
256916
257067
|
}
|
|
256917
257068
|
function hashContent(content) {
|
|
256918
257069
|
return createHash("sha256").update(content).digest("hex");
|
|
@@ -256929,7 +257080,7 @@ function countLines(content) {
|
|
|
256929
257080
|
function collectStagedFilePaths(stagingDir, currentDir, output) {
|
|
256930
257081
|
const entries = readdirSync(currentDir);
|
|
256931
257082
|
for (const entry of entries) {
|
|
256932
|
-
const absolutePath =
|
|
257083
|
+
const absolutePath = join7(currentDir, entry);
|
|
256933
257084
|
const stats = statSync3(absolutePath);
|
|
256934
257085
|
if (stats.isDirectory()) {
|
|
256935
257086
|
collectStagedFilePaths(stagingDir, absolutePath, output);
|
|
@@ -256942,36 +257093,36 @@ function collectStagedFilePaths(stagingDir, currentDir, output) {
|
|
|
256942
257093
|
function clearStaging(workspaceDir) {
|
|
256943
257094
|
const logger = createAuditLogger(workspaceDir);
|
|
256944
257095
|
const stagingDir = getStagingDir(workspaceDir);
|
|
256945
|
-
if (
|
|
257096
|
+
if (existsSync7(stagingDir)) {
|
|
256946
257097
|
rmSync2(stagingDir, { recursive: true, force: true });
|
|
256947
257098
|
}
|
|
256948
257099
|
mkdirSync5(stagingDir, { recursive: true });
|
|
256949
|
-
logger.staged(
|
|
257100
|
+
logger.staged(join7(KITT_DIR, STAGING_DIR), "cleared");
|
|
256950
257101
|
}
|
|
256951
257102
|
function writeToStaging(workspaceDir, relativePath, content) {
|
|
256952
257103
|
const logger = createAuditLogger(workspaceDir);
|
|
256953
257104
|
const stagingDir = getStagingDir(workspaceDir);
|
|
256954
|
-
const stagedPath =
|
|
257105
|
+
const stagedPath = join7(stagingDir, relativePath);
|
|
256955
257106
|
assertWithinWorkspace(stagingDir, stagedPath);
|
|
256956
257107
|
mkdirSync5(dirname3(stagedPath), { recursive: true });
|
|
256957
257108
|
writeFileSync5(stagedPath, content, "utf-8");
|
|
256958
257109
|
const hash = hashContent(content);
|
|
256959
257110
|
logger.staged(relativePath, "written to staging");
|
|
256960
|
-
logger.fileWrite(
|
|
257111
|
+
logger.fileWrite(join7(KITT_DIR, STAGING_DIR, relativePath), hash);
|
|
256961
257112
|
}
|
|
256962
257113
|
function listStagedFiles(workspaceDir) {
|
|
256963
257114
|
const logger = createAuditLogger(workspaceDir);
|
|
256964
257115
|
const stagingDir = getStagingDir(workspaceDir);
|
|
256965
|
-
if (!
|
|
257116
|
+
if (!existsSync7(stagingDir)) {
|
|
256966
257117
|
return [];
|
|
256967
257118
|
}
|
|
256968
257119
|
const filePaths = [];
|
|
256969
257120
|
collectStagedFilePaths(stagingDir, stagingDir, filePaths);
|
|
256970
257121
|
return filePaths.sort((a, b3) => a.localeCompare(b3)).map((stagedRelativePath) => {
|
|
256971
|
-
const workspacePath =
|
|
257122
|
+
const workspacePath = join7(workspaceDir, stagedRelativePath);
|
|
256972
257123
|
assertWithinWorkspace(workspaceDir, workspacePath);
|
|
256973
|
-
const content = readFileSync5(
|
|
256974
|
-
const isNew = !
|
|
257124
|
+
const content = readFileSync5(join7(stagingDir, stagedRelativePath), "utf-8");
|
|
257125
|
+
const isNew = !existsSync7(workspacePath);
|
|
256975
257126
|
const isModified = !isNew;
|
|
256976
257127
|
logger.staged(stagedRelativePath, isNew ? "new" : "modified");
|
|
256977
257128
|
return {
|
|
@@ -256994,8 +257145,8 @@ function applyStagedChanges(workspaceDir, stagedFiles) {
|
|
|
256994
257145
|
const logger = createAuditLogger(workspaceDir);
|
|
256995
257146
|
const stagingDir = getStagingDir(workspaceDir);
|
|
256996
257147
|
for (const stagedFile of stagedFiles) {
|
|
256997
|
-
const sourcePath =
|
|
256998
|
-
const destinationPath =
|
|
257148
|
+
const sourcePath = join7(stagingDir, stagedFile.relativePath);
|
|
257149
|
+
const destinationPath = join7(workspaceDir, stagedFile.relativePath);
|
|
256999
257150
|
assertWithinWorkspace(workspaceDir, destinationPath);
|
|
257000
257151
|
mkdirSync5(dirname3(destinationPath), { recursive: true });
|
|
257001
257152
|
copyFileSync(sourcePath, destinationPath);
|
|
@@ -257115,7 +257266,7 @@ function createRateLimiter() {
|
|
|
257115
257266
|
}
|
|
257116
257267
|
|
|
257117
257268
|
// src/llm/client.ts
|
|
257118
|
-
var
|
|
257269
|
+
var auditLogger2 = createAuditLogger(".");
|
|
257119
257270
|
var DEFAULT_MAX_TOKENS = 8192;
|
|
257120
257271
|
async function loadProvider(provider) {
|
|
257121
257272
|
switch (provider) {
|
|
@@ -257159,17 +257310,17 @@ function ensureRateLimit(rateLimiter, provider, model, estimatedTokens) {
|
|
|
257159
257310
|
if (check.allowed) {
|
|
257160
257311
|
return;
|
|
257161
257312
|
}
|
|
257162
|
-
|
|
257313
|
+
auditLogger2.llmCall(provider, model, PROMPT_VERSION, estimatedTokens, "FAILED");
|
|
257163
257314
|
throw new Error(check.reason ?? "LLM call limit reached for this session.");
|
|
257164
257315
|
}
|
|
257165
257316
|
async function executeWithAudit(options) {
|
|
257166
257317
|
const { provider, model, estimatedTokens, rateLimiter, operation } = options;
|
|
257167
257318
|
try {
|
|
257168
257319
|
const response = await operation();
|
|
257169
|
-
|
|
257320
|
+
auditLogger2.llmCall(provider, model, PROMPT_VERSION, estimatedTokens, "SUCCESS");
|
|
257170
257321
|
return response;
|
|
257171
257322
|
} catch (error4) {
|
|
257172
|
-
|
|
257323
|
+
auditLogger2.llmCall(provider, model, PROMPT_VERSION, estimatedTokens, "FAILED");
|
|
257173
257324
|
throw error4;
|
|
257174
257325
|
} finally {
|
|
257175
257326
|
rateLimiter.recordCall(estimatedTokens);
|
|
@@ -257915,7 +258066,7 @@ var CLIENT_INFO = {
|
|
|
257915
258066
|
name: "openkitt",
|
|
257916
258067
|
version: "0.1.0"
|
|
257917
258068
|
};
|
|
257918
|
-
var
|
|
258069
|
+
var auditLogger3 = createAuditLogger(".");
|
|
257919
258070
|
function createJsonRpcError(code, message) {
|
|
257920
258071
|
const error4 = new Error(message);
|
|
257921
258072
|
error4.code = code;
|
|
@@ -258085,7 +258236,7 @@ async function createMcpClient(server2) {
|
|
|
258085
258236
|
if (!isToolsListResult(result)) {
|
|
258086
258237
|
throw new Error("Invalid tools/list response from MCP server");
|
|
258087
258238
|
}
|
|
258088
|
-
|
|
258239
|
+
auditLogger3.mcp("tools/list", "{}", "SUCCESS");
|
|
258089
258240
|
return result.tools;
|
|
258090
258241
|
},
|
|
258091
258242
|
async callTool(name, args) {
|
|
@@ -258100,12 +258251,12 @@ async function createMcpClient(server2) {
|
|
|
258100
258251
|
throw new Error("Invalid tools/call response from MCP server");
|
|
258101
258252
|
}
|
|
258102
258253
|
const status = result.isError ? "FAILED" : "SUCCESS";
|
|
258103
|
-
|
|
258254
|
+
auditLogger3.mcp(name, paramsText, status, result.isError ? "tool returned isError=true" : undefined);
|
|
258104
258255
|
return result;
|
|
258105
258256
|
} catch (requestError) {
|
|
258106
258257
|
const error4 = requestError instanceof Error ? requestError : new Error(String(requestError));
|
|
258107
258258
|
const detail = "code" in error4 ? `${String(error4.code)}: ${error4.message}` : error4.message;
|
|
258108
|
-
|
|
258259
|
+
auditLogger3.mcp(name, paramsText, "FAILED", detail);
|
|
258109
258260
|
throw error4;
|
|
258110
258261
|
}
|
|
258111
258262
|
},
|
|
@@ -258116,137 +258267,6 @@ async function createMcpClient(server2) {
|
|
|
258116
258267
|
};
|
|
258117
258268
|
}
|
|
258118
258269
|
|
|
258119
|
-
// src/mcp/lifecycle.ts
|
|
258120
|
-
import { spawn } from "node:child_process";
|
|
258121
|
-
import { fileURLToPath } from "node:url";
|
|
258122
|
-
import { dirname as dirname4, join as join7 } from "node:path";
|
|
258123
|
-
var MCP_ENTRY_POINT = join7(dirname4(fileURLToPath(import.meta.url)), "..", "..", "node_modules", "@railway", "mcp-server", "dist", "index.js");
|
|
258124
|
-
var MCP_START_FAILURE_MESSAGE = "Railway MCP Server failed to start. Try reinstalling: npm install -g openkitt@latest";
|
|
258125
|
-
var SHUTDOWN_TIMEOUT_MS = 5000;
|
|
258126
|
-
var auditLogger3 = createAuditLogger(".");
|
|
258127
|
-
var activeServer = null;
|
|
258128
|
-
var pendingSpawn = null;
|
|
258129
|
-
var shouldLogRespawn = false;
|
|
258130
|
-
var intentionallyShuttingDown = new WeakSet;
|
|
258131
|
-
function formatExitDetail(code, signal) {
|
|
258132
|
-
const codeLabel = code === null ? "null" : String(code);
|
|
258133
|
-
const signalLabel = signal ?? "null";
|
|
258134
|
-
return `code=${codeLabel}, signal=${signalLabel}`;
|
|
258135
|
-
}
|
|
258136
|
-
function isChildRunning(child) {
|
|
258137
|
-
return child.exitCode === null && !child.killed;
|
|
258138
|
-
}
|
|
258139
|
-
function buildServerProcess(child) {
|
|
258140
|
-
if (!child.stdin || !child.stdout) {
|
|
258141
|
-
throw new Error("MCP server stdio was not created");
|
|
258142
|
-
}
|
|
258143
|
-
return {
|
|
258144
|
-
process: child,
|
|
258145
|
-
stdin: child.stdin,
|
|
258146
|
-
stdout: child.stdout,
|
|
258147
|
-
pid: child.pid ?? -1
|
|
258148
|
-
};
|
|
258149
|
-
}
|
|
258150
|
-
function attachLifecycleListeners(child) {
|
|
258151
|
-
child.stderr?.on("data", (chunk) => {
|
|
258152
|
-
const message = String(chunk).trim();
|
|
258153
|
-
if (!message) {
|
|
258154
|
-
return;
|
|
258155
|
-
}
|
|
258156
|
-
auditLogger3.mcp("server-lifecycle", "stderr", "FAILED", message);
|
|
258157
|
-
});
|
|
258158
|
-
child.on("exit", (code, signal) => {
|
|
258159
|
-
const detail = formatExitDetail(code, signal);
|
|
258160
|
-
if (activeServer?.process === child) {
|
|
258161
|
-
activeServer = null;
|
|
258162
|
-
}
|
|
258163
|
-
if (intentionallyShuttingDown.has(child)) {
|
|
258164
|
-
return;
|
|
258165
|
-
}
|
|
258166
|
-
shouldLogRespawn = true;
|
|
258167
|
-
auditLogger3.mcp("server-lifecycle", "crash", "FAILED", detail);
|
|
258168
|
-
});
|
|
258169
|
-
}
|
|
258170
|
-
function displaySpawnFailure(reason) {
|
|
258171
|
-
error(MCP_START_FAILURE_MESSAGE);
|
|
258172
|
-
auditLogger3.mcp("server-lifecycle", "spawn", "FAILED", reason);
|
|
258173
|
-
}
|
|
258174
|
-
async function spawnMcpServer() {
|
|
258175
|
-
if (activeServer && isChildRunning(activeServer.process)) {
|
|
258176
|
-
return activeServer;
|
|
258177
|
-
}
|
|
258178
|
-
if (pendingSpawn) {
|
|
258179
|
-
return pendingSpawn;
|
|
258180
|
-
}
|
|
258181
|
-
const respawn = shouldLogRespawn;
|
|
258182
|
-
const child = spawn("node", [MCP_ENTRY_POINT], {
|
|
258183
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
258184
|
-
});
|
|
258185
|
-
attachLifecycleListeners(child);
|
|
258186
|
-
pendingSpawn = new Promise((resolve2, reject) => {
|
|
258187
|
-
const handleError = (spawnError) => {
|
|
258188
|
-
child.off("spawn", handleSpawn);
|
|
258189
|
-
if (activeServer?.process === child) {
|
|
258190
|
-
activeServer = null;
|
|
258191
|
-
}
|
|
258192
|
-
displaySpawnFailure(spawnError.message);
|
|
258193
|
-
reject(spawnError);
|
|
258194
|
-
};
|
|
258195
|
-
const handleSpawn = () => {
|
|
258196
|
-
child.off("error", handleError);
|
|
258197
|
-
let serverProcess;
|
|
258198
|
-
try {
|
|
258199
|
-
serverProcess = buildServerProcess(child);
|
|
258200
|
-
} catch (buildError) {
|
|
258201
|
-
const err = buildError instanceof Error ? buildError : new Error(String(buildError));
|
|
258202
|
-
displaySpawnFailure(err.message);
|
|
258203
|
-
reject(err);
|
|
258204
|
-
return;
|
|
258205
|
-
}
|
|
258206
|
-
activeServer = serverProcess;
|
|
258207
|
-
shouldLogRespawn = false;
|
|
258208
|
-
if (respawn) {
|
|
258209
|
-
auditLogger3.mcp("server-lifecycle", "respawn", "SUCCESS", `pid=${serverProcess.pid}`);
|
|
258210
|
-
} else {
|
|
258211
|
-
auditLogger3.mcp("server-lifecycle", "spawn", "SUCCESS", `pid=${serverProcess.pid}`);
|
|
258212
|
-
}
|
|
258213
|
-
resolve2(serverProcess);
|
|
258214
|
-
};
|
|
258215
|
-
child.once("error", handleError);
|
|
258216
|
-
child.once("spawn", handleSpawn);
|
|
258217
|
-
}).finally(() => {
|
|
258218
|
-
pendingSpawn = null;
|
|
258219
|
-
});
|
|
258220
|
-
return pendingSpawn;
|
|
258221
|
-
}
|
|
258222
|
-
async function shutdownMcpServer() {
|
|
258223
|
-
if (!activeServer) {
|
|
258224
|
-
return;
|
|
258225
|
-
}
|
|
258226
|
-
const child = activeServer.process;
|
|
258227
|
-
intentionallyShuttingDown.add(child);
|
|
258228
|
-
if (!isChildRunning(child)) {
|
|
258229
|
-
activeServer = null;
|
|
258230
|
-
return;
|
|
258231
|
-
}
|
|
258232
|
-
const exitPromise = new Promise((resolve2) => {
|
|
258233
|
-
child.once("exit", (code, signal) => {
|
|
258234
|
-
resolve2({ code, signal });
|
|
258235
|
-
});
|
|
258236
|
-
});
|
|
258237
|
-
child.kill("SIGTERM");
|
|
258238
|
-
let forcedKill = false;
|
|
258239
|
-
const timeoutHandle = setTimeout(() => {
|
|
258240
|
-
forcedKill = true;
|
|
258241
|
-
child.kill("SIGKILL");
|
|
258242
|
-
}, SHUTDOWN_TIMEOUT_MS);
|
|
258243
|
-
const exitResult = await exitPromise;
|
|
258244
|
-
clearTimeout(timeoutHandle);
|
|
258245
|
-
activeServer = null;
|
|
258246
|
-
const detail = forcedKill ? `forced after timeout (${formatExitDetail(exitResult.code, exitResult.signal)})` : formatExitDetail(exitResult.code, exitResult.signal);
|
|
258247
|
-
auditLogger3.mcp("server-lifecycle", "shutdown", "SUCCESS", detail);
|
|
258248
|
-
}
|
|
258249
|
-
|
|
258250
258270
|
// src/scaffold/packages.ts
|
|
258251
258271
|
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "node:fs";
|
|
258252
258272
|
import { join as join8 } from "node:path";
|
|
@@ -258393,7 +258413,7 @@ function scaffoldDefaultPackages(packagesDir) {
|
|
|
258393
258413
|
}
|
|
258394
258414
|
|
|
258395
258415
|
// src/utils/validation.ts
|
|
258396
|
-
import { existsSync as
|
|
258416
|
+
import { existsSync as existsSync8 } from "node:fs";
|
|
258397
258417
|
import { join as join9 } from "node:path";
|
|
258398
258418
|
var APP_NAME_REGEX = /^[a-z][a-z0-9-]{1,48}[a-z0-9]$/;
|
|
258399
258419
|
function validateAppName(name) {
|
|
@@ -258420,7 +258440,7 @@ function sanitizeInput(input) {
|
|
|
258420
258440
|
function validateAppNameUniqueness(name, workspaceDir) {
|
|
258421
258441
|
const manifest = readManifest(workspaceDir);
|
|
258422
258442
|
const existsInManifest = manifest !== null && name in manifest.apps;
|
|
258423
|
-
const existsInAppsDirectory =
|
|
258443
|
+
const existsInAppsDirectory = existsSync8(join9(workspaceDir, "apps", name));
|
|
258424
258444
|
if (existsInManifest || existsInAppsDirectory) {
|
|
258425
258445
|
return {
|
|
258426
258446
|
valid: false,
|
|
@@ -258432,7 +258452,7 @@ function validateAppNameUniqueness(name, workspaceDir) {
|
|
|
258432
258452
|
|
|
258433
258453
|
// src/versions/integrity.ts
|
|
258434
258454
|
import { createHash as createHash2 } from "node:crypto";
|
|
258435
|
-
import { chmodSync as chmodSync3, existsSync as
|
|
258455
|
+
import { chmodSync as chmodSync3, existsSync as existsSync9, readFileSync as readFileSync6, renameSync as renameSync4, unlinkSync as unlinkSync3, writeFileSync as writeFileSync7 } from "node:fs";
|
|
258436
258456
|
import { platform as platform4 } from "node:os";
|
|
258437
258457
|
import { join as join10 } from "node:path";
|
|
258438
258458
|
var FILE_MODE3 = 384;
|
|
@@ -258467,7 +258487,7 @@ function writeVersionsLock(workspaceDir, hash) {
|
|
|
258467
258487
|
chmodSync3(lockPath, FILE_MODE3);
|
|
258468
258488
|
}
|
|
258469
258489
|
} catch (error4) {
|
|
258470
|
-
if (
|
|
258490
|
+
if (existsSync9(tempPath)) {
|
|
258471
258491
|
unlinkSync3(tempPath);
|
|
258472
258492
|
}
|
|
258473
258493
|
throw error4;
|
|
@@ -258921,7 +258941,7 @@ async function initCommand(context, _args) {
|
|
|
258921
258941
|
}
|
|
258922
258942
|
|
|
258923
258943
|
// src/commands/create.ts
|
|
258924
|
-
import { existsSync as
|
|
258944
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync10 } from "node:fs";
|
|
258925
258945
|
import { join as join18 } from "node:path";
|
|
258926
258946
|
init_config();
|
|
258927
258947
|
|
|
@@ -262205,7 +262225,7 @@ async function executeCreateScaffolding(options) {
|
|
|
262205
262225
|
}
|
|
262206
262226
|
|
|
262207
262227
|
// src/sandbox/scanner.ts
|
|
262208
|
-
import { existsSync as
|
|
262228
|
+
import { existsSync as existsSync10, lstatSync, readFileSync as readFileSync8 } from "node:fs";
|
|
262209
262229
|
import { extname, isAbsolute, join as join13, normalize, resolve as resolve3 } from "node:path";
|
|
262210
262230
|
var ALLOWED_EXTENSIONS = new Set([
|
|
262211
262231
|
".ts",
|
|
@@ -262281,7 +262301,7 @@ function validateFilePath(filePath) {
|
|
|
262281
262301
|
detail: "Path contains '..' segments and may escape the workspace"
|
|
262282
262302
|
});
|
|
262283
262303
|
}
|
|
262284
|
-
if (
|
|
262304
|
+
if (existsSync10(filePath)) {
|
|
262285
262305
|
const stats = lstatSync(filePath);
|
|
262286
262306
|
if (stats.isSymbolicLink()) {
|
|
262287
262307
|
warnings.push({
|
|
@@ -262390,8 +262410,8 @@ async function confirmAndApply(options) {
|
|
|
262390
262410
|
// src/ast/engine.ts
|
|
262391
262411
|
var import_ts_morph = __toESM(require_ts_morph(), 1);
|
|
262392
262412
|
import { createHash as createHash3 } from "node:crypto";
|
|
262393
|
-
import { existsSync as
|
|
262394
|
-
import { dirname as
|
|
262413
|
+
import { existsSync as existsSync11, mkdirSync as mkdirSync8, writeFileSync as writeFileSync10 } from "node:fs";
|
|
262414
|
+
import { dirname as dirname4, isAbsolute as isAbsolute2, join as join14, normalize as normalize2, relative as relative2, resolve as resolve4 } from "node:path";
|
|
262395
262415
|
var KITT_DIR2 = ".kitt";
|
|
262396
262416
|
var STAGING_DIR2 = "staging";
|
|
262397
262417
|
function hashContent2(content) {
|
|
@@ -262435,7 +262455,7 @@ function createAstEngine(workspaceDir) {
|
|
|
262435
262455
|
if (!isRelativePathInside(workspaceDir, fullPath)) {
|
|
262436
262456
|
throw new Error(`Path is outside workspace: ${relativePath}`);
|
|
262437
262457
|
}
|
|
262438
|
-
if (!
|
|
262458
|
+
if (!existsSync11(fullPath)) {
|
|
262439
262459
|
throw new Error(`File does not exist: ${relativePath}`);
|
|
262440
262460
|
}
|
|
262441
262461
|
const existing = project.getSourceFile(fullPath);
|
|
@@ -262450,7 +262470,7 @@ function createAstEngine(workspaceDir) {
|
|
|
262450
262470
|
if (!isRelativePathInside(resolve4(workspaceDir, KITT_DIR2, STAGING_DIR2), stagingPath)) {
|
|
262451
262471
|
throw new Error(`Refusing to write outside staging directory: ${relativePath}`);
|
|
262452
262472
|
}
|
|
262453
|
-
mkdirSync8(
|
|
262473
|
+
mkdirSync8(dirname4(stagingPath), { recursive: true });
|
|
262454
262474
|
const fullText = sourceFile.getFullText();
|
|
262455
262475
|
writeFileSync10(stagingPath, fullText, "utf-8");
|
|
262456
262476
|
auditLogger4.staged(relativePath, "AST modified");
|
|
@@ -262823,7 +262843,7 @@ function applyOperation(sourceFile, operation) {
|
|
|
262823
262843
|
|
|
262824
262844
|
// src/ast/validator.ts
|
|
262825
262845
|
var import_ts_morph3 = __toESM(require_ts_morph(), 1);
|
|
262826
|
-
import { existsSync as
|
|
262846
|
+
import { existsSync as existsSync12 } from "node:fs";
|
|
262827
262847
|
import { extname as extname2, isAbsolute as isAbsolute3, normalize as normalize3, relative as relative3, resolve as resolve5 } from "node:path";
|
|
262828
262848
|
var VALID_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx"]);
|
|
262829
262849
|
var TARGET_FILE_OPERATION = { op: "targetFile" };
|
|
@@ -263010,7 +263030,7 @@ function validateTargetFile(workspaceDir, filePath) {
|
|
|
263010
263030
|
message: `Path is outside workspace: ${filePath}`
|
|
263011
263031
|
});
|
|
263012
263032
|
}
|
|
263013
|
-
if (!
|
|
263033
|
+
if (!existsSync12(absoluteTargetPath)) {
|
|
263014
263034
|
errors.push({
|
|
263015
263035
|
filePath,
|
|
263016
263036
|
operation: TARGET_FILE_OPERATION,
|
|
@@ -263131,7 +263151,7 @@ function executeTransformPipeline(transforms, workspaceDir) {
|
|
|
263131
263151
|
}
|
|
263132
263152
|
|
|
263133
263153
|
// src/commands/create-pipeline.ts
|
|
263134
|
-
import { execSync as
|
|
263154
|
+
import { execSync as execSync5 } from "node:child_process";
|
|
263135
263155
|
import { join as join15 } from "node:path";
|
|
263136
263156
|
|
|
263137
263157
|
// src/utils/pm.ts
|
|
@@ -263308,7 +263328,7 @@ function executeCommandPipeline(commands, options) {
|
|
|
263308
263328
|
continue;
|
|
263309
263329
|
}
|
|
263310
263330
|
try {
|
|
263311
|
-
|
|
263331
|
+
execSync5(bare, { cwd, stdio: "inherit" });
|
|
263312
263332
|
results.push({
|
|
263313
263333
|
command: cmd.command,
|
|
263314
263334
|
purpose: cmd.purpose,
|
|
@@ -263391,13 +263411,13 @@ async function provisionInfrastructure(options) {
|
|
|
263391
263411
|
|
|
263392
263412
|
// src/commands/run.ts
|
|
263393
263413
|
import { spawn as spawn2 } from "node:child_process";
|
|
263394
|
-
import { existsSync as
|
|
263414
|
+
import { existsSync as existsSync14, readFileSync as readFileSync10 } from "node:fs";
|
|
263395
263415
|
import { join as join17 } from "node:path";
|
|
263396
263416
|
var import_picocolors6 = __toESM(require_picocolors(), 1);
|
|
263397
263417
|
|
|
263398
263418
|
// src/commands/settings.ts
|
|
263399
|
-
import { execSync as
|
|
263400
|
-
import { chmodSync as chmodSync5, existsSync as
|
|
263419
|
+
import { execSync as execSync6 } from "node:child_process";
|
|
263420
|
+
import { chmodSync as chmodSync5, existsSync as existsSync13, mkdirSync as mkdirSync9, readFileSync as readFileSync9, renameSync as renameSync5, rmSync as rmSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync11 } from "node:fs";
|
|
263401
263421
|
import { homedir as homedir3, platform as platform6 } from "node:os";
|
|
263402
263422
|
import { join as join16 } from "node:path";
|
|
263403
263423
|
var SUPPORTED_PACKAGE_MANAGERS = ["bun", "npm", "pnpm", "yarn"];
|
|
@@ -263415,7 +263435,7 @@ function isWindows4() {
|
|
|
263415
263435
|
return platform6() === "win32";
|
|
263416
263436
|
}
|
|
263417
263437
|
function ensureConfigDir2() {
|
|
263418
|
-
if (!
|
|
263438
|
+
if (!existsSync13(CONFIG_DIR2)) {
|
|
263419
263439
|
mkdirSync9(CONFIG_DIR2, { recursive: true, mode: DIR_MODE3 });
|
|
263420
263440
|
}
|
|
263421
263441
|
if (!isWindows4()) {
|
|
@@ -263427,7 +263447,7 @@ function isPackageManager(value) {
|
|
|
263427
263447
|
}
|
|
263428
263448
|
function readGlobalConfig2() {
|
|
263429
263449
|
ensureConfigDir2();
|
|
263430
|
-
if (!
|
|
263450
|
+
if (!existsSync13(CONFIG_FILE2)) {
|
|
263431
263451
|
return {};
|
|
263432
263452
|
}
|
|
263433
263453
|
const raw = readFileSync9(CONFIG_FILE2, "utf-8").trim();
|
|
@@ -263459,7 +263479,7 @@ function writeGlobalConfig2(config) {
|
|
|
263459
263479
|
chmodSync5(CONFIG_FILE2, FILE_MODE4);
|
|
263460
263480
|
}
|
|
263461
263481
|
} catch (writeError) {
|
|
263462
|
-
if (
|
|
263482
|
+
if (existsSync13(tempFile)) {
|
|
263463
263483
|
unlinkSync4(tempFile);
|
|
263464
263484
|
}
|
|
263465
263485
|
throw writeError;
|
|
@@ -263584,7 +263604,7 @@ async function maybeConfirmMigration(context, fromPm, toPm) {
|
|
|
263584
263604
|
function migrateWorkspacePackageManager(workspaceDir, fromPm, toPm) {
|
|
263585
263605
|
removePackageManagerArtifacts(workspaceDir, fromPm);
|
|
263586
263606
|
writePackageManagerFiles(workspaceDir, toPm);
|
|
263587
|
-
|
|
263607
|
+
execSync6(getInstallCommand(toPm), { cwd: workspaceDir, stdio: "inherit" });
|
|
263588
263608
|
}
|
|
263589
263609
|
async function runDisplayMode(workspaceDir) {
|
|
263590
263610
|
const autoOpen = readAutoOpenBrowser();
|
|
@@ -263668,7 +263688,7 @@ async function settingsCommand(context, args) {
|
|
|
263668
263688
|
var DEV_SCRIPT_CANDIDATES = ["dev", "start", "serve", "preview"];
|
|
263669
263689
|
function resolveDevScript(appDir) {
|
|
263670
263690
|
const pkgPath = join17(appDir, "package.json");
|
|
263671
|
-
if (!
|
|
263691
|
+
if (!existsSync14(pkgPath)) {
|
|
263672
263692
|
return { found: false, reason: "no-package-json", available: [] };
|
|
263673
263693
|
}
|
|
263674
263694
|
let pkg;
|
|
@@ -263955,7 +263975,7 @@ async function createCommand2(context, _args) {
|
|
|
263955
263975
|
});
|
|
263956
263976
|
logger.cmd("/create", "SUCCESS");
|
|
263957
263977
|
success(`App ${selections.appName} created.`);
|
|
263958
|
-
if (
|
|
263978
|
+
if (existsSync15(appDir)) {
|
|
263959
263979
|
const runCmd = getCommand(manifest.workspace.packageManager, "run");
|
|
263960
263980
|
const scriptResolution = resolveDevScript(appDir);
|
|
263961
263981
|
if (scriptResolution.found) {
|
|
@@ -264054,7 +264074,7 @@ async function deleteCommand(context, args) {
|
|
|
264054
264074
|
}
|
|
264055
264075
|
|
|
264056
264076
|
// src/commands/deploy.ts
|
|
264057
|
-
import { existsSync as
|
|
264077
|
+
import { existsSync as existsSync16, readdirSync as readdirSync3, readFileSync as readFileSync11, writeFileSync as writeFileSync13 } from "node:fs";
|
|
264058
264078
|
import { basename as basename2, join as join20 } from "node:path";
|
|
264059
264079
|
init_config();
|
|
264060
264080
|
|
|
@@ -264118,7 +264138,7 @@ function matchesGitignorePattern(filePath, pattern) {
|
|
|
264118
264138
|
}
|
|
264119
264139
|
function loadGitignorePatterns(workspaceDir) {
|
|
264120
264140
|
const gitignorePath = join20(workspaceDir, ".gitignore");
|
|
264121
|
-
if (!
|
|
264141
|
+
if (!existsSync16(gitignorePath)) {
|
|
264122
264142
|
return [];
|
|
264123
264143
|
}
|
|
264124
264144
|
return readFileSync11(gitignorePath, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
@@ -264257,7 +264277,7 @@ restartPolicyMaxRetries = 3${deployEnv}`;
|
|
|
264257
264277
|
}
|
|
264258
264278
|
function ensureRailwayToml(appName, framework, packageManager) {
|
|
264259
264279
|
const railwayTomlPath = join20("apps", appName, "railway.toml");
|
|
264260
|
-
if (
|
|
264280
|
+
if (existsSync16(railwayTomlPath)) {
|
|
264261
264281
|
return false;
|
|
264262
264282
|
}
|
|
264263
264283
|
writeFileSync13(railwayTomlPath, generateRailwayToml(framework, packageManager), "utf-8");
|
|
@@ -264746,10 +264766,10 @@ var import_picocolors7 = __toESM(require_picocolors(), 1);
|
|
|
264746
264766
|
init_config();
|
|
264747
264767
|
|
|
264748
264768
|
// src/manifest/drift.ts
|
|
264749
|
-
import { existsSync as
|
|
264769
|
+
import { existsSync as existsSync17, readdirSync as readdirSync4 } from "node:fs";
|
|
264750
264770
|
import { join as join21 } from "node:path";
|
|
264751
264771
|
function listDirectories(parentDir) {
|
|
264752
|
-
if (!
|
|
264772
|
+
if (!existsSync17(parentDir)) {
|
|
264753
264773
|
return [];
|
|
264754
264774
|
}
|
|
264755
264775
|
return readdirSync4(parentDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => left.localeCompare(right));
|
|
@@ -265084,7 +265104,7 @@ async function loginCommand(context, args, commandKey = "login") {
|
|
|
265084
265104
|
}
|
|
265085
265105
|
|
|
265086
265106
|
// src/commands/versions.ts
|
|
265087
|
-
import { existsSync as
|
|
265107
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12, writeFileSync as writeFileSync14 } from "node:fs";
|
|
265088
265108
|
import { join as join22 } from "node:path";
|
|
265089
265109
|
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
265090
265110
|
var TABLE_HEADER_INTEGRATION = "Integration";
|
|
@@ -265129,7 +265149,7 @@ function loadVersionsContext(logger) {
|
|
|
265129
265149
|
return null;
|
|
265130
265150
|
}
|
|
265131
265151
|
const versionsPath = join22(workspaceDir, "versions.md");
|
|
265132
|
-
if (!
|
|
265152
|
+
if (!existsSync18(versionsPath)) {
|
|
265133
265153
|
error("versions.md not found in workspace root.");
|
|
265134
265154
|
logger.cmd("/versions", "FAILED", "versions.md missing");
|
|
265135
265155
|
return null;
|
|
@@ -265562,7 +265582,7 @@ async function helpCommand(_context, _args) {
|
|
|
265562
265582
|
// package.json
|
|
265563
265583
|
var package_default = {
|
|
265564
265584
|
name: "openkitt",
|
|
265565
|
-
version: "0.2.
|
|
265585
|
+
version: "0.2.7",
|
|
265566
265586
|
description: "AI-powered monorepo scaffolding CLI",
|
|
265567
265587
|
keywords: [
|
|
265568
265588
|
"cli",
|
|
@@ -265606,7 +265626,6 @@ var package_default = {
|
|
|
265606
265626
|
"@anthropic-ai/sdk": "^0.66.0",
|
|
265607
265627
|
"@clack/prompts": "^0.11.0",
|
|
265608
265628
|
"@google/generative-ai": "^0.24.1",
|
|
265609
|
-
"@railway/mcp-server": "^0.1.8",
|
|
265610
265629
|
commander: "^14.0.1",
|
|
265611
265630
|
openai: "^6.6.0",
|
|
265612
265631
|
picocolors: "^1.1.1",
|
|
@@ -265716,7 +265735,7 @@ function isVersionNewer(latest, current) {
|
|
|
265716
265735
|
return false;
|
|
265717
265736
|
}
|
|
265718
265737
|
function hasFreshUpdateCache(now) {
|
|
265719
|
-
if (!
|
|
265738
|
+
if (!existsSync19(UPDATE_CHECK_FILE)) {
|
|
265720
265739
|
return false;
|
|
265721
265740
|
}
|
|
265722
265741
|
try {
|
|
@@ -265806,7 +265825,14 @@ async function dispatchCommand(commandLine, context) {
|
|
|
265806
265825
|
console.log(import_picocolors12.default.red(`✗ ${authCheck.message}`));
|
|
265807
265826
|
return "continue";
|
|
265808
265827
|
}
|
|
265809
|
-
|
|
265828
|
+
if (process.stdin.isTTY)
|
|
265829
|
+
process.stdin.setRawMode(false);
|
|
265830
|
+
try {
|
|
265831
|
+
await resolveAndRunHandler(route, context, parsed.args, parsed.key);
|
|
265832
|
+
} finally {
|
|
265833
|
+
if (process.stdin.isTTY)
|
|
265834
|
+
process.stdin.setRawMode(true);
|
|
265835
|
+
}
|
|
265810
265836
|
return "continue";
|
|
265811
265837
|
}
|
|
265812
265838
|
async function runSingleCommand(commandLine, context) {
|
|
@@ -265865,7 +265891,7 @@ function resolvePrompt() {
|
|
|
265865
265891
|
workspaceRoot = current;
|
|
265866
265892
|
break;
|
|
265867
265893
|
}
|
|
265868
|
-
const parent =
|
|
265894
|
+
const parent = dirname5(current);
|
|
265869
265895
|
if (parent === current)
|
|
265870
265896
|
break;
|
|
265871
265897
|
current = parent;
|