negotium 0.2.16 → 0.2.17
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/agent-helpers.js +44 -8
- package/dist/agent-helpers.js.map +8 -8
- package/dist/background-bash.js.map +1 -1
- package/dist/browser-runtime.js.map +1 -1
- package/dist/chunk-5cpdbbeh.js.map +1 -1
- package/dist/hosted-agent.js +3 -2
- package/dist/hosted-agent.js.map +5 -5
- package/dist/main.js +568 -395
- package/dist/main.js.map +16 -15
- package/dist/mcp-factories.js +44 -8
- package/dist/mcp-factories.js.map +8 -8
- package/dist/prompts.js.map +1 -1
- package/dist/query-runtime.js.map +1 -1
- package/dist/registry.js +2 -2
- package/dist/registry.js.map +2 -2
- package/dist/runtime/src/agents/compaction-support.ts +1 -1
- package/dist/runtime/src/agents/maestro-provider.ts +3 -0
- package/dist/runtime/src/index.ts +1 -0
- package/dist/runtime/src/runtime/turn-event-stream.ts +26 -0
- package/dist/runtime/src/runtime/turn-runner.ts +20 -9
- package/dist/runtime/src/types.ts +6 -0
- package/dist/runtime/src/version.ts +1 -1
- package/dist/runtime-helpers.js.map +1 -1
- package/dist/storage.js.map +1 -1
- package/dist/types/packages/core/src/agents/compaction-support.d.ts +1 -0
- package/dist/types/packages/core/src/runtime/turn-runner.d.ts +4 -0
- package/dist/types/packages/core/src/types.d.ts +6 -0
- package/dist/types/packages/core/src/version.d.ts +1 -1
- package/dist/vault.js.map +1 -1
- package/package.json +2 -2
package/dist/main.js
CHANGED
|
@@ -1010,6 +1010,70 @@ var init_codex_tree_kill = __esm(() => {
|
|
|
1010
1010
|
killOwnedCodexTreesForShutdown = manager.killOwnedTreesForShutdown;
|
|
1011
1011
|
});
|
|
1012
1012
|
|
|
1013
|
+
// ../../packages/core/src/agents/compaction-support.ts
|
|
1014
|
+
function isCjkCodePoint(code) {
|
|
1015
|
+
return code >= 12288 && code <= 19903 || code >= 19968 && code <= 40959 || code >= 4352 && code <= 4607 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65280 && code <= 65519 || code >= 131072 && code <= 262143;
|
|
1016
|
+
}
|
|
1017
|
+
function estimateTextTokens(text) {
|
|
1018
|
+
let cjkChars = 0;
|
|
1019
|
+
let cjkUnits = 0;
|
|
1020
|
+
for (let index = 0;index < text.length; index++) {
|
|
1021
|
+
const code = text.codePointAt(index) ?? 0;
|
|
1022
|
+
const wide = code > 65535;
|
|
1023
|
+
if (wide)
|
|
1024
|
+
index++;
|
|
1025
|
+
if (isCjkCodePoint(code)) {
|
|
1026
|
+
cjkChars++;
|
|
1027
|
+
cjkUnits += wide ? 2 : 1;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
const latinUnits = text.length - cjkUnits;
|
|
1031
|
+
return Math.ceil(cjkChars / CHARS_PER_CJK_TOKEN + latinUnits / CHARS_PER_TEXT_TOKEN);
|
|
1032
|
+
}
|
|
1033
|
+
function estimateConversationTokens(messages) {
|
|
1034
|
+
return messages.reduce((sum, message) => sum + 4 + estimateTextTokens(message.content), 0);
|
|
1035
|
+
}
|
|
1036
|
+
var ACTIVE_TASK_TEMPLATE = `You are compressing a long agent conversation so the main agent can continue
|
|
1037
|
+
without losing context. Produce a single concise summary using EXACTLY these
|
|
1038
|
+
section headers, in this order:
|
|
1039
|
+
|
|
1040
|
+
## Active Task
|
|
1041
|
+
One sentence: what is the agent currently working on?
|
|
1042
|
+
|
|
1043
|
+
## Goal
|
|
1044
|
+
One or two sentences: the user's overall objective in this session.
|
|
1045
|
+
|
|
1046
|
+
## Constraints
|
|
1047
|
+
Bulleted list of durable requirements, user preferences, technical limits, or
|
|
1048
|
+
process rules that should continue to govern the work. Skip if none.
|
|
1049
|
+
|
|
1050
|
+
## Key Decisions
|
|
1051
|
+
Bulleted list of decisions already made that should not be reopened unless the
|
|
1052
|
+
user asks. Include the rationale when it is short and important. Skip if none.
|
|
1053
|
+
|
|
1054
|
+
## Pending
|
|
1055
|
+
Bulleted list of unresolved items, decisions to make, or work explicitly
|
|
1056
|
+
deferred. Use "(blocked: <reason>)" when applicable.
|
|
1057
|
+
|
|
1058
|
+
## Next Steps
|
|
1059
|
+
Bulleted list of the concrete next actions the main agent should take after
|
|
1060
|
+
compaction, in likely execution order. Skip if none.
|
|
1061
|
+
|
|
1062
|
+
## Files
|
|
1063
|
+
Bulleted list of \`absolute/paths\` touched or referenced (read, written,
|
|
1064
|
+
inspected). Skip if none.
|
|
1065
|
+
|
|
1066
|
+
## Recent context
|
|
1067
|
+
3-5 bullets capturing the most recent tool calls + their salient outputs.
|
|
1068
|
+
Prefer specifics (paths, line numbers, exit codes, key values) over generic
|
|
1069
|
+
recaps. Skip details that have no bearing on the next step.
|
|
1070
|
+
|
|
1071
|
+
RULES:
|
|
1072
|
+
- Output ONLY the eight sections above, with no preamble or postscript.
|
|
1073
|
+
- Do NOT echo the user's words verbatim - paraphrase tightly.
|
|
1074
|
+
- Do NOT invent file paths or facts not present in the transcript.
|
|
1075
|
+
- Keep the entire summary under 1500 words.`, CHARS_PER_TEXT_TOKEN = 3.5, CHARS_PER_CJK_TOKEN = 0.9;
|
|
1076
|
+
|
|
1013
1077
|
// ../../packages/core/src/runtime/user-turn-envelope.ts
|
|
1014
1078
|
function legacyUserTurnEnvelope(prompt, attachments) {
|
|
1015
1079
|
return attachments?.length ? { prompt, attachments } : { prompt };
|
|
@@ -1572,7 +1636,7 @@ var exports_version = {};
|
|
|
1572
1636
|
__export(exports_version, {
|
|
1573
1637
|
NEGOTIUM_VERSION: () => NEGOTIUM_VERSION
|
|
1574
1638
|
});
|
|
1575
|
-
var NEGOTIUM_VERSION = "0.2.
|
|
1639
|
+
var NEGOTIUM_VERSION = "0.2.17";
|
|
1576
1640
|
|
|
1577
1641
|
// ../../packages/core/src/agents/codex-native-multi-agent.ts
|
|
1578
1642
|
import { spawn } from "child_process";
|
|
@@ -6427,6 +6491,7 @@ function maestroProvider(opts) {
|
|
|
6427
6491
|
...opts,
|
|
6428
6492
|
enableToolSearch: !opts.toolPolicy && opts.enableToolSearch !== false,
|
|
6429
6493
|
toolResultTruncation: buildMaestroToolResultTruncation(opts),
|
|
6494
|
+
ephemeralSystemPrompt: opts.ephemeralSystemPrompt,
|
|
6430
6495
|
apiKeyOverrides: resolveMaestroApiKeyOverrides(userId),
|
|
6431
6496
|
agent: "maestro",
|
|
6432
6497
|
disallowedTools: buildMaestroDisallowedTools(callerDisallowedTools, opts.toolPolicy),
|
|
@@ -11321,70 +11386,6 @@ var init_personal_general = __esm(async () => {
|
|
|
11321
11386
|
]);
|
|
11322
11387
|
});
|
|
11323
11388
|
|
|
11324
|
-
// ../../packages/core/src/agents/compaction-support.ts
|
|
11325
|
-
function isCjkCodePoint(code) {
|
|
11326
|
-
return code >= 12288 && code <= 19903 || code >= 19968 && code <= 40959 || code >= 4352 && code <= 4607 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65280 && code <= 65519 || code >= 131072 && code <= 262143;
|
|
11327
|
-
}
|
|
11328
|
-
function estimateTextTokens(text) {
|
|
11329
|
-
let cjkChars = 0;
|
|
11330
|
-
let cjkUnits = 0;
|
|
11331
|
-
for (let index = 0;index < text.length; index++) {
|
|
11332
|
-
const code = text.codePointAt(index) ?? 0;
|
|
11333
|
-
const wide = code > 65535;
|
|
11334
|
-
if (wide)
|
|
11335
|
-
index++;
|
|
11336
|
-
if (isCjkCodePoint(code)) {
|
|
11337
|
-
cjkChars++;
|
|
11338
|
-
cjkUnits += wide ? 2 : 1;
|
|
11339
|
-
}
|
|
11340
|
-
}
|
|
11341
|
-
const latinUnits = text.length - cjkUnits;
|
|
11342
|
-
return Math.ceil(cjkChars / CHARS_PER_CJK_TOKEN + latinUnits / CHARS_PER_TEXT_TOKEN);
|
|
11343
|
-
}
|
|
11344
|
-
function estimateConversationTokens(messages) {
|
|
11345
|
-
return messages.reduce((sum, message) => sum + 4 + estimateTextTokens(message.content), 0);
|
|
11346
|
-
}
|
|
11347
|
-
var ACTIVE_TASK_TEMPLATE = `You are compressing a long agent conversation so the main agent can continue
|
|
11348
|
-
without losing context. Produce a single concise summary using EXACTLY these
|
|
11349
|
-
section headers, in this order:
|
|
11350
|
-
|
|
11351
|
-
## Active Task
|
|
11352
|
-
One sentence: what is the agent currently working on?
|
|
11353
|
-
|
|
11354
|
-
## Goal
|
|
11355
|
-
One or two sentences: the user's overall objective in this session.
|
|
11356
|
-
|
|
11357
|
-
## Constraints
|
|
11358
|
-
Bulleted list of durable requirements, user preferences, technical limits, or
|
|
11359
|
-
process rules that should continue to govern the work. Skip if none.
|
|
11360
|
-
|
|
11361
|
-
## Key Decisions
|
|
11362
|
-
Bulleted list of decisions already made that should not be reopened unless the
|
|
11363
|
-
user asks. Include the rationale when it is short and important. Skip if none.
|
|
11364
|
-
|
|
11365
|
-
## Pending
|
|
11366
|
-
Bulleted list of unresolved items, decisions to make, or work explicitly
|
|
11367
|
-
deferred. Use "(blocked: <reason>)" when applicable.
|
|
11368
|
-
|
|
11369
|
-
## Next Steps
|
|
11370
|
-
Bulleted list of the concrete next actions the main agent should take after
|
|
11371
|
-
compaction, in likely execution order. Skip if none.
|
|
11372
|
-
|
|
11373
|
-
## Files
|
|
11374
|
-
Bulleted list of \`absolute/paths\` touched or referenced (read, written,
|
|
11375
|
-
inspected). Skip if none.
|
|
11376
|
-
|
|
11377
|
-
## Recent context
|
|
11378
|
-
3-5 bullets capturing the most recent tool calls + their salient outputs.
|
|
11379
|
-
Prefer specifics (paths, line numbers, exit codes, key values) over generic
|
|
11380
|
-
recaps. Skip details that have no bearing on the next step.
|
|
11381
|
-
|
|
11382
|
-
RULES:
|
|
11383
|
-
- Output ONLY the eight sections above, with no preamble or postscript.
|
|
11384
|
-
- Do NOT echo the user's words verbatim - paraphrase tightly.
|
|
11385
|
-
- Do NOT invent file paths or facts not present in the transcript.
|
|
11386
|
-
- Keep the entire summary under 1500 words.`, CHARS_PER_TEXT_TOKEN = 3.5, CHARS_PER_CJK_TOKEN = 0.9;
|
|
11387
|
-
|
|
11388
11389
|
// ../../packages/core/src/prompts/builders.ts
|
|
11389
11390
|
import { readFileSync as readFileSync13 } from "fs";
|
|
11390
11391
|
import { resolve as resolve13 } from "path";
|
|
@@ -17209,6 +17210,9 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
17209
17210
|
let pendingSawDelta = false;
|
|
17210
17211
|
let accumulatedText = "";
|
|
17211
17212
|
let pendingText = "";
|
|
17213
|
+
let assistantContextTokens = 0;
|
|
17214
|
+
let toolContextTokens = 0;
|
|
17215
|
+
let lastContextProgressAt = 0;
|
|
17212
17216
|
let lastVisibleMessageId = null;
|
|
17213
17217
|
const visibleMessageIds = [];
|
|
17214
17218
|
let lastTaskPanelText = null;
|
|
@@ -17227,6 +17231,20 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
17227
17231
|
model
|
|
17228
17232
|
});
|
|
17229
17233
|
};
|
|
17234
|
+
const broadcastContextProgress = (force = false) => {
|
|
17235
|
+
if (silent)
|
|
17236
|
+
return;
|
|
17237
|
+
const now = Date.now();
|
|
17238
|
+
if (!force && lastContextProgressAt > 0 && now - lastContextProgressAt < 250)
|
|
17239
|
+
return;
|
|
17240
|
+
lastContextProgressAt = now;
|
|
17241
|
+
hub.broadcastAiStatus(topicId, {
|
|
17242
|
+
kind: "context_progress",
|
|
17243
|
+
queryId,
|
|
17244
|
+
assistantTokens: assistantContextTokens,
|
|
17245
|
+
toolTokens: toolContextTokens
|
|
17246
|
+
});
|
|
17247
|
+
};
|
|
17230
17248
|
const nextSyntheticToolUseId = () => `tool-${queryId}-${++syntheticToolCounter}`;
|
|
17231
17249
|
const bindToolUseId = (providerToolUseId, fallback) => {
|
|
17232
17250
|
const providerId = normalizeToolUseId(providerToolUseId);
|
|
@@ -17336,6 +17354,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
17336
17354
|
const incoming = event.content;
|
|
17337
17355
|
accumulatedText += incoming;
|
|
17338
17356
|
pendingText += incoming;
|
|
17357
|
+
assistantContextTokens = estimateTextTokens(accumulatedText);
|
|
17358
|
+
broadcastContextProgress();
|
|
17339
17359
|
break;
|
|
17340
17360
|
}
|
|
17341
17361
|
case "text":
|
|
@@ -17343,10 +17363,15 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
17343
17363
|
const incoming = event.content;
|
|
17344
17364
|
accumulatedText += incoming;
|
|
17345
17365
|
pendingText += incoming;
|
|
17366
|
+
assistantContextTokens = estimateTextTokens(accumulatedText);
|
|
17367
|
+
broadcastContextProgress();
|
|
17346
17368
|
}
|
|
17347
17369
|
break;
|
|
17348
17370
|
case "tool_use":
|
|
17349
17371
|
emitPendingAssistantMessage();
|
|
17372
|
+
toolContextTokens += estimateTextTokens(`${event.name}
|
|
17373
|
+
${JSON.stringify(event.input ?? {})}`);
|
|
17374
|
+
broadcastContextProgress(true);
|
|
17350
17375
|
if (isVisualsShowHtmlTool(event.name)) {
|
|
17351
17376
|
const input = event.input;
|
|
17352
17377
|
if (typeof input.html !== "string" || input.html.trim().length === 0) {
|
|
@@ -17500,6 +17525,8 @@ async function runTurnEventStream(topicId, topicTitle, queryId, events, control,
|
|
|
17500
17525
|
}
|
|
17501
17526
|
break;
|
|
17502
17527
|
case "tool_result":
|
|
17528
|
+
toolContextTokens += estimateTextTokens(event.content);
|
|
17529
|
+
broadcastContextProgress(true);
|
|
17503
17530
|
if (isVisualToolResultHandled(event.toolUseId))
|
|
17504
17531
|
break;
|
|
17505
17532
|
if (!silent) {
|
|
@@ -17900,6 +17927,7 @@ __export(exports_turn_runner, {
|
|
|
17900
17927
|
channelTranscriptSpeaker: () => channelTranscriptSpeaker,
|
|
17901
17928
|
canonicalModelId: () => canonicalModelId,
|
|
17902
17929
|
buildVideoHtml: () => buildVideoHtml,
|
|
17930
|
+
buildTurnReminderQuery: () => buildTurnReminderQuery,
|
|
17903
17931
|
buildMermaidHtml: () => buildMermaidHtml,
|
|
17904
17932
|
buildMentionOnlyChannelPrompt: () => buildMentionOnlyChannelPrompt,
|
|
17905
17933
|
buildImageHtml: () => buildImageHtml,
|
|
@@ -17925,6 +17953,18 @@ function withDefaultPlaywright(configuredMcp, isManager) {
|
|
|
17925
17953
|
enabled.add("background-bash");
|
|
17926
17954
|
return [...enabled];
|
|
17927
17955
|
}
|
|
17956
|
+
function buildTurnReminderQuery(agent, prompt, reminders) {
|
|
17957
|
+
const reminderPrompt = reminders.join(`
|
|
17958
|
+
|
|
17959
|
+
`);
|
|
17960
|
+
if (!reminderPrompt)
|
|
17961
|
+
return { prompt };
|
|
17962
|
+
if (agent === "maestro")
|
|
17963
|
+
return { prompt, ephemeralSystemPrompt: reminderPrompt };
|
|
17964
|
+
return { prompt: `${prompt}
|
|
17965
|
+
|
|
17966
|
+
${reminderPrompt}` };
|
|
17967
|
+
}
|
|
17928
17968
|
function appendSystemMessage(topicId, text2) {
|
|
17929
17969
|
const message = {
|
|
17930
17970
|
id: randomUUID16(),
|
|
@@ -18872,15 +18912,11 @@ function startAiTurn(params) {
|
|
|
18872
18912
|
if (consumePlaywrightUnavailable(userId, topic.title)) {
|
|
18873
18913
|
turnReminders.push("<system-reminder>Playwright browser tools are UNAVAILABLE this turn. The `mcp__playwright__*` tools have been removed from this turn's catalog because the long-lived browser MCP could not be prepared. Do not attempt to call browser tools. If browser interaction is required, ask the user to retry shortly or use a non-browser alternative.</system-reminder>");
|
|
18874
18914
|
}
|
|
18875
|
-
const
|
|
18876
|
-
|
|
18877
|
-
${turnReminders.join(`
|
|
18878
|
-
|
|
18879
|
-
`)}` : agentPrompt;
|
|
18915
|
+
const reminderQuery = buildTurnReminderQuery(agentKind, agentPrompt, turnReminders);
|
|
18880
18916
|
try {
|
|
18881
18917
|
yield* runAgent({
|
|
18882
18918
|
agent: agentKind,
|
|
18883
|
-
|
|
18919
|
+
...reminderQuery,
|
|
18884
18920
|
attachments: promptAttachments,
|
|
18885
18921
|
cwd: workspaceCwd,
|
|
18886
18922
|
systemPrompt,
|
|
@@ -22461,6 +22497,7 @@ __export(exports_src, {
|
|
|
22461
22497
|
extractFileEvents: () => extractFileEvents,
|
|
22462
22498
|
executeVaultCommand: () => executeVaultCommand,
|
|
22463
22499
|
executeExternalUserTurn: () => executeExternalUserTurn,
|
|
22500
|
+
estimateTextTokens: () => estimateTextTokens,
|
|
22464
22501
|
errorResult: () => errorResult,
|
|
22465
22502
|
errMsg: () => errMsg,
|
|
22466
22503
|
ensurePersonalGeneral: () => ensurePersonalGeneral,
|
|
@@ -30914,6 +30951,7 @@ var init_commands = __esm(() => {
|
|
|
30914
30951
|
{ name: "new", usage: "/new", description: "reset the current session" },
|
|
30915
30952
|
{ name: "compact", usage: "/compact", description: "summarize and shrink context" },
|
|
30916
30953
|
{ name: "status", usage: "/status", description: "show model and token usage" },
|
|
30954
|
+
{ name: "context", usage: "/context", description: "show live context breakdown" },
|
|
30917
30955
|
{ name: "model", usage: "/model", description: "choose the model" },
|
|
30918
30956
|
{ name: "effort", usage: "/effort", description: "choose reasoning effort" },
|
|
30919
30957
|
{ name: "topics", usage: "/topics", description: "open topic picker" },
|
|
@@ -30942,297 +30980,6 @@ var init_commands = __esm(() => {
|
|
|
30942
30980
|
];
|
|
30943
30981
|
});
|
|
30944
30982
|
|
|
30945
|
-
// ../../adapters/terminal/src/path-suggest.ts
|
|
30946
|
-
import { execFile as execFile3 } from "child_process";
|
|
30947
|
-
import { existsSync as existsSync33, readdirSync as readdirSync14, statSync as statSync19 } from "fs";
|
|
30948
|
-
import { homedir as homedir10 } from "os";
|
|
30949
|
-
import { basename as basename11, dirname as dirname19, join as join40, sep as sep3 } from "path";
|
|
30950
|
-
import { promisify as promisify3 } from "util";
|
|
30951
|
-
function indexRecursivePaths(files) {
|
|
30952
|
-
const paths = [];
|
|
30953
|
-
const directories = new Set;
|
|
30954
|
-
for (const relPath of files) {
|
|
30955
|
-
const segments = relPath.split("/");
|
|
30956
|
-
if (segments.some((segment) => segment.startsWith(".")))
|
|
30957
|
-
continue;
|
|
30958
|
-
for (let index = 0;index < segments.length - 1; index += 1) {
|
|
30959
|
-
const directory = segments.slice(0, index + 1).join("/");
|
|
30960
|
-
if (directories.has(directory))
|
|
30961
|
-
continue;
|
|
30962
|
-
directories.add(directory);
|
|
30963
|
-
paths.push({
|
|
30964
|
-
relPath: directory,
|
|
30965
|
-
isDir: true,
|
|
30966
|
-
lowerName: (segments[index] ?? "").toLowerCase()
|
|
30967
|
-
});
|
|
30968
|
-
}
|
|
30969
|
-
paths.push({ relPath, isDir: false, lowerName: (segments.at(-1) ?? "").toLowerCase() });
|
|
30970
|
-
}
|
|
30971
|
-
return paths;
|
|
30972
|
-
}
|
|
30973
|
-
async function listFilesWithRipgrep(dir) {
|
|
30974
|
-
const args = ["--files", "--max-depth", String(RECURSIVE_MAX_DEPTH)];
|
|
30975
|
-
for (const excluded of RECURSIVE_EXCLUDES)
|
|
30976
|
-
args.push("-g", `!${excluded}`);
|
|
30977
|
-
args.push(".");
|
|
30978
|
-
let out = "";
|
|
30979
|
-
try {
|
|
30980
|
-
const result = await execFileAsync3("rg", args, {
|
|
30981
|
-
cwd: dir,
|
|
30982
|
-
encoding: "utf8",
|
|
30983
|
-
timeout: RECURSIVE_TIMEOUT_MS,
|
|
30984
|
-
maxBuffer: 32 * 1024 * 1024
|
|
30985
|
-
});
|
|
30986
|
-
out = result.stdout;
|
|
30987
|
-
} catch (err2) {
|
|
30988
|
-
const stdout = err2?.stdout;
|
|
30989
|
-
out = typeof stdout === "string" ? stdout : "";
|
|
30990
|
-
}
|
|
30991
|
-
return out.split(`
|
|
30992
|
-
`).filter(Boolean).map((path) => path.replaceAll(sep3, "/").replace(/^\.\//, ""));
|
|
30993
|
-
}
|
|
30994
|
-
function cacheRecursivePaths(dir, files) {
|
|
30995
|
-
const now = Date.now();
|
|
30996
|
-
for (const [key, entry] of recursiveCache) {
|
|
30997
|
-
if (now - entry.loadedAt >= RECURSIVE_CACHE_TTL_MS)
|
|
30998
|
-
recursiveCache.delete(key);
|
|
30999
|
-
}
|
|
31000
|
-
recursiveCache.delete(dir);
|
|
31001
|
-
while (recursiveCache.size >= MAX_RECURSIVE_CACHE_ENTRIES) {
|
|
31002
|
-
const oldest = recursiveCache.keys().next().value;
|
|
31003
|
-
if (oldest === undefined)
|
|
31004
|
-
break;
|
|
31005
|
-
recursiveCache.delete(oldest);
|
|
31006
|
-
}
|
|
31007
|
-
recursiveCache.set(dir, {
|
|
31008
|
-
loadedAt: now,
|
|
31009
|
-
paths: indexRecursivePaths(files),
|
|
31010
|
-
matches: new Map
|
|
31011
|
-
});
|
|
31012
|
-
}
|
|
31013
|
-
function loadFilesRecursive(dir, loader) {
|
|
31014
|
-
const cached = recursiveCache.get(dir);
|
|
31015
|
-
if (cached && Date.now() - cached.loadedAt < RECURSIVE_CACHE_TTL_MS) {
|
|
31016
|
-
recursiveCache.delete(dir);
|
|
31017
|
-
recursiveCache.set(dir, cached);
|
|
31018
|
-
return Promise.resolve(false);
|
|
31019
|
-
}
|
|
31020
|
-
const active2 = recursiveSearches.get(dir);
|
|
31021
|
-
if (active2)
|
|
31022
|
-
return active2;
|
|
31023
|
-
const search = (async () => {
|
|
31024
|
-
try {
|
|
31025
|
-
cacheRecursivePaths(dir, await loader(dir));
|
|
31026
|
-
} catch {
|
|
31027
|
-
cacheRecursivePaths(dir, []);
|
|
31028
|
-
}
|
|
31029
|
-
return true;
|
|
31030
|
-
})().finally(() => recursiveSearches.delete(dir));
|
|
31031
|
-
recursiveSearches.set(dir, search);
|
|
31032
|
-
return search;
|
|
31033
|
-
}
|
|
31034
|
-
function activeAtToken(lineText, col) {
|
|
31035
|
-
const upto = lineText.slice(0, col);
|
|
31036
|
-
const match = /(?:^|\s)@([^\s]*)$/.exec(upto);
|
|
31037
|
-
if (!match)
|
|
31038
|
-
return null;
|
|
31039
|
-
const frag = match[1] ?? "";
|
|
31040
|
-
return { start: col - frag.length - 1, frag };
|
|
31041
|
-
}
|
|
31042
|
-
function resolveFragment(frag) {
|
|
31043
|
-
const home = homedir10();
|
|
31044
|
-
let path;
|
|
31045
|
-
if (frag === "" || frag === "~")
|
|
31046
|
-
path = home;
|
|
31047
|
-
else if (frag === "~/")
|
|
31048
|
-
path = home;
|
|
31049
|
-
else if (frag.startsWith("~/"))
|
|
31050
|
-
path = join40(home, frag.slice(2));
|
|
31051
|
-
else if (frag.startsWith("/"))
|
|
31052
|
-
path = frag;
|
|
31053
|
-
else
|
|
31054
|
-
path = join40(home, frag);
|
|
31055
|
-
if (frag.endsWith("/") || frag === "" || frag === "~") {
|
|
31056
|
-
return { dir: path, prefix: "" };
|
|
31057
|
-
}
|
|
31058
|
-
return { dir: dirname19(path), prefix: basename11(path) };
|
|
31059
|
-
}
|
|
31060
|
-
function toToken(fullPath, isDir) {
|
|
31061
|
-
const home = homedir10();
|
|
31062
|
-
let shown = fullPath;
|
|
31063
|
-
if (fullPath === home)
|
|
31064
|
-
shown = "~";
|
|
31065
|
-
else if (fullPath.startsWith(`${home}/`))
|
|
31066
|
-
shown = `~/${fullPath.slice(home.length + 1)}`;
|
|
31067
|
-
return `@${shown}${isDir ? "/" : ""}`;
|
|
31068
|
-
}
|
|
31069
|
-
function rankAndSlice(dir, candidates) {
|
|
31070
|
-
candidates.sort((a, b) => {
|
|
31071
|
-
if (a.isPrefixMatch !== b.isPrefixMatch)
|
|
31072
|
-
return a.isPrefixMatch ? -1 : 1;
|
|
31073
|
-
if (a.isDir !== b.isDir)
|
|
31074
|
-
return a.isDir ? -1 : 1;
|
|
31075
|
-
const depthA = a.relPath.split("/").length;
|
|
31076
|
-
const depthB = b.relPath.split("/").length;
|
|
31077
|
-
if (depthA !== depthB)
|
|
31078
|
-
return depthA - depthB;
|
|
31079
|
-
return a.relPath.localeCompare(b.relPath);
|
|
31080
|
-
});
|
|
31081
|
-
return candidates.slice(0, MAX_SUGGESTIONS).map(({ relPath, isDir }) => ({
|
|
31082
|
-
label: `${relPath}${isDir ? "/" : ""}`,
|
|
31083
|
-
value: toToken(join40(dir, relPath), isDir),
|
|
31084
|
-
isDir
|
|
31085
|
-
}));
|
|
31086
|
-
}
|
|
31087
|
-
function recursiveCandidates(dir, lowerPrefix, seen) {
|
|
31088
|
-
const entry = recursiveCache.get(dir);
|
|
31089
|
-
if (!entry)
|
|
31090
|
-
return [];
|
|
31091
|
-
let matches = entry.matches.get(lowerPrefix);
|
|
31092
|
-
if (!matches) {
|
|
31093
|
-
matches = entry.paths.filter((path) => path.lowerName.includes(lowerPrefix)).map((path) => ({
|
|
31094
|
-
relPath: path.relPath,
|
|
31095
|
-
isDir: path.isDir,
|
|
31096
|
-
isPrefixMatch: path.lowerName.startsWith(lowerPrefix)
|
|
31097
|
-
}));
|
|
31098
|
-
if (entry.matches.size >= MAX_MATCH_CACHE_ENTRIES) {
|
|
31099
|
-
const oldest = entry.matches.keys().next().value;
|
|
31100
|
-
if (oldest !== undefined)
|
|
31101
|
-
entry.matches.delete(oldest);
|
|
31102
|
-
}
|
|
31103
|
-
entry.matches.set(lowerPrefix, matches);
|
|
31104
|
-
} else {
|
|
31105
|
-
entry.matches.delete(lowerPrefix);
|
|
31106
|
-
entry.matches.set(lowerPrefix, matches);
|
|
31107
|
-
}
|
|
31108
|
-
return matches.filter((candidate) => {
|
|
31109
|
-
if (seen.has(candidate.relPath))
|
|
31110
|
-
return false;
|
|
31111
|
-
seen.add(candidate.relPath);
|
|
31112
|
-
return true;
|
|
31113
|
-
});
|
|
31114
|
-
}
|
|
31115
|
-
function isRecursivePathQuery(lineText, col) {
|
|
31116
|
-
const token = activeAtToken(lineText, col);
|
|
31117
|
-
if (!token)
|
|
31118
|
-
return false;
|
|
31119
|
-
const { prefix } = resolveFragment(token.frag);
|
|
31120
|
-
return !prefix.startsWith(".") && prefix.length >= RECURSIVE_MIN_PREFIX_LEN;
|
|
31121
|
-
}
|
|
31122
|
-
async function warmPathSuggestions(lineText, col, loader = listFilesWithRipgrep) {
|
|
31123
|
-
if (!isRecursivePathQuery(lineText, col))
|
|
31124
|
-
return false;
|
|
31125
|
-
const token = activeAtToken(lineText, col);
|
|
31126
|
-
if (!token)
|
|
31127
|
-
return false;
|
|
31128
|
-
const { dir } = resolveFragment(token.frag);
|
|
31129
|
-
try {
|
|
31130
|
-
if (!statSync19(dir).isDirectory())
|
|
31131
|
-
return false;
|
|
31132
|
-
} catch {
|
|
31133
|
-
return false;
|
|
31134
|
-
}
|
|
31135
|
-
return loadFilesRecursive(dir, loader);
|
|
31136
|
-
}
|
|
31137
|
-
function pathSuggestions(lineText, col) {
|
|
31138
|
-
const token = activeAtToken(lineText, col);
|
|
31139
|
-
if (!token)
|
|
31140
|
-
return null;
|
|
31141
|
-
const { dir, prefix } = resolveFragment(token.frag);
|
|
31142
|
-
let entries;
|
|
31143
|
-
try {
|
|
31144
|
-
entries = readdirSync14(dir, { withFileTypes: true });
|
|
31145
|
-
} catch {
|
|
31146
|
-
return { start: token.start, end: col, items: [], truncated: 0, searching: false };
|
|
31147
|
-
}
|
|
31148
|
-
const lowerPrefix = prefix.toLowerCase();
|
|
31149
|
-
const showHidden = prefix.startsWith(".");
|
|
31150
|
-
const candidates = entries.filter((entry) => {
|
|
31151
|
-
const name = entry.name;
|
|
31152
|
-
if (!showHidden && name.startsWith("."))
|
|
31153
|
-
return false;
|
|
31154
|
-
if (lowerPrefix === "")
|
|
31155
|
-
return true;
|
|
31156
|
-
const lowerName = name.toLowerCase();
|
|
31157
|
-
return showHidden ? lowerName.startsWith(lowerPrefix) : lowerName.includes(lowerPrefix);
|
|
31158
|
-
}).map((entry) => {
|
|
31159
|
-
let isDir = entry.isDirectory();
|
|
31160
|
-
if (!isDir && entry.isSymbolicLink()) {
|
|
31161
|
-
try {
|
|
31162
|
-
isDir = statSync19(join40(dir, entry.name)).isDirectory();
|
|
31163
|
-
} catch {}
|
|
31164
|
-
}
|
|
31165
|
-
return {
|
|
31166
|
-
relPath: entry.name,
|
|
31167
|
-
isDir,
|
|
31168
|
-
isPrefixMatch: entry.name.toLowerCase().startsWith(lowerPrefix)
|
|
31169
|
-
};
|
|
31170
|
-
});
|
|
31171
|
-
if (!showHidden && lowerPrefix.length >= RECURSIVE_MIN_PREFIX_LEN) {
|
|
31172
|
-
const seen = new Set(candidates.map((c) => c.relPath));
|
|
31173
|
-
candidates.push(...recursiveCandidates(dir, lowerPrefix, seen));
|
|
31174
|
-
}
|
|
31175
|
-
const items = rankAndSlice(dir, candidates);
|
|
31176
|
-
return {
|
|
31177
|
-
start: token.start,
|
|
31178
|
-
end: col,
|
|
31179
|
-
items,
|
|
31180
|
-
truncated: Math.max(0, candidates.length - items.length),
|
|
31181
|
-
searching: recursiveSearches.has(dir)
|
|
31182
|
-
};
|
|
31183
|
-
}
|
|
31184
|
-
function fragmentToAbsolutePath(frag) {
|
|
31185
|
-
const home = homedir10();
|
|
31186
|
-
if (frag === "~" || frag === "~/")
|
|
31187
|
-
return home;
|
|
31188
|
-
if (frag.startsWith("~/"))
|
|
31189
|
-
return join40(home, frag.slice(2));
|
|
31190
|
-
if (frag.startsWith("/"))
|
|
31191
|
-
return frag;
|
|
31192
|
-
return join40(home, frag);
|
|
31193
|
-
}
|
|
31194
|
-
function fragmentResolves(frag) {
|
|
31195
|
-
try {
|
|
31196
|
-
return existsSync33(fragmentToAbsolutePath(frag));
|
|
31197
|
-
} catch {
|
|
31198
|
-
return false;
|
|
31199
|
-
}
|
|
31200
|
-
}
|
|
31201
|
-
function stripResolvedPathTriggers(text2) {
|
|
31202
|
-
return text2.replaceAll(AT_PATH_TOKEN, (whole, lead, frag) => {
|
|
31203
|
-
if (fragmentResolves(frag))
|
|
31204
|
-
return `${lead}${frag}`;
|
|
31205
|
-
const pathPart = frag.replace(TRAILING_PUNCT, "");
|
|
31206
|
-
if (pathPart && pathPart !== frag && fragmentResolves(pathPart)) {
|
|
31207
|
-
return `${lead}${pathPart}${frag.slice(pathPart.length)}`;
|
|
31208
|
-
}
|
|
31209
|
-
return whole;
|
|
31210
|
-
});
|
|
31211
|
-
}
|
|
31212
|
-
function completePathToken(lineText, col, suggestion, options = {}) {
|
|
31213
|
-
const token = activeAtToken(lineText, col);
|
|
31214
|
-
if (!token)
|
|
31215
|
-
return null;
|
|
31216
|
-
let tokenEnd = col;
|
|
31217
|
-
while (tokenEnd < lineText.length && !/\s/.test(lineText[tokenEnd] ?? " "))
|
|
31218
|
-
tokenEnd += 1;
|
|
31219
|
-
const trailingText = lineText.slice(col, tokenEnd);
|
|
31220
|
-
const pathTail = trailingText.replace(TRAILING_PUNCT, "");
|
|
31221
|
-
const end = col + pathTail.length;
|
|
31222
|
-
const replacement = options.keepTrigger ? suggestion.value : suggestion.value.slice(1);
|
|
31223
|
-
const line = lineText.slice(0, token.start) + replacement + lineText.slice(end);
|
|
31224
|
-
return { line, col: token.start + replacement.length };
|
|
31225
|
-
}
|
|
31226
|
-
var MAX_SUGGESTIONS = 8, RECURSIVE_MIN_PREFIX_LEN = 4, RECURSIVE_MAX_DEPTH = 10, RECURSIVE_TIMEOUT_MS = 2000, RECURSIVE_CACHE_TTL_MS = 30000, MAX_RECURSIVE_CACHE_ENTRIES = 3, MAX_MATCH_CACHE_ENTRIES = 24, RECURSIVE_EXCLUDES, recursiveCache, recursiveSearches, execFileAsync3, AT_PATH_TOKEN, TRAILING_PUNCT;
|
|
31227
|
-
var init_path_suggest = __esm(() => {
|
|
31228
|
-
RECURSIVE_EXCLUDES = ["node_modules", ".git", ".cache", "dist", "build", "Library", ".Trash"];
|
|
31229
|
-
recursiveCache = new Map;
|
|
31230
|
-
recursiveSearches = new Map;
|
|
31231
|
-
execFileAsync3 = promisify3(execFile3);
|
|
31232
|
-
AT_PATH_TOKEN = /(^|[\s([{<])@([^\s]+)/g;
|
|
31233
|
-
TRAILING_PUNCT = /[.,;:!?)\]}>"'`]+$/;
|
|
31234
|
-
});
|
|
31235
|
-
|
|
31236
30983
|
// ../../adapters/terminal/src/subagent-graph.ts
|
|
31237
30984
|
import {
|
|
31238
30985
|
layoutTerminalGraph,
|
|
@@ -31867,6 +31614,19 @@ function applyAiStatus(state, topicId, raw, createdAt) {
|
|
|
31867
31614
|
tools: []
|
|
31868
31615
|
});
|
|
31869
31616
|
}
|
|
31617
|
+
if (kind === "context_progress") {
|
|
31618
|
+
if (isStaleTerminalStatus(current3, status))
|
|
31619
|
+
return state;
|
|
31620
|
+
return setActivity(state, topicId, {
|
|
31621
|
+
...liveCurrent,
|
|
31622
|
+
running: true,
|
|
31623
|
+
queryId: typeof status.queryId === "string" ? status.queryId : current3.queryId,
|
|
31624
|
+
contextProgress: {
|
|
31625
|
+
assistantTokens: Math.max(0, Number(status.assistantTokens) || 0),
|
|
31626
|
+
toolTokens: Math.max(0, Number(status.toolTokens) || 0)
|
|
31627
|
+
}
|
|
31628
|
+
});
|
|
31629
|
+
}
|
|
31870
31630
|
if (kind === "ai_done") {
|
|
31871
31631
|
if (isStaleTerminalStatus(current3, status))
|
|
31872
31632
|
return state;
|
|
@@ -31980,6 +31740,356 @@ var init_state2 = __esm(async () => {
|
|
|
31980
31740
|
await init_src();
|
|
31981
31741
|
});
|
|
31982
31742
|
|
|
31743
|
+
// ../../adapters/terminal/src/context-usage.ts
|
|
31744
|
+
function latestUsageMessage(messages) {
|
|
31745
|
+
for (let index = messages.length - 1;index >= 0; index--) {
|
|
31746
|
+
const usage = messages[index]?.authorId === "ai" ? messages[index]?.usage : undefined;
|
|
31747
|
+
if (usage?.context !== undefined && usage.contextWindow)
|
|
31748
|
+
return { index, usage };
|
|
31749
|
+
}
|
|
31750
|
+
return;
|
|
31751
|
+
}
|
|
31752
|
+
function estimateMessages(messages, predicate) {
|
|
31753
|
+
return messages.reduce((sum, message) => predicate(message) ? sum + 4 + estimateTextTokens(message.text) : sum, 0);
|
|
31754
|
+
}
|
|
31755
|
+
function activeContextBreakdown(state) {
|
|
31756
|
+
const topic = activeTopic(state);
|
|
31757
|
+
if (!topic)
|
|
31758
|
+
return;
|
|
31759
|
+
const messages = activeMessages(state);
|
|
31760
|
+
const latest = latestUsageMessage(messages);
|
|
31761
|
+
const stored = state.topicUsage[topic.id]?.currentSession;
|
|
31762
|
+
const confirmed = latest?.usage.context ?? stored?.contextTokens;
|
|
31763
|
+
const contextWindow = latest?.usage.contextWindow ?? stored?.contextWindow;
|
|
31764
|
+
if (confirmed === undefined || !contextWindow)
|
|
31765
|
+
return;
|
|
31766
|
+
const activity = state.activity[topic.id];
|
|
31767
|
+
if (!activity?.running) {
|
|
31768
|
+
return {
|
|
31769
|
+
context: confirmed,
|
|
31770
|
+
contextWindow,
|
|
31771
|
+
confirmed,
|
|
31772
|
+
user: 0,
|
|
31773
|
+
assistant: 0,
|
|
31774
|
+
tools: 0,
|
|
31775
|
+
free: Math.max(0, contextWindow - confirmed),
|
|
31776
|
+
estimated: false
|
|
31777
|
+
};
|
|
31778
|
+
}
|
|
31779
|
+
const afterBaseline = latest ? messages.slice(latest.index + 1) : stored?.timestamp ? messages.filter((message) => message.createdAt > stored.timestamp) : messages;
|
|
31780
|
+
const user = estimateMessages(afterBaseline, (message) => message.authorId !== "ai" && message.kind !== "system");
|
|
31781
|
+
const assistant = activity.contextProgress?.assistantTokens ?? estimateMessages(afterBaseline, (message) => message.authorId === "ai" && message.kind !== "tool");
|
|
31782
|
+
const tools = activity.contextProgress?.toolTokens ?? estimateMessages(afterBaseline, (message) => message.kind === "tool");
|
|
31783
|
+
const context = confirmed + user + assistant + tools;
|
|
31784
|
+
return {
|
|
31785
|
+
context,
|
|
31786
|
+
contextWindow,
|
|
31787
|
+
confirmed,
|
|
31788
|
+
user,
|
|
31789
|
+
assistant,
|
|
31790
|
+
tools,
|
|
31791
|
+
free: Math.max(0, contextWindow - context),
|
|
31792
|
+
estimated: true
|
|
31793
|
+
};
|
|
31794
|
+
}
|
|
31795
|
+
var init_context_usage = __esm(async () => {
|
|
31796
|
+
await __promiseAll([
|
|
31797
|
+
init_src(),
|
|
31798
|
+
init_state2()
|
|
31799
|
+
]);
|
|
31800
|
+
});
|
|
31801
|
+
|
|
31802
|
+
// ../../adapters/terminal/src/path-suggest.ts
|
|
31803
|
+
import { execFile as execFile3 } from "child_process";
|
|
31804
|
+
import { existsSync as existsSync33, readdirSync as readdirSync14, statSync as statSync19 } from "fs";
|
|
31805
|
+
import { homedir as homedir10 } from "os";
|
|
31806
|
+
import { basename as basename11, dirname as dirname19, join as join40, sep as sep3 } from "path";
|
|
31807
|
+
import { promisify as promisify3 } from "util";
|
|
31808
|
+
function indexRecursivePaths(files) {
|
|
31809
|
+
const paths = [];
|
|
31810
|
+
const directories = new Set;
|
|
31811
|
+
for (const relPath of files) {
|
|
31812
|
+
const segments = relPath.split("/");
|
|
31813
|
+
if (segments.some((segment) => segment.startsWith(".")))
|
|
31814
|
+
continue;
|
|
31815
|
+
for (let index = 0;index < segments.length - 1; index += 1) {
|
|
31816
|
+
const directory = segments.slice(0, index + 1).join("/");
|
|
31817
|
+
if (directories.has(directory))
|
|
31818
|
+
continue;
|
|
31819
|
+
directories.add(directory);
|
|
31820
|
+
paths.push({
|
|
31821
|
+
relPath: directory,
|
|
31822
|
+
isDir: true,
|
|
31823
|
+
lowerName: (segments[index] ?? "").toLowerCase()
|
|
31824
|
+
});
|
|
31825
|
+
}
|
|
31826
|
+
paths.push({ relPath, isDir: false, lowerName: (segments.at(-1) ?? "").toLowerCase() });
|
|
31827
|
+
}
|
|
31828
|
+
return paths;
|
|
31829
|
+
}
|
|
31830
|
+
async function listFilesWithRipgrep(dir) {
|
|
31831
|
+
const args = ["--files", "--max-depth", String(RECURSIVE_MAX_DEPTH)];
|
|
31832
|
+
for (const excluded of RECURSIVE_EXCLUDES)
|
|
31833
|
+
args.push("-g", `!${excluded}`);
|
|
31834
|
+
args.push(".");
|
|
31835
|
+
let out = "";
|
|
31836
|
+
try {
|
|
31837
|
+
const result = await execFileAsync3("rg", args, {
|
|
31838
|
+
cwd: dir,
|
|
31839
|
+
encoding: "utf8",
|
|
31840
|
+
timeout: RECURSIVE_TIMEOUT_MS,
|
|
31841
|
+
maxBuffer: 32 * 1024 * 1024
|
|
31842
|
+
});
|
|
31843
|
+
out = result.stdout;
|
|
31844
|
+
} catch (err2) {
|
|
31845
|
+
const stdout = err2?.stdout;
|
|
31846
|
+
out = typeof stdout === "string" ? stdout : "";
|
|
31847
|
+
}
|
|
31848
|
+
return out.split(`
|
|
31849
|
+
`).filter(Boolean).map((path) => path.replaceAll(sep3, "/").replace(/^\.\//, ""));
|
|
31850
|
+
}
|
|
31851
|
+
function cacheRecursivePaths(dir, files) {
|
|
31852
|
+
const now = Date.now();
|
|
31853
|
+
for (const [key, entry] of recursiveCache) {
|
|
31854
|
+
if (now - entry.loadedAt >= RECURSIVE_CACHE_TTL_MS)
|
|
31855
|
+
recursiveCache.delete(key);
|
|
31856
|
+
}
|
|
31857
|
+
recursiveCache.delete(dir);
|
|
31858
|
+
while (recursiveCache.size >= MAX_RECURSIVE_CACHE_ENTRIES) {
|
|
31859
|
+
const oldest = recursiveCache.keys().next().value;
|
|
31860
|
+
if (oldest === undefined)
|
|
31861
|
+
break;
|
|
31862
|
+
recursiveCache.delete(oldest);
|
|
31863
|
+
}
|
|
31864
|
+
recursiveCache.set(dir, {
|
|
31865
|
+
loadedAt: now,
|
|
31866
|
+
paths: indexRecursivePaths(files),
|
|
31867
|
+
matches: new Map
|
|
31868
|
+
});
|
|
31869
|
+
}
|
|
31870
|
+
function loadFilesRecursive(dir, loader) {
|
|
31871
|
+
const cached = recursiveCache.get(dir);
|
|
31872
|
+
if (cached && Date.now() - cached.loadedAt < RECURSIVE_CACHE_TTL_MS) {
|
|
31873
|
+
recursiveCache.delete(dir);
|
|
31874
|
+
recursiveCache.set(dir, cached);
|
|
31875
|
+
return Promise.resolve(false);
|
|
31876
|
+
}
|
|
31877
|
+
const active2 = recursiveSearches.get(dir);
|
|
31878
|
+
if (active2)
|
|
31879
|
+
return active2;
|
|
31880
|
+
const search = (async () => {
|
|
31881
|
+
try {
|
|
31882
|
+
cacheRecursivePaths(dir, await loader(dir));
|
|
31883
|
+
} catch {
|
|
31884
|
+
cacheRecursivePaths(dir, []);
|
|
31885
|
+
}
|
|
31886
|
+
return true;
|
|
31887
|
+
})().finally(() => recursiveSearches.delete(dir));
|
|
31888
|
+
recursiveSearches.set(dir, search);
|
|
31889
|
+
return search;
|
|
31890
|
+
}
|
|
31891
|
+
function activeAtToken(lineText, col) {
|
|
31892
|
+
const upto = lineText.slice(0, col);
|
|
31893
|
+
const match = /(?:^|\s)@([^\s]*)$/.exec(upto);
|
|
31894
|
+
if (!match)
|
|
31895
|
+
return null;
|
|
31896
|
+
const frag = match[1] ?? "";
|
|
31897
|
+
return { start: col - frag.length - 1, frag };
|
|
31898
|
+
}
|
|
31899
|
+
function resolveFragment(frag) {
|
|
31900
|
+
const home = homedir10();
|
|
31901
|
+
let path;
|
|
31902
|
+
if (frag === "" || frag === "~")
|
|
31903
|
+
path = home;
|
|
31904
|
+
else if (frag === "~/")
|
|
31905
|
+
path = home;
|
|
31906
|
+
else if (frag.startsWith("~/"))
|
|
31907
|
+
path = join40(home, frag.slice(2));
|
|
31908
|
+
else if (frag.startsWith("/"))
|
|
31909
|
+
path = frag;
|
|
31910
|
+
else
|
|
31911
|
+
path = join40(home, frag);
|
|
31912
|
+
if (frag.endsWith("/") || frag === "" || frag === "~") {
|
|
31913
|
+
return { dir: path, prefix: "" };
|
|
31914
|
+
}
|
|
31915
|
+
return { dir: dirname19(path), prefix: basename11(path) };
|
|
31916
|
+
}
|
|
31917
|
+
function toToken(fullPath, isDir) {
|
|
31918
|
+
const home = homedir10();
|
|
31919
|
+
let shown = fullPath;
|
|
31920
|
+
if (fullPath === home)
|
|
31921
|
+
shown = "~";
|
|
31922
|
+
else if (fullPath.startsWith(`${home}/`))
|
|
31923
|
+
shown = `~/${fullPath.slice(home.length + 1)}`;
|
|
31924
|
+
return `@${shown}${isDir ? "/" : ""}`;
|
|
31925
|
+
}
|
|
31926
|
+
function rankAndSlice(dir, candidates) {
|
|
31927
|
+
candidates.sort((a, b) => {
|
|
31928
|
+
if (a.isPrefixMatch !== b.isPrefixMatch)
|
|
31929
|
+
return a.isPrefixMatch ? -1 : 1;
|
|
31930
|
+
if (a.isDir !== b.isDir)
|
|
31931
|
+
return a.isDir ? -1 : 1;
|
|
31932
|
+
const depthA = a.relPath.split("/").length;
|
|
31933
|
+
const depthB = b.relPath.split("/").length;
|
|
31934
|
+
if (depthA !== depthB)
|
|
31935
|
+
return depthA - depthB;
|
|
31936
|
+
return a.relPath.localeCompare(b.relPath);
|
|
31937
|
+
});
|
|
31938
|
+
return candidates.slice(0, MAX_SUGGESTIONS).map(({ relPath, isDir }) => ({
|
|
31939
|
+
label: `${relPath}${isDir ? "/" : ""}`,
|
|
31940
|
+
value: toToken(join40(dir, relPath), isDir),
|
|
31941
|
+
isDir
|
|
31942
|
+
}));
|
|
31943
|
+
}
|
|
31944
|
+
function recursiveCandidates(dir, lowerPrefix, seen) {
|
|
31945
|
+
const entry = recursiveCache.get(dir);
|
|
31946
|
+
if (!entry)
|
|
31947
|
+
return [];
|
|
31948
|
+
let matches = entry.matches.get(lowerPrefix);
|
|
31949
|
+
if (!matches) {
|
|
31950
|
+
matches = entry.paths.filter((path) => path.lowerName.includes(lowerPrefix)).map((path) => ({
|
|
31951
|
+
relPath: path.relPath,
|
|
31952
|
+
isDir: path.isDir,
|
|
31953
|
+
isPrefixMatch: path.lowerName.startsWith(lowerPrefix)
|
|
31954
|
+
}));
|
|
31955
|
+
if (entry.matches.size >= MAX_MATCH_CACHE_ENTRIES) {
|
|
31956
|
+
const oldest = entry.matches.keys().next().value;
|
|
31957
|
+
if (oldest !== undefined)
|
|
31958
|
+
entry.matches.delete(oldest);
|
|
31959
|
+
}
|
|
31960
|
+
entry.matches.set(lowerPrefix, matches);
|
|
31961
|
+
} else {
|
|
31962
|
+
entry.matches.delete(lowerPrefix);
|
|
31963
|
+
entry.matches.set(lowerPrefix, matches);
|
|
31964
|
+
}
|
|
31965
|
+
return matches.filter((candidate) => {
|
|
31966
|
+
if (seen.has(candidate.relPath))
|
|
31967
|
+
return false;
|
|
31968
|
+
seen.add(candidate.relPath);
|
|
31969
|
+
return true;
|
|
31970
|
+
});
|
|
31971
|
+
}
|
|
31972
|
+
function isRecursivePathQuery(lineText, col) {
|
|
31973
|
+
const token = activeAtToken(lineText, col);
|
|
31974
|
+
if (!token)
|
|
31975
|
+
return false;
|
|
31976
|
+
const { prefix } = resolveFragment(token.frag);
|
|
31977
|
+
return !prefix.startsWith(".") && prefix.length >= RECURSIVE_MIN_PREFIX_LEN;
|
|
31978
|
+
}
|
|
31979
|
+
async function warmPathSuggestions(lineText, col, loader = listFilesWithRipgrep) {
|
|
31980
|
+
if (!isRecursivePathQuery(lineText, col))
|
|
31981
|
+
return false;
|
|
31982
|
+
const token = activeAtToken(lineText, col);
|
|
31983
|
+
if (!token)
|
|
31984
|
+
return false;
|
|
31985
|
+
const { dir } = resolveFragment(token.frag);
|
|
31986
|
+
try {
|
|
31987
|
+
if (!statSync19(dir).isDirectory())
|
|
31988
|
+
return false;
|
|
31989
|
+
} catch {
|
|
31990
|
+
return false;
|
|
31991
|
+
}
|
|
31992
|
+
return loadFilesRecursive(dir, loader);
|
|
31993
|
+
}
|
|
31994
|
+
function pathSuggestions(lineText, col) {
|
|
31995
|
+
const token = activeAtToken(lineText, col);
|
|
31996
|
+
if (!token)
|
|
31997
|
+
return null;
|
|
31998
|
+
const { dir, prefix } = resolveFragment(token.frag);
|
|
31999
|
+
let entries;
|
|
32000
|
+
try {
|
|
32001
|
+
entries = readdirSync14(dir, { withFileTypes: true });
|
|
32002
|
+
} catch {
|
|
32003
|
+
return { start: token.start, end: col, items: [], truncated: 0, searching: false };
|
|
32004
|
+
}
|
|
32005
|
+
const lowerPrefix = prefix.toLowerCase();
|
|
32006
|
+
const showHidden = prefix.startsWith(".");
|
|
32007
|
+
const candidates = entries.filter((entry) => {
|
|
32008
|
+
const name = entry.name;
|
|
32009
|
+
if (!showHidden && name.startsWith("."))
|
|
32010
|
+
return false;
|
|
32011
|
+
if (lowerPrefix === "")
|
|
32012
|
+
return true;
|
|
32013
|
+
const lowerName = name.toLowerCase();
|
|
32014
|
+
return showHidden ? lowerName.startsWith(lowerPrefix) : lowerName.includes(lowerPrefix);
|
|
32015
|
+
}).map((entry) => {
|
|
32016
|
+
let isDir = entry.isDirectory();
|
|
32017
|
+
if (!isDir && entry.isSymbolicLink()) {
|
|
32018
|
+
try {
|
|
32019
|
+
isDir = statSync19(join40(dir, entry.name)).isDirectory();
|
|
32020
|
+
} catch {}
|
|
32021
|
+
}
|
|
32022
|
+
return {
|
|
32023
|
+
relPath: entry.name,
|
|
32024
|
+
isDir,
|
|
32025
|
+
isPrefixMatch: entry.name.toLowerCase().startsWith(lowerPrefix)
|
|
32026
|
+
};
|
|
32027
|
+
});
|
|
32028
|
+
if (!showHidden && lowerPrefix.length >= RECURSIVE_MIN_PREFIX_LEN) {
|
|
32029
|
+
const seen = new Set(candidates.map((c) => c.relPath));
|
|
32030
|
+
candidates.push(...recursiveCandidates(dir, lowerPrefix, seen));
|
|
32031
|
+
}
|
|
32032
|
+
const items = rankAndSlice(dir, candidates);
|
|
32033
|
+
return {
|
|
32034
|
+
start: token.start,
|
|
32035
|
+
end: col,
|
|
32036
|
+
items,
|
|
32037
|
+
truncated: Math.max(0, candidates.length - items.length),
|
|
32038
|
+
searching: recursiveSearches.has(dir)
|
|
32039
|
+
};
|
|
32040
|
+
}
|
|
32041
|
+
function fragmentToAbsolutePath(frag) {
|
|
32042
|
+
const home = homedir10();
|
|
32043
|
+
if (frag === "~" || frag === "~/")
|
|
32044
|
+
return home;
|
|
32045
|
+
if (frag.startsWith("~/"))
|
|
32046
|
+
return join40(home, frag.slice(2));
|
|
32047
|
+
if (frag.startsWith("/"))
|
|
32048
|
+
return frag;
|
|
32049
|
+
return join40(home, frag);
|
|
32050
|
+
}
|
|
32051
|
+
function fragmentResolves(frag) {
|
|
32052
|
+
try {
|
|
32053
|
+
return existsSync33(fragmentToAbsolutePath(frag));
|
|
32054
|
+
} catch {
|
|
32055
|
+
return false;
|
|
32056
|
+
}
|
|
32057
|
+
}
|
|
32058
|
+
function stripResolvedPathTriggers(text2) {
|
|
32059
|
+
return text2.replaceAll(AT_PATH_TOKEN, (whole, lead, frag) => {
|
|
32060
|
+
if (fragmentResolves(frag))
|
|
32061
|
+
return `${lead}${frag}`;
|
|
32062
|
+
const pathPart = frag.replace(TRAILING_PUNCT, "");
|
|
32063
|
+
if (pathPart && pathPart !== frag && fragmentResolves(pathPart)) {
|
|
32064
|
+
return `${lead}${pathPart}${frag.slice(pathPart.length)}`;
|
|
32065
|
+
}
|
|
32066
|
+
return whole;
|
|
32067
|
+
});
|
|
32068
|
+
}
|
|
32069
|
+
function completePathToken(lineText, col, suggestion, options = {}) {
|
|
32070
|
+
const token = activeAtToken(lineText, col);
|
|
32071
|
+
if (!token)
|
|
32072
|
+
return null;
|
|
32073
|
+
let tokenEnd = col;
|
|
32074
|
+
while (tokenEnd < lineText.length && !/\s/.test(lineText[tokenEnd] ?? " "))
|
|
32075
|
+
tokenEnd += 1;
|
|
32076
|
+
const trailingText = lineText.slice(col, tokenEnd);
|
|
32077
|
+
const pathTail = trailingText.replace(TRAILING_PUNCT, "");
|
|
32078
|
+
const end = col + pathTail.length;
|
|
32079
|
+
const replacement = options.keepTrigger ? suggestion.value : suggestion.value.slice(1);
|
|
32080
|
+
const line = lineText.slice(0, token.start) + replacement + lineText.slice(end);
|
|
32081
|
+
return { line, col: token.start + replacement.length };
|
|
32082
|
+
}
|
|
32083
|
+
var MAX_SUGGESTIONS = 8, RECURSIVE_MIN_PREFIX_LEN = 4, RECURSIVE_MAX_DEPTH = 10, RECURSIVE_TIMEOUT_MS = 2000, RECURSIVE_CACHE_TTL_MS = 30000, MAX_RECURSIVE_CACHE_ENTRIES = 3, MAX_MATCH_CACHE_ENTRIES = 24, RECURSIVE_EXCLUDES, recursiveCache, recursiveSearches, execFileAsync3, AT_PATH_TOKEN, TRAILING_PUNCT;
|
|
32084
|
+
var init_path_suggest = __esm(() => {
|
|
32085
|
+
RECURSIVE_EXCLUDES = ["node_modules", ".git", ".cache", "dist", "build", "Library", ".Trash"];
|
|
32086
|
+
recursiveCache = new Map;
|
|
32087
|
+
recursiveSearches = new Map;
|
|
32088
|
+
execFileAsync3 = promisify3(execFile3);
|
|
32089
|
+
AT_PATH_TOKEN = /(^|[\s([{<])@([^\s]+)/g;
|
|
32090
|
+
TRAILING_PUNCT = /[.,;:!?)\]}>"'`]+$/;
|
|
32091
|
+
});
|
|
32092
|
+
|
|
31983
32093
|
// ../../adapters/terminal/src/terminal-width.ts
|
|
31984
32094
|
function stripAnsi(value) {
|
|
31985
32095
|
return value.replace(new RegExp("\\u001b\\]8;[^\\u0007\\u001b]*(?:\\u0007|\\u001b\\\\)", "g"), "").replace(new RegExp("\\u001b\\[[0-?]*[ -/]*[@-~]", "g"), "");
|
|
@@ -32811,9 +32921,9 @@ function helpLines() {
|
|
|
32811
32921
|
line(" Esc/Ctrl-C stop active turn \xB7 Ctrl-C twice when idle to quit"),
|
|
32812
32922
|
line(""),
|
|
32813
32923
|
line(" Commands", { fg: theme.cyan, bold: true }),
|
|
32814
|
-
line(" /new /model /effort /
|
|
32815
|
-
line(" /
|
|
32816
|
-
line(" /abort /help /quit", { fg: theme.muted })
|
|
32924
|
+
line(" /new /model /effort /status /context"),
|
|
32925
|
+
line(" /topics /public /private /fork /spawn"),
|
|
32926
|
+
line(" /del /copy /abort /help /quit", { fg: theme.muted })
|
|
32817
32927
|
];
|
|
32818
32928
|
}
|
|
32819
32929
|
function tokenCount(value) {
|
|
@@ -32828,19 +32938,17 @@ function tokenCount(value) {
|
|
|
32828
32938
|
function latestActiveUsage(state) {
|
|
32829
32939
|
return activeMessages(state).slice().reverse().find((message) => message.authorId === "ai" && message.usage)?.usage;
|
|
32830
32940
|
}
|
|
32831
|
-
function
|
|
32832
|
-
|
|
32833
|
-
|
|
32834
|
-
|
|
32835
|
-
|
|
32836
|
-
|
|
32837
|
-
const current3 = topic ? state.topicUsage[topic.id]?.currentSession : undefined;
|
|
32838
|
-
return current3 ? { context: current3.contextTokens, contextWindow: current3.contextWindow } : undefined;
|
|
32941
|
+
function contextUsageColor(ratio) {
|
|
32942
|
+
if (ratio !== undefined && ratio >= 90)
|
|
32943
|
+
return theme.red;
|
|
32944
|
+
if (ratio !== undefined && ratio >= 80)
|
|
32945
|
+
return theme.amber;
|
|
32946
|
+
return theme.text;
|
|
32839
32947
|
}
|
|
32840
32948
|
function statusLines(state) {
|
|
32841
32949
|
const topic = activeTopic(state);
|
|
32842
32950
|
const usage = latestActiveUsage(state);
|
|
32843
|
-
const contextUsage =
|
|
32951
|
+
const contextUsage = activeContextBreakdown(state);
|
|
32844
32952
|
const total = topic ? state.topicUsage[topic.id] : undefined;
|
|
32845
32953
|
const hasTopicUsage = total !== undefined && total.queries > 0;
|
|
32846
32954
|
const ratio = contextUsage?.context !== undefined && contextUsage.contextWindow ? Math.round(contextUsage.context / contextUsage.contextWindow * 100) : undefined;
|
|
@@ -32852,8 +32960,8 @@ function statusLines(state) {
|
|
|
32852
32960
|
line(` Model ${effectiveTopicModel(topic)}`),
|
|
32853
32961
|
line(` Effort ${topic?.effectiveEffort ?? topic?.defaultEffort ?? "-"}`),
|
|
32854
32962
|
line(""),
|
|
32855
|
-
line(` Context ${tokenCount(contextUsage?.context)} / ${tokenCount(contextUsage?.contextWindow)}${ratio === undefined ? "" : ` (${ratio}%)`}`, { fg: ratio
|
|
32856
|
-
line(" Measured on the latest model request", { fg: theme.muted, dim: true }),
|
|
32963
|
+
line(` Context ${contextUsage?.estimated ? "~" : ""}${tokenCount(contextUsage?.context)} / ${tokenCount(contextUsage?.contextWindow)}${ratio === undefined ? "" : ` (${ratio}%)`}`, { fg: contextUsageColor(ratio) }),
|
|
32964
|
+
line(contextUsage?.estimated ? " Live estimate; replaced by provider usage when the turn finishes" : " Measured on the latest model request", { fg: theme.muted, dim: true }),
|
|
32857
32965
|
line(""),
|
|
32858
32966
|
line(` Last turn input ${tokenCount(usage?.input)} \xB7 output ${tokenCount(usage?.output)}`),
|
|
32859
32967
|
line(` Cache read ${tokenCount(usage?.cachedInput)}`),
|
|
@@ -32873,6 +32981,31 @@ function statusLines(state) {
|
|
|
32873
32981
|
line(" Esc close", { fg: theme.muted })
|
|
32874
32982
|
];
|
|
32875
32983
|
}
|
|
32984
|
+
function contextLines(state) {
|
|
32985
|
+
const usage = activeContextBreakdown(state);
|
|
32986
|
+
const ratio = usage ? Math.round(usage.context / usage.contextWindow * 100) : undefined;
|
|
32987
|
+
const value = (tokens) => tokenCount(tokens);
|
|
32988
|
+
return [
|
|
32989
|
+
line(" Context", { fg: theme.accent, bold: true }),
|
|
32990
|
+
line(""),
|
|
32991
|
+
line(` ${usage?.estimated ? "Estimated" : "Current"} ${usage?.estimated ? "~" : ""}${value(usage?.context)} / ${value(usage?.contextWindow)}${ratio === undefined ? "" : ` (${ratio}%)`}`, { fg: contextUsageColor(ratio) }),
|
|
32992
|
+
line(""),
|
|
32993
|
+
line(" Breakdown", { fg: theme.cyan, bold: true }),
|
|
32994
|
+
line(` Confirmed ${value(usage?.confirmed)}`),
|
|
32995
|
+
line(` New user ${value(usage?.user)}`),
|
|
32996
|
+
line(` Assistant ${value(usage?.assistant)}`),
|
|
32997
|
+
line(` Tools ${value(usage?.tools)}`),
|
|
32998
|
+
line(` Free ${value(usage?.free)}`),
|
|
32999
|
+
line(""),
|
|
33000
|
+
line(usage?.estimated ? " Live estimate; final provider usage replaces it" : " Provider-confirmed latest request; live categories appear during a turn", { fg: theme.muted, dim: true }),
|
|
33001
|
+
line(" System prompt and tool schemas are included in Confirmed", {
|
|
33002
|
+
fg: theme.muted,
|
|
33003
|
+
dim: true
|
|
33004
|
+
}),
|
|
33005
|
+
line(""),
|
|
33006
|
+
line(" Esc close", { fg: theme.muted })
|
|
33007
|
+
];
|
|
33008
|
+
}
|
|
32876
33009
|
function subagentTreePrefix(topic, topics, rootTopicId) {
|
|
32877
33010
|
if (!topic.isSubagent || topic.id === rootTopicId)
|
|
32878
33011
|
return "";
|
|
@@ -33241,6 +33374,8 @@ function conversationLines(state, width, height, animationFrame = 0, nowMs = ter
|
|
|
33241
33374
|
return helpLines().slice(0, height);
|
|
33242
33375
|
if (state.overlay === "status")
|
|
33243
33376
|
return statusLines(state).slice(0, height);
|
|
33377
|
+
if (state.overlay === "context")
|
|
33378
|
+
return contextLines(state).slice(0, height);
|
|
33244
33379
|
if (state.overlay === "topics")
|
|
33245
33380
|
return topicOverlayLines(state, width, height, animationFrame).slice(0, height);
|
|
33246
33381
|
if (state.overlay === "subagents")
|
|
@@ -33461,35 +33596,71 @@ function footerStatusText(state) {
|
|
|
33461
33596
|
function footerUsageText(state) {
|
|
33462
33597
|
const topic = activeTopic(state);
|
|
33463
33598
|
if (!topic)
|
|
33464
|
-
return [""];
|
|
33465
|
-
const contextUsage =
|
|
33599
|
+
return [{ text: "", spans: [] }];
|
|
33600
|
+
const contextUsage = activeContextBreakdown(state);
|
|
33466
33601
|
const total = state.topicUsage[topic.id];
|
|
33467
33602
|
const ratio = contextUsage?.context !== undefined && contextUsage.contextWindow ? Math.round(contextUsage.context / contextUsage.contextWindow * 100) : undefined;
|
|
33468
|
-
const context = contextUsage?.context !== undefined && contextUsage.contextWindow ? `${tokenCount(contextUsage.context)}/${tokenCount(contextUsage.contextWindow)} ${ratio}%` : "";
|
|
33603
|
+
const context = contextUsage?.context !== undefined && contextUsage.contextWindow ? `${contextUsage.estimated ? "~" : ""}${tokenCount(contextUsage.context)}/${tokenCount(contextUsage.contextWindow)} ${ratio}%` : "";
|
|
33469
33604
|
const hasTopicUsage = total !== undefined && total.queries > 0;
|
|
33470
33605
|
const cumulative = hasTopicUsage ? `\u03A3 ${tokenCount(total.inputTokens)} in/${tokenCount(total.outputTokens)} out` : "";
|
|
33471
33606
|
const cache = hasTopicUsage && total.cacheReadInputTokens ? `cache ${tokenCount(total.cacheReadInputTokens)}` : "";
|
|
33472
33607
|
const cost = hasTopicUsage ? `est $${total.estimatedCostUsd.toFixed(2)}` : "";
|
|
33473
|
-
const
|
|
33608
|
+
const variant = (values2) => {
|
|
33609
|
+
const present = values2.filter((value) => value.text);
|
|
33610
|
+
const spans = present.flatMap((value, index) => [
|
|
33611
|
+
...index > 0 ? [{ text: " \xB7 ", fg: theme.subtle }] : [],
|
|
33612
|
+
{ text: value.text, fg: value.fg }
|
|
33613
|
+
]);
|
|
33614
|
+
if (spans.length > 0)
|
|
33615
|
+
spans.push({ text: " ", fg: theme.muted });
|
|
33616
|
+
return {
|
|
33617
|
+
text: `${present.map((value) => value.text).join(" \xB7 ")}${present.length ? " " : ""}`,
|
|
33618
|
+
spans
|
|
33619
|
+
};
|
|
33620
|
+
};
|
|
33621
|
+
const values = {
|
|
33622
|
+
context: { text: context, fg: contextUsageColor(ratio) },
|
|
33623
|
+
cumulative: { text: cumulative, fg: theme.muted },
|
|
33624
|
+
cache: { text: cache, fg: theme.muted },
|
|
33625
|
+
cost: { text: cost, fg: theme.muted }
|
|
33626
|
+
};
|
|
33474
33627
|
return [
|
|
33475
|
-
|
|
33476
|
-
|
|
33477
|
-
|
|
33478
|
-
context
|
|
33479
|
-
|
|
33628
|
+
variant([values.context, values.cumulative, values.cache, values.cost]),
|
|
33629
|
+
variant([values.context, values.cumulative, values.cache]),
|
|
33630
|
+
variant([values.context, values.cumulative]),
|
|
33631
|
+
variant([values.context]),
|
|
33632
|
+
variant([])
|
|
33480
33633
|
];
|
|
33481
33634
|
}
|
|
33482
33635
|
function footerStatusLine(state, width) {
|
|
33483
33636
|
const leftCandidates = footerStatusText(state);
|
|
33484
33637
|
const rightCandidates = footerUsageText(state);
|
|
33485
33638
|
for (const right of rightCandidates) {
|
|
33486
|
-
for (const
|
|
33487
|
-
|
|
33488
|
-
|
|
33639
|
+
for (const left2 of leftCandidates) {
|
|
33640
|
+
const rightWidth = displayWidth(right.text);
|
|
33641
|
+
if (displayWidth(left2) + (rightWidth ? 1 + rightWidth : 0) <= width) {
|
|
33642
|
+
const gap = width - displayWidth(left2) - rightWidth;
|
|
33643
|
+
return [
|
|
33644
|
+
{ text: left2, fg: theme.accent, bold: true },
|
|
33645
|
+
{ text: " ".repeat(gap), bg: theme.surfaceRaised },
|
|
33646
|
+
...right.spans
|
|
33647
|
+
];
|
|
33489
33648
|
}
|
|
33490
33649
|
}
|
|
33491
33650
|
}
|
|
33492
|
-
|
|
33651
|
+
const left = sliceWidth(leftCandidates[leftCandidates.length - 1] ?? "", width);
|
|
33652
|
+
return [
|
|
33653
|
+
{ text: left, fg: theme.accent, bold: true },
|
|
33654
|
+
{ text: " ".repeat(Math.max(0, width - displayWidth(left))), bg: theme.surfaceRaised }
|
|
33655
|
+
];
|
|
33656
|
+
}
|
|
33657
|
+
function paintFooterSpans(spans) {
|
|
33658
|
+
return spans.map((span) => paint(span.text, {
|
|
33659
|
+
fg: span.fg ?? theme.text,
|
|
33660
|
+
bg: span.bg ?? theme.surfaceRaised,
|
|
33661
|
+
bold: span.bold,
|
|
33662
|
+
dim: span.dim
|
|
33663
|
+
})).join("");
|
|
33493
33664
|
}
|
|
33494
33665
|
function noticeStyle(state) {
|
|
33495
33666
|
return NOTICE_STYLE[state.noticeLevel ?? "warn"];
|
|
@@ -33540,11 +33711,7 @@ function footerLines(state, width) {
|
|
|
33540
33711
|
];
|
|
33541
33712
|
}
|
|
33542
33713
|
return [
|
|
33543
|
-
|
|
33544
|
-
fg: theme.accent,
|
|
33545
|
-
bg: theme.surfaceRaised,
|
|
33546
|
-
bold: true
|
|
33547
|
-
}),
|
|
33714
|
+
paintFooterSpans(footerStatusLine(state, width)),
|
|
33548
33715
|
paint(joinSides("", pickFitting(footerHintText(state), width), width), {
|
|
33549
33716
|
fg: state.notice ? noticeStyle(state).fg : theme.muted,
|
|
33550
33717
|
bg: theme.canvas
|
|
@@ -33679,6 +33846,7 @@ var init_render = __esm(async () => {
|
|
|
33679
33846
|
init_terminal_width();
|
|
33680
33847
|
await __promiseAll([
|
|
33681
33848
|
init_src(),
|
|
33849
|
+
init_context_usage(),
|
|
33682
33850
|
init_state2()
|
|
33683
33851
|
]);
|
|
33684
33852
|
theme = {
|
|
@@ -34821,6 +34989,11 @@ async function runTerminalCommand(commandLine, context) {
|
|
|
34821
34989
|
context.queueRender();
|
|
34822
34990
|
return;
|
|
34823
34991
|
}
|
|
34992
|
+
if (command === "context") {
|
|
34993
|
+
context.state = { ...context.state, overlay: "context" };
|
|
34994
|
+
context.queueRender();
|
|
34995
|
+
return;
|
|
34996
|
+
}
|
|
34824
34997
|
if (command === "model") {
|
|
34825
34998
|
if (args.length > 0) {
|
|
34826
34999
|
context.state = { ...context.state, notice: "Usage: /model", noticeLevel: "warn" };
|
|
@@ -45650,4 +45823,4 @@ switch (command) {
|
|
|
45650
45823
|
}
|
|
45651
45824
|
}
|
|
45652
45825
|
|
|
45653
|
-
//# debugId=
|
|
45826
|
+
//# debugId=C4FD6B649361AE3464756E2164756E21
|