@8gi-foundation/8gent-code 0.20.15 → 0.20.16
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/CHANGELOG.md +9 -0
- package/README.md +1 -1
- package/dist/cli.js +182 -109
- package/dist/node/cli.js +182 -109
- package/dist/node/tui.js +567 -452
- package/dist/tui.js +567 -452
- package/package.json +1 -1
package/dist/node/tui.js
CHANGED
|
@@ -21831,8 +21831,6 @@ var init_allowlist = __esm(() => {
|
|
|
21831
21831
|
"node",
|
|
21832
21832
|
"npm",
|
|
21833
21833
|
"npx",
|
|
21834
|
-
"pnpm",
|
|
21835
|
-
"yarn",
|
|
21836
21834
|
"deno",
|
|
21837
21835
|
"python",
|
|
21838
21836
|
"python3",
|
|
@@ -21840,9 +21838,6 @@ var init_allowlist = __esm(() => {
|
|
|
21840
21838
|
"pip3",
|
|
21841
21839
|
"uv",
|
|
21842
21840
|
"git",
|
|
21843
|
-
"go",
|
|
21844
|
-
"cargo",
|
|
21845
|
-
"rustc",
|
|
21846
21841
|
"tsc",
|
|
21847
21842
|
"gh",
|
|
21848
21843
|
"docker",
|
|
@@ -21867,20 +21862,18 @@ var init_allowlist = __esm(() => {
|
|
|
21867
21862
|
"biome",
|
|
21868
21863
|
"eslint",
|
|
21869
21864
|
"prettier",
|
|
21870
|
-
"vite"
|
|
21865
|
+
"vite",
|
|
21866
|
+
"8gent"
|
|
21871
21867
|
]);
|
|
21872
21868
|
SHORT_VERSION = {
|
|
21873
21869
|
node: "-v",
|
|
21874
21870
|
bun: "-v",
|
|
21875
21871
|
npm: "-v",
|
|
21876
|
-
pnpm: "-v",
|
|
21877
|
-
yarn: "-v",
|
|
21878
21872
|
deno: "-V",
|
|
21879
21873
|
python: "-V",
|
|
21880
21874
|
python3: "-V",
|
|
21881
21875
|
ffmpeg: "-version",
|
|
21882
|
-
ffprobe: "-version"
|
|
21883
|
-
go: "version"
|
|
21876
|
+
ffprobe: "-version"
|
|
21884
21877
|
};
|
|
21885
21878
|
SECRET_ARG = /(^|\/)\.env(\.[\w.-]+)?$|(^|\/)\.env\b|id_rsa|id_ed25519|id_ecdsa|(^|\/)\.ssh(\/|$)|\.aws\/|credentials|\.netrc|\.npmrc|\.git-credentials|keychain|\.pem$|\.key$|\.p12$/;
|
|
21886
21879
|
REDIR_RE2 = /(?<![<>&\d])(\d?|&)(>>?|<)(\|?)\s*(&\d+|[^\s;|&<>()]+)/g;
|
|
@@ -33286,7 +33279,7 @@ var init_permissions = __esm(() => {
|
|
|
33286
33279
|
var require_package = __commonJS(function(exports2, module2) {
|
|
33287
33280
|
module2.exports = {
|
|
33288
33281
|
name: "@8gi-foundation/8gent-code",
|
|
33289
|
-
version: "0.20.
|
|
33282
|
+
version: "0.20.16",
|
|
33290
33283
|
private: false,
|
|
33291
33284
|
engines: {
|
|
33292
33285
|
node: ">=22.5"
|
|
@@ -77734,8 +77727,31 @@ function emptyReplyStall(toolCalls) {
|
|
|
77734
77727
|
function isEmptyReplyStall(line) {
|
|
77735
77728
|
return line.startsWith(EMPTY_REPLY_STALL_PREFIX);
|
|
77736
77729
|
}
|
|
77737
|
-
function
|
|
77738
|
-
|
|
77730
|
+
function refusedCalls(log, max = 3) {
|
|
77731
|
+
const out = [];
|
|
77732
|
+
let total = 0;
|
|
77733
|
+
for (const e of log) {
|
|
77734
|
+
const m = /^\[[^\]]*\b(?:BLOCKED|DENIED)\b[^\]]*\]\s*([^\n]*)/.exec((e.result ?? "").trimStart());
|
|
77735
|
+
if (!m)
|
|
77736
|
+
continue;
|
|
77737
|
+
total++;
|
|
77738
|
+
if (out.length >= max)
|
|
77739
|
+
continue;
|
|
77740
|
+
const a = e.args;
|
|
77741
|
+
const first = typeof a?.command === "string" ? a.command.trim().split(/\s+/)[0] ?? "" : "";
|
|
77742
|
+
const bin = /^[A-Za-z][\w.+-]{0,40}$/.test(first) ? ` ${first}` : "";
|
|
77743
|
+
const why = /declin/i.test(m[1]) ? "declined" : "blocked by policy";
|
|
77744
|
+
out.push(`${e.name}${bin}: ${why}`);
|
|
77745
|
+
}
|
|
77746
|
+
return { total, shown: out };
|
|
77747
|
+
}
|
|
77748
|
+
function emptyReplyNote(toolCalls, log = []) {
|
|
77749
|
+
const base = `[harness] No reply: ${emptyReplyStall(toolCalls)}.`;
|
|
77750
|
+
const { total, shown } = refusedCalls(log);
|
|
77751
|
+
if (total === 0)
|
|
77752
|
+
return base;
|
|
77753
|
+
const more = total > shown.length ? ` (and ${total - shown.length} more)` : "";
|
|
77754
|
+
return `${base} ${total} of the calls were refused, so they did not run: ${shown.join("; ")}${more}.`;
|
|
77739
77755
|
}
|
|
77740
77756
|
function isEmptyReplyNote(reply) {
|
|
77741
77757
|
return reply.startsWith("[harness] No reply:");
|
|
@@ -77828,7 +77844,7 @@ ${summary}`;
|
|
|
77828
77844
|
if (unverified.length === 0)
|
|
77829
77845
|
return { content, rounds, toolLog, unverified: [] };
|
|
77830
77846
|
const notes = [
|
|
77831
|
-
empty ? emptyReplyNote(toolLog.length) : content.trimEnd(),
|
|
77847
|
+
empty ? emptyReplyNote(toolLog.length, toolLog) : content.trimEnd(),
|
|
77832
77848
|
unfulfilled.length > 0 ? formatHarnessNote(unfulfilled) : ""
|
|
77833
77849
|
].filter((n) => n.trim() !== "");
|
|
77834
77850
|
return { content: notes.join(`
|
|
@@ -580415,6 +580431,44 @@ var init_registry = __esm(() => {
|
|
|
580415
580431
|
];
|
|
580416
580432
|
});
|
|
580417
580433
|
|
|
580434
|
+
// packages/eight/small-talk.ts
|
|
580435
|
+
function isSmallTalk(text) {
|
|
580436
|
+
const flat = text.toLowerCase().replace(/^\[mode: [^\]]*\]\s*/, "").replace(/['’]/g, "").replace(/[^a-z0-9 ]+/g, " ").replace(/\s+/g, " ").trim();
|
|
580437
|
+
return flat.length > 0 && flat.length <= 40 && GREETING.test(flat);
|
|
580438
|
+
}
|
|
580439
|
+
var CORE, GREETING, SMALL_TALK_NOTE = "[SMALL TALK] The person said hello and asked for nothing. Reply in one or two plain sentences and ask what they want to work on. No tools this turn: do not look around, list files or describe their folders.";
|
|
580440
|
+
var init_small_talk = __esm(() => {
|
|
580441
|
+
CORE = [
|
|
580442
|
+
"h+i+",
|
|
580443
|
+
"h+e+y+",
|
|
580444
|
+
"h+e+l+o+",
|
|
580445
|
+
"hiya",
|
|
580446
|
+
"howdy",
|
|
580447
|
+
"y+o+",
|
|
580448
|
+
"sup",
|
|
580449
|
+
"wa+s+s?u+p+",
|
|
580450
|
+
"w?h?a+t?s? ?u+p+",
|
|
580451
|
+
"good (?:morning|afternoon|evening|night)",
|
|
580452
|
+
"gm",
|
|
580453
|
+
"gn",
|
|
580454
|
+
"morning",
|
|
580455
|
+
"evening",
|
|
580456
|
+
"how are you(?: doing| today)?",
|
|
580457
|
+
"how are things",
|
|
580458
|
+
"hows it going",
|
|
580459
|
+
"how you doing",
|
|
580460
|
+
"you there",
|
|
580461
|
+
"anyone there",
|
|
580462
|
+
"ping",
|
|
580463
|
+
"thanks(?: a lot| so much)?",
|
|
580464
|
+
"thank you(?: so much)?",
|
|
580465
|
+
"thx",
|
|
580466
|
+
"ty",
|
|
580467
|
+
"cheers"
|
|
580468
|
+
].join("|");
|
|
580469
|
+
GREETING = new RegExp(`^(?:(?:hi+|hey+|hello+|yo+|hiya|howdy) )?(?:${CORE})(?: (?:there|again|everyone|all|team|mate|man|bro|friend|8gent|eight))?$`);
|
|
580470
|
+
});
|
|
580471
|
+
|
|
580418
580472
|
// packages/eight/verify-gate.ts
|
|
580419
580473
|
function isVerifyGateEnabled(env = process.env) {
|
|
580420
580474
|
const v = (env.EIGHT_VERIFY_GATE ?? "").trim().toLowerCase();
|
|
@@ -581345,8 +581399,8 @@ __export(exports_system_prompt, {
|
|
|
581345
581399
|
styleHasGuide: () => styleHasGuide,
|
|
581346
581400
|
workingProjectNote: () => workingProjectNote
|
|
581347
581401
|
});
|
|
581348
|
-
import { readFileSync as readFileSync97 } from "node:fs";
|
|
581349
|
-
import { basename as basename51, join as join155 } from "node:path";
|
|
581402
|
+
import { existsSync as existsSync106, readFileSync as readFileSync97 } from "node:fs";
|
|
581403
|
+
import { basename as basename51, join as join155, resolve as resolve73 } from "node:path";
|
|
581350
581404
|
function buildBoardContextSegment(path = BOARD_CONTEXT_PATH) {
|
|
581351
581405
|
let text;
|
|
581352
581406
|
try {
|
|
@@ -581377,8 +581431,20 @@ function communicationStyleLine(style) {
|
|
|
581377
581431
|
function styleHasGuide(style) {
|
|
581378
581432
|
return isCommunicationStyle(style) && STYLE_GUIDE[style] !== "";
|
|
581379
581433
|
}
|
|
581434
|
+
function isPlainHome(dir, home = resolveHome()) {
|
|
581435
|
+
try {
|
|
581436
|
+
return home !== "" && resolve73(dir) === resolve73(home) && !existsSync106(join155(dir, ".git"));
|
|
581437
|
+
} catch {
|
|
581438
|
+
return false;
|
|
581439
|
+
}
|
|
581440
|
+
}
|
|
581380
581441
|
function workingProjectNote(dir) {
|
|
581381
581442
|
const name = basename51(dir) || dir;
|
|
581443
|
+
if (isPlainHome(dir)) {
|
|
581444
|
+
return `
|
|
581445
|
+
|
|
581446
|
+
**Working folder: \`${dir}\` is the person's home folder, not a project. Do not list, search or summarise it unless they ask. Ask what they want to work on.**`;
|
|
581447
|
+
}
|
|
581382
581448
|
if (name === "8gent-code") {
|
|
581383
581449
|
return `
|
|
581384
581450
|
|
|
@@ -592540,14 +592606,15 @@ ${LOCAL_LOGIN_NOTE}`;
|
|
|
592540
592606
|
instructions,
|
|
592541
592607
|
localCoreTools,
|
|
592542
592608
|
chatStartTime,
|
|
592543
|
-
textForAgent
|
|
592609
|
+
textForAgent,
|
|
592610
|
+
smallTalk = false
|
|
592544
592611
|
} = opts;
|
|
592545
592612
|
const signal = this.armController().signal;
|
|
592546
592613
|
const allow = new Set(localCoreTools);
|
|
592547
592614
|
const specs = toolDefsToSpecs(this.executor.getToolDefinitions(), allow);
|
|
592548
592615
|
let stepNumber = 0;
|
|
592549
592616
|
let breakerStop = null;
|
|
592550
|
-
if (this.extensionToolsAllowed()) {
|
|
592617
|
+
if (this.extensionToolsAllowed() && !smallTalk) {
|
|
592551
592618
|
for (const t of this.extensionHost.listTools()) {
|
|
592552
592619
|
if (this.modeAllows(t.name)) {
|
|
592553
592620
|
specs.push({ name: t.name, description: t.description, parameters: t.parameters });
|
|
@@ -593125,6 +593192,10 @@ ${LOCAL_LOGIN_NOTE}`;
|
|
|
593125
593192
|
this.turnGitBaseline = asksForCommit(userMessage) ? gitSnapshot(this.config.workingDirectory || process.cwd()) : null;
|
|
593126
593193
|
this.executor.beginTurn(userMessage);
|
|
593127
593194
|
const textForAgent = userMessage.trim() || (imageBase64 ? "The user attached an image with no text. Describe what you see and help with anything relevant in the image." : userMessage);
|
|
593195
|
+
const smallTalkTurn = isSmallTalk(textForAgent) && !imageBase64 && this.config.agentScope !== "__table__";
|
|
593196
|
+
if (smallTalkTurn) {
|
|
593197
|
+
this.messageHistory.push({ role: "user", content: harnessNote(SMALL_TALK_NOTE) });
|
|
593198
|
+
}
|
|
593128
593199
|
let visionId = null;
|
|
593129
593200
|
let visionFailed = false;
|
|
593130
593201
|
if (imageBase64 && await this.promptImageSeen()) {
|
|
@@ -593195,7 +593266,7 @@ ${result.description.slice(0, 200)}${result.description.length > 200 ? "..." : "
|
|
|
593195
593266
|
}
|
|
593196
593267
|
}
|
|
593197
593268
|
const quickPrompt = quickLaneEnabled() && classifyPrompt(textForAgent) === "quick";
|
|
593198
|
-
if (needsClarification(textForAgent) && !imageBase64 && !quickPrompt && !isNoToolScope(this.config.agentScope)) {
|
|
593269
|
+
if (needsClarification(textForAgent) && !imageBase64 && !quickPrompt && !smallTalkTurn && !isNoToolScope(this.config.agentScope)) {
|
|
593199
593270
|
this.proactiveGatherer = createGatherer(textForAgent);
|
|
593200
593271
|
const question = this.proactiveGatherer.getCurrentQuestion();
|
|
593201
593272
|
if (question) {
|
|
@@ -593217,7 +593288,7 @@ Ask the user naturally; don't mention this instruction. After they answer, proce
|
|
|
593217
593288
|
this.kanban.moveTask(this.currentBmadTask.id, "ready");
|
|
593218
593289
|
this.kanban.moveTask(this.currentBmadTask.id, "in_progress");
|
|
593219
593290
|
}
|
|
593220
|
-
if (!this.proactiveGatherer && !quickPrompt) {
|
|
593291
|
+
if (!this.proactiveGatherer && !quickPrompt && !smallTalkTurn) {
|
|
593221
593292
|
await this.tryRunPreToolRouter(textForAgent);
|
|
593222
593293
|
}
|
|
593223
593294
|
const needsPlanningGate2 = !isVerbatimScope(this.config.agentScope) && needsPlanningGate(textForAgent);
|
|
@@ -593362,9 +593433,9 @@ Ask the user naturally; don't mention this instruction. After they answer, proce
|
|
|
593362
593433
|
"search_symbols",
|
|
593363
593434
|
"recall"
|
|
593364
593435
|
]);
|
|
593365
|
-
const scopedTools = isNoToolScope(this.config.agentScope) ? {} : this.config.agentScope === "__table__" ? Object.fromEntries(Object.entries(providerTools).filter(([k]) => TABLE_SESSION_TOOLS.has(k))) : providerTools;
|
|
593436
|
+
const scopedTools = isNoToolScope(this.config.agentScope) || smallTalkTurn ? {} : this.config.agentScope === "__table__" ? Object.fromEntries(Object.entries(providerTools).filter(([k]) => TABLE_SESSION_TOOLS.has(k))) : providerTools;
|
|
593366
593437
|
const withExtensions = { ...scopedTools };
|
|
593367
|
-
if (this.extensionToolsAllowed()) {
|
|
593438
|
+
if (this.extensionToolsAllowed() && !smallTalkTurn) {
|
|
593368
593439
|
for (const t of this.extensionHost.listTools()) {
|
|
593369
593440
|
if (t.name in withExtensions)
|
|
593370
593441
|
continue;
|
|
@@ -593376,7 +593447,7 @@ Ask the user naturally; don't mention this instruction. After they answer, proce
|
|
|
593376
593447
|
}
|
|
593377
593448
|
}
|
|
593378
593449
|
const effectiveTools = this.modeFilter(withExtensions);
|
|
593379
|
-
const textToolAllowlist = (isNoToolScope(this.config.agentScope) ? [] : this.config.agentScope === "__table__" ? [...TABLE_SESSION_TOOLS] : localCoreTools).filter((name) => getModeManager().isToolAllowed(name));
|
|
593450
|
+
const textToolAllowlist = (isNoToolScope(this.config.agentScope) || smallTalkTurn ? [] : this.config.agentScope === "__table__" ? [...TABLE_SESSION_TOOLS] : localCoreTools).filter((name) => getModeManager().isToolAllowed(name));
|
|
593380
593451
|
const harness = this.harnessProfileFor(providerConfig.model, isLocalProvider);
|
|
593381
593452
|
Object.assign(this.runtimeParams, {
|
|
593382
593453
|
voiceChatActive: getRuntimeParams().voiceChatActive,
|
|
@@ -593401,7 +593472,8 @@ Ask the user naturally; don't mention this instruction. After they answer, proce
|
|
|
593401
593472
|
`),
|
|
593402
593473
|
localCoreTools: textToolAllowlist,
|
|
593403
593474
|
chatStartTime,
|
|
593404
|
-
textForAgent
|
|
593475
|
+
textForAgent,
|
|
593476
|
+
smallTalk: smallTalkTurn
|
|
593405
593477
|
});
|
|
593406
593478
|
await this.readServerContextWindow();
|
|
593407
593479
|
await this.compactIfNeeded(providerConfig);
|
|
@@ -594086,7 +594158,7 @@ ${summary || " (no provider errors recorded)"}`);
|
|
|
594086
594158
|
};
|
|
594087
594159
|
}
|
|
594088
594160
|
const blankNative = gatedNative.content.trim() === "";
|
|
594089
|
-
const content = blankNative ? emptyReplyNote(this.turnToolLedger.length) : gatedNative.content;
|
|
594161
|
+
const content = blankNative ? emptyReplyNote(this.turnToolLedger.length, this.turnToolLedger) : gatedNative.content;
|
|
594090
594162
|
const flavor = voice.getFlavor("complete");
|
|
594091
594163
|
const flavoredContent = fixCompletedLine(gatedNative.violated || isVerbatimScope(this.config.agentScope) ? content : flavorResponse(content, flavor)).text;
|
|
594092
594164
|
this.messageHistory.push({ role: "assistant", content: flavoredContent });
|
|
@@ -594801,6 +594873,7 @@ var init_agent2 = __esm(() => {
|
|
|
594801
594873
|
init_modes();
|
|
594802
594874
|
init_planning_gate();
|
|
594803
594875
|
init_registry();
|
|
594876
|
+
init_small_talk();
|
|
594804
594877
|
init_verify_gate();
|
|
594805
594878
|
init_local_tool_scope();
|
|
594806
594879
|
init_local_turn_error();
|
|
@@ -595296,7 +595369,7 @@ var init_install = __esm(() => {
|
|
|
595296
595369
|
|
|
595297
595370
|
// packages/eight/source-update.ts
|
|
595298
595371
|
import { execFile as execFile7 } from "node:child_process";
|
|
595299
|
-
import { existsSync as
|
|
595372
|
+
import { existsSync as existsSync111, realpathSync as realpathSync36, statSync as statSync37 } from "node:fs";
|
|
595300
595373
|
import { homedir as homedir84 } from "node:os";
|
|
595301
595374
|
import * as nodePath from "node:path";
|
|
595302
595375
|
function scrubbedEnv(base) {
|
|
@@ -595395,7 +595468,7 @@ function modulePathToFs(modulePath) {
|
|
|
595395
595468
|
}
|
|
595396
595469
|
return s;
|
|
595397
595470
|
}
|
|
595398
|
-
function findCheckoutRoot(modulePath, platform, hasGit = (d) =>
|
|
595471
|
+
function findCheckoutRoot(modulePath, platform, hasGit = (d) => existsSync111(lib(platform).join(d, ".git"))) {
|
|
595399
595472
|
const p = lib(platform);
|
|
595400
595473
|
const fsPath = modulePathToFs(modulePath);
|
|
595401
595474
|
let dir = p.dirname(platform === "win32" ? fsPath.replace(/\//g, "\\") : fsPath);
|
|
@@ -595411,7 +595484,7 @@ function findCheckoutRoot(modulePath, platform, hasGit = (d) => existsSync110(li
|
|
|
595411
595484
|
}
|
|
595412
595485
|
function findBrowserCheckout(o) {
|
|
595413
595486
|
const p = lib(o.platform);
|
|
595414
|
-
const hasGit = o.hasGit ?? ((d) =>
|
|
595487
|
+
const hasGit = o.hasGit ?? ((d) => existsSync111(p.join(d, ".git")));
|
|
595415
595488
|
const looked = [];
|
|
595416
595489
|
let note;
|
|
595417
595490
|
const cands = [];
|
|
@@ -595737,7 +595810,7 @@ async function runSourceUpdate(deps, opts, report) {
|
|
|
595737
595810
|
git,
|
|
595738
595811
|
bun: bun ?? "bun",
|
|
595739
595812
|
platform,
|
|
595740
|
-
fileExists: deps.fileExists ?? ((f) =>
|
|
595813
|
+
fileExists: deps.fileExists ?? ((f) => existsSync111(f)),
|
|
595741
595814
|
now: deps.now ?? (() => new Date),
|
|
595742
595815
|
baseEnv: env,
|
|
595743
595816
|
forgeHost: env.EIGHT_FORGE_HOST,
|
|
@@ -596183,7 +596256,7 @@ var init_update_notice = __esm(() => {
|
|
|
596183
596256
|
});
|
|
596184
596257
|
|
|
596185
596258
|
// packages/voice/cloud-transcriber.ts
|
|
596186
|
-
import { existsSync as
|
|
596259
|
+
import { existsSync as existsSync112 } from "node:fs";
|
|
596187
596260
|
async function transcribeCloud(wavPath, options) {
|
|
596188
596261
|
const {
|
|
596189
596262
|
apiKey,
|
|
@@ -596195,7 +596268,7 @@ async function transcribeCloud(wavPath, options) {
|
|
|
596195
596268
|
if (!apiKey) {
|
|
596196
596269
|
throw new Error("OpenAI API key is required for cloud transcription. Set OPENAI_API_KEY environment variable.");
|
|
596197
596270
|
}
|
|
596198
|
-
if (!
|
|
596271
|
+
if (!existsSync112(wavPath)) {
|
|
596199
596272
|
throw new Error(`WAV file not found: ${wavPath}`);
|
|
596200
596273
|
}
|
|
596201
596274
|
const startTime = Date.now();
|
|
@@ -596299,11 +596372,11 @@ var init_types4 = __esm(() => {
|
|
|
596299
596372
|
|
|
596300
596373
|
// packages/voice/model-manager.ts
|
|
596301
596374
|
import { EventEmitter as EventEmitter15 } from "node:events";
|
|
596302
|
-
import { existsSync as
|
|
596375
|
+
import { existsSync as existsSync113, mkdirSync as mkdirSync80, realpathSync as realpathSync37, unlinkSync as unlinkSync3 } from "node:fs";
|
|
596303
596376
|
import { homedir as homedir85 } from "node:os";
|
|
596304
596377
|
import { join as join169, sep as sep30 } from "node:path";
|
|
596305
596378
|
function resolveWhisperModel(opts = {}) {
|
|
596306
|
-
const exists = opts.exists ??
|
|
596379
|
+
const exists = opts.exists ?? existsSync113;
|
|
596307
596380
|
const dirs = [
|
|
596308
596381
|
resolveModelsPath(opts.modelsDir ?? "~/.8gent/models/whisper"),
|
|
596309
596382
|
...opts.extraDirs ?? []
|
|
@@ -596364,7 +596437,7 @@ var init_model_manager = __esm(() => {
|
|
|
596364
596437
|
this.modelsDir = resolveModelsPath(modelsPath);
|
|
596365
596438
|
}
|
|
596366
596439
|
ensureModelsDir() {
|
|
596367
|
-
if (!
|
|
596440
|
+
if (!existsSync113(this.modelsDir)) {
|
|
596368
596441
|
mkdirSync80(this.modelsDir, { recursive: true });
|
|
596369
596442
|
}
|
|
596370
596443
|
}
|
|
@@ -596378,7 +596451,7 @@ var init_model_manager = __esm(() => {
|
|
|
596378
596451
|
return join169(this.modelsDir, WHISPER_MODELS[name].filename);
|
|
596379
596452
|
}
|
|
596380
596453
|
isModelDownloaded(name) {
|
|
596381
|
-
return
|
|
596454
|
+
return existsSync113(this.getModelPath(name));
|
|
596382
596455
|
}
|
|
596383
596456
|
listModels() {
|
|
596384
596457
|
return Object.keys(WHISPER_MODELS).map((name) => ({
|
|
@@ -596393,7 +596466,7 @@ var init_model_manager = __esm(() => {
|
|
|
596393
596466
|
async downloadModel(name) {
|
|
596394
596467
|
const info = WHISPER_MODELS[name];
|
|
596395
596468
|
const destPath = this.getModelPath(name);
|
|
596396
|
-
if (
|
|
596469
|
+
if (existsSync113(destPath)) {
|
|
596397
596470
|
return destPath;
|
|
596398
596471
|
}
|
|
596399
596472
|
this.ensureModelsDir();
|
|
@@ -596444,7 +596517,7 @@ var init_model_manager = __esm(() => {
|
|
|
596444
596517
|
this.emit("download-complete", { model: name, path: destPath });
|
|
596445
596518
|
return destPath;
|
|
596446
596519
|
} catch (err) {
|
|
596447
|
-
if (
|
|
596520
|
+
if (existsSync113(destPath)) {
|
|
596448
596521
|
try {
|
|
596449
596522
|
unlinkSync3(destPath);
|
|
596450
596523
|
} catch {}
|
|
@@ -596456,7 +596529,7 @@ var init_model_manager = __esm(() => {
|
|
|
596456
596529
|
}
|
|
596457
596530
|
deleteModel(name) {
|
|
596458
596531
|
const path = this.getModelPath(name);
|
|
596459
|
-
if (
|
|
596532
|
+
if (existsSync113(path)) {
|
|
596460
596533
|
unlinkSync3(path);
|
|
596461
596534
|
return true;
|
|
596462
596535
|
}
|
|
@@ -596467,7 +596540,7 @@ var init_model_manager = __esm(() => {
|
|
|
596467
596540
|
let totalBytes = 0;
|
|
596468
596541
|
for (const name of Object.keys(WHISPER_MODELS)) {
|
|
596469
596542
|
const path = this.getModelPath(name);
|
|
596470
|
-
if (
|
|
596543
|
+
if (existsSync113(path)) {
|
|
596471
596544
|
try {
|
|
596472
596545
|
const stat = Bun.file(path);
|
|
596473
596546
|
models[name] = stat.size;
|
|
@@ -596532,7 +596605,7 @@ var init_termux = __esm(() => {
|
|
|
596532
596605
|
|
|
596533
596606
|
// packages/voice/recorder.ts
|
|
596534
596607
|
import { EventEmitter as EventEmitter16 } from "node:events";
|
|
596535
|
-
import { closeSync as closeSync21, existsSync as
|
|
596608
|
+
import { closeSync as closeSync21, existsSync as existsSync114, openSync as openSync21, readSync as readSync13, statSync as statSync38, unlinkSync as unlinkSync4 } from "node:fs";
|
|
596536
596609
|
import { tmpdir as tmpdir20 } from "node:os";
|
|
596537
596610
|
import { join as join171 } from "node:path";
|
|
596538
596611
|
async function findSoxPath() {
|
|
@@ -596734,7 +596807,7 @@ var init_recorder = __esm(() => {
|
|
|
596734
596807
|
}
|
|
596735
596808
|
static cleanupFile(path) {
|
|
596736
596809
|
try {
|
|
596737
|
-
if (
|
|
596810
|
+
if (existsSync114(path)) {
|
|
596738
596811
|
unlinkSync4(path);
|
|
596739
596812
|
}
|
|
596740
596813
|
} catch {}
|
|
@@ -596754,7 +596827,7 @@ var init_recorder = __esm(() => {
|
|
|
596754
596827
|
});
|
|
596755
596828
|
|
|
596756
596829
|
// packages/voice/transcriber.ts
|
|
596757
|
-
import { existsSync as
|
|
596830
|
+
import { existsSync as existsSync115 } from "node:fs";
|
|
596758
596831
|
import { arch as arch2, homedir as homedir86, platform as platform9 } from "node:os";
|
|
596759
596832
|
import { join as join172 } from "node:path";
|
|
596760
596833
|
function getWhisperBinaryPath() {
|
|
@@ -596762,7 +596835,7 @@ function getWhisperBinaryPath() {
|
|
|
596762
596835
|
}
|
|
596763
596836
|
async function findWhisperBinary() {
|
|
596764
596837
|
const managedPath = getWhisperBinaryPath();
|
|
596765
|
-
if (
|
|
596838
|
+
if (existsSync115(managedPath)) {
|
|
596766
596839
|
return managedPath;
|
|
596767
596840
|
}
|
|
596768
596841
|
const names = ["whisper-cpp", "whisper-cli", "whisper", "main"];
|
|
@@ -596777,7 +596850,7 @@ async function findWhisperBinary() {
|
|
|
596777
596850
|
} catch {}
|
|
596778
596851
|
}
|
|
596779
596852
|
for (const brewName of ["/opt/homebrew/bin/whisper-cpp", "/opt/homebrew/bin/whisper-cli"]) {
|
|
596780
|
-
if (
|
|
596853
|
+
if (existsSync115(brewName)) {
|
|
596781
596854
|
return brewName;
|
|
596782
596855
|
}
|
|
596783
596856
|
}
|
|
@@ -596785,13 +596858,13 @@ async function findWhisperBinary() {
|
|
|
596785
596858
|
}
|
|
596786
596859
|
async function transcribeLocal(wavPath, options) {
|
|
596787
596860
|
const { binaryPath, modelPath, language = "en", timeoutMs = 30000, threads } = options;
|
|
596788
|
-
if (!
|
|
596861
|
+
if (!existsSync115(wavPath)) {
|
|
596789
596862
|
throw new Error(`WAV file not found: ${wavPath}`);
|
|
596790
596863
|
}
|
|
596791
|
-
if (!
|
|
596864
|
+
if (!existsSync115(binaryPath)) {
|
|
596792
596865
|
throw new Error(`Whisper binary not found: ${binaryPath}`);
|
|
596793
596866
|
}
|
|
596794
|
-
if (!
|
|
596867
|
+
if (!existsSync115(modelPath)) {
|
|
596795
596868
|
throw new Error(`Model file not found: ${modelPath}`);
|
|
596796
596869
|
}
|
|
596797
596870
|
const startTime = Date.now();
|
|
@@ -597068,7 +597141,7 @@ var init_neudecide = __esm(() => {
|
|
|
597068
597141
|
|
|
597069
597142
|
// packages/runtime/node-runtime.ts
|
|
597070
597143
|
import { execFile as execFile8 } from "node:child_process";
|
|
597071
|
-
import { existsSync as
|
|
597144
|
+
import { existsSync as existsSync120 } from "node:fs";
|
|
597072
597145
|
import { homedir as homedir88 } from "node:os";
|
|
597073
597146
|
import { join as join179 } from "node:path";
|
|
597074
597147
|
import { promisify as promisify6 } from "node:util";
|
|
@@ -597131,7 +597204,7 @@ async function isRuntimeReady(opts) {
|
|
|
597131
597204
|
version: opts.version,
|
|
597132
597205
|
platform
|
|
597133
597206
|
});
|
|
597134
|
-
if (!
|
|
597207
|
+
if (!existsSync120(bin))
|
|
597135
597208
|
return false;
|
|
597136
597209
|
const min = opts.minVersion ?? opts.version;
|
|
597137
597210
|
try {
|
|
@@ -597169,7 +597242,7 @@ var init_node_runtime = __esm(() => {
|
|
|
597169
597242
|
import { spawn as spawn23 } from "node:child_process";
|
|
597170
597243
|
import {
|
|
597171
597244
|
createWriteStream,
|
|
597172
|
-
existsSync as
|
|
597245
|
+
existsSync as existsSync121,
|
|
597173
597246
|
mkdirSync as mkdirSync83,
|
|
597174
597247
|
mkdtempSync as mkdtempSync12,
|
|
597175
597248
|
readdirSync as readdirSync27,
|
|
@@ -597230,7 +597303,7 @@ async function installRuntime(input) {
|
|
|
597230
597303
|
throw new Error(`could not find node-* dir inside ${extractRoot}`);
|
|
597231
597304
|
}
|
|
597232
597305
|
const extractedPath = join180(extractRoot, nodeDir);
|
|
597233
|
-
if (
|
|
597306
|
+
if (existsSync121(plan.runtimeDir)) {
|
|
597234
597307
|
rmSync17(plan.runtimeDir, { recursive: true, force: true });
|
|
597235
597308
|
}
|
|
597236
597309
|
renameSync17(extractedPath, plan.runtimeDir);
|
|
@@ -599212,7 +599285,7 @@ Nothing was changed. Type /update again to apply.`);
|
|
|
599212
599285
|
// apps/tui/src/lib/telegram-setup.ts
|
|
599213
599286
|
import {
|
|
599214
599287
|
chmodSync as chmodSync6,
|
|
599215
|
-
existsSync as
|
|
599288
|
+
existsSync as existsSync136,
|
|
599216
599289
|
lstatSync as lstatSync31,
|
|
599217
599290
|
mkdirSync as mkdirSync96,
|
|
599218
599291
|
readFileSync as readFileSync121,
|
|
@@ -599334,7 +599407,7 @@ async function getSeenChats(key) {
|
|
|
599334
599407
|
function mergeSettings(chatIds, envFile, tokenVar) {
|
|
599335
599408
|
const path = join201(homeDir4(), ".8gent", "settings.json");
|
|
599336
599409
|
let settings = {};
|
|
599337
|
-
if (
|
|
599410
|
+
if (existsSync136(path)) {
|
|
599338
599411
|
try {
|
|
599339
599412
|
const parsed = JSON.parse(readFileSync121(path, "utf8"));
|
|
599340
599413
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
@@ -599701,7 +599774,7 @@ Personal 8gent mini-app. Iteration is driven by \`SKILL.md\`. Run tests with \`b
|
|
|
599701
599774
|
}
|
|
599702
599775
|
|
|
599703
599776
|
// packages/app-creator/creator.ts
|
|
599704
|
-
import { existsSync as
|
|
599777
|
+
import { existsSync as existsSync137, mkdirSync as mkdirSync98, writeFileSync as writeFileSync78 } from "node:fs";
|
|
599705
599778
|
import { homedir as homedir96 } from "node:os";
|
|
599706
599779
|
import { dirname as dirname84, join as join203 } from "node:path";
|
|
599707
599780
|
function defaultAppsRoot() {
|
|
@@ -599759,7 +599832,7 @@ function createApp(input) {
|
|
|
599759
599832
|
return { ...draft, persisted: false, written: [] };
|
|
599760
599833
|
}
|
|
599761
599834
|
const dir = draft.dir;
|
|
599762
|
-
const targetExists =
|
|
599835
|
+
const targetExists = existsSync137(dir);
|
|
599763
599836
|
if (targetExists && !input.allowOverwrite) {
|
|
599764
599837
|
return {
|
|
599765
599838
|
...draft,
|
|
@@ -600606,7 +600679,7 @@ var init_producer = __esm(() => {
|
|
|
600606
600679
|
});
|
|
600607
600680
|
|
|
600608
600681
|
// packages/pet/companion.ts
|
|
600609
|
-
import { existsSync as
|
|
600682
|
+
import { existsSync as existsSync141, mkdirSync as mkdirSync104, readFileSync as readFileSync123, writeFileSync as writeFileSync80 } from "node:fs";
|
|
600610
600683
|
import { join as join205 } from "node:path";
|
|
600611
600684
|
function seedRng(seed) {
|
|
600612
600685
|
let h = 0;
|
|
@@ -600750,7 +600823,7 @@ function getDeckPath() {
|
|
|
600750
600823
|
function loadDeck() {
|
|
600751
600824
|
const deckPath = getDeckPath();
|
|
600752
600825
|
try {
|
|
600753
|
-
if (
|
|
600826
|
+
if (existsSync141(deckPath)) {
|
|
600754
600827
|
return JSON.parse(readFileSync123(deckPath, "utf-8"));
|
|
600755
600828
|
}
|
|
600756
600829
|
} catch {}
|
|
@@ -622006,234 +622079,6 @@ function useImageInput(options = {}) {
|
|
|
622006
622079
|
// apps/tui/src/components/message-list.tsx
|
|
622007
622080
|
var import_react63 = __toESM(require_react(), 1);
|
|
622008
622081
|
|
|
622009
|
-
// apps/tui/src/lib/chat-layout.ts
|
|
622010
|
-
var SHELL_CHROME = 4;
|
|
622011
|
-
var COLUMN_GAP = 1;
|
|
622012
|
-
var ACTIVITY_RAIL_WIDTH = 34;
|
|
622013
|
-
function chatColumnWidth(cols, shell, min = 24) {
|
|
622014
|
-
let width = cols - SHELL_CHROME;
|
|
622015
|
-
if (shell.planWidth && shell.planWidth > 0)
|
|
622016
|
-
width -= shell.planWidth + COLUMN_GAP;
|
|
622017
|
-
if (shell.activity)
|
|
622018
|
-
width -= ACTIVITY_RAIL_WIDTH + COLUMN_GAP;
|
|
622019
|
-
return Math.max(min, width);
|
|
622020
|
-
}
|
|
622021
|
-
var USER_BUBBLE_SHARE = 0.78;
|
|
622022
|
-
function bubbleWidths(contentWidth, role) {
|
|
622023
|
-
const inner = Math.max(16, contentWidth - 2);
|
|
622024
|
-
const bubble = role === "user" ? Math.max(16, Math.floor(inner * USER_BUBBLE_SHARE)) : inner;
|
|
622025
|
-
return { bubble, wrap: Math.max(8, bubble - 2) };
|
|
622026
|
-
}
|
|
622027
|
-
|
|
622028
|
-
// apps/tui/src/lib/tool-trail.ts
|
|
622029
|
-
var COLLAPSE_THRESHOLD = 8;
|
|
622030
|
-
var MAX_TRAIL_ROWS = 12;
|
|
622031
|
-
var PATH_KEYS = ["path", "file_path", "filePath", "file", "directory", "dir"];
|
|
622032
|
-
var COMMAND_KEYS = ["command", "cmd"];
|
|
622033
|
-
var QUERY_KEYS = ["query", "pattern", "q", "search", "url"];
|
|
622034
|
-
function oneLine(s) {
|
|
622035
|
-
return s.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
622036
|
-
}
|
|
622037
|
-
function pick3(args, keys) {
|
|
622038
|
-
for (const k of keys) {
|
|
622039
|
-
const v = args[k];
|
|
622040
|
-
if (typeof v === "string" && v.trim())
|
|
622041
|
-
return oneLine(v);
|
|
622042
|
-
}
|
|
622043
|
-
return null;
|
|
622044
|
-
}
|
|
622045
|
-
function summarizeToolArgs(tool, args) {
|
|
622046
|
-
if (!args || typeof args !== "object")
|
|
622047
|
-
return "";
|
|
622048
|
-
const isCommand = /command|shell|exec|bash/.test(tool);
|
|
622049
|
-
const order = isCommand ? [COMMAND_KEYS, PATH_KEYS, QUERY_KEYS] : /search|grep|glob|find|fetch/.test(tool) ? [QUERY_KEYS, PATH_KEYS, COMMAND_KEYS] : [PATH_KEYS, COMMAND_KEYS, QUERY_KEYS];
|
|
622050
|
-
for (const keys of order) {
|
|
622051
|
-
const hit = pick3(args, keys);
|
|
622052
|
-
if (hit)
|
|
622053
|
-
return hit;
|
|
622054
|
-
}
|
|
622055
|
-
for (const v of Object.values(args)) {
|
|
622056
|
-
if (typeof v === "string" && v.trim())
|
|
622057
|
-
return oneLine(v);
|
|
622058
|
-
}
|
|
622059
|
-
return "";
|
|
622060
|
-
}
|
|
622061
|
-
var GATE_PREFIX = /^\s*\[([A-Z0-9_ -]*\b(?:BLOCKED|DENIED)\b[A-Z0-9_ -]*)\]/;
|
|
622062
|
-
var OTHER_BLOCK = /^\s*(?:Path blocked by path-guard|Path traversal blocked)|Hook blocked tool/;
|
|
622063
|
-
var RULE_NAME = /\[([a-z0-9]+(?:-[a-z0-9]+)+)\]/;
|
|
622064
|
-
function classifyToolResult(success, preview) {
|
|
622065
|
-
const text = preview ?? "";
|
|
622066
|
-
const gate = text.match(GATE_PREFIX);
|
|
622067
|
-
if (gate || OTHER_BLOCK.test(text)) {
|
|
622068
|
-
if (gate && /DENIED/.test(gate[1]))
|
|
622069
|
-
return { status: "blocked", reason: "denied" };
|
|
622070
|
-
const rule = text.match(RULE_NAME);
|
|
622071
|
-
return { status: "blocked", reason: rule ? `blocked: [${rule[1]}]` : "blocked" };
|
|
622072
|
-
}
|
|
622073
|
-
const exit = text.match(/^\s*Exit code (-?\d+)/);
|
|
622074
|
-
if (exit && exit[1] !== "0")
|
|
622075
|
-
return { status: "fail", reason: `exit ${exit[1]}` };
|
|
622076
|
-
if (!success || /^\s*(?:Error\b|Unknown tool:)/.test(text)) {
|
|
622077
|
-
const first = (text.split(`
|
|
622078
|
-
`).find((l) => l.trim()) ?? "").replace(/^\s*Error(?: running tool "[^"]*")?:?\s*/, "").trim();
|
|
622079
|
-
if (!first)
|
|
622080
|
-
return { status: "fail", reason: "error" };
|
|
622081
|
-
return { status: "fail", reason: first.length > 40 ? `${first.slice(0, 39)}…` : first };
|
|
622082
|
-
}
|
|
622083
|
-
return { status: "ok" };
|
|
622084
|
-
}
|
|
622085
|
-
function toTrailEntry(event) {
|
|
622086
|
-
const { status, reason } = classifyToolResult(event.success !== false, event.resultPreview);
|
|
622087
|
-
const entry = {
|
|
622088
|
-
tool: event.toolName,
|
|
622089
|
-
summary: summarizeToolArgs(event.toolName, event.args),
|
|
622090
|
-
status
|
|
622091
|
-
};
|
|
622092
|
-
if (reason)
|
|
622093
|
-
entry.reason = reason;
|
|
622094
|
-
if (event.toolName === "update_plan") {
|
|
622095
|
-
const items = event.args?.plan;
|
|
622096
|
-
if (Array.isArray(items)) {
|
|
622097
|
-
const plan = items.map((i) => i && typeof i === "object" ? i : {}).filter((i) => typeof i.step === "string" && i.step.trim() !== "").map((i) => ({ step: i.step, status: typeof i.status === "string" ? i.status : "pending" }));
|
|
622098
|
-
if (plan.length > 0)
|
|
622099
|
-
entry.plan = plan;
|
|
622100
|
-
}
|
|
622101
|
-
}
|
|
622102
|
-
return entry;
|
|
622103
|
-
}
|
|
622104
|
-
function isReadTool(tool) {
|
|
622105
|
-
return /^(?:read_|list_|get_|search|grep|glob|find|view|web_search|web_fetch)/.test(tool);
|
|
622106
|
-
}
|
|
622107
|
-
function commonDir(paths) {
|
|
622108
|
-
const split = paths.map((p) => p.split("/").slice(0, -1));
|
|
622109
|
-
const first = split[0] ?? [];
|
|
622110
|
-
let n = 0;
|
|
622111
|
-
while (n < first.length && split.every((s) => s[n] === first[n]))
|
|
622112
|
-
n++;
|
|
622113
|
-
return n > 0 ? `${first.slice(0, n).join("/")}/` : "";
|
|
622114
|
-
}
|
|
622115
|
-
function collapseTrail(entries, maxRows = MAX_TRAIL_ROWS) {
|
|
622116
|
-
let rows = entries.map((e) => ({ ...e, count: 1 }));
|
|
622117
|
-
if (entries.length > COLLAPSE_THRESHOLD) {
|
|
622118
|
-
const out = [];
|
|
622119
|
-
for (let i = 0;i < entries.length; ) {
|
|
622120
|
-
const e = entries[i];
|
|
622121
|
-
let j = i + 1;
|
|
622122
|
-
if (e.status === "ok" && isReadTool(e.tool)) {
|
|
622123
|
-
while (j < entries.length && entries[j].tool === e.tool && entries[j].status === "ok")
|
|
622124
|
-
j++;
|
|
622125
|
-
}
|
|
622126
|
-
if (j - i > 1) {
|
|
622127
|
-
const run = entries.slice(i, j);
|
|
622128
|
-
out.push({
|
|
622129
|
-
tool: e.tool,
|
|
622130
|
-
status: "ok",
|
|
622131
|
-
count: run.length,
|
|
622132
|
-
summary: commonDir(run.map((r) => r.summary))
|
|
622133
|
-
});
|
|
622134
|
-
} else {
|
|
622135
|
-
out.push({ ...e, count: 1 });
|
|
622136
|
-
}
|
|
622137
|
-
i = j;
|
|
622138
|
-
}
|
|
622139
|
-
rows = out;
|
|
622140
|
-
}
|
|
622141
|
-
const cap = Math.max(1, Math.floor(maxRows));
|
|
622142
|
-
if (rows.length > cap) {
|
|
622143
|
-
let toFold = rows.length - cap + 1;
|
|
622144
|
-
const fold = new Set;
|
|
622145
|
-
for (const wantOk of [true, false]) {
|
|
622146
|
-
for (let i = 0;i < rows.length && toFold > 0; i++) {
|
|
622147
|
-
if (fold.has(i) || wantOk && rows[i].status !== "ok")
|
|
622148
|
-
continue;
|
|
622149
|
-
fold.add(i);
|
|
622150
|
-
toFold--;
|
|
622151
|
-
}
|
|
622152
|
-
}
|
|
622153
|
-
const folded = rows.filter((_, i) => fold.has(i));
|
|
622154
|
-
const count = (s) => folded.filter((r) => r.status === s).reduce((n, r) => n + r.count, 0);
|
|
622155
|
-
const failed = count("fail");
|
|
622156
|
-
const blocked = count("blocked");
|
|
622157
|
-
const summary = {
|
|
622158
|
-
tool: "",
|
|
622159
|
-
summary: "",
|
|
622160
|
-
status: failed > 0 ? "fail" : blocked > 0 ? "blocked" : "ok",
|
|
622161
|
-
count: folded.reduce((n, r) => n + r.count, 0),
|
|
622162
|
-
folded: true,
|
|
622163
|
-
all: fold.size === rows.length
|
|
622164
|
-
};
|
|
622165
|
-
if (failed > 0)
|
|
622166
|
-
summary.failed = failed;
|
|
622167
|
-
if (blocked > 0)
|
|
622168
|
-
summary.blocked = blocked;
|
|
622169
|
-
rows = [summary, ...rows.filter((_, i) => !fold.has(i))];
|
|
622170
|
-
}
|
|
622171
|
-
return rows;
|
|
622172
|
-
}
|
|
622173
|
-
var ICONS = { ok: "✓", fail: "✗", blocked: "⊘" };
|
|
622174
|
-
function formatTrailRow(row, width) {
|
|
622175
|
-
const icon = ICONS[row.status];
|
|
622176
|
-
const budget = Math.max(1, width - icon.length - 1);
|
|
622177
|
-
if (row.folded) {
|
|
622178
|
-
const parts = [`${row.count} ${row.all ? "calls" : "earlier calls"}`];
|
|
622179
|
-
if (row.failed)
|
|
622180
|
-
parts.push(`${row.failed} failed`);
|
|
622181
|
-
if (row.blocked)
|
|
622182
|
-
parts.push(`${row.blocked} blocked`);
|
|
622183
|
-
return { icon, text: clip(parts.join(", "), budget) };
|
|
622184
|
-
}
|
|
622185
|
-
const head = row.count > 1 ? `${row.tool} ×${row.count}` : row.tool;
|
|
622186
|
-
const tail = row.reason ? ` (${row.reason})` : "";
|
|
622187
|
-
let summary = row.count > 1 ? row.summary ? `(${row.summary}…)` : "" : row.summary;
|
|
622188
|
-
if (!summary)
|
|
622189
|
-
return { icon, text: clip(`${head}${tail}`, budget) };
|
|
622190
|
-
const room = budget - head.length - 1 - tail.length;
|
|
622191
|
-
if (room < 4)
|
|
622192
|
-
return { icon, text: clip(`${head}${tail}`, budget) };
|
|
622193
|
-
if (summary.length > room)
|
|
622194
|
-
summary = `${summary.slice(0, room - 1)}…`;
|
|
622195
|
-
return { icon, text: `${head} ${summary}${tail}` };
|
|
622196
|
-
}
|
|
622197
|
-
function clip(s, width) {
|
|
622198
|
-
return s.length <= width ? s : `${s.slice(0, Math.max(0, width - 1))}…`;
|
|
622199
|
-
}
|
|
622200
|
-
function buildChatItems(messages) {
|
|
622201
|
-
const items = [];
|
|
622202
|
-
let pending = [];
|
|
622203
|
-
let pendingFirst = null;
|
|
622204
|
-
const flush = () => {
|
|
622205
|
-
if (pending.length > 0 && pendingFirst) {
|
|
622206
|
-
items.push({
|
|
622207
|
-
message: { ...pendingFirst, id: `trail-${pendingFirst.id}`, role: "tool", content: "" },
|
|
622208
|
-
trail: pending
|
|
622209
|
-
});
|
|
622210
|
-
}
|
|
622211
|
-
pending = [];
|
|
622212
|
-
pendingFirst = null;
|
|
622213
|
-
};
|
|
622214
|
-
for (const m of messages) {
|
|
622215
|
-
if (m.role === "tool") {
|
|
622216
|
-
if (m.toolTrail) {
|
|
622217
|
-
if (!pendingFirst)
|
|
622218
|
-
pendingFirst = m;
|
|
622219
|
-
pending.push(m.toolTrail);
|
|
622220
|
-
}
|
|
622221
|
-
continue;
|
|
622222
|
-
}
|
|
622223
|
-
if (m.role === "assistant") {
|
|
622224
|
-
items.push({ message: m, trail: pending });
|
|
622225
|
-
pending = [];
|
|
622226
|
-
pendingFirst = null;
|
|
622227
|
-
continue;
|
|
622228
|
-
}
|
|
622229
|
-
if (m.role === "user")
|
|
622230
|
-
flush();
|
|
622231
|
-
items.push({ message: m, trail: [] });
|
|
622232
|
-
}
|
|
622233
|
-
flush();
|
|
622234
|
-
return items;
|
|
622235
|
-
}
|
|
622236
|
-
|
|
622237
622082
|
// apps/tui/src/hooks/useMouseScroll.ts
|
|
622238
622083
|
var import_react57 = __toESM(require_react(), 1);
|
|
622239
622084
|
function useMouseScroll({
|
|
@@ -622259,111 +622104,25 @@ function useMouseScroll({
|
|
|
622259
622104
|
}, [enabled, step]);
|
|
622260
622105
|
}
|
|
622261
622106
|
|
|
622262
|
-
// apps/tui/src/
|
|
622263
|
-
var
|
|
622264
|
-
var
|
|
622265
|
-
|
|
622266
|
-
|
|
622267
|
-
|
|
622268
|
-
|
|
622269
|
-
|
|
622270
|
-
|
|
622271
|
-
|
|
622272
|
-
|
|
622273
|
-
import_react58.useEffect(() => {
|
|
622274
|
-
if (!started)
|
|
622275
|
-
return;
|
|
622276
|
-
const timeout = setTimeout(() => {
|
|
622277
|
-
onComplete?.();
|
|
622278
|
-
}, duration);
|
|
622279
|
-
return () => clearTimeout(timeout);
|
|
622280
|
-
}, [started, duration, onComplete]);
|
|
622281
|
-
if (!started)
|
|
622282
|
-
return null;
|
|
622283
|
-
return /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Box_default, {
|
|
622284
|
-
children
|
|
622285
|
-
}, undefined, false, undefined, this);
|
|
622286
|
-
}
|
|
622287
|
-
|
|
622288
|
-
// apps/tui/src/components/ToolTrail.tsx
|
|
622289
|
-
var import_react59 = __toESM(require_react(), 1);
|
|
622290
|
-
var jsx_dev_runtime31 = __toESM(require_jsx_dev_runtime(), 1);
|
|
622291
|
-
function iconColor(status) {
|
|
622292
|
-
return status === "ok" ? t.green : status === "fail" ? t.red : t.orange;
|
|
622293
|
-
}
|
|
622294
|
-
function useLandingRows(total, animate) {
|
|
622295
|
-
const [shown, setShown] = import_react59.useState(total);
|
|
622296
|
-
const shownRef = import_react59.useRef(total);
|
|
622297
|
-
shownRef.current = shown;
|
|
622298
|
-
const landingRef = import_react59.useRef(null);
|
|
622299
|
-
import_react59.useEffect(() => {
|
|
622300
|
-
const from = shownRef.current;
|
|
622301
|
-
if (total <= from + 1 || !motionEnabled(animate)) {
|
|
622302
|
-
landingRef.current = null;
|
|
622303
|
-
setShown(total);
|
|
622304
|
-
return;
|
|
622305
|
-
}
|
|
622306
|
-
landingRef.current = total;
|
|
622307
|
-
const step = staggerFor(total - from);
|
|
622308
|
-
let n = from + 1;
|
|
622309
|
-
setShown(n);
|
|
622310
|
-
const id = setInterval(() => {
|
|
622311
|
-
n += 1;
|
|
622312
|
-
setShown(Math.min(total, n));
|
|
622313
|
-
if (n >= total) {
|
|
622314
|
-
landingRef.current = null;
|
|
622315
|
-
clearInterval(id);
|
|
622316
|
-
}
|
|
622317
|
-
}, step);
|
|
622318
|
-
return () => clearInterval(id);
|
|
622319
|
-
}, [total, animate]);
|
|
622320
|
-
if (landingRef.current === total)
|
|
622321
|
-
return Math.min(shown, total);
|
|
622322
|
-
if (total <= shown + 1)
|
|
622323
|
-
return total;
|
|
622324
|
-
return shown;
|
|
622325
|
-
}
|
|
622326
|
-
function ToolTrail({
|
|
622327
|
-
entries,
|
|
622328
|
-
width,
|
|
622329
|
-
maxRows,
|
|
622330
|
-
animate = true
|
|
622331
|
-
}) {
|
|
622332
|
-
const rows = collapseTrail(entries, maxRows);
|
|
622333
|
-
const visible = useLandingRows(rows.length, animate);
|
|
622334
|
-
if (rows.length === 0)
|
|
622335
|
-
return null;
|
|
622336
|
-
return /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Box_default, {
|
|
622337
|
-
flexDirection: "column",
|
|
622338
|
-
flexShrink: 0,
|
|
622339
|
-
children: rows.slice(0, visible).map((row, i) => {
|
|
622340
|
-
const { text } = formatTrailRow(row, width);
|
|
622341
|
-
const g = glyphs();
|
|
622342
|
-
const icon = row.status === "ok" ? g.ok : row.status === "fail" ? g.fail : g.blocked;
|
|
622343
|
-
return /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Box_default, {
|
|
622344
|
-
width,
|
|
622345
|
-
children: [
|
|
622346
|
-
/* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
622347
|
-
color: iconColor(row.status),
|
|
622348
|
-
children: icon
|
|
622349
|
-
}, undefined, false, undefined, this),
|
|
622350
|
-
/* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
622351
|
-
color: row.status === "ok" ? t.muted : t.textPrimary,
|
|
622352
|
-
wrap: "truncate-end",
|
|
622353
|
-
children: ` ${text}`
|
|
622354
|
-
}, undefined, false, undefined, this)
|
|
622355
|
-
]
|
|
622356
|
-
}, i, true, undefined, this);
|
|
622357
|
-
})
|
|
622358
|
-
}, undefined, false, undefined, this);
|
|
622107
|
+
// apps/tui/src/lib/chat-layout.ts
|
|
622108
|
+
var SHELL_CHROME = 4;
|
|
622109
|
+
var COLUMN_GAP = 1;
|
|
622110
|
+
var ACTIVITY_RAIL_WIDTH = 34;
|
|
622111
|
+
function chatColumnWidth(cols, shell, min = 24) {
|
|
622112
|
+
let width = cols - SHELL_CHROME;
|
|
622113
|
+
if (shell.planWidth && shell.planWidth > 0)
|
|
622114
|
+
width -= shell.planWidth + COLUMN_GAP;
|
|
622115
|
+
if (shell.activity)
|
|
622116
|
+
width -= ACTIVITY_RAIL_WIDTH + COLUMN_GAP;
|
|
622117
|
+
return Math.max(min, width);
|
|
622359
622118
|
}
|
|
622360
|
-
|
|
622361
|
-
|
|
622119
|
+
var USER_BUBBLE_SHARE = 0.78;
|
|
622120
|
+
function bubbleWidths(contentWidth, role) {
|
|
622121
|
+
const inner = Math.max(16, contentWidth - 2);
|
|
622122
|
+
const bubble = role === "user" ? Math.max(16, Math.floor(inner * USER_BUBBLE_SHARE)) : inner;
|
|
622123
|
+
return { bubble, wrap: Math.max(8, bubble - 2) };
|
|
622362
622124
|
}
|
|
622363
622125
|
|
|
622364
|
-
// apps/tui/src/components/TurnResults.tsx
|
|
622365
|
-
var import_react60 = __toESM(require_react(), 1);
|
|
622366
|
-
|
|
622367
622126
|
// apps/tui/src/lib/inline-markdown.ts
|
|
622368
622127
|
var MAX_DEPTH3 = 3;
|
|
622369
622128
|
var INDENT_STEP = 2;
|
|
@@ -622678,6 +622437,215 @@ function blockRows(block, width) {
|
|
|
622678
622437
|
}
|
|
622679
622438
|
}
|
|
622680
622439
|
|
|
622440
|
+
// apps/tui/src/lib/tool-trail.ts
|
|
622441
|
+
var COLLAPSE_THRESHOLD = 8;
|
|
622442
|
+
var MAX_TRAIL_ROWS = 12;
|
|
622443
|
+
var PATH_KEYS = ["path", "file_path", "filePath", "file", "directory", "dir"];
|
|
622444
|
+
var COMMAND_KEYS = ["command", "cmd"];
|
|
622445
|
+
var QUERY_KEYS = ["query", "pattern", "q", "search", "url"];
|
|
622446
|
+
function oneLine(s) {
|
|
622447
|
+
return s.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
622448
|
+
}
|
|
622449
|
+
function pick3(args, keys) {
|
|
622450
|
+
for (const k of keys) {
|
|
622451
|
+
const v = args[k];
|
|
622452
|
+
if (typeof v === "string" && v.trim())
|
|
622453
|
+
return oneLine(v);
|
|
622454
|
+
}
|
|
622455
|
+
return null;
|
|
622456
|
+
}
|
|
622457
|
+
function summarizeToolArgs(tool, args) {
|
|
622458
|
+
if (!args || typeof args !== "object")
|
|
622459
|
+
return "";
|
|
622460
|
+
const isCommand = /command|shell|exec|bash/.test(tool);
|
|
622461
|
+
const order = isCommand ? [COMMAND_KEYS, PATH_KEYS, QUERY_KEYS] : /search|grep|glob|find|fetch/.test(tool) ? [QUERY_KEYS, PATH_KEYS, COMMAND_KEYS] : [PATH_KEYS, COMMAND_KEYS, QUERY_KEYS];
|
|
622462
|
+
for (const keys of order) {
|
|
622463
|
+
const hit = pick3(args, keys);
|
|
622464
|
+
if (hit)
|
|
622465
|
+
return hit;
|
|
622466
|
+
}
|
|
622467
|
+
for (const v of Object.values(args)) {
|
|
622468
|
+
if (typeof v === "string" && v.trim())
|
|
622469
|
+
return oneLine(v);
|
|
622470
|
+
}
|
|
622471
|
+
return "";
|
|
622472
|
+
}
|
|
622473
|
+
var GATE_PREFIX = /^\s*\[([A-Z0-9_ -]*\b(?:BLOCKED|DENIED)\b[A-Z0-9_ -]*)\]/;
|
|
622474
|
+
var OTHER_BLOCK = /^\s*(?:Path blocked by path-guard|Path traversal blocked)|Hook blocked tool/;
|
|
622475
|
+
var RULE_NAME = /\[([a-z0-9]+(?:-[a-z0-9]+)+)\]/;
|
|
622476
|
+
function classifyToolResult(success, preview) {
|
|
622477
|
+
const text = preview ?? "";
|
|
622478
|
+
const gate = text.match(GATE_PREFIX);
|
|
622479
|
+
if (gate || OTHER_BLOCK.test(text)) {
|
|
622480
|
+
if (gate && /DENIED/.test(gate[1]))
|
|
622481
|
+
return { status: "blocked", reason: "denied" };
|
|
622482
|
+
const rule = text.match(RULE_NAME);
|
|
622483
|
+
return { status: "blocked", reason: rule ? `blocked: [${rule[1]}]` : "blocked" };
|
|
622484
|
+
}
|
|
622485
|
+
const exit = text.match(/^\s*Exit code (-?\d+)/);
|
|
622486
|
+
if (exit && exit[1] !== "0")
|
|
622487
|
+
return { status: "fail", reason: `exit ${exit[1]}` };
|
|
622488
|
+
if (!success || /^\s*(?:Error\b|Unknown tool:)/.test(text)) {
|
|
622489
|
+
const first = (text.split(`
|
|
622490
|
+
`).find((l) => l.trim()) ?? "").replace(/^\s*Error(?: running tool "[^"]*")?:?\s*/, "").trim();
|
|
622491
|
+
if (!first)
|
|
622492
|
+
return { status: "fail", reason: "error" };
|
|
622493
|
+
return { status: "fail", reason: first.length > 40 ? `${first.slice(0, 39)}…` : first };
|
|
622494
|
+
}
|
|
622495
|
+
return { status: "ok" };
|
|
622496
|
+
}
|
|
622497
|
+
function toTrailEntry(event) {
|
|
622498
|
+
const { status, reason } = classifyToolResult(event.success !== false, event.resultPreview);
|
|
622499
|
+
const entry = {
|
|
622500
|
+
tool: event.toolName,
|
|
622501
|
+
summary: summarizeToolArgs(event.toolName, event.args),
|
|
622502
|
+
status
|
|
622503
|
+
};
|
|
622504
|
+
if (reason)
|
|
622505
|
+
entry.reason = reason;
|
|
622506
|
+
if (event.toolName === "update_plan") {
|
|
622507
|
+
const items = event.args?.plan;
|
|
622508
|
+
if (Array.isArray(items)) {
|
|
622509
|
+
const plan = items.map((i) => i && typeof i === "object" ? i : {}).filter((i) => typeof i.step === "string" && i.step.trim() !== "").map((i) => ({ step: i.step, status: typeof i.status === "string" ? i.status : "pending" }));
|
|
622510
|
+
if (plan.length > 0)
|
|
622511
|
+
entry.plan = plan;
|
|
622512
|
+
}
|
|
622513
|
+
}
|
|
622514
|
+
return entry;
|
|
622515
|
+
}
|
|
622516
|
+
function isReadTool(tool) {
|
|
622517
|
+
return /^(?:read_|list_|get_|search|grep|glob|find|view|web_search|web_fetch)/.test(tool);
|
|
622518
|
+
}
|
|
622519
|
+
function commonDir(paths) {
|
|
622520
|
+
const split = paths.map((p) => p.split("/").slice(0, -1));
|
|
622521
|
+
const first = split[0] ?? [];
|
|
622522
|
+
let n = 0;
|
|
622523
|
+
while (n < first.length && split.every((s) => s[n] === first[n]))
|
|
622524
|
+
n++;
|
|
622525
|
+
return n > 0 ? `${first.slice(0, n).join("/")}/` : "";
|
|
622526
|
+
}
|
|
622527
|
+
function collapseTrail(entries, maxRows = MAX_TRAIL_ROWS) {
|
|
622528
|
+
let rows = entries.map((e) => ({ ...e, count: 1 }));
|
|
622529
|
+
if (entries.length > COLLAPSE_THRESHOLD) {
|
|
622530
|
+
const out = [];
|
|
622531
|
+
for (let i = 0;i < entries.length; ) {
|
|
622532
|
+
const e = entries[i];
|
|
622533
|
+
let j = i + 1;
|
|
622534
|
+
if (e.status === "ok" && isReadTool(e.tool)) {
|
|
622535
|
+
while (j < entries.length && entries[j].tool === e.tool && entries[j].status === "ok")
|
|
622536
|
+
j++;
|
|
622537
|
+
}
|
|
622538
|
+
if (j - i > 1) {
|
|
622539
|
+
const run = entries.slice(i, j);
|
|
622540
|
+
out.push({
|
|
622541
|
+
tool: e.tool,
|
|
622542
|
+
status: "ok",
|
|
622543
|
+
count: run.length,
|
|
622544
|
+
summary: commonDir(run.map((r) => r.summary))
|
|
622545
|
+
});
|
|
622546
|
+
} else {
|
|
622547
|
+
out.push({ ...e, count: 1 });
|
|
622548
|
+
}
|
|
622549
|
+
i = j;
|
|
622550
|
+
}
|
|
622551
|
+
rows = out;
|
|
622552
|
+
}
|
|
622553
|
+
const cap = Math.max(1, Math.floor(maxRows));
|
|
622554
|
+
if (rows.length > cap) {
|
|
622555
|
+
let toFold = rows.length - cap + 1;
|
|
622556
|
+
const fold = new Set;
|
|
622557
|
+
for (const wantOk of [true, false]) {
|
|
622558
|
+
for (let i = 0;i < rows.length && toFold > 0; i++) {
|
|
622559
|
+
if (fold.has(i) || wantOk && rows[i].status !== "ok")
|
|
622560
|
+
continue;
|
|
622561
|
+
fold.add(i);
|
|
622562
|
+
toFold--;
|
|
622563
|
+
}
|
|
622564
|
+
}
|
|
622565
|
+
const folded = rows.filter((_, i) => fold.has(i));
|
|
622566
|
+
const count = (s) => folded.filter((r) => r.status === s).reduce((n, r) => n + r.count, 0);
|
|
622567
|
+
const failed = count("fail");
|
|
622568
|
+
const blocked = count("blocked");
|
|
622569
|
+
const summary = {
|
|
622570
|
+
tool: "",
|
|
622571
|
+
summary: "",
|
|
622572
|
+
status: failed > 0 ? "fail" : blocked > 0 ? "blocked" : "ok",
|
|
622573
|
+
count: folded.reduce((n, r) => n + r.count, 0),
|
|
622574
|
+
folded: true,
|
|
622575
|
+
all: fold.size === rows.length
|
|
622576
|
+
};
|
|
622577
|
+
if (failed > 0)
|
|
622578
|
+
summary.failed = failed;
|
|
622579
|
+
if (blocked > 0)
|
|
622580
|
+
summary.blocked = blocked;
|
|
622581
|
+
rows = [summary, ...rows.filter((_, i) => !fold.has(i))];
|
|
622582
|
+
}
|
|
622583
|
+
return rows;
|
|
622584
|
+
}
|
|
622585
|
+
var ICONS = { ok: "✓", fail: "✗", blocked: "⊘" };
|
|
622586
|
+
function formatTrailRow(row, width) {
|
|
622587
|
+
const icon = ICONS[row.status];
|
|
622588
|
+
const budget = Math.max(1, width - icon.length - 1);
|
|
622589
|
+
if (row.folded) {
|
|
622590
|
+
const parts = [`${row.count} ${row.all ? "calls" : "earlier calls"}`];
|
|
622591
|
+
if (row.failed)
|
|
622592
|
+
parts.push(`${row.failed} failed`);
|
|
622593
|
+
if (row.blocked)
|
|
622594
|
+
parts.push(`${row.blocked} blocked`);
|
|
622595
|
+
return { icon, text: clip(parts.join(", "), budget) };
|
|
622596
|
+
}
|
|
622597
|
+
const head = row.count > 1 ? `${row.tool} ×${row.count}` : row.tool;
|
|
622598
|
+
const tail = row.reason ? ` (${row.reason})` : "";
|
|
622599
|
+
let summary = row.count > 1 ? row.summary ? `(${row.summary}…)` : "" : row.summary;
|
|
622600
|
+
if (!summary)
|
|
622601
|
+
return { icon, text: clip(`${head}${tail}`, budget) };
|
|
622602
|
+
const room = budget - head.length - 1 - tail.length;
|
|
622603
|
+
if (room < 4)
|
|
622604
|
+
return { icon, text: clip(`${head}${tail}`, budget) };
|
|
622605
|
+
if (summary.length > room)
|
|
622606
|
+
summary = `${summary.slice(0, room - 1)}…`;
|
|
622607
|
+
return { icon, text: `${head} ${summary}${tail}` };
|
|
622608
|
+
}
|
|
622609
|
+
function clip(s, width) {
|
|
622610
|
+
return s.length <= width ? s : `${s.slice(0, Math.max(0, width - 1))}…`;
|
|
622611
|
+
}
|
|
622612
|
+
function buildChatItems(messages) {
|
|
622613
|
+
const items = [];
|
|
622614
|
+
let pending = [];
|
|
622615
|
+
let pendingFirst = null;
|
|
622616
|
+
const flush = () => {
|
|
622617
|
+
if (pending.length > 0 && pendingFirst) {
|
|
622618
|
+
items.push({
|
|
622619
|
+
message: { ...pendingFirst, id: `trail-${pendingFirst.id}`, role: "tool", content: "" },
|
|
622620
|
+
trail: pending
|
|
622621
|
+
});
|
|
622622
|
+
}
|
|
622623
|
+
pending = [];
|
|
622624
|
+
pendingFirst = null;
|
|
622625
|
+
};
|
|
622626
|
+
for (const m of messages) {
|
|
622627
|
+
if (m.role === "tool") {
|
|
622628
|
+
if (m.toolTrail) {
|
|
622629
|
+
if (!pendingFirst)
|
|
622630
|
+
pendingFirst = m;
|
|
622631
|
+
pending.push(m.toolTrail);
|
|
622632
|
+
}
|
|
622633
|
+
continue;
|
|
622634
|
+
}
|
|
622635
|
+
if (m.role === "assistant") {
|
|
622636
|
+
items.push({ message: m, trail: pending });
|
|
622637
|
+
pending = [];
|
|
622638
|
+
pendingFirst = null;
|
|
622639
|
+
continue;
|
|
622640
|
+
}
|
|
622641
|
+
if (m.role === "user")
|
|
622642
|
+
flush();
|
|
622643
|
+
items.push({ message: m, trail: [] });
|
|
622644
|
+
}
|
|
622645
|
+
flush();
|
|
622646
|
+
return items;
|
|
622647
|
+
}
|
|
622648
|
+
|
|
622681
622649
|
// apps/tui/src/lib/activity-rail-derivation.ts
|
|
622682
622650
|
function deriveTools(messages, isProcessing, limit = 5) {
|
|
622683
622651
|
const ended = new Map;
|
|
@@ -623149,8 +623117,85 @@ function turnResultRows(trail, maxRows, plan) {
|
|
|
623149
623117
|
return buildTurnResults(trail, maxRows, plan).length;
|
|
623150
623118
|
}
|
|
623151
623119
|
|
|
623120
|
+
// apps/tui/src/components/ToolTrail.tsx
|
|
623121
|
+
var import_react58 = __toESM(require_react(), 1);
|
|
623122
|
+
var jsx_dev_runtime30 = __toESM(require_jsx_dev_runtime(), 1);
|
|
623123
|
+
function iconColor(status) {
|
|
623124
|
+
return status === "ok" ? t.green : status === "fail" ? t.red : t.orange;
|
|
623125
|
+
}
|
|
623126
|
+
function useLandingRows(total, animate) {
|
|
623127
|
+
const [shown, setShown] = import_react58.useState(total);
|
|
623128
|
+
const shownRef = import_react58.useRef(total);
|
|
623129
|
+
shownRef.current = shown;
|
|
623130
|
+
const landingRef = import_react58.useRef(null);
|
|
623131
|
+
import_react58.useEffect(() => {
|
|
623132
|
+
const from = shownRef.current;
|
|
623133
|
+
if (total <= from + 1 || !motionEnabled(animate)) {
|
|
623134
|
+
landingRef.current = null;
|
|
623135
|
+
setShown(total);
|
|
623136
|
+
return;
|
|
623137
|
+
}
|
|
623138
|
+
landingRef.current = total;
|
|
623139
|
+
const step = staggerFor(total - from);
|
|
623140
|
+
let n = from + 1;
|
|
623141
|
+
setShown(n);
|
|
623142
|
+
const id = setInterval(() => {
|
|
623143
|
+
n += 1;
|
|
623144
|
+
setShown(Math.min(total, n));
|
|
623145
|
+
if (n >= total) {
|
|
623146
|
+
landingRef.current = null;
|
|
623147
|
+
clearInterval(id);
|
|
623148
|
+
}
|
|
623149
|
+
}, step);
|
|
623150
|
+
return () => clearInterval(id);
|
|
623151
|
+
}, [total, animate]);
|
|
623152
|
+
if (landingRef.current === total)
|
|
623153
|
+
return Math.min(shown, total);
|
|
623154
|
+
if (total <= shown + 1)
|
|
623155
|
+
return total;
|
|
623156
|
+
return shown;
|
|
623157
|
+
}
|
|
623158
|
+
function ToolTrail({
|
|
623159
|
+
entries,
|
|
623160
|
+
width,
|
|
623161
|
+
maxRows,
|
|
623162
|
+
animate = true
|
|
623163
|
+
}) {
|
|
623164
|
+
const rows = collapseTrail(entries, maxRows);
|
|
623165
|
+
const visible = useLandingRows(rows.length, animate);
|
|
623166
|
+
if (rows.length === 0)
|
|
623167
|
+
return null;
|
|
623168
|
+
return /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Box_default, {
|
|
623169
|
+
flexDirection: "column",
|
|
623170
|
+
flexShrink: 0,
|
|
623171
|
+
children: rows.slice(0, visible).map((row, i) => {
|
|
623172
|
+
const { text } = formatTrailRow(row, width);
|
|
623173
|
+
const g = glyphs();
|
|
623174
|
+
const icon = row.status === "ok" ? g.ok : row.status === "fail" ? g.fail : g.blocked;
|
|
623175
|
+
return /* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Box_default, {
|
|
623176
|
+
width,
|
|
623177
|
+
children: [
|
|
623178
|
+
/* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text, {
|
|
623179
|
+
color: iconColor(row.status),
|
|
623180
|
+
children: icon
|
|
623181
|
+
}, undefined, false, undefined, this),
|
|
623182
|
+
/* @__PURE__ */ jsx_dev_runtime30.jsxDEV(Text, {
|
|
623183
|
+
color: row.status === "ok" ? t.muted : t.textPrimary,
|
|
623184
|
+
wrap: "truncate-end",
|
|
623185
|
+
children: ` ${text}`
|
|
623186
|
+
}, undefined, false, undefined, this)
|
|
623187
|
+
]
|
|
623188
|
+
}, i, true, undefined, this);
|
|
623189
|
+
})
|
|
623190
|
+
}, undefined, false, undefined, this);
|
|
623191
|
+
}
|
|
623192
|
+
function toolTrailRows(entries, maxRows) {
|
|
623193
|
+
return entries.length === 0 ? 0 : collapseTrail(entries, maxRows).length;
|
|
623194
|
+
}
|
|
623195
|
+
|
|
623152
623196
|
// apps/tui/src/components/TurnResults.tsx
|
|
623153
|
-
var
|
|
623197
|
+
var import_react59 = __toESM(require_react(), 1);
|
|
623198
|
+
var jsx_dev_runtime31 = __toESM(require_jsx_dev_runtime(), 1);
|
|
623154
623199
|
function iconFor(status) {
|
|
623155
623200
|
const g = glyphs();
|
|
623156
623201
|
if (status === "ok")
|
|
@@ -623162,8 +623207,8 @@ function iconFor(status) {
|
|
|
623162
623207
|
return { icon: g.pending, color: t.muted };
|
|
623163
623208
|
}
|
|
623164
623209
|
function useResultLanding(total, land) {
|
|
623165
|
-
const [shown, setShown] =
|
|
623166
|
-
|
|
623210
|
+
const [shown, setShown] = import_react59.useState(land ? 0 : total);
|
|
623211
|
+
import_react59.useEffect(() => {
|
|
623167
623212
|
if (!land) {
|
|
623168
623213
|
setShown(total);
|
|
623169
623214
|
return;
|
|
@@ -623203,12 +623248,12 @@ function TurnResults({
|
|
|
623203
623248
|
const visible = useResultLanding(rows.length, land && motionEnabled(animate));
|
|
623204
623249
|
if (rows.length === 0)
|
|
623205
623250
|
return null;
|
|
623206
|
-
return /* @__PURE__ */
|
|
623251
|
+
return /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Box_default, {
|
|
623207
623252
|
flexDirection: "column",
|
|
623208
623253
|
flexShrink: 0,
|
|
623209
623254
|
children: rows.map((row, i) => {
|
|
623210
623255
|
if (i >= visible) {
|
|
623211
|
-
return /* @__PURE__ */
|
|
623256
|
+
return /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Box_default, {
|
|
623212
623257
|
height: 1,
|
|
623213
623258
|
width
|
|
623214
623259
|
}, i, false, undefined, this);
|
|
@@ -623216,55 +623261,55 @@ function TurnResults({
|
|
|
623216
623261
|
const { icon, color } = iconFor(row.status);
|
|
623217
623262
|
const fit = fitResultRow(row, width);
|
|
623218
623263
|
const quiet = row.status === "pending" || row.kind === "fold";
|
|
623219
|
-
return /* @__PURE__ */
|
|
623264
|
+
return /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Box_default, {
|
|
623220
623265
|
width,
|
|
623221
623266
|
height: 1,
|
|
623222
|
-
children: /* @__PURE__ */
|
|
623267
|
+
children: /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623223
623268
|
wrap: "truncate-end",
|
|
623224
623269
|
children: [
|
|
623225
|
-
/* @__PURE__ */
|
|
623270
|
+
/* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623226
623271
|
color,
|
|
623227
623272
|
children: icon
|
|
623228
623273
|
}, undefined, false, undefined, this),
|
|
623229
|
-
/* @__PURE__ */
|
|
623274
|
+
/* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623230
623275
|
children: " "
|
|
623231
623276
|
}, undefined, false, undefined, this),
|
|
623232
|
-
/* @__PURE__ */
|
|
623277
|
+
/* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623233
623278
|
bold: !quiet,
|
|
623234
623279
|
color: quiet ? t.muted : t.textPrimary,
|
|
623235
623280
|
children: fit.verb
|
|
623236
623281
|
}, undefined, false, undefined, this),
|
|
623237
|
-
fit.spans ? /* @__PURE__ */
|
|
623282
|
+
fit.spans ? /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(jsx_dev_runtime31.Fragment, {
|
|
623238
623283
|
children: [
|
|
623239
|
-
fit.verb ? /* @__PURE__ */
|
|
623284
|
+
fit.verb ? /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623240
623285
|
children: " "
|
|
623241
623286
|
}, undefined, false, undefined, this) : null,
|
|
623242
|
-
fit.spans.map((s, j) => s.code ? /* @__PURE__ */
|
|
623287
|
+
fit.spans.map((s, j) => s.code ? /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623243
623288
|
color: t.textPrimary,
|
|
623244
623289
|
backgroundColor: t.border,
|
|
623245
623290
|
children: s.text
|
|
623246
|
-
}, j, false, undefined, this) : /* @__PURE__ */
|
|
623291
|
+
}, j, false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623247
623292
|
color: quiet ? t.muted : t.textSecondary,
|
|
623248
623293
|
children: s.text
|
|
623249
623294
|
}, j, false, undefined, this))
|
|
623250
623295
|
]
|
|
623251
|
-
}, undefined, true, undefined, this) : fit.text ? /* @__PURE__ */
|
|
623296
|
+
}, undefined, true, undefined, this) : fit.text ? /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623252
623297
|
color: quiet ? t.muted : t.textSecondary,
|
|
623253
623298
|
children: ` ${fit.text}`
|
|
623254
623299
|
}, undefined, false, undefined, this) : null,
|
|
623255
|
-
fit.chip ? /* @__PURE__ */
|
|
623300
|
+
fit.chip ? /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(jsx_dev_runtime31.Fragment, {
|
|
623256
623301
|
children: [
|
|
623257
|
-
/* @__PURE__ */
|
|
623302
|
+
/* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623258
623303
|
children: " "
|
|
623259
623304
|
}, undefined, false, undefined, this),
|
|
623260
|
-
/* @__PURE__ */
|
|
623305
|
+
/* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623261
623306
|
color: t.textPrimary,
|
|
623262
623307
|
backgroundColor: t.border,
|
|
623263
623308
|
children: ` ${fit.chip} `
|
|
623264
623309
|
}, undefined, false, undefined, this)
|
|
623265
623310
|
]
|
|
623266
623311
|
}, undefined, true, undefined, this) : null,
|
|
623267
|
-
fit.note ? /* @__PURE__ */
|
|
623312
|
+
fit.note ? /* @__PURE__ */ jsx_dev_runtime31.jsxDEV(Text, {
|
|
623268
623313
|
color: row.status === "fail" ? t.red : t.muted,
|
|
623269
623314
|
children: `${" ".repeat(fit.noteGap ?? 2)}${fit.note}`
|
|
623270
623315
|
}, undefined, false, undefined, this) : null
|
|
@@ -623275,6 +623320,32 @@ function TurnResults({
|
|
|
623275
623320
|
}, undefined, false, undefined, this);
|
|
623276
623321
|
}
|
|
623277
623322
|
|
|
623323
|
+
// apps/tui/src/components/fade-transition.tsx
|
|
623324
|
+
var import_react60 = __toESM(require_react(), 1);
|
|
623325
|
+
var jsx_dev_runtime32 = __toESM(require_jsx_dev_runtime(), 1);
|
|
623326
|
+
function FadeIn({ children, duration = 300, delay = 0, onComplete }) {
|
|
623327
|
+
const [started, setStarted] = import_react60.useState(false);
|
|
623328
|
+
import_react60.useEffect(() => {
|
|
623329
|
+
const timeout = setTimeout(() => {
|
|
623330
|
+
setStarted(true);
|
|
623331
|
+
}, delay);
|
|
623332
|
+
return () => clearTimeout(timeout);
|
|
623333
|
+
}, [delay]);
|
|
623334
|
+
import_react60.useEffect(() => {
|
|
623335
|
+
if (!started)
|
|
623336
|
+
return;
|
|
623337
|
+
const timeout = setTimeout(() => {
|
|
623338
|
+
onComplete?.();
|
|
623339
|
+
}, duration);
|
|
623340
|
+
return () => clearTimeout(timeout);
|
|
623341
|
+
}, [started, duration, onComplete]);
|
|
623342
|
+
if (!started)
|
|
623343
|
+
return null;
|
|
623344
|
+
return /* @__PURE__ */ jsx_dev_runtime32.jsxDEV(Box_default, {
|
|
623345
|
+
children
|
|
623346
|
+
}, undefined, false, undefined, this);
|
|
623347
|
+
}
|
|
623348
|
+
|
|
623278
623349
|
// apps/tui/src/components/sound-effects.tsx
|
|
623279
623350
|
var import_react61 = __toESM(require_react(), 1);
|
|
623280
623351
|
var BELL = "\x07";
|
|
@@ -623687,6 +623758,7 @@ function MessageList({
|
|
|
623687
623758
|
showAnimations,
|
|
623688
623759
|
isLatestAssistant: message.id === lastAssistantId,
|
|
623689
623760
|
trail: trailById.get(message.id) ?? [],
|
|
623761
|
+
turnRunning,
|
|
623690
623762
|
trailMaxRows: trailCaps.get(message.id),
|
|
623691
623763
|
onAnimationStart: (id) => {
|
|
623692
623764
|
animatedIdsRef.current.add(id);
|
|
@@ -623718,6 +623790,7 @@ function MessageItem({
|
|
|
623718
623790
|
showAnimations,
|
|
623719
623791
|
isLatestAssistant = false,
|
|
623720
623792
|
trail = [],
|
|
623793
|
+
turnRunning = false,
|
|
623721
623794
|
trailMaxRows,
|
|
623722
623795
|
onAnimationStart
|
|
623723
623796
|
}) {
|
|
@@ -623903,7 +623976,7 @@ function MessageItem({
|
|
|
623903
623976
|
animate: showAnimations
|
|
623904
623977
|
}, undefined, false, undefined, this)
|
|
623905
623978
|
}, undefined, false, undefined, this),
|
|
623906
|
-
!isUser && !message.content.trim() && trail.length > 0 ? /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(MutedText, {
|
|
623979
|
+
!isUser && !turnRunning && !message.content.trim() && trail.length > 0 ? /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(MutedText, {
|
|
623907
623980
|
children: "No reply."
|
|
623908
623981
|
}, undefined, false, undefined, this) : null,
|
|
623909
623982
|
message.content.trim() || trail.length === 0 ? /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(Box_default, {
|
|
@@ -624065,7 +624138,11 @@ function MarkdownBody({
|
|
|
624065
624138
|
})
|
|
624066
624139
|
}, undefined, false, undefined, this);
|
|
624067
624140
|
}
|
|
624068
|
-
function InlineSpans({
|
|
624141
|
+
function InlineSpans({
|
|
624142
|
+
spans,
|
|
624143
|
+
color,
|
|
624144
|
+
adhdMode
|
|
624145
|
+
}) {
|
|
624069
624146
|
return /* @__PURE__ */ jsx_dev_runtime34.jsxDEV(Text, {
|
|
624070
624147
|
color,
|
|
624071
624148
|
wrap: "wrap",
|
|
@@ -626476,7 +626553,7 @@ init_cloud_transcriber();
|
|
|
626476
626553
|
init_types4();
|
|
626477
626554
|
|
|
626478
626555
|
// packages/voice/voice-chat.ts
|
|
626479
|
-
import { existsSync as
|
|
626556
|
+
import { existsSync as existsSync116, unlinkSync as unlinkSync5 } from "node:fs";
|
|
626480
626557
|
import { tmpdir as tmpdir21 } from "node:os";
|
|
626481
626558
|
import { join as join173 } from "node:path";
|
|
626482
626559
|
|
|
@@ -626935,7 +627012,7 @@ class VoiceChatLoop {
|
|
|
626935
627012
|
cleanupFile(wavPath);
|
|
626936
627013
|
throw new VoiceChatFatalError(describeRecFailure(exitCode, why));
|
|
626937
627014
|
}
|
|
626938
|
-
if (!
|
|
627015
|
+
if (!existsSync116(wavPath)) {
|
|
626939
627016
|
this.reportError("No audio was recorded. Check that your microphone is the system input.");
|
|
626940
627017
|
return null;
|
|
626941
627018
|
}
|
|
@@ -627059,7 +627136,7 @@ function sleep2(ms) {
|
|
|
627059
627136
|
}
|
|
627060
627137
|
function cleanupFile(path) {
|
|
627061
627138
|
try {
|
|
627062
|
-
if (
|
|
627139
|
+
if (existsSync116(path))
|
|
627063
627140
|
unlinkSync5(path);
|
|
627064
627141
|
} catch {}
|
|
627065
627142
|
}
|
|
@@ -627119,7 +627196,7 @@ function splitIntoSentences(text) {
|
|
|
627119
627196
|
}
|
|
627120
627197
|
// packages/voice/full-duplex-provider.ts
|
|
627121
627198
|
import { execSync as execSync6 } from "node:child_process";
|
|
627122
|
-
import { existsSync as
|
|
627199
|
+
import { existsSync as existsSync117 } from "node:fs";
|
|
627123
627200
|
import { homedir as homedir87 } from "node:os";
|
|
627124
627201
|
import { join as join174 } from "node:path";
|
|
627125
627202
|
var MOSHI_HF_CACHE_PATH = join174(homedir87(), ".cache", "huggingface", "hub", "models--kyutai--moshiko-pytorch-bf16", "snapshots");
|
|
@@ -627137,7 +627214,7 @@ async function detectCapabilities() {
|
|
|
627137
627214
|
const hasAppleSilicon = platform === "darwin" && arch === "arm64";
|
|
627138
627215
|
const hasMLX = hasAppleSilicon && tryExec('python3 -c "import mlx"');
|
|
627139
627216
|
const hasMoshiInstalled = tryExec('python3 -c "import moshi"');
|
|
627140
|
-
const hasMoshiModel =
|
|
627217
|
+
const hasMoshiModel = existsSync117(MOSHI_HF_CACHE_PATH);
|
|
627141
627218
|
const hasCUDA = tryExec("nvidia-smi");
|
|
627142
627219
|
const hasNIMKey = !!process.env.NVIDIA_NIM_KEY;
|
|
627143
627220
|
return {
|
|
@@ -628169,7 +628246,7 @@ function useWorkspaceTabs() {
|
|
|
628169
628246
|
|
|
628170
628247
|
// apps/tui/src/lib/adhd-audio.ts
|
|
628171
628248
|
init_bun_shim();
|
|
628172
|
-
import { existsSync as
|
|
628249
|
+
import { existsSync as existsSync119, mkdirSync as mkdirSync82 } from "node:fs";
|
|
628173
628250
|
import { join as join177 } from "node:path";
|
|
628174
628251
|
var DEFAULT_CONFIG4 = {
|
|
628175
628252
|
duration: 180,
|
|
@@ -628213,7 +628290,7 @@ var CACHE_DIR3 = join177(process.env.HOME || "~", ".8gent", "adhd-audio");
|
|
|
628213
628290
|
var CONFIG_PATH = join177(CACHE_DIR3, "config.json");
|
|
628214
628291
|
function loadConfig2() {
|
|
628215
628292
|
try {
|
|
628216
|
-
if (
|
|
628293
|
+
if (existsSync119(CONFIG_PATH)) {
|
|
628217
628294
|
const raw = JSON.parse(__require("node:fs").readFileSync(CONFIG_PATH, "utf-8"));
|
|
628218
628295
|
return { ...DEFAULT_CONFIG4, ...raw };
|
|
628219
628296
|
}
|
|
@@ -628222,7 +628299,7 @@ function loadConfig2() {
|
|
|
628222
628299
|
}
|
|
628223
628300
|
function saveConfig2(config) {
|
|
628224
628301
|
try {
|
|
628225
|
-
if (!
|
|
628302
|
+
if (!existsSync119(CACHE_DIR3))
|
|
628226
628303
|
mkdirSync82(CACHE_DIR3, { recursive: true });
|
|
628227
628304
|
__require("node:fs").writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
628228
628305
|
} catch {}
|
|
@@ -628234,7 +628311,7 @@ class ADHDAudio {
|
|
|
628234
628311
|
generating = false;
|
|
628235
628312
|
_config;
|
|
628236
628313
|
constructor() {
|
|
628237
|
-
if (!
|
|
628314
|
+
if (!existsSync119(CACHE_DIR3)) {
|
|
628238
628315
|
mkdirSync82(CACHE_DIR3, { recursive: true });
|
|
628239
628316
|
}
|
|
628240
628317
|
this._config = loadConfig2();
|
|
@@ -628261,7 +628338,7 @@ class ADHDAudio {
|
|
|
628261
628338
|
for (const soundscape of Object.keys(SOUNDSCAPES)) {
|
|
628262
628339
|
const path = this.getCachePath(soundscape);
|
|
628263
628340
|
try {
|
|
628264
|
-
if (
|
|
628341
|
+
if (existsSync119(path))
|
|
628265
628342
|
__require("node:fs").unlinkSync(path);
|
|
628266
628343
|
} catch {}
|
|
628267
628344
|
}
|
|
@@ -628280,7 +628357,7 @@ class ADHDAudio {
|
|
|
628280
628357
|
return join177(CACHE_DIR3, `${soundscape}.mp3`);
|
|
628281
628358
|
}
|
|
628282
628359
|
hasCached(soundscape) {
|
|
628283
|
-
return
|
|
628360
|
+
return existsSync119(this.getCachePath(soundscape));
|
|
628284
628361
|
}
|
|
628285
628362
|
async generate(soundscape) {
|
|
628286
628363
|
const preset = SOUNDSCAPES[soundscape];
|
|
@@ -633185,7 +633262,7 @@ function snapshot(manager) {
|
|
|
633185
633262
|
|
|
633186
633263
|
// apps/tui/src/hooks/useBodyParts.ts
|
|
633187
633264
|
var import_react83 = __toESM(require_react(), 1);
|
|
633188
|
-
import { existsSync as
|
|
633265
|
+
import { existsSync as existsSync124 } from "node:fs";
|
|
633189
633266
|
import { execSync as execSync8 } from "node:child_process";
|
|
633190
633267
|
import { homedir as homedir90 } from "node:os";
|
|
633191
633268
|
import { join as join188 } from "node:path";
|
|
@@ -633199,7 +633276,7 @@ function hasCliclick() {
|
|
|
633199
633276
|
}
|
|
633200
633277
|
}
|
|
633201
633278
|
function hasAxBridge() {
|
|
633202
|
-
return
|
|
633279
|
+
return existsSync124(join188(homedir90(), ".8gent", "bin", "8gent-ax-bridge"));
|
|
633203
633280
|
}
|
|
633204
633281
|
function detectDefaultBodyPartsState() {
|
|
633205
633282
|
const handsOk = hasCliclick();
|
|
@@ -634787,6 +634864,24 @@ ${r.message}`;
|
|
|
634787
634864
|
// apps/tui/src/app.tsx
|
|
634788
634865
|
init_slash_commands();
|
|
634789
634866
|
|
|
634867
|
+
// apps/tui/src/lib/term-intent.ts
|
|
634868
|
+
var VERBS2 = "run|open|start|launch|fire up|spin up|boot";
|
|
634869
|
+
var POLITE = "(?:please\\s+|can you\\s+|could you\\s+)?";
|
|
634870
|
+
var WHERE = "(?:\\s+in\\s+(?:a\\s+)?(?:new\\s+)?(?:tab|terminal(?:\\s+tab)?))?";
|
|
634871
|
+
var PRESET_INTENT = new RegExp(`^${POLITE}(?:${VERBS2})\\s+(?:up\\s+)?([a-z0-9][a-z0-9_-]*)(${WHERE})(?:\\s+please)?$`);
|
|
634872
|
+
function detectTermPresetIntent(input, presetIds) {
|
|
634873
|
+
const text = input.trim().toLowerCase().replace(/[.!?]+$/, "").replace(/\s+/g, " ");
|
|
634874
|
+
if (!text || text.length > 60)
|
|
634875
|
+
return null;
|
|
634876
|
+
const m = PRESET_INTENT.exec(text);
|
|
634877
|
+
if (!m)
|
|
634878
|
+
return null;
|
|
634879
|
+
const id = presetIds.find((p) => p.toLowerCase() === m[1]);
|
|
634880
|
+
if (!id)
|
|
634881
|
+
return null;
|
|
634882
|
+
return m[2] ? [id, "--in-tab"] : [id];
|
|
634883
|
+
}
|
|
634884
|
+
|
|
634790
634885
|
// apps/tui/src/lib/turn-outcome.ts
|
|
634791
634886
|
init_local_turn_error();
|
|
634792
634887
|
function turnEndedInError(messages) {
|
|
@@ -634804,7 +634899,7 @@ function turnEndedInError(messages) {
|
|
|
634804
634899
|
}
|
|
634805
634900
|
|
|
634806
634901
|
// apps/tui/src/screens/BTWView.tsx
|
|
634807
|
-
import { existsSync as
|
|
634902
|
+
import { existsSync as existsSync126, mkdirSync as mkdirSync89, readFileSync as readFileSync113, writeFileSync as writeFileSync69 } from "node:fs";
|
|
634808
634903
|
import { join as join190 } from "node:path";
|
|
634809
634904
|
var import_react85 = __toESM(require_react(), 1);
|
|
634810
634905
|
|
|
@@ -634820,10 +634915,10 @@ var jsx_dev_runtime50 = __toESM(require_jsx_dev_runtime(), 1);
|
|
|
634820
634915
|
var DATA_DIR5 = join190(process.env.HOME || "~", ".8gent", "tabs");
|
|
634821
634916
|
function loadBTW() {
|
|
634822
634917
|
try {
|
|
634823
|
-
if (!
|
|
634918
|
+
if (!existsSync126(DATA_DIR5))
|
|
634824
634919
|
mkdirSync89(DATA_DIR5, { recursive: true });
|
|
634825
634920
|
const filepath = join190(DATA_DIR5, "btw.json");
|
|
634826
|
-
if (
|
|
634921
|
+
if (existsSync126(filepath)) {
|
|
634827
634922
|
const raw = JSON.parse(readFileSync113(filepath, "utf-8"));
|
|
634828
634923
|
return raw.items || [];
|
|
634829
634924
|
}
|
|
@@ -634832,7 +634927,7 @@ function loadBTW() {
|
|
|
634832
634927
|
}
|
|
634833
634928
|
function saveBTW(items) {
|
|
634834
634929
|
try {
|
|
634835
|
-
if (!
|
|
634930
|
+
if (!existsSync126(DATA_DIR5))
|
|
634836
634931
|
mkdirSync89(DATA_DIR5, { recursive: true });
|
|
634837
634932
|
writeFileSync69(join190(DATA_DIR5, "btw.json"), JSON.stringify({ items }, null, 2));
|
|
634838
634933
|
} catch {}
|
|
@@ -635167,17 +635262,17 @@ function HistoryScreen({ conversations, onSelect, onBack }) {
|
|
|
635167
635262
|
}
|
|
635168
635263
|
|
|
635169
635264
|
// apps/tui/src/screens/IdeasView.tsx
|
|
635170
|
-
import { existsSync as
|
|
635265
|
+
import { existsSync as existsSync127, mkdirSync as mkdirSync90, readFileSync as readFileSync114, writeFileSync as writeFileSync70 } from "node:fs";
|
|
635171
635266
|
import { join as join191 } from "node:path";
|
|
635172
635267
|
var import_react87 = __toESM(require_react(), 1);
|
|
635173
635268
|
var jsx_dev_runtime52 = __toESM(require_jsx_dev_runtime(), 1);
|
|
635174
635269
|
var DATA_DIR6 = join191(process.env.HOME || "~", ".8gent", "tabs");
|
|
635175
635270
|
function loadIdeas() {
|
|
635176
635271
|
try {
|
|
635177
|
-
if (!
|
|
635272
|
+
if (!existsSync127(DATA_DIR6))
|
|
635178
635273
|
mkdirSync90(DATA_DIR6, { recursive: true });
|
|
635179
635274
|
const filepath = join191(DATA_DIR6, "ideas.json");
|
|
635180
|
-
if (
|
|
635275
|
+
if (existsSync127(filepath)) {
|
|
635181
635276
|
const raw = JSON.parse(readFileSync114(filepath, "utf-8"));
|
|
635182
635277
|
return raw.ideas || [];
|
|
635183
635278
|
}
|
|
@@ -635186,7 +635281,7 @@ function loadIdeas() {
|
|
|
635186
635281
|
}
|
|
635187
635282
|
function saveIdeas(ideas) {
|
|
635188
635283
|
try {
|
|
635189
|
-
if (!
|
|
635284
|
+
if (!existsSync127(DATA_DIR6))
|
|
635190
635285
|
mkdirSync90(DATA_DIR6, { recursive: true });
|
|
635191
635286
|
writeFileSync70(join191(DATA_DIR6, "ideas.json"), JSON.stringify({ ideas }, null, 2));
|
|
635192
635287
|
} catch {}
|
|
@@ -635649,7 +635744,7 @@ function KeyVaultScreen({
|
|
|
635649
635744
|
}
|
|
635650
635745
|
|
|
635651
635746
|
// apps/tui/src/screens/MusicPlayerView.tsx
|
|
635652
|
-
import { existsSync as
|
|
635747
|
+
import { existsSync as existsSync128, readdirSync as readdirSync28, statSync as statSync39 } from "node:fs";
|
|
635653
635748
|
import { basename as basename53, join as join192 } from "node:path";
|
|
635654
635749
|
var import_react89 = __toESM(require_react(), 1);
|
|
635655
635750
|
var jsx_dev_runtime54 = __toESM(require_jsx_dev_runtime(), 1);
|
|
@@ -635671,7 +635766,7 @@ function formatDate(date) {
|
|
|
635671
635766
|
}
|
|
635672
635767
|
function loadTracks(currentTrack) {
|
|
635673
635768
|
const tracks = [];
|
|
635674
|
-
if (!
|
|
635769
|
+
if (!existsSync128(CACHE_DIR4))
|
|
635675
635770
|
return tracks;
|
|
635676
635771
|
try {
|
|
635677
635772
|
const files = readdirSync28(CACHE_DIR4).filter((f) => f.endsWith(".mp3") || f.endsWith(".wav"));
|
|
@@ -636180,7 +636275,7 @@ function NarratorView({ tasks, narratorText, maxHeight }) {
|
|
|
636180
636275
|
}
|
|
636181
636276
|
|
|
636182
636277
|
// apps/tui/src/screens/NotesView.tsx
|
|
636183
|
-
import { existsSync as
|
|
636278
|
+
import { existsSync as existsSync129, mkdirSync as mkdirSync91, readFileSync as readFileSync115, writeFileSync as writeFileSync71 } from "node:fs";
|
|
636184
636279
|
import { join as join193 } from "node:path";
|
|
636185
636280
|
var import_react91 = __toESM(require_react(), 1);
|
|
636186
636281
|
var jsx_dev_runtime59 = __toESM(require_jsx_dev_runtime(), 1);
|
|
@@ -636188,10 +636283,10 @@ var DATA_DIR7 = join193(process.env.HOME || "~", ".8gent", "tabs");
|
|
|
636188
636283
|
var EMPTY_TAB_NAMES = [];
|
|
636189
636284
|
function loadNotes() {
|
|
636190
636285
|
try {
|
|
636191
|
-
if (!
|
|
636286
|
+
if (!existsSync129(DATA_DIR7))
|
|
636192
636287
|
mkdirSync91(DATA_DIR7, { recursive: true });
|
|
636193
636288
|
const filepath = join193(DATA_DIR7, "notes.json");
|
|
636194
|
-
if (
|
|
636289
|
+
if (existsSync129(filepath)) {
|
|
636195
636290
|
const raw = JSON.parse(readFileSync115(filepath, "utf-8"));
|
|
636196
636291
|
return raw.notes || [];
|
|
636197
636292
|
}
|
|
@@ -636200,7 +636295,7 @@ function loadNotes() {
|
|
|
636200
636295
|
}
|
|
636201
636296
|
function saveNotes(notes) {
|
|
636202
636297
|
try {
|
|
636203
|
-
if (!
|
|
636298
|
+
if (!existsSync129(DATA_DIR7))
|
|
636204
636299
|
mkdirSync91(DATA_DIR7, { recursive: true });
|
|
636205
636300
|
writeFileSync71(join193(DATA_DIR7, "notes.json"), JSON.stringify({ notes }, null, 2));
|
|
636206
636301
|
} catch {}
|
|
@@ -637395,7 +637490,7 @@ function OnboardingScreen({
|
|
|
637395
637490
|
|
|
637396
637491
|
// apps/tui/src/screens/ProjectsView.tsx
|
|
637397
637492
|
import { execSync as execSync9 } from "node:child_process";
|
|
637398
|
-
import { existsSync as
|
|
637493
|
+
import { existsSync as existsSync130, mkdirSync as mkdirSync92, readFileSync as readFileSync116, readdirSync as readdirSync29, statSync as statSync40, writeFileSync as writeFileSync72 } from "node:fs";
|
|
637399
637494
|
import { homedir as homedir91 } from "node:os";
|
|
637400
637495
|
import { basename as basename54, join as join194 } from "node:path";
|
|
637401
637496
|
var import_react96 = __toESM(require_react(), 1);
|
|
@@ -637410,7 +637505,7 @@ var SCAN_DIRS = [
|
|
|
637410
637505
|
var PROJECT_MARKERS = ["package.json", ".git", "CLAUDE.md", ".8gent"];
|
|
637411
637506
|
function isProjectDir(dirPath) {
|
|
637412
637507
|
try {
|
|
637413
|
-
return PROJECT_MARKERS.some((marker) =>
|
|
637508
|
+
return PROJECT_MARKERS.some((marker) => existsSync130(join194(dirPath, marker)));
|
|
637414
637509
|
} catch {
|
|
637415
637510
|
return false;
|
|
637416
637511
|
}
|
|
@@ -637418,7 +637513,7 @@ function isProjectDir(dirPath) {
|
|
|
637418
637513
|
function getProjectName(dirPath) {
|
|
637419
637514
|
try {
|
|
637420
637515
|
const pkgPath = join194(dirPath, "package.json");
|
|
637421
|
-
if (
|
|
637516
|
+
if (existsSync130(pkgPath)) {
|
|
637422
637517
|
const pkg = JSON.parse(readFileSync116(pkgPath, "utf8"));
|
|
637423
637518
|
if (pkg.name)
|
|
637424
637519
|
return pkg.name;
|
|
@@ -637428,7 +637523,7 @@ function getProjectName(dirPath) {
|
|
|
637428
637523
|
}
|
|
637429
637524
|
function getGitBranch2(dirPath) {
|
|
637430
637525
|
try {
|
|
637431
|
-
if (!
|
|
637526
|
+
if (!existsSync130(join194(dirPath, ".git")))
|
|
637432
637527
|
return;
|
|
637433
637528
|
const result = execSync9(`git -C "${dirPath}" branch --show-current 2>/dev/null`, {
|
|
637434
637529
|
encoding: "utf8",
|
|
@@ -637448,7 +637543,7 @@ function getLastModified(dirPath) {
|
|
|
637448
637543
|
}
|
|
637449
637544
|
}
|
|
637450
637545
|
function has8gent(dirPath) {
|
|
637451
|
-
return
|
|
637546
|
+
return existsSync130(join194(dirPath, ".8gent"));
|
|
637452
637547
|
}
|
|
637453
637548
|
function buildProjectEntry(dirPath) {
|
|
637454
637549
|
return {
|
|
@@ -637465,7 +637560,7 @@ function scanForProjects(currentPath) {
|
|
|
637465
637560
|
found.add(currentPath);
|
|
637466
637561
|
results.push(buildProjectEntry(currentPath));
|
|
637467
637562
|
for (const scanDir of SCAN_DIRS) {
|
|
637468
|
-
if (!
|
|
637563
|
+
if (!existsSync130(scanDir))
|
|
637469
637564
|
continue;
|
|
637470
637565
|
try {
|
|
637471
637566
|
const entries = readdirSync29(scanDir, { withFileTypes: true });
|
|
@@ -637497,7 +637592,7 @@ function scanForProjects(currentPath) {
|
|
|
637497
637592
|
}
|
|
637498
637593
|
function loadSavedProjects() {
|
|
637499
637594
|
try {
|
|
637500
|
-
if (!
|
|
637595
|
+
if (!existsSync130(SAVED_PROJECTS_PATH))
|
|
637501
637596
|
return [];
|
|
637502
637597
|
const raw = readFileSync116(SAVED_PROJECTS_PATH, "utf8");
|
|
637503
637598
|
const data = JSON.parse(raw);
|
|
@@ -637520,7 +637615,7 @@ function mergeProjects(scanned, saved) {
|
|
|
637520
637615
|
for (const s of saved) {
|
|
637521
637616
|
if (paths.has(s.path))
|
|
637522
637617
|
continue;
|
|
637523
|
-
if (!
|
|
637618
|
+
if (!existsSync130(s.path))
|
|
637524
637619
|
continue;
|
|
637525
637620
|
paths.add(s.path);
|
|
637526
637621
|
extra.push(buildProjectEntry(s.path));
|
|
@@ -637588,7 +637683,7 @@ function ProjectsView({
|
|
|
637588
637683
|
if (addMode) {
|
|
637589
637684
|
if (key.return) {
|
|
637590
637685
|
const trimmed = addInput.trim();
|
|
637591
|
-
if (trimmed &&
|
|
637686
|
+
if (trimmed && existsSync130(trimmed)) {
|
|
637592
637687
|
const newEntry = {
|
|
637593
637688
|
...buildProjectEntry(trimmed),
|
|
637594
637689
|
addedAt: new Date().toISOString()
|
|
@@ -637775,17 +637870,17 @@ function ProjectsView({
|
|
|
637775
637870
|
}
|
|
637776
637871
|
|
|
637777
637872
|
// apps/tui/src/screens/QuestionsView.tsx
|
|
637778
|
-
import { existsSync as
|
|
637873
|
+
import { existsSync as existsSync131, mkdirSync as mkdirSync93, readFileSync as readFileSync117, writeFileSync as writeFileSync73 } from "node:fs";
|
|
637779
637874
|
import { join as join195 } from "node:path";
|
|
637780
637875
|
var import_react97 = __toESM(require_react(), 1);
|
|
637781
637876
|
var jsx_dev_runtime62 = __toESM(require_jsx_dev_runtime(), 1);
|
|
637782
637877
|
var DATA_DIR8 = join195(process.env.HOME || "~", ".8gent", "tabs");
|
|
637783
637878
|
function loadQuestions() {
|
|
637784
637879
|
try {
|
|
637785
|
-
if (!
|
|
637880
|
+
if (!existsSync131(DATA_DIR8))
|
|
637786
637881
|
mkdirSync93(DATA_DIR8, { recursive: true });
|
|
637787
637882
|
const filepath = join195(DATA_DIR8, "questions.json");
|
|
637788
|
-
if (
|
|
637883
|
+
if (existsSync131(filepath)) {
|
|
637789
637884
|
const raw = JSON.parse(readFileSync117(filepath, "utf-8"));
|
|
637790
637885
|
return raw.questions || [];
|
|
637791
637886
|
}
|
|
@@ -637794,7 +637889,7 @@ function loadQuestions() {
|
|
|
637794
637889
|
}
|
|
637795
637890
|
function saveQuestions(questions) {
|
|
637796
637891
|
try {
|
|
637797
|
-
if (!
|
|
637892
|
+
if (!existsSync131(DATA_DIR8))
|
|
637798
637893
|
mkdirSync93(DATA_DIR8, { recursive: true });
|
|
637799
637894
|
writeFileSync73(join195(DATA_DIR8, "questions.json"), JSON.stringify({ questions }, null, 2));
|
|
637800
637895
|
} catch {}
|
|
@@ -639082,13 +639177,13 @@ import * as fs104 from "node:fs";
|
|
|
639082
639177
|
import * as pathMod from "node:path";
|
|
639083
639178
|
|
|
639084
639179
|
// apps/tui/src/lib/package-scripts.ts
|
|
639085
|
-
import { existsSync as
|
|
639086
|
-
import { join as join196, resolve as
|
|
639180
|
+
import { existsSync as existsSync132 } from "node:fs";
|
|
639181
|
+
import { join as join196, resolve as resolve74 } from "node:path";
|
|
639087
639182
|
var __dirname = (import.meta.dirname + "/../../apps/tui/src/lib");
|
|
639088
|
-
var PACKAGE_ROOT =
|
|
639183
|
+
var PACKAGE_ROOT = resolve74(__dirname, "../../../..");
|
|
639089
639184
|
function packageBinScript(name, root = PACKAGE_ROOT) {
|
|
639090
639185
|
const candidate = join196(root, "bin", name);
|
|
639091
|
-
return
|
|
639186
|
+
return existsSync132(candidate) ? candidate : null;
|
|
639092
639187
|
}
|
|
639093
639188
|
|
|
639094
639189
|
// apps/tui/src/app.tsx
|
|
@@ -644012,6 +644107,26 @@ ${found.slice(0, 40).map((k) => ` ${k.name} ${k.description}`).join(`
|
|
|
644012
644107
|
}
|
|
644013
644108
|
return;
|
|
644014
644109
|
}
|
|
644110
|
+
if (input && !attached) {
|
|
644111
|
+
const termArgs = detectTermPresetIntent(input, listPresetIds());
|
|
644112
|
+
if (termArgs) {
|
|
644113
|
+
appendToTab(tabId, {
|
|
644114
|
+
id: `user-${Date.now()}`,
|
|
644115
|
+
role: "user",
|
|
644116
|
+
content: bubbleContent,
|
|
644117
|
+
timestamp: new Date
|
|
644118
|
+
});
|
|
644119
|
+
setRecentCommands((prev) => [bubbleContent, ...prev].slice(0, 20));
|
|
644120
|
+
const refused = planModeRefusal2(permView(permHolderFor(tabId)).mode);
|
|
644121
|
+
if (refused) {
|
|
644122
|
+
addSystemMessage(refused);
|
|
644123
|
+
return;
|
|
644124
|
+
}
|
|
644125
|
+
addSystemMessage(`Opening ${termArgs[0]} (same as /term ${termArgs.join(" ")}).`);
|
|
644126
|
+
handleSlashCommand("term", termArgs);
|
|
644127
|
+
return;
|
|
644128
|
+
}
|
|
644129
|
+
}
|
|
644015
644130
|
if (input && !attached) {
|
|
644016
644131
|
const buildTask = detectBuildIntent(input);
|
|
644017
644132
|
if (buildTask) {
|