perchai-cli 2.4.45 → 2.4.46
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/perch.mjs +255 -22
- package/package.json +1 -1
package/dist/perch.mjs
CHANGED
|
@@ -75566,7 +75566,6 @@ var init_payroll = __esm({
|
|
|
75566
75566
|
// lib/perchBusinessTools/index.ts
|
|
75567
75567
|
var init_perchBusinessTools = __esm({
|
|
75568
75568
|
"lib/perchBusinessTools/index.ts"() {
|
|
75569
|
-
"use strict";
|
|
75570
75569
|
init_generateAPAuditPacket();
|
|
75571
75570
|
init_inventoryFolder();
|
|
75572
75571
|
init_loadBusinessTables();
|
|
@@ -75918,7 +75917,6 @@ function isTurnAbortedError(error) {
|
|
|
75918
75917
|
var TURN_STOPPED_BY_USER_MESSAGE;
|
|
75919
75918
|
var init_turnAbort = __esm({
|
|
75920
75919
|
"features/perchTerminal/runtime/turnAbort.ts"() {
|
|
75921
|
-
"use strict";
|
|
75922
75920
|
TURN_STOPPED_BY_USER_MESSAGE = "Turn stopped by user.";
|
|
75923
75921
|
}
|
|
75924
75922
|
});
|
|
@@ -76224,7 +76222,6 @@ function getToolDisplayName(toolName) {
|
|
|
76224
76222
|
var NON_MODULE_TOOL_OWNERS, TOOL_RISK, TOOL_DISPLAY_NAMES;
|
|
76225
76223
|
var init_catalog = __esm({
|
|
76226
76224
|
"features/perchTerminal/runtime/toolSystem/catalog.ts"() {
|
|
76227
|
-
"use strict";
|
|
76228
76225
|
init_toolNames();
|
|
76229
76226
|
NON_MODULE_TOOL_OWNERS = {
|
|
76230
76227
|
[TOOL_NAMES.listSources]: "lane",
|
|
@@ -86739,6 +86736,7 @@ function truncateHistoryLine(value, max2) {
|
|
|
86739
86736
|
}
|
|
86740
86737
|
var init_operatorTruth = __esm({
|
|
86741
86738
|
"features/perchTerminal/runtime/operatorTruth.ts"() {
|
|
86739
|
+
"use strict";
|
|
86742
86740
|
}
|
|
86743
86741
|
});
|
|
86744
86742
|
|
|
@@ -93085,7 +93083,7 @@ var init_agentSkillRegistry = __esm({
|
|
|
93085
93083
|
"name": "wait-operator",
|
|
93086
93084
|
"description": "Watch bounded external or local conditions, poll deployment and job status, wait through short-running tasks, and resume with verified state instead of guessing.",
|
|
93087
93085
|
"path": "features/perchTerminal/agentPlatform/skills/wait-operator/SKILL.md",
|
|
93088
|
-
"body": "\n# wait-operator\n\nUse this skill when the user asks Perch to wait, watch, poll, monitor, check back, or keep an eye on a deployment, CI run, background job, file creation, local server, browser page, or other condition.\n\n## Operating Rules\n\n- Treat waiting as an active bounded loop: define the condition, timeout, interval, and failure states before polling.\n- Never sleep indefinitely. Use short intervals and a clear maximum wait unless the user explicitly asks for a longer watch.\n- Prefer read-only checks: status commands, existing logs, HTTP status endpoints, browser observe/wait, or file existence checks.\n- For deployments and CI, distinguish pending, ready/success, failed, canceled, timed out, and unknown. Do not call a run ready from elapsed time alone.\n- Report the last observed state if the wait times out or credentials/session state blocks verification.\n- Avoid noisy transcript spam. Group repeated polling into a short progress summary unless the user asks to see every check.\n- If the user asks for a real follow-up after this turn rather than an in-turn wait, create or suggest the appropriate automation instead of pretending the current turn can run forever.\n\n## Verification\n\nFinish only after the watched condition is directly verified or a blocker is named. Include the evidence source: command status, page state, URL, log line, file path, or timestamped last check.",
|
|
93086
|
+
"body": "\n# wait-operator\n\nUse this skill when the user asks Perch to wait, watch, poll, monitor, check back, or keep an eye on a deployment, CI run, background job, file creation, local server, browser page, or other condition.\n\n## Operating Rules\n\n- **Background tasks (run_in_background):** after backgrounding a long-running command, call wait_for_background_task(taskId) to end your turn and be automatically woken with the result. NEVER busy-poll check_background_task in a loop \u2014 that wastes iterations and never triggers the wake path. One check is fine for a specific reason (e.g. reporting current progress on user request); repeated polling is always wrong.\n- Treat waiting as an active bounded loop: define the condition, timeout, interval, and failure states before polling.\n- Never sleep indefinitely. Use short intervals and a clear maximum wait unless the user explicitly asks for a longer watch.\n- Prefer read-only checks: status commands, existing logs, HTTP status endpoints, browser observe/wait, or file existence checks.\n- For deployments and CI, distinguish pending, ready/success, failed, canceled, timed out, and unknown. Do not call a run ready from elapsed time alone.\n- Report the last observed state if the wait times out or credentials/session state blocks verification.\n- Avoid noisy transcript spam. Group repeated polling into a short progress summary unless the user asks to see every check.\n- If the user asks for a real follow-up after this turn rather than an in-turn wait, create or suggest the appropriate automation instead of pretending the current turn can run forever.\n\n## Verification\n\nFinish only after the watched condition is directly verified or a blocker is named. Include the evidence source: command status, page state, URL, log line, file path, or timestamped last check.",
|
|
93089
93087
|
"surface": {
|
|
93090
93088
|
"gui": "supported",
|
|
93091
93089
|
"cli": "supported"
|
|
@@ -135384,7 +135382,7 @@ function getDesktopToolDefinitions() {
|
|
|
135384
135382
|
type: "function",
|
|
135385
135383
|
function: {
|
|
135386
135384
|
name: TOOL_NAMES.runInBackground,
|
|
135387
|
-
description: "Launch a long-running shell command in the background. Returns immediately with a taskId; the command keeps running detached.
|
|
135385
|
+
description: "Launch a long-running shell command in the background. Returns immediately with a taskId; the command keeps running detached. After launching, call wait_for_background_task(taskId) to end your turn and be automatically re-invoked when it finishes. Permission mode gates execution.",
|
|
135388
135386
|
parameters: {
|
|
135389
135387
|
type: "object",
|
|
135390
135388
|
properties: {
|
|
@@ -135406,7 +135404,7 @@ function getDesktopToolDefinitions() {
|
|
|
135406
135404
|
type: "function",
|
|
135407
135405
|
function: {
|
|
135408
135406
|
name: TOOL_NAMES.checkBackgroundTask,
|
|
135409
|
-
description: "
|
|
135407
|
+
description: "One-off status check for a background task. Returns status, exit code, runtime, and output preview. Do NOT call this repeatedly to wait for completion \u2014 use wait_for_background_task instead.",
|
|
135410
135408
|
parameters: {
|
|
135411
135409
|
type: "object",
|
|
135412
135410
|
properties: {
|
|
@@ -135448,7 +135446,7 @@ function getDesktopToolDefinitions() {
|
|
|
135448
135446
|
type: "function",
|
|
135449
135447
|
function: {
|
|
135450
135448
|
name: TOOL_NAMES.waitForBackgroundTask,
|
|
135451
|
-
description: "
|
|
135449
|
+
description: "After launching long-running work, call this to end your turn and be automatically re-invoked when it finishes. This is how you wait \u2014 do NOT poll check_background_task in a loop. The runtime delivers a system-initiated turn with the result once the task completes. Auto-wake fires in autonomous permission modes (auto_review / take_the_wheel).",
|
|
135452
135450
|
parameters: {
|
|
135453
135451
|
type: "object",
|
|
135454
135452
|
properties: {
|
|
@@ -197126,6 +197124,7 @@ function recordDispatchBatchResult(tasks, result2, ctx, opts = {}) {
|
|
|
197126
197124
|
var lifecycleByRun, MAX_LIFECYCLE_RUNS;
|
|
197127
197125
|
var init_workerLifecycle = __esm({
|
|
197128
197126
|
"features/perchTerminal/runtime/workers/workerLifecycle.ts"() {
|
|
197127
|
+
"use strict";
|
|
197129
197128
|
init_workerManifest();
|
|
197130
197129
|
lifecycleByRun = /* @__PURE__ */ new Map();
|
|
197131
197130
|
MAX_LIFECYCLE_RUNS = 200;
|
|
@@ -212049,9 +212048,13 @@ var init_backgroundWake = __esm({
|
|
|
212049
212048
|
// features/perchTerminal/runtime/toolSystem/tools/background/index.ts
|
|
212050
212049
|
var background_exports = {};
|
|
212051
212050
|
__export(background_exports, {
|
|
212051
|
+
__resetPollTrackerForTests: () => __resetPollTrackerForTests,
|
|
212052
212052
|
backgroundTools: () => backgroundTools
|
|
212053
212053
|
});
|
|
212054
|
-
|
|
212054
|
+
function __resetPollTrackerForTests() {
|
|
212055
|
+
pollTracker.clear();
|
|
212056
|
+
}
|
|
212057
|
+
var UNAVAILABLE, pollTracker, POLL_REDIRECT_THRESHOLD, runInBackgroundTool, checkBackgroundTaskTool, listBackgroundTasksTool, killBackgroundTaskTool, waitForBackgroundTaskTool, backgroundTools;
|
|
212055
212058
|
var init_background = __esm({
|
|
212056
212059
|
"features/perchTerminal/runtime/toolSystem/tools/background/index.ts"() {
|
|
212057
212060
|
"use strict";
|
|
@@ -212060,6 +212063,8 @@ var init_background = __esm({
|
|
|
212060
212063
|
init_backgroundWake();
|
|
212061
212064
|
init_toolNames();
|
|
212062
212065
|
UNAVAILABLE = "Background execution is unavailable on this surface. It requires the Perch CLI or Perch Desktop.";
|
|
212066
|
+
pollTracker = /* @__PURE__ */ new Map();
|
|
212067
|
+
POLL_REDIRECT_THRESHOLD = 2;
|
|
212063
212068
|
runInBackgroundTool = {
|
|
212064
212069
|
name: TOOL_NAMES.runInBackground,
|
|
212065
212070
|
classification: { native: false },
|
|
@@ -212079,11 +212084,26 @@ var init_background = __esm({
|
|
|
212079
212084
|
checkBackgroundTaskTool = {
|
|
212080
212085
|
name: TOOL_NAMES.checkBackgroundTask,
|
|
212081
212086
|
classification: { native: false },
|
|
212082
|
-
handler: async (args) => {
|
|
212087
|
+
handler: async (args, ctx) => {
|
|
212083
212088
|
const taskId = String(args.taskId ?? "").trim();
|
|
212084
212089
|
if (!taskId) return { ok: false, error: "taskId must be a non-empty string." };
|
|
212085
212090
|
const snapshot = await checkBackgroundTask({ taskId });
|
|
212086
212091
|
if (snapshot === null) return { ok: false, error: `No background task found for ${taskId}.` };
|
|
212092
|
+
if (snapshot.status === "running") {
|
|
212093
|
+
const key = taskId;
|
|
212094
|
+
const count = (pollTracker.get(key) ?? 0) + 1;
|
|
212095
|
+
pollTracker.set(key, count);
|
|
212096
|
+
if (count >= POLL_REDIRECT_THRESHOLD) {
|
|
212097
|
+
const mode = normalizePermissionMode(ctx.permissionMode);
|
|
212098
|
+
const wakeAvailable = WAKE_ALLOWED_PERMISSION_MODES.has(mode);
|
|
212099
|
+
return {
|
|
212100
|
+
ok: true,
|
|
212101
|
+
task: snapshot,
|
|
212102
|
+
_pollRedirect: true,
|
|
212103
|
+
note: wakeAvailable ? `Stop polling \u2014 call wait_for_background_task("${taskId}") to end this turn and be automatically woken on completion.` : `This task is still running. Auto-wake is unavailable in "${mode}" mode. Tell the user to switch to auto_review or take_the_wheel for auto-wake, or end this turn and check back later.`
|
|
212104
|
+
};
|
|
212105
|
+
}
|
|
212106
|
+
}
|
|
212087
212107
|
return { ok: true, task: snapshot };
|
|
212088
212108
|
}
|
|
212089
212109
|
};
|
|
@@ -231787,7 +231807,7 @@ function runBackgroundCommand2(input) {
|
|
|
231787
231807
|
const shell = input.shell || process.env.SHELL || "/bin/zsh";
|
|
231788
231808
|
let child;
|
|
231789
231809
|
try {
|
|
231790
|
-
child = spawn2(shell, ["-
|
|
231810
|
+
child = spawn2(shell, ["-ilc", command], {
|
|
231791
231811
|
cwd: input.cwd,
|
|
231792
231812
|
env: process.env,
|
|
231793
231813
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -233811,6 +233831,37 @@ var init_cliStandaloneOAuth = __esm({
|
|
|
233811
233831
|
}
|
|
233812
233832
|
});
|
|
233813
233833
|
|
|
233834
|
+
// lib/perchTerminal/statusLabels.ts
|
|
233835
|
+
function sectionLabel(sectionKey) {
|
|
233836
|
+
if (STATUS_LABELS[sectionKey]) return STATUS_LABELS[sectionKey];
|
|
233837
|
+
return sectionKey.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
233838
|
+
}
|
|
233839
|
+
var STATUS_LABELS;
|
|
233840
|
+
var init_statusLabels = __esm({
|
|
233841
|
+
"lib/perchTerminal/statusLabels.ts"() {
|
|
233842
|
+
STATUS_LABELS = {
|
|
233843
|
+
not_found: "Not found",
|
|
233844
|
+
not_initialized: "Not initialized",
|
|
233845
|
+
sent_raw: "Included",
|
|
233846
|
+
sent_compacted: "Summarized",
|
|
233847
|
+
output_reserve: "Reserved for response",
|
|
233848
|
+
excluded: "Excluded",
|
|
233849
|
+
skipped: "Skipped",
|
|
233850
|
+
reserved: "Reserved",
|
|
233851
|
+
generated: "Generated",
|
|
233852
|
+
error: "Error",
|
|
233853
|
+
completed: "Completed",
|
|
233854
|
+
failed: "Failed",
|
|
233855
|
+
running: "Running",
|
|
233856
|
+
pending: "Pending",
|
|
233857
|
+
blocked: "Blocked",
|
|
233858
|
+
in_progress: "In progress",
|
|
233859
|
+
sent: "Sent",
|
|
233860
|
+
compacted: "Summarized"
|
|
233861
|
+
};
|
|
233862
|
+
}
|
|
233863
|
+
});
|
|
233864
|
+
|
|
233814
233865
|
// features/perchTerminal/runtime/contextMeterDisplay.ts
|
|
233815
233866
|
function positiveInt3(value) {
|
|
233816
233867
|
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return null;
|
|
@@ -233870,13 +233921,182 @@ function resolveContextMeterDisplay(snapshot, activeModel) {
|
|
|
233870
233921
|
hasWorkers
|
|
233871
233922
|
};
|
|
233872
233923
|
}
|
|
233873
|
-
|
|
233924
|
+
function displayCategoryOrder(key) {
|
|
233925
|
+
if (key.startsWith("mcp_tools")) {
|
|
233926
|
+
const idx2 = DISPLAY_CATEGORY_ORDER.indexOf("mcp_tools");
|
|
233927
|
+
return idx2;
|
|
233928
|
+
}
|
|
233929
|
+
const idx = DISPLAY_CATEGORY_ORDER.indexOf(key);
|
|
233930
|
+
return idx === -1 ? DISPLAY_CATEGORY_ORDER.length : idx;
|
|
233931
|
+
}
|
|
233932
|
+
function displayCategoryForLane(lane) {
|
|
233933
|
+
if (lane.startsWith("mcp_tools")) {
|
|
233934
|
+
return { key: lane, label: sectionLabel(lane) };
|
|
233935
|
+
}
|
|
233936
|
+
switch (lane) {
|
|
233937
|
+
case "system":
|
|
233938
|
+
case "system_prompt":
|
|
233939
|
+
case "selected_model":
|
|
233940
|
+
return { key: "system_prompt", label: "System prompt" };
|
|
233941
|
+
case "tools":
|
|
233942
|
+
case "tool_definitions":
|
|
233943
|
+
case "system_tools":
|
|
233944
|
+
return { key: "system_tools", label: "System tools" };
|
|
233945
|
+
case "mcp_tools":
|
|
233946
|
+
return { key: "mcp_tools", label: "MCP tools" };
|
|
233947
|
+
case "skills":
|
|
233948
|
+
case "agent_skills":
|
|
233949
|
+
return { key: "skills", label: "Skills" };
|
|
233950
|
+
case "output_response":
|
|
233951
|
+
return { key: "output_response", label: "Output response" };
|
|
233952
|
+
case "output_reserve":
|
|
233953
|
+
case "reserved_output":
|
|
233954
|
+
return { key: "reserved_output", label: "Reserved output" };
|
|
233955
|
+
case "deferred":
|
|
233956
|
+
return { key: "deferred", label: "Deferred" };
|
|
233957
|
+
case "messages":
|
|
233958
|
+
case "conversation":
|
|
233959
|
+
case "summarized_conversation":
|
|
233960
|
+
return { key: "conversation", label: "Conversation" };
|
|
233961
|
+
case "tool_transcript":
|
|
233962
|
+
return { key: "tool_transcript", label: "Tool transcript" };
|
|
233963
|
+
case "project_memory":
|
|
233964
|
+
case "permanent_memory":
|
|
233965
|
+
case "rules_project_memory":
|
|
233966
|
+
case "durable_memory":
|
|
233967
|
+
return { key: "memory_rules", label: "Memory & rules" };
|
|
233968
|
+
case "tool_evidence":
|
|
233969
|
+
case "thread_evidence":
|
|
233970
|
+
case "retrieved_evidence":
|
|
233971
|
+
case "files":
|
|
233972
|
+
case "selected_source":
|
|
233973
|
+
return { key: "evidence", label: "Evidence" };
|
|
233974
|
+
case "workers":
|
|
233975
|
+
return { key: "workers", label: "Workers" };
|
|
233976
|
+
case "desktop":
|
|
233977
|
+
case "workspace_context":
|
|
233978
|
+
return { key: "workspace_context", label: "Workspace context" };
|
|
233979
|
+
case "wire_overhead":
|
|
233980
|
+
return { key: "overhead", label: "Overhead" };
|
|
233981
|
+
default:
|
|
233982
|
+
return { key: lane, label: sectionLabel(lane) };
|
|
233983
|
+
}
|
|
233984
|
+
}
|
|
233985
|
+
function isCacheKey(key) {
|
|
233986
|
+
return key.includes("cache");
|
|
233987
|
+
}
|
|
233988
|
+
function segmentsFromCategories(categories) {
|
|
233989
|
+
return categories.filter((category) => category.tokens > 0 && !isCacheKey(category.key)).map((category) => ({
|
|
233990
|
+
key: category.key,
|
|
233991
|
+
label: category.label,
|
|
233992
|
+
tokens: category.tokens
|
|
233993
|
+
}));
|
|
233994
|
+
}
|
|
233995
|
+
function segmentsFromLaneTotals(laneTotals) {
|
|
233996
|
+
return laneTotals.filter((lane) => lane.lane !== "output_reserve" && lane.tokens > 0 && !isCacheKey(lane.lane)).map((lane) => ({ key: lane.lane, label: sectionLabel(lane.lane), tokens: lane.tokens }));
|
|
233997
|
+
}
|
|
233998
|
+
function segmentsFromRows(rows) {
|
|
233999
|
+
const byLane = /* @__PURE__ */ new Map();
|
|
234000
|
+
for (const row of rows) {
|
|
234001
|
+
if (row.lane === "output_reserve") continue;
|
|
234002
|
+
if (isCacheKey(row.lane)) continue;
|
|
234003
|
+
if (!ADMITTED_ROW_STATUSES2.has(row.status)) continue;
|
|
234004
|
+
byLane.set(row.lane, (byLane.get(row.lane) ?? 0) + row.estimatedTokens);
|
|
234005
|
+
}
|
|
234006
|
+
return Array.from(byLane.entries()).filter(([, tokens]) => tokens > 0).map(([key, tokens]) => ({ key, label: sectionLabel(key), tokens }));
|
|
234007
|
+
}
|
|
234008
|
+
function segmentsFromBreakdown(breakdown) {
|
|
234009
|
+
return Object.entries(breakdown).filter(([key, val]) => val.estimatedTokens > 0 && !isCacheKey(key)).map(([key, val]) => ({ key, label: sectionLabel(key), tokens: val.estimatedTokens }));
|
|
234010
|
+
}
|
|
234011
|
+
function groupDisplaySegments(segments) {
|
|
234012
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
234013
|
+
for (const segment of segments) {
|
|
234014
|
+
const display = displayCategoryForLane(segment.key);
|
|
234015
|
+
const existing = grouped.get(display.key);
|
|
234016
|
+
if (existing) {
|
|
234017
|
+
existing.tokens += segment.tokens;
|
|
234018
|
+
} else {
|
|
234019
|
+
grouped.set(display.key, { key: display.key, label: display.label, tokens: segment.tokens });
|
|
234020
|
+
}
|
|
234021
|
+
}
|
|
234022
|
+
return Array.from(grouped.values());
|
|
234023
|
+
}
|
|
234024
|
+
function buildContentSegments(snapshot) {
|
|
234025
|
+
if (!snapshot) return [];
|
|
234026
|
+
if (snapshot.contextCategories?.length) {
|
|
234027
|
+
return segmentsFromCategories(snapshot.contextCategories);
|
|
234028
|
+
}
|
|
234029
|
+
const source = snapshot.laneTotals?.length ? segmentsFromLaneTotals(snapshot.laneTotals) : snapshot.rows ? segmentsFromRows(snapshot.rows) : segmentsFromBreakdown(snapshot.sectionBreakdown ?? {});
|
|
234030
|
+
return groupDisplaySegments(source);
|
|
234031
|
+
}
|
|
234032
|
+
function resolveTruncationState(snapshot) {
|
|
234033
|
+
if (snapshot?.truncated) return "truncated";
|
|
234034
|
+
if (snapshot?.compacted) return "compacted";
|
|
234035
|
+
return "none";
|
|
234036
|
+
}
|
|
234037
|
+
function buildContextComposition(snapshot, activeModel) {
|
|
234038
|
+
const meter = resolveContextMeterDisplay(snapshot, activeModel);
|
|
234039
|
+
const totalTokens = Math.max(1, meter.limitTokens);
|
|
234040
|
+
const reservedOutputTokens = Math.max(0, meter.reservedOutputTokens);
|
|
234041
|
+
const segments = buildContentSegments(snapshot);
|
|
234042
|
+
if (reservedOutputTokens > 0) {
|
|
234043
|
+
segments.push({ key: "reserved_output", label: "Reserved output", tokens: reservedOutputTokens });
|
|
234044
|
+
}
|
|
234045
|
+
const ordered = segments.filter((segment) => segment.tokens > 0).sort((a, b2) => displayCategoryOrder(a.key) - displayCategoryOrder(b2.key));
|
|
234046
|
+
const usedTokens = Math.min(
|
|
234047
|
+
totalTokens,
|
|
234048
|
+
ordered.reduce((sum, segment) => sum + segment.tokens, 0)
|
|
234049
|
+
);
|
|
234050
|
+
const freeSpaceTokens = Math.max(0, totalTokens - usedTokens);
|
|
234051
|
+
const slices = ordered.map((segment) => ({
|
|
234052
|
+
key: segment.key,
|
|
234053
|
+
label: segment.label,
|
|
234054
|
+
tokens: segment.tokens,
|
|
234055
|
+
pct: segment.tokens / totalTokens * 100
|
|
234056
|
+
}));
|
|
234057
|
+
return {
|
|
234058
|
+
slices,
|
|
234059
|
+
freeSpaceTokens,
|
|
234060
|
+
freeSpacePct: freeSpaceTokens / totalTokens * 100,
|
|
234061
|
+
usedTokens,
|
|
234062
|
+
totalTokens,
|
|
234063
|
+
usedPercent: usedTokens / totalTokens * 100,
|
|
234064
|
+
truncationState: resolveTruncationState(snapshot)
|
|
234065
|
+
};
|
|
234066
|
+
}
|
|
234067
|
+
function contextTruncationNotice(state) {
|
|
234068
|
+
switch (state) {
|
|
234069
|
+
case "compacted":
|
|
234070
|
+
return "\u26A0 Context full \u2014 older messages were compacted to fit";
|
|
234071
|
+
case "truncated":
|
|
234072
|
+
return "\u26A0 Context full \u2014 older messages were dropped to fit";
|
|
234073
|
+
default:
|
|
234074
|
+
return "";
|
|
234075
|
+
}
|
|
234076
|
+
}
|
|
234077
|
+
var ADMITTED_ROW_STATUSES2, DISPLAY_CATEGORY_ORDER;
|
|
233874
234078
|
var init_contextMeterDisplay = __esm({
|
|
233875
234079
|
"features/perchTerminal/runtime/contextMeterDisplay.ts"() {
|
|
233876
234080
|
"use strict";
|
|
234081
|
+
init_statusLabels();
|
|
233877
234082
|
init_contextMeter();
|
|
233878
234083
|
init_contextThresholds();
|
|
233879
234084
|
ADMITTED_ROW_STATUSES2 = /* @__PURE__ */ new Set(["sent_raw", "sent_compacted"]);
|
|
234085
|
+
DISPLAY_CATEGORY_ORDER = [
|
|
234086
|
+
"system_prompt",
|
|
234087
|
+
"system_tools",
|
|
234088
|
+
"mcp_tools",
|
|
234089
|
+
"skills",
|
|
234090
|
+
"conversation",
|
|
234091
|
+
"tool_transcript",
|
|
234092
|
+
"memory_rules",
|
|
234093
|
+
"evidence",
|
|
234094
|
+
"workspace_context",
|
|
234095
|
+
"workers",
|
|
234096
|
+
"overhead",
|
|
234097
|
+
"deferred",
|
|
234098
|
+
"reserved_output"
|
|
234099
|
+
];
|
|
233880
234100
|
}
|
|
233881
234101
|
});
|
|
233882
234102
|
|
|
@@ -290603,20 +290823,33 @@ function renderCliContextMeter(snapshot, activeModel) {
|
|
|
290603
290823
|
if (snapshot.compacted || compacted > 0) parts.push(`compacted ${compacted}`);
|
|
290604
290824
|
return parts.join(" \xB7 ");
|
|
290605
290825
|
}
|
|
290826
|
+
function renderCliBlockBar(percent2, width) {
|
|
290827
|
+
const clamped = Math.max(0, Math.min(100, percent2));
|
|
290828
|
+
const filled = Math.round(clamped / 100 * width);
|
|
290829
|
+
return `\u2595${"\u2588".repeat(filled)}${"\u2591".repeat(Math.max(0, width - filled))}\u258F`;
|
|
290830
|
+
}
|
|
290606
290831
|
function renderCliContextDetails(snapshot, activeModel) {
|
|
290607
290832
|
if (!snapshot) return "context no meter yet\n";
|
|
290608
|
-
const meter = resolveContextMeterDisplay(snapshot, activeModel);
|
|
290609
|
-
const percent2 = snapshot.contextPercentage ?? Math.round(meter.committedTokens / Math.max(1, meter.limitTokens) * 100);
|
|
290610
|
-
const lines = [
|
|
290611
|
-
["context", renderCliContextMeter(snapshot, activeModel)],
|
|
290612
|
-
["thread", `${formatCliTokenCount(meter.threadTokens)} tokens`],
|
|
290613
|
-
["limit", `${formatCliTokenCount(meter.limitTokens)} tokens`],
|
|
290614
|
-
["fill", `${Math.max(0, Math.min(100, percent2))}%`],
|
|
290615
|
-
["compacted", snapshot.compacted || (snapshot.compactedRowCount ?? 0) > 0 ? `${snapshot.compactedRowCount ?? 0} row(s)` : "no"],
|
|
290616
|
-
["not-found", `${snapshot.notFoundRowCount ?? 0} row(s)`]
|
|
290617
|
-
];
|
|
290618
290833
|
const color = shouldUseCliColor();
|
|
290619
|
-
|
|
290834
|
+
const composition = buildContextComposition(snapshot, activeModel);
|
|
290835
|
+
const percent2 = Math.max(0, Math.min(100, Math.round(composition.usedPercent)));
|
|
290836
|
+
const bar = renderCliBlockBar(composition.usedPercent, 24);
|
|
290837
|
+
const header = `${paint("context".padEnd(11), "muted", color)} ${paint(bar, percent2 >= 90 ? "red" : "accent", color)} ${formatCliTokenCount(composition.usedTokens)} / ${formatCliTokenCount(composition.totalTokens)} (${percent2}%)`;
|
|
290838
|
+
const rows = [
|
|
290839
|
+
...composition.slices.map((slice2) => ({ label: slice2.label, tokens: slice2.tokens, pct: slice2.pct })),
|
|
290840
|
+
{ label: "Free space", tokens: composition.freeSpaceTokens, pct: composition.freeSpacePct }
|
|
290841
|
+
];
|
|
290842
|
+
const labelWidth = Math.max(...rows.map((row) => row.label.length));
|
|
290843
|
+
const tokenWidth = Math.max(...rows.map((row) => formatCliTokenCount(row.tokens).length));
|
|
290844
|
+
const lines = rows.map((row) => {
|
|
290845
|
+
const label = paint(` ${row.label.padEnd(labelWidth)}`, "muted", color);
|
|
290846
|
+
const tokens = formatCliTokenCount(row.tokens).padStart(tokenWidth);
|
|
290847
|
+
return `${label} ${tokens} \xB7 ${row.pct.toFixed(1).padStart(4)}%`;
|
|
290848
|
+
});
|
|
290849
|
+
const out = [header, ...lines];
|
|
290850
|
+
const notice = contextTruncationNotice(composition.truncationState);
|
|
290851
|
+
if (notice) out.push(paint(notice, "red", color));
|
|
290852
|
+
return out.join("\n") + "\n";
|
|
290620
290853
|
}
|
|
290621
290854
|
function formatCliTokenCount(value) {
|
|
290622
290855
|
if (value < 1e3) return `${Math.max(0, Math.round(value))}`;
|