@kimbho/kimbho-cli 0.1.21 → 0.1.23

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
@@ -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.21",
12721
+ version: "0.1.23",
12722
12722
  description: "Kimbho CLI is a terminal-native coding agent for planning, execution, and verification.",
12723
12723
  type: "module",
12724
12724
  engines: {
@@ -34255,11 +34255,20 @@ ${truncateForModel(customAgentMemory)}`);
34255
34255
  sessionId,
34256
34256
  taskId: task.id,
34257
34257
  agentRole: task.agentRole,
34258
- message: `Step budget exhausted after ${maxSteps} steps.`
34258
+ message: task.agentRole !== "test-debugger" ? `Step budget exhausted after ${maxSteps} steps; handing task to test-debugger.` : `Step budget exhausted after ${maxSteps} steps; debugger escalation exhausted.`
34259
34259
  });
34260
+ if (task.agentRole !== "test-debugger") {
34261
+ return {
34262
+ status: "handoff",
34263
+ summary: `Autonomous executor reached the step limit (${maxSteps}) for ${task.id}; handing off to test-debugger.`,
34264
+ toolResults,
34265
+ artifacts: Array.from(artifacts),
34266
+ usage: usageTotals
34267
+ };
34268
+ }
34260
34269
  return {
34261
- status: "paused",
34262
- summary: `Autonomous executor reached the step limit (${maxSteps}) for ${task.id}.`,
34270
+ status: "blocked",
34271
+ summary: `Autonomous executor reached the step limit (${maxSteps}) for ${task.id}; debugger escalation exhausted.`,
34263
34272
  toolResults,
34264
34273
  artifacts: Array.from(artifacts),
34265
34274
  usage: usageTotals
@@ -38726,9 +38735,6 @@ var CHAT_PREFIXES = [
38726
38735
  "when ",
38727
38736
  "where ",
38728
38737
  "who ",
38729
- "can you ",
38730
- "could you ",
38731
- "would you ",
38732
38738
  "should ",
38733
38739
  "is ",
38734
38740
  "are ",
@@ -38749,30 +38755,40 @@ var PLAN_PREFIXES = [
38749
38755
  function looksLikeExecutionRequest(input) {
38750
38756
  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);
38751
38757
  }
38758
+ function stripConversationalLead(input) {
38759
+ let normalized = input.trim().toLowerCase();
38760
+ normalized = normalized.replace(/^(hi|hello|hey|yo|sup)\b[!,. ]*/u, "").trim();
38761
+ normalized = normalized.replace(/^(please|pls)\b[!,. ]*/u, "").trim();
38762
+ normalized = normalized.replace(/^(can you|could you|would you|will you)\b[,: ]*/u, "").trim();
38763
+ normalized = normalized.replace(/^(help me)\b[,: ]*/u, "").trim();
38764
+ normalized = normalized.replace(/^(i need you to)\b[,: ]*/u, "").trim();
38765
+ return normalized;
38766
+ }
38752
38767
  function inferPromptIntent(input) {
38753
38768
  const normalized = input.trim().toLowerCase();
38769
+ const taskCandidate = stripConversationalLead(normalized);
38754
38770
  if (!normalized) {
38755
38771
  return "chat";
38756
38772
  }
38757
- if (/^(hi|hello|hey|yo|sup)\b/.test(normalized)) {
38773
+ if (!taskCandidate) {
38758
38774
  return "chat";
38759
38775
  }
38760
- if (PLAN_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {
38776
+ if (PLAN_PREFIXES.some((prefix) => taskCandidate.startsWith(prefix))) {
38761
38777
  return "plan";
38762
38778
  }
38763
- if (EXECUTION_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {
38779
+ if (EXECUTION_PREFIXES.some((prefix) => taskCandidate.startsWith(prefix))) {
38764
38780
  return "run";
38765
38781
  }
38766
- if (looksLikeExecutionRequest(normalized)) {
38782
+ if (looksLikeExecutionRequest(taskCandidate)) {
38767
38783
  return "run";
38768
38784
  }
38769
38785
  if (normalized.endsWith("?")) {
38770
38786
  return "chat";
38771
38787
  }
38772
- if (CHAT_PREFIXES.some((prefix) => normalized.startsWith(prefix))) {
38788
+ if (CHAT_PREFIXES.some((prefix) => taskCandidate.startsWith(prefix))) {
38773
38789
  return "chat";
38774
38790
  }
38775
- return normalized.split(/\s+/).length >= 4 ? "plan" : "chat";
38791
+ return taskCandidate.split(/\s+/).length >= 4 ? "plan" : "chat";
38776
38792
  }
38777
38793
  function normalizePlanPrompt(input) {
38778
38794
  const trimmed = input.trim();
@@ -43841,6 +43857,9 @@ async function renderCustomAgents(cwd) {
43841
43857
  // src/shell.ts
43842
43858
  var AMBER = "\x1B[38;5;214m";
43843
43859
  var CYAN = "\x1B[38;5;45m";
43860
+ var RED = "\x1B[38;5;203m";
43861
+ var SHIMMER_HEAD = "\x1B[38;5;230m";
43862
+ var SHIMMER_TAIL = "\x1B[38;5;223m";
43844
43863
  var BOLD = "\x1B[1m";
43845
43864
  var DIM = "\x1B[2m";
43846
43865
  var RESET = "\x1B[0m";
@@ -43901,7 +43920,9 @@ var MAX_CHAT_MESSAGES = 12;
43901
43920
  var MAX_CHAT_CONTEXT_CHARS = 8e3;
43902
43921
  var CHAT_COMPACTION_TAIL_MESSAGES = 6;
43903
43922
  var DEFAULT_MAX_AUTO_TASKS = 3;
43923
+ var UNBOUNDED_MAX_AUTO_TASKS = Number.MAX_SAFE_INTEGER;
43904
43924
  var DEFAULT_MAX_AGENT_STEPS = 8;
43925
+ var UNBOUNDED_MAX_AGENT_STEPS = 128;
43905
43926
  var DEFAULT_MAX_REPAIR_ATTEMPTS2 = 2;
43906
43927
  var SPINNER_FRAMES = [
43907
43928
  "-",
@@ -43920,6 +43941,24 @@ var IDLE_STATUS_LABELS = [
43920
43941
  function color(code, value) {
43921
43942
  return `${code}${value}${RESET}`;
43922
43943
  }
43944
+ function renderShimmeringLabel(label, frameIndex) {
43945
+ const characters = Array.from(label);
43946
+ if (characters.length === 0) {
43947
+ return color(BOLD, label);
43948
+ }
43949
+ const shimmerWidth = Math.min(4, characters.length + 1);
43950
+ const head = frameIndex % (characters.length + shimmerWidth);
43951
+ return characters.map((character, index) => {
43952
+ const distance = head - index;
43953
+ if (distance === 0) {
43954
+ return `${BOLD}${SHIMMER_HEAD}${character}${RESET}`;
43955
+ }
43956
+ if (distance > 0 && distance < shimmerWidth) {
43957
+ return `${BOLD}${SHIMMER_TAIL}${character}${RESET}`;
43958
+ }
43959
+ return `${BOLD}${character}${RESET}`;
43960
+ }).join("");
43961
+ }
43923
43962
  function readRuntimeOverrideEntries() {
43924
43963
  const raw = import_node_process26.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV];
43925
43964
  if (!raw || raw.trim().length === 0) {
@@ -43963,6 +44002,33 @@ function syncShellRuntimeOverrides(runtime) {
43963
44002
  }
43964
44003
  import_node_process26.default.env[KIMBHO_RUNTIME_OVERRIDES_ENV] = JSON.stringify(merged);
43965
44004
  }
44005
+ function resolveRuntimeOverrideApprovalMode(runtime) {
44006
+ if (runtime.sessionApprovalModeOverride) {
44007
+ return runtime.sessionApprovalModeOverride;
44008
+ }
44009
+ for (let index = runtime.baseRuntimeOverrides.length - 1; index >= 0; index -= 1) {
44010
+ const entry = runtime.baseRuntimeOverrides[index];
44011
+ if (entry?.path !== "approvalMode" || typeof entry.value !== "string") {
44012
+ continue;
44013
+ }
44014
+ try {
44015
+ return normalizeApprovalMode(entry.value);
44016
+ } catch {
44017
+ return null;
44018
+ }
44019
+ }
44020
+ return null;
44021
+ }
44022
+ function shouldAutoStartApprovedRuns(runtime) {
44023
+ const approvalMode = resolveRuntimeOverrideApprovalMode(runtime);
44024
+ return approvalMode === "auto" || approvalMode === "dontAsk" || approvalMode === "acceptEdits" || approvalMode === "bypassPermissions";
44025
+ }
44026
+ function resolveShellMaxAutoTasks(runtime) {
44027
+ return shouldAutoStartApprovedRuns(runtime) ? UNBOUNDED_MAX_AUTO_TASKS : DEFAULT_MAX_AUTO_TASKS;
44028
+ }
44029
+ function resolveShellMaxAgentSteps(runtime) {
44030
+ return shouldAutoStartApprovedRuns(runtime) ? UNBOUNDED_MAX_AGENT_STEPS : DEFAULT_MAX_AGENT_STEPS;
44031
+ }
43966
44032
  function normalizeApprovalMode(value) {
43967
44033
  const normalized = value.trim().toLowerCase();
43968
44034
  if (normalized === "manual" || normalized === "default") {
@@ -44123,6 +44189,9 @@ var ShellActivityIndicator = class {
44123
44189
  this.interval.unref?.();
44124
44190
  }
44125
44191
  update(label) {
44192
+ if (label !== this.label) {
44193
+ this.frameIndex = 0;
44194
+ }
44126
44195
  this.label = label;
44127
44196
  if (this.interval) {
44128
44197
  this.render();
@@ -44153,7 +44222,7 @@ var ShellActivityIndicator = class {
44153
44222
  return;
44154
44223
  }
44155
44224
  const frame = color(AMBER, SPINNER_FRAMES[this.frameIndex]);
44156
- const status = color(BOLD, this.label);
44225
+ const status = renderShimmeringLabel(this.label, this.frameIndex);
44157
44226
  const raw = `${frame} ${status}${color(DIM, "...")}`;
44158
44227
  this.clear();
44159
44228
  (0, import_node_readline2.cursorTo)(import_node_process26.default.stdout, 0);
@@ -44639,13 +44708,13 @@ function renderShellPlanSummary(plan) {
44639
44708
  }
44640
44709
  return lines;
44641
44710
  }
44642
- function renderPendingRunProposal(proposal) {
44711
+ function renderPendingRunProposal(proposal, options = {}) {
44643
44712
  const lines = [
44644
44713
  `${color(BOLD, proposal.source === "queued" ? "Queued Plan Ready" : "Ready To Run")}`,
44645
44714
  ...renderShellPlanSummary(proposal.plan),
44646
44715
  "",
44647
44716
  color(DIM, `saved plan: ${proposal.planPath}`),
44648
- "next: /approve to start, /run revise <feedback> to adjust, /run cancel to drop it"
44717
+ options.autoStart ? color(DIM, "next: auto-starting in the current permission mode") : "next: /approve to start, /run revise <feedback> to adjust, /run cancel to drop it"
44649
44718
  ];
44650
44719
  if (proposal.source === "queued") {
44651
44720
  lines.splice(1, 0, color(DIM, "The next queued request has been planned and is waiting for your approval."));
@@ -44706,8 +44775,12 @@ function renderShellSessionSummary(snapshot, planPath, sessionPath) {
44706
44775
  lines.push(color(DIM, `saved session: ${sessionPath}`));
44707
44776
  if (snapshot.pendingApprovals.length > 0) {
44708
44777
  lines.push("next: /approve to continue, /deny to stop");
44709
- } else {
44778
+ } else if (snapshot.status === "paused" || snapshot.status === "running" || snapshot.status === "ready") {
44710
44779
  lines.push("next: /resume to continue a paused run or start another request");
44780
+ } else if (snapshot.status === "blocked") {
44781
+ lines.push("next: review the blocker or start another request");
44782
+ } else {
44783
+ lines.push("next: start another request");
44711
44784
  }
44712
44785
  return lines.join("\n");
44713
44786
  }
@@ -44749,7 +44822,10 @@ function renderLiveExecutionEvent(event, board, startedAt) {
44749
44822
  ];
44750
44823
  case "task-finished":
44751
44824
  return [
44752
- `${color(event.status === "completed" ? CYAN : AMBER, event.status === "completed" ? "Completed" : event.status === "awaiting-approval" ? "Paused" : "Updated")} ${simplifyExecutionSummary(event.summary) || event.taskId}`,
44825
+ `${color(
44826
+ event.status === "completed" ? CYAN : event.status === "blocked" ? RED : AMBER,
44827
+ event.status === "completed" ? "Completed" : event.status === "awaiting-approval" ? "Paused" : event.status === "handoff" ? "Rerouting" : event.status === "blocked" ? "Blocked" : "Updated"
44828
+ )} ${simplifyExecutionSummary(event.summary) || event.taskId}`,
44753
44829
  ...renderConciseProgress(board, startedAt)
44754
44830
  ];
44755
44831
  case "task-note":
@@ -44930,6 +45006,10 @@ async function drainQueuedWork(runtime) {
44930
45006
  source: "queued"
44931
45007
  });
44932
45008
  runtime.currentCwd = nextCwd;
45009
+ if (shouldAutoStartApprovedRuns(runtime)) {
45010
+ console.log(color(DIM, "Auto-starting queued request in the current permission mode."));
45011
+ startPendingRunExecution(runtime);
45012
+ }
44933
45013
  } else if (next.kind === "resume") {
44934
45014
  await resumeGoalExecution(next.cwd, runtime);
44935
45015
  } else {
@@ -45096,7 +45176,12 @@ async function prepareRunProposal(cwd, goal, runtime, options = {}) {
45096
45176
  feedback: options.feedback ?? [],
45097
45177
  source: options.source ?? "direct"
45098
45178
  };
45099
- console.log(renderPendingRunProposal(runtime.pendingRunProposal).join("\n"));
45179
+ console.log(renderPendingRunProposal(
45180
+ runtime.pendingRunProposal,
45181
+ {
45182
+ autoStart: shouldAutoStartApprovedRuns(runtime)
45183
+ }
45184
+ ).join("\n"));
45100
45185
  return request.cwd;
45101
45186
  }
45102
45187
  async function executePendingRunProposal(runtime) {
@@ -45118,8 +45203,8 @@ async function executePendingRunProposal(runtime) {
45118
45203
  proposal.goal,
45119
45204
  request,
45120
45205
  proposal.plan,
45121
- DEFAULT_MAX_AUTO_TASKS,
45122
- DEFAULT_MAX_AGENT_STEPS,
45206
+ resolveShellMaxAutoTasks(runtime),
45207
+ resolveShellMaxAgentSteps(runtime),
45123
45208
  DEFAULT_MAX_REPAIR_ATTEMPTS2
45124
45209
  );
45125
45210
  console.log(renderRunStartCard(liveBoard));
@@ -45129,8 +45214,8 @@ async function executePendingRunProposal(runtime) {
45129
45214
  let snapshot;
45130
45215
  try {
45131
45216
  snapshot = await new ExecutionOrchestrator().continueSession(proposal.snapshot, {
45132
- maxAutoTasks: DEFAULT_MAX_AUTO_TASKS,
45133
- maxAgentSteps: DEFAULT_MAX_AGENT_STEPS,
45217
+ maxAutoTasks: resolveShellMaxAutoTasks(runtime),
45218
+ maxAgentSteps: resolveShellMaxAgentSteps(runtime),
45134
45219
  maxRepairAttempts: DEFAULT_MAX_REPAIR_ATTEMPTS2,
45135
45220
  signal: controller.signal,
45136
45221
  onProgress: async (event) => {
@@ -45183,8 +45268,8 @@ async function resumeGoalExecution(cwd, runtime) {
45183
45268
  session.goal,
45184
45269
  session.request,
45185
45270
  session.plan,
45186
- DEFAULT_MAX_AUTO_TASKS,
45187
- DEFAULT_MAX_AGENT_STEPS,
45271
+ resolveShellMaxAutoTasks(runtime),
45272
+ resolveShellMaxAgentSteps(runtime),
45188
45273
  DEFAULT_MAX_REPAIR_ATTEMPTS2
45189
45274
  );
45190
45275
  const controller = new AbortController();
@@ -45198,8 +45283,8 @@ async function resumeGoalExecution(cwd, runtime) {
45198
45283
  let snapshot;
45199
45284
  try {
45200
45285
  snapshot = await new ExecutionOrchestrator().continueSession(session, {
45201
- maxAutoTasks: DEFAULT_MAX_AUTO_TASKS,
45202
- maxAgentSteps: DEFAULT_MAX_AGENT_STEPS,
45286
+ maxAutoTasks: resolveShellMaxAutoTasks(runtime),
45287
+ maxAgentSteps: resolveShellMaxAgentSteps(runtime),
45203
45288
  maxRepairAttempts: DEFAULT_MAX_REPAIR_ATTEMPTS2,
45204
45289
  signal: controller.signal,
45205
45290
  onProgress: async (event) => {
@@ -45277,8 +45362,8 @@ async function resolvePendingApproval(cwd, runtime, decision, approvalId, option
45277
45362
  session.goal,
45278
45363
  session.request,
45279
45364
  session.plan,
45280
- DEFAULT_MAX_AUTO_TASKS,
45281
- DEFAULT_MAX_AGENT_STEPS,
45365
+ resolveShellMaxAutoTasks(runtime),
45366
+ resolveShellMaxAgentSteps(runtime),
45282
45367
  DEFAULT_MAX_REPAIR_ATTEMPTS2
45283
45368
  );
45284
45369
  liveBoard.approvals = session.pendingApprovals.length;
@@ -45293,8 +45378,8 @@ async function resolvePendingApproval(cwd, runtime, decision, approvalId, option
45293
45378
  let snapshot;
45294
45379
  try {
45295
45380
  snapshot = await new ExecutionOrchestrator().continueSession(session, {
45296
- maxAutoTasks: DEFAULT_MAX_AUTO_TASKS,
45297
- maxAgentSteps: DEFAULT_MAX_AGENT_STEPS,
45381
+ maxAutoTasks: resolveShellMaxAutoTasks(runtime),
45382
+ maxAgentSteps: resolveShellMaxAgentSteps(runtime),
45298
45383
  maxRepairAttempts: DEFAULT_MAX_REPAIR_ATTEMPTS2,
45299
45384
  approvalDecisions: approvals.map((approval) => ({
45300
45385
  approvalId: approval.id,
@@ -46501,9 +46586,14 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
46501
46586
  if (runtime.activeExecution || runtime.queueDrainPromise || runtime.pendingRunProposal) {
46502
46587
  queuePlannerRequest(cwd, trimmed, runtime, "run");
46503
46588
  } else {
46504
- return prepareRunProposal(cwd, trimmed, runtime, {
46589
+ const nextCwd = await prepareRunProposal(cwd, trimmed, runtime, {
46505
46590
  source: "direct"
46506
46591
  });
46592
+ if (shouldAutoStartApprovedRuns(runtime)) {
46593
+ console.log(color(DIM, "Auto-starting in the current permission mode."));
46594
+ startPendingRunExecution(runtime);
46595
+ }
46596
+ return nextCwd;
46507
46597
  }
46508
46598
  return cwd;
46509
46599
  }
@@ -46626,7 +46716,12 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
46626
46716
  if (head === "run" || head === "new" || head === "scaffold") {
46627
46717
  const subcommand = tokens[1]?.trim().toLowerCase();
46628
46718
  if (!tokens[1] && runtime.pendingRunProposal) {
46629
- console.log(renderPendingRunProposal(runtime.pendingRunProposal).join("\n"));
46719
+ console.log(renderPendingRunProposal(
46720
+ runtime.pendingRunProposal,
46721
+ {
46722
+ autoStart: shouldAutoStartApprovedRuns(runtime)
46723
+ }
46724
+ ).join("\n"));
46630
46725
  return cwd;
46631
46726
  }
46632
46727
  if (subcommand === "approve" || subcommand === "start" || subcommand === "execute") {
@@ -46658,10 +46753,14 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
46658
46753
  queuePlannerRequest(cwd, goal, runtime, "run");
46659
46754
  return cwd;
46660
46755
  }
46661
- await prepareRunProposal(cwd, goal, runtime, {
46756
+ const nextCwd = await prepareRunProposal(cwd, goal, runtime, {
46662
46757
  source: "direct"
46663
46758
  });
46664
- return cwd;
46759
+ if (shouldAutoStartApprovedRuns(runtime)) {
46760
+ console.log(color(DIM, "Auto-starting in the current permission mode."));
46761
+ startPendingRunExecution(runtime);
46762
+ }
46763
+ return nextCwd;
46665
46764
  }
46666
46765
  if (head === "plan") {
46667
46766
  if (!isSlashCommand) {