openkitt 0.2.6 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +932 -897
  2. 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 = execSync("ioreg -rd1 -c IOPlatformExpertDevice", {
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 = execSync('reg query "HKLM\\SOFTWARE\\Microsoft\\Cryptography" /v MachineGuid', {
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(error) {
2302
- if (error instanceof Error) {
2303
- const maybeStderr = error.stderr;
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 (error.message.trim().length > 0) {
2311
- return error.message.trim();
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 (error) {
2454
- return { success: false, error: getErrorMessage(error) };
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 (error) {
2480
- const errorMessage = getErrorMessage(error);
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 (error) {
2513
- const errorMessage = getErrorMessage(error);
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() || !existsSync(path)) {
2602
+ if (isWindows() || !existsSync3(path)) {
2545
2603
  return;
2546
2604
  }
2547
- const currentMode = statSync(path).mode;
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 (!existsSync(CONFIG_DIR)) {
2555
- mkdirSync(CONFIG_DIR, { recursive: true, mode: DIR_MODE });
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 (!existsSync(CONFIG_FILE)) {
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
- writeFileSync(tempFile, payload, { encoding: "utf-8", mode: FILE_MODE });
2643
+ writeFileSync2(tempFile, payload, { encoding: "utf-8", mode: FILE_MODE });
2586
2644
  if (!isWindows()) {
2587
2645
  chmodSync(tempFile, FILE_MODE);
2588
2646
  }
2589
- renameSync(tempFile, CONFIG_FILE);
2647
+ renameSync2(tempFile, CONFIG_FILE);
2590
2648
  if (!isWindows()) {
2591
2649
  chmodSync(CONFIG_FILE, FILE_MODE);
2592
2650
  }
2593
- } catch (error) {
2594
- if (existsSync(tempFile)) {
2651
+ } catch (error2) {
2652
+ if (existsSync3(tempFile)) {
2595
2653
  unlinkSync(tempFile);
2596
2654
  }
2597
- throw error;
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 = join(homedir(), ".kitt");
2722
- CONFIG_FILE = join(CONFIG_DIR, "config.json");
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 dirname5(path3) {
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 existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync13, writeFileSync as writeFileSync15, realpathSync } from "node:fs";
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 dirname6 } from "node:path";
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
- var import_picocolors = __toESM(require_picocolors(), 1);
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/utils/global-config.ts
255697
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
255698
- import { homedir as homedir2 } from "node:os";
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/manifest/writer.ts
255737
- import { chmodSync as chmodSync2, existsSync as existsSync3, mkdirSync as mkdirSync3, renameSync as renameSync2, unlinkSync as unlinkSync2, writeFileSync as writeFileSync3 } from "node:fs";
255738
- import { platform as platform3 } from "node:os";
255739
- import { dirname, join as join3 } from "node:path";
255740
- var DIR_MODE2 = 448;
255741
- var FILE_MODE2 = 384;
255742
- var MANIFEST_VERSION = "0.1.0";
255743
- function isWindows2() {
255744
- return platform3() === "win32";
255745
- }
255746
- function ensureKittDir(manifestPath) {
255747
- const kittDir = dirname(manifestPath);
255748
- if (!existsSync3(kittDir)) {
255749
- mkdirSync3(kittDir, { recursive: true, mode: DIR_MODE2 });
255750
- }
255751
- if (!isWindows2()) {
255752
- chmodSync2(kittDir, DIR_MODE2);
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 addApp(manifest, name, app) {
255792
- return {
255793
- ...manifest,
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
- writeManifest(workspaceDir, cleaned);
255944
- return cleaned;
255635
+ mkdirSync(auditDir, { recursive: true, mode: 448 });
255945
255636
  }
255946
-
255947
- // src/utils/auth-guard.ts
255948
- init_config();
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
- async function checkRailwayAuth() {
255964
- const installed = await isRailwayInstalled();
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
- try {
255972
- const output = execSync3("railway whoami", {
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
- async function railwayLogin() {
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
- async function railwayLogout() {
255654
+ function writeAuditLine(logPath, log1Path, log2Path, type, message) {
256005
255655
  try {
256006
- execSync3("railway logout", {
256007
- encoding: "utf-8",
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 false;
255659
+ return;
256013
255660
  }
256014
255661
  }
256015
-
256016
- // src/utils/auth-guard.ts
256017
- var WORKSPACE_REQUIRED = new Set([
256018
- "create",
256019
- "delete",
256020
- "list",
256021
- "run",
256022
- "deploy",
256023
- "deploy:template",
256024
- "env:create",
256025
- "env:vars",
256026
- "domain",
256027
- "logs",
256028
- "status",
256029
- "versions"
256030
- ]);
256031
- var COMMAND_AUTH = {
256032
- login: "none",
256033
- logout: "none",
256034
- help: "none",
256035
- settings: "none",
256036
- list: "none",
256037
- versions: "none",
256038
- exit: "none",
256039
- init: "both",
256040
- create: "both",
256041
- delete: "both",
256042
- deploy: "both",
256043
- "deploy:template": "both",
256044
- "env:create": "both",
256045
- "env:vars": "both",
256046
- domain: "both",
256047
- logs: "both",
256048
- status: "both"
256049
- };
256050
- async function checkAuthGuard(commandKey) {
256051
- if (WORKSPACE_REQUIRED.has(commandKey)) {
256052
- const workspaceRoot = findWorkspaceRootStrict(process.cwd());
256053
- if (!workspaceRoot) {
256054
- return {
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 import_picocolors2 = __toESM(require_picocolors(), 1);
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}${import_picocolors2.default.inverse(import_picocolors2.default.hidden("_"))}`;
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}${import_picocolors2.default.inverse(s[0])}${s.slice(1)}`;
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}${import_picocolors2.default.inverse(t)}${F.join("")}`;
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 import_picocolors3 = __toESM(require_picocolors(), 1);
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 import_picocolors3.default.cyan(le);
256199
+ return import_picocolors2.default.cyan(le);
256579
256200
  case "cancel":
256580
- return import_picocolors3.default.red(L2);
256201
+ return import_picocolors2.default.red(L2);
256581
256202
  case "error":
256582
- return import_picocolors3.default.yellow(W2);
256203
+ return import_picocolors2.default.yellow(W2);
256583
256204
  case "submit":
256584
- return import_picocolors3.default.green(C);
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 ? import_picocolors3.default.dim("...") : i(p2, v2 + l2 === n);
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 = `${import_picocolors3.default.gray(o)}
256219
+ const n = `${import_picocolors2.default.gray(o)}
256599
256220
  ${b2(this.state)} ${t.message}
256600
- `, r2 = t.placeholder ? import_picocolors3.default.inverse(t.placeholder[0]) + import_picocolors3.default.dim(t.placeholder.slice(1)) : import_picocolors3.default.inverse(import_picocolors3.default.hidden("_")), i = this.value ? this.valueWithCursor : r2;
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
- ${import_picocolors3.default.yellow(o)} ${i}
256605
- ${import_picocolors3.default.yellow(d2)} ${import_picocolors3.default.yellow(this.error)}
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}${import_picocolors3.default.gray(o)} ${import_picocolors3.default.dim(this.value || t.placeholder)}`;
256229
+ return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(this.value || t.placeholder)}`;
256609
256230
  case "cancel":
256610
- return `${n}${import_picocolors3.default.gray(o)} ${import_picocolors3.default.strikethrough(import_picocolors3.default.dim(this.value ?? ""))}${this.value?.trim() ? `
256611
- ${import_picocolors3.default.gray(o)}` : ""}`;
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}${import_picocolors3.default.cyan(o)} ${i}
256614
- ${import_picocolors3.default.cyan(d2)}
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 = `${import_picocolors3.default.gray(o)}
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
- ${import_picocolors3.default.yellow(o)} ${i}
256626
- ${import_picocolors3.default.yellow(d2)} ${import_picocolors3.default.yellow(this.error)}
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}${import_picocolors3.default.gray(o)} ${import_picocolors3.default.dim(i)}`;
256250
+ return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(i)}`;
256630
256251
  case "cancel":
256631
- return `${n}${import_picocolors3.default.gray(o)} ${import_picocolors3.default.strikethrough(import_picocolors3.default.dim(i ?? ""))}${i ? `
256632
- ${import_picocolors3.default.gray(o)}` : ""}`;
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}${import_picocolors3.default.cyan(o)} ${r2}
256635
- ${import_picocolors3.default.cyan(d2)}
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 = `${import_picocolors3.default.gray(o)}
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}${import_picocolors3.default.gray(o)} ${import_picocolors3.default.dim(s)}`;
256268
+ return `${i}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(s)}`;
256648
256269
  case "cancel":
256649
- return `${i}${import_picocolors3.default.gray(o)} ${import_picocolors3.default.strikethrough(import_picocolors3.default.dim(s))}
256650
- ${import_picocolors3.default.gray(o)}`;
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}${import_picocolors3.default.cyan(o)} ${this.value ? `${import_picocolors3.default.green(k2)} ${n}` : `${import_picocolors3.default.dim(P2)} ${import_picocolors3.default.dim(n)}`} ${import_picocolors3.default.dim("/")} ${this.value ? `${import_picocolors3.default.dim(P2)} ${import_picocolors3.default.dim(r2)}` : `${import_picocolors3.default.green(k2)} ${r2}`}
256653
- ${import_picocolors3.default.cyan(d2)}
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 `${import_picocolors3.default.dim(s)}`;
256284
+ return `${import_picocolors2.default.dim(s)}`;
256664
256285
  case "active":
256665
- return `${import_picocolors3.default.green(k2)} ${s} ${r2.hint ? import_picocolors3.default.dim(`(${r2.hint})`) : ""}`;
256286
+ return `${import_picocolors2.default.green(k2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}`;
256666
256287
  case "cancelled":
256667
- return `${import_picocolors3.default.strikethrough(import_picocolors3.default.dim(s))}`;
256288
+ return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}`;
256668
256289
  default:
256669
- return `${import_picocolors3.default.dim(P2)} ${import_picocolors3.default.dim(s)}`;
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 = `${import_picocolors3.default.gray(o)}
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}${import_picocolors3.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
256299
+ return `${r2}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
256679
256300
  case "cancel":
256680
- return `${r2}${import_picocolors3.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
256681
- ${import_picocolors3.default.gray(o)}`;
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}${import_picocolors3.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i, s) => n(i, s ? "active" : "inactive") }).join(`
256684
- ${import_picocolors3.default.cyan(o)} `)}
256685
- ${import_picocolors3.default.cyan(d2)}
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" ? `${import_picocolors3.default.cyan(A2)} ${s} ${r2.hint ? import_picocolors3.default.dim(`(${r2.hint})`) : ""}` : i === "selected" ? `${import_picocolors3.default.green(T)} ${import_picocolors3.default.dim(s)} ${r2.hint ? import_picocolors3.default.dim(`(${r2.hint})`) : ""}` : i === "cancelled" ? `${import_picocolors3.default.strikethrough(import_picocolors3.default.dim(s))}` : i === "active-selected" ? `${import_picocolors3.default.green(T)} ${s} ${r2.hint ? import_picocolors3.default.dim(`(${r2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors3.default.dim(s)}` : `${import_picocolors3.default.dim(F)} ${import_picocolors3.default.dim(s)}`;
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
- ${import_picocolors3.default.reset(import_picocolors3.default.dim(`Press ${import_picocolors3.default.gray(import_picocolors3.default.bgWhite(import_picocolors3.default.inverse(" space ")))} to select, ${import_picocolors3.default.gray(import_picocolors3.default.bgWhite(import_picocolors3.default.inverse(" enter ")))} to submit`))}`;
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 = `${import_picocolors3.default.gray(o)}
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}${import_picocolors3.default.gray(o)} ${this.options.filter(({ value: s }) => this.value.includes(s)).map((s) => n(s, "submitted")).join(import_picocolors3.default.dim(", ")) || import_picocolors3.default.dim("none")}`;
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(import_picocolors3.default.dim(", "));
256711
- return `${r2}${import_picocolors3.default.gray(o)} ${s.trim() ? `${s}
256712
- ${import_picocolors3.default.gray(o)}` : ""}`;
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 ? `${import_picocolors3.default.yellow(d2)} ${import_picocolors3.default.yellow(c)}` : ` ${c}`).join(`
256337
+ `).map((c, a) => a === 0 ? `${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(c)}` : ` ${c}`).join(`
256717
256338
  `);
256718
- return `${r2 + import_picocolors3.default.yellow(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
256719
- ${import_picocolors3.default.yellow(o)} `)}
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}${import_picocolors3.default.cyan(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
256725
- ${import_picocolors3.default.cyan(o)} `)}
256726
- ${import_picocolors3.default.cyan(d2)}
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 = `${import_picocolors3.default.gray(o)} `;
256352
+ var J2 = `${import_picocolors2.default.gray(o)} `;
256732
256353
 
256733
256354
  // src/utils/display.ts
256734
- var import_picocolors4 = __toESM(require_picocolors(), 1);
256355
+ var import_picocolors3 = __toESM(require_picocolors(), 1);
256735
256356
  function success(message) {
256736
- console.log(`${import_picocolors4.default.green("✓")} ${message}`);
256357
+ console.log(`${import_picocolors3.default.green("✓")} ${message}`);
256737
256358
  }
256738
256359
  function error(message) {
256739
- console.log(`${import_picocolors4.default.red("✗")} ${message}`);
256360
+ console.log(`${import_picocolors3.default.red("✗")} ${message}`);
256740
256361
  }
256741
256362
  function warn(message) {
256742
- console.log(`${import_picocolors4.default.yellow("⚠")} ${message}`);
256363
+ console.log(`${import_picocolors3.default.yellow("⚠")} ${message}`);
256743
256364
  }
256744
256365
  function info(message) {
256745
- console.log(`${import_picocolors4.default.blue("ℹ")} ${message}`);
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 = import_picocolors4.default.dim("─".repeat(width));
256408
+ const border = import_picocolors3.default.dim("─".repeat(width));
256788
256409
  console.log("");
256789
- console.log(` ${import_picocolors4.default.dim(border)}`);
256790
- console.log(` ${import_picocolors4.default.dim("│")} ${import_picocolors4.default.bold("Context")}${" ".repeat(width - 9)}${import_picocolors4.default.dim("│")}`);
256791
- console.log(` ${import_picocolors4.default.dim("│")} ${import_picocolors4.default.cyan(totalTokens.toLocaleString())} ${import_picocolors4.default.dim("tokens")}${" ".repeat(Math.max(0, width - 2 - totalTokens.toLocaleString().length - 7))}${import_picocolors4.default.dim("│")}`);
256792
- console.log(` ${import_picocolors4.default.dim("│")} ${import_picocolors4.default.yellow(`${pctUsed}%`)} ${import_picocolors4.default.dim("of context window used")}${" ".repeat(Math.max(0, width - 2 - String(pctUsed).length - 1 - 22))}${import_picocolors4.default.dim("│")}`);
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(` ${import_picocolors4.default.dim("│")} ${import_picocolors4.default.green(costStr)} ${import_picocolors4.default.dim("spent")}${" ".repeat(Math.max(0, width - 2 - costStr.length - 6))}${import_picocolors4.default.dim("│")}`);
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(` ${import_picocolors4.default.dim("│")} ${import_picocolors4.default.dim(`${providerLabel} · ${model}`)}${" ".repeat(Math.max(0, width - 2 - providerLabel.length - 3 - model.length))}${import_picocolors4.default.dim("│")}`);
256798
- console.log(` ${import_picocolors4.default.dim(border)}`);
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/sandbox/staging.ts
256803
- import {
256804
- copyFileSync,
256805
- existsSync as existsSync6,
256806
- mkdirSync as mkdirSync5,
256807
- readdirSync,
256808
- readFileSync as readFileSync5,
256809
- rmSync as rmSync2,
256810
- statSync as statSync3,
256811
- writeFileSync as writeFileSync5
256812
- } from "node:fs";
256813
- import { createHash } from "node:crypto";
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
- function ensureAuditDir(auditDir) {
256837
- if (existsSync5(auditDir)) {
256838
- return;
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
- mkdirSync4(auditDir, { recursive: true, mode: 448 });
256452
+ return {
256453
+ process: child,
256454
+ stdin: child.stdin,
256455
+ stdout: child.stdout,
256456
+ pid: child.pid ?? -1
256457
+ };
256841
256458
  }
256842
- function rotateLogIfNeeded(logPath, log1Path, log2Path) {
256843
- if (!existsSync5(logPath)) {
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 stats = statSync2(logPath);
256847
- if (stats.size < MAX_LOG_SIZE_BYTES) {
256539
+ const child = activeServer.process;
256540
+ intentionallyShuttingDown.add(child);
256541
+ if (!isChildRunning(child)) {
256542
+ activeServer = null;
256848
256543
  return;
256849
256544
  }
256850
- if (existsSync5(log2Path)) {
256851
- rmSync(log2Path, { force: true });
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
- if (existsSync5(log1Path)) {
256854
- renameSync3(log1Path, log2Path);
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 writeAuditLine(logPath, log1Path, log2Path, type, message) {
256587
+ function getRailwayVersion() {
256860
256588
  try {
256861
- rotateLogIfNeeded(logPath, log1Path, log2Path);
256862
- appendFileSync(logPath, formatLine(type, message), { encoding: "utf8", mode: 384 });
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 createAuditLogger(workspaceDir) {
256868
- const auditDir = join5(workspaceDir, AUDIT_DIR_NAME);
256869
- const logPath = join5(auditDir, AUDIT_FILE_NAME);
256870
- const log1Path = join5(auditDir, ROTATED_LOG_1);
256871
- const log2Path = join5(auditDir, ROTATED_LOG_2);
256872
- return {
256873
- log(type, message) {
256874
- try {
256875
- ensureAuditDir(auditDir);
256876
- } catch {
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
- fileWrite(path, hash) {
256896
- const suffix = hash ? ` (SHA-256: ${hash})` : "";
256897
- this.log("FILE_WRITE", `${path}${suffix}`);
256609
+ {
256610
+ name: "Bun",
256611
+ found: !!bunVersion,
256612
+ version: bunVersion || undefined,
256613
+ installUrl: bunVersion ? undefined : "https://bun.sh"
256898
256614
  },
256899
- staged(path, detail) {
256900
- this.log("STAGED", `${path} (${detail})`);
256615
+ {
256616
+ name: "Railway CLI",
256617
+ found: !!railwayVersion,
256618
+ version: railwayVersion || undefined,
256619
+ installUrl: railwayVersion ? undefined : "https://docs.railway.com/cli"
256901
256620
  },
256902
- userConfirmed() {
256903
- this.log("USER_CONFIRMED", "staged changes");
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
- security(action, message) {
256906
- this.log("SECURITY", `${action} ${message}`);
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
256907
256762
  }
256908
256763
  };
256909
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
+ }
256809
+ }
256810
+ };
256811
+ }
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
+ }
256910
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 join6(workspaceDir, KITT_DIR, STAGING_DIR);
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 = join6(currentDir, entry);
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 (existsSync6(stagingDir)) {
257096
+ if (existsSync7(stagingDir)) {
256946
257097
  rmSync2(stagingDir, { recursive: true, force: true });
256947
257098
  }
256948
257099
  mkdirSync5(stagingDir, { recursive: true });
256949
- logger.staged(join6(KITT_DIR, STAGING_DIR), "cleared");
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 = join6(stagingDir, relativePath);
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(join6(KITT_DIR, STAGING_DIR, relativePath), hash);
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 (!existsSync6(stagingDir)) {
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 = join6(workspaceDir, stagedRelativePath);
257122
+ const workspacePath = join7(workspaceDir, stagedRelativePath);
256972
257123
  assertWithinWorkspace(workspaceDir, workspacePath);
256973
- const content = readFileSync5(join6(stagingDir, stagedRelativePath), "utf-8");
256974
- const isNew = !existsSync6(workspacePath);
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 = join6(stagingDir, stagedFile.relativePath);
256998
- const destinationPath = join6(workspaceDir, stagedFile.relativePath);
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 auditLogger = createAuditLogger(".");
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
- auditLogger.llmCall(provider, model, PROMPT_VERSION, estimatedTokens, "FAILED");
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
- auditLogger.llmCall(provider, model, PROMPT_VERSION, estimatedTokens, "SUCCESS");
257320
+ auditLogger2.llmCall(provider, model, PROMPT_VERSION, estimatedTokens, "SUCCESS");
257170
257321
  return response;
257171
257322
  } catch (error4) {
257172
- auditLogger.llmCall(provider, model, PROMPT_VERSION, estimatedTokens, "FAILED");
257323
+ auditLogger2.llmCall(provider, model, PROMPT_VERSION, estimatedTokens, "FAILED");
257173
257324
  throw error4;
257174
257325
  } finally {
257175
257326
  rateLimiter.recordCall(estimatedTokens);
@@ -257805,7 +257956,17 @@ function formatToolError(error4) {
257805
257956
  }
257806
257957
  return String(error4);
257807
257958
  }
257808
- function toAssistantHistoryEntry(response) {
257959
+ function toAssistantHistoryEntry(response, provider) {
257960
+ if (provider === "anthropic") {
257961
+ const contentBlocks = [];
257962
+ if (response.content) {
257963
+ contentBlocks.push({ type: "text", text: response.content });
257964
+ }
257965
+ for (const call of response.toolCalls) {
257966
+ contentBlocks.push({ type: "tool_use", id: call.id, name: call.name, input: call.arguments });
257967
+ }
257968
+ return { role: "assistant", content: contentBlocks };
257969
+ }
257809
257970
  const entry = {
257810
257971
  role: "assistant",
257811
257972
  content: response.content
@@ -257888,7 +258049,7 @@ async function executeOperations(options) {
257888
258049
  if (!hasToolCalls && expectsToolCalls) {
257889
258050
  return response.content;
257890
258051
  }
257891
- conversationHistory.push(toAssistantHistoryEntry(response));
258052
+ conversationHistory.push(toAssistantHistoryEntry(response, llmClient.getProvider()));
257892
258053
  const toolResults = [];
257893
258054
  for (const toolCall of response.toolCalls) {
257894
258055
  const result = await executeToolCall({
@@ -257915,7 +258076,7 @@ var CLIENT_INFO = {
257915
258076
  name: "openkitt",
257916
258077
  version: "0.1.0"
257917
258078
  };
257918
- var auditLogger2 = createAuditLogger(".");
258079
+ var auditLogger3 = createAuditLogger(".");
257919
258080
  function createJsonRpcError(code, message) {
257920
258081
  const error4 = new Error(message);
257921
258082
  error4.code = code;
@@ -258085,7 +258246,7 @@ async function createMcpClient(server2) {
258085
258246
  if (!isToolsListResult(result)) {
258086
258247
  throw new Error("Invalid tools/list response from MCP server");
258087
258248
  }
258088
- auditLogger2.mcp("tools/list", "{}", "SUCCESS");
258249
+ auditLogger3.mcp("tools/list", "{}", "SUCCESS");
258089
258250
  return result.tools;
258090
258251
  },
258091
258252
  async callTool(name, args) {
@@ -258100,12 +258261,12 @@ async function createMcpClient(server2) {
258100
258261
  throw new Error("Invalid tools/call response from MCP server");
258101
258262
  }
258102
258263
  const status = result.isError ? "FAILED" : "SUCCESS";
258103
- auditLogger2.mcp(name, paramsText, status, result.isError ? "tool returned isError=true" : undefined);
258264
+ auditLogger3.mcp(name, paramsText, status, result.isError ? "tool returned isError=true" : undefined);
258104
258265
  return result;
258105
258266
  } catch (requestError) {
258106
258267
  const error4 = requestError instanceof Error ? requestError : new Error(String(requestError));
258107
258268
  const detail = "code" in error4 ? `${String(error4.code)}: ${error4.message}` : error4.message;
258108
- auditLogger2.mcp(name, paramsText, "FAILED", detail);
258269
+ auditLogger3.mcp(name, paramsText, "FAILED", detail);
258109
258270
  throw error4;
258110
258271
  }
258111
258272
  },
@@ -258116,137 +258277,6 @@ async function createMcpClient(server2) {
258116
258277
  };
258117
258278
  }
258118
258279
 
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
258280
  // src/scaffold/packages.ts
258251
258281
  import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync6 } from "node:fs";
258252
258282
  import { join as join8 } from "node:path";
@@ -258393,7 +258423,7 @@ function scaffoldDefaultPackages(packagesDir) {
258393
258423
  }
258394
258424
 
258395
258425
  // src/utils/validation.ts
258396
- import { existsSync as existsSync7 } from "node:fs";
258426
+ import { existsSync as existsSync8 } from "node:fs";
258397
258427
  import { join as join9 } from "node:path";
258398
258428
  var APP_NAME_REGEX = /^[a-z][a-z0-9-]{1,48}[a-z0-9]$/;
258399
258429
  function validateAppName(name) {
@@ -258420,7 +258450,7 @@ function sanitizeInput(input) {
258420
258450
  function validateAppNameUniqueness(name, workspaceDir) {
258421
258451
  const manifest = readManifest(workspaceDir);
258422
258452
  const existsInManifest = manifest !== null && name in manifest.apps;
258423
- const existsInAppsDirectory = existsSync7(join9(workspaceDir, "apps", name));
258453
+ const existsInAppsDirectory = existsSync8(join9(workspaceDir, "apps", name));
258424
258454
  if (existsInManifest || existsInAppsDirectory) {
258425
258455
  return {
258426
258456
  valid: false,
@@ -258432,7 +258462,7 @@ function validateAppNameUniqueness(name, workspaceDir) {
258432
258462
 
258433
258463
  // src/versions/integrity.ts
258434
258464
  import { createHash as createHash2 } from "node:crypto";
258435
- import { chmodSync as chmodSync3, existsSync as existsSync8, readFileSync as readFileSync6, renameSync as renameSync4, unlinkSync as unlinkSync3, writeFileSync as writeFileSync7 } from "node:fs";
258465
+ import { chmodSync as chmodSync3, existsSync as existsSync9, readFileSync as readFileSync6, renameSync as renameSync4, unlinkSync as unlinkSync3, writeFileSync as writeFileSync7 } from "node:fs";
258436
258466
  import { platform as platform4 } from "node:os";
258437
258467
  import { join as join10 } from "node:path";
258438
258468
  var FILE_MODE3 = 384;
@@ -258467,7 +258497,7 @@ function writeVersionsLock(workspaceDir, hash) {
258467
258497
  chmodSync3(lockPath, FILE_MODE3);
258468
258498
  }
258469
258499
  } catch (error4) {
258470
- if (existsSync8(tempPath)) {
258500
+ if (existsSync9(tempPath)) {
258471
258501
  unlinkSync3(tempPath);
258472
258502
  }
258473
258503
  throw error4;
@@ -258921,7 +258951,7 @@ async function initCommand(context, _args) {
258921
258951
  }
258922
258952
 
258923
258953
  // src/commands/create.ts
258924
- import { existsSync as existsSync14, mkdirSync as mkdirSync10 } from "node:fs";
258954
+ import { existsSync as existsSync15, mkdirSync as mkdirSync10 } from "node:fs";
258925
258955
  import { join as join18 } from "node:path";
258926
258956
  init_config();
258927
258957
 
@@ -262205,7 +262235,7 @@ async function executeCreateScaffolding(options) {
262205
262235
  }
262206
262236
 
262207
262237
  // src/sandbox/scanner.ts
262208
- import { existsSync as existsSync9, lstatSync, readFileSync as readFileSync8 } from "node:fs";
262238
+ import { existsSync as existsSync10, lstatSync, readFileSync as readFileSync8 } from "node:fs";
262209
262239
  import { extname, isAbsolute, join as join13, normalize, resolve as resolve3 } from "node:path";
262210
262240
  var ALLOWED_EXTENSIONS = new Set([
262211
262241
  ".ts",
@@ -262281,7 +262311,7 @@ function validateFilePath(filePath) {
262281
262311
  detail: "Path contains '..' segments and may escape the workspace"
262282
262312
  });
262283
262313
  }
262284
- if (existsSync9(filePath)) {
262314
+ if (existsSync10(filePath)) {
262285
262315
  const stats = lstatSync(filePath);
262286
262316
  if (stats.isSymbolicLink()) {
262287
262317
  warnings.push({
@@ -262390,8 +262420,8 @@ async function confirmAndApply(options) {
262390
262420
  // src/ast/engine.ts
262391
262421
  var import_ts_morph = __toESM(require_ts_morph(), 1);
262392
262422
  import { createHash as createHash3 } from "node:crypto";
262393
- import { existsSync as existsSync10, mkdirSync as mkdirSync8, writeFileSync as writeFileSync10 } from "node:fs";
262394
- import { dirname as dirname5, isAbsolute as isAbsolute2, join as join14, normalize as normalize2, relative as relative2, resolve as resolve4 } from "node:path";
262423
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8, writeFileSync as writeFileSync10 } from "node:fs";
262424
+ import { dirname as dirname4, isAbsolute as isAbsolute2, join as join14, normalize as normalize2, relative as relative2, resolve as resolve4 } from "node:path";
262395
262425
  var KITT_DIR2 = ".kitt";
262396
262426
  var STAGING_DIR2 = "staging";
262397
262427
  function hashContent2(content) {
@@ -262435,7 +262465,7 @@ function createAstEngine(workspaceDir) {
262435
262465
  if (!isRelativePathInside(workspaceDir, fullPath)) {
262436
262466
  throw new Error(`Path is outside workspace: ${relativePath}`);
262437
262467
  }
262438
- if (!existsSync10(fullPath)) {
262468
+ if (!existsSync11(fullPath)) {
262439
262469
  throw new Error(`File does not exist: ${relativePath}`);
262440
262470
  }
262441
262471
  const existing = project.getSourceFile(fullPath);
@@ -262450,7 +262480,7 @@ function createAstEngine(workspaceDir) {
262450
262480
  if (!isRelativePathInside(resolve4(workspaceDir, KITT_DIR2, STAGING_DIR2), stagingPath)) {
262451
262481
  throw new Error(`Refusing to write outside staging directory: ${relativePath}`);
262452
262482
  }
262453
- mkdirSync8(dirname5(stagingPath), { recursive: true });
262483
+ mkdirSync8(dirname4(stagingPath), { recursive: true });
262454
262484
  const fullText = sourceFile.getFullText();
262455
262485
  writeFileSync10(stagingPath, fullText, "utf-8");
262456
262486
  auditLogger4.staged(relativePath, "AST modified");
@@ -262823,7 +262853,7 @@ function applyOperation(sourceFile, operation) {
262823
262853
 
262824
262854
  // src/ast/validator.ts
262825
262855
  var import_ts_morph3 = __toESM(require_ts_morph(), 1);
262826
- import { existsSync as existsSync11 } from "node:fs";
262856
+ import { existsSync as existsSync12 } from "node:fs";
262827
262857
  import { extname as extname2, isAbsolute as isAbsolute3, normalize as normalize3, relative as relative3, resolve as resolve5 } from "node:path";
262828
262858
  var VALID_EXTENSIONS = new Set([".ts", ".tsx", ".js", ".jsx"]);
262829
262859
  var TARGET_FILE_OPERATION = { op: "targetFile" };
@@ -263010,7 +263040,7 @@ function validateTargetFile(workspaceDir, filePath) {
263010
263040
  message: `Path is outside workspace: ${filePath}`
263011
263041
  });
263012
263042
  }
263013
- if (!existsSync11(absoluteTargetPath)) {
263043
+ if (!existsSync12(absoluteTargetPath)) {
263014
263044
  errors.push({
263015
263045
  filePath,
263016
263046
  operation: TARGET_FILE_OPERATION,
@@ -263131,7 +263161,7 @@ function executeTransformPipeline(transforms, workspaceDir) {
263131
263161
  }
263132
263162
 
263133
263163
  // src/commands/create-pipeline.ts
263134
- import { execSync as execSync4 } from "node:child_process";
263164
+ import { execSync as execSync5 } from "node:child_process";
263135
263165
  import { join as join15 } from "node:path";
263136
263166
 
263137
263167
  // src/utils/pm.ts
@@ -263308,7 +263338,7 @@ function executeCommandPipeline(commands, options) {
263308
263338
  continue;
263309
263339
  }
263310
263340
  try {
263311
- execSync4(bare, { cwd, stdio: "inherit" });
263341
+ execSync5(bare, { cwd, stdio: "inherit" });
263312
263342
  results.push({
263313
263343
  command: cmd.command,
263314
263344
  purpose: cmd.purpose,
@@ -263391,13 +263421,13 @@ async function provisionInfrastructure(options) {
263391
263421
 
263392
263422
  // src/commands/run.ts
263393
263423
  import { spawn as spawn2 } from "node:child_process";
263394
- import { existsSync as existsSync13, readFileSync as readFileSync10 } from "node:fs";
263424
+ import { existsSync as existsSync14, readFileSync as readFileSync10 } from "node:fs";
263395
263425
  import { join as join17 } from "node:path";
263396
263426
  var import_picocolors6 = __toESM(require_picocolors(), 1);
263397
263427
 
263398
263428
  // src/commands/settings.ts
263399
- import { execSync as execSync5 } from "node:child_process";
263400
- import { chmodSync as chmodSync5, existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync9, renameSync as renameSync5, rmSync as rmSync3, unlinkSync as unlinkSync4, writeFileSync as writeFileSync11 } from "node:fs";
263429
+ import { execSync as execSync6 } from "node:child_process";
263430
+ 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
263431
  import { homedir as homedir3, platform as platform6 } from "node:os";
263402
263432
  import { join as join16 } from "node:path";
263403
263433
  var SUPPORTED_PACKAGE_MANAGERS = ["bun", "npm", "pnpm", "yarn"];
@@ -263415,7 +263445,7 @@ function isWindows4() {
263415
263445
  return platform6() === "win32";
263416
263446
  }
263417
263447
  function ensureConfigDir2() {
263418
- if (!existsSync12(CONFIG_DIR2)) {
263448
+ if (!existsSync13(CONFIG_DIR2)) {
263419
263449
  mkdirSync9(CONFIG_DIR2, { recursive: true, mode: DIR_MODE3 });
263420
263450
  }
263421
263451
  if (!isWindows4()) {
@@ -263427,7 +263457,7 @@ function isPackageManager(value) {
263427
263457
  }
263428
263458
  function readGlobalConfig2() {
263429
263459
  ensureConfigDir2();
263430
- if (!existsSync12(CONFIG_FILE2)) {
263460
+ if (!existsSync13(CONFIG_FILE2)) {
263431
263461
  return {};
263432
263462
  }
263433
263463
  const raw = readFileSync9(CONFIG_FILE2, "utf-8").trim();
@@ -263459,7 +263489,7 @@ function writeGlobalConfig2(config) {
263459
263489
  chmodSync5(CONFIG_FILE2, FILE_MODE4);
263460
263490
  }
263461
263491
  } catch (writeError) {
263462
- if (existsSync12(tempFile)) {
263492
+ if (existsSync13(tempFile)) {
263463
263493
  unlinkSync4(tempFile);
263464
263494
  }
263465
263495
  throw writeError;
@@ -263584,7 +263614,7 @@ async function maybeConfirmMigration(context, fromPm, toPm) {
263584
263614
  function migrateWorkspacePackageManager(workspaceDir, fromPm, toPm) {
263585
263615
  removePackageManagerArtifacts(workspaceDir, fromPm);
263586
263616
  writePackageManagerFiles(workspaceDir, toPm);
263587
- execSync5(getInstallCommand(toPm), { cwd: workspaceDir, stdio: "inherit" });
263617
+ execSync6(getInstallCommand(toPm), { cwd: workspaceDir, stdio: "inherit" });
263588
263618
  }
263589
263619
  async function runDisplayMode(workspaceDir) {
263590
263620
  const autoOpen = readAutoOpenBrowser();
@@ -263668,7 +263698,7 @@ async function settingsCommand(context, args) {
263668
263698
  var DEV_SCRIPT_CANDIDATES = ["dev", "start", "serve", "preview"];
263669
263699
  function resolveDevScript(appDir) {
263670
263700
  const pkgPath = join17(appDir, "package.json");
263671
- if (!existsSync13(pkgPath)) {
263701
+ if (!existsSync14(pkgPath)) {
263672
263702
  return { found: false, reason: "no-package-json", available: [] };
263673
263703
  }
263674
263704
  let pkg;
@@ -263955,7 +263985,7 @@ async function createCommand2(context, _args) {
263955
263985
  });
263956
263986
  logger.cmd("/create", "SUCCESS");
263957
263987
  success(`App ${selections.appName} created.`);
263958
- if (existsSync14(appDir)) {
263988
+ if (existsSync15(appDir)) {
263959
263989
  const runCmd = getCommand(manifest.workspace.packageManager, "run");
263960
263990
  const scriptResolution = resolveDevScript(appDir);
263961
263991
  if (scriptResolution.found) {
@@ -264054,7 +264084,7 @@ async function deleteCommand(context, args) {
264054
264084
  }
264055
264085
 
264056
264086
  // src/commands/deploy.ts
264057
- import { existsSync as existsSync15, readdirSync as readdirSync3, readFileSync as readFileSync11, writeFileSync as writeFileSync13 } from "node:fs";
264087
+ import { existsSync as existsSync16, readdirSync as readdirSync3, readFileSync as readFileSync11, writeFileSync as writeFileSync13 } from "node:fs";
264058
264088
  import { basename as basename2, join as join20 } from "node:path";
264059
264089
  init_config();
264060
264090
 
@@ -264118,7 +264148,7 @@ function matchesGitignorePattern(filePath, pattern) {
264118
264148
  }
264119
264149
  function loadGitignorePatterns(workspaceDir) {
264120
264150
  const gitignorePath = join20(workspaceDir, ".gitignore");
264121
- if (!existsSync15(gitignorePath)) {
264151
+ if (!existsSync16(gitignorePath)) {
264122
264152
  return [];
264123
264153
  }
264124
264154
  return readFileSync11(gitignorePath, "utf-8").split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
@@ -264257,7 +264287,7 @@ restartPolicyMaxRetries = 3${deployEnv}`;
264257
264287
  }
264258
264288
  function ensureRailwayToml(appName, framework, packageManager) {
264259
264289
  const railwayTomlPath = join20("apps", appName, "railway.toml");
264260
- if (existsSync15(railwayTomlPath)) {
264290
+ if (existsSync16(railwayTomlPath)) {
264261
264291
  return false;
264262
264292
  }
264263
264293
  writeFileSync13(railwayTomlPath, generateRailwayToml(framework, packageManager), "utf-8");
@@ -264746,10 +264776,10 @@ var import_picocolors7 = __toESM(require_picocolors(), 1);
264746
264776
  init_config();
264747
264777
 
264748
264778
  // src/manifest/drift.ts
264749
- import { existsSync as existsSync16, readdirSync as readdirSync4 } from "node:fs";
264779
+ import { existsSync as existsSync17, readdirSync as readdirSync4 } from "node:fs";
264750
264780
  import { join as join21 } from "node:path";
264751
264781
  function listDirectories(parentDir) {
264752
- if (!existsSync16(parentDir)) {
264782
+ if (!existsSync17(parentDir)) {
264753
264783
  return [];
264754
264784
  }
264755
264785
  return readdirSync4(parentDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort((left, right) => left.localeCompare(right));
@@ -265084,7 +265114,7 @@ async function loginCommand(context, args, commandKey = "login") {
265084
265114
  }
265085
265115
 
265086
265116
  // src/commands/versions.ts
265087
- import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync14 } from "node:fs";
265117
+ import { existsSync as existsSync18, readFileSync as readFileSync12, writeFileSync as writeFileSync14 } from "node:fs";
265088
265118
  import { join as join22 } from "node:path";
265089
265119
  var import_picocolors9 = __toESM(require_picocolors(), 1);
265090
265120
  var TABLE_HEADER_INTEGRATION = "Integration";
@@ -265129,7 +265159,7 @@ function loadVersionsContext(logger) {
265129
265159
  return null;
265130
265160
  }
265131
265161
  const versionsPath = join22(workspaceDir, "versions.md");
265132
- if (!existsSync17(versionsPath)) {
265162
+ if (!existsSync18(versionsPath)) {
265133
265163
  error("versions.md not found in workspace root.");
265134
265164
  logger.cmd("/versions", "FAILED", "versions.md missing");
265135
265165
  return null;
@@ -265562,7 +265592,7 @@ async function helpCommand(_context, _args) {
265562
265592
  // package.json
265563
265593
  var package_default = {
265564
265594
  name: "openkitt",
265565
- version: "0.2.6",
265595
+ version: "0.2.8",
265566
265596
  description: "AI-powered monorepo scaffolding CLI",
265567
265597
  keywords: [
265568
265598
  "cli",
@@ -265606,7 +265636,6 @@ var package_default = {
265606
265636
  "@anthropic-ai/sdk": "^0.66.0",
265607
265637
  "@clack/prompts": "^0.11.0",
265608
265638
  "@google/generative-ai": "^0.24.1",
265609
- "@railway/mcp-server": "^0.1.8",
265610
265639
  commander: "^14.0.1",
265611
265640
  openai: "^6.6.0",
265612
265641
  picocolors: "^1.1.1",
@@ -265716,7 +265745,7 @@ function isVersionNewer(latest, current) {
265716
265745
  return false;
265717
265746
  }
265718
265747
  function hasFreshUpdateCache(now) {
265719
- if (!existsSync18(UPDATE_CHECK_FILE)) {
265748
+ if (!existsSync19(UPDATE_CHECK_FILE)) {
265720
265749
  return false;
265721
265750
  }
265722
265751
  try {
@@ -265808,9 +265837,15 @@ async function dispatchCommand(commandLine, context) {
265808
265837
  }
265809
265838
  if (process.stdin.isTTY)
265810
265839
  process.stdin.setRawMode(false);
265840
+ const originalExit = process.exit.bind(process);
265841
+ process.exit = (code) => {
265842
+ if (code !== undefined && code !== 0)
265843
+ originalExit(code);
265844
+ };
265811
265845
  try {
265812
265846
  await resolveAndRunHandler(route, context, parsed.args, parsed.key);
265813
265847
  } finally {
265848
+ process.exit = originalExit;
265814
265849
  if (process.stdin.isTTY)
265815
265850
  process.stdin.setRawMode(true);
265816
265851
  }
@@ -265872,7 +265907,7 @@ function resolvePrompt() {
265872
265907
  workspaceRoot = current;
265873
265908
  break;
265874
265909
  }
265875
- const parent = dirname6(current);
265910
+ const parent = dirname5(current);
265876
265911
  if (parent === current)
265877
265912
  break;
265878
265913
  current = parent;