@raegent/earshot 0.3.1 → 0.4.0
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/main.js +1949 -1210
- package/dist/main.js.map +26 -21
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -14446,6 +14446,11 @@ function openBrowser(url) {
|
|
|
14446
14446
|
child.unref();
|
|
14447
14447
|
} catch {}
|
|
14448
14448
|
}
|
|
14449
|
+
// packages/providers/src/types.ts
|
|
14450
|
+
var REASONING_EFFORTS = ["none", "low", "medium", "high", "xhigh"];
|
|
14451
|
+
function isReasoningEffort(value) {
|
|
14452
|
+
return typeof value === "string" && REASONING_EFFORTS.includes(value);
|
|
14453
|
+
}
|
|
14449
14454
|
// packages/core/src/context/agents-md.ts
|
|
14450
14455
|
var MEMORY_FILENAMES = ["AGENTS.md", "CLAUDE.md"];
|
|
14451
14456
|
async function readIfPresent(path) {
|
|
@@ -14902,6 +14907,8 @@ Actions that change files, run commands or reach the network ` + "prompt the use
|
|
|
14902
14907
|
}
|
|
14903
14908
|
}
|
|
14904
14909
|
// packages/core/src/model.ts
|
|
14910
|
+
var DEFAULT_MODEL = "anthropic/claude-opus-5";
|
|
14911
|
+
|
|
14905
14912
|
class MissingCredentialsError extends Error {
|
|
14906
14913
|
provider;
|
|
14907
14914
|
constructor(provider) {
|
|
@@ -15174,6 +15181,8 @@ async function loadSettings(cwd) {
|
|
|
15174
15181
|
let defaultMode;
|
|
15175
15182
|
let curiosity;
|
|
15176
15183
|
let maxCostUsd;
|
|
15184
|
+
let defaultModel;
|
|
15185
|
+
const reasoningEfforts = {};
|
|
15177
15186
|
for (const scope of scopes) {
|
|
15178
15187
|
const path = settingsPath(scope, cwd);
|
|
15179
15188
|
const file = await readSettings(path).catch((error) => {
|
|
@@ -15182,6 +15191,15 @@ async function loadSettings(cwd) {
|
|
|
15182
15191
|
});
|
|
15183
15192
|
if (!file)
|
|
15184
15193
|
continue;
|
|
15194
|
+
if (typeof file.defaultModel === "string" && file.defaultModel.trim() !== "") {
|
|
15195
|
+
defaultModel = file.defaultModel.trim();
|
|
15196
|
+
}
|
|
15197
|
+
for (const [model, effort] of Object.entries(file.reasoningEfforts ?? {})) {
|
|
15198
|
+
if (isReasoningEffort(effort))
|
|
15199
|
+
reasoningEfforts[model] = effort;
|
|
15200
|
+
else
|
|
15201
|
+
problems.push(`${path}: reasoning effort for "${model}" is invalid`);
|
|
15202
|
+
}
|
|
15185
15203
|
if (file.curiosity !== undefined) {
|
|
15186
15204
|
if (isCuriosity(file.curiosity))
|
|
15187
15205
|
curiosity = file.curiosity;
|
|
@@ -15226,9 +15244,36 @@ async function loadSettings(cwd) {
|
|
|
15226
15244
|
...defaultMode ? { defaultMode } : {},
|
|
15227
15245
|
...curiosity ? { curiosity } : {},
|
|
15228
15246
|
...maxCostUsd !== undefined ? { maxCostUsd } : {},
|
|
15247
|
+
...defaultModel ? { defaultModel } : {},
|
|
15248
|
+
reasoningEfforts,
|
|
15229
15249
|
problems
|
|
15230
15250
|
};
|
|
15231
15251
|
}
|
|
15252
|
+
async function persistDefaultModel(model, scope, cwd) {
|
|
15253
|
+
const path = settingsPath(scope, cwd);
|
|
15254
|
+
const existing = await readSettings(path).catch(() => {
|
|
15255
|
+
return;
|
|
15256
|
+
}) ?? {};
|
|
15257
|
+
await mkdir3(dirname3(path), { recursive: true });
|
|
15258
|
+
await writeFile3(path, `${JSON.stringify({ ...existing, defaultModel: model }, null, 2)}
|
|
15259
|
+
`, "utf8");
|
|
15260
|
+
return path;
|
|
15261
|
+
}
|
|
15262
|
+
async function persistReasoningEffort(model, effort, scope, cwd) {
|
|
15263
|
+
const path = settingsPath(scope, cwd);
|
|
15264
|
+
const existing = await readSettings(path).catch(() => {
|
|
15265
|
+
return;
|
|
15266
|
+
}) ?? {};
|
|
15267
|
+
const reasoningEfforts = { ...existing.reasoningEfforts ?? {} };
|
|
15268
|
+
if (effort === undefined)
|
|
15269
|
+
delete reasoningEfforts[model];
|
|
15270
|
+
else
|
|
15271
|
+
reasoningEfforts[model] = effort;
|
|
15272
|
+
await mkdir3(dirname3(path), { recursive: true });
|
|
15273
|
+
await writeFile3(path, `${JSON.stringify({ ...existing, reasoningEfforts }, null, 2)}
|
|
15274
|
+
`, "utf8");
|
|
15275
|
+
return path;
|
|
15276
|
+
}
|
|
15232
15277
|
async function persistRule(rule, scope, cwd) {
|
|
15233
15278
|
const path = settingsPath(scope, cwd);
|
|
15234
15279
|
const existing = await readSettings(path).catch(() => {
|
|
@@ -17095,6 +17140,7 @@ class Agent {
|
|
|
17095
17140
|
queued = [];
|
|
17096
17141
|
rules;
|
|
17097
17142
|
resolved;
|
|
17143
|
+
effort;
|
|
17098
17144
|
mode;
|
|
17099
17145
|
totalCostUsd = 0;
|
|
17100
17146
|
maxCostUsd;
|
|
@@ -17131,10 +17177,17 @@ class Agent {
|
|
|
17131
17177
|
this.systemPrompt = options.system;
|
|
17132
17178
|
this.maxCostUsd = options.maxCostUsd;
|
|
17133
17179
|
this.resolved = options.model;
|
|
17180
|
+
this.effort = options.reasoningEffort;
|
|
17134
17181
|
}
|
|
17135
17182
|
get model() {
|
|
17136
17183
|
return this.resolved;
|
|
17137
17184
|
}
|
|
17185
|
+
get reasoningEffort() {
|
|
17186
|
+
return this.effort;
|
|
17187
|
+
}
|
|
17188
|
+
setReasoningEffort(effort) {
|
|
17189
|
+
this.effort = effort;
|
|
17190
|
+
}
|
|
17138
17191
|
async changeModel(ref) {
|
|
17139
17192
|
const resolved = await resolveModel(this.options.registry, ref);
|
|
17140
17193
|
this.resolved = resolved;
|
|
@@ -17295,6 +17348,7 @@ ${context.join(`
|
|
|
17295
17348
|
system: this.effectiveSystem,
|
|
17296
17349
|
messages,
|
|
17297
17350
|
tools: this.offeredTools(),
|
|
17351
|
+
...this.effort ? { reasoningEffort: this.effort } : {},
|
|
17298
17352
|
abortSignal: signal
|
|
17299
17353
|
})) {
|
|
17300
17354
|
switch (event.type) {
|
|
@@ -17650,6 +17704,7 @@ If something is failing, fix it or say what is ` + `failing and why - do not des
|
|
|
17650
17704
|
for await (const event of streamModel(this.options.registry, this.resolved, {
|
|
17651
17705
|
system: SUMMARY_PROMPT,
|
|
17652
17706
|
messages: [...messages, { role: "user", content: [{ type: "text", text: SUMMARY_PROMPT }] }],
|
|
17707
|
+
...this.effort ? { reasoningEffort: this.effort } : {},
|
|
17653
17708
|
abortSignal: signal
|
|
17654
17709
|
})) {
|
|
17655
17710
|
if (event.type === "text_delta")
|
|
@@ -18234,17 +18289,40 @@ async function listSessions(cwd) {
|
|
|
18234
18289
|
const meta = entries.find((entry) => entry.type === "meta");
|
|
18235
18290
|
if (!info || meta?.type !== "meta")
|
|
18236
18291
|
continue;
|
|
18292
|
+
const configuration = latestConfiguration(entries);
|
|
18237
18293
|
infos.push({
|
|
18238
18294
|
id: name.replace(/\.jsonl$/, ""),
|
|
18239
18295
|
path,
|
|
18240
18296
|
cwd: meta.cwd,
|
|
18241
|
-
model: meta.model,
|
|
18297
|
+
model: configuration.model ?? meta.model,
|
|
18298
|
+
...configuration.reasoningEffort ? { reasoningEffort: configuration.reasoningEffort } : {},
|
|
18242
18299
|
updatedAt: info.mtimeMs,
|
|
18243
18300
|
preview: firstUserText(entries)
|
|
18244
18301
|
});
|
|
18245
18302
|
}
|
|
18246
18303
|
return infos.sort((a, b) => b.updatedAt - a.updatedAt || b.id.localeCompare(a.id));
|
|
18247
18304
|
}
|
|
18305
|
+
function latestConfiguration(entries) {
|
|
18306
|
+
const meta = entries.find((entry) => entry.type === "meta");
|
|
18307
|
+
let model = meta?.type === "meta" ? meta.model : undefined;
|
|
18308
|
+
let reasoningEffort;
|
|
18309
|
+
let reasoningConfigured = false;
|
|
18310
|
+
for (const entry of branchTo([...entries])) {
|
|
18311
|
+
if (entry.type !== "configuration")
|
|
18312
|
+
continue;
|
|
18313
|
+
if (entry.model !== undefined)
|
|
18314
|
+
model = entry.model;
|
|
18315
|
+
if (entry.reasoningEffort !== undefined) {
|
|
18316
|
+
reasoningConfigured = true;
|
|
18317
|
+
reasoningEffort = entry.reasoningEffort === null ? undefined : entry.reasoningEffort;
|
|
18318
|
+
}
|
|
18319
|
+
}
|
|
18320
|
+
return {
|
|
18321
|
+
...model ? { model } : {},
|
|
18322
|
+
...reasoningEffort ? { reasoningEffort } : {},
|
|
18323
|
+
reasoningConfigured
|
|
18324
|
+
};
|
|
18325
|
+
}
|
|
18248
18326
|
async function latestSession(cwd) {
|
|
18249
18327
|
return (await listSessions(cwd))[0];
|
|
18250
18328
|
}
|
|
@@ -18381,7 +18459,7 @@ class ShadowGit {
|
|
|
18381
18459
|
}
|
|
18382
18460
|
|
|
18383
18461
|
// packages/core/src/version.ts
|
|
18384
|
-
var VERSION = "0.
|
|
18462
|
+
var VERSION = "0.4.0";
|
|
18385
18463
|
|
|
18386
18464
|
// packages/core/src/session/repair.ts
|
|
18387
18465
|
var REPAIR_TEXT = "No result was recorded for this call: earshot exited before the tool finished. " + "The call may or may not have run, so treat its effect as unknown and check " + "the current state rather than assuming either outcome.";
|
|
@@ -18419,21 +18497,26 @@ class NoSessionToResumeError extends Error {
|
|
|
18419
18497
|
async function createSession(options) {
|
|
18420
18498
|
const registry2 = options.registry ?? buildRegistry();
|
|
18421
18499
|
const settings2 = await loadSettings(options.cwd);
|
|
18500
|
+
const resumePath = options.ephemeral ? undefined : await resolveResumePath(options);
|
|
18501
|
+
const resumeEntries = resumePath ? await readEntries(resumePath) : [];
|
|
18502
|
+
const resumedConfiguration = latestConfiguration(resumeEntries);
|
|
18503
|
+
const requestedModel = options.model ?? resumedConfiguration.model ?? settings2.defaultModel ?? DEFAULT_MODEL;
|
|
18504
|
+
const configuredEffort = options.reasoningEffort !== undefined ? options.reasoningEffort : resumedConfiguration.reasoningConfigured ? resumedConfiguration.reasoningEffort : settings2.reasoningEfforts[requestedModel];
|
|
18422
18505
|
const mode = options.mode ?? settings2.defaultMode ?? "ask";
|
|
18423
18506
|
const curiosity = options.curiosity ?? settings2.curiosity ?? "normal";
|
|
18424
18507
|
const maxCostUsd = options.maxCostUsd !== undefined ? options.maxCostUsd > 0 ? options.maxCostUsd : undefined : settings2.maxCostUsd;
|
|
18425
|
-
const resolved = await resolveModel(registry2,
|
|
18508
|
+
const resolved = await resolveModel(registry2, requestedModel, {
|
|
18426
18509
|
...options.apiKey ? { apiKey: options.apiKey } : {}
|
|
18427
18510
|
});
|
|
18428
18511
|
const modelRef = `${resolved.provider.id}/${resolved.model.id}`;
|
|
18512
|
+
const reasoningEffort = resolved.model.capabilities.reasoning ? configuredEffort ?? undefined : undefined;
|
|
18429
18513
|
const discovered = options.noExtensions ? { skills: [], commands: [], problems: [] } : await discoverExtensions(options.cwd);
|
|
18430
18514
|
let store2;
|
|
18431
18515
|
let replayed = [];
|
|
18432
18516
|
const repairProblems = [];
|
|
18433
18517
|
if (!options.ephemeral) {
|
|
18434
|
-
const resumePath = await resolveResumePath(options);
|
|
18435
18518
|
if (resumePath) {
|
|
18436
|
-
const entries =
|
|
18519
|
+
const entries = resumeEntries;
|
|
18437
18520
|
replayed = messagesOf(branchTo(entries));
|
|
18438
18521
|
store2 = await SessionStore.open(resumePath).catch(() => {
|
|
18439
18522
|
return;
|
|
@@ -18485,6 +18568,7 @@ ${started.context.join(`
|
|
|
18485
18568
|
const agentOptions = {
|
|
18486
18569
|
registry: registry2,
|
|
18487
18570
|
model: resolved,
|
|
18571
|
+
...reasoningEffort ? { reasoningEffort } : {},
|
|
18488
18572
|
cwd: options.cwd,
|
|
18489
18573
|
system,
|
|
18490
18574
|
mode,
|
|
@@ -18551,7 +18635,7 @@ ${started.context.join(`
|
|
|
18551
18635
|
const from = entryId ?? store2.tailId;
|
|
18552
18636
|
const entries = await readEntries(store2.path);
|
|
18553
18637
|
const forked = await SessionStore.create(options.cwd, {
|
|
18554
|
-
model:
|
|
18638
|
+
model: `${agent.model.provider.id}/${agent.model.model.id}`,
|
|
18555
18639
|
version: VERSION,
|
|
18556
18640
|
...from ? { forkedFrom: { sessionId: store2.id, entryId: from } } : {}
|
|
18557
18641
|
}).catch(() => {
|
|
@@ -18562,10 +18646,18 @@ ${started.context.join(`
|
|
|
18562
18646
|
const kept = messagesOf(branchTo(entries, from ?? undefined));
|
|
18563
18647
|
for (const message of kept)
|
|
18564
18648
|
await forked.appendMessage(message);
|
|
18649
|
+
await forked.append({
|
|
18650
|
+
type: "configuration",
|
|
18651
|
+
model: `${agent.model.provider.id}/${agent.model.model.id}`,
|
|
18652
|
+
reasoningEffort: agent.reasoningEffort ?? null
|
|
18653
|
+
});
|
|
18565
18654
|
agent.replaceHistory(kept);
|
|
18566
18655
|
store2 = forked;
|
|
18567
18656
|
return forked.id;
|
|
18568
18657
|
},
|
|
18658
|
+
async recordConfiguration(configuration) {
|
|
18659
|
+
await store2?.append({ type: "configuration", ...configuration });
|
|
18660
|
+
},
|
|
18569
18661
|
async undo() {
|
|
18570
18662
|
if (!shadow)
|
|
18571
18663
|
return;
|
|
@@ -18650,7 +18742,8 @@ function parseArgs(argv) {
|
|
|
18650
18742
|
"models",
|
|
18651
18743
|
"acp",
|
|
18652
18744
|
"doctor",
|
|
18653
|
-
"update"
|
|
18745
|
+
"update",
|
|
18746
|
+
"sessions"
|
|
18654
18747
|
]);
|
|
18655
18748
|
const command = positionals[0] !== undefined && known.has(positionals[0]) ? positionals[0] : undefined;
|
|
18656
18749
|
return { command, flags, positionals: command ? positionals.slice(1) : positionals };
|
|
@@ -19578,7 +19671,6 @@ async function trustedExtensions(cwd) {
|
|
|
19578
19671
|
}
|
|
19579
19672
|
|
|
19580
19673
|
// packages/cli/src/commands/acp.ts
|
|
19581
|
-
var DEFAULT_MODEL = "anthropic/claude-opus-5";
|
|
19582
19674
|
async function acpCommand(args) {
|
|
19583
19675
|
const requested = args.flags["permission-mode"];
|
|
19584
19676
|
let mode;
|
|
@@ -19590,7 +19682,8 @@ async function acpCommand(args) {
|
|
|
19590
19682
|
}
|
|
19591
19683
|
mode = requested;
|
|
19592
19684
|
}
|
|
19593
|
-
const
|
|
19685
|
+
const requestedModel = typeof args.flags.model === "string" ? args.flags.model : undefined;
|
|
19686
|
+
const model2 = requestedModel ?? DEFAULT_MODEL;
|
|
19594
19687
|
const apiKey = typeof args.flags["api-key"] === "string" ? args.flags["api-key"] : undefined;
|
|
19595
19688
|
const sessionFactory = async ({ cwd, resumeSessionId }) => {
|
|
19596
19689
|
const extensions = await startExtensions(cwd);
|
|
@@ -19606,7 +19699,7 @@ async function acpCommand(args) {
|
|
|
19606
19699
|
try {
|
|
19607
19700
|
return await createSession({
|
|
19608
19701
|
cwd,
|
|
19609
|
-
model:
|
|
19702
|
+
...requestedModel ? { model: requestedModel } : {},
|
|
19610
19703
|
extraTools: extensions.tools,
|
|
19611
19704
|
problems: extensions.problems,
|
|
19612
19705
|
onDispose: () => extensions.close(),
|
|
@@ -20049,7 +20142,6 @@ function toStreamRecord(event) {
|
|
|
20049
20142
|
}
|
|
20050
20143
|
|
|
20051
20144
|
// packages/cli/src/commands/headless.ts
|
|
20052
|
-
var DEFAULT_MODEL2 = "anthropic/claude-opus-5";
|
|
20053
20145
|
async function headlessCommand(prompt, args) {
|
|
20054
20146
|
const flags = args.flags;
|
|
20055
20147
|
const requestedFormat = typeof flags["output-format"] === "string" ? flags["output-format"] : "text";
|
|
@@ -20080,6 +20172,12 @@ async function headlessCommand(prompt, args) {
|
|
|
20080
20172
|
const maxCostUsd = parseMaxCost(flags["max-cost"]);
|
|
20081
20173
|
if (maxCostUsd === "invalid") {
|
|
20082
20174
|
process.stderr.write(`"${flags["max-cost"]}" is not an amount in dollars
|
|
20175
|
+
`);
|
|
20176
|
+
return 2;
|
|
20177
|
+
}
|
|
20178
|
+
const reasoningEffort = parseReasoningEffort(flags["reasoning-effort"]);
|
|
20179
|
+
if (reasoningEffort === "invalid") {
|
|
20180
|
+
process.stderr.write(`"${flags["reasoning-effort"]}" is not a reasoning effort
|
|
20083
20181
|
`);
|
|
20084
20182
|
return 2;
|
|
20085
20183
|
}
|
|
@@ -20091,7 +20189,8 @@ async function headlessCommand(prompt, args) {
|
|
|
20091
20189
|
extraTools: extensions.tools,
|
|
20092
20190
|
problems: extensions.problems,
|
|
20093
20191
|
onDispose: () => extensions.close(),
|
|
20094
|
-
|
|
20192
|
+
...typeof flags.model === "string" ? { model: flags.model } : {},
|
|
20193
|
+
...reasoningEffort !== undefined ? { reasoningEffort } : {},
|
|
20095
20194
|
...mode ? { mode } : {},
|
|
20096
20195
|
...typeof flags["api-key"] === "string" ? { apiKey: flags["api-key"] } : {},
|
|
20097
20196
|
...curiosity ? { curiosity } : {},
|
|
@@ -20170,7 +20269,7 @@ async function headlessCommand(prompt, args) {
|
|
|
20170
20269
|
costUsd: session2.agent.costUsd,
|
|
20171
20270
|
durationMs: Date.now() - startedAt,
|
|
20172
20271
|
numMessages: session2.agent.history.length,
|
|
20173
|
-
model:
|
|
20272
|
+
model: `${session2.agent.model.provider.id}/${session2.agent.model.model.id}`,
|
|
20174
20273
|
permissionMode: session2.agent.permissionMode,
|
|
20175
20274
|
...session2.store ? { sessionId: session2.store.id } : {},
|
|
20176
20275
|
...failure ? { error: failure } : {}
|
|
@@ -20180,6 +20279,15 @@ async function headlessCommand(prompt, args) {
|
|
|
20180
20279
|
`);
|
|
20181
20280
|
return exitCode;
|
|
20182
20281
|
}
|
|
20282
|
+
function parseReasoningEffort(value) {
|
|
20283
|
+
if (value === undefined)
|
|
20284
|
+
return;
|
|
20285
|
+
if (value === "auto")
|
|
20286
|
+
return null;
|
|
20287
|
+
if (typeof value !== "string")
|
|
20288
|
+
return "invalid";
|
|
20289
|
+
return ["none", "low", "medium", "high", "xhigh"].includes(value) ? value : "invalid";
|
|
20290
|
+
}
|
|
20183
20291
|
function resumeFrom(flags) {
|
|
20184
20292
|
if (typeof flags.resume === "string")
|
|
20185
20293
|
return { resume: { path: flags.resume } };
|
|
@@ -20287,8 +20395,8 @@ run \`earshot models\` to see what is available
|
|
|
20287
20395
|
}
|
|
20288
20396
|
|
|
20289
20397
|
// packages/tui/src/app.tsx
|
|
20290
|
-
import { Box as
|
|
20291
|
-
import { useCallback, useEffect as
|
|
20398
|
+
import { Box as Box12, Static, Text as Text14, useApp as useApp3, useInput as useInput7 } from "ink";
|
|
20399
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef3, useState as useState7 } from "react";
|
|
20292
20400
|
|
|
20293
20401
|
// packages/tui/src/commands.ts
|
|
20294
20402
|
var SPECS = [
|
|
@@ -20301,6 +20409,16 @@ var SPECS = [
|
|
|
20301
20409
|
args: "[ref]",
|
|
20302
20410
|
summary: "Show the model in use, or switch to another for the rest of the session"
|
|
20303
20411
|
},
|
|
20412
|
+
{
|
|
20413
|
+
name: "reasoning",
|
|
20414
|
+
args: "[auto|none|low|medium|high|xhigh]",
|
|
20415
|
+
summary: "Show or change reasoning effort for the current model"
|
|
20416
|
+
},
|
|
20417
|
+
{
|
|
20418
|
+
name: "thinking",
|
|
20419
|
+
args: "[show|hide]",
|
|
20420
|
+
summary: "Show or hide streamed model reasoning"
|
|
20421
|
+
},
|
|
20304
20422
|
{
|
|
20305
20423
|
name: "mode",
|
|
20306
20424
|
args: "<plan|ask|accept-edits|auto|yolo>",
|
|
@@ -20359,6 +20477,11 @@ var SPECS = [
|
|
|
20359
20477
|
summary: "List this session's prompts, numbered",
|
|
20360
20478
|
idleOnly: true
|
|
20361
20479
|
},
|
|
20480
|
+
{
|
|
20481
|
+
name: "sessions",
|
|
20482
|
+
summary: "Browse and resume chats saved for this project",
|
|
20483
|
+
idleOnly: true
|
|
20484
|
+
},
|
|
20362
20485
|
{
|
|
20363
20486
|
name: "rewind",
|
|
20364
20487
|
args: "<n>",
|
|
@@ -20404,8 +20527,9 @@ function commandRows() {
|
|
|
20404
20527
|
return rows;
|
|
20405
20528
|
}
|
|
20406
20529
|
|
|
20407
|
-
// packages/tui/src/components/
|
|
20408
|
-
import {
|
|
20530
|
+
// packages/tui/src/components/activity.tsx
|
|
20531
|
+
import { Text } from "ink";
|
|
20532
|
+
import { useEffect, useState } from "react";
|
|
20409
20533
|
|
|
20410
20534
|
// packages/tui/src/theme.ts
|
|
20411
20535
|
var theme = {
|
|
@@ -20437,8 +20561,24 @@ var MODE_COLOR = {
|
|
|
20437
20561
|
yolo: theme.danger
|
|
20438
20562
|
};
|
|
20439
20563
|
|
|
20440
|
-
// packages/tui/src/components/
|
|
20564
|
+
// packages/tui/src/components/activity.tsx
|
|
20441
20565
|
import { jsxDEV } from "react/jsx-dev-runtime";
|
|
20566
|
+
var FRAMES = ["· ", "·· ", "···", " ··", " ·", " "];
|
|
20567
|
+
function Activity({ label }) {
|
|
20568
|
+
const [frame, setFrame] = useState(0);
|
|
20569
|
+
useEffect(() => {
|
|
20570
|
+
const timer = setInterval(() => setFrame((value) => (value + 1) % FRAMES.length), 120);
|
|
20571
|
+
return () => clearInterval(timer);
|
|
20572
|
+
}, []);
|
|
20573
|
+
return /* @__PURE__ */ jsxDEV(Text, {
|
|
20574
|
+
color: theme.muted,
|
|
20575
|
+
children: label ? `${label} ${FRAMES[frame]}` : FRAMES[frame]
|
|
20576
|
+
}, undefined, false, undefined, this);
|
|
20577
|
+
}
|
|
20578
|
+
|
|
20579
|
+
// packages/tui/src/components/command-menu.tsx
|
|
20580
|
+
import { Box, Text as Text2 } from "ink";
|
|
20581
|
+
import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
|
|
20442
20582
|
var SUMMARY_WIDTH = 58;
|
|
20443
20583
|
var VISIBLE = 10;
|
|
20444
20584
|
function menuEntries(query, commands, busy) {
|
|
@@ -20499,9 +20639,9 @@ function ranked(items, query) {
|
|
|
20499
20639
|
}
|
|
20500
20640
|
function CommandMenu({ entries, selected }) {
|
|
20501
20641
|
if (entries.length === 0) {
|
|
20502
|
-
return /* @__PURE__ */
|
|
20642
|
+
return /* @__PURE__ */ jsxDEV2(Box, {
|
|
20503
20643
|
marginTop: 1,
|
|
20504
|
-
children: /* @__PURE__ */
|
|
20644
|
+
children: /* @__PURE__ */ jsxDEV2(Text2, {
|
|
20505
20645
|
color: theme.muted,
|
|
20506
20646
|
children: "no command matches"
|
|
20507
20647
|
}, undefined, false, undefined, this)
|
|
@@ -20510,31 +20650,31 @@ function CommandMenu({ entries, selected }) {
|
|
|
20510
20650
|
const start = Math.min(Math.max(0, selected - VISIBLE + 1), Math.max(0, entries.length - VISIBLE));
|
|
20511
20651
|
const shown = entries.slice(start, start + VISIBLE);
|
|
20512
20652
|
const hidden = entries.length - shown.length;
|
|
20513
|
-
return /* @__PURE__ */
|
|
20653
|
+
return /* @__PURE__ */ jsxDEV2(Box, {
|
|
20514
20654
|
flexDirection: "column",
|
|
20515
20655
|
marginTop: 1,
|
|
20516
20656
|
children: [
|
|
20517
20657
|
shown.map((entry, index) => {
|
|
20518
20658
|
const active = start + index === selected;
|
|
20519
|
-
return /* @__PURE__ */
|
|
20659
|
+
return /* @__PURE__ */ jsxDEV2(Box, {
|
|
20520
20660
|
children: [
|
|
20521
|
-
/* @__PURE__ */
|
|
20661
|
+
/* @__PURE__ */ jsxDEV2(Text2, {
|
|
20522
20662
|
color: active ? theme.user : theme.muted,
|
|
20523
20663
|
children: active ? "› " : " "
|
|
20524
20664
|
}, undefined, false, undefined, this),
|
|
20525
|
-
/* @__PURE__ */
|
|
20665
|
+
/* @__PURE__ */ jsxDEV2(Text2, {
|
|
20526
20666
|
...rowColor(entry, active),
|
|
20527
20667
|
children: entry.label.padEnd(34)
|
|
20528
20668
|
}, undefined, false, undefined, this),
|
|
20529
|
-
/* @__PURE__ */
|
|
20669
|
+
/* @__PURE__ */ jsxDEV2(Text2, {
|
|
20530
20670
|
color: theme.muted,
|
|
20531
20671
|
children: clamp(`${entry.scope ? `[${entry.scope}] ` : ""}${entry.summary}${entry.disabled ? " (not while a turn is running)" : ""}`)
|
|
20532
20672
|
}, undefined, false, undefined, this)
|
|
20533
20673
|
]
|
|
20534
20674
|
}, entry.label, true, undefined, this);
|
|
20535
20675
|
}),
|
|
20536
|
-
/* @__PURE__ */
|
|
20537
|
-
children: /* @__PURE__ */
|
|
20676
|
+
/* @__PURE__ */ jsxDEV2(Box, {
|
|
20677
|
+
children: /* @__PURE__ */ jsxDEV2(Text2, {
|
|
20538
20678
|
color: theme.muted,
|
|
20539
20679
|
children: [
|
|
20540
20680
|
hidden > 0 ? ` ${hidden} more · ` : " ",
|
|
@@ -20547,13 +20687,13 @@ function CommandMenu({ entries, selected }) {
|
|
|
20547
20687
|
}
|
|
20548
20688
|
|
|
20549
20689
|
// packages/tui/src/components/markdown.tsx
|
|
20550
|
-
import { Box as Box2, Text as
|
|
20551
|
-
import { jsxDEV as
|
|
20690
|
+
import { Box as Box2, Text as Text3 } from "ink";
|
|
20691
|
+
import { jsxDEV as jsxDEV3, Fragment } from "react/jsx-dev-runtime";
|
|
20552
20692
|
function Markdown({ text: text2 }) {
|
|
20553
20693
|
const blocks = splitBlocks(text2);
|
|
20554
|
-
return /* @__PURE__ */
|
|
20694
|
+
return /* @__PURE__ */ jsxDEV3(Box2, {
|
|
20555
20695
|
flexDirection: "column",
|
|
20556
|
-
children: blocks.map((block, index) => /* @__PURE__ */
|
|
20696
|
+
children: blocks.map((block, index) => /* @__PURE__ */ jsxDEV3(Block, {
|
|
20557
20697
|
block
|
|
20558
20698
|
}, index, false, undefined, this))
|
|
20559
20699
|
}, undefined, false, undefined, this);
|
|
@@ -20632,19 +20772,19 @@ function splitBlocks(text2) {
|
|
|
20632
20772
|
function Block({ block }) {
|
|
20633
20773
|
switch (block.kind) {
|
|
20634
20774
|
case "code":
|
|
20635
|
-
return /* @__PURE__ */
|
|
20775
|
+
return /* @__PURE__ */ jsxDEV3(Box2, {
|
|
20636
20776
|
flexDirection: "column",
|
|
20637
20777
|
marginY: 1,
|
|
20638
20778
|
paddingLeft: 2,
|
|
20639
|
-
children: block.lines.map((line, index) => /* @__PURE__ */
|
|
20779
|
+
children: block.lines.map((line, index) => /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20640
20780
|
color: theme.tool,
|
|
20641
20781
|
children: line
|
|
20642
20782
|
}, index, false, undefined, this))
|
|
20643
20783
|
}, undefined, false, undefined, this);
|
|
20644
20784
|
case "heading":
|
|
20645
|
-
return /* @__PURE__ */
|
|
20785
|
+
return /* @__PURE__ */ jsxDEV3(Box2, {
|
|
20646
20786
|
marginTop: block.level <= 2 ? 1 : 0,
|
|
20647
|
-
children: /* @__PURE__ */
|
|
20787
|
+
children: /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20648
20788
|
bold: true,
|
|
20649
20789
|
underline: block.level === 1,
|
|
20650
20790
|
color: theme.assistant,
|
|
@@ -20652,29 +20792,29 @@ function Block({ block }) {
|
|
|
20652
20792
|
}, undefined, false, undefined, this)
|
|
20653
20793
|
}, undefined, false, undefined, this);
|
|
20654
20794
|
case "rule":
|
|
20655
|
-
return /* @__PURE__ */
|
|
20795
|
+
return /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20656
20796
|
color: theme.muted,
|
|
20657
20797
|
children: "─".repeat(40)
|
|
20658
20798
|
}, undefined, false, undefined, this);
|
|
20659
20799
|
case "list":
|
|
20660
|
-
return /* @__PURE__ */
|
|
20800
|
+
return /* @__PURE__ */ jsxDEV3(Box2, {
|
|
20661
20801
|
flexDirection: "column",
|
|
20662
|
-
children: block.items.map((item, index) => /* @__PURE__ */
|
|
20802
|
+
children: block.items.map((item, index) => /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20663
20803
|
children: [
|
|
20664
20804
|
" ",
|
|
20665
20805
|
block.ordered ? `${index + 1}.` : "-",
|
|
20666
20806
|
" ",
|
|
20667
|
-
/* @__PURE__ */
|
|
20807
|
+
/* @__PURE__ */ jsxDEV3(Inline, {
|
|
20668
20808
|
text: item
|
|
20669
20809
|
}, undefined, false, undefined, this)
|
|
20670
20810
|
]
|
|
20671
20811
|
}, index, true, undefined, this))
|
|
20672
20812
|
}, undefined, false, undefined, this);
|
|
20673
20813
|
case "quote":
|
|
20674
|
-
return /* @__PURE__ */
|
|
20814
|
+
return /* @__PURE__ */ jsxDEV3(Box2, {
|
|
20675
20815
|
flexDirection: "column",
|
|
20676
20816
|
paddingLeft: 1,
|
|
20677
|
-
children: block.lines.map((line, index) => /* @__PURE__ */
|
|
20817
|
+
children: block.lines.map((line, index) => /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20678
20818
|
color: theme.muted,
|
|
20679
20819
|
italic: true,
|
|
20680
20820
|
children: [
|
|
@@ -20684,8 +20824,8 @@ function Block({ block }) {
|
|
|
20684
20824
|
}, index, true, undefined, this))
|
|
20685
20825
|
}, undefined, false, undefined, this);
|
|
20686
20826
|
default:
|
|
20687
|
-
return /* @__PURE__ */
|
|
20688
|
-
children: /* @__PURE__ */
|
|
20827
|
+
return /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20828
|
+
children: /* @__PURE__ */ jsxDEV3(Inline, {
|
|
20689
20829
|
text: block.text
|
|
20690
20830
|
}, undefined, false, undefined, this)
|
|
20691
20831
|
}, undefined, false, undefined, this);
|
|
@@ -20697,41 +20837,41 @@ function inlineToText(text2) {
|
|
|
20697
20837
|
function Inline({ text: text2 }) {
|
|
20698
20838
|
const pattern = /(\*\*.+?\*\*|__.+?__|`.+?`|\*.+?\*|_.+?_)/g;
|
|
20699
20839
|
const parts = text2.split(pattern);
|
|
20700
|
-
return /* @__PURE__ */
|
|
20840
|
+
return /* @__PURE__ */ jsxDEV3(Fragment, {
|
|
20701
20841
|
children: parts.map((part, index) => {
|
|
20702
20842
|
if (part === "")
|
|
20703
20843
|
return null;
|
|
20704
20844
|
if (part.startsWith("**") && part.endsWith("**")) {
|
|
20705
|
-
return /* @__PURE__ */
|
|
20845
|
+
return /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20706
20846
|
bold: true,
|
|
20707
20847
|
children: part.slice(2, -2)
|
|
20708
20848
|
}, index, false, undefined, this);
|
|
20709
20849
|
}
|
|
20710
20850
|
if (part.startsWith("__") && part.endsWith("__")) {
|
|
20711
|
-
return /* @__PURE__ */
|
|
20851
|
+
return /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20712
20852
|
bold: true,
|
|
20713
20853
|
children: part.slice(2, -2)
|
|
20714
20854
|
}, index, false, undefined, this);
|
|
20715
20855
|
}
|
|
20716
20856
|
if (part.startsWith("`") && part.endsWith("`")) {
|
|
20717
|
-
return /* @__PURE__ */
|
|
20857
|
+
return /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20718
20858
|
color: theme.tool,
|
|
20719
20859
|
children: part.slice(1, -1)
|
|
20720
20860
|
}, index, false, undefined, this);
|
|
20721
20861
|
}
|
|
20722
20862
|
if (part.startsWith("*") && part.endsWith("*")) {
|
|
20723
|
-
return /* @__PURE__ */
|
|
20863
|
+
return /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20724
20864
|
italic: true,
|
|
20725
20865
|
children: part.slice(1, -1)
|
|
20726
20866
|
}, index, false, undefined, this);
|
|
20727
20867
|
}
|
|
20728
20868
|
if (part.startsWith("_") && part.endsWith("_")) {
|
|
20729
|
-
return /* @__PURE__ */
|
|
20869
|
+
return /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20730
20870
|
italic: true,
|
|
20731
20871
|
children: part.slice(1, -1)
|
|
20732
20872
|
}, index, false, undefined, this);
|
|
20733
20873
|
}
|
|
20734
|
-
return /* @__PURE__ */
|
|
20874
|
+
return /* @__PURE__ */ jsxDEV3(Text3, {
|
|
20735
20875
|
children: part
|
|
20736
20876
|
}, index, false, undefined, this);
|
|
20737
20877
|
})
|
|
@@ -20739,24 +20879,24 @@ function Inline({ text: text2 }) {
|
|
|
20739
20879
|
}
|
|
20740
20880
|
|
|
20741
20881
|
// packages/tui/src/components/memory-capture.tsx
|
|
20742
|
-
import { Box as Box3, Text as
|
|
20743
|
-
import { jsxDEV as
|
|
20882
|
+
import { Box as Box3, Text as Text4 } from "ink";
|
|
20883
|
+
import { jsxDEV as jsxDEV4 } from "react/jsx-dev-runtime";
|
|
20744
20884
|
function MemoryCapture({ candidate }) {
|
|
20745
|
-
return /* @__PURE__ */
|
|
20885
|
+
return /* @__PURE__ */ jsxDEV4(Box3, {
|
|
20746
20886
|
marginTop: 1,
|
|
20747
20887
|
children: [
|
|
20748
|
-
/* @__PURE__ */
|
|
20888
|
+
/* @__PURE__ */ jsxDEV4(Text4, {
|
|
20749
20889
|
color: theme.accent,
|
|
20750
20890
|
children: "remember "
|
|
20751
20891
|
}, undefined, false, undefined, this),
|
|
20752
|
-
/* @__PURE__ */
|
|
20892
|
+
/* @__PURE__ */ jsxDEV4(Text4, {
|
|
20753
20893
|
children: [
|
|
20754
20894
|
"“",
|
|
20755
20895
|
candidate.text,
|
|
20756
20896
|
"”"
|
|
20757
20897
|
]
|
|
20758
20898
|
}, undefined, true, undefined, this),
|
|
20759
|
-
/* @__PURE__ */
|
|
20899
|
+
/* @__PURE__ */ jsxDEV4(Text4, {
|
|
20760
20900
|
color: theme.muted,
|
|
20761
20901
|
children: "? ctrl+r for this project · ctrl+g everywhere"
|
|
20762
20902
|
}, undefined, false, undefined, this)
|
|
@@ -20765,12 +20905,12 @@ function MemoryCapture({ candidate }) {
|
|
|
20765
20905
|
}
|
|
20766
20906
|
|
|
20767
20907
|
// packages/tui/src/components/permission.tsx
|
|
20768
|
-
import { Box as Box5, Text as
|
|
20769
|
-
import { useState } from "react";
|
|
20908
|
+
import { Box as Box5, Text as Text6, useInput } from "ink";
|
|
20909
|
+
import { useState as useState2 } from "react";
|
|
20770
20910
|
|
|
20771
20911
|
// packages/tui/src/components/diff.tsx
|
|
20772
|
-
import { Box as Box4, Text as
|
|
20773
|
-
import { jsxDEV as
|
|
20912
|
+
import { Box as Box4, Text as Text5 } from "ink";
|
|
20913
|
+
import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
|
|
20774
20914
|
var MAX_LINES = 60;
|
|
20775
20915
|
function DiffView({ diff: diff2, maxLines = MAX_LINES }) {
|
|
20776
20916
|
const lines = diff2.split(`
|
|
@@ -20778,15 +20918,15 @@ function DiffView({ diff: diff2, maxLines = MAX_LINES }) {
|
|
|
20778
20918
|
const body = lines.filter((line) => !line.startsWith("---") && !line.startsWith("+++"));
|
|
20779
20919
|
const shown = body.slice(0, maxLines);
|
|
20780
20920
|
const hidden = body.length - shown.length;
|
|
20781
|
-
return /* @__PURE__ */
|
|
20921
|
+
return /* @__PURE__ */ jsxDEV5(Box4, {
|
|
20782
20922
|
flexDirection: "column",
|
|
20783
20923
|
children: [
|
|
20784
|
-
shown.map((line, index) => /* @__PURE__ */
|
|
20924
|
+
shown.map((line, index) => /* @__PURE__ */ jsxDEV5(Text5, {
|
|
20785
20925
|
color: colorFor(line),
|
|
20786
20926
|
wrap: "truncate-end",
|
|
20787
20927
|
children: line === "" ? " " : line
|
|
20788
20928
|
}, index, false, undefined, this)),
|
|
20789
|
-
hidden > 0 && /* @__PURE__ */
|
|
20929
|
+
hidden > 0 && /* @__PURE__ */ jsxDEV5(Text5, {
|
|
20790
20930
|
color: theme.muted,
|
|
20791
20931
|
children: [
|
|
20792
20932
|
" ",
|
|
@@ -20821,9 +20961,9 @@ function diffStat(diff2) {
|
|
|
20821
20961
|
}
|
|
20822
20962
|
|
|
20823
20963
|
// packages/tui/src/components/permission.tsx
|
|
20824
|
-
import { jsxDEV as
|
|
20964
|
+
import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
|
|
20825
20965
|
function PermissionPrompt({ request, reason, onChoice }) {
|
|
20826
|
-
const [selected, setSelected] =
|
|
20966
|
+
const [selected, setSelected] = useState2(0);
|
|
20827
20967
|
const options = [
|
|
20828
20968
|
{ label: "Allow once", choice: { kind: "allow-once" }, color: theme.assistant },
|
|
20829
20969
|
{
|
|
@@ -20849,32 +20989,32 @@ function PermissionPrompt({ request, reason, onChoice }) {
|
|
|
20849
20989
|
});
|
|
20850
20990
|
const isDiff = request.detail.includes(`
|
|
20851
20991
|
@@`) || request.detail.startsWith("---");
|
|
20852
|
-
return /* @__PURE__ */
|
|
20992
|
+
return /* @__PURE__ */ jsxDEV6(Box5, {
|
|
20853
20993
|
flexDirection: "column",
|
|
20854
20994
|
borderStyle: "round",
|
|
20855
20995
|
borderColor: theme.warning,
|
|
20856
20996
|
paddingX: 1,
|
|
20857
20997
|
children: [
|
|
20858
|
-
/* @__PURE__ */
|
|
20998
|
+
/* @__PURE__ */ jsxDEV6(Text6, {
|
|
20859
20999
|
bold: true,
|
|
20860
21000
|
color: theme.warning,
|
|
20861
21001
|
children: request.title
|
|
20862
21002
|
}, undefined, false, undefined, this),
|
|
20863
|
-
/* @__PURE__ */
|
|
21003
|
+
/* @__PURE__ */ jsxDEV6(Text6, {
|
|
20864
21004
|
color: theme.muted,
|
|
20865
21005
|
children: reason
|
|
20866
21006
|
}, undefined, false, undefined, this),
|
|
20867
|
-
/* @__PURE__ */
|
|
21007
|
+
/* @__PURE__ */ jsxDEV6(Box5, {
|
|
20868
21008
|
marginY: 1,
|
|
20869
21009
|
flexDirection: "column",
|
|
20870
|
-
children: isDiff ? /* @__PURE__ */
|
|
21010
|
+
children: isDiff ? /* @__PURE__ */ jsxDEV6(DiffView, {
|
|
20871
21011
|
diff: request.detail
|
|
20872
|
-
}, undefined, false, undefined, this) : /* @__PURE__ */
|
|
21012
|
+
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV6(Text6, {
|
|
20873
21013
|
wrap: "wrap",
|
|
20874
21014
|
children: request.detail
|
|
20875
21015
|
}, undefined, false, undefined, this)
|
|
20876
21016
|
}, undefined, false, undefined, this),
|
|
20877
|
-
options.map((option, index) => /* @__PURE__ */
|
|
21017
|
+
options.map((option, index) => /* @__PURE__ */ jsxDEV6(Text6, {
|
|
20878
21018
|
color: index === selected ? theme.accent : option.color,
|
|
20879
21019
|
children: [
|
|
20880
21020
|
index === selected ? "❯ " : " ",
|
|
@@ -20889,13 +21029,13 @@ function truncate2(value, max) {
|
|
|
20889
21029
|
}
|
|
20890
21030
|
|
|
20891
21031
|
// packages/tui/src/components/question.tsx
|
|
20892
|
-
import { Box as Box6, Text as
|
|
20893
|
-
import { useState as
|
|
21032
|
+
import { Box as Box6, Text as Text8, useInput as useInput3 } from "ink";
|
|
21033
|
+
import { useState as useState3 } from "react";
|
|
20894
21034
|
|
|
20895
21035
|
// packages/tui/src/components/text-input.tsx
|
|
20896
|
-
import { Text as
|
|
20897
|
-
import { useEffect, useRef } from "react";
|
|
20898
|
-
import { jsxDEV as
|
|
21036
|
+
import { Text as Text7, useInput as useInput2 } from "ink";
|
|
21037
|
+
import { useEffect as useEffect2, useRef } from "react";
|
|
21038
|
+
import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
|
|
20899
21039
|
function TextInput({
|
|
20900
21040
|
value,
|
|
20901
21041
|
onChange,
|
|
@@ -20904,7 +21044,7 @@ function TextInput({
|
|
|
20904
21044
|
isActive = true
|
|
20905
21045
|
}) {
|
|
20906
21046
|
const buffer = useRef(value);
|
|
20907
|
-
|
|
21047
|
+
useEffect2(() => {
|
|
20908
21048
|
buffer.current = value;
|
|
20909
21049
|
}, [value]);
|
|
20910
21050
|
useInput2((input, key2) => {
|
|
@@ -20929,23 +21069,23 @@ function TextInput({
|
|
|
20929
21069
|
}
|
|
20930
21070
|
}, { isActive });
|
|
20931
21071
|
if (value === "") {
|
|
20932
|
-
return /* @__PURE__ */
|
|
21072
|
+
return /* @__PURE__ */ jsxDEV7(Text7, {
|
|
20933
21073
|
children: [
|
|
20934
|
-
/* @__PURE__ */
|
|
21074
|
+
/* @__PURE__ */ jsxDEV7(Text7, {
|
|
20935
21075
|
inverse: true,
|
|
20936
21076
|
children: " "
|
|
20937
21077
|
}, undefined, false, undefined, this),
|
|
20938
|
-
/* @__PURE__ */
|
|
21078
|
+
/* @__PURE__ */ jsxDEV7(Text7, {
|
|
20939
21079
|
color: theme.muted,
|
|
20940
21080
|
children: placeholder
|
|
20941
21081
|
}, undefined, false, undefined, this)
|
|
20942
21082
|
]
|
|
20943
21083
|
}, undefined, true, undefined, this);
|
|
20944
21084
|
}
|
|
20945
|
-
return /* @__PURE__ */
|
|
21085
|
+
return /* @__PURE__ */ jsxDEV7(Text7, {
|
|
20946
21086
|
children: [
|
|
20947
21087
|
value,
|
|
20948
|
-
/* @__PURE__ */
|
|
21088
|
+
/* @__PURE__ */ jsxDEV7(Text7, {
|
|
20949
21089
|
inverse: true,
|
|
20950
21090
|
children: " "
|
|
20951
21091
|
}, undefined, false, undefined, this)
|
|
@@ -20954,11 +21094,11 @@ function TextInput({
|
|
|
20954
21094
|
}
|
|
20955
21095
|
|
|
20956
21096
|
// packages/tui/src/components/question.tsx
|
|
20957
|
-
import { jsxDEV as
|
|
21097
|
+
import { jsxDEV as jsxDEV8 } from "react/jsx-dev-runtime";
|
|
20958
21098
|
function QuestionPrompt({ question, options = [], onAnswer }) {
|
|
20959
|
-
const [selected, setSelected] =
|
|
20960
|
-
const [typing, setTyping] =
|
|
20961
|
-
const [value, setValue] =
|
|
21099
|
+
const [selected, setSelected] = useState3(0);
|
|
21100
|
+
const [typing, setTyping] = useState3(options.length === 0);
|
|
21101
|
+
const [value, setValue] = useState3("");
|
|
20962
21102
|
useInput3((input, key2) => {
|
|
20963
21103
|
if (key2.upArrow)
|
|
20964
21104
|
setSelected((n) => (n + options.length - 1) % options.length);
|
|
@@ -20971,29 +21111,29 @@ function QuestionPrompt({ question, options = [], onAnswer }) {
|
|
|
20971
21111
|
setValue(input);
|
|
20972
21112
|
}
|
|
20973
21113
|
}, { isActive: !typing });
|
|
20974
|
-
return /* @__PURE__ */
|
|
21114
|
+
return /* @__PURE__ */ jsxDEV8(Box6, {
|
|
20975
21115
|
flexDirection: "column",
|
|
20976
21116
|
borderStyle: "round",
|
|
20977
21117
|
borderColor: theme.accent,
|
|
20978
21118
|
paddingX: 1,
|
|
20979
21119
|
children: [
|
|
20980
|
-
/* @__PURE__ */
|
|
21120
|
+
/* @__PURE__ */ jsxDEV8(Text8, {
|
|
20981
21121
|
bold: true,
|
|
20982
21122
|
color: theme.accent,
|
|
20983
21123
|
children: question
|
|
20984
21124
|
}, undefined, false, undefined, this),
|
|
20985
|
-
!typing && options.map((option, index) => /* @__PURE__ */
|
|
21125
|
+
!typing && options.map((option, index) => /* @__PURE__ */ jsxDEV8(Text8, {
|
|
20986
21126
|
color: index === selected ? theme.accent : theme.muted,
|
|
20987
21127
|
children: [
|
|
20988
21128
|
index === selected ? "❯ " : " ",
|
|
20989
21129
|
option
|
|
20990
21130
|
]
|
|
20991
21131
|
}, option, true, undefined, this)),
|
|
20992
|
-
!typing && /* @__PURE__ */
|
|
21132
|
+
!typing && /* @__PURE__ */ jsxDEV8(Text8, {
|
|
20993
21133
|
color: theme.muted,
|
|
20994
21134
|
children: "or start typing to answer in your own words"
|
|
20995
21135
|
}, undefined, false, undefined, this),
|
|
20996
|
-
typing && /* @__PURE__ */
|
|
21136
|
+
typing && /* @__PURE__ */ jsxDEV8(TextInput, {
|
|
20997
21137
|
value,
|
|
20998
21138
|
onChange: setValue,
|
|
20999
21139
|
onSubmit: (answer) => onAnswer(answer.trim()),
|
|
@@ -21003,11 +21143,60 @@ function QuestionPrompt({ question, options = [], onAnswer }) {
|
|
|
21003
21143
|
}, undefined, true, undefined, this);
|
|
21004
21144
|
}
|
|
21005
21145
|
|
|
21146
|
+
// packages/tui/src/components/reasoning-picker.tsx
|
|
21147
|
+
import { Box as Box7, Text as Text9, useInput as useInput4 } from "ink";
|
|
21148
|
+
import { useState as useState4 } from "react";
|
|
21149
|
+
import { jsxDEV as jsxDEV9 } from "react/jsx-dev-runtime";
|
|
21150
|
+
var choices = ["auto", "none", "low", "medium", "high", "xhigh"];
|
|
21151
|
+
function ReasoningPicker({
|
|
21152
|
+
current,
|
|
21153
|
+
onDone,
|
|
21154
|
+
onCancel
|
|
21155
|
+
}) {
|
|
21156
|
+
const [cursor, setCursor] = useState4(Math.max(0, choices.indexOf(current ?? "auto")));
|
|
21157
|
+
useInput4((_input, key2) => {
|
|
21158
|
+
if (key2.escape)
|
|
21159
|
+
return onCancel();
|
|
21160
|
+
if (key2.upArrow)
|
|
21161
|
+
setCursor((value) => value <= 0 ? choices.length - 1 : value - 1);
|
|
21162
|
+
if (key2.downArrow)
|
|
21163
|
+
setCursor((value) => value >= choices.length - 1 ? 0 : value + 1);
|
|
21164
|
+
if (key2.return) {
|
|
21165
|
+
const selected = choices[cursor] ?? "auto";
|
|
21166
|
+
onDone(selected === "auto" ? undefined : selected);
|
|
21167
|
+
}
|
|
21168
|
+
});
|
|
21169
|
+
return /* @__PURE__ */ jsxDEV9(Box7, {
|
|
21170
|
+
flexDirection: "column",
|
|
21171
|
+
children: [
|
|
21172
|
+
/* @__PURE__ */ jsxDEV9(Text9, {
|
|
21173
|
+
children: "reasoning effort"
|
|
21174
|
+
}, undefined, false, undefined, this),
|
|
21175
|
+
/* @__PURE__ */ jsxDEV9(Box7, {
|
|
21176
|
+
flexDirection: "column",
|
|
21177
|
+
marginTop: 1,
|
|
21178
|
+
children: choices.map((choice, index) => /* @__PURE__ */ jsxDEV9(Text9, {
|
|
21179
|
+
color: index === cursor ? theme.user : theme.muted,
|
|
21180
|
+
children: [
|
|
21181
|
+
index === cursor ? "› " : " ",
|
|
21182
|
+
choice
|
|
21183
|
+
]
|
|
21184
|
+
}, choice, true, undefined, this))
|
|
21185
|
+
}, undefined, false, undefined, this),
|
|
21186
|
+
/* @__PURE__ */ jsxDEV9(Text9, {
|
|
21187
|
+
color: theme.muted,
|
|
21188
|
+
children: "↑↓ choose · enter select · esc cancel"
|
|
21189
|
+
}, undefined, false, undefined, this)
|
|
21190
|
+
]
|
|
21191
|
+
}, undefined, true, undefined, this);
|
|
21192
|
+
}
|
|
21193
|
+
|
|
21006
21194
|
// packages/tui/src/components/status.tsx
|
|
21007
|
-
import { Box as
|
|
21008
|
-
import { jsxDEV as
|
|
21195
|
+
import { Box as Box8, Text as Text10 } from "ink";
|
|
21196
|
+
import { jsxDEV as jsxDEV10 } from "react/jsx-dev-runtime";
|
|
21009
21197
|
function StatusLine({
|
|
21010
21198
|
model: model2,
|
|
21199
|
+
reasoningEffort,
|
|
21011
21200
|
mode,
|
|
21012
21201
|
costUsd,
|
|
21013
21202
|
todos,
|
|
@@ -21019,27 +21208,34 @@ function StatusLine({
|
|
|
21019
21208
|
const done = todos.filter((todo2) => todo2.status === "done").length;
|
|
21020
21209
|
const current = todos.find((todo2) => todo2.status === "in_progress");
|
|
21021
21210
|
const used = context2.window > 0 ? Math.min(100, context2.tokens / context2.window * 100) : 0;
|
|
21022
|
-
return /* @__PURE__ */
|
|
21211
|
+
return /* @__PURE__ */ jsxDEV10(Box8, {
|
|
21023
21212
|
children: [
|
|
21024
|
-
/* @__PURE__ */
|
|
21213
|
+
/* @__PURE__ */ jsxDEV10(Text10, {
|
|
21025
21214
|
color: MODE_COLOR[mode] ?? theme.muted,
|
|
21026
21215
|
children: MODE_LABEL[mode] ?? mode
|
|
21027
21216
|
}, undefined, false, undefined, this),
|
|
21028
|
-
/* @__PURE__ */
|
|
21217
|
+
/* @__PURE__ */ jsxDEV10(Text10, {
|
|
21029
21218
|
color: theme.muted,
|
|
21030
21219
|
children: [
|
|
21031
21220
|
" · ",
|
|
21032
21221
|
model2
|
|
21033
21222
|
]
|
|
21034
21223
|
}, undefined, true, undefined, this),
|
|
21035
|
-
/* @__PURE__ */
|
|
21224
|
+
reasoningEffort && /* @__PURE__ */ jsxDEV10(Text10, {
|
|
21225
|
+
color: theme.muted,
|
|
21226
|
+
children: [
|
|
21227
|
+
" · ",
|
|
21228
|
+
reasoningEffort
|
|
21229
|
+
]
|
|
21230
|
+
}, undefined, true, undefined, this),
|
|
21231
|
+
/* @__PURE__ */ jsxDEV10(Text10, {
|
|
21036
21232
|
color: theme.muted,
|
|
21037
21233
|
children: [
|
|
21038
21234
|
" · $",
|
|
21039
21235
|
costUsd.toFixed(4)
|
|
21040
21236
|
]
|
|
21041
21237
|
}, undefined, true, undefined, this),
|
|
21042
|
-
context2.window > 0 && /* @__PURE__ */
|
|
21238
|
+
context2.window > 0 && /* @__PURE__ */ jsxDEV10(Text10, {
|
|
21043
21239
|
color: used >= 80 ? theme.warning : theme.muted,
|
|
21044
21240
|
children: [
|
|
21045
21241
|
" · ",
|
|
@@ -21047,7 +21243,7 @@ function StatusLine({
|
|
|
21047
21243
|
"% ctx"
|
|
21048
21244
|
]
|
|
21049
21245
|
}, undefined, true, undefined, this),
|
|
21050
|
-
compacted > 0 && /* @__PURE__ */
|
|
21246
|
+
compacted > 0 && /* @__PURE__ */ jsxDEV10(Text10, {
|
|
21051
21247
|
color: theme.muted,
|
|
21052
21248
|
children: [
|
|
21053
21249
|
" · ",
|
|
@@ -21055,7 +21251,7 @@ function StatusLine({
|
|
|
21055
21251
|
" summarised"
|
|
21056
21252
|
]
|
|
21057
21253
|
}, undefined, true, undefined, this),
|
|
21058
|
-
todos.length > 0 && /* @__PURE__ */
|
|
21254
|
+
todos.length > 0 && /* @__PURE__ */ jsxDEV10(Text10, {
|
|
21059
21255
|
color: theme.muted,
|
|
21060
21256
|
children: [
|
|
21061
21257
|
" ",
|
|
@@ -21066,11 +21262,11 @@ function StatusLine({
|
|
|
21066
21262
|
current ? ` ${truncate3(current.text, 40)}` : ""
|
|
21067
21263
|
]
|
|
21068
21264
|
}, undefined, true, undefined, this),
|
|
21069
|
-
busy && /* @__PURE__ */
|
|
21265
|
+
busy && /* @__PURE__ */ jsxDEV10(Text10, {
|
|
21070
21266
|
color: theme.warning,
|
|
21071
21267
|
children: " · working (esc to interrupt)"
|
|
21072
21268
|
}, undefined, false, undefined, this),
|
|
21073
|
-
queued > 0 && /* @__PURE__ */
|
|
21269
|
+
queued > 0 && /* @__PURE__ */ jsxDEV10(Text10, {
|
|
21074
21270
|
color: theme.accent,
|
|
21075
21271
|
children: [
|
|
21076
21272
|
" · ",
|
|
@@ -21086,8 +21282,8 @@ function truncate3(value, max) {
|
|
|
21086
21282
|
}
|
|
21087
21283
|
|
|
21088
21284
|
// packages/tui/src/components/tool-block.tsx
|
|
21089
|
-
import { Box as
|
|
21090
|
-
import { jsxDEV as
|
|
21285
|
+
import { Box as Box9, Text as Text11 } from "ink";
|
|
21286
|
+
import { jsxDEV as jsxDEV11 } from "react/jsx-dev-runtime";
|
|
21091
21287
|
var PREVIEW_LINES = 8;
|
|
21092
21288
|
function ToolBlock({
|
|
21093
21289
|
name,
|
|
@@ -21106,27 +21302,27 @@ function ToolBlock({
|
|
|
21106
21302
|
const showAll = expanded || isError;
|
|
21107
21303
|
const shown = showAll ? lines : lines.slice(0, PREVIEW_LINES);
|
|
21108
21304
|
const hidden = lines.length - shown.length;
|
|
21109
|
-
return /* @__PURE__ */
|
|
21305
|
+
return /* @__PURE__ */ jsxDEV11(Box9, {
|
|
21110
21306
|
flexDirection: "column",
|
|
21111
21307
|
marginTop: 1,
|
|
21112
21308
|
children: [
|
|
21113
|
-
/* @__PURE__ */
|
|
21309
|
+
/* @__PURE__ */ jsxDEV11(Text11, {
|
|
21114
21310
|
color,
|
|
21115
21311
|
children: [
|
|
21116
21312
|
marker2,
|
|
21117
21313
|
" ",
|
|
21118
|
-
/* @__PURE__ */
|
|
21314
|
+
/* @__PURE__ */ jsxDEV11(Text11, {
|
|
21119
21315
|
bold: true,
|
|
21120
21316
|
children: name
|
|
21121
21317
|
}, undefined, false, undefined, this),
|
|
21122
|
-
title ? /* @__PURE__ */
|
|
21318
|
+
title ? /* @__PURE__ */ jsxDEV11(Text11, {
|
|
21123
21319
|
color: theme.muted,
|
|
21124
21320
|
children: [
|
|
21125
21321
|
" ",
|
|
21126
21322
|
title
|
|
21127
21323
|
]
|
|
21128
21324
|
}, undefined, true, undefined, this) : null,
|
|
21129
|
-
isDiff && !showAll ? /* @__PURE__ */
|
|
21325
|
+
isDiff && !showAll ? /* @__PURE__ */ jsxDEV11(Text11, {
|
|
21130
21326
|
color: theme.muted,
|
|
21131
21327
|
children: [
|
|
21132
21328
|
" ",
|
|
@@ -21135,12 +21331,12 @@ function ToolBlock({
|
|
|
21135
21331
|
}, undefined, true, undefined, this) : null
|
|
21136
21332
|
]
|
|
21137
21333
|
}, undefined, true, undefined, this),
|
|
21138
|
-
isDiff && showAll ? /* @__PURE__ */
|
|
21334
|
+
isDiff && showAll ? /* @__PURE__ */ jsxDEV11(Box9, {
|
|
21139
21335
|
marginLeft: 2,
|
|
21140
|
-
children: /* @__PURE__ */
|
|
21336
|
+
children: /* @__PURE__ */ jsxDEV11(DiffView, {
|
|
21141
21337
|
diff: output
|
|
21142
21338
|
}, undefined, false, undefined, this)
|
|
21143
|
-
}, undefined, false, undefined, this) : shown.map((line, index) => /* @__PURE__ */
|
|
21339
|
+
}, undefined, false, undefined, this) : shown.map((line, index) => /* @__PURE__ */ jsxDEV11(Text11, {
|
|
21144
21340
|
color: theme.muted,
|
|
21145
21341
|
wrap: "truncate-end",
|
|
21146
21342
|
children: [
|
|
@@ -21148,7 +21344,7 @@ function ToolBlock({
|
|
|
21148
21344
|
line
|
|
21149
21345
|
]
|
|
21150
21346
|
}, index, true, undefined, this)),
|
|
21151
|
-
hidden > 0 && !isDiff && /* @__PURE__ */
|
|
21347
|
+
hidden > 0 && !isDiff && /* @__PURE__ */ jsxDEV11(Text11, {
|
|
21152
21348
|
color: theme.muted,
|
|
21153
21349
|
children: [
|
|
21154
21350
|
" ",
|
|
@@ -21161,1177 +21357,1640 @@ function ToolBlock({
|
|
|
21161
21357
|
}, undefined, true, undefined, this);
|
|
21162
21358
|
}
|
|
21163
21359
|
|
|
21164
|
-
// packages/tui/src/
|
|
21165
|
-
import {
|
|
21166
|
-
|
|
21167
|
-
|
|
21168
|
-
|
|
21169
|
-
|
|
21170
|
-
|
|
21171
|
-
|
|
21172
|
-
|
|
21173
|
-
|
|
21174
|
-
|
|
21360
|
+
// packages/tui/src/onboarding.tsx
|
|
21361
|
+
import { Box as Box10, Text as Text12, useApp, useInput as useInput5 } from "ink";
|
|
21362
|
+
import { useCallback, useRef as useRef2, useState as useState5 } from "react";
|
|
21363
|
+
import { jsxDEV as jsxDEV12 } from "react/jsx-dev-runtime";
|
|
21364
|
+
var EFFORTS = ["auto", "none", "low", "medium", "high", "xhigh"];
|
|
21365
|
+
function Onboarding({
|
|
21366
|
+
onDone,
|
|
21367
|
+
embedded = false,
|
|
21368
|
+
defaultScope = "global",
|
|
21369
|
+
...rest
|
|
21370
|
+
}) {
|
|
21175
21371
|
const { exit } = useApp();
|
|
21176
|
-
const
|
|
21177
|
-
|
|
21178
|
-
const [
|
|
21179
|
-
|
|
21180
|
-
|
|
21181
|
-
|
|
21182
|
-
|
|
21183
|
-
|
|
21184
|
-
const
|
|
21185
|
-
|
|
21186
|
-
|
|
21187
|
-
|
|
21188
|
-
|
|
21189
|
-
const
|
|
21190
|
-
|
|
21191
|
-
|
|
21192
|
-
|
|
21193
|
-
|
|
21194
|
-
|
|
21195
|
-
|
|
21196
|
-
const
|
|
21197
|
-
|
|
21198
|
-
|
|
21199
|
-
|
|
21200
|
-
|
|
21201
|
-
|
|
21202
|
-
|
|
21203
|
-
|
|
21204
|
-
|
|
21205
|
-
|
|
21206
|
-
|
|
21207
|
-
|
|
21208
|
-
|
|
21209
|
-
|
|
21210
|
-
}
|
|
21211
|
-
|
|
21212
|
-
|
|
21213
|
-
|
|
21214
|
-
|
|
21215
|
-
|
|
21216
|
-
|
|
21217
|
-
|
|
21218
|
-
|
|
21219
|
-
|
|
21220
|
-
|
|
21372
|
+
const options = useRef2(rest);
|
|
21373
|
+
options.current = rest;
|
|
21374
|
+
const [screen, setScreen] = useState5({ name: "choose" });
|
|
21375
|
+
const [cursor, setCursor] = useState5(0);
|
|
21376
|
+
const [input, setInput] = useState5("");
|
|
21377
|
+
const [error, setError] = useState5();
|
|
21378
|
+
const secret = useRef2("");
|
|
21379
|
+
const providers = order(rest.providers, rest.wanted);
|
|
21380
|
+
const finish = useCallback((result) => {
|
|
21381
|
+
onDone(result);
|
|
21382
|
+
if (!embedded)
|
|
21383
|
+
exit();
|
|
21384
|
+
}, [embedded, exit, onDone]);
|
|
21385
|
+
const complete = useCallback((provider, model2, scope2 = defaultScope, effort) => finish({
|
|
21386
|
+
outcome: "ready",
|
|
21387
|
+
providerId: provider.id,
|
|
21388
|
+
model: `${provider.id}/${model2.id}`,
|
|
21389
|
+
scope: scope2,
|
|
21390
|
+
...effort ? { reasoningEffort: effort } : {}
|
|
21391
|
+
}), [defaultScope, finish]);
|
|
21392
|
+
const readyForEffort = useCallback((provider, model2) => {
|
|
21393
|
+
const remembered = options.current.reasoningFor?.(`${provider.id}/${model2.id}`);
|
|
21394
|
+
setCursor(remembered ? Math.max(0, EFFORTS.indexOf(remembered)) : 0);
|
|
21395
|
+
if (model2.reasoning)
|
|
21396
|
+
setScreen({ name: "effort", provider, model: model2 });
|
|
21397
|
+
else
|
|
21398
|
+
complete(provider, model2);
|
|
21399
|
+
}, [complete]);
|
|
21400
|
+
const verify2 = useCallback(async (provider, model2) => {
|
|
21401
|
+
setScreen({ name: "probing", provider, model: model2 });
|
|
21402
|
+
const result = await options.current.probe(provider.id, model2.id);
|
|
21403
|
+
if (result.ok) {
|
|
21404
|
+
readyForEffort(provider, model2);
|
|
21405
|
+
return;
|
|
21406
|
+
}
|
|
21407
|
+
if (result.reason === "rejected")
|
|
21408
|
+
await options.current.forgetKey(provider.id).catch(() => {});
|
|
21409
|
+
setScreen({ name: "failed", provider, model: model2, result });
|
|
21410
|
+
}, [readyForEffort]);
|
|
21411
|
+
const submitKey = useCallback(async () => {
|
|
21412
|
+
const selected = screen.name === "key" ? screen : undefined;
|
|
21413
|
+
const key2 = secret.current;
|
|
21414
|
+
secret.current = "";
|
|
21415
|
+
setInput("");
|
|
21416
|
+
if (!selected)
|
|
21417
|
+
return;
|
|
21418
|
+
if (key2.trim() === "") {
|
|
21419
|
+
setError("a key is needed, or press esc to go back");
|
|
21420
|
+
return;
|
|
21421
|
+
}
|
|
21422
|
+
setError(undefined);
|
|
21423
|
+
await options.current.storeKey(selected.provider.id, key2.trim());
|
|
21424
|
+
await verify2(selected.provider, selected.model);
|
|
21425
|
+
}, [screen, verify2]);
|
|
21426
|
+
const startSignIn = useCallback(async (provider, model2) => {
|
|
21427
|
+
setScreen({ name: "oauth", provider, model: model2 });
|
|
21221
21428
|
try {
|
|
21222
|
-
|
|
21223
|
-
|
|
21224
|
-
|
|
21225
|
-
|
|
21226
|
-
|
|
21227
|
-
|
|
21228
|
-
|
|
21229
|
-
if (event.text === undefined) {
|
|
21230
|
-
push({
|
|
21231
|
-
kind: "notice",
|
|
21232
|
-
id: nextId(),
|
|
21233
|
-
text: `about to run ${event.calls} tool call${event.calls === 1 ? "" : "s"} without saying why`,
|
|
21234
|
-
color: theme.warning
|
|
21235
|
-
});
|
|
21236
|
-
}
|
|
21237
|
-
break;
|
|
21238
|
-
case "tool_start":
|
|
21239
|
-
if (assistantText.trim() !== "") {
|
|
21240
|
-
push({ kind: "assistant", id: nextId(), text: assistantText.trimEnd() });
|
|
21241
|
-
assistantText = "";
|
|
21242
|
-
setLive("");
|
|
21243
|
-
}
|
|
21244
|
-
setRunningTool(event.call.toolName);
|
|
21245
|
-
break;
|
|
21246
|
-
case "tool_end": {
|
|
21247
|
-
setRunningTool(undefined);
|
|
21248
|
-
const output = event.result.output.type === "text" ? event.result.output.value : "";
|
|
21249
|
-
push({
|
|
21250
|
-
kind: "tool",
|
|
21251
|
-
id: nextId(),
|
|
21252
|
-
name: event.toolName,
|
|
21253
|
-
...event.result.title ? { title: event.result.title } : {},
|
|
21254
|
-
output,
|
|
21255
|
-
...event.result.isError ? { isError: true } : {}
|
|
21256
|
-
});
|
|
21257
|
-
setTodos(agent3.todos.list());
|
|
21258
|
-
break;
|
|
21259
|
-
}
|
|
21260
|
-
case "usage":
|
|
21261
|
-
setCost(agent3.costUsd);
|
|
21262
|
-
setContext(agent3.contextUse);
|
|
21263
|
-
break;
|
|
21264
|
-
case "budget":
|
|
21265
|
-
push({
|
|
21266
|
-
kind: "notice",
|
|
21267
|
-
id: nextId(),
|
|
21268
|
-
text: event.raisedTo === undefined ? `stopped: $${event.spentUsd.toFixed(2)} spent against a ` + `$${event.limitUsd.toFixed(2)} budget` : `budget raised to $${event.raisedTo.toFixed(2)} after ` + `$${event.spentUsd.toFixed(2)} spent`,
|
|
21269
|
-
color: theme.warning
|
|
21270
|
-
});
|
|
21271
|
-
break;
|
|
21272
|
-
case "verification":
|
|
21273
|
-
push({
|
|
21274
|
-
kind: "tool",
|
|
21275
|
-
id: nextId(),
|
|
21276
|
-
name: event.result.command,
|
|
21277
|
-
title: `${event.result.command} - exit ${event.result.exitCode ?? "killed"}`,
|
|
21278
|
-
output: event.result.output,
|
|
21279
|
-
...event.result.exitCode === 0 ? {} : { isError: true }
|
|
21280
|
-
});
|
|
21281
|
-
break;
|
|
21282
|
-
case "subagent":
|
|
21283
|
-
push({
|
|
21284
|
-
kind: "notice",
|
|
21285
|
-
id: nextId(),
|
|
21286
|
-
text: `subagent "${event.description}": ${event.steps} step${event.steps === 1 ? "" : "s"}, $${event.costUsd.toFixed(4)}`
|
|
21287
|
-
});
|
|
21288
|
-
break;
|
|
21289
|
-
case "hook":
|
|
21290
|
-
if (event.blocked) {
|
|
21291
|
-
push({
|
|
21292
|
-
kind: "notice",
|
|
21293
|
-
id: nextId(),
|
|
21294
|
-
text: `${event.event} hook blocked this: ${event.blocked}`,
|
|
21295
|
-
color: theme.warning
|
|
21296
|
-
});
|
|
21297
|
-
}
|
|
21298
|
-
for (const problem of event.problems) {
|
|
21299
|
-
push({ kind: "notice", id: nextId(), text: problem, color: theme.warning });
|
|
21300
|
-
}
|
|
21301
|
-
break;
|
|
21302
|
-
case "compacted":
|
|
21303
|
-
setCompacted((count) => count + event.replaced);
|
|
21304
|
-
push({
|
|
21305
|
-
kind: "notice",
|
|
21306
|
-
id: nextId(),
|
|
21307
|
-
text: `compacted: ${event.replaced} earlier messages are now a summary`
|
|
21308
|
-
});
|
|
21309
|
-
break;
|
|
21310
|
-
case "error":
|
|
21311
|
-
push({
|
|
21312
|
-
kind: "notice",
|
|
21313
|
-
id: nextId(),
|
|
21314
|
-
text: `error: ${event.error.message}`,
|
|
21315
|
-
color: theme.danger
|
|
21316
|
-
});
|
|
21317
|
-
break;
|
|
21318
|
-
case "turn_end":
|
|
21319
|
-
if (event.reason === "aborted") {
|
|
21320
|
-
push({
|
|
21321
|
-
kind: "notice",
|
|
21322
|
-
id: nextId(),
|
|
21323
|
-
text: "interrupted",
|
|
21324
|
-
color: theme.warning
|
|
21325
|
-
});
|
|
21326
|
-
}
|
|
21327
|
-
if (event.reason === "max_steps") {
|
|
21328
|
-
push({
|
|
21329
|
-
kind: "notice",
|
|
21330
|
-
id: nextId(),
|
|
21331
|
-
text: "stopped: step limit reached",
|
|
21332
|
-
color: theme.warning
|
|
21333
|
-
});
|
|
21334
|
-
}
|
|
21335
|
-
break;
|
|
21336
|
-
default:
|
|
21337
|
-
break;
|
|
21338
|
-
}
|
|
21339
|
-
setQueued(agent3.pendingSteers);
|
|
21340
|
-
}
|
|
21341
|
-
} finally {
|
|
21342
|
-
if (assistantText.trim() !== "") {
|
|
21343
|
-
lastAssistantText.current = assistantText;
|
|
21344
|
-
push({ kind: "assistant", id: nextId(), text: assistantText.trimEnd() });
|
|
21345
|
-
}
|
|
21346
|
-
setLive("");
|
|
21347
|
-
setRunningTool(undefined);
|
|
21348
|
-
setBusy(false);
|
|
21349
|
-
setQueued(agent3.pendingSteers);
|
|
21350
|
-
controller.current = undefined;
|
|
21351
|
-
}
|
|
21352
|
-
}, [agent3, push]);
|
|
21353
|
-
const started = useRef2(false);
|
|
21354
|
-
useEffect2(() => {
|
|
21355
|
-
if (started.current || !initialPrompt)
|
|
21356
|
-
return;
|
|
21357
|
-
started.current = true;
|
|
21358
|
-
runTurn(initialPrompt);
|
|
21359
|
-
}, [initialPrompt, runTurn]);
|
|
21360
|
-
const showMemories = useCallback(async (argument) => {
|
|
21361
|
-
const [verb, ...rest] = (argument ?? "").split(/\s+/);
|
|
21362
|
-
const id = rest.join(" ").trim();
|
|
21363
|
-
if (verb === "forget" && id) {
|
|
21364
|
-
const gone = await deleteMemory(id, agent3.cwd);
|
|
21365
|
-
if (gone)
|
|
21366
|
-
await refreshSystemPrompt(agent3, model2, session2.skills);
|
|
21367
|
-
push({
|
|
21368
|
-
kind: "notice",
|
|
21369
|
-
id: nextId(),
|
|
21370
|
-
text: gone ? `forgot ${id}` : `no memory called "${id}"`,
|
|
21371
|
-
...gone ? {} : { color: theme.warning }
|
|
21429
|
+
await options.current.signIn(provider.id, (url) => setScreen({ name: "oauth", provider, model: model2, url }));
|
|
21430
|
+
} catch (failure) {
|
|
21431
|
+
setScreen({
|
|
21432
|
+
name: "failed",
|
|
21433
|
+
provider,
|
|
21434
|
+
model: model2,
|
|
21435
|
+
result: { ok: false, reason: "other", message: failure.message }
|
|
21372
21436
|
});
|
|
21373
21437
|
return;
|
|
21374
21438
|
}
|
|
21375
|
-
|
|
21376
|
-
|
|
21377
|
-
|
|
21378
|
-
|
|
21379
|
-
|
|
21380
|
-
|
|
21381
|
-
|
|
21382
|
-
|
|
21383
|
-
|
|
21384
|
-
|
|
21385
|
-
|
|
21386
|
-
|
|
21387
|
-
|
|
21388
|
-
|
|
21389
|
-
|
|
21390
|
-
|
|
21391
|
-
|
|
21392
|
-
|
|
21393
|
-
|
|
21394
|
-
|
|
21395
|
-
|
|
21396
|
-
if (!candidate)
|
|
21397
|
-
return;
|
|
21398
|
-
setCandidate(undefined);
|
|
21399
|
-
const saved = await saveMemory({ ...candidate, scope: scope2 }, agent3.cwd).catch(() => {
|
|
21400
|
-
return;
|
|
21401
|
-
});
|
|
21402
|
-
if (!saved) {
|
|
21403
|
-
push({ kind: "notice", id: nextId(), text: "could not save that", color: theme.warning });
|
|
21439
|
+
await verify2(provider, model2);
|
|
21440
|
+
}, [verify2]);
|
|
21441
|
+
const chooseModel = useCallback((provider, model2) => {
|
|
21442
|
+
setInput("");
|
|
21443
|
+
setError(undefined);
|
|
21444
|
+
if (provider.configured)
|
|
21445
|
+
readyForEffort(provider, model2);
|
|
21446
|
+
else if (provider.kind === "oauth")
|
|
21447
|
+
startSignIn(provider, model2);
|
|
21448
|
+
else
|
|
21449
|
+
setScreen({ name: "key", provider, model: model2 });
|
|
21450
|
+
}, [readyForEffort, startSignIn]);
|
|
21451
|
+
const chooseProvider = useCallback((provider) => {
|
|
21452
|
+
setInput("");
|
|
21453
|
+
setError(undefined);
|
|
21454
|
+
setCursor(preferredModelIndex(provider.models, rest.wantedModel));
|
|
21455
|
+
setScreen({ name: "model", provider });
|
|
21456
|
+
}, [rest.wantedModel]);
|
|
21457
|
+
useInput5((key2, meta) => {
|
|
21458
|
+
if (meta.ctrl && key2 === "c") {
|
|
21459
|
+
finish({ outcome: "quit" });
|
|
21404
21460
|
return;
|
|
21405
21461
|
}
|
|
21406
|
-
|
|
21407
|
-
|
|
21408
|
-
|
|
21409
|
-
id: nextId(),
|
|
21410
|
-
text: `remembered [${saved.id}] (${scope2}) - /memory to review or forget it`
|
|
21411
|
-
});
|
|
21412
|
-
}, [agent3, candidate, model2, push, session2.skills]);
|
|
21413
|
-
const sessionTree = useCallback(async (name, argument) => {
|
|
21414
|
-
const entries2 = await session2.branch();
|
|
21415
|
-
const prompts = entries2.filter((entry) => entry.type === "message" && entry.message.role === "user" && entry.message.content.some((part) => part.type === "text" && !part.text.startsWith("<self-check>")));
|
|
21416
|
-
if (name === "tree" || !argument) {
|
|
21417
|
-
if (prompts.length === 0) {
|
|
21418
|
-
push({ kind: "notice", id: nextId(), text: "nothing in this session yet" });
|
|
21462
|
+
if (screen.name === "choose") {
|
|
21463
|
+
if (key2 === "q") {
|
|
21464
|
+
finish({ outcome: "quit" });
|
|
21419
21465
|
return;
|
|
21420
21466
|
}
|
|
21421
|
-
|
|
21422
|
-
|
|
21423
|
-
|
|
21424
|
-
|
|
21425
|
-
|
|
21426
|
-
|
|
21427
|
-
|
|
21428
|
-
|
|
21429
|
-
|
|
21430
|
-
`)}
|
|
21431
|
-
|
|
21432
|
-
/rewind <n> goes back to one · /fork <n> branches from it`
|
|
21433
|
-
});
|
|
21467
|
+
if (meta.upArrow)
|
|
21468
|
+
setCursor((c) => c <= 0 ? providers.length - 1 : c - 1);
|
|
21469
|
+
if (meta.downArrow)
|
|
21470
|
+
setCursor((c) => c >= providers.length - 1 ? 0 : c + 1);
|
|
21471
|
+
if (meta.return) {
|
|
21472
|
+
const provider = providers[cursor];
|
|
21473
|
+
if (provider)
|
|
21474
|
+
chooseProvider(provider);
|
|
21475
|
+
}
|
|
21434
21476
|
return;
|
|
21435
21477
|
}
|
|
21436
|
-
|
|
21437
|
-
|
|
21438
|
-
|
|
21439
|
-
|
|
21440
|
-
|
|
21441
|
-
|
|
21442
|
-
|
|
21443
|
-
|
|
21444
|
-
|
|
21478
|
+
if (screen.name === "model") {
|
|
21479
|
+
if (meta.escape) {
|
|
21480
|
+
setInput("");
|
|
21481
|
+
setError(undefined);
|
|
21482
|
+
setCursor(0);
|
|
21483
|
+
setScreen({ name: "choose" });
|
|
21484
|
+
return;
|
|
21485
|
+
}
|
|
21486
|
+
const matches3 = matchingModels(screen.provider.models, input);
|
|
21487
|
+
if (embedded && meta.ctrl && key2 === "g") {
|
|
21488
|
+
const selected = matches3[cursor];
|
|
21489
|
+
if (selected) {
|
|
21490
|
+
if (selected.reasoning) {
|
|
21491
|
+
setCursor(0);
|
|
21492
|
+
setScreen({ name: "effort", provider: screen.provider, model: selected });
|
|
21493
|
+
} else
|
|
21494
|
+
complete(screen.provider, selected, "global");
|
|
21495
|
+
}
|
|
21496
|
+
return;
|
|
21497
|
+
}
|
|
21498
|
+
if (meta.upArrow)
|
|
21499
|
+
setCursor((c) => c <= 0 ? Math.max(0, matches3.length - 1) : c - 1);
|
|
21500
|
+
if (meta.downArrow)
|
|
21501
|
+
setCursor((c) => c >= matches3.length - 1 ? 0 : c + 1);
|
|
21445
21502
|
return;
|
|
21446
21503
|
}
|
|
21447
|
-
|
|
21448
|
-
|
|
21449
|
-
|
|
21450
|
-
|
|
21451
|
-
|
|
21452
|
-
|
|
21453
|
-
|
|
21454
|
-
|
|
21504
|
+
if (screen.name === "effort") {
|
|
21505
|
+
if (meta.escape) {
|
|
21506
|
+
setCursor(preferredModelIndex(screen.provider.models, rest.wantedModel));
|
|
21507
|
+
setScreen({ name: "model", provider: screen.provider });
|
|
21508
|
+
return;
|
|
21509
|
+
}
|
|
21510
|
+
if (meta.upArrow)
|
|
21511
|
+
setCursor((c) => c <= 0 ? EFFORTS.length - 1 : c - 1);
|
|
21512
|
+
if (meta.downArrow)
|
|
21513
|
+
setCursor((c) => c >= EFFORTS.length - 1 ? 0 : c + 1);
|
|
21514
|
+
const selected = EFFORTS[cursor] ?? "auto";
|
|
21515
|
+
if (meta.return || embedded && key2 === "g") {
|
|
21516
|
+
complete(screen.provider, screen.model, embedded && key2 === "g" ? "global" : defaultScope, selected === "auto" ? undefined : selected);
|
|
21517
|
+
}
|
|
21455
21518
|
return;
|
|
21456
21519
|
}
|
|
21457
|
-
|
|
21458
|
-
|
|
21459
|
-
|
|
21460
|
-
|
|
21461
|
-
|
|
21462
|
-
|
|
21463
|
-
|
|
21464
|
-
|
|
21465
|
-
|
|
21466
|
-
|
|
21467
|
-
|
|
21468
|
-
|
|
21520
|
+
if (screen.name === "key" && !meta.escape) {
|
|
21521
|
+
if (meta.return) {
|
|
21522
|
+
submitKey();
|
|
21523
|
+
return;
|
|
21524
|
+
}
|
|
21525
|
+
if (meta.backspace || meta.delete) {
|
|
21526
|
+
secret.current = secret.current.slice(0, -1);
|
|
21527
|
+
setInput(secret.current);
|
|
21528
|
+
return;
|
|
21529
|
+
}
|
|
21530
|
+
if (meta.ctrl || meta.meta || meta.tab)
|
|
21531
|
+
return;
|
|
21532
|
+
if (key2) {
|
|
21533
|
+
secret.current += key2;
|
|
21534
|
+
setInput(secret.current);
|
|
21535
|
+
}
|
|
21469
21536
|
return;
|
|
21470
21537
|
}
|
|
21471
|
-
|
|
21472
|
-
|
|
21473
|
-
|
|
21474
|
-
|
|
21475
|
-
|
|
21476
|
-
});
|
|
21477
|
-
}, [push, session2]);
|
|
21478
|
-
const plan2 = useCallback(async (argument) => {
|
|
21479
|
-
const path = planPath(session2.store?.id ?? "scratch");
|
|
21480
|
-
const [verb = "", ...rest] = (argument ?? "").split(/\s+/);
|
|
21481
|
-
const task2 = [verb, ...rest].join(" ").trim();
|
|
21482
|
-
if (verb === "show") {
|
|
21483
|
-
const text2 = await readPlan(path);
|
|
21484
|
-
push({
|
|
21485
|
-
kind: "notice",
|
|
21486
|
-
id: nextId(),
|
|
21487
|
-
text: text2 ? `${path}
|
|
21488
|
-
|
|
21489
|
-
${text2}` : `no plan yet at ${path}`
|
|
21490
|
-
});
|
|
21538
|
+
if (meta.escape) {
|
|
21539
|
+
secret.current = "";
|
|
21540
|
+
setInput("");
|
|
21541
|
+
setError(undefined);
|
|
21542
|
+
setScreen(screen.name === "key" || screen.name === "oauth" || screen.name === "failed" ? { name: "model", provider: screen.provider } : { name: "choose" });
|
|
21491
21543
|
return;
|
|
21492
21544
|
}
|
|
21493
|
-
if (
|
|
21494
|
-
|
|
21495
|
-
push({
|
|
21496
|
-
kind: "notice",
|
|
21497
|
-
id: nextId(),
|
|
21498
|
-
text: result.message,
|
|
21499
|
-
...result.edited ? {} : { color: theme.warning }
|
|
21500
|
-
});
|
|
21501
|
-
return;
|
|
21545
|
+
if (screen.name === "failed" && key2 === "k" && screen.result.reason === "unreachable") {
|
|
21546
|
+
readyForEffort(screen.provider, screen.model);
|
|
21502
21547
|
}
|
|
21503
|
-
|
|
21504
|
-
|
|
21505
|
-
|
|
21506
|
-
|
|
21507
|
-
|
|
21508
|
-
|
|
21509
|
-
|
|
21510
|
-
|
|
21511
|
-
|
|
21512
|
-
|
|
21513
|
-
|
|
21514
|
-
|
|
21515
|
-
|
|
21516
|
-
|
|
21517
|
-
|
|
21518
|
-
|
|
21519
|
-
|
|
21520
|
-
|
|
21521
|
-
|
|
21522
|
-
|
|
21523
|
-
|
|
21524
|
-
|
|
21525
|
-
}
|
|
21526
|
-
if (verb === "clear") {
|
|
21527
|
-
agent3.setPlan(undefined);
|
|
21528
|
-
push({ kind: "notice", id: nextId(), text: "plan unpinned" });
|
|
21529
|
-
return;
|
|
21530
|
-
}
|
|
21531
|
-
if (task2 === "") {
|
|
21532
|
-
push({
|
|
21533
|
-
kind: "notice",
|
|
21534
|
-
id: nextId(),
|
|
21535
|
-
text: "usage: /plan <what you want planned>, then /plan edit, /plan approve",
|
|
21536
|
-
color: theme.warning
|
|
21537
|
-
});
|
|
21538
|
-
return;
|
|
21539
|
-
}
|
|
21540
|
-
modeBeforePlan.current = agent3.permissionMode;
|
|
21541
|
-
agent3.setPermissionMode("plan");
|
|
21542
|
-
setMode("plan");
|
|
21543
|
-
await runTurn(`${task2}
|
|
21544
|
-
|
|
21545
|
-
${PLAN_PROMPT}`);
|
|
21546
|
-
const drafted = lastAssistantText.current.trim();
|
|
21547
|
-
if (drafted === "") {
|
|
21548
|
-
push({
|
|
21549
|
-
kind: "notice",
|
|
21550
|
-
id: nextId(),
|
|
21551
|
-
text: "the model produced no plan to write",
|
|
21552
|
-
color: theme.warning
|
|
21553
|
-
});
|
|
21554
|
-
return;
|
|
21555
|
-
}
|
|
21556
|
-
await savePlan(path, drafted);
|
|
21557
|
-
push({
|
|
21558
|
-
kind: "notice",
|
|
21559
|
-
id: nextId(),
|
|
21560
|
-
text: `plan written to ${path}
|
|
21561
|
-
/plan edit to change it, /plan approve to pin it`
|
|
21562
|
-
});
|
|
21563
|
-
}, [agent3, push, runTurn, session2.store]);
|
|
21564
|
-
const switchModel = useCallback(async (ref) => {
|
|
21565
|
-
if (!ref) {
|
|
21566
|
-
const current = agent3.model;
|
|
21567
|
-
const price = current.model.cost;
|
|
21568
|
-
push({
|
|
21569
|
-
kind: "notice",
|
|
21570
|
-
id: nextId(),
|
|
21571
|
-
text: [
|
|
21572
|
-
` ${current.provider.id}/${current.model.id}`,
|
|
21573
|
-
` context ${(current.model.contextWindow ?? 0).toLocaleString()} tokens`,
|
|
21574
|
-
` price $${price?.input ?? "?"} in / $${price?.output ?? "?"} out per million`,
|
|
21575
|
-
"",
|
|
21576
|
-
" /model <provider/model> switches; `earshot models` lists them"
|
|
21577
|
-
].join(`
|
|
21578
|
-
`)
|
|
21579
|
-
});
|
|
21580
|
-
return;
|
|
21581
|
-
}
|
|
21582
|
-
try {
|
|
21583
|
-
const resolved = await agent3.changeModel(ref);
|
|
21584
|
-
const next = `${resolved.provider.id}/${resolved.model.id}`;
|
|
21585
|
-
setModel(next);
|
|
21586
|
-
await refreshSystemPrompt(agent3, next, session2.skills);
|
|
21587
|
-
push({ kind: "notice", id: nextId(), text: `model: ${next}` });
|
|
21588
|
-
} catch (error) {
|
|
21589
|
-
push({
|
|
21590
|
-
kind: "notice",
|
|
21591
|
-
id: nextId(),
|
|
21592
|
-
text: `${error.message}`,
|
|
21593
|
-
color: theme.warning
|
|
21594
|
-
});
|
|
21595
|
-
}
|
|
21596
|
-
}, [agent3, push, session2.skills]);
|
|
21597
|
-
const compactNow = useCallback(async () => {
|
|
21598
|
-
const abort = new AbortController;
|
|
21599
|
-
controller.current = abort;
|
|
21600
|
-
setBusy(true);
|
|
21601
|
-
try {
|
|
21602
|
-
let compactedAnything = false;
|
|
21603
|
-
for await (const event of agent3.compactNow(abort.signal)) {
|
|
21604
|
-
if (event.type === "compacted") {
|
|
21605
|
-
compactedAnything = true;
|
|
21606
|
-
setCompacted((count) => count + event.replaced);
|
|
21607
|
-
push({
|
|
21608
|
-
kind: "notice",
|
|
21609
|
-
id: nextId(),
|
|
21610
|
-
text: `compacted: ${event.replaced} earlier messages are now a summary`
|
|
21611
|
-
});
|
|
21612
|
-
}
|
|
21613
|
-
}
|
|
21614
|
-
if (!compactedAnything) {
|
|
21615
|
-
push({ kind: "notice", id: nextId(), text: "nothing to compact yet" });
|
|
21616
|
-
}
|
|
21617
|
-
} catch (error) {
|
|
21618
|
-
push({
|
|
21619
|
-
kind: "notice",
|
|
21620
|
-
id: nextId(),
|
|
21621
|
-
text: `could not compact: ${error.message}`,
|
|
21622
|
-
color: theme.warning
|
|
21623
|
-
});
|
|
21624
|
-
} finally {
|
|
21625
|
-
setBusy(false);
|
|
21626
|
-
setContext(agent3.contextUse);
|
|
21627
|
-
controller.current = undefined;
|
|
21628
|
-
}
|
|
21629
|
-
}, [agent3, push]);
|
|
21630
|
-
const handlers = {
|
|
21631
|
-
exit: () => exit(),
|
|
21632
|
-
help: () => push({ kind: "notice", id: nextId(), text: describeCommands(session2) }),
|
|
21633
|
-
model: (argument) => void switchModel(argument),
|
|
21634
|
-
compact: () => void compactNow(),
|
|
21635
|
-
context: () => {
|
|
21636
|
-
const { tokens, window } = agent3.contextUse;
|
|
21637
|
-
const percent = window > 0 ? Math.round(tokens / window * 100) : 0;
|
|
21638
|
-
const files = agent3.touchedFiles;
|
|
21639
|
-
push({
|
|
21640
|
-
kind: "notice",
|
|
21641
|
-
id: nextId(),
|
|
21642
|
-
text: [
|
|
21643
|
-
` model ${model2}`,
|
|
21644
|
-
` context ~${tokens.toLocaleString()} of ${window.toLocaleString()} tokens (${percent}%)`,
|
|
21645
|
-
` dropped ${compacted} earlier message${compacted === 1 ? "" : "s"} replaced by a summary`,
|
|
21646
|
-
` files ${files.length === 0 ? "none touched yet" : files.join(", ")}`,
|
|
21647
|
-
"",
|
|
21648
|
-
" /compact summarises now rather than waiting for 80%"
|
|
21649
|
-
].join(`
|
|
21650
|
-
`)
|
|
21651
|
-
});
|
|
21652
|
-
},
|
|
21653
|
-
cost: (argument) => {
|
|
21654
|
-
if (argument !== undefined && argument !== "") {
|
|
21655
|
-
const amount = Number.parseFloat(argument.replace(/^\$/, ""));
|
|
21656
|
-
if (Number.isNaN(amount)) {
|
|
21657
|
-
push({
|
|
21658
|
-
kind: "notice",
|
|
21659
|
-
id: nextId(),
|
|
21660
|
-
text: `usage: /cost [usd] - "${argument}" is not an amount`,
|
|
21661
|
-
color: theme.warning
|
|
21662
|
-
});
|
|
21663
|
-
return;
|
|
21664
|
-
}
|
|
21665
|
-
agent3.setBudget(amount > 0 ? amount : undefined);
|
|
21666
|
-
push({
|
|
21667
|
-
kind: "notice",
|
|
21668
|
-
id: nextId(),
|
|
21669
|
-
text: amount > 0 ? `budget: $${amount.toFixed(2)}` : "budget removed"
|
|
21670
|
-
});
|
|
21671
|
-
return;
|
|
21672
|
-
}
|
|
21673
|
-
const budget = agent3.budgetUsd;
|
|
21674
|
-
push({
|
|
21675
|
-
kind: "notice",
|
|
21676
|
-
id: nextId(),
|
|
21677
|
-
text: ` spent $${agent3.costUsd.toFixed(4)}
|
|
21678
|
-
` + ` budget ${budget === undefined ? "none - /cost <usd> sets one" : `$${budget.toFixed(2)}`}`
|
|
21679
|
-
});
|
|
21680
|
-
},
|
|
21681
|
-
todo: () => {
|
|
21682
|
-
const todos2 = agent3.todos.list();
|
|
21683
|
-
push({
|
|
21684
|
-
kind: "notice",
|
|
21685
|
-
id: nextId(),
|
|
21686
|
-
text: todos2.length === 0 ? "no todos in this session" : todos2.map((todo2) => ` ${todo2.status === "done" ? "x" : todo2.status === "in_progress" ? ">" : " "} ${todo2.text}`).join(`
|
|
21687
|
-
`)
|
|
21688
|
-
});
|
|
21689
|
-
},
|
|
21690
|
-
permissions: () => {
|
|
21691
|
-
const rules2 = agent3.permissionRules;
|
|
21692
|
-
push({
|
|
21693
|
-
kind: "notice",
|
|
21694
|
-
id: nextId(),
|
|
21695
|
-
text: [
|
|
21696
|
-
` mode ${agent3.permissionMode} (/mode changes it)`,
|
|
21697
|
-
...rules2.length === 0 ? [" rules none configured"] : [
|
|
21698
|
-
" rules (deny always wins, whatever the mode or scope)",
|
|
21699
|
-
...rules2.map((rule) => ` ${rule.effect.padEnd(5)} ${rule.source} [${rule.scope}]`)
|
|
21548
|
+
});
|
|
21549
|
+
if (screen.name === "choose") {
|
|
21550
|
+
return /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21551
|
+
flexDirection: "column",
|
|
21552
|
+
children: [
|
|
21553
|
+
/* @__PURE__ */ jsxDEV12(Header, {
|
|
21554
|
+
embedded
|
|
21555
|
+
}, undefined, false, undefined, this),
|
|
21556
|
+
providers.map((provider, index) => /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21557
|
+
children: [
|
|
21558
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21559
|
+
color: index === cursor ? theme.user : theme.muted,
|
|
21560
|
+
children: index === cursor ? "› " : " "
|
|
21561
|
+
}, undefined, false, undefined, this),
|
|
21562
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21563
|
+
...index === cursor ? { color: theme.user } : {},
|
|
21564
|
+
children: provider.id.padEnd(14)
|
|
21565
|
+
}, undefined, false, undefined, this),
|
|
21566
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21567
|
+
color: theme.muted,
|
|
21568
|
+
children: hint(provider)
|
|
21569
|
+
}, undefined, false, undefined, this)
|
|
21700
21570
|
]
|
|
21701
|
-
|
|
21702
|
-
|
|
21703
|
-
|
|
21704
|
-
|
|
21705
|
-
|
|
21706
|
-
|
|
21707
|
-
|
|
21708
|
-
|
|
21709
|
-
|
|
21710
|
-
|
|
21711
|
-
|
|
21712
|
-
|
|
21713
|
-
|
|
21714
|
-
|
|
21715
|
-
|
|
21716
|
-
|
|
21717
|
-
|
|
21718
|
-
|
|
21719
|
-
|
|
21720
|
-
|
|
21721
|
-
|
|
21722
|
-
|
|
21723
|
-
|
|
21724
|
-
|
|
21725
|
-
|
|
21726
|
-
|
|
21571
|
+
}, provider.id, true, undefined, this)),
|
|
21572
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21573
|
+
marginTop: 1,
|
|
21574
|
+
children: /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21575
|
+
color: theme.muted,
|
|
21576
|
+
children: "↑↓ choose · enter select · q quit"
|
|
21577
|
+
}, undefined, false, undefined, this)
|
|
21578
|
+
}, undefined, false, undefined, this),
|
|
21579
|
+
error ? /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21580
|
+
color: theme.warning,
|
|
21581
|
+
children: error
|
|
21582
|
+
}, undefined, false, undefined, this) : null
|
|
21583
|
+
]
|
|
21584
|
+
}, undefined, true, undefined, this);
|
|
21585
|
+
}
|
|
21586
|
+
if (screen.name === "model") {
|
|
21587
|
+
const matches3 = matchingModels(screen.provider.models, input);
|
|
21588
|
+
const selected = matches3[cursor];
|
|
21589
|
+
const start = Math.max(0, Math.min(cursor - 3, matches3.length - 8));
|
|
21590
|
+
return /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21591
|
+
flexDirection: "column",
|
|
21592
|
+
children: [
|
|
21593
|
+
/* @__PURE__ */ jsxDEV12(Header, {
|
|
21594
|
+
embedded
|
|
21595
|
+
}, undefined, false, undefined, this),
|
|
21596
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21597
|
+
children: [
|
|
21598
|
+
"choose a model from ",
|
|
21599
|
+
screen.provider.id,
|
|
21600
|
+
" (",
|
|
21601
|
+
matches3.length,
|
|
21602
|
+
" matching)"
|
|
21603
|
+
]
|
|
21604
|
+
}, undefined, true, undefined, this),
|
|
21605
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21606
|
+
children: [
|
|
21607
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21608
|
+
color: theme.user,
|
|
21609
|
+
children: "> "
|
|
21610
|
+
}, undefined, false, undefined, this),
|
|
21611
|
+
/* @__PURE__ */ jsxDEV12(TextInput, {
|
|
21612
|
+
value: input,
|
|
21613
|
+
onChange: (value) => {
|
|
21614
|
+
setInput(value);
|
|
21615
|
+
setCursor(0);
|
|
21616
|
+
setError(undefined);
|
|
21617
|
+
},
|
|
21618
|
+
onSubmit: () => {
|
|
21619
|
+
if (selected)
|
|
21620
|
+
chooseModel(screen.provider, selected);
|
|
21621
|
+
else
|
|
21622
|
+
setError("no model matches that search");
|
|
21623
|
+
},
|
|
21624
|
+
placeholder: "type to filter models"
|
|
21625
|
+
}, undefined, false, undefined, this)
|
|
21626
|
+
]
|
|
21627
|
+
}, undefined, true, undefined, this),
|
|
21628
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21629
|
+
flexDirection: "column",
|
|
21630
|
+
marginTop: 1,
|
|
21631
|
+
children: [
|
|
21632
|
+
matches3.slice(start, start + 8).map((model2) => /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21633
|
+
color: model2 === selected ? theme.user : theme.muted,
|
|
21634
|
+
children: [
|
|
21635
|
+
model2 === selected ? "› " : " ",
|
|
21636
|
+
model2.id,
|
|
21637
|
+
" · ",
|
|
21638
|
+
model2.name
|
|
21639
|
+
]
|
|
21640
|
+
}, model2.id, true, undefined, this)),
|
|
21641
|
+
matches3.length === 0 ? /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21642
|
+
color: theme.muted,
|
|
21643
|
+
children: "no matching models"
|
|
21644
|
+
}, undefined, false, undefined, this) : null
|
|
21645
|
+
]
|
|
21646
|
+
}, undefined, true, undefined, this),
|
|
21647
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21648
|
+
marginTop: 1,
|
|
21649
|
+
children: /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21650
|
+
color: theme.muted,
|
|
21651
|
+
children: "type filter · ↑↓ choose · enter select · esc back"
|
|
21652
|
+
}, undefined, false, undefined, this)
|
|
21653
|
+
}, undefined, false, undefined, this),
|
|
21654
|
+
error ? /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21655
|
+
color: theme.warning,
|
|
21656
|
+
children: error
|
|
21657
|
+
}, undefined, false, undefined, this) : null
|
|
21658
|
+
]
|
|
21659
|
+
}, undefined, true, undefined, this);
|
|
21660
|
+
}
|
|
21661
|
+
if (screen.name === "key") {
|
|
21662
|
+
return /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21663
|
+
flexDirection: "column",
|
|
21664
|
+
children: [
|
|
21665
|
+
/* @__PURE__ */ jsxDEV12(Header, {
|
|
21666
|
+
embedded
|
|
21667
|
+
}, undefined, false, undefined, this),
|
|
21668
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21669
|
+
children: [
|
|
21670
|
+
"paste an api key for ",
|
|
21671
|
+
screen.provider.id
|
|
21672
|
+
]
|
|
21673
|
+
}, undefined, true, undefined, this),
|
|
21674
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21675
|
+
marginTop: 1,
|
|
21676
|
+
children: /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21677
|
+
color: theme.muted,
|
|
21678
|
+
children: [
|
|
21679
|
+
screen.provider.envVars?.length ? `or set ${screen.provider.envVars.join(" or ")} instead and restart.
|
|
21680
|
+
` : "",
|
|
21681
|
+
"stored in your config directory, readable only by you, and never printed."
|
|
21682
|
+
]
|
|
21683
|
+
}, undefined, true, undefined, this)
|
|
21684
|
+
}, undefined, false, undefined, this),
|
|
21685
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21686
|
+
marginTop: 1,
|
|
21687
|
+
children: [
|
|
21688
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21689
|
+
color: theme.user,
|
|
21690
|
+
children: "> "
|
|
21691
|
+
}, undefined, false, undefined, this),
|
|
21692
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21693
|
+
children: "•".repeat(input.length)
|
|
21694
|
+
}, undefined, false, undefined, this),
|
|
21695
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21696
|
+
inverse: true,
|
|
21697
|
+
children: " "
|
|
21698
|
+
}, undefined, false, undefined, this)
|
|
21699
|
+
]
|
|
21700
|
+
}, undefined, true, undefined, this),
|
|
21701
|
+
error ? /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21702
|
+
color: theme.warning,
|
|
21703
|
+
children: error
|
|
21704
|
+
}, undefined, false, undefined, this) : null,
|
|
21705
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21706
|
+
marginTop: 1,
|
|
21707
|
+
children: /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21708
|
+
color: theme.muted,
|
|
21709
|
+
children: "enter continue · esc back"
|
|
21710
|
+
}, undefined, false, undefined, this)
|
|
21711
|
+
}, undefined, false, undefined, this)
|
|
21712
|
+
]
|
|
21713
|
+
}, undefined, true, undefined, this);
|
|
21714
|
+
}
|
|
21715
|
+
if (screen.name === "oauth") {
|
|
21716
|
+
return /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21717
|
+
flexDirection: "column",
|
|
21718
|
+
children: [
|
|
21719
|
+
/* @__PURE__ */ jsxDEV12(Header, {
|
|
21720
|
+
embedded
|
|
21721
|
+
}, undefined, false, undefined, this),
|
|
21722
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21723
|
+
children: [
|
|
21724
|
+
"signing in to ",
|
|
21725
|
+
screen.provider.id,
|
|
21726
|
+
" in your browser…"
|
|
21727
|
+
]
|
|
21728
|
+
}, undefined, true, undefined, this),
|
|
21729
|
+
screen.url ? /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21730
|
+
marginTop: 1,
|
|
21731
|
+
flexDirection: "column",
|
|
21732
|
+
children: [
|
|
21733
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21734
|
+
color: theme.muted,
|
|
21735
|
+
children: "if it did not open, use this link:"
|
|
21736
|
+
}, undefined, false, undefined, this),
|
|
21737
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21738
|
+
children: screen.url
|
|
21739
|
+
}, undefined, false, undefined, this)
|
|
21740
|
+
]
|
|
21741
|
+
}, undefined, true, undefined, this) : null,
|
|
21742
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21743
|
+
marginTop: 1,
|
|
21744
|
+
children: /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21745
|
+
color: theme.muted,
|
|
21746
|
+
children: "esc cancel"
|
|
21747
|
+
}, undefined, false, undefined, this)
|
|
21748
|
+
}, undefined, false, undefined, this)
|
|
21749
|
+
]
|
|
21750
|
+
}, undefined, true, undefined, this);
|
|
21751
|
+
}
|
|
21752
|
+
if (screen.name === "probing") {
|
|
21753
|
+
return /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21754
|
+
flexDirection: "column",
|
|
21755
|
+
children: [
|
|
21756
|
+
/* @__PURE__ */ jsxDEV12(Header, {
|
|
21757
|
+
embedded
|
|
21758
|
+
}, undefined, false, undefined, this),
|
|
21759
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21760
|
+
color: theme.muted,
|
|
21761
|
+
children: [
|
|
21762
|
+
"checking the credentials with ",
|
|
21763
|
+
screen.provider.id,
|
|
21764
|
+
"…"
|
|
21765
|
+
]
|
|
21766
|
+
}, undefined, true, undefined, this)
|
|
21767
|
+
]
|
|
21768
|
+
}, undefined, true, undefined, this);
|
|
21769
|
+
}
|
|
21770
|
+
if (screen.name === "failed") {
|
|
21771
|
+
return /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21772
|
+
flexDirection: "column",
|
|
21773
|
+
children: [
|
|
21774
|
+
/* @__PURE__ */ jsxDEV12(Header, {
|
|
21775
|
+
embedded
|
|
21776
|
+
}, undefined, false, undefined, this),
|
|
21777
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21778
|
+
color: theme.warning,
|
|
21779
|
+
children: screen.result.reason === "rejected" ? `${screen.provider.id} rejected that credential. It has not been kept.` : screen.result.reason === "unreachable" ? `could not reach ${screen.provider.id}.` : `${screen.provider.id} said:`
|
|
21780
|
+
}, undefined, false, undefined, this),
|
|
21781
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21782
|
+
color: theme.muted,
|
|
21783
|
+
children: screen.result.message
|
|
21784
|
+
}, undefined, false, undefined, this),
|
|
21785
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21786
|
+
marginTop: 1,
|
|
21787
|
+
children: /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21788
|
+
color: theme.muted,
|
|
21789
|
+
children: screen.result.reason === "unreachable" ? "k keep it anyway and carry on · esc start over · ctrl-c quit" : "esc start over · ctrl-c quit"
|
|
21790
|
+
}, undefined, false, undefined, this)
|
|
21791
|
+
}, undefined, false, undefined, this)
|
|
21792
|
+
]
|
|
21793
|
+
}, undefined, true, undefined, this);
|
|
21794
|
+
}
|
|
21795
|
+
if (screen.name === "effort")
|
|
21796
|
+
return /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21797
|
+
flexDirection: "column",
|
|
21798
|
+
children: [
|
|
21799
|
+
/* @__PURE__ */ jsxDEV12(Header, {
|
|
21800
|
+
embedded
|
|
21801
|
+
}, undefined, false, undefined, this),
|
|
21802
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21803
|
+
children: [
|
|
21804
|
+
"reasoning effort for ",
|
|
21805
|
+
screen.model.name
|
|
21806
|
+
]
|
|
21807
|
+
}, undefined, true, undefined, this),
|
|
21808
|
+
/* @__PURE__ */ jsxDEV12(Box10, {
|
|
21809
|
+
flexDirection: "column",
|
|
21810
|
+
marginTop: 1,
|
|
21811
|
+
children: EFFORTS.map((effort, index) => /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21812
|
+
color: index === cursor ? theme.user : theme.muted,
|
|
21813
|
+
children: [
|
|
21814
|
+
index === cursor ? "› " : " ",
|
|
21815
|
+
effort
|
|
21816
|
+
]
|
|
21817
|
+
}, effort, true, undefined, this))
|
|
21818
|
+
}, undefined, false, undefined, this),
|
|
21819
|
+
/* @__PURE__ */ jsxDEV12(Text12, {
|
|
21820
|
+
color: theme.muted,
|
|
21821
|
+
children: [
|
|
21822
|
+
"↑↓ choose · enter use",
|
|
21823
|
+
embedded ? " here · g use everywhere" : "",
|
|
21824
|
+
" · esc back"
|
|
21825
|
+
]
|
|
21826
|
+
}, undefined, true, undefined, this)
|
|
21827
|
+
]
|
|
21828
|
+
}, undefined, true, undefined, this);
|
|
21829
|
+
return null;
|
|
21830
|
+
}
|
|
21831
|
+
function Header({ embedded }) {
|
|
21832
|
+
return /* @__PURE__ */ jsxDEV12(Box10, {
|
|
21833
|
+
flexDirection: "column",
|
|
21834
|
+
marginBottom: 1,
|
|
21835
|
+
children: /* @__PURE__ */ jsxDEV12(Text12, {
|
|
21836
|
+
children: embedded ? "switch model" : "earshot needs a model provider before it can do anything."
|
|
21837
|
+
}, undefined, false, undefined, this)
|
|
21838
|
+
}, undefined, false, undefined, this);
|
|
21839
|
+
}
|
|
21840
|
+
function hint(provider) {
|
|
21841
|
+
if (provider.configured)
|
|
21842
|
+
return provider.configured;
|
|
21843
|
+
if (provider.kind === "oauth")
|
|
21844
|
+
return "sign in with a browser - no key to paste";
|
|
21845
|
+
return provider.envVars?.length ? provider.envVars.join(" or ") : "api key";
|
|
21846
|
+
}
|
|
21847
|
+
function matchingModels(models, query) {
|
|
21848
|
+
const wanted = query.trim().toLowerCase();
|
|
21849
|
+
if (!wanted)
|
|
21850
|
+
return models;
|
|
21851
|
+
return models.filter((model2) => model2.id.toLowerCase().includes(wanted) || model2.name.toLowerCase().includes(wanted));
|
|
21852
|
+
}
|
|
21853
|
+
function preferredModelIndex(models, wanted) {
|
|
21854
|
+
if (!wanted)
|
|
21855
|
+
return 0;
|
|
21856
|
+
const modelId = wanted.includes("/") ? wanted.slice(wanted.indexOf("/") + 1) : wanted;
|
|
21857
|
+
const index = models.findIndex((model2) => model2.id === wanted || model2.id === modelId);
|
|
21858
|
+
return Math.max(0, index);
|
|
21859
|
+
}
|
|
21860
|
+
function order(providers, wanted) {
|
|
21861
|
+
if (!wanted)
|
|
21862
|
+
return providers;
|
|
21863
|
+
return [
|
|
21864
|
+
...providers.filter((provider) => provider.id === wanted),
|
|
21865
|
+
...providers.filter((provider) => provider.id !== wanted)
|
|
21866
|
+
];
|
|
21867
|
+
}
|
|
21868
|
+
|
|
21869
|
+
// packages/tui/src/sessions.tsx
|
|
21870
|
+
import { Box as Box11, Text as Text13, useApp as useApp2, useInput as useInput6 } from "ink";
|
|
21871
|
+
import { useMemo, useState as useState6 } from "react";
|
|
21872
|
+
import { jsxDEV as jsxDEV13 } from "react/jsx-dev-runtime";
|
|
21873
|
+
function SessionPicker({
|
|
21874
|
+
sessions,
|
|
21875
|
+
onDone,
|
|
21876
|
+
embedded = false
|
|
21877
|
+
}) {
|
|
21878
|
+
const { exit } = useApp2();
|
|
21879
|
+
const [query, setQuery] = useState6("");
|
|
21880
|
+
const [cursor, setCursor] = useState6(0);
|
|
21881
|
+
const matches3 = useMemo(() => {
|
|
21882
|
+
const wanted = query.trim().toLowerCase();
|
|
21883
|
+
return wanted ? sessions.filter((session2) => `${session2.preview} ${session2.model} ${session2.id}`.toLowerCase().includes(wanted)) : sessions;
|
|
21884
|
+
}, [query, sessions]);
|
|
21885
|
+
const finish = (path) => {
|
|
21886
|
+
onDone(path);
|
|
21887
|
+
if (!embedded)
|
|
21888
|
+
exit();
|
|
21727
21889
|
};
|
|
21728
|
-
|
|
21729
|
-
|
|
21730
|
-
|
|
21731
|
-
|
|
21732
|
-
|
|
21733
|
-
|
|
21734
|
-
|
|
21735
|
-
|
|
21736
|
-
|
|
21737
|
-
|
|
21738
|
-
|
|
21739
|
-
|
|
21740
|
-
|
|
21741
|
-
|
|
21742
|
-
|
|
21743
|
-
|
|
21744
|
-
|
|
21745
|
-
|
|
21746
|
-
|
|
21747
|
-
|
|
21748
|
-
|
|
21749
|
-
|
|
21750
|
-
|
|
21751
|
-
|
|
21752
|
-
|
|
21753
|
-
|
|
21754
|
-
|
|
21755
|
-
|
|
21756
|
-
|
|
21757
|
-
|
|
21758
|
-
|
|
21759
|
-
|
|
21760
|
-
|
|
21761
|
-
|
|
21762
|
-
|
|
21890
|
+
useInput6((input, key2) => {
|
|
21891
|
+
if (key2.escape || input === "q" && query === "")
|
|
21892
|
+
return finish();
|
|
21893
|
+
if (key2.upArrow)
|
|
21894
|
+
setCursor((value) => value <= 0 ? Math.max(0, matches3.length - 1) : value - 1);
|
|
21895
|
+
if (key2.downArrow)
|
|
21896
|
+
setCursor((value) => value >= matches3.length - 1 ? 0 : value + 1);
|
|
21897
|
+
});
|
|
21898
|
+
return /* @__PURE__ */ jsxDEV13(Box11, {
|
|
21899
|
+
flexDirection: "column",
|
|
21900
|
+
children: [
|
|
21901
|
+
/* @__PURE__ */ jsxDEV13(Text13, {
|
|
21902
|
+
children: "saved chats for this project"
|
|
21903
|
+
}, undefined, false, undefined, this),
|
|
21904
|
+
/* @__PURE__ */ jsxDEV13(Box11, {
|
|
21905
|
+
marginTop: 1,
|
|
21906
|
+
children: [
|
|
21907
|
+
/* @__PURE__ */ jsxDEV13(Text13, {
|
|
21908
|
+
color: theme.user,
|
|
21909
|
+
children: "> "
|
|
21910
|
+
}, undefined, false, undefined, this),
|
|
21911
|
+
/* @__PURE__ */ jsxDEV13(TextInput, {
|
|
21912
|
+
value: query,
|
|
21913
|
+
onChange: (value) => {
|
|
21914
|
+
setQuery(value);
|
|
21915
|
+
setCursor(0);
|
|
21916
|
+
},
|
|
21917
|
+
onSubmit: () => {
|
|
21918
|
+
const selected = matches3[cursor];
|
|
21919
|
+
if (selected)
|
|
21920
|
+
finish(selected.path);
|
|
21921
|
+
},
|
|
21922
|
+
placeholder: "filter chats"
|
|
21923
|
+
}, undefined, false, undefined, this)
|
|
21924
|
+
]
|
|
21925
|
+
}, undefined, true, undefined, this),
|
|
21926
|
+
/* @__PURE__ */ jsxDEV13(Box11, {
|
|
21927
|
+
flexDirection: "column",
|
|
21928
|
+
marginTop: 1,
|
|
21929
|
+
children: [
|
|
21930
|
+
matches3.slice(Math.max(0, cursor - 4), Math.max(0, cursor - 4) + 9).map((session2) => /* @__PURE__ */ jsxDEV13(Text13, {
|
|
21931
|
+
color: session2 === matches3[cursor] ? theme.user : theme.muted,
|
|
21932
|
+
children: [
|
|
21933
|
+
session2 === matches3[cursor] ? "› " : " ",
|
|
21934
|
+
session2.preview.padEnd(42).slice(0, 42),
|
|
21935
|
+
" ",
|
|
21936
|
+
relativeTime(session2.updatedAt).padStart(8),
|
|
21937
|
+
" ",
|
|
21938
|
+
session2.model,
|
|
21939
|
+
" ",
|
|
21940
|
+
session2.id.slice(0, 8)
|
|
21941
|
+
]
|
|
21942
|
+
}, session2.id, true, undefined, this)),
|
|
21943
|
+
matches3.length === 0 && /* @__PURE__ */ jsxDEV13(Text13, {
|
|
21944
|
+
color: theme.muted,
|
|
21945
|
+
children: "no saved chats match"
|
|
21946
|
+
}, undefined, false, undefined, this)
|
|
21947
|
+
]
|
|
21948
|
+
}, undefined, true, undefined, this),
|
|
21949
|
+
/* @__PURE__ */ jsxDEV13(Box11, {
|
|
21950
|
+
marginTop: 1,
|
|
21951
|
+
children: /* @__PURE__ */ jsxDEV13(Text13, {
|
|
21952
|
+
color: theme.muted,
|
|
21953
|
+
children: "type filter · ↑↓ choose · enter resume · esc quit"
|
|
21954
|
+
}, undefined, false, undefined, this)
|
|
21955
|
+
}, undefined, false, undefined, this)
|
|
21956
|
+
]
|
|
21957
|
+
}, undefined, true, undefined, this);
|
|
21958
|
+
}
|
|
21959
|
+
function relativeTime(updatedAt) {
|
|
21960
|
+
const seconds = Math.max(0, Math.floor((Date.now() - updatedAt) / 1000));
|
|
21961
|
+
if (seconds < 60)
|
|
21962
|
+
return "now";
|
|
21963
|
+
const minutes = Math.floor(seconds / 60);
|
|
21964
|
+
if (minutes < 60)
|
|
21965
|
+
return `${minutes}m ago`;
|
|
21966
|
+
const hours = Math.floor(minutes / 60);
|
|
21967
|
+
if (hours < 24)
|
|
21968
|
+
return `${hours}h ago`;
|
|
21969
|
+
return `${Math.floor(hours / 24)}d ago`;
|
|
21970
|
+
}
|
|
21971
|
+
|
|
21972
|
+
// packages/tui/src/app.tsx
|
|
21973
|
+
import { jsxDEV as jsxDEV14 } from "react/jsx-dev-runtime";
|
|
21974
|
+
var sequence = 0;
|
|
21975
|
+
var nextId = () => `item_${sequence++}`;
|
|
21976
|
+
function promptLabel(prompt) {
|
|
21977
|
+
if (typeof prompt === "string")
|
|
21978
|
+
return prompt;
|
|
21979
|
+
return prompt.map((part) => part.type === "text" ? part.text : `[attached ${part.mediaType} image]`).join(`
|
|
21980
|
+
`);
|
|
21981
|
+
}
|
|
21982
|
+
function App({
|
|
21983
|
+
session: session2,
|
|
21984
|
+
model: initialModel,
|
|
21985
|
+
initialPrompt,
|
|
21986
|
+
modelOptions,
|
|
21987
|
+
onResume
|
|
21988
|
+
}) {
|
|
21989
|
+
const { exit } = useApp3();
|
|
21990
|
+
const agent3 = session2.agent;
|
|
21991
|
+
const [model2, setModel] = useState7(initialModel);
|
|
21992
|
+
const [items, setItems] = useState7(() => session2.problems.map((problem) => ({
|
|
21993
|
+
kind: "notice",
|
|
21994
|
+
id: nextId(),
|
|
21995
|
+
text: `warning: ${problem}`,
|
|
21996
|
+
color: theme.warning
|
|
21997
|
+
})));
|
|
21998
|
+
const [live, setLive] = useState7("");
|
|
21999
|
+
const [reasoningLive, setReasoningLive] = useState7("");
|
|
22000
|
+
const [showThinking, setShowThinking] = useState7(true);
|
|
22001
|
+
const [activity, setActivity] = useState7();
|
|
22002
|
+
const [choosingModel, setChoosingModel] = useState7(false);
|
|
22003
|
+
const [choosingReasoning, setChoosingReasoning] = useState7(false);
|
|
22004
|
+
const [sessionChoices, setSessionChoices] = useState7();
|
|
22005
|
+
const [runningTool, setRunningTool] = useState7();
|
|
22006
|
+
const [input, setInput] = useState7("");
|
|
22007
|
+
const [menuIndex, setMenuIndex] = useState7(0);
|
|
22008
|
+
const [busy, setBusy] = useState7(false);
|
|
22009
|
+
const [mode, setMode] = useState7(agent3.permissionMode);
|
|
22010
|
+
const [cost, setCost] = useState7(0);
|
|
22011
|
+
const [todos, setTodos] = useState7([]);
|
|
22012
|
+
const [queued, setQueued] = useState7(0);
|
|
22013
|
+
const [candidate, setCandidate] = useState7();
|
|
22014
|
+
const [context2, setContext] = useState7(() => agent3.contextUse);
|
|
22015
|
+
const [compacted, setCompacted] = useState7(0);
|
|
22016
|
+
const [pending, setPending] = useState7();
|
|
22017
|
+
const [question, setQuestion] = useState7();
|
|
22018
|
+
const controller = useRef3(undefined);
|
|
22019
|
+
const push = useCallback2((item) => setItems((current) => [...current, item]), []);
|
|
22020
|
+
const pendingRef = useRef3(setPending);
|
|
22021
|
+
pendingRef.current = setPending;
|
|
22022
|
+
const questionRef = useRef3(setQuestion);
|
|
22023
|
+
questionRef.current = setQuestion;
|
|
22024
|
+
useEffect3(() => {
|
|
22025
|
+
session2.installPrompt((request, reason) => new Promise((resolve4) => {
|
|
22026
|
+
pendingRef.current({ request, reason, resolve: resolve4 });
|
|
22027
|
+
}));
|
|
22028
|
+
session2.installAsk((q, options) => new Promise((resolve4) => {
|
|
22029
|
+
questionRef.current({ question: q, ...options ? { options } : {}, resolve: resolve4 });
|
|
22030
|
+
}));
|
|
22031
|
+
}, [session2]);
|
|
22032
|
+
const modeBeforePlan = useRef3(undefined);
|
|
22033
|
+
const lastAssistantText = useRef3("");
|
|
22034
|
+
const runTurn = useCallback2(async (prompt) => {
|
|
22035
|
+
setBusy(true);
|
|
22036
|
+
setActivity("preparing");
|
|
22037
|
+
lastAssistantText.current = "";
|
|
22038
|
+
push({ kind: "user", id: nextId(), text: promptLabel(prompt) });
|
|
22039
|
+
const abort = new AbortController;
|
|
22040
|
+
controller.current = abort;
|
|
22041
|
+
let assistantText = "";
|
|
22042
|
+
let reasoningText = "";
|
|
22043
|
+
let reasoningFlushed = false;
|
|
22044
|
+
try {
|
|
22045
|
+
for await (const event of agent3.runTurn(prompt, abort.signal)) {
|
|
22046
|
+
switch (event.type) {
|
|
22047
|
+
case "model_start":
|
|
22048
|
+
setActivity("thinking");
|
|
22049
|
+
break;
|
|
22050
|
+
case "text_delta":
|
|
22051
|
+
if (!reasoningFlushed && reasoningText.trim() !== "" && showThinking) {
|
|
22052
|
+
push({ kind: "reasoning", id: nextId(), text: reasoningText.trimEnd() });
|
|
22053
|
+
reasoningFlushed = true;
|
|
22054
|
+
setReasoningLive("");
|
|
22055
|
+
}
|
|
22056
|
+
setActivity(undefined);
|
|
22057
|
+
assistantText += event.text;
|
|
22058
|
+
setLive(assistantText);
|
|
22059
|
+
break;
|
|
22060
|
+
case "reasoning_delta":
|
|
22061
|
+
setActivity("reasoning");
|
|
22062
|
+
reasoningText += event.text;
|
|
22063
|
+
if (showThinking)
|
|
22064
|
+
setReasoningLive(reasoningText);
|
|
22065
|
+
break;
|
|
22066
|
+
case "intent":
|
|
22067
|
+
if (event.text === undefined) {
|
|
22068
|
+
push({
|
|
22069
|
+
kind: "notice",
|
|
22070
|
+
id: nextId(),
|
|
22071
|
+
text: `about to run ${event.calls} tool call${event.calls === 1 ? "" : "s"} without saying why`,
|
|
22072
|
+
color: theme.warning
|
|
22073
|
+
});
|
|
22074
|
+
}
|
|
22075
|
+
break;
|
|
22076
|
+
case "tool_start":
|
|
22077
|
+
setActivity(undefined);
|
|
22078
|
+
if (assistantText.trim() !== "") {
|
|
22079
|
+
push({ kind: "assistant", id: nextId(), text: assistantText.trimEnd() });
|
|
22080
|
+
assistantText = "";
|
|
22081
|
+
setLive("");
|
|
22082
|
+
}
|
|
22083
|
+
setRunningTool(event.call.toolName);
|
|
22084
|
+
break;
|
|
22085
|
+
case "tool_end": {
|
|
22086
|
+
setRunningTool(undefined);
|
|
22087
|
+
const output = event.result.output.type === "text" ? event.result.output.value : "";
|
|
22088
|
+
push({
|
|
22089
|
+
kind: "tool",
|
|
22090
|
+
id: nextId(),
|
|
22091
|
+
name: event.toolName,
|
|
22092
|
+
...event.result.title ? { title: event.result.title } : {},
|
|
22093
|
+
output,
|
|
22094
|
+
...event.result.isError ? { isError: true } : {}
|
|
22095
|
+
});
|
|
22096
|
+
setTodos(agent3.todos.list());
|
|
22097
|
+
break;
|
|
22098
|
+
}
|
|
22099
|
+
case "usage":
|
|
22100
|
+
setCost(agent3.costUsd);
|
|
22101
|
+
setContext(agent3.contextUse);
|
|
22102
|
+
break;
|
|
22103
|
+
case "budget":
|
|
22104
|
+
push({
|
|
22105
|
+
kind: "notice",
|
|
22106
|
+
id: nextId(),
|
|
22107
|
+
text: event.raisedTo === undefined ? `stopped: $${event.spentUsd.toFixed(2)} spent against a ` + `$${event.limitUsd.toFixed(2)} budget` : `budget raised to $${event.raisedTo.toFixed(2)} after ` + `$${event.spentUsd.toFixed(2)} spent`,
|
|
22108
|
+
color: theme.warning
|
|
22109
|
+
});
|
|
22110
|
+
break;
|
|
22111
|
+
case "verification":
|
|
22112
|
+
push({
|
|
22113
|
+
kind: "tool",
|
|
22114
|
+
id: nextId(),
|
|
22115
|
+
name: event.result.command,
|
|
22116
|
+
title: `${event.result.command} - exit ${event.result.exitCode ?? "killed"}`,
|
|
22117
|
+
output: event.result.output,
|
|
22118
|
+
...event.result.exitCode === 0 ? {} : { isError: true }
|
|
22119
|
+
});
|
|
22120
|
+
break;
|
|
22121
|
+
case "subagent":
|
|
22122
|
+
push({
|
|
22123
|
+
kind: "notice",
|
|
22124
|
+
id: nextId(),
|
|
22125
|
+
text: `subagent "${event.description}": ${event.steps} step${event.steps === 1 ? "" : "s"}, $${event.costUsd.toFixed(4)}`
|
|
22126
|
+
});
|
|
22127
|
+
break;
|
|
22128
|
+
case "hook":
|
|
22129
|
+
if (event.blocked) {
|
|
22130
|
+
push({
|
|
22131
|
+
kind: "notice",
|
|
22132
|
+
id: nextId(),
|
|
22133
|
+
text: `${event.event} hook blocked this: ${event.blocked}`,
|
|
22134
|
+
color: theme.warning
|
|
22135
|
+
});
|
|
22136
|
+
}
|
|
22137
|
+
for (const problem of event.problems) {
|
|
22138
|
+
push({ kind: "notice", id: nextId(), text: problem, color: theme.warning });
|
|
22139
|
+
}
|
|
22140
|
+
break;
|
|
22141
|
+
case "compacted":
|
|
22142
|
+
setCompacted((count) => count + event.replaced);
|
|
22143
|
+
push({
|
|
22144
|
+
kind: "notice",
|
|
22145
|
+
id: nextId(),
|
|
22146
|
+
text: `compacted: ${event.replaced} earlier messages are now a summary`
|
|
22147
|
+
});
|
|
22148
|
+
break;
|
|
22149
|
+
case "error":
|
|
22150
|
+
setActivity(undefined);
|
|
22151
|
+
push({
|
|
22152
|
+
kind: "notice",
|
|
22153
|
+
id: nextId(),
|
|
22154
|
+
text: `error: ${event.error.message}`,
|
|
22155
|
+
color: theme.danger
|
|
22156
|
+
});
|
|
22157
|
+
break;
|
|
22158
|
+
case "turn_end":
|
|
22159
|
+
if (event.reason === "aborted") {
|
|
22160
|
+
push({
|
|
22161
|
+
kind: "notice",
|
|
22162
|
+
id: nextId(),
|
|
22163
|
+
text: "interrupted",
|
|
22164
|
+
color: theme.warning
|
|
22165
|
+
});
|
|
22166
|
+
}
|
|
22167
|
+
if (event.reason === "max_steps") {
|
|
22168
|
+
push({
|
|
22169
|
+
kind: "notice",
|
|
22170
|
+
id: nextId(),
|
|
22171
|
+
text: "stopped: step limit reached",
|
|
22172
|
+
color: theme.warning
|
|
22173
|
+
});
|
|
22174
|
+
}
|
|
22175
|
+
break;
|
|
22176
|
+
default:
|
|
22177
|
+
break;
|
|
22178
|
+
}
|
|
21763
22179
|
setQueued(agent3.pendingSteers);
|
|
21764
|
-
push({ kind: "user", id: nextId(), text: command });
|
|
21765
|
-
return;
|
|
21766
22180
|
}
|
|
21767
|
-
|
|
22181
|
+
} finally {
|
|
22182
|
+
if (!reasoningFlushed && reasoningText.trim() !== "" && showThinking) {
|
|
22183
|
+
push({ kind: "reasoning", id: nextId(), text: reasoningText.trimEnd() });
|
|
22184
|
+
}
|
|
22185
|
+
if (assistantText.trim() !== "") {
|
|
22186
|
+
lastAssistantText.current = assistantText;
|
|
22187
|
+
push({ kind: "assistant", id: nextId(), text: assistantText.trimEnd() });
|
|
22188
|
+
}
|
|
22189
|
+
setLive("");
|
|
22190
|
+
setReasoningLive("");
|
|
22191
|
+
setActivity(undefined);
|
|
22192
|
+
setRunningTool(undefined);
|
|
22193
|
+
setBusy(false);
|
|
22194
|
+
setQueued(agent3.pendingSteers);
|
|
22195
|
+
controller.current = undefined;
|
|
22196
|
+
}
|
|
22197
|
+
}, [agent3, push, showThinking]);
|
|
22198
|
+
const started = useRef3(false);
|
|
22199
|
+
useEffect3(() => {
|
|
22200
|
+
if (started.current || !initialPrompt)
|
|
22201
|
+
return;
|
|
22202
|
+
started.current = true;
|
|
22203
|
+
runTurn(initialPrompt);
|
|
22204
|
+
}, [initialPrompt, runTurn]);
|
|
22205
|
+
const showMemories = useCallback2(async (argument) => {
|
|
22206
|
+
const [verb, ...rest] = (argument ?? "").split(/\s+/);
|
|
22207
|
+
const id = rest.join(" ").trim();
|
|
22208
|
+
if (verb === "forget" && id) {
|
|
22209
|
+
const gone = await deleteMemory(id, agent3.cwd);
|
|
22210
|
+
if (gone)
|
|
22211
|
+
await refreshSystemPrompt(agent3, model2, session2.skills);
|
|
22212
|
+
push({
|
|
22213
|
+
kind: "notice",
|
|
22214
|
+
id: nextId(),
|
|
22215
|
+
text: gone ? `forgot ${id}` : `no memory called "${id}"`,
|
|
22216
|
+
...gone ? {} : { color: theme.warning }
|
|
22217
|
+
});
|
|
22218
|
+
return;
|
|
22219
|
+
}
|
|
22220
|
+
const memories = await loadMemories(agent3.cwd);
|
|
22221
|
+
if (memories.length === 0) {
|
|
22222
|
+
push({ kind: "notice", id: nextId(), text: "nothing remembered yet" });
|
|
21768
22223
|
return;
|
|
21769
22224
|
}
|
|
22225
|
+
const lines = memories.map((memory2) => {
|
|
22226
|
+
const when = memory2.created.slice(0, 10);
|
|
22227
|
+
const why = memory2.source ? `
|
|
22228
|
+
from "${memory2.source}" on ${when}` : "";
|
|
22229
|
+
return ` [${memory2.id}] (${memory2.scope}) ${memory2.text}${why}`;
|
|
22230
|
+
});
|
|
21770
22231
|
push({
|
|
21771
22232
|
kind: "notice",
|
|
21772
22233
|
id: nextId(),
|
|
21773
|
-
text: `
|
|
21774
|
-
|
|
22234
|
+
text: `${lines.join(`
|
|
22235
|
+
`)}
|
|
22236
|
+
|
|
22237
|
+
/memory forget <id> removes one`
|
|
21775
22238
|
});
|
|
21776
|
-
}, [agent3,
|
|
21777
|
-
const
|
|
21778
|
-
|
|
21779
|
-
if (entry) {
|
|
21780
|
-
setInput("");
|
|
21781
|
-
setMenuIndex(0);
|
|
21782
|
-
handleCommand(entry.insert);
|
|
21783
|
-
return;
|
|
21784
|
-
}
|
|
21785
|
-
const trimmed = text2.trim();
|
|
21786
|
-
setInput("");
|
|
21787
|
-
if (trimmed === "")
|
|
22239
|
+
}, [agent3, model2, push, session2.skills]);
|
|
22240
|
+
const remember = useCallback2(async (scope2) => {
|
|
22241
|
+
if (!candidate)
|
|
21788
22242
|
return;
|
|
21789
|
-
|
|
21790
|
-
|
|
22243
|
+
setCandidate(undefined);
|
|
22244
|
+
const saved = await saveMemory({ ...candidate, scope: scope2 }, agent3.cwd).catch(() => {
|
|
21791
22245
|
return;
|
|
21792
|
-
}
|
|
21793
|
-
|
|
21794
|
-
|
|
21795
|
-
agent3.steer(trimmed);
|
|
21796
|
-
setQueued(agent3.pendingSteers);
|
|
21797
|
-
push({ kind: "user", id: nextId(), text: trimmed });
|
|
22246
|
+
});
|
|
22247
|
+
if (!saved) {
|
|
22248
|
+
push({ kind: "notice", id: nextId(), text: "could not save that", color: theme.warning });
|
|
21798
22249
|
return;
|
|
21799
22250
|
}
|
|
21800
|
-
|
|
21801
|
-
|
|
21802
|
-
|
|
21803
|
-
|
|
21804
|
-
|
|
21805
|
-
|
|
21806
|
-
|
|
21807
|
-
|
|
21808
|
-
|
|
21809
|
-
|
|
21810
|
-
|
|
21811
|
-
|
|
21812
|
-
|
|
21813
|
-
if (menuOpen && entries.length > 0) {
|
|
21814
|
-
if (key2.upArrow) {
|
|
21815
|
-
setMenuIndex((current) => current <= 0 ? entries.length - 1 : current - 1);
|
|
21816
|
-
return;
|
|
21817
|
-
}
|
|
21818
|
-
if (key2.downArrow) {
|
|
21819
|
-
setMenuIndex((current) => current >= entries.length - 1 ? 0 : current + 1);
|
|
21820
|
-
return;
|
|
21821
|
-
}
|
|
21822
|
-
if (key2.tab) {
|
|
21823
|
-
const entry = entries[selected];
|
|
21824
|
-
if (entry)
|
|
21825
|
-
setInput(`${entry.insert} `);
|
|
21826
|
-
setMenuIndex(0);
|
|
21827
|
-
return;
|
|
21828
|
-
}
|
|
21829
|
-
if (key2.escape) {
|
|
21830
|
-
setInput("");
|
|
21831
|
-
setMenuIndex(0);
|
|
22251
|
+
await refreshSystemPrompt(agent3, model2, session2.skills);
|
|
22252
|
+
push({
|
|
22253
|
+
kind: "notice",
|
|
22254
|
+
id: nextId(),
|
|
22255
|
+
text: `remembered [${saved.id}] (${scope2}) - /memory to review or forget it`
|
|
22256
|
+
});
|
|
22257
|
+
}, [agent3, candidate, model2, push, session2.skills]);
|
|
22258
|
+
const sessionTree = useCallback2(async (name, argument) => {
|
|
22259
|
+
const entries2 = await session2.branch();
|
|
22260
|
+
const prompts = entries2.filter((entry) => entry.type === "message" && entry.message.role === "user" && entry.message.content.some((part) => part.type === "text" && !part.text.startsWith("<self-check>")));
|
|
22261
|
+
if (name === "tree" || !argument) {
|
|
22262
|
+
if (prompts.length === 0) {
|
|
22263
|
+
push({ kind: "notice", id: nextId(), text: "nothing in this session yet" });
|
|
21832
22264
|
return;
|
|
21833
22265
|
}
|
|
22266
|
+
const lines = prompts.map((entry, index2) => {
|
|
22267
|
+
const text2 = entry.type === "message" ? entry.message.content.find((part) => part.type === "text")?.text ?? "" : "";
|
|
22268
|
+
return ` ${index2 + 1}. ${text2.split(`
|
|
22269
|
+
`)[0]?.slice(0, 70) ?? ""}`;
|
|
22270
|
+
});
|
|
22271
|
+
push({
|
|
22272
|
+
kind: "notice",
|
|
22273
|
+
id: nextId(),
|
|
22274
|
+
text: `${lines.join(`
|
|
22275
|
+
`)}
|
|
22276
|
+
|
|
22277
|
+
/rewind <n> goes back to one · /fork <n> branches from it`
|
|
22278
|
+
});
|
|
22279
|
+
return;
|
|
21834
22280
|
}
|
|
21835
|
-
|
|
21836
|
-
|
|
21837
|
-
|
|
21838
|
-
|
|
22281
|
+
const index = Number.parseInt(argument, 10) - 1;
|
|
22282
|
+
const target = prompts[index];
|
|
22283
|
+
if (!target) {
|
|
22284
|
+
push({
|
|
22285
|
+
kind: "notice",
|
|
22286
|
+
id: nextId(),
|
|
22287
|
+
text: `no prompt ${argument} in this session - /tree lists them`,
|
|
22288
|
+
color: theme.warning
|
|
22289
|
+
});
|
|
21839
22290
|
return;
|
|
21840
22291
|
}
|
|
21841
|
-
|
|
21842
|
-
|
|
22292
|
+
const previous = entries2[entries2.indexOf(target) - 1] ?? target;
|
|
22293
|
+
if (name === "rewind") {
|
|
22294
|
+
const kept = await session2.rewindTo(previous.id);
|
|
22295
|
+
push({
|
|
22296
|
+
kind: "notice",
|
|
22297
|
+
id: nextId(),
|
|
22298
|
+
text: `rewound to before prompt ${index + 1}; ${kept} message${kept === 1 ? "" : "s"} kept. Nothing was deleted - the rest is still in the transcript as another branch.`
|
|
22299
|
+
});
|
|
22300
|
+
return;
|
|
21843
22301
|
}
|
|
21844
|
-
|
|
21845
|
-
|
|
21846
|
-
|
|
21847
|
-
|
|
21848
|
-
|
|
21849
|
-
|
|
21850
|
-
|
|
21851
|
-
|
|
21852
|
-
|
|
21853
|
-
|
|
21854
|
-
|
|
21855
|
-
|
|
21856
|
-
|
|
21857
|
-
text: live
|
|
21858
|
-
}, undefined, false, undefined, this)
|
|
21859
|
-
}, undefined, false, undefined, this),
|
|
21860
|
-
runningTool && /* @__PURE__ */ jsxDEV10(ToolBlock, {
|
|
21861
|
-
name: runningTool,
|
|
21862
|
-
running: true
|
|
21863
|
-
}, undefined, false, undefined, this),
|
|
21864
|
-
pending && /* @__PURE__ */ jsxDEV10(PermissionPrompt, {
|
|
21865
|
-
request: pending.request,
|
|
21866
|
-
reason: pending.reason,
|
|
21867
|
-
onChoice: (choice) => {
|
|
21868
|
-
setPending(undefined);
|
|
21869
|
-
pending.resolve(choice);
|
|
21870
|
-
}
|
|
21871
|
-
}, undefined, false, undefined, this),
|
|
21872
|
-
question && /* @__PURE__ */ jsxDEV10(QuestionPrompt, {
|
|
21873
|
-
question: question.question,
|
|
21874
|
-
...question.options ? { options: question.options } : {},
|
|
21875
|
-
onAnswer: (answer) => {
|
|
21876
|
-
setQuestion(undefined);
|
|
21877
|
-
question.resolve(answer);
|
|
21878
|
-
}
|
|
21879
|
-
}, undefined, false, undefined, this),
|
|
21880
|
-
candidate && inputActive && /* @__PURE__ */ jsxDEV10(MemoryCapture, {
|
|
21881
|
-
candidate
|
|
21882
|
-
}, undefined, false, undefined, this),
|
|
21883
|
-
menuOpen && /* @__PURE__ */ jsxDEV10(CommandMenu, {
|
|
21884
|
-
entries,
|
|
21885
|
-
selected
|
|
21886
|
-
}, undefined, false, undefined, this),
|
|
21887
|
-
inputActive && /* @__PURE__ */ jsxDEV10(Box9, {
|
|
21888
|
-
marginTop: 1,
|
|
21889
|
-
children: [
|
|
21890
|
-
/* @__PURE__ */ jsxDEV10(Text10, {
|
|
21891
|
-
color: theme.user,
|
|
21892
|
-
children: "> "
|
|
21893
|
-
}, undefined, false, undefined, this),
|
|
21894
|
-
/* @__PURE__ */ jsxDEV10(TextInput, {
|
|
21895
|
-
value: input,
|
|
21896
|
-
onChange: (value) => {
|
|
21897
|
-
setInput(value);
|
|
21898
|
-
setMenuIndex(0);
|
|
21899
|
-
},
|
|
21900
|
-
onSubmit: submit,
|
|
21901
|
-
placeholder: busy ? "steer the agent, or esc to interrupt" : "what should I do?"
|
|
21902
|
-
}, undefined, false, undefined, this)
|
|
21903
|
-
]
|
|
21904
|
-
}, undefined, true, undefined, this),
|
|
21905
|
-
/* @__PURE__ */ jsxDEV10(StatusLine, {
|
|
21906
|
-
model: model2,
|
|
21907
|
-
mode,
|
|
21908
|
-
costUsd: cost,
|
|
21909
|
-
todos,
|
|
21910
|
-
busy,
|
|
21911
|
-
queued,
|
|
21912
|
-
context: context2,
|
|
21913
|
-
compacted
|
|
21914
|
-
}, undefined, false, undefined, this)
|
|
21915
|
-
]
|
|
21916
|
-
}, undefined, true, undefined, this);
|
|
21917
|
-
}
|
|
21918
|
-
function ScrollRow({ item }) {
|
|
21919
|
-
if (item.kind === "user") {
|
|
21920
|
-
return /* @__PURE__ */ jsxDEV10(Box9, {
|
|
21921
|
-
marginTop: 1,
|
|
21922
|
-
children: [
|
|
21923
|
-
/* @__PURE__ */ jsxDEV10(Text10, {
|
|
21924
|
-
color: theme.user,
|
|
21925
|
-
children: "> "
|
|
21926
|
-
}, undefined, false, undefined, this),
|
|
21927
|
-
/* @__PURE__ */ jsxDEV10(Text10, {
|
|
21928
|
-
children: item.text
|
|
21929
|
-
}, undefined, false, undefined, this)
|
|
21930
|
-
]
|
|
21931
|
-
}, undefined, true, undefined, this);
|
|
21932
|
-
}
|
|
21933
|
-
if (item.kind === "assistant") {
|
|
21934
|
-
return /* @__PURE__ */ jsxDEV10(Box9, {
|
|
21935
|
-
marginTop: 1,
|
|
21936
|
-
children: /* @__PURE__ */ jsxDEV10(Markdown, {
|
|
21937
|
-
text: item.text
|
|
21938
|
-
}, undefined, false, undefined, this)
|
|
21939
|
-
}, undefined, false, undefined, this);
|
|
21940
|
-
}
|
|
21941
|
-
if (item.kind === "tool") {
|
|
21942
|
-
return /* @__PURE__ */ jsxDEV10(ToolBlock, {
|
|
21943
|
-
name: item.name,
|
|
21944
|
-
...item.title ? { title: item.title } : {},
|
|
21945
|
-
...item.output ? { output: item.output } : {},
|
|
21946
|
-
...item.isError ? { isError: true } : {}
|
|
21947
|
-
}, undefined, false, undefined, this);
|
|
21948
|
-
}
|
|
21949
|
-
return /* @__PURE__ */ jsxDEV10(Box9, {
|
|
21950
|
-
marginTop: 1,
|
|
21951
|
-
children: /* @__PURE__ */ jsxDEV10(Text10, {
|
|
21952
|
-
color: item.color ?? theme.muted,
|
|
21953
|
-
children: item.text
|
|
21954
|
-
}, undefined, false, undefined, this)
|
|
21955
|
-
}, undefined, false, undefined, this);
|
|
21956
|
-
}
|
|
21957
|
-
function describeCommands(session2) {
|
|
21958
|
-
const lines = commandRows().map((row) => ` ${row.command.padEnd(34)} ${row.summary}`);
|
|
21959
|
-
if (session2.commands.length > 0) {
|
|
21960
|
-
lines.push("", " commands from this directory:");
|
|
21961
|
-
for (const command of session2.commands) {
|
|
21962
|
-
lines.push(` ${`/${command.name}`.padEnd(34)} ${command.description}`);
|
|
22302
|
+
const forked = await session2.fork(previous.id);
|
|
22303
|
+
push({
|
|
22304
|
+
kind: "notice",
|
|
22305
|
+
id: nextId(),
|
|
22306
|
+
text: forked ? `forked from prompt ${index + 1} into ${forked}; this session continues there and the original is untouched` : "could not fork this session",
|
|
22307
|
+
...forked ? {} : { color: theme.warning }
|
|
22308
|
+
});
|
|
22309
|
+
}, [push, session2]);
|
|
22310
|
+
const undoLast = useCallback2(async () => {
|
|
22311
|
+
const result = await session2.undo();
|
|
22312
|
+
if (!result) {
|
|
22313
|
+
push({ kind: "notice", id: nextId(), text: "nothing to undo", color: theme.warning });
|
|
22314
|
+
return;
|
|
21963
22315
|
}
|
|
21964
|
-
|
|
21965
|
-
|
|
21966
|
-
|
|
21967
|
-
|
|
21968
|
-
}
|
|
21969
|
-
|
|
22316
|
+
const created2 = result.wasCreated.length ? ` Left in place because the batch created them: ${result.wasCreated.join(", ")}.` : "";
|
|
22317
|
+
push({
|
|
22318
|
+
kind: "notice",
|
|
22319
|
+
id: nextId(),
|
|
22320
|
+
text: result.restored.length ? `undid ${result.label}: restored ${result.restored.join(", ")}.${created2}` : `nothing to restore from ${result.label}.${created2}`
|
|
22321
|
+
});
|
|
22322
|
+
}, [push, session2]);
|
|
22323
|
+
const plan2 = useCallback2(async (argument) => {
|
|
22324
|
+
const path = planPath(session2.store?.id ?? "scratch");
|
|
22325
|
+
const [verb = "", ...rest] = (argument ?? "").split(/\s+/);
|
|
22326
|
+
const task2 = [verb, ...rest].join(" ").trim();
|
|
22327
|
+
if (verb === "show") {
|
|
22328
|
+
const text2 = await readPlan(path);
|
|
22329
|
+
push({
|
|
22330
|
+
kind: "notice",
|
|
22331
|
+
id: nextId(),
|
|
22332
|
+
text: text2 ? `${path}
|
|
21970
22333
|
|
|
21971
|
-
|
|
21972
|
-
|
|
21973
|
-
|
|
21974
|
-
if (session2.skills.length > 0) {
|
|
21975
|
-
lines.push("skills (the agent loads these itself when they fit):");
|
|
21976
|
-
for (const skill of session2.skills) {
|
|
21977
|
-
lines.push(` ${skill.name} [${skill.scope}] ${skill.description}`);
|
|
22334
|
+
${text2}` : `no plan yet at ${path}`
|
|
22335
|
+
});
|
|
22336
|
+
return;
|
|
21978
22337
|
}
|
|
21979
|
-
|
|
21980
|
-
|
|
21981
|
-
|
|
21982
|
-
|
|
21983
|
-
|
|
21984
|
-
|
|
21985
|
-
|
|
22338
|
+
if (verb === "edit") {
|
|
22339
|
+
const result = await openInEditor(path);
|
|
22340
|
+
push({
|
|
22341
|
+
kind: "notice",
|
|
22342
|
+
id: nextId(),
|
|
22343
|
+
text: result.message,
|
|
22344
|
+
...result.edited ? {} : { color: theme.warning }
|
|
22345
|
+
});
|
|
22346
|
+
return;
|
|
21986
22347
|
}
|
|
21987
|
-
|
|
21988
|
-
|
|
21989
|
-
|
|
21990
|
-
|
|
21991
|
-
|
|
21992
|
-
|
|
21993
|
-
|
|
21994
|
-
|
|
21995
|
-
|
|
21996
|
-
|
|
21997
|
-
|
|
21998
|
-
|
|
21999
|
-
|
|
22000
|
-
|
|
22001
|
-
|
|
22002
|
-
|
|
22003
|
-
|
|
22004
|
-
|
|
22005
|
-
|
|
22006
|
-
|
|
22007
|
-
|
|
22008
|
-
}, [exit, onDone]);
|
|
22009
|
-
const verify2 = useCallback2(async (provider) => {
|
|
22010
|
-
setScreen({ name: "probing", provider });
|
|
22011
|
-
const result = await options.current.probe(provider.id);
|
|
22012
|
-
if (result.ok) {
|
|
22013
|
-
setScreen({ name: "ready", provider });
|
|
22348
|
+
if (verb === "approve") {
|
|
22349
|
+
const text2 = await readPlan(path);
|
|
22350
|
+
if (!text2) {
|
|
22351
|
+
push({
|
|
22352
|
+
kind: "notice",
|
|
22353
|
+
id: nextId(),
|
|
22354
|
+
text: `there is no plan at ${path} to approve`,
|
|
22355
|
+
color: theme.warning
|
|
22356
|
+
});
|
|
22357
|
+
return;
|
|
22358
|
+
}
|
|
22359
|
+
agent3.setPlan(text2);
|
|
22360
|
+
const restored = modeBeforePlan.current ?? "ask";
|
|
22361
|
+
agent3.setPermissionMode(restored);
|
|
22362
|
+
setMode(restored);
|
|
22363
|
+
modeBeforePlan.current = undefined;
|
|
22364
|
+
push({
|
|
22365
|
+
kind: "notice",
|
|
22366
|
+
id: nextId(),
|
|
22367
|
+
text: `plan approved and pinned for this run; permission mode: ${restored}`
|
|
22368
|
+
});
|
|
22014
22369
|
return;
|
|
22015
22370
|
}
|
|
22016
|
-
if (
|
|
22017
|
-
|
|
22018
|
-
|
|
22019
|
-
}, []);
|
|
22020
|
-
const submitKey = useCallback2(async () => {
|
|
22021
|
-
const provider = screen.name === "key" ? screen.provider : undefined;
|
|
22022
|
-
const key2 = secret.current;
|
|
22023
|
-
secret.current = "";
|
|
22024
|
-
setInput("");
|
|
22025
|
-
if (!provider)
|
|
22371
|
+
if (verb === "clear") {
|
|
22372
|
+
agent3.setPlan(undefined);
|
|
22373
|
+
push({ kind: "notice", id: nextId(), text: "plan unpinned" });
|
|
22026
22374
|
return;
|
|
22027
|
-
|
|
22028
|
-
|
|
22375
|
+
}
|
|
22376
|
+
if (task2 === "") {
|
|
22377
|
+
push({
|
|
22378
|
+
kind: "notice",
|
|
22379
|
+
id: nextId(),
|
|
22380
|
+
text: "usage: /plan <what you want planned>, then /plan edit, /plan approve",
|
|
22381
|
+
color: theme.warning
|
|
22382
|
+
});
|
|
22383
|
+
return;
|
|
22384
|
+
}
|
|
22385
|
+
modeBeforePlan.current = agent3.permissionMode;
|
|
22386
|
+
agent3.setPermissionMode("plan");
|
|
22387
|
+
setMode("plan");
|
|
22388
|
+
await runTurn(`${task2}
|
|
22389
|
+
|
|
22390
|
+
${PLAN_PROMPT}`);
|
|
22391
|
+
const drafted = lastAssistantText.current.trim();
|
|
22392
|
+
if (drafted === "") {
|
|
22393
|
+
push({
|
|
22394
|
+
kind: "notice",
|
|
22395
|
+
id: nextId(),
|
|
22396
|
+
text: "the model produced no plan to write",
|
|
22397
|
+
color: theme.warning
|
|
22398
|
+
});
|
|
22399
|
+
return;
|
|
22400
|
+
}
|
|
22401
|
+
await savePlan(path, drafted);
|
|
22402
|
+
push({
|
|
22403
|
+
kind: "notice",
|
|
22404
|
+
id: nextId(),
|
|
22405
|
+
text: `plan written to ${path}
|
|
22406
|
+
/plan edit to change it, /plan approve to pin it`
|
|
22407
|
+
});
|
|
22408
|
+
}, [agent3, push, runTurn, session2.store]);
|
|
22409
|
+
const switchModel = useCallback2(async (ref) => {
|
|
22410
|
+
if (!ref) {
|
|
22411
|
+
if (modelOptions)
|
|
22412
|
+
setChoosingModel(true);
|
|
22413
|
+
else
|
|
22414
|
+
push({ kind: "notice", id: nextId(), text: "model picker is unavailable" });
|
|
22029
22415
|
return;
|
|
22030
22416
|
}
|
|
22031
|
-
setError(undefined);
|
|
22032
|
-
await options.current.storeKey(provider.id, key2.trim());
|
|
22033
|
-
await verify2(provider);
|
|
22034
|
-
}, [screen, verify2]);
|
|
22035
|
-
const startSignIn = useCallback2(async (provider) => {
|
|
22036
|
-
setScreen({ name: "oauth", provider });
|
|
22037
22417
|
try {
|
|
22038
|
-
|
|
22039
|
-
|
|
22040
|
-
|
|
22041
|
-
|
|
22042
|
-
|
|
22043
|
-
|
|
22418
|
+
const resolved = await agent3.changeModel(ref);
|
|
22419
|
+
const next = `${resolved.provider.id}/${resolved.model.id}`;
|
|
22420
|
+
const effort = modelOptions?.reasoningFor?.(next);
|
|
22421
|
+
agent3.setReasoningEffort(effort);
|
|
22422
|
+
setModel(next);
|
|
22423
|
+
await refreshSystemPrompt(agent3, next, session2.skills);
|
|
22424
|
+
await modelOptions?.remember?.(next, effort, "project");
|
|
22425
|
+
await session2.recordConfiguration({ model: next, reasoningEffort: effort ?? null });
|
|
22426
|
+
push({
|
|
22427
|
+
kind: "notice",
|
|
22428
|
+
id: nextId(),
|
|
22429
|
+
text: `model: ${next}${effort ? ` · ${effort}` : ""}`
|
|
22430
|
+
});
|
|
22431
|
+
} catch (error) {
|
|
22432
|
+
push({
|
|
22433
|
+
kind: "notice",
|
|
22434
|
+
id: nextId(),
|
|
22435
|
+
text: `${error.message}`,
|
|
22436
|
+
color: theme.warning
|
|
22044
22437
|
});
|
|
22438
|
+
}
|
|
22439
|
+
}, [agent3, modelOptions, push, session2]);
|
|
22440
|
+
const finishModelChoice = useCallback2(async (result) => {
|
|
22441
|
+
if (result.outcome === "quit" || !result.model) {
|
|
22442
|
+
setChoosingModel(false);
|
|
22045
22443
|
return;
|
|
22046
22444
|
}
|
|
22047
|
-
|
|
22048
|
-
|
|
22049
|
-
|
|
22050
|
-
|
|
22051
|
-
|
|
22052
|
-
|
|
22053
|
-
|
|
22054
|
-
|
|
22055
|
-
|
|
22056
|
-
|
|
22057
|
-
|
|
22058
|
-
|
|
22445
|
+
try {
|
|
22446
|
+
const resolved = await agent3.changeModel(result.model);
|
|
22447
|
+
const next = `${resolved.provider.id}/${resolved.model.id}`;
|
|
22448
|
+
agent3.setReasoningEffort(result.reasoningEffort);
|
|
22449
|
+
setModel(next);
|
|
22450
|
+
await refreshSystemPrompt(agent3, next, session2.skills);
|
|
22451
|
+
await modelOptions?.remember?.(next, result.reasoningEffort, result.scope ?? "project");
|
|
22452
|
+
await session2.recordConfiguration({
|
|
22453
|
+
model: next,
|
|
22454
|
+
reasoningEffort: result.reasoningEffort ?? null
|
|
22455
|
+
});
|
|
22456
|
+
push({
|
|
22457
|
+
kind: "notice",
|
|
22458
|
+
id: nextId(),
|
|
22459
|
+
text: `model: ${next}${result.reasoningEffort ? ` · ${result.reasoningEffort}` : " · auto"}`
|
|
22460
|
+
});
|
|
22461
|
+
} catch (error) {
|
|
22462
|
+
push({
|
|
22463
|
+
kind: "notice",
|
|
22464
|
+
id: nextId(),
|
|
22465
|
+
text: error.message,
|
|
22466
|
+
color: theme.warning
|
|
22467
|
+
});
|
|
22468
|
+
} finally {
|
|
22469
|
+
setChoosingModel(false);
|
|
22470
|
+
}
|
|
22471
|
+
}, [agent3, modelOptions, push, session2, session2.skills]);
|
|
22472
|
+
const changeReasoning = useCallback2(async (argument) => {
|
|
22473
|
+
const value = argument?.trim().toLowerCase();
|
|
22474
|
+
if (!value) {
|
|
22475
|
+
if (!agent3.model.model.capabilities.reasoning) {
|
|
22476
|
+
push({
|
|
22477
|
+
kind: "notice",
|
|
22478
|
+
id: nextId(),
|
|
22479
|
+
text: `${agent3.model.model.name} does not support reasoning`,
|
|
22480
|
+
color: theme.warning
|
|
22481
|
+
});
|
|
22482
|
+
} else
|
|
22483
|
+
setChoosingReasoning(true);
|
|
22059
22484
|
return;
|
|
22060
22485
|
}
|
|
22061
|
-
|
|
22062
|
-
|
|
22063
|
-
|
|
22064
|
-
|
|
22486
|
+
const effort = value === "auto" ? undefined : value;
|
|
22487
|
+
if (value !== "auto" && !["none", "low", "medium", "high", "xhigh"].includes(value)) {
|
|
22488
|
+
push({
|
|
22489
|
+
kind: "notice",
|
|
22490
|
+
id: nextId(),
|
|
22491
|
+
text: `unknown reasoning effort "${value}"`,
|
|
22492
|
+
color: theme.warning
|
|
22493
|
+
});
|
|
22494
|
+
return;
|
|
22495
|
+
}
|
|
22496
|
+
if (!agent3.model.model.capabilities.reasoning && effort !== undefined) {
|
|
22497
|
+
push({
|
|
22498
|
+
kind: "notice",
|
|
22499
|
+
id: nextId(),
|
|
22500
|
+
text: `${agent3.model.model.name} does not support reasoning`,
|
|
22501
|
+
color: theme.warning
|
|
22502
|
+
});
|
|
22503
|
+
return;
|
|
22504
|
+
}
|
|
22505
|
+
agent3.setReasoningEffort(effort);
|
|
22506
|
+
await modelOptions?.remember?.(model2, effort, "project");
|
|
22507
|
+
await session2.recordConfiguration({ reasoningEffort: effort ?? null });
|
|
22508
|
+
push({ kind: "notice", id: nextId(), text: `reasoning: ${effort ?? "auto"}` });
|
|
22509
|
+
}, [agent3, model2, modelOptions, push, session2]);
|
|
22510
|
+
const finishReasoningChoice = useCallback2(async (effort) => {
|
|
22511
|
+
setChoosingReasoning(false);
|
|
22512
|
+
agent3.setReasoningEffort(effort);
|
|
22513
|
+
await modelOptions?.remember?.(model2, effort, "project");
|
|
22514
|
+
await session2.recordConfiguration({ reasoningEffort: effort ?? null });
|
|
22515
|
+
push({ kind: "notice", id: nextId(), text: `reasoning: ${effort ?? "auto"}` });
|
|
22516
|
+
}, [agent3, model2, modelOptions, push, session2]);
|
|
22517
|
+
const compactNow = useCallback2(async () => {
|
|
22518
|
+
const abort = new AbortController;
|
|
22519
|
+
controller.current = abort;
|
|
22520
|
+
setBusy(true);
|
|
22521
|
+
try {
|
|
22522
|
+
let compactedAnything = false;
|
|
22523
|
+
for await (const event of agent3.compactNow(abort.signal)) {
|
|
22524
|
+
if (event.type === "compacted") {
|
|
22525
|
+
compactedAnything = true;
|
|
22526
|
+
setCompacted((count) => count + event.replaced);
|
|
22527
|
+
push({
|
|
22528
|
+
kind: "notice",
|
|
22529
|
+
id: nextId(),
|
|
22530
|
+
text: `compacted: ${event.replaced} earlier messages are now a summary`
|
|
22531
|
+
});
|
|
22532
|
+
}
|
|
22065
22533
|
}
|
|
22066
|
-
if (
|
|
22067
|
-
|
|
22068
|
-
if (meta.downArrow)
|
|
22069
|
-
setCursor((c) => c >= providers.length - 1 ? 0 : c + 1);
|
|
22070
|
-
if (meta.return) {
|
|
22071
|
-
const provider = providers[cursor];
|
|
22072
|
-
if (provider)
|
|
22073
|
-
choose(provider);
|
|
22534
|
+
if (!compactedAnything) {
|
|
22535
|
+
push({ kind: "notice", id: nextId(), text: "nothing to compact yet" });
|
|
22074
22536
|
}
|
|
22075
|
-
|
|
22537
|
+
} catch (error) {
|
|
22538
|
+
push({
|
|
22539
|
+
kind: "notice",
|
|
22540
|
+
id: nextId(),
|
|
22541
|
+
text: `could not compact: ${error.message}`,
|
|
22542
|
+
color: theme.warning
|
|
22543
|
+
});
|
|
22544
|
+
} finally {
|
|
22545
|
+
setBusy(false);
|
|
22546
|
+
setContext(agent3.contextUse);
|
|
22547
|
+
controller.current = undefined;
|
|
22076
22548
|
}
|
|
22077
|
-
|
|
22078
|
-
|
|
22079
|
-
|
|
22549
|
+
}, [agent3, push]);
|
|
22550
|
+
const handlers = {
|
|
22551
|
+
exit: () => exit(),
|
|
22552
|
+
help: () => push({ kind: "notice", id: nextId(), text: describeCommands(session2) }),
|
|
22553
|
+
model: (argument) => void switchModel(argument),
|
|
22554
|
+
reasoning: (argument) => void changeReasoning(argument),
|
|
22555
|
+
thinking: (argument) => {
|
|
22556
|
+
if (argument !== "show" && argument !== "hide") {
|
|
22557
|
+
push({
|
|
22558
|
+
kind: "notice",
|
|
22559
|
+
id: nextId(),
|
|
22560
|
+
text: `thinking: ${showThinking ? "shown" : "hidden"}
|
|
22561
|
+
/thinking <show|hide>`
|
|
22562
|
+
});
|
|
22080
22563
|
return;
|
|
22081
22564
|
}
|
|
22082
|
-
|
|
22083
|
-
|
|
22084
|
-
|
|
22565
|
+
const shown = argument === "show";
|
|
22566
|
+
setShowThinking(shown);
|
|
22567
|
+
if (!shown)
|
|
22568
|
+
setReasoningLive("");
|
|
22569
|
+
push({ kind: "notice", id: nextId(), text: `thinking: ${shown ? "shown" : "hidden"}` });
|
|
22570
|
+
},
|
|
22571
|
+
compact: () => void compactNow(),
|
|
22572
|
+
context: () => {
|
|
22573
|
+
const { tokens, window } = agent3.contextUse;
|
|
22574
|
+
const percent = window > 0 ? Math.round(tokens / window * 100) : 0;
|
|
22575
|
+
const files = agent3.touchedFiles;
|
|
22576
|
+
push({
|
|
22577
|
+
kind: "notice",
|
|
22578
|
+
id: nextId(),
|
|
22579
|
+
text: [
|
|
22580
|
+
` model ${model2}`,
|
|
22581
|
+
` context ~${tokens.toLocaleString()} of ${window.toLocaleString()} tokens (${percent}%)`,
|
|
22582
|
+
` dropped ${compacted} earlier message${compacted === 1 ? "" : "s"} replaced by a summary`,
|
|
22583
|
+
` files ${files.length === 0 ? "none touched yet" : files.join(", ")}`,
|
|
22584
|
+
"",
|
|
22585
|
+
" /compact summarises now rather than waiting for 80%"
|
|
22586
|
+
].join(`
|
|
22587
|
+
`)
|
|
22588
|
+
});
|
|
22589
|
+
},
|
|
22590
|
+
cost: (argument) => {
|
|
22591
|
+
if (argument !== undefined && argument !== "") {
|
|
22592
|
+
const amount = Number.parseFloat(argument.replace(/^\$/, ""));
|
|
22593
|
+
if (Number.isNaN(amount)) {
|
|
22594
|
+
push({
|
|
22595
|
+
kind: "notice",
|
|
22596
|
+
id: nextId(),
|
|
22597
|
+
text: `usage: /cost [usd] - "${argument}" is not an amount`,
|
|
22598
|
+
color: theme.warning
|
|
22599
|
+
});
|
|
22600
|
+
return;
|
|
22601
|
+
}
|
|
22602
|
+
agent3.setBudget(amount > 0 ? amount : undefined);
|
|
22603
|
+
push({
|
|
22604
|
+
kind: "notice",
|
|
22605
|
+
id: nextId(),
|
|
22606
|
+
text: amount > 0 ? `budget: $${amount.toFixed(2)}` : "budget removed"
|
|
22607
|
+
});
|
|
22085
22608
|
return;
|
|
22086
22609
|
}
|
|
22087
|
-
|
|
22610
|
+
const budget = agent3.budgetUsd;
|
|
22611
|
+
push({
|
|
22612
|
+
kind: "notice",
|
|
22613
|
+
id: nextId(),
|
|
22614
|
+
text: ` spent $${agent3.costUsd.toFixed(4)}
|
|
22615
|
+
` + ` budget ${budget === undefined ? "none - /cost <usd> sets one" : `$${budget.toFixed(2)}`}`
|
|
22616
|
+
});
|
|
22617
|
+
},
|
|
22618
|
+
todo: () => {
|
|
22619
|
+
const todos2 = agent3.todos.list();
|
|
22620
|
+
push({
|
|
22621
|
+
kind: "notice",
|
|
22622
|
+
id: nextId(),
|
|
22623
|
+
text: todos2.length === 0 ? "no todos in this session" : todos2.map((todo2) => ` ${todo2.status === "done" ? "x" : todo2.status === "in_progress" ? ">" : " "} ${todo2.text}`).join(`
|
|
22624
|
+
`)
|
|
22625
|
+
});
|
|
22626
|
+
},
|
|
22627
|
+
permissions: () => {
|
|
22628
|
+
const rules2 = agent3.permissionRules;
|
|
22629
|
+
push({
|
|
22630
|
+
kind: "notice",
|
|
22631
|
+
id: nextId(),
|
|
22632
|
+
text: [
|
|
22633
|
+
` mode ${agent3.permissionMode} (/mode changes it)`,
|
|
22634
|
+
...rules2.length === 0 ? [" rules none configured"] : [
|
|
22635
|
+
" rules (deny always wins, whatever the mode or scope)",
|
|
22636
|
+
...rules2.map((rule) => ` ${rule.effect.padEnd(5)} ${rule.source} [${rule.scope}]`)
|
|
22637
|
+
]
|
|
22638
|
+
].join(`
|
|
22639
|
+
`)
|
|
22640
|
+
});
|
|
22641
|
+
},
|
|
22642
|
+
init: () => void runTurn(INIT_PROMPT),
|
|
22643
|
+
mode: (argument) => {
|
|
22644
|
+
if (argument && isPermissionMode(argument)) {
|
|
22645
|
+
agent3.setPermissionMode(argument);
|
|
22646
|
+
setMode(argument);
|
|
22647
|
+
push({ kind: "notice", id: nextId(), text: `permission mode: ${argument}` });
|
|
22648
|
+
} else {
|
|
22649
|
+
push({
|
|
22650
|
+
kind: "notice",
|
|
22651
|
+
id: nextId(),
|
|
22652
|
+
text: `usage: /mode <${PERMISSION_MODES.join("|")}>`,
|
|
22653
|
+
color: theme.warning
|
|
22654
|
+
});
|
|
22655
|
+
}
|
|
22656
|
+
},
|
|
22657
|
+
memory: (argument) => void showMemories(argument),
|
|
22658
|
+
tree: (argument) => void sessionTree("tree", argument),
|
|
22659
|
+
sessions: () => {
|
|
22660
|
+
listSessions(agent3.cwd).then((saved) => setSessionChoices(saved));
|
|
22661
|
+
},
|
|
22662
|
+
rewind: (argument) => void sessionTree("rewind", argument),
|
|
22663
|
+
fork: (argument) => void sessionTree("fork", argument),
|
|
22664
|
+
undo: () => void undoLast(),
|
|
22665
|
+
plan: (argument) => void plan2(argument),
|
|
22666
|
+
skills: () => push({ kind: "notice", id: nextId(), text: describeExtensions(session2) })
|
|
22667
|
+
};
|
|
22668
|
+
const handlersRef = useRef3(handlers);
|
|
22669
|
+
handlersRef.current = handlers;
|
|
22670
|
+
const handleCommand = useCallback2((command) => {
|
|
22671
|
+
const body = command.slice(1).trim();
|
|
22672
|
+
const space = body.search(/\s/);
|
|
22673
|
+
const name = space === -1 ? body : body.slice(0, space);
|
|
22674
|
+
const argument = space === -1 ? undefined : body.slice(space + 1).trim();
|
|
22675
|
+
const spec = findCommand(name);
|
|
22676
|
+
if (spec) {
|
|
22677
|
+
if (spec.idleOnly && busy) {
|
|
22678
|
+
push({
|
|
22679
|
+
kind: "notice",
|
|
22680
|
+
id: nextId(),
|
|
22681
|
+
text: "finish or interrupt the current turn first (esc)",
|
|
22682
|
+
color: theme.warning
|
|
22683
|
+
});
|
|
22088
22684
|
return;
|
|
22089
|
-
if (key2) {
|
|
22090
|
-
secret.current += key2;
|
|
22091
|
-
setInput(secret.current);
|
|
22092
22685
|
}
|
|
22686
|
+
handlersRef.current[spec.name](argument);
|
|
22093
22687
|
return;
|
|
22094
22688
|
}
|
|
22095
|
-
|
|
22096
|
-
|
|
22097
|
-
|
|
22098
|
-
|
|
22099
|
-
|
|
22100
|
-
|
|
22101
|
-
|
|
22102
|
-
|
|
22103
|
-
|
|
22104
|
-
|
|
22105
|
-
|
|
22106
|
-
|
|
22107
|
-
|
|
22108
|
-
|
|
22109
|
-
|
|
22110
|
-
|
|
22111
|
-
|
|
22112
|
-
|
|
22113
|
-
|
|
22114
|
-
|
|
22115
|
-
|
|
22116
|
-
|
|
22117
|
-
|
|
22118
|
-
|
|
22119
|
-
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22125
|
-
|
|
22126
|
-
|
|
22127
|
-
|
|
22128
|
-
|
|
22129
|
-
|
|
22130
|
-
|
|
22131
|
-
|
|
22132
|
-
|
|
22133
|
-
|
|
22134
|
-
|
|
22135
|
-
|
|
22136
|
-
|
|
22137
|
-
|
|
22138
|
-
|
|
22139
|
-
|
|
22140
|
-
|
|
22141
|
-
|
|
22142
|
-
|
|
22143
|
-
|
|
22144
|
-
|
|
22145
|
-
|
|
22146
|
-
|
|
22147
|
-
|
|
22148
|
-
|
|
22149
|
-
|
|
22150
|
-
|
|
22151
|
-
|
|
22152
|
-
|
|
22153
|
-
|
|
22154
|
-
|
|
22155
|
-
|
|
22156
|
-
|
|
22157
|
-
|
|
22158
|
-
|
|
22159
|
-
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22166
|
-
|
|
22167
|
-
|
|
22168
|
-
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
|
|
22172
|
-
|
|
22173
|
-
|
|
22174
|
-
|
|
22175
|
-
|
|
22176
|
-
|
|
22177
|
-
|
|
22178
|
-
|
|
22179
|
-
|
|
22180
|
-
|
|
22181
|
-
|
|
22182
|
-
|
|
22183
|
-
|
|
22184
|
-
|
|
22185
|
-
|
|
22186
|
-
|
|
22187
|
-
|
|
22188
|
-
|
|
22189
|
-
|
|
22190
|
-
|
|
22191
|
-
|
|
22192
|
-
}
|
|
22193
|
-
if (screen.name === "oauth") {
|
|
22194
|
-
return /* @__PURE__ */ jsxDEV11(Box10, {
|
|
22195
|
-
flexDirection: "column",
|
|
22196
|
-
children: [
|
|
22197
|
-
/* @__PURE__ */ jsxDEV11(Header, {}, undefined, false, undefined, this),
|
|
22198
|
-
/* @__PURE__ */ jsxDEV11(Text11, {
|
|
22199
|
-
children: [
|
|
22200
|
-
"signing in to ",
|
|
22201
|
-
screen.provider.id,
|
|
22202
|
-
" in your browser…"
|
|
22203
|
-
]
|
|
22204
|
-
}, undefined, true, undefined, this),
|
|
22205
|
-
screen.url ? /* @__PURE__ */ jsxDEV11(Box10, {
|
|
22206
|
-
marginTop: 1,
|
|
22207
|
-
flexDirection: "column",
|
|
22208
|
-
children: [
|
|
22209
|
-
/* @__PURE__ */ jsxDEV11(Text11, {
|
|
22210
|
-
color: theme.muted,
|
|
22211
|
-
children: "if it did not open, use this link:"
|
|
22212
|
-
}, undefined, false, undefined, this),
|
|
22213
|
-
/* @__PURE__ */ jsxDEV11(Text11, {
|
|
22214
|
-
children: screen.url
|
|
22215
|
-
}, undefined, false, undefined, this)
|
|
22216
|
-
]
|
|
22217
|
-
}, undefined, true, undefined, this) : null,
|
|
22218
|
-
/* @__PURE__ */ jsxDEV11(Box10, {
|
|
22219
|
-
marginTop: 1,
|
|
22220
|
-
children: /* @__PURE__ */ jsxDEV11(Text11, {
|
|
22221
|
-
color: theme.muted,
|
|
22222
|
-
children: "esc cancel"
|
|
22223
|
-
}, undefined, false, undefined, this)
|
|
22224
|
-
}, undefined, false, undefined, this)
|
|
22225
|
-
]
|
|
22226
|
-
}, undefined, true, undefined, this);
|
|
22227
|
-
}
|
|
22228
|
-
if (screen.name === "probing") {
|
|
22229
|
-
return /* @__PURE__ */ jsxDEV11(Box10, {
|
|
22230
|
-
flexDirection: "column",
|
|
22231
|
-
children: [
|
|
22232
|
-
/* @__PURE__ */ jsxDEV11(Header, {}, undefined, false, undefined, this),
|
|
22233
|
-
/* @__PURE__ */ jsxDEV11(Text11, {
|
|
22234
|
-
color: theme.muted,
|
|
22235
|
-
children: [
|
|
22236
|
-
"checking the credentials with ",
|
|
22237
|
-
screen.provider.id,
|
|
22238
|
-
"…"
|
|
22239
|
-
]
|
|
22240
|
-
}, undefined, true, undefined, this)
|
|
22241
|
-
]
|
|
22242
|
-
}, undefined, true, undefined, this);
|
|
22243
|
-
}
|
|
22244
|
-
if (screen.name === "failed") {
|
|
22245
|
-
return /* @__PURE__ */ jsxDEV11(Box10, {
|
|
22246
|
-
flexDirection: "column",
|
|
22247
|
-
children: [
|
|
22248
|
-
/* @__PURE__ */ jsxDEV11(Header, {}, undefined, false, undefined, this),
|
|
22249
|
-
/* @__PURE__ */ jsxDEV11(Text11, {
|
|
22250
|
-
color: theme.warning,
|
|
22251
|
-
children: screen.result.reason === "rejected" ? `${screen.provider.id} rejected that credential. It has not been kept.` : screen.result.reason === "unreachable" ? `could not reach ${screen.provider.id}.` : `${screen.provider.id} said:`
|
|
22252
|
-
}, undefined, false, undefined, this),
|
|
22253
|
-
/* @__PURE__ */ jsxDEV11(Text11, {
|
|
22254
|
-
color: theme.muted,
|
|
22255
|
-
children: screen.result.message
|
|
22256
|
-
}, undefined, false, undefined, this),
|
|
22257
|
-
/* @__PURE__ */ jsxDEV11(Box10, {
|
|
22258
|
-
marginTop: 1,
|
|
22259
|
-
children: /* @__PURE__ */ jsxDEV11(Text11, {
|
|
22260
|
-
color: theme.muted,
|
|
22261
|
-
children: screen.result.reason === "unreachable" ? "k keep it anyway and carry on · esc start over · ctrl-c quit" : "esc start over · ctrl-c quit"
|
|
22262
|
-
}, undefined, false, undefined, this)
|
|
22263
|
-
}, undefined, false, undefined, this)
|
|
22264
|
-
]
|
|
22265
|
-
}, undefined, true, undefined, this);
|
|
22266
|
-
}
|
|
22267
|
-
return /* @__PURE__ */ jsxDEV11(Box10, {
|
|
22689
|
+
const custom = session2.commands.find((entry) => entry.name === name);
|
|
22690
|
+
if (custom) {
|
|
22691
|
+
const prompt = expandCommand(custom, argument ?? "");
|
|
22692
|
+
if (prompt.trim() === "") {
|
|
22693
|
+
push({
|
|
22694
|
+
kind: "notice",
|
|
22695
|
+
id: nextId(),
|
|
22696
|
+
text: `/${name} expanded to nothing`,
|
|
22697
|
+
color: theme.warning
|
|
22698
|
+
});
|
|
22699
|
+
return;
|
|
22700
|
+
}
|
|
22701
|
+
if (busy) {
|
|
22702
|
+
agent3.steer(prompt);
|
|
22703
|
+
setQueued(agent3.pendingSteers);
|
|
22704
|
+
push({ kind: "user", id: nextId(), text: command });
|
|
22705
|
+
return;
|
|
22706
|
+
}
|
|
22707
|
+
runTurn(prompt);
|
|
22708
|
+
return;
|
|
22709
|
+
}
|
|
22710
|
+
push({
|
|
22711
|
+
kind: "notice",
|
|
22712
|
+
id: nextId(),
|
|
22713
|
+
text: `unknown command "${name}"`,
|
|
22714
|
+
color: theme.warning
|
|
22715
|
+
});
|
|
22716
|
+
}, [agent3, busy, push, runTurn, session2]);
|
|
22717
|
+
const submit = useCallback2((text2) => {
|
|
22718
|
+
const entry = menuOpenRef.current ? menuEntriesRef.current[selectedRef.current] : undefined;
|
|
22719
|
+
if (entry) {
|
|
22720
|
+
setInput("");
|
|
22721
|
+
setMenuIndex(0);
|
|
22722
|
+
handleCommand(entry.insert);
|
|
22723
|
+
return;
|
|
22724
|
+
}
|
|
22725
|
+
const trimmed = text2.trim();
|
|
22726
|
+
setInput("");
|
|
22727
|
+
if (trimmed === "")
|
|
22728
|
+
return;
|
|
22729
|
+
if (trimmed.startsWith("/")) {
|
|
22730
|
+
handleCommand(trimmed);
|
|
22731
|
+
return;
|
|
22732
|
+
}
|
|
22733
|
+
setCandidate(detectPreference(trimmed));
|
|
22734
|
+
if (busy) {
|
|
22735
|
+
agent3.steer(trimmed);
|
|
22736
|
+
setQueued(agent3.pendingSteers);
|
|
22737
|
+
push({ kind: "user", id: nextId(), text: trimmed });
|
|
22738
|
+
return;
|
|
22739
|
+
}
|
|
22740
|
+
runTurn(trimmed);
|
|
22741
|
+
}, [agent3, busy, push, runTurn, handleCommand]);
|
|
22742
|
+
const inputActive = !pending && !question && !choosingModel && !choosingReasoning && !sessionChoices;
|
|
22743
|
+
const menuOpen = inputActive && input.startsWith("/") && !input.includes(" ");
|
|
22744
|
+
const entries = menuOpen ? menuEntries(input.slice(1), session2.commands, busy) : [];
|
|
22745
|
+
const selected = Math.min(menuIndex, Math.max(0, entries.length - 1));
|
|
22746
|
+
const menuOpenRef = useRef3(menuOpen);
|
|
22747
|
+
menuOpenRef.current = menuOpen;
|
|
22748
|
+
const menuEntriesRef = useRef3(entries);
|
|
22749
|
+
menuEntriesRef.current = entries;
|
|
22750
|
+
const selectedRef = useRef3(selected);
|
|
22751
|
+
selectedRef.current = selected;
|
|
22752
|
+
useInput7((input_, key2) => {
|
|
22753
|
+
if (menuOpen && entries.length > 0) {
|
|
22754
|
+
if (key2.upArrow) {
|
|
22755
|
+
setMenuIndex((current) => current <= 0 ? entries.length - 1 : current - 1);
|
|
22756
|
+
return;
|
|
22757
|
+
}
|
|
22758
|
+
if (key2.downArrow) {
|
|
22759
|
+
setMenuIndex((current) => current >= entries.length - 1 ? 0 : current + 1);
|
|
22760
|
+
return;
|
|
22761
|
+
}
|
|
22762
|
+
if (key2.tab) {
|
|
22763
|
+
const entry = entries[selected];
|
|
22764
|
+
if (entry)
|
|
22765
|
+
setInput(`${entry.insert} `);
|
|
22766
|
+
setMenuIndex(0);
|
|
22767
|
+
return;
|
|
22768
|
+
}
|
|
22769
|
+
if (key2.escape) {
|
|
22770
|
+
setInput("");
|
|
22771
|
+
setMenuIndex(0);
|
|
22772
|
+
return;
|
|
22773
|
+
}
|
|
22774
|
+
}
|
|
22775
|
+
if (key2.escape) {
|
|
22776
|
+
setCandidate(undefined);
|
|
22777
|
+
if (busy)
|
|
22778
|
+
controller.current?.abort();
|
|
22779
|
+
return;
|
|
22780
|
+
}
|
|
22781
|
+
if (key2.ctrl && candidate && (input_ === "r" || input_ === "g")) {
|
|
22782
|
+
remember(input_ === "r" ? "project" : "user");
|
|
22783
|
+
}
|
|
22784
|
+
}, { isActive: inputActive });
|
|
22785
|
+
return /* @__PURE__ */ jsxDEV14(Box12, {
|
|
22268
22786
|
flexDirection: "column",
|
|
22269
22787
|
children: [
|
|
22270
|
-
/* @__PURE__ */
|
|
22271
|
-
|
|
22272
|
-
children:
|
|
22273
|
-
|
|
22274
|
-
|
|
22275
|
-
|
|
22276
|
-
|
|
22277
|
-
|
|
22788
|
+
/* @__PURE__ */ jsxDEV14(Static, {
|
|
22789
|
+
items,
|
|
22790
|
+
children: (item) => /* @__PURE__ */ jsxDEV14(ScrollRow, {
|
|
22791
|
+
item
|
|
22792
|
+
}, item.id, false, undefined, this)
|
|
22793
|
+
}, undefined, false, undefined, this),
|
|
22794
|
+
choosingModel && modelOptions && /* @__PURE__ */ jsxDEV14(Onboarding, {
|
|
22795
|
+
...modelOptions,
|
|
22796
|
+
wanted: agent3.model.provider.id,
|
|
22797
|
+
wantedModel: model2,
|
|
22798
|
+
embedded: true,
|
|
22799
|
+
defaultScope: "project",
|
|
22800
|
+
onDone: (result) => void finishModelChoice(result)
|
|
22801
|
+
}, undefined, false, undefined, this),
|
|
22802
|
+
choosingReasoning && /* @__PURE__ */ jsxDEV14(ReasoningPicker, {
|
|
22803
|
+
...agent3.reasoningEffort ? { current: agent3.reasoningEffort } : {},
|
|
22804
|
+
onDone: finishReasoningChoice,
|
|
22805
|
+
onCancel: () => setChoosingReasoning(false)
|
|
22806
|
+
}, undefined, false, undefined, this),
|
|
22807
|
+
sessionChoices && /* @__PURE__ */ jsxDEV14(SessionPicker, {
|
|
22808
|
+
sessions: sessionChoices,
|
|
22809
|
+
embedded: true,
|
|
22810
|
+
onDone: (path) => {
|
|
22811
|
+
setSessionChoices(undefined);
|
|
22812
|
+
if (path) {
|
|
22813
|
+
onResume?.(path);
|
|
22814
|
+
exit();
|
|
22815
|
+
}
|
|
22816
|
+
}
|
|
22817
|
+
}, undefined, false, undefined, this),
|
|
22818
|
+
!choosingModel && !choosingReasoning && !sessionChoices && reasoningLive !== "" && showThinking && /* @__PURE__ */ jsxDEV14(Box12, {
|
|
22278
22819
|
marginTop: 1,
|
|
22279
|
-
children: /* @__PURE__ */
|
|
22280
|
-
color: theme.
|
|
22281
|
-
children:
|
|
22820
|
+
children: /* @__PURE__ */ jsxDEV14(Text14, {
|
|
22821
|
+
color: theme.reasoning,
|
|
22822
|
+
children: reasoningLive
|
|
22282
22823
|
}, undefined, false, undefined, this)
|
|
22283
22824
|
}, undefined, false, undefined, this),
|
|
22284
|
-
/* @__PURE__ */
|
|
22825
|
+
!choosingModel && !choosingReasoning && live !== "" && /* @__PURE__ */ jsxDEV14(Box12, {
|
|
22826
|
+
marginTop: 1,
|
|
22827
|
+
children: /* @__PURE__ */ jsxDEV14(Markdown, {
|
|
22828
|
+
text: live
|
|
22829
|
+
}, undefined, false, undefined, this)
|
|
22830
|
+
}, undefined, false, undefined, this),
|
|
22831
|
+
runningTool && /* @__PURE__ */ jsxDEV14(ToolBlock, {
|
|
22832
|
+
name: runningTool,
|
|
22833
|
+
running: true
|
|
22834
|
+
}, undefined, false, undefined, this),
|
|
22835
|
+
!choosingModel && !choosingReasoning && activity && live === "" && !runningTool && !pending && !question && /* @__PURE__ */ jsxDEV14(Box12, {
|
|
22836
|
+
marginTop: 1,
|
|
22837
|
+
children: /* @__PURE__ */ jsxDEV14(Activity, {
|
|
22838
|
+
...activity === "preparing" ? {} : { label: activity === "thinking" ? "Thinking" : "Reasoning" }
|
|
22839
|
+
}, undefined, false, undefined, this)
|
|
22840
|
+
}, undefined, false, undefined, this),
|
|
22841
|
+
pending && /* @__PURE__ */ jsxDEV14(PermissionPrompt, {
|
|
22842
|
+
request: pending.request,
|
|
22843
|
+
reason: pending.reason,
|
|
22844
|
+
onChoice: (choice) => {
|
|
22845
|
+
setPending(undefined);
|
|
22846
|
+
pending.resolve(choice);
|
|
22847
|
+
}
|
|
22848
|
+
}, undefined, false, undefined, this),
|
|
22849
|
+
question && /* @__PURE__ */ jsxDEV14(QuestionPrompt, {
|
|
22850
|
+
question: question.question,
|
|
22851
|
+
...question.options ? { options: question.options } : {},
|
|
22852
|
+
onAnswer: (answer) => {
|
|
22853
|
+
setQuestion(undefined);
|
|
22854
|
+
question.resolve(answer);
|
|
22855
|
+
}
|
|
22856
|
+
}, undefined, false, undefined, this),
|
|
22857
|
+
candidate && inputActive && /* @__PURE__ */ jsxDEV14(MemoryCapture, {
|
|
22858
|
+
candidate
|
|
22859
|
+
}, undefined, false, undefined, this),
|
|
22860
|
+
menuOpen && /* @__PURE__ */ jsxDEV14(CommandMenu, {
|
|
22861
|
+
entries,
|
|
22862
|
+
selected
|
|
22863
|
+
}, undefined, false, undefined, this),
|
|
22864
|
+
inputActive && /* @__PURE__ */ jsxDEV14(Box12, {
|
|
22865
|
+
marginTop: 1,
|
|
22285
22866
|
children: [
|
|
22286
|
-
/* @__PURE__ */
|
|
22867
|
+
/* @__PURE__ */ jsxDEV14(Text14, {
|
|
22287
22868
|
color: theme.user,
|
|
22288
22869
|
children: "> "
|
|
22289
22870
|
}, undefined, false, undefined, this),
|
|
22290
|
-
/* @__PURE__ */
|
|
22871
|
+
/* @__PURE__ */ jsxDEV14(TextInput, {
|
|
22291
22872
|
value: input,
|
|
22292
|
-
onChange:
|
|
22293
|
-
|
|
22873
|
+
onChange: (value) => {
|
|
22874
|
+
setInput(value);
|
|
22875
|
+
setMenuIndex(0);
|
|
22876
|
+
},
|
|
22877
|
+
onSubmit: submit,
|
|
22878
|
+
placeholder: busy ? "steer the agent, or esc to interrupt" : "what should I do?"
|
|
22294
22879
|
}, undefined, false, undefined, this)
|
|
22295
22880
|
]
|
|
22296
|
-
}, undefined, true, undefined, this)
|
|
22881
|
+
}, undefined, true, undefined, this),
|
|
22882
|
+
/* @__PURE__ */ jsxDEV14(StatusLine, {
|
|
22883
|
+
model: model2,
|
|
22884
|
+
...agent3.reasoningEffort ? { reasoningEffort: agent3.reasoningEffort } : {},
|
|
22885
|
+
mode,
|
|
22886
|
+
costUsd: cost,
|
|
22887
|
+
todos,
|
|
22888
|
+
busy,
|
|
22889
|
+
queued,
|
|
22890
|
+
context: context2,
|
|
22891
|
+
compacted
|
|
22892
|
+
}, undefined, false, undefined, this)
|
|
22297
22893
|
]
|
|
22298
22894
|
}, undefined, true, undefined, this);
|
|
22299
22895
|
}
|
|
22300
|
-
function
|
|
22301
|
-
|
|
22302
|
-
|
|
22303
|
-
|
|
22304
|
-
|
|
22305
|
-
|
|
22896
|
+
function ScrollRow({ item }) {
|
|
22897
|
+
if (item.kind === "user") {
|
|
22898
|
+
return /* @__PURE__ */ jsxDEV14(Box12, {
|
|
22899
|
+
marginTop: 1,
|
|
22900
|
+
children: [
|
|
22901
|
+
/* @__PURE__ */ jsxDEV14(Text14, {
|
|
22902
|
+
color: theme.user,
|
|
22903
|
+
children: "> "
|
|
22904
|
+
}, undefined, false, undefined, this),
|
|
22905
|
+
/* @__PURE__ */ jsxDEV14(Text14, {
|
|
22906
|
+
children: item.text
|
|
22907
|
+
}, undefined, false, undefined, this)
|
|
22908
|
+
]
|
|
22909
|
+
}, undefined, true, undefined, this);
|
|
22910
|
+
}
|
|
22911
|
+
if (item.kind === "assistant") {
|
|
22912
|
+
return /* @__PURE__ */ jsxDEV14(Box12, {
|
|
22913
|
+
marginTop: 1,
|
|
22914
|
+
children: /* @__PURE__ */ jsxDEV14(Markdown, {
|
|
22915
|
+
text: item.text
|
|
22916
|
+
}, undefined, false, undefined, this)
|
|
22917
|
+
}, undefined, false, undefined, this);
|
|
22918
|
+
}
|
|
22919
|
+
if (item.kind === "reasoning") {
|
|
22920
|
+
return /* @__PURE__ */ jsxDEV14(Box12, {
|
|
22921
|
+
marginTop: 1,
|
|
22922
|
+
children: /* @__PURE__ */ jsxDEV14(Text14, {
|
|
22923
|
+
color: theme.reasoning,
|
|
22924
|
+
children: item.text
|
|
22925
|
+
}, undefined, false, undefined, this)
|
|
22926
|
+
}, undefined, false, undefined, this);
|
|
22927
|
+
}
|
|
22928
|
+
if (item.kind === "tool") {
|
|
22929
|
+
return /* @__PURE__ */ jsxDEV14(ToolBlock, {
|
|
22930
|
+
name: item.name,
|
|
22931
|
+
...item.title ? { title: item.title } : {},
|
|
22932
|
+
...item.output ? { output: item.output } : {},
|
|
22933
|
+
...item.isError ? { isError: true } : {}
|
|
22934
|
+
}, undefined, false, undefined, this);
|
|
22935
|
+
}
|
|
22936
|
+
return /* @__PURE__ */ jsxDEV14(Box12, {
|
|
22937
|
+
marginTop: 1,
|
|
22938
|
+
children: /* @__PURE__ */ jsxDEV14(Text14, {
|
|
22939
|
+
color: item.color ?? theme.muted,
|
|
22940
|
+
children: item.text
|
|
22306
22941
|
}, undefined, false, undefined, this)
|
|
22307
22942
|
}, undefined, false, undefined, this);
|
|
22308
22943
|
}
|
|
22309
|
-
function
|
|
22310
|
-
|
|
22311
|
-
|
|
22312
|
-
|
|
22313
|
-
|
|
22314
|
-
|
|
22944
|
+
function describeCommands(session2) {
|
|
22945
|
+
const lines = commandRows().map((row) => ` ${row.command.padEnd(34)} ${row.summary}`);
|
|
22946
|
+
if (session2.commands.length > 0) {
|
|
22947
|
+
lines.push("", " commands from this directory:");
|
|
22948
|
+
for (const command of session2.commands) {
|
|
22949
|
+
lines.push(` ${`/${command.name}`.padEnd(34)} ${command.description}`);
|
|
22950
|
+
}
|
|
22951
|
+
}
|
|
22952
|
+
lines.push("", " type / at the prompt to filter this list and pick one");
|
|
22953
|
+
return lines.join(`
|
|
22954
|
+
`);
|
|
22315
22955
|
}
|
|
22316
|
-
|
|
22317
|
-
|
|
22318
|
-
|
|
22319
|
-
|
|
22320
|
-
|
|
22321
|
-
|
|
22322
|
-
|
|
22956
|
+
var INIT_PROMPT = `Write an AGENTS.md at the root of this project for a coding agent that has never seen it.
|
|
22957
|
+
|
|
22958
|
+
Read enough of the repository first to be accurate. Cover: what the project is, how it is laid out, the commands to build, test and lint it, and the conventions and rules that are not obvious from the code. Prefer rules that prevent a specific failure, and say what the failure is. If an AGENTS.md or CLAUDE.md already exists, improve it in place rather than replacing it.`;
|
|
22959
|
+
function describeExtensions(session2) {
|
|
22960
|
+
const lines = [];
|
|
22961
|
+
if (session2.skills.length > 0) {
|
|
22962
|
+
lines.push("skills (the agent loads these itself when they fit):");
|
|
22963
|
+
for (const skill of session2.skills) {
|
|
22964
|
+
lines.push(` ${skill.name} [${skill.scope}] ${skill.description}`);
|
|
22965
|
+
}
|
|
22966
|
+
}
|
|
22967
|
+
if (session2.commands.length > 0) {
|
|
22968
|
+
if (lines.length > 0)
|
|
22969
|
+
lines.push("");
|
|
22970
|
+
lines.push("commands you can type:");
|
|
22971
|
+
for (const command of session2.commands) {
|
|
22972
|
+
lines.push(` /${command.name} [${command.scope}] ${command.description}`);
|
|
22973
|
+
}
|
|
22974
|
+
}
|
|
22975
|
+
return lines.length === 0 ? "no skills or commands found in .earshot/skills, .earshot/commands or your config directory" : lines.join(`
|
|
22976
|
+
`);
|
|
22323
22977
|
}
|
|
22324
22978
|
// packages/tui/src/run.tsx
|
|
22325
22979
|
import { platform as platform6 } from "node:os";
|
|
22326
22980
|
import { render } from "ink";
|
|
22327
|
-
import { jsxDEV as
|
|
22981
|
+
import { jsxDEV as jsxDEV15 } from "react/jsx-dev-runtime";
|
|
22328
22982
|
var WINDOWS_MAX_FPS = 30;
|
|
22329
22983
|
async function runTui(options) {
|
|
22330
22984
|
const isWindows = platform6() === "win32";
|
|
22331
|
-
|
|
22985
|
+
let resumePath;
|
|
22986
|
+
const instance = render(/* @__PURE__ */ jsxDEV15(App, {
|
|
22332
22987
|
session: options.session,
|
|
22333
22988
|
model: options.model,
|
|
22334
|
-
...options.initialPrompt ? { initialPrompt: options.initialPrompt } : {}
|
|
22989
|
+
...options.initialPrompt ? { initialPrompt: options.initialPrompt } : {},
|
|
22990
|
+
...options.modelOptions ? { modelOptions: options.modelOptions } : {},
|
|
22991
|
+
onResume: (path) => {
|
|
22992
|
+
resumePath = path;
|
|
22993
|
+
}
|
|
22335
22994
|
}, undefined, false, undefined, this), {
|
|
22336
22995
|
exitOnCtrlC: false,
|
|
22337
22996
|
patchConsole: true,
|
|
@@ -22342,12 +23001,12 @@ async function runTui(options) {
|
|
|
22342
23001
|
} finally {
|
|
22343
23002
|
await options.session.dispose();
|
|
22344
23003
|
}
|
|
22345
|
-
return 0;
|
|
23004
|
+
return { exitCode: 0, ...resumePath ? { resumePath } : {} };
|
|
22346
23005
|
}
|
|
22347
23006
|
async function runOnboarding(options) {
|
|
22348
23007
|
const isWindows = platform6() === "win32";
|
|
22349
23008
|
let result = { outcome: "quit" };
|
|
22350
|
-
const instance = render(/* @__PURE__ */
|
|
23009
|
+
const instance = render(/* @__PURE__ */ jsxDEV15(Onboarding, {
|
|
22351
23010
|
...options,
|
|
22352
23011
|
onDone: (decided) => {
|
|
22353
23012
|
result = decided;
|
|
@@ -22360,27 +23019,47 @@ async function runOnboarding(options) {
|
|
|
22360
23019
|
await instance.waitUntilExit();
|
|
22361
23020
|
return result;
|
|
22362
23021
|
}
|
|
23022
|
+
async function runSessionPicker(sessions) {
|
|
23023
|
+
const isWindows = platform6() === "win32";
|
|
23024
|
+
let selected;
|
|
23025
|
+
const instance = render(/* @__PURE__ */ jsxDEV15(SessionPicker, {
|
|
23026
|
+
sessions,
|
|
23027
|
+
onDone: (path) => {
|
|
23028
|
+
selected = path;
|
|
23029
|
+
}
|
|
23030
|
+
}, undefined, false, undefined, this), { exitOnCtrlC: false, patchConsole: true, ...isWindows ? { maxFps: WINDOWS_MAX_FPS } : {} });
|
|
23031
|
+
await instance.waitUntilExit();
|
|
23032
|
+
return selected;
|
|
23033
|
+
}
|
|
22363
23034
|
// packages/cli/src/onboard.ts
|
|
22364
|
-
async function buildOnboardingOptions(wanted) {
|
|
23035
|
+
async function buildOnboardingOptions(wanted, wantedModel) {
|
|
22365
23036
|
const registry2 = buildRegistry();
|
|
22366
23037
|
const store3 = new AuthStore;
|
|
23038
|
+
const cwd = process.cwd();
|
|
23039
|
+
const settings2 = await loadSettings(cwd);
|
|
22367
23040
|
const providers = [];
|
|
22368
23041
|
for (const provider of registry2.list()) {
|
|
22369
23042
|
if (provider.auth.kind === "none")
|
|
22370
23043
|
continue;
|
|
22371
23044
|
providers.push(await describe3(provider, store3));
|
|
22372
23045
|
}
|
|
22373
|
-
providers.sort((a, b) => Number(b.kind === "oauth") - Number(a.kind === "oauth"));
|
|
23046
|
+
providers.sort((a, b) => Number(Boolean(b.configured)) - Number(Boolean(a.configured)) || Number(b.kind === "oauth") - Number(a.kind === "oauth"));
|
|
22374
23047
|
return {
|
|
22375
23048
|
providers,
|
|
22376
23049
|
...wanted ? { wanted } : {},
|
|
23050
|
+
...wantedModel ? { wantedModel } : {},
|
|
22377
23051
|
storeKey: (providerId, key2) => store3.set(providerId, { type: "api-key", apiKey: key2 }),
|
|
22378
23052
|
forgetKey: (providerId) => store3.remove(providerId),
|
|
22379
23053
|
signIn: async (providerId, onUrl) => {
|
|
22380
23054
|
const credentials = await loginToOpenRouter({ onUrl });
|
|
22381
23055
|
await store3.set(providerId, credentials);
|
|
22382
23056
|
},
|
|
22383
|
-
probe: (providerId) => probe(registry2, providerId)
|
|
23057
|
+
probe: (providerId, modelId) => probe(registry2, providerId, modelId),
|
|
23058
|
+
reasoningFor: (model2) => settings2.reasoningEfforts[model2],
|
|
23059
|
+
remember: async (model2, effort, scope2) => {
|
|
23060
|
+
await persistDefaultModel(model2, scope2, cwd);
|
|
23061
|
+
await persistReasoningEffort(model2, effort, scope2, cwd);
|
|
23062
|
+
}
|
|
22384
23063
|
};
|
|
22385
23064
|
}
|
|
22386
23065
|
async function describe3(provider, store3) {
|
|
@@ -22389,6 +23068,11 @@ async function describe3(provider, store3) {
|
|
|
22389
23068
|
});
|
|
22390
23069
|
return {
|
|
22391
23070
|
id: provider.id,
|
|
23071
|
+
models: provider.models().map((model2) => ({
|
|
23072
|
+
id: model2.id,
|
|
23073
|
+
name: model2.name,
|
|
23074
|
+
reasoning: model2.capabilities.reasoning
|
|
23075
|
+
})),
|
|
22392
23076
|
kind: provider.auth.kind === "oauth" ? "oauth" : "api-key",
|
|
22393
23077
|
...envVarsOf2(provider.auth).length ? { envVars: envVarsOf2(provider.auth) } : {},
|
|
22394
23078
|
...configured ? { configured: describeConfigured(configured.type) } : {}
|
|
@@ -22400,16 +23084,16 @@ function envVarsOf2(auth2) {
|
|
|
22400
23084
|
function describeConfigured(kind) {
|
|
22401
23085
|
return kind === "ambient" ? "ambient credentials" : kind === "oauth" ? "signed in" : "api key set";
|
|
22402
23086
|
}
|
|
22403
|
-
async function probe(registry2, providerId) {
|
|
23087
|
+
async function probe(registry2, providerId, modelId) {
|
|
22404
23088
|
const listed = registry2.list().find((provider) => provider.id === providerId);
|
|
22405
23089
|
if (!listed)
|
|
22406
23090
|
return { ok: false, reason: "other", message: `unknown provider "${providerId}"` };
|
|
22407
|
-
const model2 = listed.models()
|
|
23091
|
+
const model2 = listed.models().find((candidate) => candidate.id === modelId);
|
|
22408
23092
|
if (!model2) {
|
|
22409
23093
|
return {
|
|
22410
23094
|
ok: false,
|
|
22411
23095
|
reason: "other",
|
|
22412
|
-
message: `${providerId}
|
|
23096
|
+
message: `${providerId} does not publish model "${modelId}"`
|
|
22413
23097
|
};
|
|
22414
23098
|
}
|
|
22415
23099
|
let resolved;
|
|
@@ -22444,7 +23128,6 @@ async function probe(registry2, providerId) {
|
|
|
22444
23128
|
}
|
|
22445
23129
|
|
|
22446
23130
|
// packages/cli/src/commands/interactive.ts
|
|
22447
|
-
var DEFAULT_MODEL3 = "anthropic/claude-opus-5";
|
|
22448
23131
|
async function interactiveCommand(args) {
|
|
22449
23132
|
const flags = args.flags;
|
|
22450
23133
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
@@ -22485,9 +23168,14 @@ async function interactiveCommand(args) {
|
|
|
22485
23168
|
return 2;
|
|
22486
23169
|
}
|
|
22487
23170
|
const extensions = await startExtensions(process.cwd());
|
|
22488
|
-
|
|
23171
|
+
let model2 = typeof flags.model === "string" ? flags.model : undefined;
|
|
23172
|
+
let reasoningEffort = parseReasoningEffort2(flags["reasoning-effort"]);
|
|
23173
|
+
if (reasoningEffort === "invalid") {
|
|
23174
|
+
process.stderr.write(`"${flags["reasoning-effort"]}" is not a reasoning effort
|
|
23175
|
+
`);
|
|
23176
|
+
return 2;
|
|
23177
|
+
}
|
|
22489
23178
|
const onboardingAllowed = flags["no-onboarding"] !== true;
|
|
22490
|
-
let firstPrompt = initialPrompt;
|
|
22491
23179
|
let attempted = false;
|
|
22492
23180
|
for (;; ) {
|
|
22493
23181
|
try {
|
|
@@ -22496,30 +23184,47 @@ async function interactiveCommand(args) {
|
|
|
22496
23184
|
extraTools: extensions.tools,
|
|
22497
23185
|
problems: extensions.problems,
|
|
22498
23186
|
onDispose: () => extensions.close(),
|
|
22499
|
-
model: model2,
|
|
23187
|
+
...model2 ? { model: model2 } : {},
|
|
23188
|
+
...reasoningEffort !== undefined ? { reasoningEffort } : {},
|
|
22500
23189
|
...mode ? { mode } : {},
|
|
22501
23190
|
...typeof flags["api-key"] === "string" ? { apiKey: flags["api-key"] } : {},
|
|
22502
23191
|
...curiosity ? { curiosity } : {},
|
|
22503
23192
|
...maxCostUsd !== undefined ? { maxCostUsd } : {},
|
|
22504
23193
|
...resumeFrom2(flags)
|
|
22505
23194
|
});
|
|
22506
|
-
|
|
23195
|
+
const tui = await runTui({
|
|
22507
23196
|
session: session2,
|
|
22508
|
-
model:
|
|
22509
|
-
|
|
22510
|
-
|
|
23197
|
+
model: `${session2.agent.model.provider.id}/${session2.agent.model.model.id}`,
|
|
23198
|
+
modelOptions: await buildOnboardingOptions(),
|
|
23199
|
+
...initialPrompt !== "" || image ? {
|
|
23200
|
+
initialPrompt: image ? [
|
|
23201
|
+
...initialPrompt ? [{ type: "text", text: initialPrompt }] : [],
|
|
23202
|
+
image
|
|
23203
|
+
] : initialPrompt
|
|
22511
23204
|
} : {}
|
|
22512
23205
|
});
|
|
23206
|
+
if (tui.resumePath) {
|
|
23207
|
+
return interactiveCommand({
|
|
23208
|
+
command: undefined,
|
|
23209
|
+
flags: { ...flags, resume: tui.resumePath, continue: false },
|
|
23210
|
+
positionals: []
|
|
23211
|
+
});
|
|
23212
|
+
}
|
|
23213
|
+
return tui.exitCode;
|
|
22513
23214
|
} catch (error) {
|
|
22514
23215
|
if (error instanceof MissingCredentialsError && onboardingAllowed && !attempted) {
|
|
22515
23216
|
attempted = true;
|
|
22516
|
-
const result = await runOnboarding(await buildOnboardingOptions(error.provider.id));
|
|
23217
|
+
const result = await runOnboarding(await buildOnboardingOptions(error.provider.id, model2));
|
|
22517
23218
|
if (result.outcome === "quit") {
|
|
22518
23219
|
process.stdout.write("nothing was stored. run `earshot auth login <provider>` when you are ready.\n");
|
|
22519
23220
|
await extensions.close();
|
|
22520
23221
|
return 0;
|
|
22521
23222
|
}
|
|
22522
|
-
|
|
23223
|
+
if (result.model) {
|
|
23224
|
+
model2 = result.model;
|
|
23225
|
+
reasoningEffort = result.reasoningEffort;
|
|
23226
|
+
await (await buildOnboardingOptions()).remember?.(result.model, result.reasoningEffort, "global");
|
|
23227
|
+
}
|
|
22523
23228
|
continue;
|
|
22524
23229
|
}
|
|
22525
23230
|
await extensions.close();
|
|
@@ -22544,6 +23249,13 @@ run \`earshot models\` to see what is available
|
|
|
22544
23249
|
}
|
|
22545
23250
|
}
|
|
22546
23251
|
}
|
|
23252
|
+
function parseReasoningEffort2(value) {
|
|
23253
|
+
if (value === undefined)
|
|
23254
|
+
return;
|
|
23255
|
+
if (typeof value !== "string")
|
|
23256
|
+
return "invalid";
|
|
23257
|
+
return ["none", "low", "medium", "high", "xhigh"].includes(value) ? value : value === "auto" ? null : "invalid";
|
|
23258
|
+
}
|
|
22547
23259
|
function resumeFrom2(flags) {
|
|
22548
23260
|
if (typeof flags.resume === "string")
|
|
22549
23261
|
return { resume: { path: flags.resume } };
|
|
@@ -22663,6 +23375,29 @@ ${models.length} models across ${new Set(models.map((m) => m.providerId)).size}
|
|
|
22663
23375
|
return 0;
|
|
22664
23376
|
}
|
|
22665
23377
|
|
|
23378
|
+
// packages/cli/src/commands/sessions.ts
|
|
23379
|
+
async function sessionsCommand(args) {
|
|
23380
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
23381
|
+
process.stderr.write(`earshot sessions needs an interactive terminal.
|
|
23382
|
+
`);
|
|
23383
|
+
return 2;
|
|
23384
|
+
}
|
|
23385
|
+
const sessions2 = await listSessions(process.cwd());
|
|
23386
|
+
if (sessions2.length === 0) {
|
|
23387
|
+
process.stdout.write(`no saved chats for this project
|
|
23388
|
+
`);
|
|
23389
|
+
return 0;
|
|
23390
|
+
}
|
|
23391
|
+
const path = await runSessionPicker(sessions2);
|
|
23392
|
+
if (!path)
|
|
23393
|
+
return 0;
|
|
23394
|
+
return interactiveCommand({
|
|
23395
|
+
command: undefined,
|
|
23396
|
+
flags: { ...args.flags, resume: path },
|
|
23397
|
+
positionals: []
|
|
23398
|
+
});
|
|
23399
|
+
}
|
|
23400
|
+
|
|
22666
23401
|
// packages/cli/src/commands/update.ts
|
|
22667
23402
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
22668
23403
|
import { createHash as createHash4 } from "node:crypto";
|
|
@@ -23048,6 +23783,7 @@ Usage
|
|
|
23048
23783
|
earshot acp serve editor clients over ACP v1 on stdio
|
|
23049
23784
|
earshot doctor diagnose the local setup
|
|
23050
23785
|
earshot update [--check] update earshot to the latest release
|
|
23786
|
+
earshot sessions browse and resume saved chats for this project
|
|
23051
23787
|
|
|
23052
23788
|
Flags
|
|
23053
23789
|
--model <provider/model> model for this session
|
|
@@ -23059,6 +23795,7 @@ Flags
|
|
|
23059
23795
|
--image <path|https-url> attach one PNG, JPEG, GIF or WebP image
|
|
23060
23796
|
--max-cost <usd> stop and ask before spending past this
|
|
23061
23797
|
--curiosity <level> low, normal or high: how readily it asks
|
|
23798
|
+
--reasoning-effort <level> auto | none | low | medium | high | xhigh
|
|
23062
23799
|
--version, -v print the version
|
|
23063
23800
|
--help, -h print this help
|
|
23064
23801
|
`;
|
|
@@ -23089,6 +23826,8 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
23089
23826
|
return doctorCommand(args);
|
|
23090
23827
|
if (command === "update")
|
|
23091
23828
|
return updateCommand(args);
|
|
23829
|
+
if (command === "sessions")
|
|
23830
|
+
return sessionsCommand(args);
|
|
23092
23831
|
if (command === "acp")
|
|
23093
23832
|
return acpCommand(args);
|
|
23094
23833
|
if (command) {
|
|
@@ -23103,5 +23842,5 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
23103
23842
|
var code = await main();
|
|
23104
23843
|
process.exitCode = code;
|
|
23105
23844
|
|
|
23106
|
-
//# debugId=
|
|
23845
|
+
//# debugId=BF0091864A65A6E164756E2164756E21
|
|
23107
23846
|
//# sourceMappingURL=main.js.map
|