@buildaharness/aielia 0.3.7 → 0.3.9
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/README.md +6 -3
- package/dist/action-approval-service.d.ts +2 -0
- package/dist/ask-draft.d.ts +22 -0
- package/dist/assistant-options.d.ts +35 -0
- package/dist/assistant-session.d.ts +1 -1
- package/dist/{bin-C_hgDdSf.js → bin-CCwDFxDe.js} +145 -258
- package/dist/bin-CCwDFxDe.js.map +1 -0
- package/dist/cli-config.d.ts +2 -2
- package/dist/cli-session.d.ts +2 -1
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +1 -1
- package/dist/commands.d.ts +32 -0
- package/dist/config-keys.d.ts +43 -0
- package/dist/doctor-checks.d.ts +1 -2
- package/dist/fact-extraction.d.ts +4 -0
- package/dist/goal-graph-store.d.ts +6 -0
- package/dist/index.d.ts +17 -2
- package/dist/index.js +199 -148
- package/dist/index.js.map +1 -1
- package/dist/llm-client-factory.d.ts +13 -0
- package/dist/memory-service.d.ts +2 -0
- package/dist/model-pricing.d.ts +12 -9
- package/dist/node-display-names.d.ts +1 -1
- package/dist/project-command.d.ts +16 -0
- package/dist/{provider-setup-wX2IBw2X.js → provider-setup-Cy9dwqrd.js} +13504 -13034
- package/dist/provider-setup-Cy9dwqrd.js.map +1 -0
- package/dist/proxy-health.d.ts +8 -0
- package/dist/redact-url.d.ts +2 -0
- package/dist/reply-audit.d.ts +2 -0
- package/dist/response-service.d.ts +10 -0
- package/dist/run-explain.d.ts +58 -0
- package/dist/{tui-app-C0J6HRzv.js → tui-app-Dt72u8vZ.js} +11 -3
- package/dist/{tui-app-C0J6HRzv.js.map → tui-app-Dt72u8vZ.js.map} +1 -1
- package/dist/turn-cost.d.ts +12 -0
- package/dist/turn-presentation.d.ts +86 -0
- package/dist/undo-action-command.d.ts +12 -0
- package/dist/undo-plan.d.ts +13 -0
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/dist/bin-C_hgDdSf.js.map +0 -1
- package/dist/provider-setup-wX2IBw2X.js.map +0 -1
|
@@ -7,8 +7,8 @@ import { createInterface } from "node:readline";
|
|
|
7
7
|
import { rename, stat, realpath, readdir, mkdir, unlink, writeFile, readFile } from "node:fs/promises";
|
|
8
8
|
import { homedir, tmpdir } from "node:os";
|
|
9
9
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
10
|
-
import { OPENROUTER_DEFAULT_MODEL, OPENAI_DEFAULT_MODEL, ANTHROPIC_DEFAULT_MODEL, InMemoryReminderStore, FileSystemAdapter, FileSystemExperienceStore
|
|
11
|
-
import {
|
|
10
|
+
import { OPENROUTER_DEFAULT_MODEL, OPENAI_DEFAULT_MODEL, ANTHROPIC_DEFAULT_MODEL, InMemoryReminderStore, FileSystemAdapter, FileSystemExperienceStore } from "@buildaharness/runtime";
|
|
11
|
+
import { af as buildClaudePrompt, co as stripJsonCodeFence, c2 as recallToolEnabled, bw as lexicalOffEnvValue, a as ALREADY_STAGED_ACTION_TOOL, cn as stagedActionInput, bT as parseClaudeCliOutput, cp as stripMcpToolPrefix, bE as memoryStatusChecks, bR as normalizePlanNodes, V as PROVIDER_SETUP, ao as cleanApiKey, ah as checkApiKeyFormat, aG as envOverridesFromProcessEnv, c6 as resolveConfig, cl as shouldLaunchTuiApp, t as DEFAULT_TUI_MODE, a8 as applyLayerSettings, cj as sanitizeLayerChoices, cu as testApiKey, cx as validateConfig, aW as findInvalidNumericSettings, f as ConfigValidationError, be as formatSpendCapStatus, br as isPlanGraphEnabled, X as PersonalAssistant, ae as buildAssistantOptions, cq as stripTerminalControls, bn as isGoalGraphEnabled, b$ as planToSnapshot, ar as createLlmClient, au as createSmtpSender, at as createResendSender, aZ as formatConfigListing, bm as isConfigKey, e as CONFIG_KEYS, x as ENV_VAR_FOR_CONFIG_KEY, bU as parseConfigValue, g as ConfigValueParseError, ai as checkProxyHealth, a$ as formatDoctorReport, a_ as formatCostSummary, bW as parseProjectCommand, b1 as formatGoalGraphState, bd as formatSearchResults, b6 as formatMemoryHistory, b9 as formatMemoryStatus, b8 as formatMemoryPendingOutcome, b4 as formatMemoryArchive, bY as parseUndoActionCommand, bh as formatUndoLogListing, c0 as planUndo, ax as defaultExportFilename, bg as formatTranscriptMarkdown, aj as classifyError, bf as formatStatus, b2 as formatHelp, aS as explainSteps, aR as explainSources, aP as explainLayers, b3 as formatLayerListing, cA as withLayerChoice, O as LayerSettingError, aT as explainWhy, bt as isQuitCommand, P as LiveSteeringChannel, ay as defaultMemoryExportFilename, b5 as formatMemoryExport, bD as memoryAuditLogEnabled, ba as formatMemorySummary, aa as approvalLabels, U as NO_TRACE, R as MISSING_PLAN_APPROVAL_ID_REASON, c1 as presentTurnResult, bb as formatNextSteps, aQ as explainPlan, bH as nodeToLayer, L as LAYER_DISPLAY_NAME, bG as nodeDisplayName, j as DEFAULT_CLARIFICATION_REASON, aE as emptyDraft, aC as draftToAnswer, bS as orderedOptions, cz as withCostEstimate, C as CLI_FEATURES, ad as braveSearch } from "./provider-setup-Cy9dwqrd.js";
|
|
12
12
|
import { spawn } from "node:child_process";
|
|
13
13
|
import { createServer, connect } from "node:net";
|
|
14
14
|
import { createRequire } from "node:module";
|
|
@@ -129,7 +129,7 @@ function createNodeFsBackend() {
|
|
|
129
129
|
}
|
|
130
130
|
};
|
|
131
131
|
}
|
|
132
|
-
const CLI_VERSION = "0.3.
|
|
132
|
+
const CLI_VERSION = "0.3.9";
|
|
133
133
|
function seaCacheDir(version, home = homedir()) {
|
|
134
134
|
return join(home, ".buildaharness", "personal-assistant", "sea-cache", version);
|
|
135
135
|
}
|
|
@@ -699,22 +699,6 @@ class NodeConfigStore {
|
|
|
699
699
|
}
|
|
700
700
|
}
|
|
701
701
|
const DOCTOR_CHECK_TIMEOUT_MS = 3e3;
|
|
702
|
-
async function checkProxyHealth(proxyUrl) {
|
|
703
|
-
const label = `proxy reachable (${redactUrlCredentials(proxyUrl)}/health)`;
|
|
704
|
-
const controller = new AbortController();
|
|
705
|
-
const timeout = setTimeout(() => controller.abort(), DOCTOR_CHECK_TIMEOUT_MS);
|
|
706
|
-
try {
|
|
707
|
-
const res = await fetch(`${proxyUrl}/health`, { signal: controller.signal });
|
|
708
|
-
if (!res.ok) return { label, ok: false, detail: `HTTP ${res.status}` };
|
|
709
|
-
const body = await res.json().catch(() => void 0);
|
|
710
|
-
return (body == null ? void 0 : body.status) === "ok" ? { label, ok: true } : { label, ok: false, detail: "unexpected response body" };
|
|
711
|
-
} catch (err) {
|
|
712
|
-
const timedOut = err instanceof Error && err.name === "AbortError";
|
|
713
|
-
return { label, ok: false, detail: timedOut ? "timed out" : err instanceof Error ? err.message : String(err) };
|
|
714
|
-
} finally {
|
|
715
|
-
clearTimeout(timeout);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
702
|
function checkClaudeCli(claudePath) {
|
|
719
703
|
const label = `claude binary (${claudePath})`;
|
|
720
704
|
return new Promise((resolvePromise) => {
|
|
@@ -3475,84 +3459,47 @@ function buildEmailSender(config) {
|
|
|
3475
3459
|
return void 0;
|
|
3476
3460
|
}
|
|
3477
3461
|
function buildLlmClient(config, workspaceRoot, remindersFile) {
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
case "anthropic":
|
|
3488
|
-
return new AnthropicLLMClient({ apiKey: config.apiKey ?? "" });
|
|
3489
|
-
case "openai":
|
|
3490
|
-
return new OpenAICompatibleLLMClient({ apiKey: config.apiKey ?? "", baseUrl: OPENAI_BASE_URL, defaultModel: OPENAI_DEFAULT_MODEL });
|
|
3491
|
-
case "openrouter":
|
|
3492
|
-
return new OpenAICompatibleLLMClient({
|
|
3493
|
-
apiKey: config.apiKey ?? "",
|
|
3494
|
-
baseUrl: OPENROUTER_BASE_URL,
|
|
3495
|
-
defaultModel: OPENROUTER_DEFAULT_MODEL,
|
|
3496
|
-
extraHeaders: OPENROUTER_EXTRA_HEADERS
|
|
3497
|
-
});
|
|
3498
|
-
case "proxy":
|
|
3499
|
-
return new LLMClient({ proxyUrl: config.proxyUrl, authToken: config.authToken });
|
|
3500
|
-
}
|
|
3462
|
+
return createLlmClient(config, {
|
|
3463
|
+
claudeCli: () => new ClaudeCliLLMClient({
|
|
3464
|
+
fileTools: { workspaceRoot },
|
|
3465
|
+
remindersFile,
|
|
3466
|
+
shellTools: config.enableShell ? { workspaceRoot } : void 0,
|
|
3467
|
+
webTools: config.enableWeb ? { braveApiKey: config.braveApiKey } : void 0,
|
|
3468
|
+
actionTools: config.enableEmail ? { workspaceRoot } : void 0
|
|
3469
|
+
})
|
|
3470
|
+
});
|
|
3501
3471
|
}
|
|
3502
3472
|
async function buildAssistant(config, { backend, dataDir, remindersFile }) {
|
|
3503
3473
|
const workspaceRoot = config.workspaceRoot ?? process.cwd();
|
|
3504
3474
|
if (backend === defaultBackend) excludeAieliaStateFromGit(workspaceRoot);
|
|
3505
3475
|
const search = (query) => braveSearch(query, config.braveApiKey);
|
|
3506
3476
|
const llmClient = buildLlmClient(config, workspaceRoot, remindersFile);
|
|
3507
|
-
return PersonalAssistant.create(
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
|
|
3523
|
-
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
return sendEmail ? { backend, workspaceRoot, sendEmail } : void 0;
|
|
3532
|
-
})(),
|
|
3533
|
-
dangerouslySkipPermissions: config.dangerouslySkipPermissions,
|
|
3534
|
-
// Opt-in durable record of tool calls/results and approvals (see activity-log.ts).
|
|
3535
|
-
onDebugLog: activityLogEnabled(process.env) ? createActivityLogger(join(dataDir, "activity-log.jsonl")) : void 0,
|
|
3536
|
-
spendCap: config.sessionCostLimitUsd !== void 0 || config.sessionCallLimit !== void 0 ? { sessionCostLimitUsd: config.sessionCostLimitUsd, sessionCallLimit: config.sessionCallLimit } : void 0,
|
|
3537
|
-
// Resolved through the shared config seam (cli-config.ts's envOverridesFromProcessEnv reads
|
|
3538
|
-
// ASSISTANT_ONE_LOOP into config.oneLoopMode; /config set oneLoopMode persists it) so the CLI,
|
|
3539
|
-
// chat-ui, and the Tauri desktop build all decide this the same way. Undefined here means
|
|
3540
|
-
// PersonalAssistant falls back to DEFAULT_ONE_LOOP_MODE.
|
|
3541
|
-
oneLoopMode: config.oneLoopMode,
|
|
3542
|
-
layerPolicyMode: config.layerPolicyMode,
|
|
3543
|
-
// R7: turn-end next-step options and DONE-thread suggestions. Undefined config means the
|
|
3544
|
-
// package default (enabled); PersonalAssistant itself defaults to disabled, so this is where
|
|
3545
|
-
// the front end opts in.
|
|
3546
|
-
goalGraphSuggestMode: isGoalGraphSuggestEnabled(config.goalGraphSuggestMode) ? "enabled" : "disabled",
|
|
3547
|
-
// P11 of the internal plan — resolved through the same shared config
|
|
3548
|
-
// seam as oneLoopMode above (ASSISTANT_PLAN_MODE / `/config set planMode`). Undefined here
|
|
3549
|
-
// means PersonalAssistant falls back to DEFAULT_PLAN_MODE ('legacy').
|
|
3550
|
-
planMode: config.planMode,
|
|
3551
|
-
ambiguityGuardMode: config.ambiguityGuardMode
|
|
3552
|
-
});
|
|
3477
|
+
return PersonalAssistant.create(
|
|
3478
|
+
buildAssistantOptions(config, {
|
|
3479
|
+
llmClient,
|
|
3480
|
+
workspaceRoot,
|
|
3481
|
+
features: CLI_FEATURES,
|
|
3482
|
+
memory: new FileSystemAdapter({ backend, baseDir: dataDir, namespace: "transcripts" }),
|
|
3483
|
+
experienceStore: await FileSystemExperienceStore.create({ backend, baseDir: dataDir, namespace: "experience" }),
|
|
3484
|
+
checkpointStore: new FileSystemAdapter({ backend, baseDir: dataDir, namespace: "checkpoints" }),
|
|
3485
|
+
reminderStore: new InMemoryReminderStore(new FileSystemAdapter({ backend, baseDir: dataDir, namespace: "reminders" })),
|
|
3486
|
+
fileTools: { backend, workspaceRoot },
|
|
3487
|
+
webTools: config.enableWeb ? { search } : void 0,
|
|
3488
|
+
// executeCommand is the real child_process.spawn-based implementation (shell-executor.ts) —
|
|
3489
|
+
// wired in here, not inside assistant.ts, so the browser build never needs node:child_process.
|
|
3490
|
+
shellTools: config.enableShell ? { backend, workspaceRoot, timeoutMs: config.shellTimeoutMs, networkAllowlist: config.shellNetworkAllowlist, executeCommand: runApprovedShellCommand } : void 0,
|
|
3491
|
+
// The Resend/SMTP transport is wired in here, not inside assistant.ts, so the browser build
|
|
3492
|
+
// never needs nodemailer or a mail server — same split as shellTools' executeCommand.
|
|
3493
|
+
actionTools: (() => {
|
|
3494
|
+
const sendEmail = buildEmailSender(config);
|
|
3495
|
+
return sendEmail ? { backend, workspaceRoot, sendEmail } : void 0;
|
|
3496
|
+
})(),
|
|
3497
|
+
// Opt-in durable record of tool calls/results and approvals (see activity-log.ts).
|
|
3498
|
+
onDebugLog: activityLogEnabled(process.env) ? createActivityLogger(join(dataDir, "activity-log.jsonl")) : void 0
|
|
3499
|
+
})
|
|
3500
|
+
);
|
|
3553
3501
|
}
|
|
3554
3502
|
async function runCli(options = {}) {
|
|
3555
|
-
printSafe("Aielia is alpha software — expect rough edges and breaking changes. It uses AI models and can make mistakes; verify anything important.\n");
|
|
3556
3503
|
const dataDir = options.dataDir ?? defaultDataDir;
|
|
3557
3504
|
const configStore = options.configStore ?? defaultConfigStore;
|
|
3558
3505
|
const backend = options.backend ?? defaultBackend;
|
|
@@ -3620,25 +3567,39 @@ Fix it by setting the missing value (in the config file under ${dataDir}, or via
|
|
|
3620
3567
|
openai: OPENAI_DEFAULT_MODEL,
|
|
3621
3568
|
openrouter: OPENROUTER_DEFAULT_MODEL
|
|
3622
3569
|
};
|
|
3623
|
-
|
|
3570
|
+
const backendLine = `${config.llmBackend} · ${config.model ?? backendDisplayModel[config.llmBackend]}`;
|
|
3624
3571
|
const enabledCapabilities = [];
|
|
3625
3572
|
if (config.enableWeb) enabledCapabilities.push("web search/fetch (brave)");
|
|
3626
3573
|
if (config.enableShell) enabledCapabilities.push(`shell commands (${config.dangerouslySkipPermissions ? "NOT approval-gated" : "approval-gated"})`);
|
|
3627
|
-
const
|
|
3628
|
-
|
|
3629
|
-
const
|
|
3574
|
+
const capabilityRow = enabledCapabilities.length > 0 ? `
|
|
3575
|
+
tools ${enabledCapabilities.join(", ")}` : "";
|
|
3576
|
+
const dangerBanner = config.dangerouslySkipPermissions ? "\n ⚠ dangerouslySkipPermissions is ON — every approval prompt is skipped automatically." : "";
|
|
3577
|
+
const nonInteractiveBanner = nonInteractiveApprovalMode === "decline" ? "\n ⚠ ASSISTANT_NON_INTERACTIVE_APPROVAL=decline — every approval prompt auto-declines." : "";
|
|
3630
3578
|
const startupUndoLogEntries = await assistant.listUndoLogEntries();
|
|
3631
3579
|
const undoableFromBefore = startupUndoLogEntries.filter((e) => e.undoable).length;
|
|
3632
3580
|
const undoBanner = undoableFromBefore > 0 ? `
|
|
3633
|
-
${undoableFromBefore} action${undoableFromBefore === 1 ? "" : "s"}
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3581
|
+
undo ${undoableFromBefore} earlier action${undoableFromBefore === 1 ? "" : "s"} can be reverted with /undo-action` : "";
|
|
3582
|
+
const startupSpend = await assistant.getSpendState("cli");
|
|
3583
|
+
const fmtUsage = (input, output, cost) => `↑${input.toLocaleString()} ↓${output.toLocaleString()} tokens (~$${cost.toFixed(4)})`;
|
|
3584
|
+
const totalUsageRow = `
|
|
3585
|
+
total ${fmtUsage(startupSpend.cumulativeInputTokens, startupSpend.cumulativeOutputTokens, startupSpend.cumulativeCostUsd)} across all sessions`;
|
|
3586
|
+
printSafe(
|
|
3587
|
+
[
|
|
3588
|
+
`Aielia v${CLI_VERSION}`,
|
|
3589
|
+
"Your personal assistant, one turn at a time.",
|
|
3590
|
+
" ",
|
|
3591
|
+
` backend ${backendLine}${capabilityRow}${undoBanner}${totalUsageRow}${dangerBanner}${nonInteractiveBanner}`,
|
|
3592
|
+
" ",
|
|
3593
|
+
" /help commands /config settings Ctrl+C exit",
|
|
3594
|
+
" Alpha software: it can make mistakes, so verify anything important.",
|
|
3595
|
+
" "
|
|
3596
|
+
].join("\n")
|
|
3597
|
+
);
|
|
3638
3598
|
void assistant.proposeMemoryConsolidation("cli").catch(() => void 0);
|
|
3639
3599
|
rl.prompt();
|
|
3640
3600
|
let lastTrace;
|
|
3641
3601
|
let lastSources;
|
|
3602
|
+
let lastAnswerClaim;
|
|
3642
3603
|
let lastPlanStatus;
|
|
3643
3604
|
let pendingPlanApproval;
|
|
3644
3605
|
let lastTurnUsage;
|
|
@@ -3651,33 +3612,17 @@ ${dangerBanner}${nonInteractiveBanner}${undoBanner}`);
|
|
|
3651
3612
|
{ key: "a", label: "Yes, don't ask again this session" },
|
|
3652
3613
|
{ key: "n", label: "No" }
|
|
3653
3614
|
];
|
|
3654
|
-
function
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
}
|
|
3659
|
-
const PLAN_TASK_STATUS_ICON = {
|
|
3660
|
-
PENDING: "○",
|
|
3661
|
-
RUNNING: "▶",
|
|
3662
|
-
COMPLETE: "✓",
|
|
3663
|
-
FAILED: "✗",
|
|
3664
|
-
BLOCKED: "✗",
|
|
3665
|
-
HUMAN_REQUIRED: "~"
|
|
3666
|
-
};
|
|
3667
|
-
function printPlan() {
|
|
3615
|
+
function priceUsage(usage) {
|
|
3616
|
+
return withCostEstimate(usage, { backend: config.llmBackend, model: config.model });
|
|
3617
|
+
}
|
|
3618
|
+
function printPlan(goalGraph) {
|
|
3668
3619
|
if (!lastPlanStatus) {
|
|
3669
|
-
printSafe(
|
|
3620
|
+
printSafe(`
|
|
3621
|
+
${explainPlan({ ...lastTurnExplainInput(), goalGraph }).join("\n")}
|
|
3622
|
+
`);
|
|
3670
3623
|
return;
|
|
3671
3624
|
}
|
|
3672
|
-
const lines = [
|
|
3673
|
-
PLAN_LINE_PREFIX,
|
|
3674
|
-
`Plan: ${lastPlanStatus.templateName ?? "custom plan"} (${lastPlanStatus.completionPct.toFixed(1)}% complete)`,
|
|
3675
|
-
...lastPlanStatus.tasks.flatMap((task) => [
|
|
3676
|
-
` ${PLAN_TASK_STATUS_ICON[task.status] ?? "?"} [${task.status}] ${task.id} — ${task.description}`,
|
|
3677
|
-
...task.note ? [` not accepted as done: ${task.note}`] : []
|
|
3678
|
-
]),
|
|
3679
|
-
`Success criteria: ${lastPlanStatus.successCriteria}`
|
|
3680
|
-
];
|
|
3625
|
+
const lines = [PLAN_LINE_PREFIX, ...explainPlan(lastTurnExplainInput())];
|
|
3681
3626
|
console.log(stripTerminalControls(`
|
|
3682
3627
|
${lines.join("\n")}
|
|
3683
3628
|
`));
|
|
@@ -3692,7 +3637,7 @@ ${lines.join("\n")}
|
|
|
3692
3637
|
const result = await assistant.sketchPlan("cli", request);
|
|
3693
3638
|
console.log(stripTerminalControls(`Aielia> ${result.reply ?? "(no reply)"}
|
|
3694
3639
|
`));
|
|
3695
|
-
if (result.usage) lastTurnUsage =
|
|
3640
|
+
if (result.usage) lastTurnUsage = priceUsage(result.usage);
|
|
3696
3641
|
}
|
|
3697
3642
|
const PLAN_APPROVAL_OPTIONS = [
|
|
3698
3643
|
{ key: "y", label: "Approve" },
|
|
@@ -3757,7 +3702,7 @@ ${lines.join("\n")}
|
|
|
3757
3702
|
}
|
|
3758
3703
|
pendingPlanApproval = void 0;
|
|
3759
3704
|
lastTrace = void 0;
|
|
3760
|
-
lastNoTraceReason =
|
|
3705
|
+
lastNoTraceReason = NO_TRACE.planApproval(decision === "decline" ? "declined" : "approved");
|
|
3761
3706
|
await handleTurn(message, false, void 0, void 0, void 0, id, decision, edits);
|
|
3762
3707
|
}
|
|
3763
3708
|
async function loadPlanGraphNodes(live, threadId) {
|
|
@@ -3825,86 +3770,38 @@ ${result.lines.join("\n")}
|
|
|
3825
3770
|
printPlanApproval(pendingPlanApproval.snapshot);
|
|
3826
3771
|
return;
|
|
3827
3772
|
}
|
|
3828
|
-
printPlan();
|
|
3829
|
-
}
|
|
3830
|
-
function verificationHealthLabel({ strength, feasibility }) {
|
|
3831
|
-
const confidence = Math.min(strength, feasibility);
|
|
3832
|
-
if (confidence >= 0.7) return "High confidence";
|
|
3833
|
-
if (confidence >= 0.4) return "Reasonably confident";
|
|
3834
|
-
return "Worth double-checking";
|
|
3773
|
+
printPlan(lastPlanStatus ? void 0 : await assistant.getGoalGraphState("cli"));
|
|
3835
3774
|
}
|
|
3836
|
-
function
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3775
|
+
function lastTurnExplainInput() {
|
|
3776
|
+
return {
|
|
3777
|
+
trace: lastTrace,
|
|
3778
|
+
noTraceReason: lastNoTraceReason,
|
|
3779
|
+
answerClaim: lastAnswerClaim,
|
|
3780
|
+
memoryInjection: assistant.getLastMemoryInjection(),
|
|
3781
|
+
sources: lastSources,
|
|
3782
|
+
toolSteps: lastTurnToolSteps,
|
|
3783
|
+
planStatus: lastPlanStatus
|
|
3784
|
+
};
|
|
3841
3785
|
}
|
|
3842
3786
|
function printWhy() {
|
|
3843
|
-
const memoryLine = formatMemoryInjection(assistant.getLastMemoryInjection());
|
|
3844
|
-
if (!lastTrace) {
|
|
3845
|
-
printSafe(`
|
|
3846
|
-
${lastNoTraceReason ?? "No harness trace for the last turn (nothing to explain yet, or it took the fast path)."}
|
|
3847
|
-
${memoryLine}
|
|
3848
|
-
`);
|
|
3849
|
-
return;
|
|
3850
|
-
}
|
|
3851
3787
|
printSafe(`
|
|
3852
|
-
${
|
|
3853
|
-
|
|
3854
|
-
if (chain.length > 0) {
|
|
3855
|
-
printSafe(" " + chain.map((item) => `${LAYER_SHORT_CODE[item.layer]} (${item.reason})`).join(" > "));
|
|
3856
|
-
}
|
|
3857
|
-
if (lastTrace.batchBudget) {
|
|
3858
|
-
printSafe(" " + batchBudgetSummaryLine(lastTrace.batchBudget));
|
|
3859
|
-
}
|
|
3860
|
-
printSafe(memoryLine);
|
|
3861
|
-
printSafe("");
|
|
3788
|
+
${explainWhy(lastTurnExplainInput()).join("\n")}
|
|
3789
|
+
`);
|
|
3862
3790
|
}
|
|
3863
3791
|
function printLayers() {
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
${lastNoTraceReason ?? "No harness trace for the last turn (nothing to explain yet, or it took the fast path)."}
|
|
3792
|
+
printSafe(`
|
|
3793
|
+
${explainLayers(lastTurnExplainInput()).join("\n")}
|
|
3867
3794
|
`);
|
|
3868
|
-
return;
|
|
3869
|
-
}
|
|
3870
|
-
printSafe("");
|
|
3871
|
-
const byLayer = new Map(lastTrace.layerActivity.map((e) => [e.layer, e]));
|
|
3872
|
-
for (const layer of LAYER_ORDER) {
|
|
3873
|
-
const e = byLayer.get(layer);
|
|
3874
|
-
const mark = (e == null ? void 0 : e.fired) ? "✓" : "·";
|
|
3875
|
-
const reason = (e == null ? void 0 : e.reason) ?? "not evaluated this turn";
|
|
3876
|
-
printSafe(` [${mark}] ${LAYER_DISPLAY_NAME[layer].padEnd(22)} ${reason}`);
|
|
3877
|
-
}
|
|
3878
|
-
if (lastTrace.batchBudget) {
|
|
3879
|
-
printSafe("");
|
|
3880
|
-
printSafe(` ${batchBudgetSummaryLine(lastTrace.batchBudget)}`);
|
|
3881
|
-
const STATUS_MARK = {
|
|
3882
|
-
found: "✓",
|
|
3883
|
-
not_found: "✗",
|
|
3884
|
-
truncated_while_productive: "~"
|
|
3885
|
-
};
|
|
3886
|
-
for (const outcome of lastTrace.batchBudget.perItemOutcomes) {
|
|
3887
|
-
printSafe(` [${STATUS_MARK[outcome.status]}] ${outcome.item.padEnd(30)} ${outcome.status} (${outcome.callsUsed} calls)`);
|
|
3888
|
-
}
|
|
3889
|
-
}
|
|
3890
|
-
printSafe("");
|
|
3891
3795
|
}
|
|
3892
|
-
const SOURCE_TOOL_LABEL = {
|
|
3893
|
-
read_file: "Read",
|
|
3894
|
-
list_directory: "Listed",
|
|
3895
|
-
web_search: "Searched",
|
|
3896
|
-
fetch_url: "Fetched"
|
|
3897
|
-
};
|
|
3898
3796
|
function printSources() {
|
|
3899
|
-
|
|
3900
|
-
|
|
3901
|
-
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
printSafe("");
|
|
3797
|
+
printSafe(`
|
|
3798
|
+
${explainSources(lastTurnExplainInput()).join("\n")}
|
|
3799
|
+
`);
|
|
3800
|
+
}
|
|
3801
|
+
function printSteps() {
|
|
3802
|
+
printSafe(`
|
|
3803
|
+
${explainSteps(lastTurnExplainInput()).join("\n")}
|
|
3804
|
+
`);
|
|
3908
3805
|
}
|
|
3909
3806
|
function printHelp() {
|
|
3910
3807
|
printSafe(`
|
|
@@ -3979,12 +3876,12 @@ ${formatStatus({ config, overriddenKeys, transcriptLength: transcript.length, pl
|
|
|
3979
3876
|
}
|
|
3980
3877
|
}
|
|
3981
3878
|
async function handleUndo() {
|
|
3982
|
-
const
|
|
3983
|
-
if (
|
|
3879
|
+
const plan = planUndo(await assistant.getTranscript("cli"));
|
|
3880
|
+
if (plan.nothingToUndo) {
|
|
3984
3881
|
printSafe("\nNothing to undo.\n");
|
|
3985
3882
|
return;
|
|
3986
3883
|
}
|
|
3987
|
-
const wasPendingApproval =
|
|
3884
|
+
const { wasPendingApproval } = plan;
|
|
3988
3885
|
const undoneReminders = lastTurnToolSteps.filter((s) => s.tool === "create_reminder");
|
|
3989
3886
|
const result = await assistant.undoLastTurn("cli");
|
|
3990
3887
|
if (!result.undone) {
|
|
@@ -4003,14 +3900,15 @@ ${formatStatus({ config, overriddenKeys, transcriptLength: transcript.length, pl
|
|
|
4003
3900
|
);
|
|
4004
3901
|
}
|
|
4005
3902
|
async function handleUndoAction(args) {
|
|
4006
|
-
|
|
3903
|
+
const command = parseUndoActionCommand(args);
|
|
3904
|
+
if (command.kind === "list") {
|
|
4007
3905
|
const entries = await assistant.listUndoLogEntries();
|
|
4008
3906
|
printSafe(`
|
|
4009
3907
|
${formatUndoLogListing(entries)}
|
|
4010
3908
|
`);
|
|
4011
3909
|
return;
|
|
4012
3910
|
}
|
|
4013
|
-
const staged = await assistant.stageUndoAction(
|
|
3911
|
+
const staged = await assistant.stageUndoAction(command.id);
|
|
4014
3912
|
if (staged.status === "error") {
|
|
4015
3913
|
printSafe(`
|
|
4016
3914
|
✗ ${staged.message}
|
|
@@ -4021,7 +3919,7 @@ ${formatUndoLogListing(entries)}
|
|
|
4021
3919
|
[needs approval — revert] ${staged.reason}`));
|
|
4022
3920
|
const confirmed = await askYesNo("Apply this revert? (y/N) ");
|
|
4023
3921
|
lastTrace = void 0;
|
|
4024
|
-
lastNoTraceReason =
|
|
3922
|
+
lastNoTraceReason = NO_TRACE.stagedAction("revert", confirmed ? "approved" : "declined");
|
|
4025
3923
|
await handleTurn("", confirmed, staged.pendingActionId);
|
|
4026
3924
|
}
|
|
4027
3925
|
async function printMemory() {
|
|
@@ -4240,24 +4138,8 @@ ${formatDoctorReport(checks)}
|
|
|
4240
4138
|
}
|
|
4241
4139
|
lastTurnToolSteps.push(step);
|
|
4242
4140
|
}
|
|
4243
|
-
function emptyClarificationDraft() {
|
|
4244
|
-
return { selectedLabels: [], editText: "", freeText: "" };
|
|
4245
|
-
}
|
|
4246
|
-
function orderedAskOptions(question) {
|
|
4247
|
-
const options2 = question.options ?? [];
|
|
4248
|
-
return options2.map((option, index) => ({ option, index })).sort((a, b) => Number(b.option.recommended ?? false) - Number(a.option.recommended ?? false) || a.index - b.index).map(({ option }) => option);
|
|
4249
|
-
}
|
|
4250
|
-
function clarificationDraftToAnswer(questionId, draft) {
|
|
4251
|
-
if (draft.selectedLabels.length > 0) {
|
|
4252
|
-
return draft.editText.trim() ? { questionId, kind: "selected_with_edit", selectedLabels: draft.selectedLabels, editText: draft.editText.trim() } : { questionId, kind: "selected", selectedLabels: draft.selectedLabels };
|
|
4253
|
-
}
|
|
4254
|
-
if (draft.freeText.trim()) {
|
|
4255
|
-
return { questionId, kind: "free_text", freeText: draft.freeText.trim() };
|
|
4256
|
-
}
|
|
4257
|
-
return null;
|
|
4258
|
-
}
|
|
4259
4141
|
function printClarificationQuestion(question, draft, index, total) {
|
|
4260
|
-
const options2 =
|
|
4142
|
+
const options2 = orderedOptions(question);
|
|
4261
4143
|
const allowFreeText = question.allowFreeText !== false;
|
|
4262
4144
|
printSafe("");
|
|
4263
4145
|
if (question.header) console.log(stripTerminalControls(`[${question.header}]`));
|
|
@@ -4287,9 +4169,10 @@ ${formatDoctorReport(checks)}
|
|
|
4287
4169
|
const pendingClarificationId = result.pendingClarificationId;
|
|
4288
4170
|
if (questions.length === 0 || !pendingClarificationId) {
|
|
4289
4171
|
lastTrace = void 0;
|
|
4290
|
-
|
|
4172
|
+
const unanswerable = presentTurnResult(result);
|
|
4173
|
+
lastNoTraceReason = unanswerable.noTraceReason;
|
|
4291
4174
|
console.log(stripTerminalControls(`
|
|
4292
|
-
[needs clarification] ${
|
|
4175
|
+
[needs clarification] ${unanswerable.kind === "escalation" ? unanswerable.reason : DEFAULT_CLARIFICATION_REASON}
|
|
4293
4176
|
`));
|
|
4294
4177
|
return;
|
|
4295
4178
|
}
|
|
@@ -4306,7 +4189,7 @@ ${formatDoctorReport(checks)}
|
|
|
4306
4189
|
}
|
|
4307
4190
|
printSafe(`
|
|
4308
4191
|
[needs clarification] ${questions.length} question${questions.length === 1 ? "" : "s"} to answer.`);
|
|
4309
|
-
const drafts = new Map(questions.map((q2) => [q2.id,
|
|
4192
|
+
const drafts = new Map(questions.map((q2) => [q2.id, emptyDraft()]));
|
|
4310
4193
|
let index = 0;
|
|
4311
4194
|
while (true) {
|
|
4312
4195
|
const question = questions[index];
|
|
@@ -4321,7 +4204,7 @@ ${formatDoctorReport(checks)}
|
|
|
4321
4204
|
return;
|
|
4322
4205
|
}
|
|
4323
4206
|
if (lower === "s" || lower === "submit") {
|
|
4324
|
-
const answers = questions.map((q2) =>
|
|
4207
|
+
const answers = questions.map((q2) => draftToAnswer(q2.id, drafts.get(q2.id)));
|
|
4325
4208
|
const missing = questions.filter((q2, i) => answers[i] === null);
|
|
4326
4209
|
if (missing.length > 0) {
|
|
4327
4210
|
printSafe(`
|
|
@@ -4356,7 +4239,7 @@ Still need an answer for: ${missing.map((q2) => q2.question).join("; ")}
|
|
|
4356
4239
|
}
|
|
4357
4240
|
const editMatch = /^e(\d+)$/i.exec(token);
|
|
4358
4241
|
if (editMatch) {
|
|
4359
|
-
const options2 =
|
|
4242
|
+
const options2 = orderedOptions(question);
|
|
4360
4243
|
const option = options2[Number(editMatch[1]) - 1];
|
|
4361
4244
|
if (!option) {
|
|
4362
4245
|
printSafe(`
|
|
@@ -4376,7 +4259,7 @@ Select option ${editMatch[1]} first, then add a note with e${editMatch[1]}.
|
|
|
4376
4259
|
}
|
|
4377
4260
|
const toggleMatch = /^t(\d+)$/i.exec(token) ?? /^(\d+)$/.exec(token);
|
|
4378
4261
|
if (toggleMatch) {
|
|
4379
|
-
const options2 =
|
|
4262
|
+
const options2 = orderedOptions(question);
|
|
4380
4263
|
const option = options2[Number(toggleMatch[1]) - 1];
|
|
4381
4264
|
if (!option) {
|
|
4382
4265
|
printSafe(`
|
|
@@ -4447,8 +4330,7 @@ Unrecognized input "${token}".
|
|
|
4447
4330
|
});
|
|
4448
4331
|
if (!streamedAnyTokens) clearProgress();
|
|
4449
4332
|
if (result.status === "needs_approval" && result.pendingActionId) {
|
|
4450
|
-
const kindLabel
|
|
4451
|
-
const promptText = result.pendingActionKind === "shell" ? "Run this command?" : result.pendingActionKind === "email" ? "Send this email?" : result.pendingActionKind === "batch" ? "Continue?" : "Apply this write?";
|
|
4333
|
+
const { kindLabel, promptText } = approvalLabels(result.pendingActionKind);
|
|
4452
4334
|
console.log(stripTerminalControls(`
|
|
4453
4335
|
[needs approval — ${kindLabel}] ${result.reason}`));
|
|
4454
4336
|
let confirmed;
|
|
@@ -4461,7 +4343,7 @@ Unrecognized input "${token}".
|
|
|
4461
4343
|
if (decision === "a" && result.pendingActionKind) rememberedActionKinds.add(result.pendingActionKind);
|
|
4462
4344
|
}
|
|
4463
4345
|
lastTrace = void 0;
|
|
4464
|
-
lastNoTraceReason =
|
|
4346
|
+
lastNoTraceReason = NO_TRACE.stagedAction(kindLabel, confirmed ? "approved" : "declined");
|
|
4465
4347
|
await handleTurn(message, confirmed, result.pendingActionId);
|
|
4466
4348
|
return;
|
|
4467
4349
|
}
|
|
@@ -4482,7 +4364,7 @@ Unrecognized input "${token}".
|
|
|
4482
4364
|
await handleTurn(message, true);
|
|
4483
4365
|
} else {
|
|
4484
4366
|
lastTrace = void 0;
|
|
4485
|
-
lastNoTraceReason = "
|
|
4367
|
+
lastNoTraceReason = NO_TRACE.messageApproval("declined");
|
|
4486
4368
|
await assistant.recordDeclinedRequest("cli", message, result.reason ?? "This request needed approval.");
|
|
4487
4369
|
printSafe("Cancelled.\n");
|
|
4488
4370
|
}
|
|
@@ -4495,7 +4377,7 @@ Unrecognized input "${token}".
|
|
|
4495
4377
|
if (result.status === "needs_plan_approval") {
|
|
4496
4378
|
if (!result.planApprovalId) {
|
|
4497
4379
|
printSafe(`
|
|
4498
|
-
[needs plan approval] ${result.reason ??
|
|
4380
|
+
[needs plan approval] ${result.reason ?? MISSING_PLAN_APPROVAL_ID_REASON}
|
|
4499
4381
|
`);
|
|
4500
4382
|
return;
|
|
4501
4383
|
}
|
|
@@ -4506,7 +4388,7 @@ ${result.reason}`);
|
|
|
4506
4388
|
if (snapshot) printPlanApproval(snapshot);
|
|
4507
4389
|
pendingPlanApproval = { id, message, snapshot };
|
|
4508
4390
|
lastTrace = void 0;
|
|
4509
|
-
lastNoTraceReason =
|
|
4391
|
+
lastNoTraceReason = NO_TRACE.planApproval(void 0, " (pending /plan approve|decline|edit)");
|
|
4510
4392
|
if (!snapshot) {
|
|
4511
4393
|
printSafe("Decide with /plan approve or /plan decline.\n");
|
|
4512
4394
|
return;
|
|
@@ -4529,44 +4411,48 @@ ${result.reason}`);
|
|
|
4529
4411
|
} else {
|
|
4530
4412
|
decision = "decline";
|
|
4531
4413
|
}
|
|
4532
|
-
lastNoTraceReason =
|
|
4414
|
+
lastNoTraceReason = NO_TRACE.planApproval(decision === "decline" ? "declined" : "approved");
|
|
4533
4415
|
await handleTurn(message, false, void 0, void 0, void 0, id, decision, edits);
|
|
4534
4416
|
return;
|
|
4535
4417
|
}
|
|
4536
4418
|
if (result.status === "escalated") {
|
|
4537
4419
|
lastTrace = void 0;
|
|
4538
|
-
|
|
4420
|
+
const escalation = presentTurnResult(result);
|
|
4421
|
+
lastNoTraceReason = escalation.noTraceReason;
|
|
4539
4422
|
console.log(stripTerminalControls(`
|
|
4540
|
-
[escalated] ${result.reason}
|
|
4423
|
+
[escalated] ${escalation.kind === "escalation" ? escalation.reason : result.reason}
|
|
4541
4424
|
`));
|
|
4542
4425
|
return;
|
|
4543
4426
|
}
|
|
4544
4427
|
if (!pendingActionId) {
|
|
4545
4428
|
lastTrace = result.harnessSkipped ? void 0 : result.trace;
|
|
4546
|
-
|
|
4429
|
+
lastAnswerClaim = result.answerClaim;
|
|
4430
|
+
lastNoTraceReason = result.harnessSkipped ? NO_TRACE.fastPath : void 0;
|
|
4547
4431
|
}
|
|
4548
4432
|
lastSources = result.sources;
|
|
4549
4433
|
if (!pendingActionId && (!result.harnessSkipped || result.planStatus)) lastPlanStatus = result.planStatus;
|
|
4550
|
-
lastTurnUsage = result.usage ?
|
|
4434
|
+
lastTurnUsage = result.usage ? priceUsage(result.usage) : void 0;
|
|
4435
|
+
const shown = presentTurnResult(result);
|
|
4436
|
+
const hints = shown.kind === "reply" ? shown.hints : {};
|
|
4551
4437
|
const riskSuffix = result.riskLevel && result.riskLevel !== "LOW" ? ` [risk: ${result.riskLevel}]` : "";
|
|
4552
|
-
const sourcesHint =
|
|
4553
|
-
const planHint =
|
|
4554
|
-
const contradictionNotice =
|
|
4438
|
+
const sourcesHint = hints.sourcesCount ? ` (${hints.sourcesCount} source${hints.sourcesCount > 1 ? "s" : ""} — /sources)` : "";
|
|
4439
|
+
const planHint = hints.planCompletionPct !== void 0 ? ` (plan: ${hints.planCompletionPct.toFixed(0)}% — /plan)` : "";
|
|
4440
|
+
const contradictionNotice = hints.contradictionNotice ? `
|
|
4555
4441
|
|
|
4556
|
-
${
|
|
4557
|
-
const reviewNotice = (
|
|
4442
|
+
${hints.contradictionNotice}` : "";
|
|
4443
|
+
const reviewNotice = (hints.reviewNotice ? `
|
|
4558
4444
|
|
|
4559
|
-
${
|
|
4445
|
+
${hints.reviewNotice}` : "") + (hints.auditNotice ? `
|
|
4560
4446
|
|
|
4561
|
-
${
|
|
4562
|
-
lastNextSteps =
|
|
4447
|
+
${hints.auditNotice}` : "");
|
|
4448
|
+
lastNextSteps = hints.nextSteps;
|
|
4563
4449
|
const nextStepsBlock = lastNextSteps ? `
|
|
4564
4450
|
|
|
4565
4451
|
${formatNextSteps(lastNextSteps)}` : "";
|
|
4566
4452
|
if (streamedAnyTokens) {
|
|
4567
|
-
const pausedNoteText =
|
|
4453
|
+
const pausedNoteText = hints.pausedNote ? `
|
|
4568
4454
|
|
|
4569
|
-
${
|
|
4455
|
+
${hints.pausedNote}` : "";
|
|
4570
4456
|
process.stdout.write(stripTerminalControls(`${pausedNoteText}${riskSuffix}${sourcesHint}${planHint}${contradictionNotice}${reviewNotice}${nextStepsBlock}
|
|
4571
4457
|
|
|
4572
4458
|
`));
|
|
@@ -4788,17 +4674,12 @@ ${config.model ?? "(using each backend's default)"}
|
|
|
4788
4674
|
await handleConfigCommand(["set", "model", args.join(" ")]);
|
|
4789
4675
|
}
|
|
4790
4676
|
async function handleProject(args) {
|
|
4791
|
-
|
|
4792
|
-
|
|
4793
|
-
${
|
|
4677
|
+
const command = parseProjectCommand(args, assistant.getActiveProject());
|
|
4678
|
+
if (command.kind === "show") printSafe(`
|
|
4679
|
+
${command.message}
|
|
4794
4680
|
`);
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
if (args[0] === "clear") {
|
|
4798
|
-
await handleConfigCommand(["reset", "activeProject"]);
|
|
4799
|
-
return;
|
|
4800
|
-
}
|
|
4801
|
-
await handleConfigCommand(["set", "activeProject", args.join(" ")]);
|
|
4681
|
+
else if (command.kind === "clear") await handleConfigCommand(["reset", "activeProject"]);
|
|
4682
|
+
else await handleConfigCommand(["set", "activeProject", command.project]);
|
|
4802
4683
|
}
|
|
4803
4684
|
let turnInProgress = false;
|
|
4804
4685
|
let lastNextSteps;
|
|
@@ -4808,6 +4689,7 @@ ${assistant.getActiveProject() || "(none)"}
|
|
|
4808
4689
|
// Bare /layers is the last-turn fired/skipped view; its subcommands (settings/on/off/reset) edit the on/off choices.
|
|
4809
4690
|
"/layers": (args) => args.length === 0 ? printLayers() : handleLayers(args),
|
|
4810
4691
|
"/sources": () => printSources(),
|
|
4692
|
+
"/steps": () => printSteps(),
|
|
4811
4693
|
"/plan": (args) => handlePlan(args),
|
|
4812
4694
|
"/help": () => printHelp(),
|
|
4813
4695
|
"/clear": () => handleClear(),
|
|
@@ -4897,6 +4779,7 @@ ${assistant.getActiveProject() || "(none)"}
|
|
|
4897
4779
|
});
|
|
4898
4780
|
rl.resume();
|
|
4899
4781
|
return {
|
|
4782
|
+
commandNames: Object.keys(commands),
|
|
4900
4783
|
dispatchLine: async (line) => {
|
|
4901
4784
|
const message = line.trim();
|
|
4902
4785
|
if (!message) return;
|
|
@@ -4912,7 +4795,11 @@ ${assistant.getActiveProject() || "(none)"}
|
|
|
4912
4795
|
indicators.push(`Model: ${config.model ?? backendDisplayModel[config.llmBackend]}`);
|
|
4913
4796
|
const spendState = await assistant.getSpendState("cli");
|
|
4914
4797
|
indicators.push(
|
|
4915
|
-
|
|
4798
|
+
`This session: ${fmtUsage(
|
|
4799
|
+
spendState.cumulativeInputTokens - startupSpend.cumulativeInputTokens,
|
|
4800
|
+
spendState.cumulativeOutputTokens - startupSpend.cumulativeOutputTokens,
|
|
4801
|
+
spendState.cumulativeCostUsd - startupSpend.cumulativeCostUsd
|
|
4802
|
+
)}`
|
|
4916
4803
|
);
|
|
4917
4804
|
const spendCapLine = formatSpendCapStatus(spendState, { sessionCostLimitUsd: config.sessionCostLimitUsd, sessionCallLimit: config.sessionCallLimit });
|
|
4918
4805
|
if (spendCapLine) indicators.push(spendCapLine);
|
|
@@ -4956,7 +4843,7 @@ async function mainInner(argv) {
|
|
|
4956
4843
|
});
|
|
4957
4844
|
}
|
|
4958
4845
|
if (shouldLaunchTuiApp(config.tuiMode ?? DEFAULT_TUI_MODE, Boolean(process.stdout.isTTY), Boolean(process.stdin.isTTY))) {
|
|
4959
|
-
const { runTuiApp } = await import("./tui-app-
|
|
4846
|
+
const { runTuiApp } = await import("./tui-app-Dt72u8vZ.js");
|
|
4960
4847
|
await runTuiApp();
|
|
4961
4848
|
return;
|
|
4962
4849
|
}
|
|
@@ -4983,4 +4870,4 @@ export {
|
|
|
4983
4870
|
sanitizeLabel as s,
|
|
4984
4871
|
toLines as t
|
|
4985
4872
|
};
|
|
4986
|
-
//# sourceMappingURL=bin-
|
|
4873
|
+
//# sourceMappingURL=bin-CCwDFxDe.js.map
|