@kimbho/kimbho-cli 0.1.9 → 0.1.11
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 +429 -48
- package/dist/index.cjs.map +3 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3346,7 +3346,7 @@ var {
|
|
|
3346
3346
|
// package.json
|
|
3347
3347
|
var package_default = {
|
|
3348
3348
|
name: "@kimbho/kimbho-cli",
|
|
3349
|
-
version: "0.1.
|
|
3349
|
+
version: "0.1.11",
|
|
3350
3350
|
description: "Kimbho CLI is a terminal-native coding agent for planning, execution, and verification.",
|
|
3351
3351
|
type: "module",
|
|
3352
3352
|
engines: {
|
|
@@ -10690,7 +10690,7 @@ async function generateNextPrisma(cwd, projectName) {
|
|
|
10690
10690
|
]
|
|
10691
10691
|
}),
|
|
10692
10692
|
"next-env.d.ts": '/// <reference types="next" />\n/// <reference types="next/image-types/global" />\n',
|
|
10693
|
-
"next.config.
|
|
10693
|
+
"next.config.mjs": "/** @type {import('next').NextConfig} */\nconst nextConfig = {};\n\nexport default nextConfig;\n",
|
|
10694
10694
|
".env.example": 'DATABASE_URL="postgresql://postgres:postgres@localhost:5432/app"\n',
|
|
10695
10695
|
"prisma/schema.prisma": [
|
|
10696
10696
|
"generator client {",
|
|
@@ -10722,6 +10722,8 @@ async function generateNextPrisma(cwd, projectName) {
|
|
|
10722
10722
|
"}"
|
|
10723
10723
|
].join("\n"),
|
|
10724
10724
|
"src/app/page.tsx": [
|
|
10725
|
+
`const title = "${title}";`,
|
|
10726
|
+
"",
|
|
10725
10727
|
"export default function HomePage() {",
|
|
10726
10728
|
" return (",
|
|
10727
10729
|
" <main style={{ fontFamily: 'Georgia, serif', padding: '4rem 1.5rem', maxWidth: 960, margin: '0 auto' }}>",
|
|
@@ -11088,6 +11090,29 @@ var READ_ONLY_SHELL_PREFIXES = [
|
|
|
11088
11090
|
"pnpm ls",
|
|
11089
11091
|
"yarn list"
|
|
11090
11092
|
];
|
|
11093
|
+
var VERIFICATION_SHELL_PREFIXES = [
|
|
11094
|
+
"npm test",
|
|
11095
|
+
"npm run test",
|
|
11096
|
+
"npm run build",
|
|
11097
|
+
"npm run lint",
|
|
11098
|
+
"pnpm test",
|
|
11099
|
+
"pnpm run test",
|
|
11100
|
+
"pnpm build",
|
|
11101
|
+
"pnpm run build",
|
|
11102
|
+
"pnpm lint",
|
|
11103
|
+
"pnpm run lint",
|
|
11104
|
+
"yarn test",
|
|
11105
|
+
"yarn build",
|
|
11106
|
+
"yarn lint",
|
|
11107
|
+
"bun test",
|
|
11108
|
+
"bun run test",
|
|
11109
|
+
"bun run build",
|
|
11110
|
+
"bun run lint",
|
|
11111
|
+
"tsc",
|
|
11112
|
+
"vitest",
|
|
11113
|
+
"jest",
|
|
11114
|
+
"next build"
|
|
11115
|
+
];
|
|
11091
11116
|
var DESTRUCTIVE_SHELL_PATTERNS = [
|
|
11092
11117
|
/\brm\s+-rf\b/i,
|
|
11093
11118
|
/\brm\s+-fr\b/i,
|
|
@@ -11109,6 +11134,10 @@ function isReadOnlyShellCommand(command) {
|
|
|
11109
11134
|
const normalized = command.trim().toLowerCase();
|
|
11110
11135
|
return READ_ONLY_SHELL_PREFIXES.some((prefix) => normalized === prefix || normalized.startsWith(prefix));
|
|
11111
11136
|
}
|
|
11137
|
+
function isVerificationShellCommand(command) {
|
|
11138
|
+
const normalized = command.trim().toLowerCase();
|
|
11139
|
+
return VERIFICATION_SHELL_PREFIXES.some((prefix) => normalized === prefix || normalized.startsWith(`${prefix} `));
|
|
11140
|
+
}
|
|
11112
11141
|
function isDestructiveShellCommand(command) {
|
|
11113
11142
|
return DESTRUCTIVE_SHELL_PATTERNS.some((pattern) => pattern.test(command));
|
|
11114
11143
|
}
|
|
@@ -11178,7 +11207,7 @@ function enforceToolPolicy(toolId, input, descriptor, context) {
|
|
|
11178
11207
|
const approvalMode = context.approvalMode ?? "manual";
|
|
11179
11208
|
const command = typeof input.command === "string" ? input.command : "";
|
|
11180
11209
|
if (sandboxMode === "read-only") {
|
|
11181
|
-
if (toolId === "shell.exec" && isReadOnlyShellCommand(command)) {
|
|
11210
|
+
if (toolId === "shell.exec" && (isReadOnlyShellCommand(command) || isVerificationShellCommand(command))) {
|
|
11182
11211
|
return null;
|
|
11183
11212
|
}
|
|
11184
11213
|
if (descriptor.permission !== "safe") {
|
|
@@ -11190,6 +11219,9 @@ function enforceToolPolicy(toolId, input, descriptor, context) {
|
|
|
11190
11219
|
return new ToolApprovalRequiredError(createApprovalRequest(toolId, input, descriptor, context, `Approval required for destructive shell command: ${command}`));
|
|
11191
11220
|
}
|
|
11192
11221
|
}
|
|
11222
|
+
if (toolId === "shell.exec" && isVerificationShellCommand(command)) {
|
|
11223
|
+
return null;
|
|
11224
|
+
}
|
|
11193
11225
|
if ((toolId === "file.write" || toolId === "file.patch") && sandboxMode === "workspace-write") {
|
|
11194
11226
|
const targets = extractProspectiveWriteTargets(toolId, input, context.cwd);
|
|
11195
11227
|
const protectedTargets = targets.filter((target) => isProtectedWritePath(target));
|
|
@@ -12214,6 +12246,7 @@ function buildSystemPrompt(agent, task, request, allowedTools, plan) {
|
|
|
12214
12246
|
`- Use browser.open, browser.inspect, browser.click, browser.fill, and browser.close when a web UI needs browser-level verification.`,
|
|
12215
12247
|
`- Use process.start/process.logs/process.stop for long-running dev servers or watchers when they are available.`,
|
|
12216
12248
|
`- Keep paths relative to the workspace.`,
|
|
12249
|
+
`- In an existing repo, inspect and change the likely source files before running build or test verification. Do not front-load verification unless you are confirming an already-completed change or diagnosing a failure.`,
|
|
12217
12250
|
`- After changing code, run verification with tests.run or shell.exec when appropriate.`,
|
|
12218
12251
|
`- Do not claim success unless the task acceptance criteria are satisfied.`,
|
|
12219
12252
|
`- If the task is underspecified, make a pragmatic implementation choice and continue.`
|
|
@@ -12279,6 +12312,114 @@ function buildInitialUserPrompt(task, request) {
|
|
|
12279
12312
|
`Choose the next single action now.`
|
|
12280
12313
|
].join("\n");
|
|
12281
12314
|
}
|
|
12315
|
+
function extractCodeFences(raw) {
|
|
12316
|
+
const matches = Array.from(raw.matchAll(/```([a-z0-9_-]*)\s*\n([\s\S]*?)```/gi));
|
|
12317
|
+
return matches.map((match) => ({
|
|
12318
|
+
language: (match[1] ?? "").trim().toLowerCase(),
|
|
12319
|
+
code: (match[2] ?? "").trim()
|
|
12320
|
+
})).filter((match) => match.code.length > 0);
|
|
12321
|
+
}
|
|
12322
|
+
function normalizeWritableTaskFiles(task) {
|
|
12323
|
+
return Array.from(new Set(task.filesLikelyTouched.map((filePath) => filePath.trim()).filter((filePath) => filePath.length > 0 && !filePath.endsWith("/") && !filePath.includes("*") && !filePath.startsWith(".kimbho/"))));
|
|
12324
|
+
}
|
|
12325
|
+
function extractMentionedFilePaths(raw, task) {
|
|
12326
|
+
const mentioned = /* @__PURE__ */ new Set();
|
|
12327
|
+
const normalizedTaskFiles = normalizeWritableTaskFiles(task);
|
|
12328
|
+
const directMatches = raw.match(/([A-Za-z0-9_./-]+\.(?:tsx|ts|jsx|js|css|html|md|json|sql|prisma))/g) ?? [];
|
|
12329
|
+
for (const match of directMatches) {
|
|
12330
|
+
mentioned.add(match);
|
|
12331
|
+
}
|
|
12332
|
+
for (const candidate of normalizedTaskFiles) {
|
|
12333
|
+
const basename = import_node_path9.default.basename(candidate);
|
|
12334
|
+
if (raw.includes(candidate) || raw.includes(basename)) {
|
|
12335
|
+
mentioned.add(candidate);
|
|
12336
|
+
}
|
|
12337
|
+
}
|
|
12338
|
+
return Array.from(mentioned);
|
|
12339
|
+
}
|
|
12340
|
+
function inferFallbackFilePath(raw, task, fence) {
|
|
12341
|
+
const mentioned = extractMentionedFilePaths(raw, task);
|
|
12342
|
+
if (mentioned.length === 1) {
|
|
12343
|
+
return mentioned[0] ?? null;
|
|
12344
|
+
}
|
|
12345
|
+
const writableFiles = normalizeWritableTaskFiles(task);
|
|
12346
|
+
const sourceFiles = writableFiles.filter((filePath) => /\.[a-z0-9]+$/i.test(filePath));
|
|
12347
|
+
if (sourceFiles.length === 1) {
|
|
12348
|
+
return sourceFiles[0] ?? null;
|
|
12349
|
+
}
|
|
12350
|
+
if (fence.language === "html") {
|
|
12351
|
+
return sourceFiles.find((filePath) => filePath.endsWith(".html")) ?? null;
|
|
12352
|
+
}
|
|
12353
|
+
if (fence.language === "css") {
|
|
12354
|
+
return sourceFiles.find((filePath) => filePath.endsWith(".css")) ?? null;
|
|
12355
|
+
}
|
|
12356
|
+
if ([
|
|
12357
|
+
"tsx",
|
|
12358
|
+
"ts",
|
|
12359
|
+
"jsx",
|
|
12360
|
+
"js",
|
|
12361
|
+
"typescript",
|
|
12362
|
+
"javascript"
|
|
12363
|
+
].includes(fence.language)) {
|
|
12364
|
+
return sourceFiles.find((filePath) => /\.(tsx?|jsx?)$/i.test(filePath)) ?? null;
|
|
12365
|
+
}
|
|
12366
|
+
if (fence.language === "json") {
|
|
12367
|
+
return sourceFiles.find((filePath) => filePath.endsWith(".json")) ?? null;
|
|
12368
|
+
}
|
|
12369
|
+
return sourceFiles[0] ?? null;
|
|
12370
|
+
}
|
|
12371
|
+
function extractCommandFromResponse(raw) {
|
|
12372
|
+
const trimmed = raw.trim();
|
|
12373
|
+
if (/^(npm|pnpm|yarn|bun|npx|tsx|tsc|vitest|jest|next)\b/i.test(trimmed) && !trimmed.includes("\n")) {
|
|
12374
|
+
return trimmed;
|
|
12375
|
+
}
|
|
12376
|
+
const bashFence = extractCodeFences(raw).find((fence) => [
|
|
12377
|
+
"bash",
|
|
12378
|
+
"sh",
|
|
12379
|
+
"shell",
|
|
12380
|
+
"zsh"
|
|
12381
|
+
].includes(fence.language));
|
|
12382
|
+
if (!bashFence) {
|
|
12383
|
+
return null;
|
|
12384
|
+
}
|
|
12385
|
+
const lines = bashFence.code.split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
12386
|
+
return lines.length === 1 ? lines[0] ?? null : null;
|
|
12387
|
+
}
|
|
12388
|
+
function inferFallbackActionFromResponse(raw, task, allowedTools) {
|
|
12389
|
+
if (allowedTools.includes("shell.exec")) {
|
|
12390
|
+
const command = extractCommandFromResponse(raw);
|
|
12391
|
+
if (command) {
|
|
12392
|
+
return {
|
|
12393
|
+
type: "tool",
|
|
12394
|
+
tool: "shell.exec",
|
|
12395
|
+
input: {
|
|
12396
|
+
command
|
|
12397
|
+
},
|
|
12398
|
+
reason: "Run the command inferred from the model response."
|
|
12399
|
+
};
|
|
12400
|
+
}
|
|
12401
|
+
}
|
|
12402
|
+
if (!allowedTools.includes("file.write")) {
|
|
12403
|
+
return null;
|
|
12404
|
+
}
|
|
12405
|
+
const fences = extractCodeFences(raw);
|
|
12406
|
+
for (const fence of fences) {
|
|
12407
|
+
const filePath = inferFallbackFilePath(raw, task, fence);
|
|
12408
|
+
if (!filePath) {
|
|
12409
|
+
continue;
|
|
12410
|
+
}
|
|
12411
|
+
return {
|
|
12412
|
+
type: "tool",
|
|
12413
|
+
tool: "file.write",
|
|
12414
|
+
input: {
|
|
12415
|
+
path: filePath,
|
|
12416
|
+
content: fence.code
|
|
12417
|
+
},
|
|
12418
|
+
reason: `Apply the drafted contents for ${filePath} inferred from the model response.`
|
|
12419
|
+
};
|
|
12420
|
+
}
|
|
12421
|
+
return null;
|
|
12422
|
+
}
|
|
12282
12423
|
function buildToolResultUserMessage(step, result) {
|
|
12283
12424
|
return [
|
|
12284
12425
|
`Step ${step} tool result:`,
|
|
@@ -12852,6 +12993,19 @@ var AutonomousTaskExecutor = class {
|
|
|
12852
12993
|
runtimeNote: `${parseSummary} ${error instanceof Error ? error.message : String(error)}`
|
|
12853
12994
|
});
|
|
12854
12995
|
if (attempt === MAX_PARSE_RETRIES) {
|
|
12996
|
+
const inferredFallbackAction = inferFallbackActionFromResponse(response.text, task, allowedTools);
|
|
12997
|
+
if (inferredFallbackAction) {
|
|
12998
|
+
parsedAction = inferredFallbackAction;
|
|
12999
|
+
await emitProgress({
|
|
13000
|
+
type: "task-note",
|
|
13001
|
+
sessionId,
|
|
13002
|
+
taskId: task.id,
|
|
13003
|
+
agentRole: task.agentRole,
|
|
13004
|
+
step,
|
|
13005
|
+
message: `Model stayed out of structured mode; inferred ${inferredFallbackAction.tool} from the response.`
|
|
13006
|
+
});
|
|
13007
|
+
break;
|
|
13008
|
+
}
|
|
12855
13009
|
const transcriptPath2 = await writeTranscriptArtifact(request.cwd, sessionId, task.id, transcript);
|
|
12856
13010
|
artifacts.add(transcriptPath2);
|
|
12857
13011
|
await emitProgress({
|
|
@@ -13109,16 +13263,27 @@ function foundationMilestone(shape) {
|
|
|
13109
13263
|
"docs/",
|
|
13110
13264
|
"packages/"
|
|
13111
13265
|
], "medium"),
|
|
13112
|
-
buildTask("t3-scaffold", "Scaffold the repository foundation", "Create the workspace layout, TypeScript build config, package manifests, and initial CLI entry points.", shape === "cli-agent" ? "backend-specialist" : "infra-specialist", "scaffold", [
|
|
13266
|
+
buildTask("t3-scaffold", "Scaffold the repository foundation", shape === "static-site" ? "Create or adapt the primary landing-page entrypoint, styles, and workspace shell needed for the requested site." : "Create the workspace layout, TypeScript build config, package manifests, and initial CLI entry points.", shape === "cli-agent" ? "backend-specialist" : "infra-specialist", "scaffold", [
|
|
13113
13267
|
"t2-architecture"
|
|
13114
13268
|
], [
|
|
13115
|
-
"The monorepo or app workspace builds cleanly.",
|
|
13116
|
-
"Core commands or entry points exist."
|
|
13117
|
-
], [
|
|
13118
|
-
"package manifests",
|
|
13119
|
-
"TypeScript config",
|
|
13120
|
-
"CLI or app shell"
|
|
13269
|
+
shape === "static-site" ? "The primary page entry exists and renders the requested brand direction." : "The monorepo or app workspace builds cleanly.",
|
|
13270
|
+
shape === "static-site" ? "Core layout files or styles exist for the landing page." : "Core commands or entry points exist."
|
|
13121
13271
|
], [
|
|
13272
|
+
...shape === "static-site" ? [
|
|
13273
|
+
"Page entrypoint",
|
|
13274
|
+
"Stylesheet or layout shell"
|
|
13275
|
+
] : [
|
|
13276
|
+
"package manifests",
|
|
13277
|
+
"TypeScript config",
|
|
13278
|
+
"CLI or app shell"
|
|
13279
|
+
]
|
|
13280
|
+
], shape === "static-site" ? [
|
|
13281
|
+
"src/app/page.tsx",
|
|
13282
|
+
"src/app/layout.tsx",
|
|
13283
|
+
"src/pages/index.tsx",
|
|
13284
|
+
"index.html",
|
|
13285
|
+
"styles.css"
|
|
13286
|
+
] : [
|
|
13122
13287
|
"package.json",
|
|
13123
13288
|
"packages/",
|
|
13124
13289
|
"src/"
|
|
@@ -13141,6 +13306,9 @@ function implementationMilestone(shape) {
|
|
|
13141
13306
|
], [
|
|
13142
13307
|
"Customized landing page"
|
|
13143
13308
|
], [
|
|
13309
|
+
"src/app/page.tsx",
|
|
13310
|
+
"src/app/layout.tsx",
|
|
13311
|
+
"src/pages/index.tsx",
|
|
13144
13312
|
"index.html",
|
|
13145
13313
|
"styles.css",
|
|
13146
13314
|
"src/"
|
|
@@ -15685,14 +15853,25 @@ var ExecutionOrchestrator = class {
|
|
|
15685
15853
|
async executeRepoAnalysisTask(sessionId, task, request, emitProgress, signal) {
|
|
15686
15854
|
const context = { cwd: request.cwd };
|
|
15687
15855
|
const toolResults = [];
|
|
15688
|
-
const probes =
|
|
15856
|
+
const probes = [
|
|
15689
15857
|
{ toolId: "repo.index", input: {} }
|
|
15690
|
-
] : [
|
|
15691
|
-
{ toolId: "repo.index", input: {} },
|
|
15692
|
-
{ toolId: "git.status", input: {} },
|
|
15693
|
-
{ toolId: "file.read", input: { path: "package.json" } },
|
|
15694
|
-
{ toolId: "file.read", input: { path: "README.md" } }
|
|
15695
15858
|
];
|
|
15859
|
+
if (request.workspaceState !== "empty") {
|
|
15860
|
+
const candidatePaths = await Promise.all([
|
|
15861
|
+
(0, import_promises11.access)(import_node_path11.default.join(request.cwd, ".git")).then(() => true).catch(() => false),
|
|
15862
|
+
(0, import_promises11.access)(import_node_path11.default.join(request.cwd, "package.json")).then(() => true).catch(() => false),
|
|
15863
|
+
(0, import_promises11.access)(import_node_path11.default.join(request.cwd, "README.md")).then(() => true).catch(() => false)
|
|
15864
|
+
]);
|
|
15865
|
+
if (candidatePaths[0]) {
|
|
15866
|
+
probes.push({ toolId: "git.status", input: {} });
|
|
15867
|
+
}
|
|
15868
|
+
if (candidatePaths[1]) {
|
|
15869
|
+
probes.push({ toolId: "file.read", input: { path: "package.json" } });
|
|
15870
|
+
}
|
|
15871
|
+
if (candidatePaths[2]) {
|
|
15872
|
+
probes.push({ toolId: "file.read", input: { path: "README.md" } });
|
|
15873
|
+
}
|
|
15874
|
+
}
|
|
15696
15875
|
for (const probe of probes) {
|
|
15697
15876
|
if (emitProgress) {
|
|
15698
15877
|
await emitProgress({
|
|
@@ -16601,7 +16780,8 @@ function renderPlanGenerationNotes(result) {
|
|
|
16601
16780
|
lines.push(`planner tokens: ${result.usage.inputTokens} in / ${result.usage.outputTokens} out`);
|
|
16602
16781
|
}
|
|
16603
16782
|
if (result.warning) {
|
|
16604
|
-
|
|
16783
|
+
const warning = result.source === "fallback" ? `${summarizeStructuredOutputError("Planner", new Error(result.warning))} Using the safe default plan.` : result.warning;
|
|
16784
|
+
lines.push(`planner note: ${warning}`);
|
|
16605
16785
|
}
|
|
16606
16786
|
return lines;
|
|
16607
16787
|
}
|
|
@@ -17279,6 +17459,7 @@ function createProgram(onOpenShell) {
|
|
|
17279
17459
|
}
|
|
17280
17460
|
|
|
17281
17461
|
// src/shell.ts
|
|
17462
|
+
var import_node_readline = require("node:readline");
|
|
17282
17463
|
var import_promises14 = require("node:readline/promises");
|
|
17283
17464
|
var import_node_process12 = __toESM(require("node:process"), 1);
|
|
17284
17465
|
var AMBER = "\x1B[38;5;214m";
|
|
@@ -17287,7 +17468,9 @@ var BOLD = "\x1B[1m";
|
|
|
17287
17468
|
var DIM = "\x1B[2m";
|
|
17288
17469
|
var RESET = "\x1B[0m";
|
|
17289
17470
|
var TOP_LEVEL_COMMANDS = /* @__PURE__ */ new Set([
|
|
17471
|
+
"approval",
|
|
17290
17472
|
"approve",
|
|
17473
|
+
"approve-all",
|
|
17291
17474
|
"agents",
|
|
17292
17475
|
"brain",
|
|
17293
17476
|
"brains",
|
|
@@ -17331,6 +17514,20 @@ var MAX_CHAT_MESSAGES = 12;
|
|
|
17331
17514
|
var DEFAULT_MAX_AUTO_TASKS = 3;
|
|
17332
17515
|
var DEFAULT_MAX_AGENT_STEPS = 8;
|
|
17333
17516
|
var DEFAULT_MAX_REPAIR_ATTEMPTS2 = 2;
|
|
17517
|
+
var SPINNER_FRAMES = [
|
|
17518
|
+
"-",
|
|
17519
|
+
"\\",
|
|
17520
|
+
"|",
|
|
17521
|
+
"/"
|
|
17522
|
+
];
|
|
17523
|
+
var IDLE_STATUS_LABELS = [
|
|
17524
|
+
"thinking",
|
|
17525
|
+
"musing",
|
|
17526
|
+
"discombobulating",
|
|
17527
|
+
"assembling",
|
|
17528
|
+
"drafting",
|
|
17529
|
+
"tinkering"
|
|
17530
|
+
];
|
|
17334
17531
|
var EXECUTION_PREFIXES = [
|
|
17335
17532
|
"build ",
|
|
17336
17533
|
"create ",
|
|
@@ -17390,6 +17587,71 @@ function createExecutionTelemetry() {
|
|
|
17390
17587
|
outputTokens: 0
|
|
17391
17588
|
};
|
|
17392
17589
|
}
|
|
17590
|
+
var ShellActivityIndicator = class {
|
|
17591
|
+
interval = null;
|
|
17592
|
+
frameIndex = 0;
|
|
17593
|
+
label;
|
|
17594
|
+
activeLine = false;
|
|
17595
|
+
constructor(label) {
|
|
17596
|
+
this.label = label;
|
|
17597
|
+
}
|
|
17598
|
+
start() {
|
|
17599
|
+
if (!import_node_process12.default.stdout.isTTY || this.interval) {
|
|
17600
|
+
return;
|
|
17601
|
+
}
|
|
17602
|
+
this.activeLine = true;
|
|
17603
|
+
this.render();
|
|
17604
|
+
this.interval = setInterval(() => {
|
|
17605
|
+
this.frameIndex = (this.frameIndex + 1) % SPINNER_FRAMES.length;
|
|
17606
|
+
this.render();
|
|
17607
|
+
}, 120);
|
|
17608
|
+
this.interval.unref?.();
|
|
17609
|
+
}
|
|
17610
|
+
update(label) {
|
|
17611
|
+
this.label = label;
|
|
17612
|
+
if (this.interval) {
|
|
17613
|
+
this.render();
|
|
17614
|
+
}
|
|
17615
|
+
}
|
|
17616
|
+
suspend() {
|
|
17617
|
+
if (!import_node_process12.default.stdout.isTTY) {
|
|
17618
|
+
return;
|
|
17619
|
+
}
|
|
17620
|
+
this.clear();
|
|
17621
|
+
}
|
|
17622
|
+
resume() {
|
|
17623
|
+
if (!import_node_process12.default.stdout.isTTY || !this.interval) {
|
|
17624
|
+
return;
|
|
17625
|
+
}
|
|
17626
|
+
this.render();
|
|
17627
|
+
}
|
|
17628
|
+
stop() {
|
|
17629
|
+
if (this.interval) {
|
|
17630
|
+
clearInterval(this.interval);
|
|
17631
|
+
this.interval = null;
|
|
17632
|
+
}
|
|
17633
|
+
this.clear();
|
|
17634
|
+
this.activeLine = false;
|
|
17635
|
+
}
|
|
17636
|
+
render() {
|
|
17637
|
+
if (!import_node_process12.default.stdout.isTTY) {
|
|
17638
|
+
return;
|
|
17639
|
+
}
|
|
17640
|
+
const frame = color(AMBER, SPINNER_FRAMES[this.frameIndex]);
|
|
17641
|
+
const status = color(BOLD, this.label);
|
|
17642
|
+
const raw = `${frame} ${status}${color(DIM, "...")}`;
|
|
17643
|
+
this.clear();
|
|
17644
|
+
(0, import_node_readline.cursorTo)(import_node_process12.default.stdout, 0);
|
|
17645
|
+
import_node_process12.default.stdout.write(raw);
|
|
17646
|
+
}
|
|
17647
|
+
clear() {
|
|
17648
|
+
if (!import_node_process12.default.stdout.isTTY || !this.activeLine) {
|
|
17649
|
+
return;
|
|
17650
|
+
}
|
|
17651
|
+
(0, import_node_readline.cursorTo)(import_node_process12.default.stdout, 0);
|
|
17652
|
+
(0, import_node_readline.clearLine)(import_node_process12.default.stdout, 0);
|
|
17653
|
+
}
|
|
17654
|
+
};
|
|
17393
17655
|
function renderExecutionTelemetry(telemetry, startedAt) {
|
|
17394
17656
|
return `telemetry: ${((Date.now() - startedAt) / 1e3).toFixed(1)}s | ${telemetry.toolCalls} tools | ${telemetry.modelCalls} model calls | ${telemetry.inputTokens} in / ${telemetry.outputTokens} out`;
|
|
17395
17657
|
}
|
|
@@ -17579,7 +17841,9 @@ function renderHelp() {
|
|
|
17579
17841
|
"/plan <goal> Create a structured implementation plan.",
|
|
17580
17842
|
"/run <goal> Start a Kimbho execution session for a goal.",
|
|
17581
17843
|
"/resume Show the latest saved session.",
|
|
17844
|
+
"/approval [mode] Show or set approval mode: manual or auto.",
|
|
17582
17845
|
"/approve [id] Approve a pending risky action and continue the session.",
|
|
17846
|
+
"/approve-all Approve all pending actions in the current session.",
|
|
17583
17847
|
"/deny [id] Deny a pending risky action.",
|
|
17584
17848
|
"/agents Inspect agent roles and the active session.",
|
|
17585
17849
|
"/review Review the current git diff and summarize risk.",
|
|
@@ -17604,7 +17868,7 @@ function renderStartupCard(cwd, state) {
|
|
|
17604
17868
|
renderCardLine("approval", state.approvalMode),
|
|
17605
17869
|
renderCardLine("sandbox", state.sandboxMode),
|
|
17606
17870
|
renderCardLine("preset", state.stackPreset),
|
|
17607
|
-
renderCardLine("shortcuts", "/ask /run /
|
|
17871
|
+
renderCardLine("shortcuts", "/ask /run /approval /approve-all /models /quit")
|
|
17608
17872
|
];
|
|
17609
17873
|
if (!state.configured) {
|
|
17610
17874
|
cardLines.push("setup: run /init or /providers add <template> to create .kimbho/config.json");
|
|
@@ -17755,6 +18019,29 @@ function pickStatusLabel(message) {
|
|
|
17755
18019
|
"checking"
|
|
17756
18020
|
]);
|
|
17757
18021
|
}
|
|
18022
|
+
function pickIdleStatusLabel(seed) {
|
|
18023
|
+
return IDLE_STATUS_LABELS[hashString(seed) % IDLE_STATUS_LABELS.length];
|
|
18024
|
+
}
|
|
18025
|
+
function statusLabelForEvent(event) {
|
|
18026
|
+
switch (event.type) {
|
|
18027
|
+
case "task-note":
|
|
18028
|
+
return pickStatusLabel(event.message);
|
|
18029
|
+
case "task-started":
|
|
18030
|
+
return pickStatusLabel(event.task.title);
|
|
18031
|
+
case "tool-started":
|
|
18032
|
+
return pickStatusLabel(event.reason ?? event.toolId);
|
|
18033
|
+
case "model-usage":
|
|
18034
|
+
return "thinking";
|
|
18035
|
+
case "approval-requested":
|
|
18036
|
+
return "waiting";
|
|
18037
|
+
case "approval-resolved":
|
|
18038
|
+
return "continuing";
|
|
18039
|
+
case "task-finished":
|
|
18040
|
+
return event.status === "handoff" ? "rerouting" : "settling";
|
|
18041
|
+
default:
|
|
18042
|
+
return "thinking";
|
|
18043
|
+
}
|
|
18044
|
+
}
|
|
17758
18045
|
function simplifyTaskNote(message) {
|
|
17759
18046
|
const trimmed = message.trim();
|
|
17760
18047
|
if (trimmed.startsWith("Using ") && trimmed.includes(" via ")) {
|
|
@@ -17977,7 +18264,7 @@ function renderLiveExecutionEvent(event) {
|
|
|
17977
18264
|
];
|
|
17978
18265
|
case "task-note":
|
|
17979
18266
|
return [
|
|
17980
|
-
`${color(
|
|
18267
|
+
`${color(AMBER, `[${pickStatusLabel(event.message)}]`)} ${simplifyTaskNote(event.message)}`
|
|
17981
18268
|
];
|
|
17982
18269
|
case "approval-requested":
|
|
17983
18270
|
return [
|
|
@@ -18110,6 +18397,8 @@ async function handleChatPrompt(cwd, prompt, runtime) {
|
|
|
18110
18397
|
}
|
|
18111
18398
|
]);
|
|
18112
18399
|
let result;
|
|
18400
|
+
const activity = new ShellActivityIndicator(pickIdleStatusLabel(prompt));
|
|
18401
|
+
activity.start();
|
|
18113
18402
|
try {
|
|
18114
18403
|
result = await brain.client.generateText({
|
|
18115
18404
|
model: brain.model,
|
|
@@ -18125,9 +18414,11 @@ async function handleChatPrompt(cwd, prompt, runtime) {
|
|
|
18125
18414
|
} : {}
|
|
18126
18415
|
});
|
|
18127
18416
|
} catch (error) {
|
|
18417
|
+
activity.stop();
|
|
18128
18418
|
const message = error instanceof Error ? error.message : String(error);
|
|
18129
18419
|
throw new Error(`Chat failed for ${brain.role} via ${brain.provider.id}/${brain.model}: ${message}`);
|
|
18130
18420
|
}
|
|
18421
|
+
activity.stop();
|
|
18131
18422
|
const nextConversation = trimConversation([
|
|
18132
18423
|
...messages,
|
|
18133
18424
|
{
|
|
@@ -18152,13 +18443,29 @@ async function runGoalExecution(cwd, goal, runtime) {
|
|
|
18152
18443
|
workspaceState: workspace.workspaceState,
|
|
18153
18444
|
constraints: []
|
|
18154
18445
|
};
|
|
18155
|
-
const
|
|
18446
|
+
const startedAt = Date.now();
|
|
18447
|
+
const telemetry = createExecutionTelemetry();
|
|
18448
|
+
const controller = new AbortController();
|
|
18449
|
+
runtime.activeExecution = {
|
|
18450
|
+
controller,
|
|
18451
|
+
label: goal
|
|
18452
|
+
};
|
|
18453
|
+
const planningSpinner = new ShellActivityIndicator("planning");
|
|
18454
|
+
console.log(color(DIM, `Working on: ${goal}`));
|
|
18455
|
+
for (const note of workspace.notes) {
|
|
18456
|
+
console.log(color(DIM, note));
|
|
18457
|
+
}
|
|
18458
|
+
planningSpinner.start();
|
|
18459
|
+
let planResult;
|
|
18460
|
+
try {
|
|
18461
|
+
planResult = await generatePlanForRequest(request);
|
|
18462
|
+
} finally {
|
|
18463
|
+
planningSpinner.stop();
|
|
18464
|
+
}
|
|
18156
18465
|
const plan = planResult.plan;
|
|
18157
18466
|
const planPath = await savePlan(plan, request.cwd);
|
|
18158
18467
|
const envelope = orchestrator.buildEnvelope(request, plan);
|
|
18159
18468
|
const initialSnapshot = orchestrator.createSessionSnapshot(envelope);
|
|
18160
|
-
const startedAt = Date.now();
|
|
18161
|
-
const telemetry = createExecutionTelemetry();
|
|
18162
18469
|
const liveBoard = createLiveRunBoard(
|
|
18163
18470
|
initialSnapshot.id,
|
|
18164
18471
|
goal,
|
|
@@ -18168,21 +18475,14 @@ async function runGoalExecution(cwd, goal, runtime) {
|
|
|
18168
18475
|
DEFAULT_MAX_AGENT_STEPS,
|
|
18169
18476
|
DEFAULT_MAX_REPAIR_ATTEMPTS2
|
|
18170
18477
|
);
|
|
18171
|
-
const controller = new AbortController();
|
|
18172
|
-
runtime.activeExecution = {
|
|
18173
|
-
controller,
|
|
18174
|
-
label: goal
|
|
18175
|
-
};
|
|
18176
|
-
console.log(color(DIM, `Working on: ${goal}`));
|
|
18177
|
-
for (const note of workspace.notes) {
|
|
18178
|
-
console.log(color(DIM, note));
|
|
18179
|
-
}
|
|
18180
18478
|
for (const line of renderPlanGenerationNotes(planResult)) {
|
|
18181
18479
|
console.log(color(DIM, line));
|
|
18182
18480
|
}
|
|
18183
18481
|
console.log(renderShellPlanPreview(plan).join("\n"));
|
|
18184
18482
|
console.log(renderRunStartCard(liveBoard));
|
|
18185
18483
|
console.log("");
|
|
18484
|
+
const activity = new ShellActivityIndicator("starting");
|
|
18485
|
+
activity.start();
|
|
18186
18486
|
let snapshot;
|
|
18187
18487
|
try {
|
|
18188
18488
|
snapshot = await orchestrator.continueSession(initialSnapshot, {
|
|
@@ -18200,6 +18500,8 @@ async function runGoalExecution(cwd, goal, runtime) {
|
|
|
18200
18500
|
telemetry.inputTokens += event.usage?.inputTokens ?? 0;
|
|
18201
18501
|
telemetry.outputTokens += event.usage?.outputTokens ?? 0;
|
|
18202
18502
|
}
|
|
18503
|
+
activity.update(statusLabelForEvent(event));
|
|
18504
|
+
activity.suspend();
|
|
18203
18505
|
for (const line of renderLiveExecutionEvent(event)) {
|
|
18204
18506
|
console.log(line);
|
|
18205
18507
|
}
|
|
@@ -18208,12 +18510,15 @@ async function runGoalExecution(cwd, goal, runtime) {
|
|
|
18208
18510
|
console.log(line);
|
|
18209
18511
|
}
|
|
18210
18512
|
}
|
|
18513
|
+
activity.resume();
|
|
18211
18514
|
}
|
|
18212
18515
|
});
|
|
18213
18516
|
} catch (error) {
|
|
18517
|
+
activity.stop();
|
|
18214
18518
|
const message = error instanceof Error ? error.message : String(error);
|
|
18215
18519
|
throw new Error(`Execution failed while working on "${goal}": ${message}`);
|
|
18216
18520
|
} finally {
|
|
18521
|
+
activity.stop();
|
|
18217
18522
|
runtime.activeExecution = null;
|
|
18218
18523
|
}
|
|
18219
18524
|
const sessionPath = await saveSession(snapshot, request.cwd);
|
|
@@ -18247,6 +18552,8 @@ async function resumeGoalExecution(cwd, runtime) {
|
|
|
18247
18552
|
label: session.id
|
|
18248
18553
|
};
|
|
18249
18554
|
console.log(renderRunStartCard(liveBoard));
|
|
18555
|
+
const activity = new ShellActivityIndicator("resuming");
|
|
18556
|
+
activity.start();
|
|
18250
18557
|
let snapshot;
|
|
18251
18558
|
try {
|
|
18252
18559
|
snapshot = await new ExecutionOrchestrator().continueSession(session, {
|
|
@@ -18264,6 +18571,8 @@ async function resumeGoalExecution(cwd, runtime) {
|
|
|
18264
18571
|
telemetry.inputTokens += event.usage?.inputTokens ?? 0;
|
|
18265
18572
|
telemetry.outputTokens += event.usage?.outputTokens ?? 0;
|
|
18266
18573
|
}
|
|
18574
|
+
activity.update(statusLabelForEvent(event));
|
|
18575
|
+
activity.suspend();
|
|
18267
18576
|
for (const line of renderLiveExecutionEvent(event)) {
|
|
18268
18577
|
console.log(line);
|
|
18269
18578
|
}
|
|
@@ -18272,12 +18581,15 @@ async function resumeGoalExecution(cwd, runtime) {
|
|
|
18272
18581
|
console.log(line);
|
|
18273
18582
|
}
|
|
18274
18583
|
}
|
|
18584
|
+
activity.resume();
|
|
18275
18585
|
}
|
|
18276
18586
|
});
|
|
18277
18587
|
} catch (error) {
|
|
18588
|
+
activity.stop();
|
|
18278
18589
|
const message = error instanceof Error ? error.message : String(error);
|
|
18279
18590
|
throw new Error(`Resume failed for ${session.id}: ${message}`);
|
|
18280
18591
|
} finally {
|
|
18592
|
+
activity.stop();
|
|
18281
18593
|
runtime.activeExecution = null;
|
|
18282
18594
|
}
|
|
18283
18595
|
const sessionPath = await saveSession(snapshot, cwd);
|
|
@@ -18286,29 +18598,42 @@ async function resumeGoalExecution(cwd, runtime) {
|
|
|
18286
18598
|
console.log(color(DIM, renderExecutionTelemetry(telemetry, startedAt)));
|
|
18287
18599
|
console.log(renderShellSessionSummary(snapshot, null, sessionPath));
|
|
18288
18600
|
}
|
|
18289
|
-
function
|
|
18601
|
+
function resolveApprovalChoices(snapshot, requestedId, options = {}) {
|
|
18290
18602
|
if (snapshot.pendingApprovals.length === 0) {
|
|
18291
18603
|
throw new Error("No pending approvals in the current session.");
|
|
18292
18604
|
}
|
|
18605
|
+
if (requestedId === "all") {
|
|
18606
|
+
if (!options.allowAll) {
|
|
18607
|
+
throw new Error("Use /approve-all to approve every pending action.");
|
|
18608
|
+
}
|
|
18609
|
+
return [
|
|
18610
|
+
...snapshot.pendingApprovals
|
|
18611
|
+
];
|
|
18612
|
+
}
|
|
18293
18613
|
if (requestedId) {
|
|
18294
18614
|
const approval = snapshot.pendingApprovals.find((candidate) => candidate.id === requestedId);
|
|
18295
18615
|
if (!approval) {
|
|
18296
18616
|
throw new Error(`No pending approval found for "${requestedId}".`);
|
|
18297
18617
|
}
|
|
18298
|
-
return
|
|
18618
|
+
return [
|
|
18619
|
+
approval
|
|
18620
|
+
];
|
|
18299
18621
|
}
|
|
18300
18622
|
if (snapshot.pendingApprovals.length > 1) {
|
|
18301
|
-
throw new Error("Multiple pending approvals exist. Use /approve <approval-id
|
|
18623
|
+
throw new Error("Multiple pending approvals exist. Use /approve <approval-id>, /deny <approval-id>, or /approve-all.");
|
|
18302
18624
|
}
|
|
18303
|
-
return
|
|
18625
|
+
return [
|
|
18626
|
+
snapshot.pendingApprovals[0]
|
|
18627
|
+
];
|
|
18304
18628
|
}
|
|
18305
|
-
async function resolvePendingApproval(cwd, runtime, decision, approvalId) {
|
|
18629
|
+
async function resolvePendingApproval(cwd, runtime, decision, approvalId, options = {}) {
|
|
18306
18630
|
const session = await loadLatestSession(cwd);
|
|
18307
18631
|
if (!session) {
|
|
18308
18632
|
throw new Error("No saved session found. Run a goal first.");
|
|
18309
18633
|
}
|
|
18310
|
-
const
|
|
18311
|
-
|
|
18634
|
+
const approvals = resolveApprovalChoices(session, approvalId, options);
|
|
18635
|
+
const label = approvals.length === 1 ? `${approvals[0].toolId} for ${approvals[0].taskId}` : `${approvals.length} pending actions`;
|
|
18636
|
+
console.log(color(DIM, `${decision === "approve" ? "Approving" : "Denying"} ${label}...`));
|
|
18312
18637
|
const startedAt = Date.now();
|
|
18313
18638
|
const telemetry = createExecutionTelemetry();
|
|
18314
18639
|
const liveBoard = createLiveRunBoard(
|
|
@@ -18324,21 +18649,21 @@ async function resolvePendingApproval(cwd, runtime, decision, approvalId) {
|
|
|
18324
18649
|
const controller = new AbortController();
|
|
18325
18650
|
runtime.activeExecution = {
|
|
18326
18651
|
controller,
|
|
18327
|
-
label: `${session.id}:${
|
|
18652
|
+
label: approvals.length === 1 ? `${session.id}:${approvals[0].id}` : `${session.id}:batch-approval`
|
|
18328
18653
|
};
|
|
18329
18654
|
console.log(renderRunStartCard(liveBoard));
|
|
18655
|
+
const activity = new ShellActivityIndicator(decision === "approve" ? "approving" : "denying");
|
|
18656
|
+
activity.start();
|
|
18330
18657
|
let snapshot;
|
|
18331
18658
|
try {
|
|
18332
18659
|
snapshot = await new ExecutionOrchestrator().continueSession(session, {
|
|
18333
18660
|
maxAutoTasks: DEFAULT_MAX_AUTO_TASKS,
|
|
18334
18661
|
maxAgentSteps: DEFAULT_MAX_AGENT_STEPS,
|
|
18335
18662
|
maxRepairAttempts: DEFAULT_MAX_REPAIR_ATTEMPTS2,
|
|
18336
|
-
approvalDecisions:
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
|
|
18340
|
-
}
|
|
18341
|
-
],
|
|
18663
|
+
approvalDecisions: approvals.map((approval) => ({
|
|
18664
|
+
approvalId: approval.id,
|
|
18665
|
+
decision
|
|
18666
|
+
})),
|
|
18342
18667
|
signal: controller.signal,
|
|
18343
18668
|
onProgress: async (event) => {
|
|
18344
18669
|
updateLiveRunBoard(liveBoard, event);
|
|
@@ -18350,6 +18675,8 @@ async function resolvePendingApproval(cwd, runtime, decision, approvalId) {
|
|
|
18350
18675
|
telemetry.inputTokens += event.usage?.inputTokens ?? 0;
|
|
18351
18676
|
telemetry.outputTokens += event.usage?.outputTokens ?? 0;
|
|
18352
18677
|
}
|
|
18678
|
+
activity.update(statusLabelForEvent(event));
|
|
18679
|
+
activity.suspend();
|
|
18353
18680
|
for (const line of renderLiveExecutionEvent(event)) {
|
|
18354
18681
|
console.log(line);
|
|
18355
18682
|
}
|
|
@@ -18358,12 +18685,15 @@ async function resolvePendingApproval(cwd, runtime, decision, approvalId) {
|
|
|
18358
18685
|
console.log(line);
|
|
18359
18686
|
}
|
|
18360
18687
|
}
|
|
18688
|
+
activity.resume();
|
|
18361
18689
|
}
|
|
18362
18690
|
});
|
|
18363
18691
|
} catch (error) {
|
|
18692
|
+
activity.stop();
|
|
18364
18693
|
const message = error instanceof Error ? error.message : String(error);
|
|
18365
|
-
throw new Error(`Approval resolution failed for ${approval.id}: ${message}`);
|
|
18694
|
+
throw new Error(`Approval resolution failed for ${approvals.map((approval) => approval.id).join(", ")}: ${message}`);
|
|
18366
18695
|
} finally {
|
|
18696
|
+
activity.stop();
|
|
18367
18697
|
runtime.activeExecution = null;
|
|
18368
18698
|
}
|
|
18369
18699
|
const sessionPath = await saveSession(snapshot, cwd);
|
|
@@ -18379,6 +18709,28 @@ async function printLatestPlanSummary(cwd) {
|
|
|
18379
18709
|
}
|
|
18380
18710
|
console.log(renderShellPlanSummary(plan).join("\n"));
|
|
18381
18711
|
}
|
|
18712
|
+
async function handleApprovalModeCommand(cwd, tokens) {
|
|
18713
|
+
const config = await loadConfig(cwd);
|
|
18714
|
+
if (!config) {
|
|
18715
|
+
throw new Error("No config found. Run /init or /providers add <template> first.");
|
|
18716
|
+
}
|
|
18717
|
+
const subcommand = tokens[1]?.trim().toLowerCase();
|
|
18718
|
+
if (!subcommand || subcommand === "status") {
|
|
18719
|
+
console.log(`approval mode: ${config.approvalMode}`);
|
|
18720
|
+
console.log("manual = ask before risky actions");
|
|
18721
|
+
console.log("auto = approve non-destructive actions automatically");
|
|
18722
|
+
return;
|
|
18723
|
+
}
|
|
18724
|
+
if (subcommand !== "manual" && subcommand !== "auto") {
|
|
18725
|
+
throw new Error("Usage: /approval [manual|auto|status]");
|
|
18726
|
+
}
|
|
18727
|
+
const outputPath = await saveConfig({
|
|
18728
|
+
...config,
|
|
18729
|
+
approvalMode: subcommand
|
|
18730
|
+
}, cwd);
|
|
18731
|
+
console.log(`Updated ${outputPath}`);
|
|
18732
|
+
console.log(`approval mode: ${subcommand}`);
|
|
18733
|
+
}
|
|
18382
18734
|
async function createPlanOnly(cwd, goal) {
|
|
18383
18735
|
const request = {
|
|
18384
18736
|
goal,
|
|
@@ -18387,7 +18739,14 @@ async function createPlanOnly(cwd, goal) {
|
|
|
18387
18739
|
workspaceState: await inferPlanningWorkspaceState(cwd, goal),
|
|
18388
18740
|
constraints: []
|
|
18389
18741
|
};
|
|
18390
|
-
const
|
|
18742
|
+
const activity = new ShellActivityIndicator("planning");
|
|
18743
|
+
activity.start();
|
|
18744
|
+
let planResult;
|
|
18745
|
+
try {
|
|
18746
|
+
planResult = await generatePlanForRequest(request);
|
|
18747
|
+
} finally {
|
|
18748
|
+
activity.stop();
|
|
18749
|
+
}
|
|
18391
18750
|
const plan = planResult.plan;
|
|
18392
18751
|
const planPath = await savePlan(plan, cwd);
|
|
18393
18752
|
for (const line of renderPlanGenerationNotes(planResult)) {
|
|
@@ -18966,13 +19325,35 @@ async function handleShellCommand(cwd, input, state, runtime, execute) {
|
|
|
18966
19325
|
await resumeGoalExecution(cwd, runtime);
|
|
18967
19326
|
return cwd;
|
|
18968
19327
|
}
|
|
19328
|
+
if (head === "approval") {
|
|
19329
|
+
await handleApprovalModeCommand(cwd, [
|
|
19330
|
+
"approval",
|
|
19331
|
+
...tokens.slice(1)
|
|
19332
|
+
]);
|
|
19333
|
+
return cwd;
|
|
19334
|
+
}
|
|
19335
|
+
if (head === "approve-all") {
|
|
19336
|
+
await resolvePendingApproval(
|
|
19337
|
+
cwd,
|
|
19338
|
+
runtime,
|
|
19339
|
+
"approve",
|
|
19340
|
+
"all",
|
|
19341
|
+
{
|
|
19342
|
+
allowAll: true
|
|
19343
|
+
}
|
|
19344
|
+
);
|
|
19345
|
+
return cwd;
|
|
19346
|
+
}
|
|
18969
19347
|
if (head === "approve" || head === "deny") {
|
|
18970
19348
|
const approvalId = tokens[1]?.trim();
|
|
18971
19349
|
await resolvePendingApproval(
|
|
18972
19350
|
cwd,
|
|
18973
19351
|
runtime,
|
|
18974
19352
|
head === "approve" ? "approve" : "deny",
|
|
18975
|
-
approvalId && approvalId.length > 0 ? approvalId : void 0
|
|
19353
|
+
approvalId && approvalId.length > 0 ? approvalId : void 0,
|
|
19354
|
+
{
|
|
19355
|
+
allowAll: false
|
|
19356
|
+
}
|
|
18976
19357
|
);
|
|
18977
19358
|
return cwd;
|
|
18978
19359
|
}
|