pi-ui-extend 1.0.41 → 1.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -13
- package/dist/app/app.d.ts +13 -0
- package/dist/app/app.js +158 -8
- package/dist/app/cli/install.js +2 -2
- package/dist/app/commands/command-controller.d.ts +4 -0
- package/dist/app/commands/command-controller.js +11 -0
- package/dist/app/commands/command-git-actions.d.ts +25 -0
- package/dist/app/commands/command-git-actions.js +381 -0
- package/dist/app/commands/command-host.d.ts +4 -0
- package/dist/app/commands/command-host.js +5 -2
- package/dist/app/commands/command-model-actions.d.ts +1 -0
- package/dist/app/commands/command-model-actions.js +57 -35
- package/dist/app/commands/command-navigation-actions.d.ts +1 -0
- package/dist/app/commands/command-navigation-actions.js +16 -3
- package/dist/app/commands/command-registry.d.ts +2 -0
- package/dist/app/commands/command-registry.js +15 -1
- package/dist/app/commands/command-session-actions.js +9 -3
- package/dist/app/commands/reload-context-inventory.d.ts +11 -0
- package/dist/app/commands/reload-context-inventory.js +70 -0
- package/dist/app/extensions/extension-actions-controller.d.ts +1 -0
- package/dist/app/extensions/extension-actions-controller.js +6 -0
- package/dist/app/extensions/subagent-catalog-state.d.ts +9 -0
- package/dist/app/extensions/subagent-catalog-state.js +23 -0
- package/dist/app/input/autocomplete-controller.js +61 -34
- package/dist/app/input/input-action-controller.d.ts +2 -0
- package/dist/app/input/input-action-controller.js +8 -1
- package/dist/app/input/input-controller.d.ts +2 -1
- package/dist/app/input/input-controller.js +7 -2
- package/dist/app/input/prompt-enhancer-controller.js +53 -35
- package/dist/app/input/voice-controller.d.ts +41 -45
- package/dist/app/input/voice-controller.js +351 -419
- package/dist/app/model/model-usage-controller.js +17 -7
- package/dist/app/model/model-usage-status.d.ts +4 -1
- package/dist/app/model/model-usage-status.js +270 -46
- package/dist/app/popup/menu-items-controller.d.ts +13 -3
- package/dist/app/popup/menu-items-controller.js +37 -21
- package/dist/app/popup/popup-action-controller.d.ts +12 -2
- package/dist/app/popup/popup-action-controller.js +77 -24
- package/dist/app/popup/popup-menu-controller.d.ts +36 -14
- package/dist/app/popup/popup-menu-controller.js +239 -69
- package/dist/app/rendering/dcp-stats.d.ts +9 -4
- package/dist/app/rendering/dcp-stats.js +40 -425
- package/dist/app/rendering/editor-panels.js +10 -4
- package/dist/app/rendering/popup-menu-renderer.d.ts +3 -5
- package/dist/app/rendering/popup-menu-renderer.js +42 -37
- package/dist/app/rendering/render-controller.js +23 -2
- package/dist/app/rendering/status-line-renderer.d.ts +5 -0
- package/dist/app/rendering/status-line-renderer.js +41 -5
- package/dist/app/rendering/tab-line-renderer.js +26 -20
- package/dist/app/runtime.d.ts +12 -1
- package/dist/app/runtime.js +120 -12
- package/dist/app/screen/mouse-controller.d.ts +2 -0
- package/dist/app/screen/mouse-controller.js +17 -7
- package/dist/app/screen/status-controller.d.ts +4 -0
- package/dist/app/screen/status-controller.js +5 -0
- package/dist/app/session/lazy-session-manager.js +34 -0
- package/dist/app/session/session-event-controller.d.ts +1 -0
- package/dist/app/session/session-event-controller.js +10 -1
- package/dist/app/session/session-history.d.ts +1 -0
- package/dist/app/session/session-history.js +12 -1
- package/dist/app/session/session-lifecycle-controller.d.ts +7 -1
- package/dist/app/session/session-lifecycle-controller.js +16 -1
- package/dist/app/session/tabs-controller.d.ts +26 -1
- package/dist/app/session/tabs-controller.js +454 -147
- package/dist/app/subagents/subagents-files.js +60 -1
- package/dist/app/subagents/subagents-model.d.ts +1 -0
- package/dist/app/subagents/subagents-model.js +18 -2
- package/dist/app/subagents/subagents-widget-controller.d.ts +1 -0
- package/dist/app/subagents/subagents-widget-controller.js +6 -0
- package/dist/app/types.d.ts +16 -1
- package/dist/app/workspace/workspace-actions-controller.js +10 -2
- package/dist/app/workspace/workspace-undo.d.ts +1 -0
- package/dist/app/workspace/workspace-undo.js +1 -0
- package/dist/bundled-extensions/question/index.js +9 -1
- package/dist/bundled-extensions/question/remote.d.ts +4 -0
- package/dist/bundled-extensions/question/remote.js +33 -0
- package/dist/bundled-extensions/telegram-connector/bot.d.ts +43 -0
- package/dist/bundled-extensions/telegram-connector/bot.js +166 -0
- package/dist/bundled-extensions/telegram-connector/config.d.ts +8 -0
- package/dist/bundled-extensions/telegram-connector/config.js +87 -0
- package/dist/bundled-extensions/telegram-connector/coordinator.d.ts +66 -0
- package/dist/bundled-extensions/telegram-connector/coordinator.js +413 -0
- package/dist/bundled-extensions/telegram-connector/index.d.ts +3 -0
- package/dist/bundled-extensions/telegram-connector/index.js +195 -0
- package/dist/bundled-extensions/terminal-bell/index.d.ts +0 -8
- package/dist/bundled-extensions/terminal-bell/index.js +0 -76
- package/dist/bundled-extensions/workspace-undo/index.d.ts +26 -0
- package/dist/bundled-extensions/workspace-undo/index.js +191 -0
- package/dist/config.d.ts +21 -2
- package/dist/config.js +159 -32
- package/dist/default-pix-config.js +25 -5
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.js +1 -0
- package/dist/schemas/pi-tools-suite-schema.d.ts +88 -62
- package/dist/schemas/pi-tools-suite-schema.js +54 -83
- package/dist/schemas/pix-schema.d.ts +19 -2
- package/dist/schemas/pix-schema.js +47 -5
- package/dist/schemas/tasks-schema.d.ts +18 -0
- package/dist/schemas/tasks-schema.js +41 -0
- package/docs/concurrency.md +9 -1
- package/docs/desktop-mvp.md +22 -6
- package/docs/desktop-task-manager.md +148 -84
- package/docs/release.md +30 -6
- package/external/pi-tools-suite/README.md +197 -84
- package/external/pi-tools-suite/docs/evals.md +1 -1
- package/external/pi-tools-suite/docs/session-recovery.md +47 -14
- package/external/pi-tools-suite/docs/subagent-model-pools.md +48 -30
- package/external/pi-tools-suite/docs/ui-qa-subagent.md +440 -0
- package/external/pi-tools-suite/package.json +6 -1
- package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +2 -1
- package/external/pi-tools-suite/src/antigravity-auth/constants.ts +9 -3
- package/external/pi-tools-suite/src/antigravity-auth/headers.ts +41 -3
- package/external/pi-tools-suite/src/antigravity-auth/models.ts +94 -21
- package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +5 -17
- package/external/pi-tools-suite/src/antigravity-auth/payload.ts +72 -7
- package/external/pi-tools-suite/src/antigravity-auth/stream.ts +13 -1
- package/external/pi-tools-suite/src/async-subagents/agents/frontier-review.md +23 -0
- package/external/pi-tools-suite/src/async-subagents/agents/implement.md +1 -1
- package/external/pi-tools-suite/src/async-subagents/agents/presets.jsonc +16 -0
- package/external/pi-tools-suite/src/async-subagents/agents/research.md +5 -3
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/browser.mjs +346 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/desktop.mjs +1038 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/backends/tui.mjs +759 -0
- package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/scripts/browser-qa-runner.mjs +32 -23
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/chrome-devtools/chrome-devtools-provider.mjs +895 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/linux/linux-atspi.py +494 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/macos/macos-accessibility.swift +1085 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/bridge-client.mjs +50 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/native-terminal/native-terminal-host.mjs +501 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/drivers/windows/windows-uia.ps1 +454 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-auth.md +114 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-chrome-devtools.md +91 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser-playwright.md +145 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/browser.md +82 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-linux.md +26 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-macos.md +29 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop-windows.md +23 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/desktop.md +54 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-native-terminal.md +59 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui-pty.md +37 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/guides/tui.md +60 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa/scripts/ui-qa-runner.mjs +535 -0
- package/external/pi-tools-suite/src/async-subagents/agents/ui-qa.md +75 -0
- package/external/pi-tools-suite/src/async-subagents/commands.ts +15 -71
- package/external/pi-tools-suite/src/async-subagents/core/activity.ts +33 -0
- package/external/pi-tools-suite/src/async-subagents/core/agent-catalog.ts +5 -4
- package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +1 -1
- package/external/pi-tools-suite/src/async-subagents/core/agents-dir.ts +8 -5
- package/external/pi-tools-suite/src/async-subagents/core/browser-qa.ts +16 -2
- package/external/pi-tools-suite/src/async-subagents/core/config.ts +160 -327
- package/external/pi-tools-suite/src/async-subagents/core/model-selection.ts +2 -1
- package/external/pi-tools-suite/src/async-subagents/core/registry.ts +158 -33
- package/external/pi-tools-suite/src/async-subagents/core/routing.ts +21 -5
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +40 -26
- package/external/pi-tools-suite/src/async-subagents/core/state.ts +40 -0
- package/external/pi-tools-suite/src/async-subagents/core/types.ts +7 -0
- package/external/pi-tools-suite/src/async-subagents/core/ultrawork-auto.ts +51 -45
- package/external/pi-tools-suite/src/async-subagents/index.ts +69 -5
- package/external/pi-tools-suite/src/async-subagents/lib.ts +16 -9
- package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +8 -5
- package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +5 -4
- package/external/pi-tools-suite/src/async-subagents/types.ts +1 -0
- package/external/pi-tools-suite/src/coding-discipline/index.ts +90 -59
- package/external/pi-tools-suite/src/config.ts +55 -1
- package/external/pi-tools-suite/src/context-gateway/accounting-log.ts +282 -0
- package/external/pi-tools-suite/src/context-gateway/config.ts +77 -3
- package/external/pi-tools-suite/src/context-gateway/efficiency.ts +414 -0
- package/external/pi-tools-suite/src/context-gateway/enforcement.ts +222 -0
- package/external/pi-tools-suite/src/context-gateway/index.ts +206 -19
- package/external/pi-tools-suite/src/context-gateway/storeless-capabilities.ts +7 -7
- package/external/pi-tools-suite/src/context-gateway/telemetry.ts +101 -28
- package/external/pi-tools-suite/src/context-gateway/types.ts +16 -3
- package/external/pi-tools-suite/src/context-inventory.ts +99 -0
- package/external/pi-tools-suite/src/dcp/auto-compress-budget.ts +39 -4
- package/external/pi-tools-suite/src/dcp/auto-compress.ts +128 -49
- package/external/pi-tools-suite/src/dcp/commands.ts +32 -156
- package/external/pi-tools-suite/src/dcp/compress-tool.ts +177 -46
- package/external/pi-tools-suite/src/dcp/compression-blocks.ts +6 -58
- package/external/pi-tools-suite/src/dcp/compression-preview.ts +9 -0
- package/external/pi-tools-suite/src/dcp/compression-progress.ts +22 -0
- package/external/pi-tools-suite/src/dcp/config.ts +114 -17
- package/external/pi-tools-suite/src/dcp/conversation-index.ts +36 -9
- package/external/pi-tools-suite/src/dcp/diagnostics.ts +41 -0
- package/external/pi-tools-suite/src/dcp/fresh-tool-results.ts +38 -0
- package/external/pi-tools-suite/src/dcp/index.ts +338 -66
- package/external/pi-tools-suite/src/dcp/journal.ts +126 -4
- package/external/pi-tools-suite/src/dcp/progress-controller.ts +2 -1
- package/external/pi-tools-suite/src/dcp/prompts.ts +83 -192
- package/external/pi-tools-suite/src/dcp/protected-continuity.ts +175 -0
- package/external/pi-tools-suite/src/dcp/pruner-candidates.ts +93 -3
- package/external/pi-tools-suite/src/dcp/pruner-message-ids.ts +6 -10
- package/external/pi-tools-suite/src/dcp/pruner-nudge.ts +36 -33
- package/external/pi-tools-suite/src/dcp/pruner-tools.ts +6 -3
- package/external/pi-tools-suite/src/dcp/pruner.ts +1 -0
- package/external/pi-tools-suite/src/dcp/routine-pressure.ts +86 -0
- package/external/pi-tools-suite/src/dcp/state.ts +9 -0
- package/external/pi-tools-suite/src/dcp/statistics.d.ts +8 -0
- package/external/pi-tools-suite/src/dcp/statistics.js +156 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +78 -22
- package/external/pi-tools-suite/src/index.ts +7 -1
- package/external/pi-tools-suite/src/lib/project.ts +36 -1
- package/external/pi-tools-suite/src/model-tools/index.ts +10 -7
- package/external/pi-tools-suite/src/repo-discovery/index.ts +304 -4
- package/external/pi-tools-suite/src/resource-registry/index.ts +2551 -0
- package/external/pi-tools-suite/src/session-recovery/index.ts +17 -0
- package/external/pi-tools-suite/src/shell-command-policy.ts +219 -0
- package/external/pi-tools-suite/src/todo/index.ts +21 -0
- package/external/pi-tools-suite/src/todo/todo.ts +19 -1
- package/external/pi-tools-suite/src/tool-descriptions.ts +47 -19
- package/package.json +10 -9
- package/schemas/pi-tools-suite.json +466 -287
- package/schemas/pix.json +129 -11
- package/schemas/tasks.json +131 -0
- package/skills/simplify/SKILL.md +33 -5
- package/docs/desktop-markdown-media.md +0 -77
- package/external/pi-tools-suite/docs/browser-qa-subagent.md +0 -177
- package/external/pi-tools-suite/docs/dcp-emergency-current-turn.md +0 -102
- package/external/pi-tools-suite/src/async-subagents/agents/browser-qa.md +0 -598
- package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +0 -54
- package/external/pi-tools-suite/src/skill-installer/index.ts +0 -333
- package/skills/playwright-cli/SKILL.md +0 -420
- package/skills/playwright-cli/references/element-attributes.md +0 -23
- package/skills/playwright-cli/references/playwright-tests.md +0 -50
- package/skills/playwright-cli/references/request-mocking.md +0 -87
- package/skills/playwright-cli/references/running-code.md +0 -241
- package/skills/playwright-cli/references/session-management.md +0 -273
- package/skills/playwright-cli/references/spec-driven-testing.md +0 -311
- package/skills/playwright-cli/references/storage-state.md +0 -290
- package/skills/playwright-cli/references/test-generation.md +0 -142
- package/skills/playwright-cli/references/tracing.md +0 -154
- package/skills/playwright-cli/references/video-recording.md +0 -147
- package/skills/spec-lite/SKILL.md +0 -140
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-auth.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/examples/qa-flow.example.jsonc +0 -0
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.LICENSE +0 -0
- /package/external/pi-tools-suite/src/async-subagents/agents/{browser-qa → ui-qa/browser}/vendor/fflate.mjs +0 -0
|
@@ -1,439 +1,54 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const stats = collectDcpSessionStats(session, latestState, branch, manualModeBaseline);
|
|
12
|
-
const nudgeStats = collectDcpNudgeStats(branch, latestState?.data);
|
|
13
|
-
const activeBlocks = stats.activeBlocks ?? 0;
|
|
14
|
-
const totalBlocks = stats.totalBlocks ?? stats.activeBlocks ?? 0;
|
|
15
|
-
const totalNudgeEvents = nudgeStats.emitted + nudgeStats.reapplied + nudgeStats.upgraded;
|
|
16
|
-
const activeAnchors = NUDGE_TYPES.reduce((sum, type) => sum + nudgeStats.activeByType[type], 0);
|
|
17
|
-
const lines = [
|
|
18
|
-
"DCP Session Statistics:",
|
|
19
|
-
` Tokens saved (estimated): ${fmt(stats.tokensSaved)}`,
|
|
20
|
-
` Total pruning operations: ${fmt(stats.totalPruneCount)}`,
|
|
21
|
-
` Compression blocks active: ${activeBlocks} / ${totalBlocks} total`,
|
|
22
|
-
` Manual mode: ${stats.manualMode === true ? "on" : stats.manualMode === false ? "off" : "unknown"}`,
|
|
23
|
-
` State source: ${formatStateSource(stats.stateSource)}`,
|
|
24
|
-
"",
|
|
25
|
-
"Nudge telemetry:",
|
|
26
|
-
` Sent: ${fmt(nudgeStats.emitted)} emitted, ${fmt(nudgeStats.reapplied)} reapplied, ${fmt(nudgeStats.upgraded)} upgraded`,
|
|
27
|
-
` By type: ${NUDGE_TYPES.map((type) => `${type}=${fmt(nudgeStats.byType[type])}`).join(", ")}`,
|
|
28
|
-
` Active anchors: ${fmt(activeAnchors)}${activeAnchors > 0 ? ` (${NUDGE_TYPES.map((type) => `${type}=${fmt(nudgeStats.activeByType[type])}`).join(", ")})` : ""}`,
|
|
29
|
-
` Cleared after compress: ${fmt(nudgeStats.clearedEvents)} time${nudgeStats.clearedEvents === 1 ? "" : "s"} (${fmt(nudgeStats.clearedAnchors)} anchor${nudgeStats.clearedAnchors === 1 ? "" : "s"})`,
|
|
30
|
-
` Compliance proxy: ${fmt(nudgeStats.clearedEvents)} compress-after-nudge / ${fmt(totalNudgeEvents)} nudge event${totalNudgeEvents === 1 ? "" : "s"} (${pct(nudgeStats.clearedEvents, totalNudgeEvents)})`,
|
|
31
|
-
nudgeStats.last
|
|
32
|
-
? ` Last nudge: ${nudgeStats.last.type} ${nudgeStats.last.event} at ${formatDate(nudgeStats.last.createdAt)} (${formatContextPercent(nudgeStats.last.contextPercent)})`
|
|
33
|
-
: " Last nudge: none recorded",
|
|
34
|
-
"",
|
|
35
|
-
`Context: ${formatContextUsage(stats)}`,
|
|
36
|
-
];
|
|
37
|
-
return lines.join("\n");
|
|
38
|
-
}
|
|
39
|
-
function collectDcpSessionStats(session, latestState, branch, manualModeBaseline) {
|
|
40
|
-
const usage = session.getContextUsage();
|
|
41
|
-
const stats = {
|
|
42
|
-
runs: 0,
|
|
43
|
-
tokensSaved: 0,
|
|
44
|
-
totalPruneCount: 0,
|
|
45
|
-
items: 0,
|
|
46
|
-
summaryTokens: 0,
|
|
47
|
-
prunedTools: 0,
|
|
48
|
-
stateSource: latestState?.source ?? "tool-results",
|
|
49
|
-
...(latestState ? { manualMode: manualModeBaseline } : {}),
|
|
50
|
-
...(usage?.tokens != null ? { contextTokens: usage.tokens } : {}),
|
|
51
|
-
...(usage?.contextWindow != null ? { contextWindow: usage.contextWindow } : {}),
|
|
52
|
-
...(usage?.percent != null ? { contextPercent: usage.percent } : {}),
|
|
53
|
-
};
|
|
54
|
-
if (latestState)
|
|
55
|
-
applyDcpStateStats(stats, latestState.data);
|
|
56
|
-
for (const entry of branch) {
|
|
57
|
-
if (entry.type !== "message")
|
|
58
|
-
continue;
|
|
59
|
-
const message = entry.message;
|
|
60
|
-
if (message.role !== "toolResult")
|
|
61
|
-
continue;
|
|
62
|
-
if (normalizeToolName(message.toolName) !== "compress")
|
|
63
|
-
continue;
|
|
64
|
-
if ("isError" in message && message.isError === true)
|
|
65
|
-
continue;
|
|
66
|
-
const result = parseToolResultText(message.content);
|
|
67
|
-
if (!result)
|
|
68
|
-
continue;
|
|
69
|
-
if (result.idempotentReplay !== true) {
|
|
70
|
-
stats.runs += 1;
|
|
71
|
-
stats.tokensSaved += numberValue(result.tokensSaved) ?? 0;
|
|
72
|
-
stats.items += numberValue(result.itemCount) ?? sumDefined(numberValue(result.ranges), numberValue(result.messages)) ?? 0;
|
|
73
|
-
stats.summaryTokens += numberValue(result.totalSummaryTokens) ?? 0;
|
|
74
|
-
}
|
|
75
|
-
if (!latestState) {
|
|
76
|
-
stats.totalPruneCount = Math.max(stats.totalPruneCount, numberValue(result.totalPruneCount) ?? 0);
|
|
77
|
-
const prunedTools = numberValue(result.prunedTools);
|
|
78
|
-
if (prunedTools != null)
|
|
79
|
-
stats.prunedTools = prunedTools;
|
|
80
|
-
const activeBlocks = numberValue(result.activeBlocks);
|
|
81
|
-
const totalBlocks = numberValue(result.totalBlocks);
|
|
82
|
-
if (activeBlocks != null)
|
|
83
|
-
stats.activeBlocks = activeBlocks;
|
|
84
|
-
if (totalBlocks != null)
|
|
85
|
-
stats.totalBlocks = totalBlocks;
|
|
86
|
-
}
|
|
87
|
-
const contextTokens = numberValue(result.contextTokens);
|
|
88
|
-
const contextWindow = numberValue(result.contextWindow);
|
|
89
|
-
const contextPercent = numberValue(result.contextPercent);
|
|
90
|
-
if (stats.contextTokens == null && contextTokens != null)
|
|
91
|
-
stats.contextTokens = contextTokens;
|
|
92
|
-
if (stats.contextWindow == null && contextWindow != null)
|
|
93
|
-
stats.contextWindow = contextWindow;
|
|
94
|
-
if (stats.contextPercent == null && contextPercent != null)
|
|
95
|
-
stats.contextPercent = contextPercent;
|
|
96
|
-
}
|
|
97
|
-
if (latestState) {
|
|
98
|
-
// Journal state owns durable block/prune counts; successful compress tool
|
|
99
|
-
// results own operation gain because the journal intentionally stores only
|
|
100
|
-
// projection decisions rather than derived accounting snapshots.
|
|
101
|
-
stats.totalPruneCount = Math.max(stats.totalPruneCount, (stats.totalBlocks ?? 0) + stats.prunedTools);
|
|
102
|
-
}
|
|
103
|
-
return stats;
|
|
104
|
-
}
|
|
105
|
-
function applyDcpStateStats(stats, data) {
|
|
106
|
-
stats.tokensSaved = numberValue(data.tokensSaved) ?? stats.tokensSaved;
|
|
107
|
-
stats.tokensSaved += numberValue(data.prunedTokensSaved) ?? 0;
|
|
108
|
-
stats.totalPruneCount = numberValue(data.totalPruneCount) ?? stats.totalPruneCount;
|
|
109
|
-
const blocks = Array.isArray(data.compressionBlocks) ? data.compressionBlocks : undefined;
|
|
110
|
-
if (blocks) {
|
|
111
|
-
stats.totalBlocks = blocks.length;
|
|
112
|
-
stats.activeBlocks = blocks.filter((block) => isRecord(block) && block.active !== false).length;
|
|
113
|
-
}
|
|
114
|
-
if (Array.isArray(data.prunedToolIds))
|
|
115
|
-
stats.prunedTools = data.prunedToolIds.length;
|
|
116
|
-
if (typeof data.manualMode === "boolean")
|
|
117
|
-
stats.manualMode = data.manualMode;
|
|
118
|
-
}
|
|
119
|
-
function collectDcpNudgeStats(branch, latestState) {
|
|
120
|
-
const stats = {
|
|
121
|
-
emitted: 0,
|
|
122
|
-
reapplied: 0,
|
|
123
|
-
upgraded: 0,
|
|
124
|
-
clearedEvents: 0,
|
|
125
|
-
clearedAnchors: 0,
|
|
126
|
-
byType: { "turn": 0, "iteration": 0, "context-soft": 0, "context-strong": 0 },
|
|
127
|
-
activeByType: { "turn": 0, "iteration": 0, "context-soft": 0, "context-strong": 0 },
|
|
128
|
-
};
|
|
129
|
-
if (latestState)
|
|
130
|
-
applyActiveAnchorStats(stats, latestState);
|
|
131
|
-
for (const entry of branch) {
|
|
132
|
-
const data = customEntryData(entry, "dcp-nudge");
|
|
133
|
-
if (!data)
|
|
134
|
-
continue;
|
|
135
|
-
const event = data.event;
|
|
136
|
-
if ((event === "emitted" || event === "reapplied" || event === "upgraded") && isNudgeType(data.type)) {
|
|
137
|
-
if (event === "emitted")
|
|
138
|
-
stats.emitted += 1;
|
|
139
|
-
else if (event === "reapplied")
|
|
140
|
-
stats.reapplied += 1;
|
|
141
|
-
else
|
|
142
|
-
stats.upgraded += 1;
|
|
143
|
-
stats.byType[data.type] += 1;
|
|
144
|
-
const createdAt = numberValue(data.createdAt);
|
|
145
|
-
const contextPercent = typeof data.contextPercent === "number" || data.contextPercent === null ? data.contextPercent : undefined;
|
|
146
|
-
if (!stats.last || (createdAt ?? 0) >= (stats.last.createdAt ?? 0)) {
|
|
147
|
-
stats.last = {
|
|
148
|
-
type: data.type,
|
|
149
|
-
event,
|
|
150
|
-
...(createdAt !== undefined ? { createdAt } : {}),
|
|
151
|
-
...(contextPercent !== undefined ? { contextPercent } : {}),
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
else if (event === "cleared") {
|
|
156
|
-
stats.clearedEvents += 1;
|
|
157
|
-
stats.clearedAnchors += Math.max(0, numberValue(data.clearedAnchors) ?? 0);
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
return stats;
|
|
161
|
-
}
|
|
162
|
-
function readDcpManualModeBaseline(session, configPath = join(homedir(), ".config", "pi", "pi-tools-suite.jsonc")) {
|
|
163
|
-
let enabled = false;
|
|
164
|
-
if (!existsSync(configPath))
|
|
165
|
-
return enabled;
|
|
1
|
+
import { formatDcpStatistics } from "../../../external/pi-tools-suite/src/dcp/statistics.js";
|
|
2
|
+
/** On-demand TUI path: read the full branch asynchronously without hydrating
|
|
3
|
+
* the lazy presentation manager or blocking terminal input. ACP supplies a
|
|
4
|
+
* complete branch directly to the synchronous formatter instead. */
|
|
5
|
+
export async function loadDcpStatsToast(session) {
|
|
6
|
+
const manager = session.sessionManager;
|
|
7
|
+
if (!manager.readFullBranchEntries)
|
|
8
|
+
return formatDcpStatsToast(session);
|
|
9
|
+
const sessionId = manager.getSessionId?.(), leafId = manager.getLeafId?.();
|
|
10
|
+
const model = session.model;
|
|
166
11
|
try {
|
|
167
|
-
const
|
|
168
|
-
if (
|
|
169
|
-
|
|
170
|
-
const dcp = parsed.dcp;
|
|
171
|
-
if (!isRecord(dcp))
|
|
172
|
-
return enabled;
|
|
173
|
-
const manualMode = dcp.manualMode;
|
|
174
|
-
if (isRecord(manualMode) && typeof manualMode.enabled === "boolean")
|
|
175
|
-
enabled = manualMode.enabled;
|
|
176
|
-
const overrides = dcp.modelOverrides;
|
|
177
|
-
if (!isRecord(overrides))
|
|
178
|
-
return enabled;
|
|
179
|
-
for (const override of matchingModelOverrides(overrides, dcpModelKeys(session))) {
|
|
180
|
-
const overrideManualMode = override.manualMode;
|
|
181
|
-
if (isRecord(overrideManualMode) && typeof overrideManualMode.enabled === "boolean") {
|
|
182
|
-
enabled = overrideManualMode.enabled;
|
|
183
|
-
}
|
|
12
|
+
const branch = await manager.readFullBranchEntries();
|
|
13
|
+
if (session.sessionManager !== manager || manager.getSessionId?.() !== sessionId || manager.getLeafId?.() !== leafId || session.model !== model) {
|
|
14
|
+
throw new Error("Statistics owner changed during read");
|
|
184
15
|
}
|
|
16
|
+
return formatDcpStatsToast(session, { branch });
|
|
185
17
|
}
|
|
186
18
|
catch {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
function dcpModelKeys(session) {
|
|
192
|
-
const model = session.model;
|
|
193
|
-
const provider = normalizeModelKey(model?.provider);
|
|
194
|
-
const id = normalizeModelKey(model?.id);
|
|
195
|
-
return [provider && id ? `${provider}/${id}` : undefined, id].filter((key) => key !== undefined);
|
|
196
|
-
}
|
|
197
|
-
function matchingModelOverrides(overrides, modelKeys) {
|
|
198
|
-
const candidates = modelKeys.map(normalizeModelKey).filter((key, index, all) => key !== undefined && all.indexOf(key) === index);
|
|
199
|
-
const exact = new Map();
|
|
200
|
-
const wildcard = [];
|
|
201
|
-
for (const [rawKey, value] of Object.entries(overrides)) {
|
|
202
|
-
const key = normalizeModelKey(rawKey);
|
|
203
|
-
if (!key || !isRecord(value))
|
|
204
|
-
continue;
|
|
205
|
-
if (key.includes("*") || key.includes("?"))
|
|
206
|
-
wildcard.push([key, value]);
|
|
207
|
-
else
|
|
208
|
-
exact.set(key, value);
|
|
209
|
-
}
|
|
210
|
-
const bare = candidates.filter((candidate) => !candidate.includes("/"));
|
|
211
|
-
const full = candidates.filter((candidate) => candidate.includes("/"));
|
|
212
|
-
const matches = [];
|
|
213
|
-
for (const candidate of bare)
|
|
214
|
-
for (const [pattern, value] of wildcard)
|
|
215
|
-
if (!pattern.includes("/") && globMatches(pattern, candidate))
|
|
216
|
-
matches.push(value);
|
|
217
|
-
for (const candidate of bare) {
|
|
218
|
-
const value = exact.get(candidate);
|
|
219
|
-
if (value)
|
|
220
|
-
matches.push(value);
|
|
221
|
-
}
|
|
222
|
-
for (const candidate of full)
|
|
223
|
-
for (const [pattern, value] of wildcard)
|
|
224
|
-
if (pattern.includes("/") && globMatches(pattern, candidate))
|
|
225
|
-
matches.push(value);
|
|
226
|
-
for (const candidate of full) {
|
|
227
|
-
const value = exact.get(candidate);
|
|
228
|
-
if (value)
|
|
229
|
-
matches.push(value);
|
|
230
|
-
}
|
|
231
|
-
return matches;
|
|
232
|
-
}
|
|
233
|
-
function normalizeModelKey(value) {
|
|
234
|
-
if (typeof value !== "string")
|
|
235
|
-
return undefined;
|
|
236
|
-
const trimmed = value.trim();
|
|
237
|
-
return trimmed || undefined;
|
|
238
|
-
}
|
|
239
|
-
function globMatches(pattern, candidate) {
|
|
240
|
-
let source = "^";
|
|
241
|
-
for (const char of pattern) {
|
|
242
|
-
if (char === "*")
|
|
243
|
-
source += ".*";
|
|
244
|
-
else if (char === "?")
|
|
245
|
-
source += ".";
|
|
246
|
-
else
|
|
247
|
-
source += char.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
|
|
248
|
-
}
|
|
249
|
-
return new RegExp(`${source}$`).test(candidate);
|
|
250
|
-
}
|
|
251
|
-
function applyActiveAnchorStats(stats, data) {
|
|
252
|
-
stats.activeByType = { "turn": 0, "iteration": 0, "context-soft": 0, "context-strong": 0 };
|
|
253
|
-
const anchors = Array.isArray(data.nudgeAnchors) ? data.nudgeAnchors : [];
|
|
254
|
-
for (const anchor of anchors) {
|
|
255
|
-
if (isRecord(anchor) && isNudgeType(anchor.type))
|
|
256
|
-
stats.activeByType[anchor.type] += 1;
|
|
257
|
-
}
|
|
258
|
-
const last = isRecord(data.lastNudge) ? data.lastNudge : undefined;
|
|
259
|
-
if (last && isNudgeType(last.type) && !stats.last) {
|
|
260
|
-
const contextPercent = numberValue(last.contextPercent);
|
|
261
|
-
const createdAt = numberValue(last.createdAt);
|
|
262
|
-
stats.last = {
|
|
263
|
-
type: last.type,
|
|
264
|
-
event: "emitted",
|
|
265
|
-
...(createdAt !== undefined ? { createdAt } : {}),
|
|
266
|
-
...(contextPercent !== undefined ? { contextPercent: contextPercent * 100 } : {}),
|
|
267
|
-
};
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
function resolveJournalDcpState(branch) {
|
|
271
|
-
const blocks = new Map();
|
|
272
|
-
const pruned = new Map();
|
|
273
|
-
let initialized = false;
|
|
274
|
-
let manualMode;
|
|
275
|
-
let nudgeAnchors = [];
|
|
276
|
-
let lastNudge;
|
|
277
|
-
for (const entry of branch) {
|
|
278
|
-
const operation = customEntryData(entry, "dcp-journal");
|
|
279
|
-
if (!operation || operation.schemaVersion !== 1)
|
|
280
|
-
continue;
|
|
281
|
-
if (operation.kind === "init") {
|
|
282
|
-
initialized = true;
|
|
283
|
-
continue;
|
|
284
|
-
}
|
|
285
|
-
if (!initialized || operation.kind !== "delta")
|
|
286
|
-
continue;
|
|
287
|
-
if (Array.isArray(operation.blocks)) {
|
|
288
|
-
for (const raw of operation.blocks) {
|
|
289
|
-
if (!isRecord(raw) || typeof raw.id !== "number")
|
|
290
|
-
continue;
|
|
291
|
-
blocks.set(raw.id, { ...raw });
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
if (Array.isArray(operation.blockStates)) {
|
|
295
|
-
for (const raw of operation.blockStates) {
|
|
296
|
-
if (!isRecord(raw) || typeof raw.id !== "number")
|
|
297
|
-
continue;
|
|
298
|
-
const block = blocks.get(raw.id);
|
|
299
|
-
if (!block)
|
|
300
|
-
continue;
|
|
301
|
-
if (typeof raw.active === "boolean")
|
|
302
|
-
block.active = raw.active;
|
|
303
|
-
if (typeof raw.deactivatedReason === "string")
|
|
304
|
-
block.deactivatedReason = raw.deactivatedReason;
|
|
305
|
-
}
|
|
19
|
+
let usage;
|
|
20
|
+
try {
|
|
21
|
+
usage = session.getContextUsage();
|
|
306
22
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
if (!isRecord(raw) || typeof raw.toolCallId !== "string")
|
|
310
|
-
continue;
|
|
311
|
-
pruned.set(raw.toolCallId, {
|
|
312
|
-
...(typeof raw.reason === "string" ? { reason: raw.reason } : {}),
|
|
313
|
-
tokenEstimate: Math.max(0, numberValue(raw.tokenEstimate) ?? 0),
|
|
314
|
-
});
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
if (typeof operation.manualMode === "boolean")
|
|
318
|
-
manualMode = operation.manualMode;
|
|
319
|
-
if (Array.isArray(operation.nudgeAnchors))
|
|
320
|
-
nudgeAnchors = operation.nudgeAnchors;
|
|
321
|
-
if (Object.prototype.hasOwnProperty.call(operation, "lastNudge"))
|
|
322
|
-
lastNudge = operation.lastNudge ?? undefined;
|
|
23
|
+
catch { /* Unknown. */ }
|
|
24
|
+
return formatDcpStatistics({ model: session.model, usage, historyStatus: "unavailable" });
|
|
323
25
|
}
|
|
324
|
-
if (!initialized)
|
|
325
|
-
return undefined;
|
|
326
|
-
return {
|
|
327
|
-
source: "journal",
|
|
328
|
-
data: {
|
|
329
|
-
compressionBlocks: [...blocks.values()],
|
|
330
|
-
prunedToolIds: [...pruned.keys()],
|
|
331
|
-
prunedTokensSaved: [...pruned.values()].reduce((sum, item) => sum + item.tokenEstimate, 0),
|
|
332
|
-
manualMode,
|
|
333
|
-
nudgeAnchors,
|
|
334
|
-
lastNudge,
|
|
335
|
-
},
|
|
336
|
-
};
|
|
337
26
|
}
|
|
338
|
-
|
|
339
|
-
|
|
27
|
+
/** TUI and ACP use the same passive report as /dcp stats. Opening this view
|
|
28
|
+
* never re-runs pruning, mutates history, or launches a model. */
|
|
29
|
+
export function formatDcpStatsToast(session, options = {}) {
|
|
30
|
+
let branch = [];
|
|
31
|
+
let historyStatus = "full";
|
|
340
32
|
try {
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
33
|
+
if (options.branch)
|
|
34
|
+
branch = options.branch;
|
|
35
|
+
else {
|
|
36
|
+
const manager = session.sessionManager;
|
|
37
|
+
branch = manager.readFullBranchEntriesSync ? manager.readFullBranchEntriesSync() : manager.getBranch();
|
|
38
|
+
}
|
|
39
|
+
if (!Array.isArray(branch) || branch[0]?.parentId != null) {
|
|
40
|
+
historyStatus = "unavailable";
|
|
41
|
+
branch = [];
|
|
42
|
+
}
|
|
344
43
|
}
|
|
345
44
|
catch {
|
|
346
|
-
//
|
|
45
|
+
// A broken full reader is not permission to substitute the UI's lazy tail.
|
|
46
|
+
historyStatus = "unavailable";
|
|
347
47
|
}
|
|
48
|
+
let usage;
|
|
348
49
|
try {
|
|
349
|
-
|
|
350
|
-
return Array.isArray(branch) ? branch : [];
|
|
351
|
-
}
|
|
352
|
-
catch {
|
|
353
|
-
return [];
|
|
50
|
+
usage = session.getContextUsage();
|
|
354
51
|
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
if (source === "journal")
|
|
358
|
-
return "session journal";
|
|
359
|
-
return "compress tool results";
|
|
360
|
-
}
|
|
361
|
-
function customEntryData(entry, customType) {
|
|
362
|
-
if (!isRecord(entry) || entry.type !== "custom" || entry.customType !== customType)
|
|
363
|
-
return undefined;
|
|
364
|
-
return isRecord(entry.data) ? entry.data : undefined;
|
|
365
|
-
}
|
|
366
|
-
function parseToolResultText(content) {
|
|
367
|
-
const parsed = parseArgsText(textContent(content));
|
|
368
|
-
return isRecord(parsed) ? parsed : undefined;
|
|
369
|
-
}
|
|
370
|
-
function textContent(content) {
|
|
371
|
-
if (typeof content === "string")
|
|
372
|
-
return content;
|
|
373
|
-
if (!Array.isArray(content))
|
|
374
|
-
return "";
|
|
375
|
-
return content
|
|
376
|
-
.map((part) => isRecord(part) && typeof part.text === "string" ? part.text : "")
|
|
377
|
-
.filter(Boolean)
|
|
378
|
-
.join("\n");
|
|
379
|
-
}
|
|
380
|
-
function formatContextUsage(stats) {
|
|
381
|
-
const percent = stats.contextPercent;
|
|
382
|
-
const tokens = stats.contextTokens;
|
|
383
|
-
const window = stats.contextWindow;
|
|
384
|
-
const percentText = percent != null ? formatPercent(percent) : "unknown";
|
|
385
|
-
if (tokens != null && window != null)
|
|
386
|
-
return `${percentText} (${formatCompactNumber(tokens)}/${formatCompactNumber(window)})`;
|
|
387
|
-
if (tokens != null)
|
|
388
|
-
return `${formatCompactNumber(tokens)} tokens`;
|
|
389
|
-
if (window != null)
|
|
390
|
-
return `${percentText} of ${formatCompactNumber(window)}`;
|
|
391
|
-
return percentText;
|
|
392
|
-
}
|
|
393
|
-
function isNudgeType(value) {
|
|
394
|
-
return typeof value === "string" && NUDGE_TYPES.includes(value);
|
|
395
|
-
}
|
|
396
|
-
function fmt(n) {
|
|
397
|
-
return Math.round(n).toLocaleString();
|
|
398
|
-
}
|
|
399
|
-
function pct(numerator, denominator) {
|
|
400
|
-
if (denominator <= 0)
|
|
401
|
-
return "n/a";
|
|
402
|
-
return `${((numerator / denominator) * 100).toFixed(1)}%`;
|
|
403
|
-
}
|
|
404
|
-
function formatDate(ts) {
|
|
405
|
-
if (typeof ts !== "number" || !Number.isFinite(ts) || ts <= 0)
|
|
406
|
-
return "unknown time";
|
|
407
|
-
return new Date(ts).toLocaleString();
|
|
408
|
-
}
|
|
409
|
-
function formatContextPercent(value) {
|
|
410
|
-
if (value === null)
|
|
411
|
-
return "unknown context";
|
|
412
|
-
if (typeof value !== "number" || !Number.isFinite(value))
|
|
413
|
-
return "unknown context";
|
|
414
|
-
return `${value.toFixed(1)}% context`;
|
|
415
|
-
}
|
|
416
|
-
function numberValue(value) {
|
|
417
|
-
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
418
|
-
}
|
|
419
|
-
function sumDefined(...values) {
|
|
420
|
-
const defined = values.filter((value) => value != null);
|
|
421
|
-
return defined.length > 0 ? defined.reduce((sum, value) => sum + value, 0) : undefined;
|
|
422
|
-
}
|
|
423
|
-
function formatCompactNumber(value) {
|
|
424
|
-
const abs = Math.abs(value);
|
|
425
|
-
if (abs >= 1_000_000)
|
|
426
|
-
return `${trimDecimal(value / 1_000_000)}M`;
|
|
427
|
-
if (abs >= 1_000)
|
|
428
|
-
return `${trimDecimal(value / 1_000)}K`;
|
|
429
|
-
return Math.round(value).toLocaleString();
|
|
430
|
-
}
|
|
431
|
-
function formatPercent(value) {
|
|
432
|
-
return `${trimDecimal(value)}%`;
|
|
433
|
-
}
|
|
434
|
-
function trimDecimal(value) {
|
|
435
|
-
return value.toFixed(1).replace(/\.0$/, "");
|
|
436
|
-
}
|
|
437
|
-
function isRecord(value) {
|
|
438
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
52
|
+
catch { /* Explicitly unknown. */ }
|
|
53
|
+
return formatDcpStatistics({ branch, historyStatus, model: session.model, usage });
|
|
439
54
|
}
|
|
@@ -2,7 +2,7 @@ import { stringDisplayWidth } from "../../terminal-width.js";
|
|
|
2
2
|
import { SUBAGENTS_WIDGET_MAX_ROWS } from "../constants.js";
|
|
3
3
|
import { ellipsizeDisplay, padOrTrimPlain, sanitizeText, wrapLine } from "./render-text.js";
|
|
4
4
|
import { thinkingLevelThemeColor } from "./status-line-renderer.js";
|
|
5
|
-
import { activeSubagentStates, formatElapsedSince, formatSubagentsPanelStats, subagentIcon, subagentModelThinkingLabel, subagentRunName, taskPreviewMap, } from "../subagents/subagents-model.js";
|
|
5
|
+
import { activeSubagentStates, formatElapsedSince, formatSubagentLastActivity, formatSubagentsPanelStats, subagentIcon, subagentModelThinkingLabel, subagentRunName, taskPreviewMap, } from "../subagents/subagents-model.js";
|
|
6
6
|
import { formatTodoPanelStats, formatTodoTaskLine, hasOpenTodoTasks, shiftSegmentsToSlice, todoTaskLineSegments, visibleTodoTaskRows, visibleTodoTasks, } from "../todo/todo-model.js";
|
|
7
7
|
export function renderTodoPanel(details, expanded, width, colors) {
|
|
8
8
|
if (!details)
|
|
@@ -110,14 +110,16 @@ export function renderSubagentsPanel(state, expanded, width, colors) {
|
|
|
110
110
|
const icon = subagentIcon(preview);
|
|
111
111
|
const runLabel = visibleRun.showRunLabel ? `${subagentRunName(visibleRun.runDir)} ` : "";
|
|
112
112
|
const prefix = `${runLabel}${icon} ${agent.id} ${model} `;
|
|
113
|
-
const
|
|
113
|
+
const activity = formatSubagentLastActivity(agent.lastActivity);
|
|
114
|
+
const elapsed = formatElapsedSince(agent.startedAt, now);
|
|
115
|
+
const suffix = activity ? ` ${activity} ${elapsed}` : ` ${elapsed}`;
|
|
114
116
|
const taskWidth = Math.max(8, rowWidth - stringDisplayWidth(prefix) - stringDisplayWidth(suffix));
|
|
115
117
|
const taskText = ellipsizeDisplay(task, taskWidth);
|
|
116
118
|
const text = `${prefix}${taskText}${suffix}`;
|
|
117
119
|
lines.push({
|
|
118
120
|
text: padOrTrimPlain(text, width),
|
|
119
121
|
colorOverride: colors.muted,
|
|
120
|
-
segments: subagentPanelLineSegments({ text, icon, agentId: agent.id, model, taskText, prefix, runLabel, status: agent.status }, colors),
|
|
122
|
+
segments: subagentPanelLineSegments({ text, icon, agentId: agent.id, model, taskText, prefix, runLabel, activity, elapsed, status: agent.status }, colors),
|
|
121
123
|
target,
|
|
122
124
|
});
|
|
123
125
|
}
|
|
@@ -136,13 +138,17 @@ function subagentPanelLineSegments(input, colors) {
|
|
|
136
138
|
const modelStart = input.text.indexOf(input.model, nameStart + input.agentId.length);
|
|
137
139
|
const taskStart = input.prefix.length;
|
|
138
140
|
const suffixStart = taskStart + input.taskText.length;
|
|
141
|
+
const elapsedStart = input.text.length - input.elapsed.length;
|
|
142
|
+
const activityStart = input.activity ? elapsedStart - input.activity.length - 1 : -1;
|
|
139
143
|
return [
|
|
140
144
|
...(runLabelStart >= 0 ? [{ start: runLabelStart, end: runLabelStart + input.runLabel.length, foreground: colors.warning }] : []),
|
|
141
145
|
{ start: iconStart, end: iconStart + input.icon.length, foreground: subagentStatusColor(input.status, colors), bold: true },
|
|
142
146
|
{ start: nameStart, end: nameStart + input.agentId.length, foreground: colors.accent, bold: true },
|
|
143
147
|
{ start: modelStart, end: modelStart + input.model.length, foreground: colors.info },
|
|
144
148
|
{ start: taskStart, end: suffixStart, foreground: colors.muted },
|
|
145
|
-
{ start: suffixStart, end: input.text.length, foreground: colors.muted },
|
|
149
|
+
{ start: suffixStart, end: input.activity ? activityStart : input.text.length, foreground: colors.muted },
|
|
150
|
+
...(input.activity ? [{ start: activityStart, end: activityStart + input.activity.length, foreground: colors.info }] : []),
|
|
151
|
+
...(input.activity ? [{ start: activityStart + input.activity.length, end: input.text.length, foreground: colors.muted }] : []),
|
|
146
152
|
].filter((segment) => segment.start >= 0 && segment.end > segment.start);
|
|
147
153
|
}
|
|
148
154
|
function subagentStatusColor(status, colors) {
|
|
@@ -2,7 +2,7 @@ import { type Theme } from "../../theme.js";
|
|
|
2
2
|
import { type ModelColorsConfig } from "../../config.js";
|
|
3
3
|
import type { PopupMenu } from "../../ui.js";
|
|
4
4
|
import type { ScreenStyler } from "../screen/screen-styler.js";
|
|
5
|
-
import type { Entry, ModelMenuValue, PixMenuItem, PixMenuOptions, QueueMessageMenuValue, RenderedLine, ResumeMenuValue, SlashCommand,
|
|
5
|
+
import type { Entry, ModelMenuValue, ModelThinkingMenuState, PixMenuItem, PixMenuOptions, QueueMessageMenuValue, RenderedLine, ResumeMenuValue, SlashCommand, UserMessageJumpMenuValue, UserMessageMenuValue } from "../types.js";
|
|
6
6
|
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
7
7
|
export type PopupMenuRendererHost = {
|
|
8
8
|
readonly theme: Theme;
|
|
@@ -24,12 +24,12 @@ export declare class PopupMenuRenderer {
|
|
|
24
24
|
overlayPlainText(line: RenderedLine, width: number): string;
|
|
25
25
|
renderUserMessageMenu(width: number, menu: PopupMenu<UserMessageMenuValue>): RenderedLine[];
|
|
26
26
|
renderSlashCommandMenu(width: number, menu: PopupMenu<SlashCommand>): RenderedLine[];
|
|
27
|
-
renderModelMenu(width: number, menu: PopupMenu<ModelMenuValue
|
|
28
|
-
renderThinkingMenu(width: number, menu: PopupMenu<ThinkingMenuValue>): RenderedLine[];
|
|
27
|
+
renderModelMenu(width: number, menu: PopupMenu<ModelMenuValue>, state: ModelThinkingMenuState): RenderedLine[];
|
|
29
28
|
renderResumeMenu(width: number, menu: PopupMenu<ResumeMenuValue>, state: {
|
|
30
29
|
directQuery: string;
|
|
31
30
|
allSessionsLoaded: boolean;
|
|
32
31
|
loadedSessionCount: number;
|
|
32
|
+
draft: boolean;
|
|
33
33
|
}): RenderedLine[];
|
|
34
34
|
renderUserMessageJumpMenu(width: number, menu: PopupMenu<UserMessageJumpMenuValue>, directQuery: string): RenderedLine[];
|
|
35
35
|
renderQueueMessageMenu(width: number, menu: PopupMenu<QueueMessageMenuValue>): RenderedLine[];
|
|
@@ -40,10 +40,8 @@ export declare class PopupMenuRenderer {
|
|
|
40
40
|
private labelDescriptionText;
|
|
41
41
|
private userMessageActionForeground;
|
|
42
42
|
private selectableItemVariant;
|
|
43
|
-
private thinkingMenuItemSegments;
|
|
44
43
|
private modelMenuItemSegments;
|
|
45
44
|
private modelMenuItemColor;
|
|
46
|
-
private availableThinkingLevels;
|
|
47
45
|
private queueMessageItemVariant;
|
|
48
46
|
private sdkItemVariant;
|
|
49
47
|
private sdkMenuItemSegments;
|