@kimbho/kimbho-cli 0.1.31 → 0.1.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1147,9 +1147,9 @@ var require_command = __commonJS({
1147
1147
  "../../node_modules/commander/lib/command.js"(exports2) {
1148
1148
  var EventEmitter = require("node:events").EventEmitter;
1149
1149
  var childProcess = require("node:child_process");
1150
- var path34 = require("node:path");
1150
+ var path35 = require("node:path");
1151
1151
  var fs = require("node:fs");
1152
- var process37 = require("node:process");
1152
+ var process38 = require("node:process");
1153
1153
  var { Argument: Argument2, humanReadableArgName } = require_argument();
1154
1154
  var { CommanderError: CommanderError2 } = require_error();
1155
1155
  var { Help: Help2, stripColor } = require_help();
@@ -1196,13 +1196,13 @@ var require_command = __commonJS({
1196
1196
  this._showSuggestionAfterError = true;
1197
1197
  this._savedState = null;
1198
1198
  this._outputConfiguration = {
1199
- writeOut: (str) => process37.stdout.write(str),
1200
- writeErr: (str) => process37.stderr.write(str),
1199
+ writeOut: (str) => process38.stdout.write(str),
1200
+ writeErr: (str) => process38.stderr.write(str),
1201
1201
  outputError: (str, write) => write(str),
1202
- getOutHelpWidth: () => process37.stdout.isTTY ? process37.stdout.columns : void 0,
1203
- getErrHelpWidth: () => process37.stderr.isTTY ? process37.stderr.columns : void 0,
1204
- getOutHasColors: () => useColor() ?? (process37.stdout.isTTY && process37.stdout.hasColors?.()),
1205
- getErrHasColors: () => useColor() ?? (process37.stderr.isTTY && process37.stderr.hasColors?.()),
1202
+ getOutHelpWidth: () => process38.stdout.isTTY ? process38.stdout.columns : void 0,
1203
+ getErrHelpWidth: () => process38.stderr.isTTY ? process38.stderr.columns : void 0,
1204
+ getOutHasColors: () => useColor() ?? (process38.stdout.isTTY && process38.stdout.hasColors?.()),
1205
+ getErrHasColors: () => useColor() ?? (process38.stderr.isTTY && process38.stderr.hasColors?.()),
1206
1206
  stripColor: (str) => stripColor(str)
1207
1207
  };
1208
1208
  this._hidden = false;
@@ -1585,7 +1585,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1585
1585
  if (this._exitCallback) {
1586
1586
  this._exitCallback(new CommanderError2(exitCode, code, message));
1587
1587
  }
1588
- process37.exit(exitCode);
1588
+ process38.exit(exitCode);
1589
1589
  }
1590
1590
  /**
1591
1591
  * Register callback `fn` for the command.
@@ -1983,16 +1983,16 @@ Expecting one of '${allowedValues.join("', '")}'`);
1983
1983
  }
1984
1984
  parseOptions = parseOptions || {};
1985
1985
  if (argv === void 0 && parseOptions.from === void 0) {
1986
- if (process37.versions?.electron) {
1986
+ if (process38.versions?.electron) {
1987
1987
  parseOptions.from = "electron";
1988
1988
  }
1989
- const execArgv = process37.execArgv ?? [];
1989
+ const execArgv = process38.execArgv ?? [];
1990
1990
  if (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) {
1991
1991
  parseOptions.from = "eval";
1992
1992
  }
1993
1993
  }
1994
1994
  if (argv === void 0) {
1995
- argv = process37.argv;
1995
+ argv = process38.argv;
1996
1996
  }
1997
1997
  this.rawArgs = argv.slice();
1998
1998
  let userArgs;
@@ -2003,7 +2003,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2003
2003
  userArgs = argv.slice(2);
2004
2004
  break;
2005
2005
  case "electron":
2006
- if (process37.defaultApp) {
2006
+ if (process38.defaultApp) {
2007
2007
  this._scriptPath = argv[1];
2008
2008
  userArgs = argv.slice(2);
2009
2009
  } else {
@@ -2147,9 +2147,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
2147
2147
  let launchWithNode = false;
2148
2148
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
2149
2149
  function findFile(baseDir, baseName) {
2150
- const localBin = path34.resolve(baseDir, baseName);
2150
+ const localBin = path35.resolve(baseDir, baseName);
2151
2151
  if (fs.existsSync(localBin)) return localBin;
2152
- if (sourceExt.includes(path34.extname(baseName))) return void 0;
2152
+ if (sourceExt.includes(path35.extname(baseName))) return void 0;
2153
2153
  const foundExt = sourceExt.find(
2154
2154
  (ext) => fs.existsSync(`${localBin}${ext}`)
2155
2155
  );
@@ -2167,17 +2167,17 @@ Expecting one of '${allowedValues.join("', '")}'`);
2167
2167
  } catch {
2168
2168
  resolvedScriptPath = this._scriptPath;
2169
2169
  }
2170
- executableDir = path34.resolve(
2171
- path34.dirname(resolvedScriptPath),
2170
+ executableDir = path35.resolve(
2171
+ path35.dirname(resolvedScriptPath),
2172
2172
  executableDir
2173
2173
  );
2174
2174
  }
2175
2175
  if (executableDir) {
2176
2176
  let localFile = findFile(executableDir, executableFile);
2177
2177
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
2178
- const legacyName = path34.basename(
2178
+ const legacyName = path35.basename(
2179
2179
  this._scriptPath,
2180
- path34.extname(this._scriptPath)
2180
+ path35.extname(this._scriptPath)
2181
2181
  );
2182
2182
  if (legacyName !== this._name) {
2183
2183
  localFile = findFile(
@@ -2188,13 +2188,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
2188
2188
  }
2189
2189
  executableFile = localFile || executableFile;
2190
2190
  }
2191
- launchWithNode = sourceExt.includes(path34.extname(executableFile));
2191
+ launchWithNode = sourceExt.includes(path35.extname(executableFile));
2192
2192
  let proc;
2193
- if (process37.platform !== "win32") {
2193
+ if (process38.platform !== "win32") {
2194
2194
  if (launchWithNode) {
2195
2195
  args.unshift(executableFile);
2196
- args = incrementNodeInspectorPort(process37.execArgv).concat(args);
2197
- proc = childProcess.spawn(process37.argv[0], args, { stdio: "inherit" });
2196
+ args = incrementNodeInspectorPort(process38.execArgv).concat(args);
2197
+ proc = childProcess.spawn(process38.argv[0], args, { stdio: "inherit" });
2198
2198
  } else {
2199
2199
  proc = childProcess.spawn(executableFile, args, { stdio: "inherit" });
2200
2200
  }
@@ -2205,13 +2205,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
2205
2205
  subcommand._name
2206
2206
  );
2207
2207
  args.unshift(executableFile);
2208
- args = incrementNodeInspectorPort(process37.execArgv).concat(args);
2209
- proc = childProcess.spawn(process37.execPath, args, { stdio: "inherit" });
2208
+ args = incrementNodeInspectorPort(process38.execArgv).concat(args);
2209
+ proc = childProcess.spawn(process38.execPath, args, { stdio: "inherit" });
2210
2210
  }
2211
2211
  if (!proc.killed) {
2212
2212
  const signals = ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"];
2213
2213
  signals.forEach((signal) => {
2214
- process37.on(signal, () => {
2214
+ process38.on(signal, () => {
2215
2215
  if (proc.killed === false && proc.exitCode === null) {
2216
2216
  proc.kill(signal);
2217
2217
  }
@@ -2222,7 +2222,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2222
2222
  proc.on("close", (code) => {
2223
2223
  code = code ?? 1;
2224
2224
  if (!exitCallback) {
2225
- process37.exit(code);
2225
+ process38.exit(code);
2226
2226
  } else {
2227
2227
  exitCallback(
2228
2228
  new CommanderError2(
@@ -2244,7 +2244,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
2244
2244
  throw new Error(`'${executableFile}' not executable`);
2245
2245
  }
2246
2246
  if (!exitCallback) {
2247
- process37.exit(1);
2247
+ process38.exit(1);
2248
2248
  } else {
2249
2249
  const wrappedError = new CommanderError2(
2250
2250
  1,
@@ -2739,13 +2739,13 @@ Expecting one of '${allowedValues.join("', '")}'`);
2739
2739
  */
2740
2740
  _parseOptionsEnv() {
2741
2741
  this.options.forEach((option) => {
2742
- if (option.envVar && option.envVar in process37.env) {
2742
+ if (option.envVar && option.envVar in process38.env) {
2743
2743
  const optionKey = option.attributeName();
2744
2744
  if (this.getOptionValue(optionKey) === void 0 || ["default", "config", "env"].includes(
2745
2745
  this.getOptionValueSource(optionKey)
2746
2746
  )) {
2747
2747
  if (option.required || option.optional) {
2748
- this.emit(`optionEnv:${option.name()}`, process37.env[option.envVar]);
2748
+ this.emit(`optionEnv:${option.name()}`, process38.env[option.envVar]);
2749
2749
  } else {
2750
2750
  this.emit(`optionEnv:${option.name()}`);
2751
2751
  }
@@ -3035,7 +3035,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3035
3035
  * @return {Command}
3036
3036
  */
3037
3037
  nameFromFilename(filename) {
3038
- this._name = path34.basename(filename, path34.extname(filename));
3038
+ this._name = path35.basename(filename, path35.extname(filename));
3039
3039
  return this;
3040
3040
  }
3041
3041
  /**
@@ -3049,9 +3049,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3049
3049
  * @param {string} [path]
3050
3050
  * @return {(string|null|Command)}
3051
3051
  */
3052
- executableDir(path35) {
3053
- if (path35 === void 0) return this._executableDir;
3054
- this._executableDir = path35;
3052
+ executableDir(path36) {
3053
+ if (path36 === void 0) return this._executableDir;
3054
+ this._executableDir = path36;
3055
3055
  return this;
3056
3056
  }
3057
3057
  /**
@@ -3200,7 +3200,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
3200
3200
  */
3201
3201
  help(contextOptions) {
3202
3202
  this.outputHelp(contextOptions);
3203
- let exitCode = Number(process37.exitCode ?? 0);
3203
+ let exitCode = Number(process38.exitCode ?? 0);
3204
3204
  if (exitCode === 0 && contextOptions && typeof contextOptions !== "function" && contextOptions.error) {
3205
3205
  exitCode = 1;
3206
3206
  }
@@ -3290,9 +3290,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
3290
3290
  });
3291
3291
  }
3292
3292
  function useColor() {
3293
- if (process37.env.NO_COLOR || process37.env.FORCE_COLOR === "0" || process37.env.FORCE_COLOR === "false")
3293
+ if (process38.env.NO_COLOR || process38.env.FORCE_COLOR === "0" || process38.env.FORCE_COLOR === "false")
3294
3294
  return false;
3295
- if (process37.env.FORCE_COLOR || process37.env.CLICOLOR_FORCE !== void 0)
3295
+ if (process38.env.FORCE_COLOR || process38.env.CLICOLOR_FORCE !== void 0)
3296
3296
  return true;
3297
3297
  return void 0;
3298
3298
  }
@@ -8511,8 +8511,8 @@ var require_utils = __commonJS({
8511
8511
  }
8512
8512
  return ind;
8513
8513
  }
8514
- function removeDotSegments(path34) {
8515
- let input = path34;
8514
+ function removeDotSegments(path35) {
8515
+ let input = path35;
8516
8516
  const output = [];
8517
8517
  let nextSlash = -1;
8518
8518
  let len = 0;
@@ -8711,8 +8711,8 @@ var require_schemes = __commonJS({
8711
8711
  wsComponent.secure = void 0;
8712
8712
  }
8713
8713
  if (wsComponent.resourceName) {
8714
- const [path34, query] = wsComponent.resourceName.split("?");
8715
- wsComponent.path = path34 && path34 !== "/" ? path34 : void 0;
8714
+ const [path35, query] = wsComponent.resourceName.split("?");
8715
+ wsComponent.path = path35 && path35 !== "/" ? path35 : void 0;
8716
8716
  wsComponent.query = query;
8717
8717
  wsComponent.resourceName = void 0;
8718
8718
  }
@@ -12093,7 +12093,7 @@ var require_windows = __commonJS({
12093
12093
  module2.exports = isexe;
12094
12094
  isexe.sync = sync;
12095
12095
  var fs = require("fs");
12096
- function checkPathExt(path34, options) {
12096
+ function checkPathExt(path35, options) {
12097
12097
  var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
12098
12098
  if (!pathext) {
12099
12099
  return true;
@@ -12104,25 +12104,25 @@ var require_windows = __commonJS({
12104
12104
  }
12105
12105
  for (var i = 0; i < pathext.length; i++) {
12106
12106
  var p = pathext[i].toLowerCase();
12107
- if (p && path34.substr(-p.length).toLowerCase() === p) {
12107
+ if (p && path35.substr(-p.length).toLowerCase() === p) {
12108
12108
  return true;
12109
12109
  }
12110
12110
  }
12111
12111
  return false;
12112
12112
  }
12113
- function checkStat(stat2, path34, options) {
12113
+ function checkStat(stat2, path35, options) {
12114
12114
  if (!stat2.isSymbolicLink() && !stat2.isFile()) {
12115
12115
  return false;
12116
12116
  }
12117
- return checkPathExt(path34, options);
12117
+ return checkPathExt(path35, options);
12118
12118
  }
12119
- function isexe(path34, options, cb) {
12120
- fs.stat(path34, function(er, stat2) {
12121
- cb(er, er ? false : checkStat(stat2, path34, options));
12119
+ function isexe(path35, options, cb) {
12120
+ fs.stat(path35, function(er, stat2) {
12121
+ cb(er, er ? false : checkStat(stat2, path35, options));
12122
12122
  });
12123
12123
  }
12124
- function sync(path34, options) {
12125
- return checkStat(fs.statSync(path34), path34, options);
12124
+ function sync(path35, options) {
12125
+ return checkStat(fs.statSync(path35), path35, options);
12126
12126
  }
12127
12127
  }
12128
12128
  });
@@ -12133,13 +12133,13 @@ var require_mode = __commonJS({
12133
12133
  module2.exports = isexe;
12134
12134
  isexe.sync = sync;
12135
12135
  var fs = require("fs");
12136
- function isexe(path34, options, cb) {
12137
- fs.stat(path34, function(er, stat2) {
12136
+ function isexe(path35, options, cb) {
12137
+ fs.stat(path35, function(er, stat2) {
12138
12138
  cb(er, er ? false : checkStat(stat2, options));
12139
12139
  });
12140
12140
  }
12141
- function sync(path34, options) {
12142
- return checkStat(fs.statSync(path34), options);
12141
+ function sync(path35, options) {
12142
+ return checkStat(fs.statSync(path35), options);
12143
12143
  }
12144
12144
  function checkStat(stat2, options) {
12145
12145
  return stat2.isFile() && checkMode(stat2, options);
@@ -12172,7 +12172,7 @@ var require_isexe = __commonJS({
12172
12172
  }
12173
12173
  module2.exports = isexe;
12174
12174
  isexe.sync = sync;
12175
- function isexe(path34, options, cb) {
12175
+ function isexe(path35, options, cb) {
12176
12176
  if (typeof options === "function") {
12177
12177
  cb = options;
12178
12178
  options = {};
@@ -12182,7 +12182,7 @@ var require_isexe = __commonJS({
12182
12182
  throw new TypeError("callback not provided");
12183
12183
  }
12184
12184
  return new Promise(function(resolve, reject) {
12185
- isexe(path34, options || {}, function(er, is) {
12185
+ isexe(path35, options || {}, function(er, is) {
12186
12186
  if (er) {
12187
12187
  reject(er);
12188
12188
  } else {
@@ -12191,7 +12191,7 @@ var require_isexe = __commonJS({
12191
12191
  });
12192
12192
  });
12193
12193
  }
12194
- core(path34, options || {}, function(er, is) {
12194
+ core(path35, options || {}, function(er, is) {
12195
12195
  if (er) {
12196
12196
  if (er.code === "EACCES" || options && options.ignoreErrors) {
12197
12197
  er = null;
@@ -12201,9 +12201,9 @@ var require_isexe = __commonJS({
12201
12201
  cb(er, is);
12202
12202
  });
12203
12203
  }
12204
- function sync(path34, options) {
12204
+ function sync(path35, options) {
12205
12205
  try {
12206
- return core.sync(path34, options || {});
12206
+ return core.sync(path35, options || {});
12207
12207
  } catch (er) {
12208
12208
  if (options && options.ignoreErrors || er.code === "EACCES") {
12209
12209
  return false;
@@ -12219,7 +12219,7 @@ var require_isexe = __commonJS({
12219
12219
  var require_which = __commonJS({
12220
12220
  "../../node_modules/which/which.js"(exports2, module2) {
12221
12221
  var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
12222
- var path34 = require("path");
12222
+ var path35 = require("path");
12223
12223
  var COLON = isWindows ? ";" : ":";
12224
12224
  var isexe = require_isexe();
12225
12225
  var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
@@ -12257,7 +12257,7 @@ var require_which = __commonJS({
12257
12257
  return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
12258
12258
  const ppRaw = pathEnv[i];
12259
12259
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
12260
- const pCmd = path34.join(pathPart, cmd);
12260
+ const pCmd = path35.join(pathPart, cmd);
12261
12261
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
12262
12262
  resolve(subStep(p, i, 0));
12263
12263
  });
@@ -12284,7 +12284,7 @@ var require_which = __commonJS({
12284
12284
  for (let i = 0; i < pathEnv.length; i++) {
12285
12285
  const ppRaw = pathEnv[i];
12286
12286
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
12287
- const pCmd = path34.join(pathPart, cmd);
12287
+ const pCmd = path35.join(pathPart, cmd);
12288
12288
  const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
12289
12289
  for (let j = 0; j < pathExt.length; j++) {
12290
12290
  const cur = p + pathExt[j];
@@ -12332,7 +12332,7 @@ var require_path_key = __commonJS({
12332
12332
  var require_resolveCommand = __commonJS({
12333
12333
  "../../node_modules/cross-spawn/lib/util/resolveCommand.js"(exports2, module2) {
12334
12334
  "use strict";
12335
- var path34 = require("path");
12335
+ var path35 = require("path");
12336
12336
  var which = require_which();
12337
12337
  var getPathKey = require_path_key();
12338
12338
  function resolveCommandAttempt(parsed, withoutPathExt) {
@@ -12350,7 +12350,7 @@ var require_resolveCommand = __commonJS({
12350
12350
  try {
12351
12351
  resolved = which.sync(parsed.command, {
12352
12352
  path: env[getPathKey({ env })],
12353
- pathExt: withoutPathExt ? path34.delimiter : void 0
12353
+ pathExt: withoutPathExt ? path35.delimiter : void 0
12354
12354
  });
12355
12355
  } catch (e) {
12356
12356
  } finally {
@@ -12359,7 +12359,7 @@ var require_resolveCommand = __commonJS({
12359
12359
  }
12360
12360
  }
12361
12361
  if (resolved) {
12362
- resolved = path34.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
12362
+ resolved = path35.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
12363
12363
  }
12364
12364
  return resolved;
12365
12365
  }
@@ -12413,8 +12413,8 @@ var require_shebang_command = __commonJS({
12413
12413
  if (!match) {
12414
12414
  return null;
12415
12415
  }
12416
- const [path34, argument] = match[0].replace(/#! ?/, "").split(" ");
12417
- const binary = path34.split("/").pop();
12416
+ const [path35, argument] = match[0].replace(/#! ?/, "").split(" ");
12417
+ const binary = path35.split("/").pop();
12418
12418
  if (binary === "env") {
12419
12419
  return argument;
12420
12420
  }
@@ -12449,7 +12449,7 @@ var require_readShebang = __commonJS({
12449
12449
  var require_parse2 = __commonJS({
12450
12450
  "../../node_modules/cross-spawn/lib/parse.js"(exports2, module2) {
12451
12451
  "use strict";
12452
- var path34 = require("path");
12452
+ var path35 = require("path");
12453
12453
  var resolveCommand = require_resolveCommand();
12454
12454
  var escape2 = require_escape();
12455
12455
  var readShebang = require_readShebang();
@@ -12474,7 +12474,7 @@ var require_parse2 = __commonJS({
12474
12474
  const needsShell = !isExecutableRegExp.test(commandFile);
12475
12475
  if (parsed.options.forceShell || needsShell) {
12476
12476
  const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
12477
- parsed.command = path34.normalize(parsed.command);
12477
+ parsed.command = path35.normalize(parsed.command);
12478
12478
  parsed.command = escape2.command(parsed.command);
12479
12479
  parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
12480
12480
  const shellCommand = [parsed.command].concat(parsed.args).join(" ");
@@ -12718,7 +12718,7 @@ function createCompletionRuntimeCommand(program2) {
12718
12718
  // package.json
12719
12719
  var package_default = {
12720
12720
  name: "@kimbho/kimbho-cli",
12721
- version: "0.1.31",
12721
+ version: "0.1.36",
12722
12722
  description: "Kimbho CLI is a terminal-native coding agent for planning, execution, and verification.",
12723
12723
  type: "module",
12724
12724
  engines: {
@@ -13771,8 +13771,8 @@ function getErrorMap() {
13771
13771
 
13772
13772
  // ../../node_modules/zod/v3/helpers/parseUtil.js
13773
13773
  var makeIssue = (params) => {
13774
- const { data, path: path34, errorMaps, issueData } = params;
13775
- const fullPath = [...path34, ...issueData.path || []];
13774
+ const { data, path: path35, errorMaps, issueData } = params;
13775
+ const fullPath = [...path35, ...issueData.path || []];
13776
13776
  const fullIssue = {
13777
13777
  ...issueData,
13778
13778
  path: fullPath
@@ -13888,11 +13888,11 @@ var errorUtil;
13888
13888
 
13889
13889
  // ../../node_modules/zod/v3/types.js
13890
13890
  var ParseInputLazyPath = class {
13891
- constructor(parent, value, path34, key) {
13891
+ constructor(parent, value, path35, key) {
13892
13892
  this._cachedPath = [];
13893
13893
  this.parent = parent;
13894
13894
  this.data = value;
13895
- this._path = path34;
13895
+ this._path = path35;
13896
13896
  this._key = key;
13897
13897
  }
13898
13898
  get path() {
@@ -26304,10 +26304,10 @@ function assignProp(target, prop, value) {
26304
26304
  configurable: true
26305
26305
  });
26306
26306
  }
26307
- function getElementAtPath(obj, path34) {
26308
- if (!path34)
26307
+ function getElementAtPath(obj, path35) {
26308
+ if (!path35)
26309
26309
  return obj;
26310
- return path34.reduce((acc, key) => acc?.[key], obj);
26310
+ return path35.reduce((acc, key) => acc?.[key], obj);
26311
26311
  }
26312
26312
  function promiseAllObject(promisesObj) {
26313
26313
  const keys = Object.keys(promisesObj);
@@ -26627,11 +26627,11 @@ function aborted(x, startIndex = 0) {
26627
26627
  }
26628
26628
  return false;
26629
26629
  }
26630
- function prefixIssues(path34, issues) {
26630
+ function prefixIssues(path35, issues) {
26631
26631
  return issues.map((iss) => {
26632
26632
  var _a;
26633
26633
  (_a = iss).path ?? (_a.path = []);
26634
- iss.path.unshift(path34);
26634
+ iss.path.unshift(path35);
26635
26635
  return iss;
26636
26636
  });
26637
26637
  }
@@ -41714,7 +41714,7 @@ function formatCliHookIssues(issues) {
41714
41714
 
41715
41715
  // src/commands/exec.ts
41716
41716
  var import_promises22 = require("node:fs/promises");
41717
- var import_node_path22 = __toESM(require("node:path"), 1);
41717
+ var import_node_path23 = __toESM(require("node:path"), 1);
41718
41718
  var import_node_process8 = __toESM(require("node:process"), 1);
41719
41719
  var import_ajv2 = __toESM(require_ajv(), 1);
41720
41720
 
@@ -42420,6 +42420,9 @@ async function resolveAgentSelection(cwd, options) {
42420
42420
  }
42421
42421
 
42422
42422
  // src/prompt-intent.ts
42423
+ var WORKSPACE_NOUN_PATTERN = /\b(project|repo|repository|codebase|workspace|app|directory|folder|dir)\b/;
42424
+ var WORKSPACE_CONTENT_PATTERN = /\b(files?|contents?|structure|layout|tree|code)\b/;
42425
+ var WORKSPACE_REFERENCE_PATTERN = /\b(current|this|the|local|working)\s+(project|repo|repository|codebase|workspace|app|directory|folder|dir)\b/;
42423
42426
  var EXECUTION_PREFIXES = [
42424
42427
  "build ",
42425
42428
  "create ",
@@ -42456,7 +42459,13 @@ var CHAT_PREFIXES = [
42456
42459
  "explain ",
42457
42460
  "summarize ",
42458
42461
  "review ",
42459
- "analyze "
42462
+ "analyze ",
42463
+ "tell me ",
42464
+ "describe ",
42465
+ "detail ",
42466
+ "details ",
42467
+ "walk me through ",
42468
+ "help me understand "
42460
42469
  ];
42461
42470
  var PLAN_PREFIXES = [
42462
42471
  "plan ",
@@ -42468,6 +42477,31 @@ var PLAN_PREFIXES = [
42468
42477
  function looksLikeExecutionRequest(input) {
42469
42478
  return /\b(build|create|make|scaffold|implement|fix|refactor|setup|set up|generate|add|change|update|edit|rewrite|restyle|redesign|improve|enhance)\b/.test(input);
42470
42479
  }
42480
+ function looksLikeInformationalRequest(input) {
42481
+ if (/\b(tell me|describe|walk me through|help me understand)\b/.test(input)) {
42482
+ return true;
42483
+ }
42484
+ if (/\b(details?|overview|summary|walkthrough|explanation|structure|layout|contents?)\b/.test(input) && (WORKSPACE_NOUN_PATTERN.test(input) || WORKSPACE_CONTENT_PATTERN.test(input))) {
42485
+ return true;
42486
+ }
42487
+ return WORKSPACE_REFERENCE_PATTERN.test(input) && /\b(details?|overview|summary|about|inside|in|contents?|structure|layout)\b/.test(input);
42488
+ }
42489
+ function looksLikeWorkspaceInfoPrompt(input) {
42490
+ const normalized = input.toLowerCase();
42491
+ if (looksLikeInformationalRequest(normalized) && (WORKSPACE_NOUN_PATTERN.test(normalized) || WORKSPACE_CONTENT_PATTERN.test(normalized))) {
42492
+ return true;
42493
+ }
42494
+ if (/\b(analy[sz]e|summari[sz]e|explain|describe|show|list|walk me through|tell me about)\b/.test(normalized) && (WORKSPACE_NOUN_PATTERN.test(normalized) || WORKSPACE_CONTENT_PATTERN.test(normalized))) {
42495
+ return true;
42496
+ }
42497
+ if (/\b(what('?s| is)?\s+in|show me|list)\b/.test(normalized) && /\b(this|the current|current)\s+(directory|folder|workspace|repo|repository|project|dir)\b/.test(normalized)) {
42498
+ return true;
42499
+ }
42500
+ if (/\bfiles?\s+in\s+(this|the current|current)\s+(directory|folder|workspace|repo|repository|project|dir)\b/.test(normalized)) {
42501
+ return true;
42502
+ }
42503
+ return false;
42504
+ }
42471
42505
  function stripConversationalLead(input) {
42472
42506
  let normalized = input.trim().toLowerCase();
42473
42507
  normalized = normalized.replace(/^(hi|hello|hey|yo|sup)\b[!,. ]*/u, "").trim();
@@ -42495,6 +42529,9 @@ function inferPromptIntent(input) {
42495
42529
  if (looksLikeExecutionRequest(taskCandidate)) {
42496
42530
  return "run";
42497
42531
  }
42532
+ if (looksLikeInformationalRequest(taskCandidate)) {
42533
+ return "chat";
42534
+ }
42498
42535
  if (normalized.endsWith("?")) {
42499
42536
  return "chat";
42500
42537
  }
@@ -42783,10 +42820,265 @@ async function resolveExecutionWorkspace(cwd, goal) {
42783
42820
  };
42784
42821
  }
42785
42822
 
42823
+ // src/workspace-analysis.ts
42824
+ var import_node_path22 = __toESM(require("node:path"), 1);
42825
+ function buildWorkspaceAnalysisPlan(request, prompt) {
42826
+ const generatedAt = (/* @__PURE__ */ new Date()).toISOString();
42827
+ return {
42828
+ goal: request.goal,
42829
+ generatedAt,
42830
+ summary: "Read-only multi-agent analysis of the current repository to answer the operator's question with concrete workspace evidence.",
42831
+ repoStrategy: {
42832
+ mode: "existing-repo",
42833
+ reasoning: "This is an analysis-only request about the current workspace, so the agent team should inspect the repo and synthesize findings without editing source files."
42834
+ },
42835
+ assumptions: [
42836
+ "The user wants a grounded explanation of the current repository, not code changes.",
42837
+ "The analysis should stay read-only and avoid modifying product files."
42838
+ ],
42839
+ openQuestions: [],
42840
+ milestones: [
42841
+ {
42842
+ id: "m1-repo-survey",
42843
+ title: "Repository Survey",
42844
+ objective: "Inspect the current workspace structure, entrypoints, tooling, and conventions.",
42845
+ tasks: [
42846
+ {
42847
+ id: "t1-repo-analysis",
42848
+ title: "Analyze the current workspace and conventions",
42849
+ description: "Map the repository shape, commands, entrypoints, and constraints before answering the user's question.",
42850
+ type: "analysis",
42851
+ status: "pending",
42852
+ agentRole: "repo-analyst",
42853
+ dependsOn: [],
42854
+ acceptanceCriteria: [
42855
+ "Repository shape and commands are captured.",
42856
+ "Likely entrypoints and major packages are identified."
42857
+ ],
42858
+ outputs: [
42859
+ "Repo analysis summary"
42860
+ ],
42861
+ filesLikelyTouched: [
42862
+ ".",
42863
+ ".kimbho/"
42864
+ ],
42865
+ riskLevel: "low",
42866
+ sandboxModeOverride: "read-only"
42867
+ },
42868
+ {
42869
+ id: "t2-architecture",
42870
+ title: "Synthesize the architecture and package boundaries",
42871
+ description: "Turn the repository findings into a clear explanation of the system structure and responsibilities.",
42872
+ type: "documentation",
42873
+ status: "pending",
42874
+ agentRole: "planner",
42875
+ dependsOn: [
42876
+ "t1-repo-analysis"
42877
+ ],
42878
+ acceptanceCriteria: [
42879
+ "Architecture summary is grounded in repo analysis findings.",
42880
+ "The main packages and responsibilities are explicit."
42881
+ ],
42882
+ outputs: [
42883
+ "Architecture brief"
42884
+ ],
42885
+ filesLikelyTouched: [
42886
+ ".kimbho/"
42887
+ ],
42888
+ riskLevel: "low",
42889
+ sandboxModeOverride: "read-only"
42890
+ }
42891
+ ]
42892
+ },
42893
+ {
42894
+ id: "m2-answer",
42895
+ title: "Answer",
42896
+ objective: "Review the gathered analysis artifacts and produce the final project explanation.",
42897
+ tasks: [
42898
+ {
42899
+ id: "t3-project-brief",
42900
+ title: "Review the analysis artifacts and prepare the project explanation",
42901
+ description: "Inspect the repo-analysis and architecture artifacts, then summarize the current project in terms that answer the user's question.",
42902
+ type: "documentation",
42903
+ status: "pending",
42904
+ agentRole: "reviewer",
42905
+ dependsOn: [
42906
+ "t1-repo-analysis",
42907
+ "t2-architecture"
42908
+ ],
42909
+ acceptanceCriteria: [
42910
+ "The answer addresses the user's question directly.",
42911
+ "The summary is grounded in repository evidence instead of generic assistant chatter."
42912
+ ],
42913
+ outputs: [
42914
+ "Project explanation summary"
42915
+ ],
42916
+ filesLikelyTouched: [
42917
+ ".kimbho/logs/",
42918
+ "kimbho_init.md"
42919
+ ],
42920
+ riskLevel: "low",
42921
+ sandboxModeOverride: "read-only",
42922
+ allowedTools: [
42923
+ "file.read",
42924
+ "file.search",
42925
+ "file.list",
42926
+ "repo.index",
42927
+ "repo.query",
42928
+ "git.diff"
42929
+ ],
42930
+ deniedTools: [
42931
+ "file.write",
42932
+ "file.patch",
42933
+ "shell.exec"
42934
+ ],
42935
+ agentPromptPreamble: [
42936
+ "This is a read-only repository explanation task.",
42937
+ "Do not modify product files, install packages, or run development servers.",
42938
+ `Answer the operator's question: ${prompt}`,
42939
+ "Use the repo-analysis and architecture artifacts plus direct file inspection if needed.",
42940
+ "Finish with a concise but concrete summary of the project, stack, entrypoints, commands, and notable risks or gaps."
42941
+ ].join("\n")
42942
+ }
42943
+ ]
42944
+ }
42945
+ ],
42946
+ verificationChecklist: [
42947
+ "Repo analysis artifacts were captured.",
42948
+ "The architecture summary is grounded in the workspace.",
42949
+ "The final explanation answers the user's question without changing source files."
42950
+ ],
42951
+ executionNotes: [
42952
+ "Read-only analysis run triggered directly from a workspace question.",
42953
+ "Prefer repo/file tools and existing memory artifacts over generic assistant responses."
42954
+ ]
42955
+ };
42956
+ }
42957
+ async function synthesizeWorkspaceAnalysisAnswer(cwd, prompt, role, snapshot) {
42958
+ const config2 = await loadConfig(cwd);
42959
+ const projectInit = await readMarkdownIfExists(import_node_path22.default.join(cwd, "kimbho_init.md"));
42960
+ const artifactPaths = Array.from(new Set(
42961
+ snapshot.events.flatMap((event) => [
42962
+ ...event.artifacts,
42963
+ ...event.toolResults.flatMap((toolResult) => toolResult.artifacts)
42964
+ ])
42965
+ ));
42966
+ const prioritizedArtifacts = artifactPaths.filter((artifactPath) => /repo-analysis|architecture-brief|project-brief|transcript/i.test(import_node_path22.default.basename(artifactPath))).slice(0, 4);
42967
+ const artifactSections = (await Promise.all(
42968
+ prioritizedArtifacts.map(async (artifactPath) => {
42969
+ const content = await readMarkdownIfExists(artifactPath);
42970
+ if (!content) {
42971
+ return null;
42972
+ }
42973
+ return `Artifact: ${artifactPath}
42974
+ ${content.slice(0, 4e3)}`;
42975
+ })
42976
+ )).filter((section) => Boolean(section));
42977
+ if (!config2) {
42978
+ return [
42979
+ "Repository analysis completed.",
42980
+ projectInit ? `Current workspace summary:
42981
+ ${projectInit.slice(0, 4e3)}` : "Project summary is available in the session artifacts, but no configured model was available to synthesize a narrative answer."
42982
+ ].join("\n\n");
42983
+ }
42984
+ const resolver = new BrainResolver(config2, createDefaultBrainProviderRegistry(cwd));
42985
+ const brain = await resolver.resolve(role);
42986
+ const result = await brain.client.generateText({
42987
+ model: brain.model,
42988
+ systemPrompt: [
42989
+ brain.settings.promptPreamble,
42990
+ "You are summarizing the current repository after a read-only multi-agent analysis session.",
42991
+ "Answer the user's question directly and concretely from the provided workspace evidence.",
42992
+ "Do not greet, do not speak generically about your own capabilities, and do not invent repository details.",
42993
+ "Prefer a crisp project overview with stack, structure, key entrypoints, commands, and notable risks or gaps."
42994
+ ].filter(Boolean).join("\n\n"),
42995
+ userPrompt: [
42996
+ `User question: ${prompt}`,
42997
+ projectInit ? `Workspace overview:
42998
+ ${projectInit.slice(0, 6e3)}` : null,
42999
+ artifactSections.length > 0 ? artifactSections.join("\n\n") : "No detailed analysis artifacts were available; answer from the workspace overview only."
43000
+ ].filter((value) => Boolean(value)).join("\n\n"),
43001
+ ...typeof brain.settings.temperature === "number" ? {
43002
+ temperature: brain.settings.temperature
43003
+ } : {},
43004
+ ...typeof brain.settings.maxTokens === "number" ? {
43005
+ maxTokens: brain.settings.maxTokens
43006
+ } : {}
43007
+ });
43008
+ return result.text;
43009
+ }
43010
+ async function executeWorkspaceAnalysis(cwd, prompt, options) {
43011
+ const prepared = await preparePlanningRequest({
43012
+ goal: `Analyze the current repository and answer the user's question: ${prompt}`,
43013
+ mode: "run",
43014
+ cwd,
43015
+ workspaceState: "existing",
43016
+ constraints: [
43017
+ "Read-only repository analysis only.",
43018
+ "Do not modify source files, install packages, or start development servers.",
43019
+ "Use multiple agents to inspect the workspace and synthesize the answer when helpful."
43020
+ ],
43021
+ ...options.agentSelection ? {
43022
+ agentSelection: options.agentSelection
43023
+ } : {}
43024
+ });
43025
+ const request = prepared.request;
43026
+ const plan = buildWorkspaceAnalysisPlan(request, prompt);
43027
+ const planPath = options.ephemeral ? null : await savePlan(plan, request.cwd);
43028
+ const orchestrator = new ExecutionOrchestrator();
43029
+ const envelope = orchestrator.buildEnvelope(request, plan, options.sessionId);
43030
+ const initialSnapshot = orchestrator.createSessionSnapshot(envelope);
43031
+ const progressEvents = [];
43032
+ const snapshot = await orchestrator.continueSession(initialSnapshot, {
43033
+ maxAutoTasks: options.maxAutoTasks,
43034
+ maxAgentSteps: options.maxAgentSteps,
43035
+ maxRepairAttempts: options.maxRepairAttempts,
43036
+ ...typeof options.maxToolCalls === "number" ? {
43037
+ maxToolCalls: options.maxToolCalls
43038
+ } : {},
43039
+ ...typeof options.maxModelCalls === "number" ? {
43040
+ maxModelCalls: options.maxModelCalls
43041
+ } : {},
43042
+ ...typeof options.maxInputTokens === "number" ? {
43043
+ maxInputTokens: options.maxInputTokens
43044
+ } : {},
43045
+ ...typeof options.maxOutputTokens === "number" ? {
43046
+ maxOutputTokens: options.maxOutputTokens
43047
+ } : {},
43048
+ onProgress: async (event) => {
43049
+ progressEvents.push(event);
43050
+ await options.onProgress?.(event);
43051
+ }
43052
+ });
43053
+ const sessionPath = options.ephemeral ? null : await saveSession(snapshot, request.cwd);
43054
+ const answer = await synthesizeWorkspaceAnalysisAnswer(
43055
+ request.cwd,
43056
+ prompt,
43057
+ options.answerRole ?? "coder",
43058
+ snapshot
43059
+ );
43060
+ return {
43061
+ answer,
43062
+ plan,
43063
+ planPath,
43064
+ preparedNotes: prepared.notes,
43065
+ progressEvents,
43066
+ request,
43067
+ sessionPath,
43068
+ snapshot
43069
+ };
43070
+ }
43071
+
42786
43072
  // src/commands/exec.ts
42787
43073
  function resolveSkillPromptSource(input) {
42788
43074
  return input.prompt || input.messages.at(-1)?.content || "";
42789
43075
  }
43076
+ function shouldRouteToWorkspaceAnalysis(input, explicitIntent) {
43077
+ if (explicitIntent) {
43078
+ return false;
43079
+ }
43080
+ return looksLikeWorkspaceInfoPrompt(resolveSkillPromptSource(input));
43081
+ }
42790
43082
  var IMAGE_EXTENSIONS = /* @__PURE__ */ new Map([
42791
43083
  [".png", "image/png"],
42792
43084
  [".jpg", "image/jpeg"],
@@ -42881,14 +43173,14 @@ async function pathExists4(filePath) {
42881
43173
  }
42882
43174
  }
42883
43175
  function inferMimeType(name, fallback = "application/octet-stream") {
42884
- const extension = import_node_path22.default.extname(name).toLowerCase();
43176
+ const extension = import_node_path23.default.extname(name).toLowerCase();
42885
43177
  return IMAGE_EXTENSIONS.get(extension) ?? TEXT_EXTENSIONS.get(extension) ?? fallback;
42886
43178
  }
42887
43179
  function isLikelyText(name, mimeType, buffer) {
42888
43180
  if (mimeType.startsWith("text/") || mimeType === "application/json" || mimeType === "application/toml" || mimeType === "application/yaml" || mimeType === "application/xml") {
42889
43181
  return true;
42890
43182
  }
42891
- if (TEXT_EXTENSIONS.has(import_node_path22.default.extname(name).toLowerCase())) {
43183
+ if (TEXT_EXTENSIONS.has(import_node_path23.default.extname(name).toLowerCase())) {
42892
43184
  return true;
42893
43185
  }
42894
43186
  return !buffer.includes(0);
@@ -42911,7 +43203,7 @@ async function fetchAttachment(value) {
42911
43203
  throw new Error(`Failed to download attachment "${value}": ${response.status} ${response.statusText}`);
42912
43204
  }
42913
43205
  const url = new URL(value);
42914
- const name2 = import_node_path22.default.basename(url.pathname) || "attachment";
43206
+ const name2 = import_node_path23.default.basename(url.pathname) || "attachment";
42915
43207
  const mimeType = response.headers.get("content-type")?.split(";")[0]?.trim() ?? inferMimeType(name2);
42916
43208
  const buffer2 = Buffer.from(await response.arrayBuffer());
42917
43209
  return {
@@ -42920,9 +43212,9 @@ async function fetchAttachment(value) {
42920
43212
  buffer: buffer2
42921
43213
  };
42922
43214
  }
42923
- const filePath = import_node_path22.default.resolve(import_node_process8.default.cwd(), value);
43215
+ const filePath = import_node_path23.default.resolve(import_node_process8.default.cwd(), value);
42924
43216
  const buffer = await (0, import_promises22.readFile)(filePath);
42925
- const name = import_node_path22.default.basename(filePath);
43217
+ const name = import_node_path23.default.basename(filePath);
42926
43218
  return {
42927
43219
  name,
42928
43220
  mimeType: inferMimeType(name),
@@ -43119,7 +43411,7 @@ async function resolveJsonSchemaInput(cwd, schemaInput) {
43119
43411
  if (!schemaInput) {
43120
43412
  return null;
43121
43413
  }
43122
- const candidatePath = import_node_path22.default.resolve(cwd, schemaInput);
43414
+ const candidatePath = import_node_path23.default.resolve(cwd, schemaInput);
43123
43415
  if (await pathExists4(candidatePath)) {
43124
43416
  const raw = await (0, import_promises22.readFile)(candidatePath, "utf8");
43125
43417
  return JSON.parse(raw);
@@ -43148,7 +43440,7 @@ async function maybeWriteOutputFile(outputFile, format, payload, textOutput) {
43148
43440
  if (!outputFile) {
43149
43441
  return;
43150
43442
  }
43151
- const filePath = import_node_path22.default.resolve(import_node_process8.default.cwd(), outputFile);
43443
+ const filePath = import_node_path23.default.resolve(import_node_process8.default.cwd(), outputFile);
43152
43444
  const serialized = format === "text" ? textOutput : `${renderJson(payload)}
43153
43445
  `;
43154
43446
  await (0, import_promises22.writeFile)(filePath, serialized, "utf8");
@@ -43376,8 +43668,104 @@ async function executeRunPrompt(cwd, input, format, options) {
43376
43668
  textOutput
43377
43669
  };
43378
43670
  }
43671
+ async function executeWorkspaceAnalysisPrompt(cwd, input, format, options) {
43672
+ const question = enrichPromptWithAttachments(resolveSkillPromptSource(input), input.attachments);
43673
+ const result = await executeWorkspaceAnalysis(cwd, question, {
43674
+ answerRole: "coder",
43675
+ ephemeral: options.ephemeral,
43676
+ maxAutoTasks: options.maxAutoTasks,
43677
+ maxAgentSteps: options.maxAgentSteps,
43678
+ maxRepairAttempts: options.maxRepairAttempts,
43679
+ ...typeof options.maxToolCalls === "number" ? {
43680
+ maxToolCalls: options.maxToolCalls
43681
+ } : {},
43682
+ ...typeof options.maxModelCalls === "number" ? {
43683
+ maxModelCalls: options.maxModelCalls
43684
+ } : {},
43685
+ ...typeof options.maxInputTokens === "number" ? {
43686
+ maxInputTokens: options.maxInputTokens
43687
+ } : {},
43688
+ ...typeof options.maxOutputTokens === "number" ? {
43689
+ maxOutputTokens: options.maxOutputTokens
43690
+ } : {},
43691
+ ...options.sessionId ? {
43692
+ sessionId: options.sessionId
43693
+ } : {},
43694
+ ...options.agentSelection ? {
43695
+ agentSelection: options.agentSelection
43696
+ } : {},
43697
+ ...format === "stream-json" ? {
43698
+ onProgress: async (event) => {
43699
+ printStreamEvent({
43700
+ type: "progress",
43701
+ event
43702
+ });
43703
+ }
43704
+ } : {}
43705
+ });
43706
+ const textOutput = [
43707
+ ...result.preparedNotes,
43708
+ ...result.preparedNotes.length > 0 ? [""] : [],
43709
+ renderPlan(result.plan),
43710
+ "",
43711
+ renderSession(result.snapshot),
43712
+ ...result.planPath ? ["", `Saved plan: ${result.planPath}`] : [],
43713
+ ...result.sessionPath ? [`Saved session: ${result.sessionPath}`] : [],
43714
+ ...result.request.cwd !== cwd ? [`Continue in: cd ${result.request.cwd}`] : [],
43715
+ "",
43716
+ "[analysis answer]",
43717
+ result.answer
43718
+ ].join("\n");
43719
+ const payload = {
43720
+ mode: "workspace-analysis",
43721
+ prompt: question,
43722
+ answer: result.answer,
43723
+ plan: result.plan,
43724
+ session: result.snapshot,
43725
+ planningNotes: result.preparedNotes,
43726
+ attachments: input.attachments.map((attachment) => ({
43727
+ kind: attachment.kind,
43728
+ name: attachment.name,
43729
+ mimeType: attachment.mimeType
43730
+ })),
43731
+ planPath: result.planPath,
43732
+ sessionPath: result.sessionPath,
43733
+ progressEvents: result.progressEvents
43734
+ };
43735
+ return {
43736
+ payload,
43737
+ lastMessage: result.answer,
43738
+ textOutput
43739
+ };
43740
+ }
43379
43741
  async function executePromptByIntent(cwd, input, options = {}) {
43380
- const intent = options.intent ?? inferPromptIntent(input.prompt || input.messages.at(-1)?.content || "");
43742
+ if (shouldRouteToWorkspaceAnalysis(input, options.intent)) {
43743
+ return executeWorkspaceAnalysisPrompt(cwd, input, options.outputFormat ?? "json", {
43744
+ ephemeral: options.ephemeral ?? false,
43745
+ maxAutoTasks: options.maxAutoTasks ?? 4,
43746
+ maxAgentSteps: options.maxAgentSteps ?? 8,
43747
+ maxRepairAttempts: options.maxRepairAttempts ?? 2,
43748
+ ...typeof options.maxToolCalls === "number" ? {
43749
+ maxToolCalls: options.maxToolCalls
43750
+ } : {},
43751
+ ...typeof options.maxModelCalls === "number" ? {
43752
+ maxModelCalls: options.maxModelCalls
43753
+ } : {},
43754
+ ...typeof options.maxInputTokens === "number" ? {
43755
+ maxInputTokens: options.maxInputTokens
43756
+ } : {},
43757
+ ...typeof options.maxOutputTokens === "number" ? {
43758
+ maxOutputTokens: options.maxOutputTokens
43759
+ } : {},
43760
+ ...options.sessionId ? {
43761
+ sessionId: options.sessionId
43762
+ } : {},
43763
+ ...options.agentSelection ? {
43764
+ agentSelection: options.agentSelection
43765
+ } : {}
43766
+ });
43767
+ }
43768
+ const intent = options.intent ?? inferPromptIntent(resolveSkillPromptSource(input));
43381
43769
  if (intent === "chat") {
43382
43770
  return executeChatPrompt(cwd, input);
43383
43771
  }
@@ -43435,12 +43823,9 @@ function createExecCommand() {
43435
43823
  file: options.file,
43436
43824
  image: options.image
43437
43825
  });
43438
- const intent = inferPromptIntent(input.prompt || input.messages.at(-1)?.content || "");
43439
43826
  const schema = await resolveJsonSchemaInput(cwd, options.jsonSchema);
43440
- const result = intent === "chat" ? await executeChatPrompt(cwd, input) : intent === "plan" ? await executePlanPrompt(cwd, input, {
43441
- ephemeral: options.ephemeral,
43442
- agentSelection
43443
- }) : await executeRunPrompt(cwd, input, format, {
43827
+ const result = await executePromptByIntent(cwd, input, {
43828
+ outputFormat: format,
43444
43829
  sessionId: options.sessionId,
43445
43830
  ephemeral: options.ephemeral,
43446
43831
  maxAutoTasks: options.maxAutoTasks,
@@ -43481,7 +43866,7 @@ function createExecCommand() {
43481
43866
 
43482
43867
  // src/review-service.ts
43483
43868
  var import_promises23 = require("node:fs/promises");
43484
- var import_node_path23 = __toESM(require("node:path"), 1);
43869
+ var import_node_path24 = __toESM(require("node:path"), 1);
43485
43870
  function summarizeChangedFiles2(diff) {
43486
43871
  const files = /* @__PURE__ */ new Set();
43487
43872
  for (const line of diff.split("\n")) {
@@ -43550,20 +43935,20 @@ async function reviewWorkspace(cwd, options = {}) {
43550
43935
  toolId: "file.read",
43551
43936
  success: true,
43552
43937
  summary: `Loaded review patch ${options.patchPath}.`,
43553
- stdout: `patch:${import_node_path23.default.resolve(cwd, options.patchPath)}`,
43938
+ stdout: `patch:${import_node_path24.default.resolve(cwd, options.patchPath)}`,
43554
43939
  stderr: "",
43555
43940
  artifacts: [
43556
- import_node_path23.default.resolve(cwd, options.patchPath)
43941
+ import_node_path24.default.resolve(cwd, options.patchPath)
43557
43942
  ]
43558
43943
  } : await runtime.run("git.status", {}, { cwd });
43559
43944
  const diff = options.patchPath ? {
43560
43945
  toolId: "file.read",
43561
43946
  success: true,
43562
43947
  summary: `Loaded review patch ${options.patchPath}.`,
43563
- stdout: await (0, import_promises23.readFile)(import_node_path23.default.resolve(cwd, options.patchPath), "utf8"),
43948
+ stdout: await (0, import_promises23.readFile)(import_node_path24.default.resolve(cwd, options.patchPath), "utf8"),
43564
43949
  stderr: "",
43565
43950
  artifacts: [
43566
- import_node_path23.default.resolve(cwd, options.patchPath)
43951
+ import_node_path24.default.resolve(cwd, options.patchPath)
43567
43952
  ]
43568
43953
  } : await runtime.run("git.diff", {}, { cwd });
43569
43954
  const repoIndex = await runtime.run("repo.index", {}, { cwd }).catch(() => null);
@@ -43630,7 +44015,7 @@ ${diff.stdout}`
43630
44015
  }
43631
44016
  }
43632
44017
  await ensureKimbhoDir(cwd);
43633
- const artifactPath = import_node_path23.default.join(resolveKimbhoDir(cwd), "logs", `review-${Date.now()}.md`);
44018
+ const artifactPath = import_node_path24.default.join(resolveKimbhoDir(cwd), "logs", `review-${Date.now()}.md`);
43634
44019
  await (0, import_promises23.writeFile)(artifactPath, [
43635
44020
  `# Review`,
43636
44021
  ``,
@@ -45224,7 +45609,7 @@ function createChromeCommand() {
45224
45609
 
45225
45610
  // src/commands/cloud.ts
45226
45611
  var import_promises24 = require("node:fs/promises");
45227
- var import_node_path24 = __toESM(require("node:path"), 1);
45612
+ var import_node_path25 = __toESM(require("node:path"), 1);
45228
45613
  var import_node_process12 = __toESM(require("node:process"), 1);
45229
45614
  var import_node_child_process8 = require("node:child_process");
45230
45615
  function parseCount2(value) {
@@ -45296,15 +45681,15 @@ async function resolveSession(sessionId, last = false) {
45296
45681
  return loadSessionById(sessionId, import_node_process12.default.cwd());
45297
45682
  }
45298
45683
  async function ensureCloudPatchDir(cwd) {
45299
- const outputDir = import_node_path24.default.join(resolveKimbhoDir(cwd), "cloud");
45684
+ const outputDir = import_node_path25.default.join(resolveKimbhoDir(cwd), "cloud");
45300
45685
  await (0, import_promises24.mkdir)(outputDir, {
45301
45686
  recursive: true
45302
45687
  });
45303
45688
  return outputDir;
45304
45689
  }
45305
45690
  async function writePatchArtifact(cwd, taskId, patchArtifact, output) {
45306
- const outputPath = output ? import_node_path24.default.resolve(cwd, output) : import_node_path24.default.join(await ensureCloudPatchDir(cwd), patchArtifact.fileName ?? `${taskId}.patch`);
45307
- await (0, import_promises24.mkdir)(import_node_path24.default.dirname(outputPath), {
45691
+ const outputPath = output ? import_node_path25.default.resolve(cwd, output) : import_node_path25.default.join(await ensureCloudPatchDir(cwd), patchArtifact.fileName ?? `${taskId}.patch`);
45692
+ await (0, import_promises24.mkdir)(import_node_path25.default.dirname(outputPath), {
45308
45693
  recursive: true
45309
45694
  });
45310
45695
  await (0, import_promises24.writeFile)(outputPath, patchArtifact.content, "utf8");
@@ -45453,7 +45838,7 @@ function createCloudCommand() {
45453
45838
  }
45454
45839
 
45455
45840
  // src/commands/compat.ts
45456
- var import_node_path25 = __toESM(require("node:path"), 1);
45841
+ var import_node_path26 = __toESM(require("node:path"), 1);
45457
45842
  var import_node_process13 = __toESM(require("node:process"), 1);
45458
45843
 
45459
45844
  // src/plugin-commands.ts
@@ -45816,7 +46201,7 @@ function createPluginCommand() {
45816
46201
  const cwd = import_node_process13.default.cwd();
45817
46202
  const { direct, resolved } = await loadScopedConfig(scope, cwd);
45818
46203
  const current = baseConfig(direct, resolved);
45819
- const normalized = import_node_path25.default.resolve(cwd, directory);
46204
+ const normalized = import_node_path26.default.resolve(cwd, directory);
45820
46205
  const outputPath = await saveScopedConfig(scope, cwd, {
45821
46206
  ...current,
45822
46207
  pluginDirectories: Array.from(/* @__PURE__ */ new Set([
@@ -45831,7 +46216,7 @@ function createPluginCommand() {
45831
46216
  const cwd = import_node_process13.default.cwd();
45832
46217
  const { direct, resolved } = await loadScopedConfig(scope, cwd);
45833
46218
  const current = baseConfig(direct, resolved);
45834
- const normalized = import_node_path25.default.resolve(cwd, directory);
46219
+ const normalized = import_node_path26.default.resolve(cwd, directory);
45835
46220
  const outputPath = await saveScopedConfig(scope, cwd, {
45836
46221
  ...current,
45837
46222
  pluginDirectories: current.pluginDirectories.filter((entry) => entry !== directory && entry !== normalized)
@@ -46008,11 +46393,11 @@ function createSandboxCommand() {
46008
46393
  var import_node_process14 = __toESM(require("node:process"), 1);
46009
46394
 
46010
46395
  // src/memory.ts
46011
- var import_node_path27 = __toESM(require("node:path"), 1);
46396
+ var import_node_path28 = __toESM(require("node:path"), 1);
46012
46397
 
46013
46398
  // src/project-init.ts
46014
46399
  var import_promises25 = require("node:fs/promises");
46015
- var import_node_path26 = __toESM(require("node:path"), 1);
46400
+ var import_node_path27 = __toESM(require("node:path"), 1);
46016
46401
  var import_node_child_process9 = require("node:child_process");
46017
46402
  var import_node_util = require("node:util");
46018
46403
  var execFileAsync = (0, import_node_util.promisify)(import_node_child_process9.execFile);
@@ -46025,16 +46410,16 @@ async function pathExists5(filePath) {
46025
46410
  }
46026
46411
  }
46027
46412
  async function detectPackageManager(cwd) {
46028
- if (await pathExists5(import_node_path26.default.join(cwd, "pnpm-lock.yaml"))) {
46413
+ if (await pathExists5(import_node_path27.default.join(cwd, "pnpm-lock.yaml"))) {
46029
46414
  return "pnpm";
46030
46415
  }
46031
- if (await pathExists5(import_node_path26.default.join(cwd, "yarn.lock"))) {
46416
+ if (await pathExists5(import_node_path27.default.join(cwd, "yarn.lock"))) {
46032
46417
  return "yarn";
46033
46418
  }
46034
- if (await pathExists5(import_node_path26.default.join(cwd, "bun.lockb")) || await pathExists5(import_node_path26.default.join(cwd, "bun.lock"))) {
46419
+ if (await pathExists5(import_node_path27.default.join(cwd, "bun.lockb")) || await pathExists5(import_node_path27.default.join(cwd, "bun.lock"))) {
46035
46420
  return "bun";
46036
46421
  }
46037
- if (await pathExists5(import_node_path26.default.join(cwd, "package-lock.json"))) {
46422
+ if (await pathExists5(import_node_path27.default.join(cwd, "package-lock.json"))) {
46038
46423
  return "npm";
46039
46424
  }
46040
46425
  return "npm";
@@ -46178,8 +46563,8 @@ async function generateProjectInitFile(cwd, outputFileName = "kimbho_init.md") {
46178
46563
  const entrypoints = inferPrimaryEntrypoints(index);
46179
46564
  const verificationCommands = inferVerificationCommands(rootPackage, packageManager);
46180
46565
  const git = await captureGitSnapshot(cwd);
46181
- const packageJson = await readJsonFile2(import_node_path26.default.join(cwd, "package.json"));
46182
- const outputPath = import_node_path26.default.join(cwd, outputFileName);
46566
+ const packageJson = await readJsonFile2(import_node_path27.default.join(cwd, "package.json"));
46567
+ const outputPath = import_node_path27.default.join(cwd, outputFileName);
46183
46568
  const summaryLines = [
46184
46569
  `- workspace: \`${cwd}\``,
46185
46570
  `- generated: ${(/* @__PURE__ */ new Date()).toISOString()}`,
@@ -46240,14 +46625,14 @@ async function generateProjectInitFile(cwd, outputFileName = "kimbho_init.md") {
46240
46625
  renderSection("Schemas", schemaLines),
46241
46626
  renderSection("Key Symbols", symbolLines),
46242
46627
  renderSection("Agent Guidance", guidanceLines),
46243
- `Repo index artifact: \`${import_node_path26.default.relative(cwd, artifactPath) || artifactPath}\``,
46628
+ `Repo index artifact: \`${import_node_path27.default.relative(cwd, artifactPath) || artifactPath}\``,
46244
46629
  ""
46245
46630
  ].join("\n");
46246
46631
  await (0, import_promises25.writeFile)(outputPath, content, "utf8");
46247
46632
  return {
46248
46633
  outputPath,
46249
46634
  indexArtifactPath: artifactPath,
46250
- summary: `Generated ${outputFileName} with indexed project context for ${import_node_path26.default.basename(cwd)}.`,
46635
+ summary: `Generated ${outputFileName} with indexed project context for ${import_node_path27.default.basename(cwd)}.`,
46251
46636
  purpose,
46252
46637
  frameworks,
46253
46638
  entrypoints,
@@ -46268,7 +46653,7 @@ function renderProjectMemory(initFilePath) {
46268
46653
  "",
46269
46654
  "## Canonical References",
46270
46655
  "",
46271
- `- bootstrap: \`${import_node_path27.default.basename(initFilePath)}\``,
46656
+ `- bootstrap: \`${import_node_path28.default.basename(initFilePath)}\``,
46272
46657
  "- read the bootstrap file before large changes",
46273
46658
  "- record important repo-specific rules here so future runs do not need to rediscover them",
46274
46659
  "",
@@ -46312,7 +46697,7 @@ async function refreshMemoryFiles(cwd) {
46312
46697
  initFilePath: init.outputPath,
46313
46698
  projectMemoryPath,
46314
46699
  userMemoryPath,
46315
- summary: `Refreshed project bootstrap and memory files for ${import_node_path27.default.basename(cwd)}.`,
46700
+ summary: `Refreshed project bootstrap and memory files for ${import_node_path28.default.basename(cwd)}.`,
46316
46701
  purpose: init.purpose,
46317
46702
  frameworks: init.frameworks,
46318
46703
  entrypoints: init.entrypoints,
@@ -46333,7 +46718,7 @@ async function appendMemoryNote(cwd, scope, text, agentId) {
46333
46718
  throw new Error("Agent memory updates require an agent id.");
46334
46719
  }
46335
46720
  return appendMarkdownSection(
46336
- import_node_path27.default.join(resolveAgentMemoryDir(cwd), `${agentId}.md`),
46721
+ import_node_path28.default.join(resolveAgentMemoryDir(cwd), `${agentId}.md`),
46337
46722
  "Note",
46338
46723
  text
46339
46724
  );
@@ -46343,7 +46728,7 @@ async function appendMemoryNote(cwd, scope, text, agentId) {
46343
46728
  async function listMemoryPaths(cwd) {
46344
46729
  await ensureMemoryDirs(cwd);
46345
46730
  return {
46346
- initFilePath: import_node_path27.default.join(cwd, "kimbho_init.md"),
46731
+ initFilePath: import_node_path28.default.join(cwd, "kimbho_init.md"),
46347
46732
  projectMemoryPath: resolveProjectMemoryPath(cwd),
46348
46733
  userMemoryPath: resolveUserMemoryPath(),
46349
46734
  adaptiveProjectMemoryPath: resolveAdaptiveProjectMemoryPath(cwd),
@@ -46705,7 +47090,7 @@ function createDoctorCommand() {
46705
47090
  });
46706
47091
  }
46707
47092
 
46708
- // src/commands/fork.ts
47093
+ // src/commands/fix.ts
46709
47094
  var import_node_process17 = __toESM(require("node:process"), 1);
46710
47095
  function parseCount3(value) {
46711
47096
  const parsed = Number(value);
@@ -46714,6 +47099,111 @@ function parseCount3(value) {
46714
47099
  }
46715
47100
  return parsed;
46716
47101
  }
47102
+ function buildFixPrompt(issue2, review) {
47103
+ const lines = [
47104
+ issue2?.trim() ? `Fix request: ${issue2.trim()}` : "Fix the current repository issue.",
47105
+ "Diagnose the failing behavior first, identify the root cause, implement the minimum safe fix, and verify the result before finishing."
47106
+ ];
47107
+ if (!review) {
47108
+ return lines.join("\n\n");
47109
+ }
47110
+ lines.push(
47111
+ "Use the current repository state and review context below as additional evidence.",
47112
+ [
47113
+ "Review context:",
47114
+ `- source: ${review.source}`,
47115
+ `- risk: ${review.riskLevel}`,
47116
+ `- changed files: ${review.changedFiles.length > 0 ? review.changedFiles.join(", ") : "none recorded"}`,
47117
+ `- summary: ${review.summary}`,
47118
+ ...review.findings.length > 0 ? review.findings.slice(0, 5).map((finding) => `- finding: [${finding.severity}] ${finding.title}${finding.file ? ` (${finding.file})` : ""} :: ${finding.detail}`) : [
47119
+ "- findings: none recorded"
47120
+ ],
47121
+ ...review.missingVerification.length > 0 ? review.missingVerification.map((item) => `- missing verification: ${item}`) : [
47122
+ "- missing verification: none recorded"
47123
+ ],
47124
+ `- review artifact: ${review.artifactPath}`
47125
+ ].join("\n")
47126
+ );
47127
+ return lines.join("\n\n");
47128
+ }
47129
+ function renderFixTextOutput(input, result, review) {
47130
+ const lines = [
47131
+ `Goal: ${input.prompt}`
47132
+ ];
47133
+ if (review) {
47134
+ lines.push(`Diagnostic review: ${review.artifactPath}`);
47135
+ lines.push(`Risk: ${review.riskLevel}`);
47136
+ lines.push("");
47137
+ }
47138
+ lines.push(result.textOutput);
47139
+ return lines.join("\n");
47140
+ }
47141
+ function createFixCommand() {
47142
+ return new Command("fix").description("Diagnose the current repository issue, implement the minimum safe fix, and verify the result.").argument("[issue]", "Optional issue description or failure symptom").option("--json", "Print the fix payload as JSON", false).option("--patch <path>", "Use a patch file as additional diagnostic context").option("--agent <id>", "Prefer one custom or plugin agent id for this invocation").option("--agents <jsonOrPath>", "Inline agent definitions as JSON or a path to a JSON file").option("--session-id <id>", "Use an explicit session id for the repair run").option("--ephemeral", "Do not persist plans or sessions for this invocation", false).option("--max-auto-tasks <count>", "Maximum ready tasks to auto-execute", parseCount3, 4).option("--max-agent-steps <count>", "Maximum tool/model steps per autonomous task", parseCount3, 8).option("--max-repair-attempts <count>", "Maximum failed verification cycles per autonomous task", parseCount3, 2).option("--max-tool-calls <count>", "Maximum tool calls per autonomous task", parseCount3).option("--max-model-calls <count>", "Maximum model calls per autonomous task", parseCount3).option("--max-input-tokens <count>", "Maximum input tokens per autonomous task", parseCount3).option("--max-output-tokens <count>", "Maximum output tokens per autonomous task", parseCount3).action(async (issue2, options) => {
47143
+ const cwd = import_node_process17.default.cwd();
47144
+ const agentSelection = await resolveAgentSelection(cwd, {
47145
+ agent: options.agent,
47146
+ agents: options.agents
47147
+ });
47148
+ const review = await reviewWorkspace(cwd, {
47149
+ patchPath: options.patch
47150
+ }).catch(() => null);
47151
+ const input = {
47152
+ prompt: buildFixPrompt(issue2, review),
47153
+ messages: [],
47154
+ attachments: []
47155
+ };
47156
+ const result = await executePromptByIntent(cwd, input, {
47157
+ intent: "run",
47158
+ outputFormat: options.json ? "json" : "text",
47159
+ sessionId: options.sessionId,
47160
+ ephemeral: options.ephemeral,
47161
+ maxAutoTasks: options.maxAutoTasks,
47162
+ maxAgentSteps: options.maxAgentSteps,
47163
+ maxRepairAttempts: options.maxRepairAttempts,
47164
+ ...typeof options.maxToolCalls === "number" ? {
47165
+ maxToolCalls: options.maxToolCalls
47166
+ } : {},
47167
+ ...typeof options.maxModelCalls === "number" ? {
47168
+ maxModelCalls: options.maxModelCalls
47169
+ } : {},
47170
+ ...typeof options.maxInputTokens === "number" ? {
47171
+ maxInputTokens: options.maxInputTokens
47172
+ } : {},
47173
+ ...typeof options.maxOutputTokens === "number" ? {
47174
+ maxOutputTokens: options.maxOutputTokens
47175
+ } : {},
47176
+ ...agentSelection ? {
47177
+ agentSelection
47178
+ } : {}
47179
+ });
47180
+ if (options.json) {
47181
+ console.log(renderJson({
47182
+ mode: "fix",
47183
+ goal: input.prompt,
47184
+ review: review ? {
47185
+ source: review.source,
47186
+ riskLevel: review.riskLevel,
47187
+ changedFiles: review.changedFiles,
47188
+ artifactPath: review.artifactPath
47189
+ } : null,
47190
+ result: result.payload
47191
+ }));
47192
+ return;
47193
+ }
47194
+ console.log(renderFixTextOutput(input, result, review));
47195
+ });
47196
+ }
47197
+
47198
+ // src/commands/fork.ts
47199
+ var import_node_process18 = __toESM(require("node:process"), 1);
47200
+ function parseCount4(value) {
47201
+ const parsed = Number(value);
47202
+ if (!Number.isInteger(parsed) || parsed <= 0) {
47203
+ throw new Error(`Expected a positive integer, received "${value}".`);
47204
+ }
47205
+ return parsed;
47206
+ }
46717
47207
  function printSessionList(rows) {
46718
47208
  if (rows.length === 0) {
46719
47209
  console.log("No saved sessions found.");
@@ -46738,8 +47228,8 @@ async function resolveSourceSession(cwd, sessionId, last = false, search) {
46738
47228
  return loadSessionById(sessionId, cwd);
46739
47229
  }
46740
47230
  function createForkCommand() {
46741
- return new Command("fork").description("Fork a saved session into a new session snapshot.").argument("[sessionId]", "Optional session id; defaults to the latest session").option("--last", "Fork the most recent session", false).option("--list", "List recent sessions and exit", false).option("--search <query>", "Filter sessions by id, goal, cwd, or labels").option("--json", "Print the forked snapshot as JSON", false).option("--execute", "Continue auto-executing the forked session", false).option("--max-auto-tasks <count>", "Maximum ready tasks to auto-execute", parseCount3, 4).option("--max-agent-steps <count>", "Maximum tool/model steps per autonomous task", parseCount3, 8).option("--max-repair-attempts <count>", "Maximum failed verification cycles per autonomous task", parseCount3, 2).option("--max-tool-calls <count>", "Maximum tool calls per autonomous task", parseCount3).option("--max-model-calls <count>", "Maximum model calls per autonomous task", parseCount3).option("--max-input-tokens <count>", "Maximum input tokens per autonomous task", parseCount3).option("--max-output-tokens <count>", "Maximum output tokens per autonomous task", parseCount3).action(async (sessionId, options) => {
46742
- const cwd = import_node_process17.default.cwd();
47231
+ return new Command("fork").description("Fork a saved session into a new session snapshot.").argument("[sessionId]", "Optional session id; defaults to the latest session").option("--last", "Fork the most recent session", false).option("--list", "List recent sessions and exit", false).option("--search <query>", "Filter sessions by id, goal, cwd, or labels").option("--json", "Print the forked snapshot as JSON", false).option("--execute", "Continue auto-executing the forked session", false).option("--max-auto-tasks <count>", "Maximum ready tasks to auto-execute", parseCount4, 4).option("--max-agent-steps <count>", "Maximum tool/model steps per autonomous task", parseCount4, 8).option("--max-repair-attempts <count>", "Maximum failed verification cycles per autonomous task", parseCount4, 2).option("--max-tool-calls <count>", "Maximum tool calls per autonomous task", parseCount4).option("--max-model-calls <count>", "Maximum model calls per autonomous task", parseCount4).option("--max-input-tokens <count>", "Maximum input tokens per autonomous task", parseCount4).option("--max-output-tokens <count>", "Maximum output tokens per autonomous task", parseCount4).action(async (sessionId, options) => {
47232
+ const cwd = import_node_process18.default.cwd();
46743
47233
  if (options.list) {
46744
47234
  const sessions = options.search ? await searchSessions(options.search, cwd) : await listSessions(cwd);
46745
47235
  if (options.json) {
@@ -46752,7 +47242,7 @@ function createForkCommand() {
46752
47242
  const source = await resolveSourceSession(cwd, sessionId, options.last, options.search);
46753
47243
  if (!source) {
46754
47244
  console.error("No saved session found.");
46755
- import_node_process17.default.exitCode = 1;
47245
+ import_node_process18.default.exitCode = 1;
46756
47246
  return;
46757
47247
  }
46758
47248
  const forked = forkSessionSnapshot(source);
@@ -46790,7 +47280,7 @@ function createForkCommand() {
46790
47280
  }
46791
47281
 
46792
47282
  // src/commands/init.ts
46793
- var import_node_process18 = __toESM(require("node:process"), 1);
47283
+ var import_node_process19 = __toESM(require("node:process"), 1);
46794
47284
  function printProjectUnderstanding(result) {
46795
47285
  console.log(result.summary);
46796
47286
  console.log("Now I have a durable understanding of the current project structure.");
@@ -46809,7 +47299,7 @@ function printProjectUnderstanding(result) {
46809
47299
  }
46810
47300
  function createInitCommand() {
46811
47301
  return new Command("init").description("Create or refresh local Kimbho config and project bootstrap memory.").option("--template <template>", "Provider template to use for the initial provider").option("--provider-id <id>", "Identifier for the initial provider").option("--driver <driver>", "Provider driver to use when no template is supplied").option("--label <label>", "Human-readable provider label").option("--model <model>", "Default model to use for planner/coder/reviewer brains").option("--fast-model <model>", "Model to use for the fast utility brain").option("--api-key-env <env>", "Environment variable that stores the provider API key").option("--base-url <url>", "Base URL or endpoint for the provider driver").option("--module-path <path>", "Module path for a custom provider driver").option("--config-only", "Only write .kimbho/config.toml and skip project memory generation", false).option("--memory-only", "Only generate kimbho_init.md and keep the existing config untouched", false).option("--memory-file <file>", "Project memory file to write", "kimbho_init.md").option("--force", "Overwrite an existing config file", false).action(async (options) => {
46812
- const existing = await loadConfig(import_node_process18.default.cwd());
47302
+ const existing = await loadConfig(import_node_process19.default.cwd());
46813
47303
  const configMutationRequested = [
46814
47304
  options.template,
46815
47305
  options.providerId,
@@ -46823,12 +47313,12 @@ function createInitCommand() {
46823
47313
  ].some((value) => typeof value === "string" && value.trim().length > 0);
46824
47314
  if (options.configOnly && options.memoryOnly) {
46825
47315
  console.error("Choose either --config-only or --memory-only, not both.");
46826
- import_node_process18.default.exitCode = 1;
47316
+ import_node_process19.default.exitCode = 1;
46827
47317
  return;
46828
47318
  }
46829
47319
  if (existing && !options.force && configMutationRequested && !options.memoryOnly) {
46830
47320
  console.error("Config already exists. Re-run with --force to overwrite it.");
46831
- import_node_process18.default.exitCode = 1;
47321
+ import_node_process19.default.exitCode = 1;
46832
47322
  return;
46833
47323
  }
46834
47324
  if (!options.memoryOnly) {
@@ -46866,20 +47356,20 @@ function createInitCommand() {
46866
47356
  defaultModel: options.model ?? provider.defaultModel,
46867
47357
  fastModel: options.fastModel ?? options.model ?? provider.defaultModel
46868
47358
  });
46869
- const outputPath = await saveConfig(nextConfig, import_node_process18.default.cwd());
47359
+ const outputPath = await saveConfig(nextConfig, import_node_process19.default.cwd());
46870
47360
  console.log(`Created ${outputPath}`);
46871
47361
  }
46872
47362
  }
46873
47363
  if (!options.configOnly) {
46874
- const result = await refreshMemoryFiles(import_node_process18.default.cwd());
47364
+ const result = await refreshMemoryFiles(import_node_process19.default.cwd());
46875
47365
  printProjectUnderstanding(result);
46876
47366
  }
46877
47367
  });
46878
47368
  }
46879
47369
 
46880
47370
  // src/commands/ide.ts
46881
- var import_node_path28 = __toESM(require("node:path"), 1);
46882
- var import_node_process19 = __toESM(require("node:process"), 1);
47371
+ var import_node_path29 = __toESM(require("node:path"), 1);
47372
+ var import_node_process20 = __toESM(require("node:process"), 1);
46883
47373
  function renderIdeState(state) {
46884
47374
  if (!state) {
46885
47375
  return "No IDE companion is linked.";
@@ -46897,27 +47387,27 @@ function renderIdeState(state) {
46897
47387
  function createIdeCommand() {
46898
47388
  const command = new Command("ide").description("Discover, link, and open the active workspace in a local IDE companion.");
46899
47389
  command.command("status").description("Show the linked or detected IDE companion.").option("--json", "Print the IDE companion payload as JSON", false).action(async (options) => {
46900
- const state = await detectIdeBridge(import_node_process19.default.cwd());
47390
+ const state = await detectIdeBridge(import_node_process20.default.cwd());
46901
47391
  if (options.json) {
46902
47392
  console.log(JSON.stringify(state, null, 2));
46903
47393
  return;
46904
47394
  }
46905
47395
  console.log(renderIdeState(state));
46906
47396
  });
46907
- command.command("link").description("Persist a local IDE companion link for this workspace.").option("--editor <id>", "Editor id", "manual").option("--label <label>", "Human-readable label").option("--command <binary>", "Launcher command").option("--workspace <path>", "Workspace path", import_node_process19.default.cwd()).option("--json", "Print the IDE companion payload as JSON", false).action(async (options) => {
46908
- const detected = !options.command ? await detectIdeBridge(import_node_process19.default.cwd()) : null;
47397
+ command.command("link").description("Persist a local IDE companion link for this workspace.").option("--editor <id>", "Editor id", "manual").option("--label <label>", "Human-readable label").option("--command <binary>", "Launcher command").option("--workspace <path>", "Workspace path", import_node_process20.default.cwd()).option("--json", "Print the IDE companion payload as JSON", false).action(async (options) => {
47398
+ const detected = !options.command ? await detectIdeBridge(import_node_process20.default.cwd()) : null;
46909
47399
  const state = {
46910
47400
  editorId: options.command ? options.editor : detected?.editorId ?? options.editor,
46911
47401
  label: options.label ?? detected?.label ?? options.editor,
46912
47402
  command: options.command ?? detected?.command ?? options.editor,
46913
- workspace: import_node_path28.default.resolve(import_node_process19.default.cwd(), options.workspace),
47403
+ workspace: import_node_path29.default.resolve(import_node_process20.default.cwd(), options.workspace),
46914
47404
  source: options.command ? "manual" : detected?.source ?? "detected",
46915
47405
  linkedAt: (/* @__PURE__ */ new Date()).toISOString(),
46916
47406
  ...detected?.lastOpenedPath ? {
46917
47407
  lastOpenedPath: detected.lastOpenedPath
46918
47408
  } : {}
46919
47409
  };
46920
- const outputPath = await saveIdeBridgeState(import_node_process19.default.cwd(), state);
47410
+ const outputPath = await saveIdeBridgeState(import_node_process20.default.cwd(), state);
46921
47411
  if (options.json) {
46922
47412
  console.log(JSON.stringify({
46923
47413
  state,
@@ -46929,13 +47419,13 @@ function createIdeCommand() {
46929
47419
  console.log(`Saved: ${outputPath}`);
46930
47420
  });
46931
47421
  command.command("open").description("Open one file or the current workspace in the linked IDE.").argument("[target]", "Optional file path; defaults to the current workspace", ".").option("--line <line>", "Open at a specific line", (value) => Number.parseInt(value, 10)).option("--column <column>", "Open at a specific column", (value) => Number.parseInt(value, 10)).option("--json", "Print the IDE companion payload as JSON", false).action(async (target, options) => {
46932
- const state = await openInIde(import_node_process19.default.cwd(), target, {
47422
+ const state = await openInIde(import_node_process20.default.cwd(), target, {
46933
47423
  line: Number.isInteger(options.line) && options.line > 0 ? options.line : void 0,
46934
47424
  column: Number.isInteger(options.column) && options.column > 0 ? options.column : void 0
46935
47425
  });
46936
47426
  const payload = {
46937
47427
  state,
46938
- target: import_node_path28.default.resolve(import_node_process19.default.cwd(), target)
47428
+ target: import_node_path29.default.resolve(import_node_process20.default.cwd(), target)
46939
47429
  };
46940
47430
  if (options.json) {
46941
47431
  console.log(JSON.stringify(payload, null, 2));
@@ -46947,7 +47437,7 @@ function createIdeCommand() {
46947
47437
  }
46948
47438
 
46949
47439
  // src/commands/update.ts
46950
- var import_node_process20 = __toESM(require("node:process"), 1);
47440
+ var import_node_process21 = __toESM(require("node:process"), 1);
46951
47441
  function renderUpdatePayload(payload) {
46952
47442
  return [
46953
47443
  `current: ${payload.currentVersion}`,
@@ -46976,7 +47466,7 @@ function createInstallCommand() {
46976
47466
  console.log(result.detail);
46977
47467
  }
46978
47468
  if (!result.ok) {
46979
- import_node_process20.default.exitCode = 1;
47469
+ import_node_process21.default.exitCode = 1;
46980
47470
  }
46981
47471
  return;
46982
47472
  }
@@ -46989,7 +47479,7 @@ function createInstallCommand() {
46989
47479
  }
46990
47480
  function createUpdateCommand(commandName = "update") {
46991
47481
  return new Command(commandName).description(commandName === "upgrade" ? "Check for and optionally install a newer Kimbho CLI build." : "Check for and optionally install a newer Kimbho CLI build.").option("--apply", "Run the global npm install command immediately when an update exists", false).option("--json", "Print the update payload as JSON", false).action(async (options) => {
46992
- const payload = await resolveUpdateManifest(import_node_process20.default.cwd());
47482
+ const payload = await resolveUpdateManifest(import_node_process21.default.cwd());
46993
47483
  const updateAvailable = isUpgradeAvailable(payload);
46994
47484
  if (options.apply && updateAvailable) {
46995
47485
  const result = runGlobalNpmInstall(payload.latestVersion);
@@ -47003,7 +47493,7 @@ function createUpdateCommand(commandName = "update") {
47003
47493
  console.log(result.detail);
47004
47494
  }
47005
47495
  if (!result.ok) {
47006
- import_node_process20.default.exitCode = 1;
47496
+ import_node_process21.default.exitCode = 1;
47007
47497
  }
47008
47498
  return;
47009
47499
  }
@@ -47020,7 +47510,7 @@ function createUpdateCommand(commandName = "update") {
47020
47510
  }
47021
47511
 
47022
47512
  // src/commands/mcp.ts
47023
- var import_node_process21 = __toESM(require("node:process"), 1);
47513
+ var import_node_process22 = __toESM(require("node:process"), 1);
47024
47514
 
47025
47515
  // src/mcp.ts
47026
47516
  async function renderMcpServerList(cwd) {
@@ -47184,7 +47674,7 @@ function collectValues(value, previous = []) {
47184
47674
  function createMcpCommand() {
47185
47675
  const command = new Command("mcp").description("Manage project-local MCP servers in .mcp.json.");
47186
47676
  command.command("list").description("List configured MCP servers.").action(async () => {
47187
- for (const line of await renderMcpServerList(import_node_process21.default.cwd())) {
47677
+ for (const line of await renderMcpServerList(import_node_process22.default.cwd())) {
47188
47678
  console.log(line);
47189
47679
  }
47190
47680
  });
@@ -47192,7 +47682,7 @@ function createMcpCommand() {
47192
47682
  const env = Object.fromEntries(
47193
47683
  options.env.map((pair) => pair.split("=", 2)).filter((entry) => entry.length === 2 && entry[0].length > 0)
47194
47684
  );
47195
- const outputPath = await addMcpServer(import_node_process21.default.cwd(), name, {
47685
+ const outputPath = await addMcpServer(import_node_process22.default.cwd(), name, {
47196
47686
  command: options.command,
47197
47687
  args: options.arg,
47198
47688
  env,
@@ -47206,34 +47696,34 @@ function createMcpCommand() {
47206
47696
  console.log(`Updated ${outputPath}`);
47207
47697
  });
47208
47698
  command.command("remove").description("Remove an MCP server.").argument("<name>", "Server name").action(async (name) => {
47209
- const outputPath = await removeMcpServerByName(import_node_process21.default.cwd(), name);
47699
+ const outputPath = await removeMcpServerByName(import_node_process22.default.cwd(), name);
47210
47700
  console.log(`Updated ${outputPath}`);
47211
47701
  });
47212
47702
  command.command("enable").description("Enable an MCP server.").argument("<name>", "Server name").action(async (name) => {
47213
- const outputPath = await toggleMcpServer(import_node_process21.default.cwd(), name, true);
47703
+ const outputPath = await toggleMcpServer(import_node_process22.default.cwd(), name, true);
47214
47704
  console.log(`Updated ${outputPath}`);
47215
47705
  });
47216
47706
  command.command("disable").description("Disable an MCP server.").argument("<name>", "Server name").action(async (name) => {
47217
- const outputPath = await toggleMcpServer(import_node_process21.default.cwd(), name, false);
47707
+ const outputPath = await toggleMcpServer(import_node_process22.default.cwd(), name, false);
47218
47708
  console.log(`Updated ${outputPath}`);
47219
47709
  });
47220
47710
  command.command("tools").description("Inspect MCP tool, prompt, and resource inventory.").argument("[name]", "Optional server name").action(async (name) => {
47221
- for (const line of await renderMcpInventory(import_node_process21.default.cwd(), name)) {
47711
+ for (const line of await renderMcpInventory(import_node_process22.default.cwd(), name)) {
47222
47712
  console.log(line);
47223
47713
  }
47224
47714
  });
47225
47715
  command.command("discover").description("Show MCP tools, prompts-as-commands, and resource attachment syntax.").argument("[name]", "Optional server name").action(async (name) => {
47226
- for (const line of await renderMcpInventory(import_node_process21.default.cwd(), name)) {
47716
+ for (const line of await renderMcpInventory(import_node_process22.default.cwd(), name)) {
47227
47717
  console.log(line);
47228
47718
  }
47229
47719
  });
47230
47720
  command.command("prompts").description("List MCP prompts.").argument("[name]", "Optional server name").action(async (name) => {
47231
- for (const line of await renderMcpPromptList(import_node_process21.default.cwd(), name)) {
47721
+ for (const line of await renderMcpPromptList(import_node_process22.default.cwd(), name)) {
47232
47722
  console.log(line);
47233
47723
  }
47234
47724
  });
47235
47725
  command.command("resources").description("List MCP resources and resource templates.").argument("[name]", "Optional server name").action(async (name) => {
47236
- for (const line of await renderMcpResourceList(import_node_process21.default.cwd(), name)) {
47726
+ for (const line of await renderMcpResourceList(import_node_process22.default.cwd(), name)) {
47237
47727
  console.log(line);
47238
47728
  }
47239
47729
  });
@@ -47241,12 +47731,12 @@ function createMcpCommand() {
47241
47731
  const args = Object.fromEntries(
47242
47732
  rawArgs.map((entry) => entry.split("=", 2)).filter((parts) => parts.length === 2 && parts[0].length > 0)
47243
47733
  );
47244
- for (const line of await renderMcpPromptInvocation(import_node_process21.default.cwd(), server, prompt, args)) {
47734
+ for (const line of await renderMcpPromptInvocation(import_node_process22.default.cwd(), server, prompt, args)) {
47245
47735
  console.log(line);
47246
47736
  }
47247
47737
  });
47248
47738
  command.command("read").description("Read one MCP resource by URI.").argument("<server>", "Server name").argument("<uri>", "Resource URI").action(async (server, uri) => {
47249
- for (const line of await renderMcpResourceRead(import_node_process21.default.cwd(), server, uri)) {
47739
+ for (const line of await renderMcpResourceRead(import_node_process22.default.cwd(), server, uri)) {
47250
47740
  console.log(line);
47251
47741
  }
47252
47742
  });
@@ -47254,20 +47744,20 @@ function createMcpCommand() {
47254
47744
  }
47255
47745
 
47256
47746
  // src/commands/mcp-server.ts
47257
- var import_node_process22 = __toESM(require("node:process"), 1);
47747
+ var import_node_process23 = __toESM(require("node:process"), 1);
47258
47748
  function createMcpServerCommand() {
47259
47749
  return new Command("mcp-server").description("Run Kimbho as an MCP server over stdio.").action(async () => {
47260
- await runMcpServer(import_node_process22.default.cwd());
47750
+ await runMcpServer(import_node_process23.default.cwd());
47261
47751
  });
47262
47752
  }
47263
47753
 
47264
47754
  // src/commands/memory.ts
47265
- var import_node_path29 = __toESM(require("node:path"), 1);
47266
- var import_node_process23 = __toESM(require("node:process"), 1);
47755
+ var import_node_path30 = __toESM(require("node:path"), 1);
47756
+ var import_node_process24 = __toESM(require("node:process"), 1);
47267
47757
  function createMemoryCommand() {
47268
47758
  const command = new Command("memory").description("Manage markdown-backed Kimbho memory files.");
47269
47759
  command.command("status").description("Show the memory file locations.").action(async () => {
47270
- const paths = await listMemoryPaths(import_node_process23.default.cwd());
47760
+ const paths = await listMemoryPaths(import_node_process24.default.cwd());
47271
47761
  console.log(`init: ${paths.initFilePath}`);
47272
47762
  console.log(`project: ${paths.projectMemoryPath}`);
47273
47763
  console.log(`user: ${paths.userMemoryPath}`);
@@ -47277,7 +47767,7 @@ function createMemoryCommand() {
47277
47767
  console.log(`agents: ${paths.agentMemoryDir}`);
47278
47768
  });
47279
47769
  command.command("refresh").description("Refresh kimbho_init.md and project memory.").action(async () => {
47280
- const result = await refreshMemoryFiles(import_node_process23.default.cwd());
47770
+ const result = await refreshMemoryFiles(import_node_process24.default.cwd());
47281
47771
  console.log(result.summary);
47282
47772
  console.log(`Wrote ${result.initFilePath}`);
47283
47773
  console.log(`Wrote ${result.projectMemoryPath}`);
@@ -47286,16 +47776,16 @@ function createMemoryCommand() {
47286
47776
  command.command("show").description("Print one memory file.").argument("<scope>", "init, project, user, or agent").argument("[agentId]", "Agent id when scope is agent").action(async (scope, agentId) => {
47287
47777
  let filePath;
47288
47778
  if (scope === "init") {
47289
- filePath = import_node_path29.default.join(import_node_process23.default.cwd(), "kimbho_init.md");
47779
+ filePath = import_node_path30.default.join(import_node_process24.default.cwd(), "kimbho_init.md");
47290
47780
  } else if (scope === "project") {
47291
- filePath = resolveProjectMemoryPath(import_node_process23.default.cwd());
47781
+ filePath = resolveProjectMemoryPath(import_node_process24.default.cwd());
47292
47782
  } else if (scope === "user") {
47293
47783
  filePath = resolveUserMemoryPath();
47294
47784
  } else if (scope === "agent") {
47295
47785
  if (!agentId) {
47296
47786
  throw new Error("Pass an agent id when using scope=agent.");
47297
47787
  }
47298
- filePath = import_node_path29.default.join(resolveAgentMemoryDir(import_node_process23.default.cwd()), `${agentId}.md`);
47788
+ filePath = import_node_path30.default.join(resolveAgentMemoryDir(import_node_process24.default.cwd()), `${agentId}.md`);
47299
47789
  } else {
47300
47790
  throw new Error("Scope must be one of: init, project, user, agent.");
47301
47791
  }
@@ -47308,7 +47798,7 @@ function createMemoryCommand() {
47308
47798
  });
47309
47799
  command.command("add").description("Append a memory note.").argument("<scope>", "project, user, or agent").argument("<first>", "Text or agent id when scope=agent").argument("[rest...]", "Remaining note text").action(async (scope, first, rest = []) => {
47310
47800
  if (scope === "project" || scope === "user") {
47311
- const outputPath = await appendMemoryNote(import_node_process23.default.cwd(), scope, [
47801
+ const outputPath = await appendMemoryNote(import_node_process24.default.cwd(), scope, [
47312
47802
  first,
47313
47803
  ...rest
47314
47804
  ].join(" "));
@@ -47316,7 +47806,7 @@ function createMemoryCommand() {
47316
47806
  return;
47317
47807
  }
47318
47808
  if (scope === "agent") {
47319
- const outputPath = await appendMemoryNote(import_node_process23.default.cwd(), "agent", rest.join(" "), first);
47809
+ const outputPath = await appendMemoryNote(import_node_process24.default.cwd(), "agent", rest.join(" "), first);
47320
47810
  console.log(`Updated ${outputPath}`);
47321
47811
  return;
47322
47812
  }
@@ -47326,7 +47816,7 @@ function createMemoryCommand() {
47326
47816
  }
47327
47817
 
47328
47818
  // src/commands/model.ts
47329
- var import_node_process24 = __toESM(require("node:process"), 1);
47819
+ var import_node_process25 = __toESM(require("node:process"), 1);
47330
47820
  function requireConfig() {
47331
47821
  throw new Error("No config found. Run `kimbho init` first.");
47332
47822
  }
@@ -47349,7 +47839,7 @@ async function fetchModels(provider, options) {
47349
47839
  models: cachedModels
47350
47840
  };
47351
47841
  }
47352
- const registry2 = createDefaultBrainProviderRegistry(import_node_process24.default.cwd());
47842
+ const registry2 = createDefaultBrainProviderRegistry(import_node_process25.default.cwd());
47353
47843
  try {
47354
47844
  const models = await registry2.listModels(provider, {
47355
47845
  ...options.search ? {
@@ -47391,14 +47881,14 @@ function printAssignments(config2) {
47391
47881
  function createModelCommand() {
47392
47882
  const command = new Command("model").description("Use one MECE surface for providers, models, and role assignments.");
47393
47883
  command.command("show").description("Show current provider/model assignments.").action(async () => {
47394
- const config2 = await loadConfig(import_node_process24.default.cwd());
47884
+ const config2 = await loadConfig(import_node_process25.default.cwd());
47395
47885
  if (!config2) {
47396
47886
  requireConfig();
47397
47887
  }
47398
47888
  printAssignments(config2);
47399
47889
  });
47400
47890
  command.command("providers").description("List configured providers.").action(async () => {
47401
- const config2 = await loadConfig(import_node_process24.default.cwd());
47891
+ const config2 = await loadConfig(import_node_process25.default.cwd());
47402
47892
  if (!config2) {
47403
47893
  requireConfig();
47404
47894
  }
@@ -47421,7 +47911,7 @@ function createModelCommand() {
47421
47911
  }
47422
47912
  });
47423
47913
  command.command("add").description("Add a provider from a template.").argument("<template>", "Template id").argument("[providerId]", "Optional provider id").option("--label <label>", "Provider label").option("--base-url <url>", "Base URL override").option("--api-key-env <env>", "API key environment variable").option("--model <id>", "Default model").action(async (templateId, providerId, options) => {
47424
- const config2 = await loadConfig(import_node_process24.default.cwd());
47914
+ const config2 = await loadConfig(import_node_process25.default.cwd());
47425
47915
  if (!config2) {
47426
47916
  requireConfig();
47427
47917
  }
@@ -47432,12 +47922,12 @@ function createModelCommand() {
47432
47922
  apiKeyEnv: options.apiKeyEnv,
47433
47923
  model: options.model
47434
47924
  });
47435
- const outputPath = await saveConfig(upsertProvider(config2, provider), import_node_process24.default.cwd());
47925
+ const outputPath = await saveConfig(upsertProvider(config2, provider), import_node_process25.default.cwd());
47436
47926
  console.log(`Updated ${outputPath}`);
47437
47927
  console.log(`Added ${provider.id} via ${templateId}`);
47438
47928
  });
47439
47929
  command.command("find").description("Find models on a provider.").argument("[search]", "Optional search text").option("--provider <id>", "Provider id; defaults to coder provider").option("--limit <count>", "Max number of models", parseInteger, 20).option("--cached", "Use cached provider models", false).action(async (search, options) => {
47440
- const config2 = await loadConfig(import_node_process24.default.cwd());
47930
+ const config2 = await loadConfig(import_node_process25.default.cwd());
47441
47931
  if (!config2) {
47442
47932
  requireConfig();
47443
47933
  }
@@ -47462,7 +47952,7 @@ function createModelCommand() {
47462
47952
  }
47463
47953
  });
47464
47954
  command.command("use").description("Assign one provider/model globally or to one role.").argument("<provider>", "Provider id").argument("[model]", "Optional model id").option("--role <role>", "Optional role override").action(async (providerId, modelId, options) => {
47465
- let config2 = await loadConfig(import_node_process24.default.cwd());
47955
+ let config2 = await loadConfig(import_node_process25.default.cwd());
47466
47956
  if (!config2) {
47467
47957
  requireConfig();
47468
47958
  }
@@ -47479,7 +47969,7 @@ function createModelCommand() {
47479
47969
  } else {
47480
47970
  config2 = assignProviderToAllBrains(config2, providerId);
47481
47971
  }
47482
- const outputPath2 = await saveConfig(config2, import_node_process24.default.cwd());
47972
+ const outputPath2 = await saveConfig(config2, import_node_process25.default.cwd());
47483
47973
  console.log(`Updated ${outputPath2}`);
47484
47974
  console.log(options.role ? `Assigned ${providerId} to ${options.role}` : `Assigned ${providerId} to all roles`);
47485
47975
  return;
@@ -47517,16 +48007,16 @@ function createModelCommand() {
47517
48007
  model: modelId
47518
48008
  });
47519
48009
  }
47520
- const outputPath = await saveConfig(config2, import_node_process24.default.cwd());
48010
+ const outputPath = await saveConfig(config2, import_node_process25.default.cwd());
47521
48011
  console.log(`Updated ${outputPath}`);
47522
48012
  console.log(options.role ? `Assigned ${providerId}/${modelId} to ${options.role}` : `Assigned ${providerId}/${modelId} to all roles`);
47523
48013
  });
47524
48014
  command.command("check").description("Run health checks for configured providers.").action(async () => {
47525
- const config2 = await loadConfig(import_node_process24.default.cwd());
48015
+ const config2 = await loadConfig(import_node_process25.default.cwd());
47526
48016
  if (!config2) {
47527
48017
  requireConfig();
47528
48018
  }
47529
- const registry2 = createDefaultBrainProviderRegistry(import_node_process24.default.cwd());
48019
+ const registry2 = createDefaultBrainProviderRegistry(import_node_process25.default.cwd());
47530
48020
  for (const provider of config2.providers) {
47531
48021
  try {
47532
48022
  const result = await registry2.healthCheck(provider);
@@ -47538,7 +48028,7 @@ function createModelCommand() {
47538
48028
  }
47539
48029
  });
47540
48030
  command.action(async () => {
47541
- const config2 = await loadConfig(import_node_process24.default.cwd());
48031
+ const config2 = await loadConfig(import_node_process25.default.cwd());
47542
48032
  if (!config2) {
47543
48033
  requireConfig();
47544
48034
  }
@@ -47548,7 +48038,7 @@ function createModelCommand() {
47548
48038
  }
47549
48039
 
47550
48040
  // src/commands/models.ts
47551
- var import_node_process25 = __toESM(require("node:process"), 1);
48041
+ var import_node_process26 = __toESM(require("node:process"), 1);
47552
48042
  function parseInteger2(value) {
47553
48043
  const parsed = Number.parseInt(value, 10);
47554
48044
  if (!Number.isFinite(parsed)) {
@@ -47607,7 +48097,7 @@ async function fetchProviderModels(provider, options) {
47607
48097
  models: cachedModels
47608
48098
  };
47609
48099
  }
47610
- const registry2 = createDefaultBrainProviderRegistry(import_node_process25.default.cwd());
48100
+ const registry2 = createDefaultBrainProviderRegistry(import_node_process26.default.cwd());
47611
48101
  try {
47612
48102
  const models = await registry2.listModels(provider, {
47613
48103
  ...options.search ? {
@@ -47634,7 +48124,7 @@ async function fetchProviderModels(provider, options) {
47634
48124
  function createModelsCommand() {
47635
48125
  const command = new Command("models").description("[legacy] Discover and select models from configured providers.");
47636
48126
  command.command("list").description("List models for one provider or all configured providers.").argument("[provider]", "Optional provider id to inspect").option("--search <term>", "Filter the returned models by search text").option("--limit <count>", "Maximum number of models to print", parseInteger2, 25).option("--cached", "Use cached models from config instead of remote discovery", false).option("--sync", "Persist discovered model ids back into config", false).option("--json", "Print models as JSON", false).action(async (providerId, options) => {
47637
- let config2 = await loadConfig(import_node_process25.default.cwd());
48127
+ let config2 = await loadConfig(import_node_process26.default.cwd());
47638
48128
  if (!config2) {
47639
48129
  requireConfigMessage2();
47640
48130
  }
@@ -47663,7 +48153,7 @@ function createModelsCommand() {
47663
48153
  }
47664
48154
  }
47665
48155
  if (mutated) {
47666
- await saveConfig(config2, import_node_process25.default.cwd());
48156
+ await saveConfig(config2, import_node_process26.default.cwd());
47667
48157
  }
47668
48158
  if (options.json) {
47669
48159
  console.log(renderJson(groups));
@@ -47680,7 +48170,7 @@ function createModelsCommand() {
47680
48170
  }
47681
48171
  });
47682
48172
  command.command("sync").description("Fetch remote models for one provider and cache the ids in config.").argument("<provider>", "Provider id to sync").option("--search <term>", "Optional search filter to limit what gets cached").option("--limit <count>", "Maximum number of models to cache", parseInteger2, 200).action(async (providerId, options) => {
47683
- const config2 = await loadConfig(import_node_process25.default.cwd());
48173
+ const config2 = await loadConfig(import_node_process26.default.cwd());
47684
48174
  if (!config2) {
47685
48175
  requireConfigMessage2();
47686
48176
  }
@@ -47688,7 +48178,7 @@ function createModelsCommand() {
47688
48178
  if (!provider) {
47689
48179
  throw new Error(`Unknown provider "${providerId}".`);
47690
48180
  }
47691
- const registry2 = createDefaultBrainProviderRegistry(import_node_process25.default.cwd());
48181
+ const registry2 = createDefaultBrainProviderRegistry(import_node_process26.default.cwd());
47692
48182
  const models = await registry2.listModels(provider, {
47693
48183
  ...options.search ? {
47694
48184
  search: options.search
@@ -47699,12 +48189,12 @@ function createModelsCommand() {
47699
48189
  ...provider,
47700
48190
  models: Array.from(new Set(models.map((model) => model.id)))
47701
48191
  });
47702
- const outputPath = await saveConfig(nextConfig, import_node_process25.default.cwd());
48192
+ const outputPath = await saveConfig(nextConfig, import_node_process26.default.cwd());
47703
48193
  console.log(`Updated ${outputPath}`);
47704
48194
  console.log(`Synced ${models.length} models for ${provider.id}`);
47705
48195
  });
47706
48196
  command.command("use").description("Select a model for a provider and assign it globally unless a specific role is requested.").argument("<model>", "Model id to select").requiredOption("--provider <provider>", "Provider id to use").option("--role <role>", "Brain role to assign: planner, coder, reviewer, or fast").option("--set-default", "Also set this model as the provider default", false).option("--force", "Skip remote model validation", false).option("--temperature <value>", "Temperature override for the role", parseNumber2).option("--max-tokens <value>", "Max token override for the role", parseInteger2).action(async (model, options) => {
47707
- let config2 = await loadConfig(import_node_process25.default.cwd());
48197
+ let config2 = await loadConfig(import_node_process26.default.cwd());
47708
48198
  if (!config2) {
47709
48199
  requireConfigMessage2();
47710
48200
  }
@@ -47714,7 +48204,7 @@ function createModelsCommand() {
47714
48204
  }
47715
48205
  if (!options.force) {
47716
48206
  try {
47717
- const registry2 = createDefaultBrainProviderRegistry(import_node_process25.default.cwd());
48207
+ const registry2 = createDefaultBrainProviderRegistry(import_node_process26.default.cwd());
47718
48208
  const models = await registry2.listModels(provider, {
47719
48209
  search: model,
47720
48210
  limit: 500
@@ -47756,7 +48246,7 @@ function createModelsCommand() {
47756
48246
  } else {
47757
48247
  config2 = assignProviderToAllBrains(config2, provider.id, model);
47758
48248
  }
47759
- const outputPath = await saveConfig(config2, import_node_process25.default.cwd());
48249
+ const outputPath = await saveConfig(config2, import_node_process26.default.cwd());
47760
48250
  console.log(`Updated ${outputPath}`);
47761
48251
  console.log(`Selected ${provider.id}/${model}`);
47762
48252
  if (options.role) {
@@ -47772,7 +48262,7 @@ function createModelsCommand() {
47772
48262
  }
47773
48263
 
47774
48264
  // src/commands/plan.ts
47775
- var import_node_process26 = __toESM(require("node:process"), 1);
48265
+ var import_node_process27 = __toESM(require("node:process"), 1);
47776
48266
  function createPlanCommand() {
47777
48267
  return new Command("plan").description("Generate a structured Kimbho execution plan for the provided goal.").argument("<goal>", "High-level product or engineering goal").option("--stack <stack>", "Preferred stack or preset").option(
47778
48268
  "--constraint <constraint>",
@@ -47780,7 +48270,7 @@ function createPlanCommand() {
47780
48270
  (value, previous = []) => [...previous, value],
47781
48271
  []
47782
48272
  ).option("--json", "Print the plan as JSON", false).action(async (goal, options) => {
47783
- const cwd = import_node_process26.default.cwd();
48273
+ const cwd = import_node_process27.default.cwd();
47784
48274
  const request = {
47785
48275
  goal,
47786
48276
  mode: "plan",
@@ -47837,8 +48327,8 @@ function createPlanCommand() {
47837
48327
  }
47838
48328
 
47839
48329
  // src/commands/permissions.ts
47840
- var import_node_process27 = __toESM(require("node:process"), 1);
47841
- var import_node_path30 = __toESM(require("node:path"), 1);
48330
+ var import_node_process28 = __toESM(require("node:process"), 1);
48331
+ var import_node_path31 = __toESM(require("node:path"), 1);
47842
48332
  function getScope2(options) {
47843
48333
  return options.scope === "user" ? "user" : "project";
47844
48334
  }
@@ -47857,7 +48347,7 @@ function createPermissionsCommand() {
47857
48347
  const command = new Command("permissions").description("Manage approval mode, sandbox mode, and trusted directories.");
47858
48348
  command.command("status").description("Show permission settings.").option("--scope <scope>", "project or user", "project").action(async (options) => {
47859
48349
  const scope = getScope2(options);
47860
- const { direct, resolved } = await loadScopedConfig2(scope, import_node_process27.default.cwd());
48350
+ const { direct, resolved } = await loadScopedConfig2(scope, import_node_process28.default.cwd());
47861
48351
  console.log(`scope: ${scope}`);
47862
48352
  console.log(`direct config: ${direct ? "present" : "missing"}`);
47863
48353
  if (!resolved) {
@@ -47879,7 +48369,7 @@ function createPermissionsCommand() {
47879
48369
  });
47880
48370
  command.command("set").description("Set approval mode or sandbox mode.").option("--scope <scope>", "project or user", "project").option("--approval <mode>", "manual, on-request, plan, auto, dontAsk, acceptEdits, or bypassPermissions").option("--sandbox <mode>", "read-only, workspace-write, or full").action(async (options) => {
47881
48371
  const scope = getScope2(options);
47882
- const cwd = import_node_process27.default.cwd();
48372
+ const cwd = import_node_process28.default.cwd();
47883
48373
  const { direct, resolved } = await loadScopedConfig2(scope, cwd);
47884
48374
  if (!resolved && !direct) {
47885
48375
  throw new Error("No config found. Run `kimbho init` first.");
@@ -47899,13 +48389,13 @@ function createPermissionsCommand() {
47899
48389
  });
47900
48390
  command.command("trust").description("Add a trusted directory.").argument("<path>", "Directory to trust").option("--scope <scope>", "project or user", "project").action(async (trustedPath, options) => {
47901
48391
  const scope = getScope2(options);
47902
- const cwd = import_node_process27.default.cwd();
48392
+ const cwd = import_node_process28.default.cwd();
47903
48393
  const { direct, resolved } = await loadScopedConfig2(scope, cwd);
47904
48394
  if (!resolved && !direct) {
47905
48395
  throw new Error("No config found. Run `kimbho init` first.");
47906
48396
  }
47907
48397
  const base = direct ?? resolved ?? createDefaultConfig();
47908
- const normalizedPath = import_node_path30.default.resolve(cwd, trustedPath);
48398
+ const normalizedPath = import_node_path31.default.resolve(cwd, trustedPath);
47909
48399
  const outputPath = await saveScopedConfig2(scope, cwd, {
47910
48400
  ...base,
47911
48401
  trustedDirectories: Array.from(/* @__PURE__ */ new Set([
@@ -47917,13 +48407,13 @@ function createPermissionsCommand() {
47917
48407
  });
47918
48408
  command.command("untrust").description("Remove a trusted directory.").argument("<path>", "Directory to remove").option("--scope <scope>", "project or user", "project").action(async (trustedPath, options) => {
47919
48409
  const scope = getScope2(options);
47920
- const cwd = import_node_process27.default.cwd();
48410
+ const cwd = import_node_process28.default.cwd();
47921
48411
  const { direct, resolved } = await loadScopedConfig2(scope, cwd);
47922
48412
  if (!resolved && !direct) {
47923
48413
  throw new Error("No config found. Run `kimbho init` first.");
47924
48414
  }
47925
48415
  const base = direct ?? resolved ?? createDefaultConfig();
47926
- const normalizedPath = import_node_path30.default.resolve(cwd, trustedPath);
48416
+ const normalizedPath = import_node_path31.default.resolve(cwd, trustedPath);
47927
48417
  const outputPath = await saveScopedConfig2(scope, cwd, {
47928
48418
  ...base,
47929
48419
  trustedDirectories: base.trustedDirectories.filter((directory) => directory !== trustedPath && directory !== normalizedPath)
@@ -47934,14 +48424,14 @@ function createPermissionsCommand() {
47934
48424
  }
47935
48425
 
47936
48426
  // src/commands/providers.ts
47937
- var import_node_process28 = __toESM(require("node:process"), 1);
48427
+ var import_node_process29 = __toESM(require("node:process"), 1);
47938
48428
  function requireConfigMessage3() {
47939
48429
  throw new Error("No config found. Run `kimbho init` first.");
47940
48430
  }
47941
48431
  function createProvidersCommand() {
47942
48432
  const command = new Command("providers").description("[legacy] Manage configured model providers and built-in templates.");
47943
48433
  command.command("list").description("List configured providers.").option("--json", "Print providers as JSON", false).action(async (options) => {
47944
- const config2 = await loadConfig(import_node_process28.default.cwd());
48434
+ const config2 = await loadConfig(import_node_process29.default.cwd());
47945
48435
  if (!config2) {
47946
48436
  requireConfigMessage3();
47947
48437
  }
@@ -47982,7 +48472,7 @@ function createProvidersCommand() {
47982
48472
  (value, previous = []) => [...previous, value],
47983
48473
  []
47984
48474
  ).option("--module-path <path>", "Module path for a custom provider driver").action(async (options) => {
47985
- const config2 = await loadConfig(import_node_process28.default.cwd());
48475
+ const config2 = await loadConfig(import_node_process29.default.cwd());
47986
48476
  if (!config2) {
47987
48477
  requireConfigMessage3();
47988
48478
  }
@@ -48016,16 +48506,16 @@ function createProvidersCommand() {
48016
48506
  } : {}
48017
48507
  });
48018
48508
  const nextConfig = upsertProvider(config2, provider);
48019
- const outputPath = await saveConfig(nextConfig, import_node_process28.default.cwd());
48509
+ const outputPath = await saveConfig(nextConfig, import_node_process29.default.cwd());
48020
48510
  console.log(`Updated ${outputPath}`);
48021
48511
  console.log(`Provider ${provider.id} -> ${provider.driver}`);
48022
48512
  });
48023
48513
  command.command("check").description("Run health checks for the configured providers.").action(async () => {
48024
- const config2 = await loadConfig(import_node_process28.default.cwd());
48514
+ const config2 = await loadConfig(import_node_process29.default.cwd());
48025
48515
  if (!config2) {
48026
48516
  requireConfigMessage3();
48027
48517
  }
48028
- const registry2 = createDefaultBrainProviderRegistry(import_node_process28.default.cwd());
48518
+ const registry2 = createDefaultBrainProviderRegistry(import_node_process29.default.cwd());
48029
48519
  for (const provider of config2.providers) {
48030
48520
  try {
48031
48521
  const result = await registry2.healthCheck(provider);
@@ -48040,10 +48530,10 @@ function createProvidersCommand() {
48040
48530
  }
48041
48531
 
48042
48532
  // src/commands/review.ts
48043
- var import_node_process29 = __toESM(require("node:process"), 1);
48533
+ var import_node_process30 = __toESM(require("node:process"), 1);
48044
48534
  function createReviewCommand() {
48045
48535
  return new Command("review").description("Review the current diff, summarize changed files, and surface risks.").option("--json", "Print the review payload as JSON", false).option("--patch <path>", "Review a patch file instead of the current git diff").action(async (options) => {
48046
- const cwd = import_node_process29.default.cwd();
48536
+ const cwd = import_node_process30.default.cwd();
48047
48537
  const payload = await reviewWorkspace(cwd, {
48048
48538
  patchPath: options.patch
48049
48539
  });
@@ -48076,8 +48566,8 @@ function createReviewCommand() {
48076
48566
  }
48077
48567
 
48078
48568
  // src/commands/resume.ts
48079
- var import_node_process30 = __toESM(require("node:process"), 1);
48080
- function parseCount4(value) {
48569
+ var import_node_process31 = __toESM(require("node:process"), 1);
48570
+ function parseCount5(value) {
48081
48571
  const parsed = Number(value);
48082
48572
  if (!Number.isInteger(parsed) || parsed <= 0) {
48083
48573
  throw new Error(`Expected a positive integer, received "${value}".`);
@@ -48085,8 +48575,8 @@ function parseCount4(value) {
48085
48575
  return parsed;
48086
48576
  }
48087
48577
  function createResumeCommand() {
48088
- return new Command("resume").alias("continue").description("Resume the latest saved Kimbho session snapshot.").argument("[sessionId]", "Optional session id; defaults to the latest session").option("--json", "Print the latest session as JSON", false).option("--last", "Resume the most recent session", false).option("--list", "List recent sessions and exit", false).option("--search <query>", "Filter sessions by id, goal, cwd, or labels").option("--pr <query>", "Filter sessions by linked PR url, repo, or number").option("--execute", "Continue auto-executing the ready-task frontier", false).option("--approve <approvalId>", "Approve a pending action before continuing").option("--deny <approvalId>", "Deny a pending action before continuing").option("--max-auto-tasks <count>", "Maximum ready tasks to auto-execute", parseCount4, 4).option("--max-agent-steps <count>", "Maximum tool/model steps per autonomous task", parseCount4, 8).option("--max-repair-attempts <count>", "Maximum failed verification cycles per autonomous task", parseCount4, 2).option("--max-tool-calls <count>", "Maximum tool calls per autonomous task", parseCount4).option("--max-model-calls <count>", "Maximum model calls per autonomous task", parseCount4).option("--max-input-tokens <count>", "Maximum input tokens per autonomous task", parseCount4).option("--max-output-tokens <count>", "Maximum output tokens per autonomous task", parseCount4).action(async (sessionId, options) => {
48089
- const cwd = import_node_process30.default.cwd();
48578
+ return new Command("resume").alias("continue").description("Resume the latest saved Kimbho session snapshot.").argument("[sessionId]", "Optional session id; defaults to the latest session").option("--json", "Print the latest session as JSON", false).option("--last", "Resume the most recent session", false).option("--list", "List recent sessions and exit", false).option("--search <query>", "Filter sessions by id, goal, cwd, or labels").option("--pr <query>", "Filter sessions by linked PR url, repo, or number").option("--execute", "Continue auto-executing the ready-task frontier", false).option("--approve <approvalId>", "Approve a pending action before continuing").option("--deny <approvalId>", "Deny a pending action before continuing").option("--max-auto-tasks <count>", "Maximum ready tasks to auto-execute", parseCount5, 4).option("--max-agent-steps <count>", "Maximum tool/model steps per autonomous task", parseCount5, 8).option("--max-repair-attempts <count>", "Maximum failed verification cycles per autonomous task", parseCount5, 2).option("--max-tool-calls <count>", "Maximum tool calls per autonomous task", parseCount5).option("--max-model-calls <count>", "Maximum model calls per autonomous task", parseCount5).option("--max-input-tokens <count>", "Maximum input tokens per autonomous task", parseCount5).option("--max-output-tokens <count>", "Maximum output tokens per autonomous task", parseCount5).action(async (sessionId, options) => {
48579
+ const cwd = import_node_process31.default.cwd();
48090
48580
  const effectiveSearch = options.pr?.trim() || options.search?.trim();
48091
48581
  const firstSearchMatch = effectiveSearch ? (await searchSessions(effectiveSearch, cwd, 1)).at(0) ?? null : null;
48092
48582
  if (options.list) {
@@ -48111,12 +48601,12 @@ function createResumeCommand() {
48111
48601
  const session = effectiveSearch && !sessionId && !options.last ? firstSearchMatch ? await loadSessionById(firstSearchMatch.id, cwd) : null : options.last || !sessionId ? await loadLatestSession(cwd) : await loadSessionById(sessionId, cwd);
48112
48602
  if (!session) {
48113
48603
  console.error("No saved session found. Run `kimbho run` first.");
48114
- import_node_process30.default.exitCode = 1;
48604
+ import_node_process31.default.exitCode = 1;
48115
48605
  return;
48116
48606
  }
48117
48607
  if (options.approve && options.deny) {
48118
48608
  console.error("Pass only one of --approve or --deny.");
48119
- import_node_process30.default.exitCode = 1;
48609
+ import_node_process31.default.exitCode = 1;
48120
48610
  return;
48121
48611
  }
48122
48612
  const snapshot = options.execute ? await new ExecutionOrchestrator().continueSession(session, {
@@ -48163,7 +48653,7 @@ function createResumeCommand() {
48163
48653
  }
48164
48654
 
48165
48655
  // src/commands/run.ts
48166
- var import_node_process31 = __toESM(require("node:process"), 1);
48656
+ var import_node_process32 = __toESM(require("node:process"), 1);
48167
48657
 
48168
48658
  // src/pr-link.ts
48169
48659
  function inferProvider(hostname2) {
@@ -48206,7 +48696,7 @@ function parsePrLinkFromUrl(value, overrides = {}) {
48206
48696
  }
48207
48697
 
48208
48698
  // src/commands/run.ts
48209
- function parseCount5(value) {
48699
+ function parseCount6(value) {
48210
48700
  const parsed = Number(value);
48211
48701
  if (!Number.isInteger(parsed) || parsed <= 0) {
48212
48702
  throw new Error(`Expected a positive integer, received "${value}".`);
@@ -48219,8 +48709,8 @@ function createRunCommand() {
48219
48709
  "Explicit execution constraint; can be provided multiple times",
48220
48710
  (value, previous = []) => [...previous, value],
48221
48711
  []
48222
- ).option("--json", "Print the session snapshot as JSON", false).option("--snapshot-only", "Create the session without auto-executing ready tasks", false).option("--agent <id>", "Prefer one custom or plugin agent id for this session").option("--agents <jsonOrPath>", "Inline agent definitions as JSON or a path to a JSON file").option("--session-id <id>", "Use an explicit session id").option("--pr-url <url>", "Link this session to a pull request URL").option("--ephemeral", "Do not persist plans or sessions for this invocation", false).option("--max-auto-tasks <count>", "Maximum ready tasks to auto-execute", parseCount5, 4).option("--max-agent-steps <count>", "Maximum tool/model steps per autonomous task", parseCount5, 8).option("--max-repair-attempts <count>", "Maximum failed verification cycles per autonomous task", parseCount5, 2).option("--max-tool-calls <count>", "Maximum tool calls per autonomous task", parseCount5).option("--max-model-calls <count>", "Maximum model calls per autonomous task", parseCount5).option("--max-input-tokens <count>", "Maximum input tokens per autonomous task", parseCount5).option("--max-output-tokens <count>", "Maximum output tokens per autonomous task", parseCount5).action(async (goal, options) => {
48223
- const cwd = import_node_process31.default.cwd();
48712
+ ).option("--json", "Print the session snapshot as JSON", false).option("--snapshot-only", "Create the session without auto-executing ready tasks", false).option("--agent <id>", "Prefer one custom or plugin agent id for this session").option("--agents <jsonOrPath>", "Inline agent definitions as JSON or a path to a JSON file").option("--session-id <id>", "Use an explicit session id").option("--pr-url <url>", "Link this session to a pull request URL").option("--ephemeral", "Do not persist plans or sessions for this invocation", false).option("--max-auto-tasks <count>", "Maximum ready tasks to auto-execute", parseCount6, 4).option("--max-agent-steps <count>", "Maximum tool/model steps per autonomous task", parseCount6, 8).option("--max-repair-attempts <count>", "Maximum failed verification cycles per autonomous task", parseCount6, 2).option("--max-tool-calls <count>", "Maximum tool calls per autonomous task", parseCount6).option("--max-model-calls <count>", "Maximum model calls per autonomous task", parseCount6).option("--max-input-tokens <count>", "Maximum input tokens per autonomous task", parseCount6).option("--max-output-tokens <count>", "Maximum output tokens per autonomous task", parseCount6).action(async (goal, options) => {
48713
+ const cwd = import_node_process32.default.cwd();
48224
48714
  const orchestrator = new ExecutionOrchestrator();
48225
48715
  const agentSelection = await resolveAgentSelection(cwd, {
48226
48716
  agent: options.agent,
@@ -48232,7 +48722,7 @@ function createRunCommand() {
48232
48722
  let planResult = null;
48233
48723
  if (!plan && !goal) {
48234
48724
  console.error("No saved plan found. Pass a goal or run `kimbho plan` first.");
48235
- import_node_process31.default.exitCode = 1;
48725
+ import_node_process32.default.exitCode = 1;
48236
48726
  return;
48237
48727
  }
48238
48728
  if (goal) {
@@ -48337,7 +48827,7 @@ function createRunCommand() {
48337
48827
  }
48338
48828
 
48339
48829
  // src/commands/skills.ts
48340
- var import_node_process32 = __toESM(require("node:process"), 1);
48830
+ var import_node_process33 = __toESM(require("node:process"), 1);
48341
48831
  function renderMetadataBlock(metadata) {
48342
48832
  return [
48343
48833
  ` userInvocable: ${String(metadata.userInvocable)}`,
@@ -48355,7 +48845,7 @@ function renderOriginLabel(definition) {
48355
48845
  function createSkillsCommand() {
48356
48846
  const command = new Command("skills").description("Inspect Kimbho-native skill packs and command packs, with .claude fallback compatibility.");
48357
48847
  command.action(async () => {
48358
- const skills = await listClaudeSkills(import_node_process32.default.cwd());
48848
+ const skills = await listClaudeSkills(import_node_process33.default.cwd());
48359
48849
  if (skills.length === 0) {
48360
48850
  console.log("No skill packs discovered.");
48361
48851
  return;
@@ -48366,7 +48856,7 @@ function createSkillsCommand() {
48366
48856
  }
48367
48857
  });
48368
48858
  command.command("list").description("List discovered skill packs from .kimbho/skills and .claude/skills.").action(async () => {
48369
- const skills = await listClaudeSkills(import_node_process32.default.cwd());
48859
+ const skills = await listClaudeSkills(import_node_process33.default.cwd());
48370
48860
  if (skills.length === 0) {
48371
48861
  console.log("No skill packs discovered.");
48372
48862
  return;
@@ -48377,7 +48867,7 @@ function createSkillsCommand() {
48377
48867
  }
48378
48868
  });
48379
48869
  command.command("commands").description("List discovered command packs from .kimbho/commands and .claude/commands.").option("--all", "Include commands marked user-invocable=false", false).action(async (options) => {
48380
- const commands = await listClaudeCommands(import_node_process32.default.cwd(), {
48870
+ const commands = await listClaudeCommands(import_node_process33.default.cwd(), {
48381
48871
  includeHidden: Boolean(options.all)
48382
48872
  });
48383
48873
  if (commands.length === 0) {
@@ -48390,7 +48880,7 @@ function createSkillsCommand() {
48390
48880
  }
48391
48881
  });
48392
48882
  command.command("inspect").description("Inspect one skill pack entry.").argument("<id>", "Skill id").action(async (id) => {
48393
- const skill = await loadClaudeSkillById(import_node_process32.default.cwd(), id);
48883
+ const skill = await loadClaudeSkillById(import_node_process33.default.cwd(), id);
48394
48884
  if (!skill) {
48395
48885
  throw new Error(`Unknown skill "${id}".`);
48396
48886
  }
@@ -48403,7 +48893,7 @@ function createSkillsCommand() {
48403
48893
  }
48404
48894
  });
48405
48895
  command.command("inspect-command").description("Inspect one command pack entry.").argument("<name>", "Command name").action(async (name) => {
48406
- const definition = await loadClaudeCommandByName(import_node_process32.default.cwd(), name, {
48896
+ const definition = await loadClaudeCommandByName(import_node_process33.default.cwd(), name, {
48407
48897
  includeHidden: true
48408
48898
  });
48409
48899
  if (!definition) {
@@ -48418,7 +48908,7 @@ function createSkillsCommand() {
48418
48908
  }
48419
48909
  });
48420
48910
  command.command("render-command").description("Render one command pack entry with arguments, without executing it.").argument("<name>", "Command name").argument("[args...]", "Arguments to substitute into the command body").action(async (name, args = []) => {
48421
- const invocation = await resolveClaudeCommandInvocation(import_node_process32.default.cwd(), [
48911
+ const invocation = await resolveClaudeCommandInvocation(import_node_process33.default.cwd(), [
48422
48912
  name,
48423
48913
  ...args
48424
48914
  ]);
@@ -48432,8 +48922,8 @@ function createSkillsCommand() {
48432
48922
 
48433
48923
  // src/commands/worktree.ts
48434
48924
  var import_promises26 = require("node:fs/promises");
48435
- var import_node_path31 = __toESM(require("node:path"), 1);
48436
- var import_node_process33 = __toESM(require("node:process"), 1);
48925
+ var import_node_path32 = __toESM(require("node:path"), 1);
48926
+ var import_node_process34 = __toESM(require("node:process"), 1);
48437
48927
  var import_node_child_process12 = require("node:child_process");
48438
48928
  function sanitizeName3(value) {
48439
48929
  return value.replace(/[^a-zA-Z0-9._-]+/g, "-").slice(0, 80);
@@ -48442,10 +48932,10 @@ function storedWorktreeName(name) {
48442
48932
  return sanitizeName3(`manual-${name}`);
48443
48933
  }
48444
48934
  function resolveStoredWorktreePath(cwd, name) {
48445
- return import_node_path31.default.join(resolveKimbhoDir(cwd), "worktrees", storedWorktreeName(name));
48935
+ return import_node_path32.default.join(resolveKimbhoDir(cwd), "worktrees", storedWorktreeName(name));
48446
48936
  }
48447
48937
  function resolveStoredPatchPath(cwd, name) {
48448
- return import_node_path31.default.join(resolveKimbhoDir(cwd), "logs", `${storedWorktreeName(name)}.patch`);
48938
+ return import_node_path32.default.join(resolveKimbhoDir(cwd), "logs", `${storedWorktreeName(name)}.patch`);
48449
48939
  }
48450
48940
  async function resolveStoredWorktree(cwd, name) {
48451
48941
  const worktreePath = resolveStoredWorktreePath(cwd, name);
@@ -48471,14 +48961,14 @@ function gitRun(cwd, args) {
48471
48961
  function createWorktreeCommand() {
48472
48962
  const command = new Command("worktree").description("Manage user-visible isolated worktrees and apply their diffs back.");
48473
48963
  command.command("list").description("List Kimbho-managed worktrees.").option("--json", "Print the worktree payload as JSON", false).action(async (options) => {
48474
- const dir = import_node_path31.default.join(resolveKimbhoDir(import_node_process33.default.cwd()), "worktrees");
48964
+ const dir = import_node_path32.default.join(resolveKimbhoDir(import_node_process34.default.cwd()), "worktrees");
48475
48965
  const entries = await (0, import_promises26.readdir)(dir, {
48476
48966
  withFileTypes: true
48477
48967
  }).catch(() => []);
48478
48968
  const worktrees = entries.filter((entry) => entry.isDirectory()).map((entry) => ({
48479
48969
  id: entry.name.replace(/^manual-/, ""),
48480
- worktreePath: import_node_path31.default.join(dir, entry.name),
48481
- patchPath: import_node_path31.default.join(resolveKimbhoDir(import_node_process33.default.cwd()), "logs", `${entry.name}.patch`)
48970
+ worktreePath: import_node_path32.default.join(dir, entry.name),
48971
+ patchPath: import_node_path32.default.join(resolveKimbhoDir(import_node_process34.default.cwd()), "logs", `${entry.name}.patch`)
48482
48972
  }));
48483
48973
  if (options.json) {
48484
48974
  console.log(JSON.stringify(worktrees, null, 2));
@@ -48495,7 +48985,7 @@ function createWorktreeCommand() {
48495
48985
  }
48496
48986
  });
48497
48987
  command.command("create").description("Create one user-visible isolated worktree.").argument("<name>", "Worktree name").option("--json", "Print the worktree payload as JSON", false).action(async (name, options) => {
48498
- const worktree = await createIsolatedWorktree(import_node_process33.default.cwd(), "manual", name);
48988
+ const worktree = await createIsolatedWorktree(import_node_process34.default.cwd(), "manual", name);
48499
48989
  if (!worktree) {
48500
48990
  throw new Error("This workspace is not a git repo with a valid HEAD. Worktrees require git history.");
48501
48991
  }
@@ -48507,19 +48997,19 @@ function createWorktreeCommand() {
48507
48997
  console.log(`Patch artifact: ${worktree.patchArtifactPath}`);
48508
48998
  });
48509
48999
  command.command("diff").description("Inspect the current diff inside one managed worktree.").argument("<name>", "Worktree name").option("--stat", "Show only diff stats", false).action(async (name, options) => {
48510
- const worktree = await resolveStoredWorktree(import_node_process33.default.cwd(), name);
49000
+ const worktree = await resolveStoredWorktree(import_node_process34.default.cwd(), name);
48511
49001
  const args = options.stat ? ["diff", "--stat", "HEAD"] : ["diff", "--binary", "--full-index", "--no-ext-diff", "--stat", "--patch", "HEAD"];
48512
49002
  const result = gitRun(worktree.worktreePath, args);
48513
49003
  if (!result.ok) {
48514
49004
  console.error(result.detail);
48515
- import_node_process33.default.exitCode = 1;
49005
+ import_node_process34.default.exitCode = 1;
48516
49006
  return;
48517
49007
  }
48518
49008
  console.log(result.stdout.trim() || "No diff.");
48519
49009
  });
48520
49010
  command.command("apply").description("Apply one managed worktree back into the main workspace and clean it up.").argument("<name>", "Worktree name").option("--json", "Print the integration payload as JSON", false).action(async (name, options) => {
48521
- const worktree = await resolveStoredWorktree(import_node_process33.default.cwd(), name);
48522
- const result = await integrateIsolatedWorktree(import_node_process33.default.cwd(), worktree, [], []);
49011
+ const worktree = await resolveStoredWorktree(import_node_process34.default.cwd(), name);
49012
+ const result = await integrateIsolatedWorktree(import_node_process34.default.cwd(), worktree, [], []);
48523
49013
  if (options.json) {
48524
49014
  console.log(JSON.stringify(result, null, 2));
48525
49015
  return;
@@ -48531,11 +49021,11 @@ function createWorktreeCommand() {
48531
49021
  console.log(`artifact: ${artifact}`);
48532
49022
  }
48533
49023
  if (result.integrationFailed) {
48534
- import_node_process33.default.exitCode = 1;
49024
+ import_node_process34.default.exitCode = 1;
48535
49025
  }
48536
49026
  });
48537
49027
  command.command("remove").description("Delete one managed worktree without applying it back.").argument("<name>", "Worktree name").option("--json", "Print the removal payload as JSON", false).action(async (name, options) => {
48538
- const cwd = import_node_process33.default.cwd();
49028
+ const cwd = import_node_process34.default.cwd();
48539
49029
  const worktreePath = resolveStoredWorktreePath(cwd, name);
48540
49030
  const removal = gitRun(cwd, [
48541
49031
  "worktree",
@@ -48565,20 +49055,6 @@ function createWorktreeCommand() {
48565
49055
  return command;
48566
49056
  }
48567
49057
 
48568
- // src/commands/placeholders.ts
48569
- function createPlaceholder(name, description, milestone) {
48570
- return new Command(name).description(description).action(() => {
48571
- console.log(`${name} is planned for ${milestone}.`);
48572
- });
48573
- }
48574
- function createFixCommand() {
48575
- return createPlaceholder(
48576
- "fix",
48577
- "Diagnose and repair a failing repository state.",
48578
- "Milestone 4: Executor Loop"
48579
- );
48580
- }
48581
-
48582
49058
  // src/program.ts
48583
49059
  var MODELS_SUBCOMMANDS = /* @__PURE__ */ new Set([
48584
49060
  "help",
@@ -48705,10 +49181,10 @@ function createProgram(onOpenShell) {
48705
49181
  }
48706
49182
 
48707
49183
  // src/runtime-flags.ts
48708
- var import_node_path32 = __toESM(require("node:path"), 1);
48709
- var import_node_process34 = __toESM(require("node:process"), 1);
49184
+ var import_node_path33 = __toESM(require("node:path"), 1);
49185
+ var import_node_process35 = __toESM(require("node:process"), 1);
48710
49186
  function parseJsonEnv2(name, fallback) {
48711
- const raw = import_node_process34.default.env[name];
49187
+ const raw = import_node_process35.default.env[name];
48712
49188
  if (!raw || raw.trim().length === 0) {
48713
49189
  return fallback;
48714
49190
  }
@@ -48792,7 +49268,7 @@ function readOptionValue(tokens, index, label) {
48792
49268
  return value;
48793
49269
  }
48794
49270
  function applyRuntimeFlags(tokens) {
48795
- const initialCwd = import_node_process34.default.cwd();
49271
+ const initialCwd = import_node_process35.default.cwd();
48796
49272
  const remaining = [];
48797
49273
  const overrides = parseJsonEnv2(
48798
49274
  KIMBHO_RUNTIME_OVERRIDES_ENV,
@@ -48803,7 +49279,7 @@ function applyRuntimeFlags(tokens) {
48803
49279
  []
48804
49280
  );
48805
49281
  let nextCwd = null;
48806
- let selectedProfile = import_node_process34.default.env[KIMBHO_RUNTIME_PROFILE_ENV] ?? null;
49282
+ let selectedProfile = import_node_process35.default.env[KIMBHO_RUNTIME_PROFILE_ENV] ?? null;
48807
49283
  let forceExec = false;
48808
49284
  let index = 0;
48809
49285
  while (index < tokens.length) {
@@ -48901,14 +49377,14 @@ function applyRuntimeFlags(tokens) {
48901
49377
  break;
48902
49378
  }
48903
49379
  if (nextCwd) {
48904
- import_node_process34.default.chdir(import_node_path32.default.resolve(initialCwd, nextCwd));
49380
+ import_node_process35.default.chdir(import_node_path33.default.resolve(initialCwd, nextCwd));
48905
49381
  }
48906
49382
  if (selectedProfile) {
48907
- import_node_process34.default.env[KIMBHO_RUNTIME_PROFILE_ENV] = selectedProfile;
49383
+ import_node_process35.default.env[KIMBHO_RUNTIME_PROFILE_ENV] = selectedProfile;
48908
49384
  }
48909
- import_node_process34.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV] = JSON.stringify(overrides);
48910
- import_node_process34.default.env[KIMBHO_RUNTIME_ADDITIONAL_DIRS_ENV] = JSON.stringify(
48911
- additionalDirectories.map((directory) => import_node_path32.default.resolve(import_node_process34.default.cwd(), directory))
49385
+ import_node_process35.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV] = JSON.stringify(overrides);
49386
+ import_node_process35.default.env[KIMBHO_RUNTIME_ADDITIONAL_DIRS_ENV] = JSON.stringify(
49387
+ additionalDirectories.map((directory) => import_node_path33.default.resolve(import_node_process35.default.cwd(), directory))
48912
49388
  );
48913
49389
  return {
48914
49390
  tokens: remaining,
@@ -48920,8 +49396,8 @@ function applyRuntimeFlags(tokens) {
48920
49396
  var import_node_child_process13 = require("node:child_process");
48921
49397
  var import_node_readline2 = require("node:readline");
48922
49398
  var import_promises27 = require("node:readline/promises");
48923
- var import_node_path33 = __toESM(require("node:path"), 1);
48924
- var import_node_process35 = __toESM(require("node:process"), 1);
49399
+ var import_node_path34 = __toESM(require("node:path"), 1);
49400
+ var import_node_process36 = __toESM(require("node:process"), 1);
48925
49401
 
48926
49402
  // src/agent-management.ts
48927
49403
  async function renderCustomAgents(cwd) {
@@ -49095,7 +49571,7 @@ function renderShimmeringLabel(label, frameIndex) {
49095
49571
  }).join("");
49096
49572
  }
49097
49573
  function readRuntimeOverrideEntries() {
49098
- const raw = import_node_process35.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV];
49574
+ const raw = import_node_process36.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV];
49099
49575
  if (!raw || raw.trim().length === 0) {
49100
49576
  return [];
49101
49577
  }
@@ -49113,7 +49589,7 @@ function readRuntimeOverrideEntries() {
49113
49589
  }
49114
49590
  }
49115
49591
  function readAdditionalDirectories2() {
49116
- const raw = import_node_process35.default.env[KIMBHO_RUNTIME_ADDITIONAL_DIRS_ENV];
49592
+ const raw = import_node_process36.default.env[KIMBHO_RUNTIME_ADDITIONAL_DIRS_ENV];
49117
49593
  if (!raw || raw.trim().length === 0) {
49118
49594
  return [];
49119
49595
  }
@@ -49149,17 +49625,17 @@ function syncShellRuntimeOverrides(runtime) {
49149
49625
  ] : []
49150
49626
  ];
49151
49627
  if (merged.length === 0) {
49152
- delete import_node_process35.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV];
49628
+ delete import_node_process36.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV];
49153
49629
  return;
49154
49630
  }
49155
- import_node_process35.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV] = JSON.stringify(merged);
49631
+ import_node_process36.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV] = JSON.stringify(merged);
49156
49632
  }
49157
49633
  function syncShellAdditionalDirectories(runtime) {
49158
49634
  if (runtime.additionalDirectories.length === 0) {
49159
- delete import_node_process35.default.env[KIMBHO_RUNTIME_ADDITIONAL_DIRS_ENV];
49635
+ delete import_node_process36.default.env[KIMBHO_RUNTIME_ADDITIONAL_DIRS_ENV];
49160
49636
  return;
49161
49637
  }
49162
- import_node_process35.default.env[KIMBHO_RUNTIME_ADDITIONAL_DIRS_ENV] = JSON.stringify(runtime.additionalDirectories);
49638
+ import_node_process36.default.env[KIMBHO_RUNTIME_ADDITIONAL_DIRS_ENV] = JSON.stringify(runtime.additionalDirectories);
49163
49639
  }
49164
49640
  function resolveRuntimeOverrideApprovalMode(runtime) {
49165
49641
  if (runtime.sessionApprovalModeOverride) {
@@ -49341,7 +49817,7 @@ var ShellActivityIndicator = class {
49341
49817
  this.label = label;
49342
49818
  }
49343
49819
  start() {
49344
- if (!import_node_process35.default.stdout.isTTY || this.interval) {
49820
+ if (!import_node_process36.default.stdout.isTTY || this.interval) {
49345
49821
  return;
49346
49822
  }
49347
49823
  this.activeLine = true;
@@ -49362,13 +49838,13 @@ var ShellActivityIndicator = class {
49362
49838
  }
49363
49839
  }
49364
49840
  suspend() {
49365
- if (!import_node_process35.default.stdout.isTTY) {
49841
+ if (!import_node_process36.default.stdout.isTTY) {
49366
49842
  return;
49367
49843
  }
49368
49844
  this.clear();
49369
49845
  }
49370
49846
  resume() {
49371
- if (!import_node_process35.default.stdout.isTTY || !this.interval) {
49847
+ if (!import_node_process36.default.stdout.isTTY || !this.interval) {
49372
49848
  return;
49373
49849
  }
49374
49850
  this.render();
@@ -49382,7 +49858,7 @@ var ShellActivityIndicator = class {
49382
49858
  this.activeLine = false;
49383
49859
  }
49384
49860
  render() {
49385
- if (!import_node_process35.default.stdout.isTTY) {
49861
+ if (!import_node_process36.default.stdout.isTTY) {
49386
49862
  return;
49387
49863
  }
49388
49864
  const frame = color(AMBER, SPINNER_FRAMES[this.animationTick % SPINNER_FRAMES.length]);
@@ -49390,15 +49866,15 @@ var ShellActivityIndicator = class {
49390
49866
  const dots = color(DIM, ELLIPSIS_FRAMES[this.animationTick % ELLIPSIS_FRAMES.length]);
49391
49867
  const raw = `${frame} ${status}${dots}`;
49392
49868
  this.clear();
49393
- (0, import_node_readline2.cursorTo)(import_node_process35.default.stdout, 0);
49394
- import_node_process35.default.stdout.write(raw);
49869
+ (0, import_node_readline2.cursorTo)(import_node_process36.default.stdout, 0);
49870
+ import_node_process36.default.stdout.write(raw);
49395
49871
  }
49396
49872
  clear() {
49397
- if (!import_node_process35.default.stdout.isTTY || !this.activeLine) {
49873
+ if (!import_node_process36.default.stdout.isTTY || !this.activeLine) {
49398
49874
  return;
49399
49875
  }
49400
- (0, import_node_readline2.cursorTo)(import_node_process35.default.stdout, 0);
49401
- (0, import_node_readline2.clearLine)(import_node_process35.default.stdout, 0);
49876
+ (0, import_node_readline2.cursorTo)(import_node_process36.default.stdout, 0);
49877
+ (0, import_node_readline2.clearLine)(import_node_process36.default.stdout, 0);
49402
49878
  }
49403
49879
  };
49404
49880
  var ShellExecutionTui = class {
@@ -49417,12 +49893,12 @@ var ShellExecutionTui = class {
49417
49893
  this.render();
49418
49894
  };
49419
49895
  start() {
49420
- if (!import_node_process35.default.stdout.isTTY) {
49896
+ if (!import_node_process36.default.stdout.isTTY) {
49421
49897
  return;
49422
49898
  }
49423
49899
  if (this.ownsScreen) {
49424
- import_node_process35.default.stdout.write(`${ALT_SCREEN_ENTER}${HIDE_CURSOR}${CLEAR_SCREEN}${HOME_CURSOR}`);
49425
- import_node_process35.default.stdout.on("resize", this.handleResize);
49900
+ import_node_process36.default.stdout.write(`${ALT_SCREEN_ENTER}${HIDE_CURSOR}${CLEAR_SCREEN}${HOME_CURSOR}`);
49901
+ import_node_process36.default.stdout.on("resize", this.handleResize);
49426
49902
  }
49427
49903
  this.render();
49428
49904
  this.interval = setInterval(() => {
@@ -49436,12 +49912,12 @@ var ShellExecutionTui = class {
49436
49912
  clearInterval(this.interval);
49437
49913
  this.interval = null;
49438
49914
  }
49439
- if (!import_node_process35.default.stdout.isTTY) {
49915
+ if (!import_node_process36.default.stdout.isTTY) {
49440
49916
  return;
49441
49917
  }
49442
49918
  if (this.ownsScreen) {
49443
- import_node_process35.default.stdout.off("resize", this.handleResize);
49444
- import_node_process35.default.stdout.write(`${SHOW_CURSOR}${ALT_SCREEN_EXIT}`);
49919
+ import_node_process36.default.stdout.off("resize", this.handleResize);
49920
+ import_node_process36.default.stdout.write(`${SHOW_CURSOR}${ALT_SCREEN_EXIT}`);
49445
49921
  }
49446
49922
  }
49447
49923
  updateActivity(label) {
@@ -49462,11 +49938,11 @@ var ShellExecutionTui = class {
49462
49938
  this.render();
49463
49939
  }
49464
49940
  render() {
49465
- if (!import_node_process35.default.stdout.isTTY) {
49941
+ if (!import_node_process36.default.stdout.isTTY) {
49466
49942
  return;
49467
49943
  }
49468
- const columns = Math.max(import_node_process35.default.stdout.columns ?? 100, 72);
49469
- const rows = Math.max(import_node_process35.default.stdout.rows ?? 36, 24);
49944
+ const columns = Math.max(import_node_process36.default.stdout.columns ?? 100, 72);
49945
+ const rows = Math.max(import_node_process36.default.stdout.rows ?? 36, 24);
49470
49946
  const headerLines = [
49471
49947
  color(BOLD, "Kimbho Execution"),
49472
49948
  color(DIM, `session ${shortenMiddle(this.board.sessionId, Math.max(20, columns - 12))}`),
@@ -49477,6 +49953,10 @@ var ShellExecutionTui = class {
49477
49953
  const footerLines = [
49478
49954
  "",
49479
49955
  `${color(AMBER, SPINNER_FRAMES[this.animationTick % SPINNER_FRAMES.length])} ${renderShimmeringLabel(this.activityLabel, this.animationTick)}${color(DIM, ELLIPSIS_FRAMES[this.animationTick % ELLIPSIS_FRAMES.length])} `,
49956
+ ...this.board.approvals > 0 ? [
49957
+ color(DIM, renderApprovalCommandHint()),
49958
+ color(DIM, renderApprovalShortcutHint(this.board.approvals))
49959
+ ] : [],
49480
49960
  color(DIM, "Ctrl+C pauses the run and returns to the shell. A concise summary prints after the run exits.")
49481
49961
  ];
49482
49962
  const chromeLines = headerLines.length + boardLines.length + footerLines.length + 1;
@@ -49494,7 +49974,7 @@ var ShellExecutionTui = class {
49494
49974
  while (paddedLines.length < rows) {
49495
49975
  paddedLines.push("");
49496
49976
  }
49497
- import_node_process35.default.stdout.write(`${CLEAR_SCREEN}${HOME_CURSOR}${paddedLines.join("\n")}`);
49977
+ import_node_process36.default.stdout.write(`${CLEAR_SCREEN}${HOME_CURSOR}${paddedLines.join("\n")}`);
49498
49978
  }
49499
49979
  };
49500
49980
  function renderExecutionTelemetry(telemetry, startedAt) {
@@ -49631,6 +50111,8 @@ function renderBanner() {
49631
50111
  }
49632
50112
  async function getShellSessionState(cwd, focusRole, runtime) {
49633
50113
  const config2 = await loadConfig(cwd);
50114
+ const latestSession = await loadLatestSession(cwd).catch(() => null);
50115
+ const pendingApprovals = latestSession?.pendingApprovals ?? [];
49634
50116
  if (!config2) {
49635
50117
  return {
49636
50118
  focusRole,
@@ -49642,7 +50124,8 @@ async function getShellSessionState(cwd, focusRole, runtime) {
49642
50124
  approvalMode: "manual",
49643
50125
  sandboxMode: "workspace-write",
49644
50126
  stackPreset: "next-prisma-postgres",
49645
- configured: false
50127
+ configured: false,
50128
+ pendingApprovals
49646
50129
  };
49647
50130
  }
49648
50131
  const focusSettings = config2.brains[focusRole];
@@ -49657,7 +50140,8 @@ async function getShellSessionState(cwd, focusRole, runtime) {
49657
50140
  approvalMode: runtime?.sessionApprovalModeOverride ? `${runtime.sessionApprovalModeOverride} (session override)` : config2.approvalMode,
49658
50141
  sandboxMode: runtime?.sessionSandboxModeOverride ? `${runtime.sessionSandboxModeOverride} (session override)` : config2.sandboxMode,
49659
50142
  stackPreset: config2.stackPresets[0] ?? "none",
49660
- configured: true
50143
+ configured: true,
50144
+ pendingApprovals
49661
50145
  };
49662
50146
  }
49663
50147
  function renderCardLine(label, value) {
@@ -49746,8 +50230,8 @@ function renderHelp() {
49746
50230
  "/permissions sandbox <mode> Set read-only, workspace-write, or full.",
49747
50231
  "/permissions trust <path> Add a trusted directory.",
49748
50232
  "/permissions untrust <path> Remove a trusted directory.",
49749
- "/approve [id] Approve a pending risky action and continue.",
49750
- "/approve-all [full-auto|full] Approve pending actions and optionally stop future prompts in this shell.",
50233
+ "/approve [id] Approve a pending risky action and continue once.",
50234
+ "/approve-all [auto|full-auto|full|once] Approve pending actions. Default: auto for the rest of this shell.",
49751
50235
  "/deny [id] Deny a pending risky action.",
49752
50236
  "",
49753
50237
  `${color(BOLD, "Memory")}`,
@@ -49809,6 +50293,10 @@ function renderStartupCard(cwd, state) {
49809
50293
  renderCardLine("approval", state.approvalMode),
49810
50294
  renderCardLine("sandbox", state.sandboxMode),
49811
50295
  renderCardLine("preset", state.stackPreset),
50296
+ ...state.pendingApprovals.length > 0 ? [
50297
+ renderCardLine("pending approvals", String(state.pendingApprovals.length)),
50298
+ renderCardLine("next", "select 1 approve once | 2 approve all | 3 deny")
50299
+ ] : [],
49812
50300
  renderCardLine("shortcuts", "/ask /run /model /permissions /memory /mcp /quit")
49813
50301
  ];
49814
50302
  if (!state.configured) {
@@ -49850,9 +50338,83 @@ function renderShellRuntimeOverview(runtime) {
49850
50338
  return lines;
49851
50339
  }
49852
50340
  function formatPrompt(state) {
50341
+ if (state.pendingApprovals.length > 0) {
50342
+ return state.pendingApprovals.length > 1 ? `${color(AMBER, "select approvals")} ${color(DIM, "[1 current | 2 current+future | 3 deny]")} > ` : `${color(AMBER, "select approval")} ${color(DIM, "[1 approve | 2 all | 3 deny]")} > `;
50343
+ }
49853
50344
  const model = state.focusModel === "not set" ? "unconfigured" : shortenMiddle(state.focusModel, 18);
49854
50345
  return `${color(AMBER, "kimbho")} ${color(DIM, `[${state.focusRole}:${model}]`)} > `;
49855
50346
  }
50347
+ async function readSelectionPrompt(prompt) {
50348
+ if (!import_node_process36.default.stdin.isTTY || !import_node_process36.default.stdout.isTTY) {
50349
+ return "";
50350
+ }
50351
+ return new Promise((resolve) => {
50352
+ const stdin = import_node_process36.default.stdin;
50353
+ const stdout = import_node_process36.default.stdout;
50354
+ const previousRawMode = stdin.isRaw;
50355
+ let buffer = "";
50356
+ const redraw = () => {
50357
+ (0, import_node_readline2.cursorTo)(stdout, 0);
50358
+ (0, import_node_readline2.clearLine)(stdout, 0);
50359
+ stdout.write(`${prompt}${buffer}`);
50360
+ };
50361
+ const cleanup = () => {
50362
+ stdin.off("keypress", onKeypress);
50363
+ stdin.setRawMode?.(Boolean(previousRawMode));
50364
+ };
50365
+ const finish = (value, options = {}) => {
50366
+ cleanup();
50367
+ if (options.printNewline ?? true) {
50368
+ stdout.write("\n");
50369
+ }
50370
+ resolve(value);
50371
+ };
50372
+ const onKeypress = (character, key) => {
50373
+ if (key.ctrl && key.name === "c") {
50374
+ finish("__kimbho_sigint__");
50375
+ return;
50376
+ }
50377
+ if (buffer.length === 0 && (character === "1" || character === "2" || character === "3")) {
50378
+ stdout.write(`${character}
50379
+ `);
50380
+ finish(character, {
50381
+ printNewline: false
50382
+ });
50383
+ return;
50384
+ }
50385
+ if (key.name === "return" || key.name === "enter") {
50386
+ finish(buffer.trim());
50387
+ return;
50388
+ }
50389
+ if (key.name === "backspace") {
50390
+ buffer = buffer.slice(0, -1);
50391
+ redraw();
50392
+ return;
50393
+ }
50394
+ if (key.name === "escape") {
50395
+ buffer = "";
50396
+ redraw();
50397
+ return;
50398
+ }
50399
+ if (key.ctrl || key.meta || !character || key.name === "tab") {
50400
+ return;
50401
+ }
50402
+ buffer += character;
50403
+ redraw();
50404
+ };
50405
+ (0, import_node_readline2.emitKeypressEvents)(stdin);
50406
+ stdin.setRawMode?.(true);
50407
+ stdout.write(prompt);
50408
+ stdin.on("keypress", onKeypress);
50409
+ });
50410
+ }
50411
+ async function readShellInput(readline, state) {
50412
+ const prompt = formatPrompt(state);
50413
+ if (state.pendingApprovals.length > 0) {
50414
+ return readSelectionPrompt(prompt);
50415
+ }
50416
+ return readline.question(prompt);
50417
+ }
49856
50418
  function printHeader(cwd, state) {
49857
50419
  console.log(renderBanner());
49858
50420
  console.log(color(DIM, "Terminal-native coding agent"));
@@ -49876,8 +50438,8 @@ function appendShellLog(runtime, value) {
49876
50438
  }
49877
50439
  }
49878
50440
  function renderShellDashboard(cwd, state, runtime) {
49879
- const columns = Math.max(import_node_process35.default.stdout.columns ?? 100, 76);
49880
- const rows = Math.max(import_node_process35.default.stdout.rows ?? 30, 20);
50441
+ const columns = Math.max(import_node_process36.default.stdout.columns ?? 100, 76);
50442
+ const rows = Math.max(import_node_process36.default.stdout.rows ?? 30, 20);
49881
50443
  const lines = [
49882
50444
  `${color(BOLD, "Kimbho CLI")} ${color(DIM, `(v${KIMBHO_VERSION})`)}`,
49883
50445
  color(DIM, `focus ${state.focusRole} | model ${shortenMiddle(state.focusModel, 28)} | provider ${state.providerId}`),
@@ -49900,6 +50462,16 @@ function renderShellDashboard(cwd, state, runtime) {
49900
50462
  lines.push(`\u2022 ${shortenMiddle(runtime.pendingHookElicitation.question, Math.max(24, columns - 10))}`);
49901
50463
  lines.push(color(DIM, "next: /answer <text> or /skip"));
49902
50464
  }
50465
+ if (state.pendingApprovals.length > 0) {
50466
+ lines.push("");
50467
+ lines.push(color(BOLD, state.pendingApprovals.length === 1 ? "Pending Approval" : "Pending Approvals"));
50468
+ lines.push(...renderPendingApprovalLines(
50469
+ state.pendingApprovals.slice(0, 3),
50470
+ Math.max(32, columns - 18)
50471
+ ));
50472
+ lines.push(color(DIM, renderApprovalCommandHint()));
50473
+ lines.push(color(DIM, renderApprovalShortcutHint(state.pendingApprovals.length)));
50474
+ }
49903
50475
  if (runtime.activeExecution) {
49904
50476
  lines.push("");
49905
50477
  lines.push(color(BOLD, "Active Execution"));
@@ -49921,9 +50493,10 @@ function renderShellDashboard(cwd, state, runtime) {
49921
50493
  }
49922
50494
  lines.push("");
49923
50495
  lines.push(color(BOLD, "Recent Output"));
50496
+ const footerActionLabel = runtime.pendingRunProposal ? "Direct request to act | /ask chat | /run approve | /run revise | /status | /quit" : "Direct request to act | /ask chat | /run <goal> | /queue list | /status | /quit";
49924
50497
  const footerLines = [
49925
50498
  "",
49926
- color(DIM, "Direct request to act | /ask chat | /run approve | /queue list | /status | /quit")
50499
+ color(DIM, footerActionLabel)
49927
50500
  ];
49928
50501
  const activityBudget = Math.max(6, rows - lines.length - footerLines.length - 2);
49929
50502
  const activity = runtime.shellLog.slice(-activityBudget);
@@ -49942,23 +50515,54 @@ function renderShellDashboard(cwd, state, runtime) {
49942
50515
  return `${CLEAR_SCREEN}${HOME_CURSOR}${frame.join("\n")}
49943
50516
  `;
49944
50517
  }
50518
+ function renderApprovalCommandHint() {
50519
+ return "next: /approve once, /approve-all to stop future prompts in this shell, /deny to stop";
50520
+ }
50521
+ function renderApprovalShortcutHint(pendingCount = 1) {
50522
+ return pendingCount > 1 ? "choices: 1 approve current set | 2 approve current + future for this shell | 3 deny current set" : "choices: 1 approve once | 2 approve all for this shell | 3 deny";
50523
+ }
50524
+ function summarizeApprovalInput(input) {
50525
+ if (typeof input.command === "string" && input.command.trim().length > 0) {
50526
+ return shortenMiddle(input.command.trim(), 90);
50527
+ }
50528
+ if (typeof input.path === "string" && input.path.trim().length > 0) {
50529
+ return shortenMiddle(input.path.trim(), 90);
50530
+ }
50531
+ if (typeof input.url === "string" && input.url.trim().length > 0) {
50532
+ return shortenMiddle(input.url.trim(), 90);
50533
+ }
50534
+ const serialized = Object.entries(input).slice(0, 3).map(([key, value]) => `${key}=${String(value)}`).join(" ");
50535
+ return serialized.length > 0 ? shortenMiddle(serialized, 90) : null;
50536
+ }
50537
+ function renderPendingApprovalLines(approvals, maxReasonWidth = 110) {
50538
+ const lines = [];
50539
+ for (const approval of approvals) {
50540
+ lines.push(`\u2022 ${approval.toolId} for ${approval.taskId} (${approval.permission})`);
50541
+ lines.push(` reason: ${shortenMiddle(approval.reason, maxReasonWidth)}`);
50542
+ const request = summarizeApprovalInput(approval.input);
50543
+ if (request) {
50544
+ lines.push(` request: ${request}`);
50545
+ }
50546
+ }
50547
+ return lines;
50548
+ }
49945
50549
  var ShellDashboardTui = class {
49946
50550
  constructor(runtime) {
49947
50551
  this.runtime = runtime;
49948
50552
  }
49949
- cwd = import_node_process35.default.cwd();
50553
+ cwd = import_node_process36.default.cwd();
49950
50554
  state = null;
49951
50555
  handleResize = () => {
49952
50556
  this.render();
49953
50557
  };
49954
50558
  start(cwd, state) {
49955
- if (!import_node_process35.default.stdout.isTTY) {
50559
+ if (!import_node_process36.default.stdout.isTTY) {
49956
50560
  return;
49957
50561
  }
49958
50562
  this.cwd = cwd;
49959
50563
  this.state = state;
49960
- import_node_process35.default.stdout.write(`${ALT_SCREEN_ENTER}${HIDE_CURSOR}`);
49961
- import_node_process35.default.stdout.on("resize", this.handleResize);
50564
+ import_node_process36.default.stdout.write(`${ALT_SCREEN_ENTER}${HIDE_CURSOR}`);
50565
+ import_node_process36.default.stdout.on("resize", this.handleResize);
49962
50566
  this.render();
49963
50567
  }
49964
50568
  update(cwd, state) {
@@ -49967,17 +50571,17 @@ var ShellDashboardTui = class {
49967
50571
  this.render();
49968
50572
  }
49969
50573
  render() {
49970
- if (!import_node_process35.default.stdout.isTTY || !this.state || this.runtime.activeExecution) {
50574
+ if (!import_node_process36.default.stdout.isTTY || !this.state || this.runtime.activeExecution) {
49971
50575
  return;
49972
50576
  }
49973
- import_node_process35.default.stdout.write(renderShellDashboard(this.cwd, this.state, this.runtime));
50577
+ import_node_process36.default.stdout.write(renderShellDashboard(this.cwd, this.state, this.runtime));
49974
50578
  }
49975
50579
  stop() {
49976
- if (!import_node_process35.default.stdout.isTTY) {
50580
+ if (!import_node_process36.default.stdout.isTTY) {
49977
50581
  return;
49978
50582
  }
49979
- import_node_process35.default.stdout.off("resize", this.handleResize);
49980
- import_node_process35.default.stdout.write(`${SHOW_CURSOR}${ALT_SCREEN_EXIT}`);
50583
+ import_node_process36.default.stdout.off("resize", this.handleResize);
50584
+ import_node_process36.default.stdout.write(`${SHOW_CURSOR}${ALT_SCREEN_EXIT}`);
49981
50585
  }
49982
50586
  };
49983
50587
  function renderInlineMarkdown(value) {
@@ -50414,7 +51018,7 @@ function renderShellSessionSummary(snapshot, planPath, sessionPath) {
50414
51018
  snapshot.events.flatMap((event) => [
50415
51019
  ...event.artifacts,
50416
51020
  ...event.toolResults.flatMap((toolResult) => toolResult.artifacts)
50417
- ]).filter((artifact) => !artifact.includes(`${import_node_path33.default.sep}.kimbho${import_node_path33.default.sep}`))
51021
+ ]).filter((artifact) => !artifact.includes(`${import_node_path34.default.sep}.kimbho${import_node_path34.default.sep}`))
50418
51022
  ));
50419
51023
  const visibleNotes = snapshot.notes.filter(
50420
51024
  (note) => /limit reached|approval|blocked|failed|error|conflict|denied/i.test(note)
@@ -50441,9 +51045,7 @@ function renderShellSessionSummary(snapshot, planPath, sessionPath) {
50441
51045
  if (snapshot.pendingApprovals.length > 0) {
50442
51046
  lines.push("");
50443
51047
  lines.push(color(BOLD, "Waiting For Approval"));
50444
- for (const approval of snapshot.pendingApprovals) {
50445
- lines.push(`\u2022 ${approval.reason}`);
50446
- }
51048
+ lines.push(...renderPendingApprovalLines(snapshot.pendingApprovals.slice(0, 4)));
50447
51049
  }
50448
51050
  if (visibleNotes.length > 0) {
50449
51051
  lines.push("");
@@ -50458,7 +51060,8 @@ function renderShellSessionSummary(snapshot, planPath, sessionPath) {
50458
51060
  }
50459
51061
  lines.push(color(DIM, `saved session: ${sessionPath}`));
50460
51062
  if (snapshot.pendingApprovals.length > 0) {
50461
- lines.push("next: /approve to continue, /deny to stop");
51063
+ lines.push(renderApprovalCommandHint());
51064
+ lines.push(color(DIM, renderApprovalShortcutHint(snapshot.pendingApprovals.length)));
50462
51065
  } else if (snapshot.status === "paused" || snapshot.status === "running" || snapshot.status === "ready") {
50463
51066
  lines.push("next: /resume to continue a paused run or start another request");
50464
51067
  } else if (snapshot.status === "blocked") {
@@ -50570,7 +51173,8 @@ function renderLiveExecutionEvent(event, board, startedAt, options = {}) {
50570
51173
  case "approval-requested":
50571
51174
  return [
50572
51175
  `${color(AMBER, "Approval Needed")} ${event.approval.reason}`,
50573
- color(DIM, "next: /approve to continue, /deny to stop, /approve-all full-auto to stop future prompts"),
51176
+ color(DIM, renderApprovalCommandHint()),
51177
+ color(DIM, renderApprovalShortcutHint(board.approvals)),
50574
51178
  ...progressLines
50575
51179
  ];
50576
51180
  case "approval-resolved":
@@ -50757,12 +51361,12 @@ function rewindConversation(runtime, role, turns) {
50757
51361
  return removed;
50758
51362
  }
50759
51363
  async function writeTextToClipboard(value) {
50760
- const candidates = import_node_process35.default.platform === "darwin" ? [
51364
+ const candidates = import_node_process36.default.platform === "darwin" ? [
50761
51365
  {
50762
51366
  command: "pbcopy",
50763
51367
  args: []
50764
51368
  }
50765
- ] : import_node_process35.default.platform === "win32" ? [
51369
+ ] : import_node_process36.default.platform === "win32" ? [
50766
51370
  {
50767
51371
  command: "clip",
50768
51372
  args: []
@@ -50810,7 +51414,7 @@ async function writeTextToClipboard(value) {
50810
51414
  }
50811
51415
  function createShellExportPath(cwd, role, kind) {
50812
51416
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
50813
- return import_node_path33.default.join(cwd, ".kimbho", "exports", `${kind}-${role}-${stamp}.md`);
51417
+ return import_node_path34.default.join(cwd, ".kimbho", "exports", `${kind}-${role}-${stamp}.md`);
50814
51418
  }
50815
51419
  function clearConversation(runtime, role) {
50816
51420
  runtime.conversations[role] = [];
@@ -50913,6 +51517,22 @@ async function handleChatPrompt(cwd, prompt, runtime) {
50913
51517
  maxCharsPerFile: 3e3
50914
51518
  });
50915
51519
  const skillContext = await resolveActivatedSkillContext(cwd, hydrated.prompt);
51520
+ const workspaceInfoPrompt = looksLikeWorkspaceInfoPrompt(hydrated.prompt);
51521
+ let workspaceOverview = null;
51522
+ if (workspaceInfoPrompt) {
51523
+ const existingOverview = await readMarkdownIfExists(import_node_path34.default.join(cwd, "kimbho_init.md"));
51524
+ if (existingOverview) {
51525
+ workspaceOverview = existingOverview.slice(0, 6e3);
51526
+ } else {
51527
+ try {
51528
+ const generated = await generateProjectInitFile(cwd, "kimbho_init.md");
51529
+ const generatedOverview = await readMarkdownIfExists(generated.outputPath);
51530
+ workspaceOverview = generatedOverview?.slice(0, 6e3) ?? null;
51531
+ } catch {
51532
+ workspaceOverview = null;
51533
+ }
51534
+ }
51535
+ }
50916
51536
  const compactionPath = await compactConversationIfNeeded(cwd, runtime, runtime.focusRole);
50917
51537
  if (compactionPath) {
50918
51538
  console.log(color(DIM, `[compacting] condensed ${runtime.focusRole} chat context -> ${compactionPath}`));
@@ -50928,27 +51548,34 @@ async function handleChatPrompt(cwd, prompt, runtime) {
50928
51548
  let result;
50929
51549
  const activity = new ShellActivityIndicator(pickIdleStatusLabel(prompt));
50930
51550
  activity.start();
51551
+ const systemPromptSections = [
51552
+ brain.settings.promptPreamble,
51553
+ adaptiveMemory.chatSummary.length > 0 ? `Adaptive memory:
51554
+ ${adaptiveMemory.chatSummary}` : null,
51555
+ memoryContext.length > 0 ? [
51556
+ "Workspace memory:",
51557
+ ...memoryContext.map((record2) => `File: ${record2.filePath}
51558
+ ${record2.content}`)
51559
+ ].join("\n\n") : null,
51560
+ workspaceOverview ? [
51561
+ "Workspace question handling:",
51562
+ "The user is asking about the current repository. Ground the answer in the workspace context below and do not reply with a generic assistant introduction.",
51563
+ `Workspace overview:
51564
+ ${workspaceOverview}`
51565
+ ].join("\n\n") : null,
51566
+ skillContext.systemPromptSections.length > 0 ? [
51567
+ "Active skill packs:",
51568
+ ...skillContext.systemPromptSections
51569
+ ].join("\n\n") : null,
51570
+ runtime.conversationSummaries[runtime.focusRole] ? `Compacted conversation summary:
51571
+ ${runtime.conversationSummaries[runtime.focusRole]}` : null
51572
+ ].filter((value) => Boolean(value));
50931
51573
  try {
50932
51574
  result = await brain.client.generateText({
50933
51575
  model: brain.model,
50934
51576
  messages,
50935
- ...brain.settings.promptPreamble || runtime.conversationSummaries[runtime.focusRole] ? {
50936
- systemPrompt: [
50937
- brain.settings.promptPreamble,
50938
- adaptiveMemory.chatSummary.length > 0 ? `Adaptive memory:
50939
- ${adaptiveMemory.chatSummary}` : null,
50940
- memoryContext.length > 0 ? [
50941
- "Workspace memory:",
50942
- ...memoryContext.map((record2) => `File: ${record2.filePath}
50943
- ${record2.content}`)
50944
- ].join("\n\n") : null,
50945
- skillContext.systemPromptSections.length > 0 ? [
50946
- "Active skill packs:",
50947
- ...skillContext.systemPromptSections
50948
- ].join("\n\n") : null,
50949
- runtime.conversationSummaries[runtime.focusRole] ? `Compacted conversation summary:
50950
- ${runtime.conversationSummaries[runtime.focusRole]}` : null
50951
- ].filter((value) => Boolean(value)).join("\n\n")
51577
+ ...systemPromptSections.length > 0 ? {
51578
+ systemPrompt: systemPromptSections.join("\n\n")
50952
51579
  } : {},
50953
51580
  ...typeof brain.settings.temperature === "number" ? {
50954
51581
  temperature: brain.settings.temperature
@@ -51079,7 +51706,7 @@ async function executePendingRunProposal(runtime) {
51079
51706
  resolveShellMaxAgentSteps(runtime),
51080
51707
  DEFAULT_MAX_REPAIR_ATTEMPTS2
51081
51708
  );
51082
- const tui = import_node_process35.default.stdout.isTTY ? new ShellExecutionTui(liveBoard, telemetry, startedAt, "starting", !runtime.dashboard) : null;
51709
+ const tui = import_node_process36.default.stdout.isTTY ? new ShellExecutionTui(liveBoard, telemetry, startedAt, "starting", !runtime.dashboard) : null;
51083
51710
  const activity = tui ? null : new ShellActivityIndicator("starting");
51084
51711
  if (tui) {
51085
51712
  tui.start();
@@ -51147,6 +51774,126 @@ async function executePendingRunProposal(runtime) {
51147
51774
  void drainQueuedWork(runtime);
51148
51775
  return request.cwd;
51149
51776
  }
51777
+ async function handleWorkspaceAnalysisPrompt(cwd, prompt, runtime) {
51778
+ const hydrated = await hydratePromptWithMcpResources(cwd, prompt);
51779
+ await recordAdaptiveTextObservation(cwd, hydrated.prompt, "chat");
51780
+ const skillAwareRequest = await preparePlanningRequest({
51781
+ goal: `Analyze the current repository and answer the user's question: ${hydrated.prompt}`,
51782
+ mode: "run",
51783
+ cwd,
51784
+ workspaceState: "existing",
51785
+ constraints: [
51786
+ "Read-only repository analysis only.",
51787
+ "Do not modify source files, install packages, or start development servers.",
51788
+ "Use multiple agents to inspect the workspace and synthesize the answer when helpful."
51789
+ ]
51790
+ });
51791
+ const request = skillAwareRequest.request;
51792
+ const plan = buildWorkspaceAnalysisPlan(request, hydrated.prompt);
51793
+ const planPath = await savePlan(plan, request.cwd);
51794
+ const orchestrator = new ExecutionOrchestrator();
51795
+ const initialSnapshot = orchestrator.createSessionSnapshot(
51796
+ orchestrator.buildEnvelope(request, plan)
51797
+ );
51798
+ const startedAt = Date.now();
51799
+ const telemetry = createExecutionTelemetry();
51800
+ const controller = new AbortController();
51801
+ runtime.activeExecution = {
51802
+ controller,
51803
+ label: hydrated.prompt
51804
+ };
51805
+ const liveBoard = createLiveRunBoard(
51806
+ initialSnapshot.id,
51807
+ hydrated.prompt,
51808
+ request,
51809
+ plan,
51810
+ resolveShellMaxAutoTasks(runtime),
51811
+ resolveShellMaxAgentSteps(runtime),
51812
+ DEFAULT_MAX_REPAIR_ATTEMPTS2
51813
+ );
51814
+ const tui = import_node_process36.default.stdout.isTTY ? new ShellExecutionTui(liveBoard, telemetry, startedAt, "analyzing", !runtime.dashboard) : null;
51815
+ const activity = tui ? null : new ShellActivityIndicator("analyzing");
51816
+ if (tui) {
51817
+ tui.start();
51818
+ tui.pushEvent(renderLiveExecutionEvent({
51819
+ type: "task-note",
51820
+ sessionId: initialSnapshot.id,
51821
+ message: "Read-only repository analysis session started."
51822
+ }, liveBoard, startedAt, {
51823
+ includeProgress: false
51824
+ }));
51825
+ } else {
51826
+ console.log(renderRunStartCard(liveBoard));
51827
+ console.log("");
51828
+ activity?.start();
51829
+ }
51830
+ let snapshot;
51831
+ try {
51832
+ snapshot = await orchestrator.continueSession(initialSnapshot, {
51833
+ maxAutoTasks: resolveShellMaxAutoTasks(runtime),
51834
+ maxAgentSteps: resolveShellMaxAgentSteps(runtime),
51835
+ maxRepairAttempts: DEFAULT_MAX_REPAIR_ATTEMPTS2,
51836
+ signal: controller.signal,
51837
+ onProgress: async (event) => {
51838
+ updateLiveRunBoard(liveBoard, event);
51839
+ if (event.type === "tool-started") {
51840
+ telemetry.toolCalls += 1;
51841
+ }
51842
+ if (event.type === "model-usage") {
51843
+ telemetry.modelCalls += 1;
51844
+ telemetry.inputTokens += event.usage?.inputTokens ?? 0;
51845
+ telemetry.outputTokens += event.usage?.outputTokens ?? 0;
51846
+ }
51847
+ if (tui) {
51848
+ tui.updateActivity(statusLabelForEvent(event));
51849
+ tui.pushEvent(renderLiveExecutionEvent(event, liveBoard, startedAt, {
51850
+ includeProgress: false
51851
+ }));
51852
+ } else {
51853
+ activity?.update(statusLabelForEvent(event));
51854
+ activity?.suspend();
51855
+ for (const line of renderLiveExecutionEvent(event, liveBoard, startedAt)) {
51856
+ console.log(line);
51857
+ }
51858
+ activity?.resume();
51859
+ }
51860
+ }
51861
+ });
51862
+ } finally {
51863
+ tui?.stop();
51864
+ activity?.stop();
51865
+ runtime.activeExecution = null;
51866
+ }
51867
+ const sessionPath = await saveSession(snapshot, request.cwd);
51868
+ await recordAdaptiveSessionOutcome(request.cwd, snapshot);
51869
+ runtime.currentCwd = request.cwd;
51870
+ const answer = await synthesizeWorkspaceAnalysisAnswer(
51871
+ request.cwd,
51872
+ hydrated.prompt,
51873
+ runtime.focusRole,
51874
+ snapshot
51875
+ );
51876
+ const conversation = trimConversation([
51877
+ ...getConversation(runtime, runtime.focusRole),
51878
+ {
51879
+ role: "user",
51880
+ content: hydrated.prompt
51881
+ },
51882
+ {
51883
+ role: "assistant",
51884
+ content: answer
51885
+ }
51886
+ ]);
51887
+ runtime.conversations[runtime.focusRole] = conversation;
51888
+ console.log("");
51889
+ console.log(color(DIM, `elapsed: ${((Date.now() - startedAt) / 1e3).toFixed(1)}s`));
51890
+ console.log(color(DIM, renderExecutionTelemetry(telemetry, startedAt)));
51891
+ console.log(renderShellSessionSummary(snapshot, planPath, sessionPath));
51892
+ console.log("");
51893
+ console.log(color(DIM, "[analysis answer]"));
51894
+ console.log(renderTerminalMarkdown(answer));
51895
+ void drainQueuedWork(runtime);
51896
+ }
51150
51897
  async function resumeGoalExecution(cwd, runtime) {
51151
51898
  const session = await loadLatestSession(cwd);
51152
51899
  if (!session) {
@@ -51169,7 +51916,7 @@ async function resumeGoalExecution(cwd, runtime) {
51169
51916
  controller,
51170
51917
  label: session.id
51171
51918
  };
51172
- const tui = import_node_process35.default.stdout.isTTY ? new ShellExecutionTui(liveBoard, telemetry, startedAt, "resuming", !runtime.dashboard) : null;
51919
+ const tui = import_node_process36.default.stdout.isTTY ? new ShellExecutionTui(liveBoard, telemetry, startedAt, "resuming", !runtime.dashboard) : null;
51173
51920
  const activity = tui ? null : new ShellActivityIndicator("resuming");
51174
51921
  if (tui) {
51175
51922
  tui.start();
@@ -51285,7 +52032,7 @@ async function resolvePendingApproval(cwd, runtime, decision, approvalId, option
51285
52032
  controller,
51286
52033
  label: approvals.length === 1 ? `${session.id}:${approvals[0].id}` : `${session.id}:batch-approval`
51287
52034
  };
51288
- const tui = import_node_process35.default.stdout.isTTY ? new ShellExecutionTui(liveBoard, telemetry, startedAt, decision === "approve" ? "approving" : "denying", !runtime.dashboard) : null;
52035
+ const tui = import_node_process36.default.stdout.isTTY ? new ShellExecutionTui(liveBoard, telemetry, startedAt, decision === "approve" ? "approving" : "denying", !runtime.dashboard) : null;
51289
52036
  const activity = tui ? null : new ShellActivityIndicator(decision === "approve" ? "approving" : "denying");
51290
52037
  if (tui) {
51291
52038
  tui.start();
@@ -51349,16 +52096,74 @@ async function resolvePendingApproval(cwd, runtime, decision, approvalId, option
51349
52096
  void drainQueuedWork(runtime);
51350
52097
  }
51351
52098
  async function applyApproveAllPreset(cwd, runtime, rawPreset) {
51352
- if (!rawPreset) {
51353
- return false;
52099
+ const normalized = rawPreset?.trim().toLowerCase();
52100
+ if (!normalized) {
52101
+ runtime.sessionApprovalModeOverride = "auto";
52102
+ syncShellRuntimeOverrides(runtime);
52103
+ console.log("Shell permission override: auto approvals for the rest of this shell.");
52104
+ await recordAdaptiveTextObservation(cwd, "User approval preference: auto approvals for the rest of this shell.", "approval");
52105
+ const session2 = await loadLatestSession(cwd);
52106
+ return Boolean(session2 && session2.pendingApprovals.length > 0);
52107
+ }
52108
+ if (normalized === "once" || normalized === "current") {
52109
+ const session2 = await loadLatestSession(cwd);
52110
+ if (!session2 || session2.pendingApprovals.length === 0) {
52111
+ return false;
52112
+ }
52113
+ console.log("Approving all currently pending actions once. Future actions will keep the current approval mode.");
52114
+ return true;
51354
52115
  }
51355
- const preset = resolvePermissionPreset(rawPreset);
52116
+ const preset = resolvePermissionPreset(rawPreset ?? "auto");
51356
52117
  setShellSessionPermissions(runtime, preset);
51357
52118
  console.log(`Shell permission override: ${preset.label}`);
51358
52119
  await recordAdaptiveTextObservation(cwd, `User approval preference: ${preset.label}`, "approval");
51359
52120
  const session = await loadLatestSession(cwd);
51360
52121
  return Boolean(session && session.pendingApprovals.length > 0);
51361
52122
  }
52123
+ async function tryResolveApprovalShortcut(cwd, runtime, input) {
52124
+ if (input !== "1" && input !== "2" && input !== "3") {
52125
+ return false;
52126
+ }
52127
+ const session = await loadLatestSession(cwd);
52128
+ if (!session || session.pendingApprovals.length === 0) {
52129
+ return false;
52130
+ }
52131
+ if (input === "1") {
52132
+ await resolvePendingApproval(
52133
+ cwd,
52134
+ runtime,
52135
+ "approve",
52136
+ session.pendingApprovals.length > 1 ? "all" : void 0,
52137
+ {
52138
+ allowAll: session.pendingApprovals.length > 1
52139
+ }
52140
+ );
52141
+ return true;
52142
+ }
52143
+ if (input === "2") {
52144
+ await applyApproveAllPreset(cwd, runtime);
52145
+ await resolvePendingApproval(
52146
+ cwd,
52147
+ runtime,
52148
+ "approve",
52149
+ "all",
52150
+ {
52151
+ allowAll: true
52152
+ }
52153
+ );
52154
+ return true;
52155
+ }
52156
+ await resolvePendingApproval(
52157
+ cwd,
52158
+ runtime,
52159
+ "deny",
52160
+ session.pendingApprovals.length > 1 ? "all" : void 0,
52161
+ {
52162
+ allowAll: session.pendingApprovals.length > 1
52163
+ }
52164
+ );
52165
+ return true;
52166
+ }
51362
52167
  async function printLatestPlanSummary(cwd) {
51363
52168
  const plan = await loadLatestPlan(cwd);
51364
52169
  if (!plan) {
@@ -51505,7 +52310,7 @@ async function handlePermissionsCommand(cwd, tokens, runtime) {
51505
52310
  if (!target) {
51506
52311
  throw new Error(`Usage: /permissions ${subcommand} <path>`);
51507
52312
  }
51508
- const normalizedTarget = import_node_path33.default.resolve(cwd, target);
52313
+ const normalizedTarget = import_node_path34.default.resolve(cwd, target);
51509
52314
  const trustedDirectories = subcommand === "trust" ? Array.from(/* @__PURE__ */ new Set([
51510
52315
  ...effective.trustedDirectories,
51511
52316
  normalizedTarget
@@ -51621,7 +52426,7 @@ async function handleExportCommand(cwd, tokens, runtime) {
51621
52426
  );
51622
52427
  const destinationToken = knownKind ? tokens[2] : tokens[1];
51623
52428
  const outputPath = await writeMarkdownFile(
51624
- destinationToken ? import_node_path33.default.resolve(cwd, destinationToken) : createShellExportPath(cwd, runtime.focusRole, knownKind ? kindToken : "context"),
52429
+ destinationToken ? import_node_path34.default.resolve(cwd, destinationToken) : createShellExportPath(cwd, runtime.focusRole, knownKind ? kindToken : "context"),
51625
52430
  payload.content
51626
52431
  );
51627
52432
  console.log(`Exported ${payload.label} -> ${outputPath}`);
@@ -51631,7 +52436,7 @@ async function handleAddDirCommand(cwd, tokens, runtime) {
51631
52436
  if (!target) {
51632
52437
  throw new Error("Usage: /add-dir <path>");
51633
52438
  }
51634
- const resolved = import_node_path33.default.resolve(cwd, target);
52439
+ const resolved = import_node_path34.default.resolve(cwd, target);
51635
52440
  if (!runtime.additionalDirectories.includes(resolved)) {
51636
52441
  runtime.additionalDirectories.push(resolved);
51637
52442
  runtime.additionalDirectories.sort((left, right) => left.localeCompare(right));
@@ -51708,7 +52513,7 @@ async function handleHooksCommand(cwd, tokens) {
51708
52513
  console.log(lines.join("\n"));
51709
52514
  }
51710
52515
  function shellHookSessionId(runtime, cwd) {
51711
- return runtime.pendingRunProposal?.snapshot.id ?? `shell-${import_node_process35.default.pid}-${import_node_path33.default.basename(cwd) || "workspace"}`;
52516
+ return runtime.pendingRunProposal?.snapshot.id ?? `shell-${import_node_process36.default.pid}-${import_node_path34.default.basename(cwd) || "workspace"}`;
51712
52517
  }
51713
52518
  async function createShellHookRunner(cwd, config2) {
51714
52519
  const resolvedConfig = config2 ?? await loadConfig(cwd).catch(() => null);
@@ -51892,7 +52697,7 @@ async function handleMemoryCommand(cwd, tokens) {
51892
52697
  }
51893
52698
  let filePath;
51894
52699
  if (scope === "init") {
51895
- filePath = import_node_path33.default.join(cwd, "kimbho_init.md");
52700
+ filePath = import_node_path34.default.join(cwd, "kimbho_init.md");
51896
52701
  } else if (scope === "project") {
51897
52702
  filePath = resolveProjectMemoryPath(cwd);
51898
52703
  } else if (scope === "user") {
@@ -51902,7 +52707,7 @@ async function handleMemoryCommand(cwd, tokens) {
51902
52707
  if (!agentId) {
51903
52708
  throw new Error("Usage: /memory show agent <agent-id>");
51904
52709
  }
51905
- filePath = import_node_path33.default.join(resolveAgentMemoryDir(cwd), `${agentId}.md`);
52710
+ filePath = import_node_path34.default.join(resolveAgentMemoryDir(cwd), `${agentId}.md`);
51906
52711
  } else {
51907
52712
  throw new Error("Usage: /memory show <init|project|user|agent> [id]");
51908
52713
  }
@@ -52511,7 +53316,7 @@ async function printProviderList(cwd, focusRole) {
52511
53316
  const activeProviderId = config2.brains[focusRole].providerId;
52512
53317
  for (const provider of config2.providers) {
52513
53318
  const marker = provider.id === activeProviderId ? "*" : " ";
52514
- const envState = provider.apiKeyEnv ? import_node_process35.default.env[provider.apiKeyEnv] ? "present" : `missing ${provider.apiKeyEnv}` : "no key required";
53319
+ const envState = provider.apiKeyEnv ? import_node_process36.default.env[provider.apiKeyEnv] ? "present" : `missing ${provider.apiKeyEnv}` : "no key required";
52515
53320
  console.log(`${marker} ${provider.id}`);
52516
53321
  console.log(` label: ${provider.label ?? "-"}`);
52517
53322
  console.log(` driver: ${provider.driver}`);
@@ -52848,6 +53653,10 @@ async function startPendingRunExecution(cwd, runtime) {
52848
53653
  console.log(color(DIM, "Waiting on a hook question before starting the plan."));
52849
53654
  return;
52850
53655
  }
53656
+ if (!proposal) {
53657
+ console.log("No pending run proposal. Start with a build/change request or /run <goal>.");
53658
+ return;
53659
+ }
52851
53660
  if (proposal && planRequiresOperatorReview(proposal.plan)) {
52852
53661
  await emitShellHookEvent(
52853
53662
  proposal.request.cwd,
@@ -52864,6 +53673,15 @@ async function startPendingRunExecution(cwd, runtime) {
52864
53673
  }
52865
53674
  );
52866
53675
  }
53676
+ const confirmedProposal = runtime.pendingRunProposal;
53677
+ if (runtime.pendingHookElicitation) {
53678
+ console.log(color(DIM, "Waiting on a hook question before starting the plan."));
53679
+ return;
53680
+ }
53681
+ if (!confirmedProposal) {
53682
+ console.log(color(DIM, "Pending plan was cleared before execution could start."));
53683
+ return;
53684
+ }
52867
53685
  console.log(color(DIM, "Starting the approved plan..."));
52868
53686
  void executePendingRunProposal(runtime).catch((error2) => {
52869
53687
  console.error(error2 instanceof Error ? error2.message : String(error2));
@@ -52953,6 +53771,9 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
52953
53771
  await resolvePendingHookElicitation(cwd, runtime, "answer", trimmed);
52954
53772
  return cwd;
52955
53773
  }
53774
+ if (!isSlashCommand && !runtime.pendingRunProposal && await tryResolveApprovalShortcut(cwd, runtime, trimmed)) {
53775
+ return cwd;
53776
+ }
52956
53777
  if (head.startsWith("mcp__")) {
52957
53778
  const parts = head.split("__").filter((part) => part.length > 0);
52958
53779
  if (parts.length < 3) {
@@ -52971,6 +53792,14 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
52971
53792
  return cwd;
52972
53793
  }
52973
53794
  if (!firstToken?.startsWith("/") && !TOP_LEVEL_COMMANDS.has(head) && !head.startsWith("-")) {
53795
+ if (looksLikeWorkspaceInfoPrompt(trimmed)) {
53796
+ if (runtime.activeExecution || runtime.queueDrainPromise || runtime.pendingRunProposal) {
53797
+ queuePlannerRequest(cwd, `Analyze the current repository and answer: ${trimmed}`, runtime, "run");
53798
+ return cwd;
53799
+ }
53800
+ await handleWorkspaceAnalysisPrompt(cwd, trimmed, runtime);
53801
+ return cwd;
53802
+ }
52974
53803
  const intent = inferPromptIntent(trimmed);
52975
53804
  if (intent === "run") {
52976
53805
  if (runtime.activeExecution || runtime.queueDrainPromise || runtime.pendingRunProposal) {
@@ -53248,7 +54077,7 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
53248
54077
  await createPlanOnly(cwd, goal);
53249
54078
  return cwd;
53250
54079
  }
53251
- if (head === "resume") {
54080
+ if (head === "resume" || head === "continue") {
53252
54081
  queueResumeRequest(cwd, runtime);
53253
54082
  return cwd;
53254
54083
  }
@@ -53261,16 +54090,16 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
53261
54090
  }
53262
54091
  if (head === "approve-all") {
53263
54092
  const shouldResolvePending = await applyApproveAllPreset(cwd, runtime, tokens[1]?.trim());
53264
- if (tokens[1] && !shouldResolvePending) {
54093
+ if (!shouldResolvePending) {
53265
54094
  if (runtime.pendingRunProposal) {
53266
54095
  void startPendingRunExecution(cwd, runtime);
53267
54096
  return cwd;
53268
54097
  }
53269
- console.log("No pending approvals right now. Future actions in this shell will use the new permission mode.");
53270
- return cwd;
53271
- }
53272
- if (!shouldResolvePending && runtime.pendingRunProposal) {
53273
- void startPendingRunExecution(cwd, runtime);
54098
+ if (tokens[1]?.trim()) {
54099
+ console.log("No pending approvals right now. Future actions in this shell will use the new permission mode.");
54100
+ } else {
54101
+ console.log("No pending approvals right now. Future actions in this shell will use auto approvals.");
54102
+ }
53274
54103
  return cwd;
53275
54104
  }
53276
54105
  await resolvePendingApproval(
@@ -53286,6 +54115,27 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
53286
54115
  }
53287
54116
  if (head === "approve" || head === "deny") {
53288
54117
  const approvalId = tokens[1]?.trim();
54118
+ if (head === "approve" && approvalId === "all") {
54119
+ const shouldResolvePending = await applyApproveAllPreset(cwd, runtime);
54120
+ if (!shouldResolvePending) {
54121
+ if (runtime.pendingRunProposal) {
54122
+ void startPendingRunExecution(cwd, runtime);
54123
+ return cwd;
54124
+ }
54125
+ console.log("No pending approvals right now. Future actions in this shell will use auto approvals.");
54126
+ return cwd;
54127
+ }
54128
+ await resolvePendingApproval(
54129
+ cwd,
54130
+ runtime,
54131
+ "approve",
54132
+ "all",
54133
+ {
54134
+ allowAll: true
54135
+ }
54136
+ );
54137
+ return cwd;
54138
+ }
53289
54139
  if (!approvalId && runtime.pendingRunProposal) {
53290
54140
  if (head === "approve") {
53291
54141
  void startPendingRunExecution(cwd, runtime);
@@ -53316,9 +54166,9 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
53316
54166
  }
53317
54167
  async function runInteractiveShell(options) {
53318
54168
  const readline = (0, import_promises27.createInterface)({
53319
- input: import_node_process35.default.stdin,
53320
- output: import_node_process35.default.stdout,
53321
- terminal: Boolean(import_node_process35.default.stdin.isTTY && import_node_process35.default.stdout.isTTY)
54169
+ input: import_node_process36.default.stdin,
54170
+ output: import_node_process36.default.stdout,
54171
+ terminal: Boolean(import_node_process36.default.stdin.isTTY && import_node_process36.default.stdout.isTTY)
53322
54172
  });
53323
54173
  const runtime = {
53324
54174
  focusRole: "coder",
@@ -53350,7 +54200,7 @@ async function runInteractiveShell(options) {
53350
54200
  };
53351
54201
  let currentCwd = options.cwd;
53352
54202
  let closed = false;
53353
- const useDashboard = Boolean(import_node_process35.default.stdin.isTTY && import_node_process35.default.stdout.isTTY);
54203
+ const useDashboard = Boolean(import_node_process36.default.stdin.isTTY && import_node_process36.default.stdout.isTTY);
53354
54204
  const originalLog = console.log;
53355
54205
  const originalError = console.error;
53356
54206
  if (useDashboard) {
@@ -53366,7 +54216,7 @@ async function runInteractiveShell(options) {
53366
54216
  readline.on("SIGINT", () => {
53367
54217
  if (runtime.activeExecution) {
53368
54218
  runtime.activeExecution.controller.abort();
53369
- import_node_process35.default.stdout.write("\n");
54219
+ import_node_process36.default.stdout.write("\n");
53370
54220
  console.log(color(DIM, `Interrupt requested. Pausing ${runtime.activeExecution.label} after the current step...`));
53371
54221
  return;
53372
54222
  }
@@ -53387,10 +54237,14 @@ async function runInteractiveShell(options) {
53387
54237
  try {
53388
54238
  state = await getShellSessionState(currentCwd, runtime.focusRole, runtime);
53389
54239
  runtime.dashboard?.update(currentCwd, state);
53390
- line = await readline.question(formatPrompt(state));
54240
+ line = await readShellInput(readline, state);
53391
54241
  } catch {
53392
54242
  break;
53393
54243
  }
54244
+ if (line === "__kimbho_sigint__") {
54245
+ closed = true;
54246
+ break;
54247
+ }
53394
54248
  try {
53395
54249
  currentCwd = await handleShellCommand(currentCwd, line, state, runtime, options.execute);
53396
54250
  runtime.currentCwd = currentCwd;
@@ -53402,7 +54256,7 @@ async function runInteractiveShell(options) {
53402
54256
  }
53403
54257
  console.error(message);
53404
54258
  } finally {
53405
- import_node_process35.default.exitCode = 0;
54259
+ import_node_process36.default.exitCode = 0;
53406
54260
  }
53407
54261
  if (!closed && !useDashboard) {
53408
54262
  console.log("");
@@ -53413,7 +54267,7 @@ async function runInteractiveShell(options) {
53413
54267
  if (runtime.activeExecution) {
53414
54268
  runtime.activeExecution.controller.abort();
53415
54269
  }
53416
- import_node_process35.default.exitCode = 0;
54270
+ import_node_process36.default.exitCode = 0;
53417
54271
  if (useDashboard) {
53418
54272
  runtime.dashboard?.stop();
53419
54273
  console.log = originalLog;