@buildaharness/aielia 0.3.8 → 0.3.10
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/_memory-core-generated.d.ts +6 -0
- 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/assistant.d.ts +11 -0
- package/dist/{bin-DETwedpj.js → bin-Cz3FY6Ew.js} +144 -254
- package/dist/bin-Cz3FY6Ew.js.map +1 -0
- package/dist/claude-cli-llm-client.d.ts +2 -0
- package/dist/claude-cli-prompt.d.ts +7 -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/fact-repository.contract.d.ts +2 -0
- package/dist/fact-repository.d.ts +44 -0
- package/dist/file-tools-mcp-server.mjs +29 -0
- package/dist/goal-graph-store.d.ts +6 -0
- package/dist/harness-bridge.d.ts +5 -5
- package/dist/html-to-markdown.d.ts +11 -0
- package/dist/index.d.ts +98 -3
- package/dist/index.js +5003 -150
- package/dist/index.js.map +1 -1
- package/dist/layer-settings.d.ts +16 -3
- package/dist/llm-client-factory.d.ts +13 -0
- package/dist/memory-events.d.ts +177 -0
- package/dist/memory-service.d.ts +17 -0
- package/dist/model-pricing.d.ts +15 -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-DG8iYm_F.js} +14471 -13032
- package/dist/provider-setup-DG8iYm_F.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/scripted-llm-client.d.ts +1 -1
- package/dist/{tui-app-CcxiwZyM.js → tui-app-oWbIUcBW.js} +3 -3
- package/dist/{tui-app-CcxiwZyM.js.map → tui-app-oWbIUcBW.js.map} +1 -1
- package/dist/turn-abort.d.ts +5 -0
- 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/dist/web-fetch-core.d.ts +0 -14
- package/dist/writer/article-autosave.d.ts +12 -0
- package/dist/writer/article-change-summary.d.ts +28 -0
- package/dist/writer/article-claims.d.ts +49 -0
- package/dist/writer/article-comments.d.ts +20 -0
- package/dist/writer/article-consistency.d.ts +27 -0
- package/dist/writer/article-decorations.d.ts +23 -0
- package/dist/writer/article-dependencies.d.ts +44 -0
- package/dist/writer/article-draft.d.ts +23 -0
- package/dist/writer/article-edit-outline.d.ts +16 -0
- package/dist/writer/article-edit-suggest.d.ts +30 -0
- package/dist/writer/article-folder.d.ts +29 -0
- package/dist/writer/article-history.d.ts +73 -0
- package/dist/writer/article-ideas.d.ts +34 -0
- package/dist/writer/article-issues.d.ts +47 -0
- package/dist/writer/article-marks.d.ts +25 -0
- package/dist/writer/article-memory-store.d.ts +3 -0
- package/dist/writer/article-model.d.ts +1337 -0
- package/dist/writer/article-outline.d.ts +43 -0
- package/dist/writer/article-resolver.d.ts +55 -0
- package/dist/writer/article-revisions.d.ts +30 -0
- package/dist/writer/article-rules.d.ts +60 -0
- package/dist/writer/article-sections.d.ts +26 -0
- package/dist/writer/article-selection.d.ts +26 -0
- package/dist/writer/article-service.d.ts +542 -0
- package/dist/writer/article-source-links.d.ts +42 -0
- package/dist/writer/article-sources.d.ts +82 -0
- package/dist/writer/article-style-derive.d.ts +26 -0
- package/dist/writer/article-style.d.ts +31 -0
- package/dist/writer/article-suggestions.d.ts +33 -0
- package/dist/writer/article-support.d.ts +33 -0
- package/dist/writer/article-verify.d.ts +42 -0
- package/dist/writer/local-folder.d.ts +49 -0
- package/dist/writer/model-failure-hint.d.ts +7 -0
- package/dist/writer/repo-reader.d.ts +29 -0
- package/dist/writer/repo-search.d.ts +33 -0
- package/dist/writer/repo-verify-loop.d.ts +61 -0
- package/dist/writer/text-tool-calls.d.ts +11 -0
- package/dist/writer/work-progress.d.ts +51 -0
- package/dist/writer/write-activity.d.ts +61 -0
- package/dist/writer/write-models.d.ts +12 -0
- package/dist/writer/write-parameters.d.ts +31 -0
- package/dist/writer/write-permissions.d.ts +89 -0
- package/dist/writer/write-spend.d.ts +16 -0
- package/dist/writer/writer-chat-capture.d.ts +25 -0
- package/dist/writer/writer-chat-history.d.ts +17 -0
- package/dist/writer/writer-chat-state.d.ts +358 -0
- package/dist/writer/writer-chat-turn.d.ts +52 -0
- package/dist/writer/writer-intent.d.ts +20 -0
- package/package.json +3 -3
- package/dist/bin-DETwedpj.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 { ap as buildClaudePrompt, cU as stripJsonCodeFence, ct as recallToolEnabled, bT as lexicalOffEnvValue, a as ALREADY_STAGED_ACTION_TOOL, cR as stagedActionInput, az as claudeFailureMessage, ch as parseClaudeCliOutput, cV as stripMcpToolPrefix, c0 as memoryStatusChecks, cd as normalizePlanNodes, X as PROVIDER_SETUP, aA as cleanApiKey, as as checkApiKeyFormat, aV as envOverridesFromProcessEnv, cA as resolveConfig, cP as shouldLaunchTuiApp, t as DEFAULT_TUI_MODE, ag as applyLayerSettings, cN as sanitizeLayerChoices, c_ as testApiKey, d2 as validateConfig, bb as findInvalidNumericSettings, f as ConfigValidationError, by as formatSpendCapStatus, bN as isPlanGraphEnabled, Z as PersonalAssistant, ao as buildAssistantOptions, cW as stripTerminalControls, bJ as isGoalGraphEnabled, cp as planToSnapshot, aE as createLlmClient, aI as createSmtpSender, aH as createResendSender, bg as formatConfigListing, bI as isConfigKey, e as CONFIG_KEYS, x as ENV_VAR_FOR_CONFIG_KEY, ci as parseConfigValue, g as ConfigValueParseError, at as checkProxyHealth, bi as formatDoctorReport, bh as formatCostSummary, ck as parseProjectCommand, bk as formatGoalGraphState, bx as formatSearchResults, bo as formatMemoryEvents, bq as formatMemoryHistory, bt as formatMemoryStatus, bs as formatMemoryPendingOutcome, bn as formatMemoryArchive, cm as parseUndoActionCommand, bB as formatUndoLogListing, cq as planUndo, aL as defaultExportFilename, bA as formatTranscriptMarkdown, au as classifyError, bz as formatStatus, bl as formatHelp, b5 as explainSteps, b4 as explainSources, b2 as explainLayers, bm as formatLayerListing, d5 as withLayerChoice, P as LayerSettingError, bR as layerWarnings, b6 as explainWhy, bP as isQuitCommand, Q as LiveSteeringChannel, aM as defaultMemoryExportFilename, bp as formatMemoryExport, b$ as memoryAuditLogEnabled, bu as formatMemorySummary, ai as approvalLabels, W as NO_TRACE, S as MISSING_PLAN_APPROVAL_ID_REASON, cr as presentTurnResult, bv as formatNextSteps, b3 as explainPlan, c3 as nodeToLayer, L as LAYER_DISPLAY_NAME, c2 as nodeDisplayName, j as DEFAULT_CLARIFICATION_REASON, aS as emptyDraft, aQ as draftToAnswer, cg as orderedOptions, d4 as withCostEstimate, C as CLI_FEATURES, an as braveSearch } from "./provider-setup-DG8iYm_F.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.10";
|
|
133
133
|
function seaCacheDir(version, home = homedir()) {
|
|
134
134
|
return join(home, ".buildaharness", "personal-assistant", "sea-cache", version);
|
|
135
135
|
}
|
|
@@ -166,9 +166,15 @@ function resolveMcpServerPath(seaOverride, home) {
|
|
|
166
166
|
return fileURLToPath(new URL(MCP_SERVER_FILE_NAME, import.meta.url));
|
|
167
167
|
}
|
|
168
168
|
const EMPTY_MCP_CONFIG = JSON.stringify({ mcpServers: {} });
|
|
169
|
-
function
|
|
169
|
+
function killOnAbort(proc, signal) {
|
|
170
|
+
if (!signal) return;
|
|
171
|
+
if (signal.aborted) proc.kill();
|
|
172
|
+
else signal.addEventListener("abort", () => proc.kill(), { once: true });
|
|
173
|
+
}
|
|
174
|
+
function invokeClaude(claudePath, args, signal) {
|
|
170
175
|
return new Promise((resolvePromise, reject) => {
|
|
171
176
|
const proc = spawn(claudePath, args, { cwd: tmpdir(), stdio: ["ignore", "pipe", "pipe"] });
|
|
177
|
+
killOnAbort(proc, signal);
|
|
172
178
|
let stdout = "";
|
|
173
179
|
let stderr = "";
|
|
174
180
|
proc.stdout.on("data", (chunk) => {
|
|
@@ -180,16 +186,17 @@ function invokeClaude(claudePath, args) {
|
|
|
180
186
|
proc.on("error", reject);
|
|
181
187
|
proc.on("close", (code) => {
|
|
182
188
|
if (code !== 0) {
|
|
183
|
-
reject(new Error(
|
|
189
|
+
reject(new Error(claudeFailureMessage(stdout, stderr, code)));
|
|
184
190
|
return;
|
|
185
191
|
}
|
|
186
192
|
resolvePromise(parseClaudeCliOutput(stdout));
|
|
187
193
|
});
|
|
188
194
|
});
|
|
189
195
|
}
|
|
190
|
-
function invokeClaudeStreaming(claudePath, args, onToolStep) {
|
|
196
|
+
function invokeClaudeStreaming(claudePath, args, onToolStep, signal) {
|
|
191
197
|
return new Promise((resolvePromise, reject) => {
|
|
192
198
|
const proc = spawn(claudePath, args, { cwd: tmpdir(), stdio: ["ignore", "pipe", "pipe"] });
|
|
199
|
+
killOnAbort(proc, signal);
|
|
193
200
|
let buffer = "";
|
|
194
201
|
let stderr = "";
|
|
195
202
|
let finalResultLine;
|
|
@@ -229,7 +236,7 @@ function invokeClaudeStreaming(claudePath, args, onToolStep) {
|
|
|
229
236
|
proc.on("error", reject);
|
|
230
237
|
proc.on("close", (code) => {
|
|
231
238
|
if (code !== 0) {
|
|
232
|
-
reject(new Error(
|
|
239
|
+
reject(new Error(claudeFailureMessage(finalResultLine ?? "", stderr, code)));
|
|
233
240
|
return;
|
|
234
241
|
}
|
|
235
242
|
handleLine(buffer);
|
|
@@ -312,6 +319,8 @@ function startToolGateServer(onToolProposal, onToolResult, onToolExecute) {
|
|
|
312
319
|
}
|
|
313
320
|
class ClaudeCliLLMClient {
|
|
314
321
|
constructor(options = {}) {
|
|
322
|
+
/** Runs its own tool loop inside `claude -p`; it cannot return tool calls to a caller's loop, so those callers use text tool calls (see writer/text-tool-calls.ts). */
|
|
323
|
+
__publicField(this, "nativeToolCalls", false);
|
|
315
324
|
__publicField(this, "claudePath");
|
|
316
325
|
__publicField(this, "fileTools");
|
|
317
326
|
__publicField(this, "remindersFile");
|
|
@@ -356,7 +365,7 @@ class ClaudeCliLLMClient {
|
|
|
356
365
|
const model = options.model ?? this.model;
|
|
357
366
|
if (model) args.push("--model", model);
|
|
358
367
|
args.push("--", prompt);
|
|
359
|
-
const { reply, usage, model: resolved } = await invokeClaude(this.claudePath, args);
|
|
368
|
+
const { reply, usage, model: resolved } = await invokeClaude(this.claudePath, args, options.signal);
|
|
360
369
|
if (resolved) this.resolvedModelId = resolved;
|
|
361
370
|
if (usage) (_a = options.onUsage) == null ? void 0 : _a.call(options, usage);
|
|
362
371
|
return reply;
|
|
@@ -414,7 +423,9 @@ class ClaudeCliLLMClient {
|
|
|
414
423
|
// M3: recall_memory is registered (gated, then served by the parent via onToolExecute) only under AUDIT_RECALL_TOOL.
|
|
415
424
|
...recallToolEnabled() ? { ENABLE_RECALL_TOOL: "1" } : {},
|
|
416
425
|
// Always passed (even empty): the server reads an unset value as the default, every family off.
|
|
417
|
-
ASSISTANT_LEXICAL_RESOLVED_OFF: lexicalOffEnvValue()
|
|
426
|
+
ASSISTANT_LEXICAL_RESOLVED_OFF: lexicalOffEnvValue(),
|
|
427
|
+
// Eval harness only: absent in the product, so the env block is unchanged.
|
|
428
|
+
...process.env.BENCHMARK_TOOL_FAILURE ? { BENCHMARK_TOOL_FAILURE: process.env.BENCHMARK_TOOL_FAILURE } : {}
|
|
418
429
|
}
|
|
419
430
|
}
|
|
420
431
|
}
|
|
@@ -443,7 +454,7 @@ class ClaudeCliLLMClient {
|
|
|
443
454
|
if (model) args.push("--model", model);
|
|
444
455
|
args.push("--", prompt);
|
|
445
456
|
const callStartedAt = Date.now();
|
|
446
|
-
const { reply, usage, model: resolved } = await invokeClaudeStreaming(this.claudePath, args, options.onToolStep);
|
|
457
|
+
const { reply, usage, model: resolved } = await invokeClaudeStreaming(this.claudePath, args, options.onToolStep, options.signal);
|
|
447
458
|
if (resolved) this.resolvedModelId = resolved;
|
|
448
459
|
if (usage) (_f = options.onUsage) == null ? void 0 : _f.call(options, usage);
|
|
449
460
|
const staged = await this.findPendingActionStagedSince(workspaceRoot, callStartedAt);
|
|
@@ -699,22 +710,6 @@ class NodeConfigStore {
|
|
|
699
710
|
}
|
|
700
711
|
}
|
|
701
712
|
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
713
|
function checkClaudeCli(claudePath) {
|
|
719
714
|
const label = `claude binary (${claudePath})`;
|
|
720
715
|
return new Promise((resolvePromise) => {
|
|
@@ -3475,81 +3470,45 @@ function buildEmailSender(config) {
|
|
|
3475
3470
|
return void 0;
|
|
3476
3471
|
}
|
|
3477
3472
|
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
|
-
}
|
|
3473
|
+
return createLlmClient(config, {
|
|
3474
|
+
claudeCli: () => new ClaudeCliLLMClient({
|
|
3475
|
+
fileTools: { workspaceRoot },
|
|
3476
|
+
remindersFile,
|
|
3477
|
+
shellTools: config.enableShell ? { workspaceRoot } : void 0,
|
|
3478
|
+
webTools: config.enableWeb ? { braveApiKey: config.braveApiKey } : void 0,
|
|
3479
|
+
actionTools: config.enableEmail ? { workspaceRoot } : void 0
|
|
3480
|
+
})
|
|
3481
|
+
});
|
|
3501
3482
|
}
|
|
3502
3483
|
async function buildAssistant(config, { backend, dataDir, remindersFile }) {
|
|
3503
3484
|
const workspaceRoot = config.workspaceRoot ?? process.cwd();
|
|
3504
3485
|
if (backend === defaultBackend) excludeAieliaStateFromGit(workspaceRoot);
|
|
3505
3486
|
const search = (query) => braveSearch(query, config.braveApiKey);
|
|
3506
3487
|
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
|
-
});
|
|
3488
|
+
return PersonalAssistant.create(
|
|
3489
|
+
buildAssistantOptions(config, {
|
|
3490
|
+
llmClient,
|
|
3491
|
+
workspaceRoot,
|
|
3492
|
+
features: CLI_FEATURES,
|
|
3493
|
+
memory: new FileSystemAdapter({ backend, baseDir: dataDir, namespace: "transcripts" }),
|
|
3494
|
+
experienceStore: await FileSystemExperienceStore.create({ backend, baseDir: dataDir, namespace: "experience" }),
|
|
3495
|
+
checkpointStore: new FileSystemAdapter({ backend, baseDir: dataDir, namespace: "checkpoints" }),
|
|
3496
|
+
reminderStore: new InMemoryReminderStore(new FileSystemAdapter({ backend, baseDir: dataDir, namespace: "reminders" })),
|
|
3497
|
+
fileTools: { backend, workspaceRoot },
|
|
3498
|
+
webTools: config.enableWeb ? { search } : void 0,
|
|
3499
|
+
// executeCommand is the real child_process.spawn-based implementation (shell-executor.ts) —
|
|
3500
|
+
// wired in here, not inside assistant.ts, so the browser build never needs node:child_process.
|
|
3501
|
+
shellTools: config.enableShell ? { backend, workspaceRoot, timeoutMs: config.shellTimeoutMs, networkAllowlist: config.shellNetworkAllowlist, executeCommand: runApprovedShellCommand } : void 0,
|
|
3502
|
+
// The Resend/SMTP transport is wired in here, not inside assistant.ts, so the browser build
|
|
3503
|
+
// never needs nodemailer or a mail server — same split as shellTools' executeCommand.
|
|
3504
|
+
actionTools: (() => {
|
|
3505
|
+
const sendEmail = buildEmailSender(config);
|
|
3506
|
+
return sendEmail ? { backend, workspaceRoot, sendEmail } : void 0;
|
|
3507
|
+
})(),
|
|
3508
|
+
// Opt-in durable record of tool calls/results and approvals (see activity-log.ts).
|
|
3509
|
+
onDebugLog: activityLogEnabled(process.env) ? createActivityLogger(join(dataDir, "activity-log.jsonl")) : void 0
|
|
3510
|
+
})
|
|
3511
|
+
);
|
|
3553
3512
|
}
|
|
3554
3513
|
async function runCli(options = {}) {
|
|
3555
3514
|
const dataDir = options.dataDir ?? defaultDataDir;
|
|
@@ -3651,6 +3610,7 @@ Fix it by setting the missing value (in the config file under ${dataDir}, or via
|
|
|
3651
3610
|
rl.prompt();
|
|
3652
3611
|
let lastTrace;
|
|
3653
3612
|
let lastSources;
|
|
3613
|
+
let lastAnswerClaim;
|
|
3654
3614
|
let lastPlanStatus;
|
|
3655
3615
|
let pendingPlanApproval;
|
|
3656
3616
|
let lastTurnUsage;
|
|
@@ -3663,33 +3623,17 @@ Fix it by setting the missing value (in the config file under ${dataDir}, or via
|
|
|
3663
3623
|
{ key: "a", label: "Yes, don't ask again this session" },
|
|
3664
3624
|
{ key: "n", label: "No" }
|
|
3665
3625
|
];
|
|
3666
|
-
function
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
}
|
|
3671
|
-
const PLAN_TASK_STATUS_ICON = {
|
|
3672
|
-
PENDING: "○",
|
|
3673
|
-
RUNNING: "▶",
|
|
3674
|
-
COMPLETE: "✓",
|
|
3675
|
-
FAILED: "✗",
|
|
3676
|
-
BLOCKED: "✗",
|
|
3677
|
-
HUMAN_REQUIRED: "~"
|
|
3678
|
-
};
|
|
3679
|
-
function printPlan() {
|
|
3626
|
+
function priceUsage(usage) {
|
|
3627
|
+
return withCostEstimate(usage, { backend: config.llmBackend, model: config.model });
|
|
3628
|
+
}
|
|
3629
|
+
function printPlan(goalGraph) {
|
|
3680
3630
|
if (!lastPlanStatus) {
|
|
3681
|
-
printSafe(
|
|
3631
|
+
printSafe(`
|
|
3632
|
+
${explainPlan({ ...lastTurnExplainInput(), goalGraph }).join("\n")}
|
|
3633
|
+
`);
|
|
3682
3634
|
return;
|
|
3683
3635
|
}
|
|
3684
|
-
const lines = [
|
|
3685
|
-
PLAN_LINE_PREFIX,
|
|
3686
|
-
`Plan: ${lastPlanStatus.templateName ?? "custom plan"} (${lastPlanStatus.completionPct.toFixed(1)}% complete)`,
|
|
3687
|
-
...lastPlanStatus.tasks.flatMap((task) => [
|
|
3688
|
-
` ${PLAN_TASK_STATUS_ICON[task.status] ?? "?"} [${task.status}] ${task.id} — ${task.description}`,
|
|
3689
|
-
...task.note ? [` not accepted as done: ${task.note}`] : []
|
|
3690
|
-
]),
|
|
3691
|
-
`Success criteria: ${lastPlanStatus.successCriteria}`
|
|
3692
|
-
];
|
|
3636
|
+
const lines = [PLAN_LINE_PREFIX, ...explainPlan(lastTurnExplainInput())];
|
|
3693
3637
|
console.log(stripTerminalControls(`
|
|
3694
3638
|
${lines.join("\n")}
|
|
3695
3639
|
`));
|
|
@@ -3704,7 +3648,7 @@ ${lines.join("\n")}
|
|
|
3704
3648
|
const result = await assistant.sketchPlan("cli", request);
|
|
3705
3649
|
console.log(stripTerminalControls(`Aielia> ${result.reply ?? "(no reply)"}
|
|
3706
3650
|
`));
|
|
3707
|
-
if (result.usage) lastTurnUsage =
|
|
3651
|
+
if (result.usage) lastTurnUsage = priceUsage(result.usage);
|
|
3708
3652
|
}
|
|
3709
3653
|
const PLAN_APPROVAL_OPTIONS = [
|
|
3710
3654
|
{ key: "y", label: "Approve" },
|
|
@@ -3769,7 +3713,7 @@ ${lines.join("\n")}
|
|
|
3769
3713
|
}
|
|
3770
3714
|
pendingPlanApproval = void 0;
|
|
3771
3715
|
lastTrace = void 0;
|
|
3772
|
-
lastNoTraceReason =
|
|
3716
|
+
lastNoTraceReason = NO_TRACE.planApproval(decision === "decline" ? "declined" : "approved");
|
|
3773
3717
|
await handleTurn(message, false, void 0, void 0, void 0, id, decision, edits);
|
|
3774
3718
|
}
|
|
3775
3719
|
async function loadPlanGraphNodes(live, threadId) {
|
|
@@ -3837,86 +3781,38 @@ ${result.lines.join("\n")}
|
|
|
3837
3781
|
printPlanApproval(pendingPlanApproval.snapshot);
|
|
3838
3782
|
return;
|
|
3839
3783
|
}
|
|
3840
|
-
printPlan();
|
|
3841
|
-
}
|
|
3842
|
-
function verificationHealthLabel({ strength, feasibility }) {
|
|
3843
|
-
const confidence = Math.min(strength, feasibility);
|
|
3844
|
-
if (confidence >= 0.7) return "High confidence";
|
|
3845
|
-
if (confidence >= 0.4) return "Reasonably confident";
|
|
3846
|
-
return "Worth double-checking";
|
|
3784
|
+
printPlan(lastPlanStatus ? void 0 : await assistant.getGoalGraphState("cli"));
|
|
3847
3785
|
}
|
|
3848
|
-
function
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3786
|
+
function lastTurnExplainInput() {
|
|
3787
|
+
return {
|
|
3788
|
+
trace: lastTrace,
|
|
3789
|
+
noTraceReason: lastNoTraceReason,
|
|
3790
|
+
answerClaim: lastAnswerClaim,
|
|
3791
|
+
memoryInjection: assistant.getLastMemoryInjection(),
|
|
3792
|
+
sources: lastSources,
|
|
3793
|
+
toolSteps: lastTurnToolSteps,
|
|
3794
|
+
planStatus: lastPlanStatus
|
|
3795
|
+
};
|
|
3853
3796
|
}
|
|
3854
3797
|
function printWhy() {
|
|
3855
|
-
const memoryLine = formatMemoryInjection(assistant.getLastMemoryInjection());
|
|
3856
|
-
if (!lastTrace) {
|
|
3857
|
-
printSafe(`
|
|
3858
|
-
${lastNoTraceReason ?? "No harness trace for the last turn (nothing to explain yet, or it took the fast path)."}
|
|
3859
|
-
${memoryLine}
|
|
3860
|
-
`);
|
|
3861
|
-
return;
|
|
3862
|
-
}
|
|
3863
3798
|
printSafe(`
|
|
3864
|
-
${
|
|
3865
|
-
|
|
3866
|
-
if (chain.length > 0) {
|
|
3867
|
-
printSafe(" " + chain.map((item) => `${LAYER_SHORT_CODE[item.layer]} (${item.reason})`).join(" > "));
|
|
3868
|
-
}
|
|
3869
|
-
if (lastTrace.batchBudget) {
|
|
3870
|
-
printSafe(" " + batchBudgetSummaryLine(lastTrace.batchBudget));
|
|
3871
|
-
}
|
|
3872
|
-
printSafe(memoryLine);
|
|
3873
|
-
printSafe("");
|
|
3799
|
+
${explainWhy(lastTurnExplainInput()).join("\n")}
|
|
3800
|
+
`);
|
|
3874
3801
|
}
|
|
3875
3802
|
function printLayers() {
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
${lastNoTraceReason ?? "No harness trace for the last turn (nothing to explain yet, or it took the fast path)."}
|
|
3803
|
+
printSafe(`
|
|
3804
|
+
${explainLayers(lastTurnExplainInput()).join("\n")}
|
|
3879
3805
|
`);
|
|
3880
|
-
return;
|
|
3881
|
-
}
|
|
3882
|
-
printSafe("");
|
|
3883
|
-
const byLayer = new Map(lastTrace.layerActivity.map((e) => [e.layer, e]));
|
|
3884
|
-
for (const layer of LAYER_ORDER) {
|
|
3885
|
-
const e = byLayer.get(layer);
|
|
3886
|
-
const mark = (e == null ? void 0 : e.fired) ? "✓" : "·";
|
|
3887
|
-
const reason = (e == null ? void 0 : e.reason) ?? "not evaluated this turn";
|
|
3888
|
-
printSafe(` [${mark}] ${LAYER_DISPLAY_NAME[layer].padEnd(22)} ${reason}`);
|
|
3889
|
-
}
|
|
3890
|
-
if (lastTrace.batchBudget) {
|
|
3891
|
-
printSafe("");
|
|
3892
|
-
printSafe(` ${batchBudgetSummaryLine(lastTrace.batchBudget)}`);
|
|
3893
|
-
const STATUS_MARK = {
|
|
3894
|
-
found: "✓",
|
|
3895
|
-
not_found: "✗",
|
|
3896
|
-
truncated_while_productive: "~"
|
|
3897
|
-
};
|
|
3898
|
-
for (const outcome of lastTrace.batchBudget.perItemOutcomes) {
|
|
3899
|
-
printSafe(` [${STATUS_MARK[outcome.status]}] ${outcome.item.padEnd(30)} ${outcome.status} (${outcome.callsUsed} calls)`);
|
|
3900
|
-
}
|
|
3901
|
-
}
|
|
3902
|
-
printSafe("");
|
|
3903
3806
|
}
|
|
3904
|
-
const SOURCE_TOOL_LABEL = {
|
|
3905
|
-
read_file: "Read",
|
|
3906
|
-
list_directory: "Listed",
|
|
3907
|
-
web_search: "Searched",
|
|
3908
|
-
fetch_url: "Fetched"
|
|
3909
|
-
};
|
|
3910
3807
|
function printSources() {
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
printSafe("");
|
|
3808
|
+
printSafe(`
|
|
3809
|
+
${explainSources(lastTurnExplainInput()).join("\n")}
|
|
3810
|
+
`);
|
|
3811
|
+
}
|
|
3812
|
+
function printSteps() {
|
|
3813
|
+
printSafe(`
|
|
3814
|
+
${explainSteps(lastTurnExplainInput()).join("\n")}
|
|
3815
|
+
`);
|
|
3920
3816
|
}
|
|
3921
3817
|
function printHelp() {
|
|
3922
3818
|
printSafe(`
|
|
@@ -3991,12 +3887,12 @@ ${formatStatus({ config, overriddenKeys, transcriptLength: transcript.length, pl
|
|
|
3991
3887
|
}
|
|
3992
3888
|
}
|
|
3993
3889
|
async function handleUndo() {
|
|
3994
|
-
const
|
|
3995
|
-
if (
|
|
3890
|
+
const plan = planUndo(await assistant.getTranscript("cli"));
|
|
3891
|
+
if (plan.nothingToUndo) {
|
|
3996
3892
|
printSafe("\nNothing to undo.\n");
|
|
3997
3893
|
return;
|
|
3998
3894
|
}
|
|
3999
|
-
const wasPendingApproval =
|
|
3895
|
+
const { wasPendingApproval } = plan;
|
|
4000
3896
|
const undoneReminders = lastTurnToolSteps.filter((s) => s.tool === "create_reminder");
|
|
4001
3897
|
const result = await assistant.undoLastTurn("cli");
|
|
4002
3898
|
if (!result.undone) {
|
|
@@ -4015,14 +3911,15 @@ ${formatStatus({ config, overriddenKeys, transcriptLength: transcript.length, pl
|
|
|
4015
3911
|
);
|
|
4016
3912
|
}
|
|
4017
3913
|
async function handleUndoAction(args) {
|
|
4018
|
-
|
|
3914
|
+
const command = parseUndoActionCommand(args);
|
|
3915
|
+
if (command.kind === "list") {
|
|
4019
3916
|
const entries = await assistant.listUndoLogEntries();
|
|
4020
3917
|
printSafe(`
|
|
4021
3918
|
${formatUndoLogListing(entries)}
|
|
4022
3919
|
`);
|
|
4023
3920
|
return;
|
|
4024
3921
|
}
|
|
4025
|
-
const staged = await assistant.stageUndoAction(
|
|
3922
|
+
const staged = await assistant.stageUndoAction(command.id);
|
|
4026
3923
|
if (staged.status === "error") {
|
|
4027
3924
|
printSafe(`
|
|
4028
3925
|
✗ ${staged.message}
|
|
@@ -4033,7 +3930,7 @@ ${formatUndoLogListing(entries)}
|
|
|
4033
3930
|
[needs approval — revert] ${staged.reason}`));
|
|
4034
3931
|
const confirmed = await askYesNo("Apply this revert? (y/N) ");
|
|
4035
3932
|
lastTrace = void 0;
|
|
4036
|
-
lastNoTraceReason =
|
|
3933
|
+
lastNoTraceReason = NO_TRACE.stagedAction("revert", confirmed ? "approved" : "declined");
|
|
4037
3934
|
await handleTurn("", confirmed, staged.pendingActionId);
|
|
4038
3935
|
}
|
|
4039
3936
|
async function printMemory() {
|
|
@@ -4109,6 +4006,12 @@ Forgot ${removed} session digest${removed === 1 ? "" : "s"}.
|
|
|
4109
4006
|
await handleMemoryForget(args.slice(1));
|
|
4110
4007
|
return;
|
|
4111
4008
|
}
|
|
4009
|
+
if (args[0] === "history" && args[1] === "events") {
|
|
4010
|
+
printSafe(`
|
|
4011
|
+
${formatMemoryEvents(await assistant.memoryEvents(50, args[2] ? { fact: args[2] } : {}))}
|
|
4012
|
+
`);
|
|
4013
|
+
return;
|
|
4014
|
+
}
|
|
4112
4015
|
if (args[0] === "history") {
|
|
4113
4016
|
printSafe(`
|
|
4114
4017
|
${formatMemoryHistory(await assistant.memoryHistory())}
|
|
@@ -4252,24 +4155,8 @@ ${formatDoctorReport(checks)}
|
|
|
4252
4155
|
}
|
|
4253
4156
|
lastTurnToolSteps.push(step);
|
|
4254
4157
|
}
|
|
4255
|
-
function emptyClarificationDraft() {
|
|
4256
|
-
return { selectedLabels: [], editText: "", freeText: "" };
|
|
4257
|
-
}
|
|
4258
|
-
function orderedAskOptions(question) {
|
|
4259
|
-
const options2 = question.options ?? [];
|
|
4260
|
-
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);
|
|
4261
|
-
}
|
|
4262
|
-
function clarificationDraftToAnswer(questionId, draft) {
|
|
4263
|
-
if (draft.selectedLabels.length > 0) {
|
|
4264
|
-
return draft.editText.trim() ? { questionId, kind: "selected_with_edit", selectedLabels: draft.selectedLabels, editText: draft.editText.trim() } : { questionId, kind: "selected", selectedLabels: draft.selectedLabels };
|
|
4265
|
-
}
|
|
4266
|
-
if (draft.freeText.trim()) {
|
|
4267
|
-
return { questionId, kind: "free_text", freeText: draft.freeText.trim() };
|
|
4268
|
-
}
|
|
4269
|
-
return null;
|
|
4270
|
-
}
|
|
4271
4158
|
function printClarificationQuestion(question, draft, index, total) {
|
|
4272
|
-
const options2 =
|
|
4159
|
+
const options2 = orderedOptions(question);
|
|
4273
4160
|
const allowFreeText = question.allowFreeText !== false;
|
|
4274
4161
|
printSafe("");
|
|
4275
4162
|
if (question.header) console.log(stripTerminalControls(`[${question.header}]`));
|
|
@@ -4299,9 +4186,10 @@ ${formatDoctorReport(checks)}
|
|
|
4299
4186
|
const pendingClarificationId = result.pendingClarificationId;
|
|
4300
4187
|
if (questions.length === 0 || !pendingClarificationId) {
|
|
4301
4188
|
lastTrace = void 0;
|
|
4302
|
-
|
|
4189
|
+
const unanswerable = presentTurnResult(result);
|
|
4190
|
+
lastNoTraceReason = unanswerable.noTraceReason;
|
|
4303
4191
|
console.log(stripTerminalControls(`
|
|
4304
|
-
[needs clarification] ${
|
|
4192
|
+
[needs clarification] ${unanswerable.kind === "escalation" ? unanswerable.reason : DEFAULT_CLARIFICATION_REASON}
|
|
4305
4193
|
`));
|
|
4306
4194
|
return;
|
|
4307
4195
|
}
|
|
@@ -4318,7 +4206,7 @@ ${formatDoctorReport(checks)}
|
|
|
4318
4206
|
}
|
|
4319
4207
|
printSafe(`
|
|
4320
4208
|
[needs clarification] ${questions.length} question${questions.length === 1 ? "" : "s"} to answer.`);
|
|
4321
|
-
const drafts = new Map(questions.map((q2) => [q2.id,
|
|
4209
|
+
const drafts = new Map(questions.map((q2) => [q2.id, emptyDraft()]));
|
|
4322
4210
|
let index = 0;
|
|
4323
4211
|
while (true) {
|
|
4324
4212
|
const question = questions[index];
|
|
@@ -4333,7 +4221,7 @@ ${formatDoctorReport(checks)}
|
|
|
4333
4221
|
return;
|
|
4334
4222
|
}
|
|
4335
4223
|
if (lower === "s" || lower === "submit") {
|
|
4336
|
-
const answers = questions.map((q2) =>
|
|
4224
|
+
const answers = questions.map((q2) => draftToAnswer(q2.id, drafts.get(q2.id)));
|
|
4337
4225
|
const missing = questions.filter((q2, i) => answers[i] === null);
|
|
4338
4226
|
if (missing.length > 0) {
|
|
4339
4227
|
printSafe(`
|
|
@@ -4368,7 +4256,7 @@ Still need an answer for: ${missing.map((q2) => q2.question).join("; ")}
|
|
|
4368
4256
|
}
|
|
4369
4257
|
const editMatch = /^e(\d+)$/i.exec(token);
|
|
4370
4258
|
if (editMatch) {
|
|
4371
|
-
const options2 =
|
|
4259
|
+
const options2 = orderedOptions(question);
|
|
4372
4260
|
const option = options2[Number(editMatch[1]) - 1];
|
|
4373
4261
|
if (!option) {
|
|
4374
4262
|
printSafe(`
|
|
@@ -4388,7 +4276,7 @@ Select option ${editMatch[1]} first, then add a note with e${editMatch[1]}.
|
|
|
4388
4276
|
}
|
|
4389
4277
|
const toggleMatch = /^t(\d+)$/i.exec(token) ?? /^(\d+)$/.exec(token);
|
|
4390
4278
|
if (toggleMatch) {
|
|
4391
|
-
const options2 =
|
|
4279
|
+
const options2 = orderedOptions(question);
|
|
4392
4280
|
const option = options2[Number(toggleMatch[1]) - 1];
|
|
4393
4281
|
if (!option) {
|
|
4394
4282
|
printSafe(`
|
|
@@ -4459,8 +4347,7 @@ Unrecognized input "${token}".
|
|
|
4459
4347
|
});
|
|
4460
4348
|
if (!streamedAnyTokens) clearProgress();
|
|
4461
4349
|
if (result.status === "needs_approval" && result.pendingActionId) {
|
|
4462
|
-
const kindLabel
|
|
4463
|
-
const promptText = result.pendingActionKind === "shell" ? "Run this command?" : result.pendingActionKind === "email" ? "Send this email?" : result.pendingActionKind === "batch" ? "Continue?" : "Apply this write?";
|
|
4350
|
+
const { kindLabel, promptText } = approvalLabels(result.pendingActionKind);
|
|
4464
4351
|
console.log(stripTerminalControls(`
|
|
4465
4352
|
[needs approval — ${kindLabel}] ${result.reason}`));
|
|
4466
4353
|
let confirmed;
|
|
@@ -4473,7 +4360,7 @@ Unrecognized input "${token}".
|
|
|
4473
4360
|
if (decision === "a" && result.pendingActionKind) rememberedActionKinds.add(result.pendingActionKind);
|
|
4474
4361
|
}
|
|
4475
4362
|
lastTrace = void 0;
|
|
4476
|
-
lastNoTraceReason =
|
|
4363
|
+
lastNoTraceReason = NO_TRACE.stagedAction(kindLabel, confirmed ? "approved" : "declined");
|
|
4477
4364
|
await handleTurn(message, confirmed, result.pendingActionId);
|
|
4478
4365
|
return;
|
|
4479
4366
|
}
|
|
@@ -4494,7 +4381,7 @@ Unrecognized input "${token}".
|
|
|
4494
4381
|
await handleTurn(message, true);
|
|
4495
4382
|
} else {
|
|
4496
4383
|
lastTrace = void 0;
|
|
4497
|
-
lastNoTraceReason = "
|
|
4384
|
+
lastNoTraceReason = NO_TRACE.messageApproval("declined");
|
|
4498
4385
|
await assistant.recordDeclinedRequest("cli", message, result.reason ?? "This request needed approval.");
|
|
4499
4386
|
printSafe("Cancelled.\n");
|
|
4500
4387
|
}
|
|
@@ -4507,7 +4394,7 @@ Unrecognized input "${token}".
|
|
|
4507
4394
|
if (result.status === "needs_plan_approval") {
|
|
4508
4395
|
if (!result.planApprovalId) {
|
|
4509
4396
|
printSafe(`
|
|
4510
|
-
[needs plan approval] ${result.reason ??
|
|
4397
|
+
[needs plan approval] ${result.reason ?? MISSING_PLAN_APPROVAL_ID_REASON}
|
|
4511
4398
|
`);
|
|
4512
4399
|
return;
|
|
4513
4400
|
}
|
|
@@ -4518,7 +4405,7 @@ ${result.reason}`);
|
|
|
4518
4405
|
if (snapshot) printPlanApproval(snapshot);
|
|
4519
4406
|
pendingPlanApproval = { id, message, snapshot };
|
|
4520
4407
|
lastTrace = void 0;
|
|
4521
|
-
lastNoTraceReason =
|
|
4408
|
+
lastNoTraceReason = NO_TRACE.planApproval(void 0, " (pending /plan approve|decline|edit)");
|
|
4522
4409
|
if (!snapshot) {
|
|
4523
4410
|
printSafe("Decide with /plan approve or /plan decline.\n");
|
|
4524
4411
|
return;
|
|
@@ -4541,44 +4428,48 @@ ${result.reason}`);
|
|
|
4541
4428
|
} else {
|
|
4542
4429
|
decision = "decline";
|
|
4543
4430
|
}
|
|
4544
|
-
lastNoTraceReason =
|
|
4431
|
+
lastNoTraceReason = NO_TRACE.planApproval(decision === "decline" ? "declined" : "approved");
|
|
4545
4432
|
await handleTurn(message, false, void 0, void 0, void 0, id, decision, edits);
|
|
4546
4433
|
return;
|
|
4547
4434
|
}
|
|
4548
4435
|
if (result.status === "escalated") {
|
|
4549
4436
|
lastTrace = void 0;
|
|
4550
|
-
|
|
4437
|
+
const escalation = presentTurnResult(result);
|
|
4438
|
+
lastNoTraceReason = escalation.noTraceReason;
|
|
4551
4439
|
console.log(stripTerminalControls(`
|
|
4552
|
-
[escalated] ${result.reason}
|
|
4440
|
+
[escalated] ${escalation.kind === "escalation" ? escalation.reason : result.reason}
|
|
4553
4441
|
`));
|
|
4554
4442
|
return;
|
|
4555
4443
|
}
|
|
4556
4444
|
if (!pendingActionId) {
|
|
4557
4445
|
lastTrace = result.harnessSkipped ? void 0 : result.trace;
|
|
4558
|
-
|
|
4446
|
+
lastAnswerClaim = result.answerClaim;
|
|
4447
|
+
lastNoTraceReason = result.harnessSkipped ? NO_TRACE.fastPath : void 0;
|
|
4559
4448
|
}
|
|
4560
4449
|
lastSources = result.sources;
|
|
4561
4450
|
if (!pendingActionId && (!result.harnessSkipped || result.planStatus)) lastPlanStatus = result.planStatus;
|
|
4562
|
-
lastTurnUsage = result.usage ?
|
|
4451
|
+
lastTurnUsage = result.usage ? priceUsage(result.usage) : void 0;
|
|
4452
|
+
const shown = presentTurnResult(result);
|
|
4453
|
+
const hints = shown.kind === "reply" ? shown.hints : {};
|
|
4563
4454
|
const riskSuffix = result.riskLevel && result.riskLevel !== "LOW" ? ` [risk: ${result.riskLevel}]` : "";
|
|
4564
|
-
const sourcesHint =
|
|
4565
|
-
const planHint =
|
|
4566
|
-
const contradictionNotice =
|
|
4455
|
+
const sourcesHint = hints.sourcesCount ? ` (${hints.sourcesCount} source${hints.sourcesCount > 1 ? "s" : ""} — /sources)` : "";
|
|
4456
|
+
const planHint = hints.planCompletionPct !== void 0 ? ` (plan: ${hints.planCompletionPct.toFixed(0)}% — /plan)` : "";
|
|
4457
|
+
const contradictionNotice = hints.contradictionNotice ? `
|
|
4567
4458
|
|
|
4568
|
-
${
|
|
4569
|
-
const reviewNotice = (
|
|
4459
|
+
${hints.contradictionNotice}` : "";
|
|
4460
|
+
const reviewNotice = (hints.reviewNotice ? `
|
|
4570
4461
|
|
|
4571
|
-
${
|
|
4462
|
+
${hints.reviewNotice}` : "") + (hints.auditNotice ? `
|
|
4572
4463
|
|
|
4573
|
-
${
|
|
4574
|
-
lastNextSteps =
|
|
4464
|
+
${hints.auditNotice}` : "");
|
|
4465
|
+
lastNextSteps = hints.nextSteps;
|
|
4575
4466
|
const nextStepsBlock = lastNextSteps ? `
|
|
4576
4467
|
|
|
4577
4468
|
${formatNextSteps(lastNextSteps)}` : "";
|
|
4578
4469
|
if (streamedAnyTokens) {
|
|
4579
|
-
const pausedNoteText =
|
|
4470
|
+
const pausedNoteText = hints.pausedNote ? `
|
|
4580
4471
|
|
|
4581
|
-
${
|
|
4472
|
+
${hints.pausedNote}` : "";
|
|
4582
4473
|
process.stdout.write(stripTerminalControls(`${pausedNoteText}${riskSuffix}${sourcesHint}${planHint}${contradictionNotice}${reviewNotice}${nextStepsBlock}
|
|
4583
4474
|
|
|
4584
4475
|
`));
|
|
@@ -4788,6 +4679,8 @@ Usage: /layers ${sub} <id>
|
|
|
4788
4679
|
✗ Saved, but "${id}" is pinned by its AUDIT_* env flag, so the saved choice has no effect until that is unset.
|
|
4789
4680
|
` : `
|
|
4790
4681
|
✓ Layers updated (took effect immediately, no restart needed)
|
|
4682
|
+
`);
|
|
4683
|
+
for (const warning of layerWarnings(sanitizeLayerChoices(config.layers), layerPins, process.env)) printSafe(`⚠ ${warning}
|
|
4791
4684
|
`);
|
|
4792
4685
|
}
|
|
4793
4686
|
async function handleModel(args) {
|
|
@@ -4800,17 +4693,12 @@ ${config.model ?? "(using each backend's default)"}
|
|
|
4800
4693
|
await handleConfigCommand(["set", "model", args.join(" ")]);
|
|
4801
4694
|
}
|
|
4802
4695
|
async function handleProject(args) {
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
${
|
|
4696
|
+
const command = parseProjectCommand(args, assistant.getActiveProject());
|
|
4697
|
+
if (command.kind === "show") printSafe(`
|
|
4698
|
+
${command.message}
|
|
4806
4699
|
`);
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
if (args[0] === "clear") {
|
|
4810
|
-
await handleConfigCommand(["reset", "activeProject"]);
|
|
4811
|
-
return;
|
|
4812
|
-
}
|
|
4813
|
-
await handleConfigCommand(["set", "activeProject", args.join(" ")]);
|
|
4700
|
+
else if (command.kind === "clear") await handleConfigCommand(["reset", "activeProject"]);
|
|
4701
|
+
else await handleConfigCommand(["set", "activeProject", command.project]);
|
|
4814
4702
|
}
|
|
4815
4703
|
let turnInProgress = false;
|
|
4816
4704
|
let lastNextSteps;
|
|
@@ -4820,6 +4708,7 @@ ${assistant.getActiveProject() || "(none)"}
|
|
|
4820
4708
|
// Bare /layers is the last-turn fired/skipped view; its subcommands (settings/on/off/reset) edit the on/off choices.
|
|
4821
4709
|
"/layers": (args) => args.length === 0 ? printLayers() : handleLayers(args),
|
|
4822
4710
|
"/sources": () => printSources(),
|
|
4711
|
+
"/steps": () => printSteps(),
|
|
4823
4712
|
"/plan": (args) => handlePlan(args),
|
|
4824
4713
|
"/help": () => printHelp(),
|
|
4825
4714
|
"/clear": () => handleClear(),
|
|
@@ -4909,6 +4798,7 @@ ${assistant.getActiveProject() || "(none)"}
|
|
|
4909
4798
|
});
|
|
4910
4799
|
rl.resume();
|
|
4911
4800
|
return {
|
|
4801
|
+
commandNames: Object.keys(commands),
|
|
4912
4802
|
dispatchLine: async (line) => {
|
|
4913
4803
|
const message = line.trim();
|
|
4914
4804
|
if (!message) return;
|
|
@@ -4972,7 +4862,7 @@ async function mainInner(argv) {
|
|
|
4972
4862
|
});
|
|
4973
4863
|
}
|
|
4974
4864
|
if (shouldLaunchTuiApp(config.tuiMode ?? DEFAULT_TUI_MODE, Boolean(process.stdout.isTTY), Boolean(process.stdin.isTTY))) {
|
|
4975
|
-
const { runTuiApp } = await import("./tui-app-
|
|
4865
|
+
const { runTuiApp } = await import("./tui-app-oWbIUcBW.js");
|
|
4976
4866
|
await runTuiApp();
|
|
4977
4867
|
return;
|
|
4978
4868
|
}
|
|
@@ -4999,4 +4889,4 @@ export {
|
|
|
4999
4889
|
sanitizeLabel as s,
|
|
5000
4890
|
toLines as t
|
|
5001
4891
|
};
|
|
5002
|
-
//# sourceMappingURL=bin-
|
|
4892
|
+
//# sourceMappingURL=bin-Cz3FY6Ew.js.map
|