pi-ui-extend 0.1.8 → 0.1.11
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 +57 -2
- package/bin/pix.mjs +4 -4
- package/dist/app/app.d.ts +4 -0
- package/dist/app/app.js +112 -45
- package/dist/app/{cli.d.ts → cli/cli.d.ts} +1 -1
- package/dist/app/{cli.js → cli/cli.js} +1 -1
- package/dist/app/{install.d.ts → cli/install.d.ts} +2 -0
- package/dist/app/{install.js → cli/install.js} +18 -3
- package/dist/app/{command-controller.d.ts → commands/command-controller.d.ts} +1 -1
- package/dist/app/{command-controller.js → commands/command-controller.js} +4 -0
- package/dist/app/{command-host.d.ts → commands/command-host.d.ts} +7 -3
- package/dist/app/{command-model-actions.d.ts → commands/command-model-actions.d.ts} +6 -1
- package/dist/app/{command-model-actions.js → commands/command-model-actions.js} +106 -2
- package/dist/app/{command-navigation-actions.d.ts → commands/command-navigation-actions.d.ts} +7 -2
- package/dist/app/{command-navigation-actions.js → commands/command-navigation-actions.js} +42 -19
- package/dist/app/{command-registry.d.ts → commands/command-registry.d.ts} +5 -1
- package/dist/app/{command-registry.js → commands/command-registry.js} +32 -0
- package/dist/app/{command-runtime.js → commands/command-runtime.js} +1 -1
- package/dist/app/{command-session-actions.d.ts → commands/command-session-actions.d.ts} +1 -0
- package/dist/app/{command-session-actions.js → commands/command-session-actions.js} +18 -8
- package/dist/app/{shell-controller.d.ts → commands/shell-controller.d.ts} +2 -1
- package/dist/app/{shell-controller.js → commands/shell-controller.js} +2 -2
- package/dist/app/{slash-commands.d.ts → commands/slash-commands.d.ts} +2 -2
- package/dist/app/{slash-commands.js → commands/slash-commands.js} +1 -1
- package/dist/app/constants.d.ts +1 -1
- package/dist/app/constants.js +1 -1
- package/dist/app/{extension-actions-controller.d.ts → extensions/extension-actions-controller.d.ts} +1 -1
- package/dist/app/{extension-actions-controller.js → extensions/extension-actions-controller.js} +1 -1
- package/dist/app/{extension-ui-controller.d.ts → extensions/extension-ui-controller.d.ts} +3 -3
- package/dist/app/{extension-ui-controller.js → extensions/extension-ui-controller.js} +3 -3
- package/dist/app/icons.js +1 -1
- package/dist/app/input/autocomplete-controller.d.ts +52 -0
- package/dist/app/input/autocomplete-controller.js +352 -0
- package/dist/app/{input-action-controller.d.ts → input/input-action-controller.d.ts} +8 -7
- package/dist/app/{input-action-controller.js → input/input-action-controller.js} +24 -3
- package/dist/app/{input-controller.d.ts → input/input-controller.d.ts} +4 -3
- package/dist/app/{input-controller.js → input/input-controller.js} +3 -1
- package/dist/app/{input-paste-handler.d.ts → input/input-paste-handler.d.ts} +2 -1
- package/dist/app/{input-paste-handler.js → input/input-paste-handler.js} +25 -21
- package/dist/app/{native-modifiers.js → input/native-modifiers.js} +2 -2
- package/dist/app/{prompt-enhancer-controller.d.ts → input/prompt-enhancer-controller.d.ts} +5 -5
- package/dist/app/{prompt-enhancer-controller.js → input/prompt-enhancer-controller.js} +3 -3
- package/dist/app/{voice-controller.d.ts → input/voice-controller.d.ts} +3 -1
- package/dist/app/{voice-controller.js → input/voice-controller.js} +29 -17
- package/dist/app/{model-ref.d.ts → model/model-ref.d.ts} +1 -1
- package/dist/app/{model-ref.js → model/model-ref.js} +1 -1
- package/dist/app/{model-usage-controller.js → model/model-usage-controller.js} +1 -1
- package/dist/app/{model-usage-status.d.ts → model/model-usage-status.d.ts} +10 -1
- package/dist/app/{model-usage-status.js → model/model-usage-status.js} +125 -35
- package/dist/app/{menu-items-controller.d.ts → popup/menu-items-controller.d.ts} +4 -4
- package/dist/app/{menu-items-controller.js → popup/menu-items-controller.js} +5 -5
- package/dist/app/{popup-action-controller.d.ts → popup/popup-action-controller.d.ts} +4 -4
- package/dist/app/{popup-action-controller.js → popup/popup-action-controller.js} +3 -3
- package/dist/app/{popup-menu-controller.d.ts → popup/popup-menu-controller.d.ts} +4 -4
- package/dist/app/{popup-menu-controller.js → popup/popup-menu-controller.js} +7 -7
- package/dist/app/process.d.ts +17 -0
- package/dist/app/process.js +68 -0
- package/dist/app/{conversation-entry-renderer.d.ts → rendering/conversation-entry-renderer.d.ts} +3 -3
- package/dist/app/{conversation-entry-renderer.js → rendering/conversation-entry-renderer.js} +20 -9
- package/dist/app/{conversation-shell-renderer.d.ts → rendering/conversation-shell-renderer.d.ts} +1 -1
- package/dist/app/{conversation-shell-renderer.js → rendering/conversation-shell-renderer.js} +1 -1
- package/dist/app/{conversation-tool-renderer.d.ts → rendering/conversation-tool-renderer.d.ts} +3 -3
- package/dist/app/{conversation-tool-renderer.js → rendering/conversation-tool-renderer.js} +10 -9
- package/dist/app/{conversation-viewport.d.ts → rendering/conversation-viewport.d.ts} +3 -3
- package/dist/app/{dcp-stats.js → rendering/dcp-stats.js} +1 -1
- package/dist/app/{editor-layout-renderer.d.ts → rendering/editor-layout-renderer.d.ts} +4 -3
- package/dist/app/{editor-layout-renderer.js → rendering/editor-layout-renderer.js} +13 -3
- package/dist/app/{editor-panels.d.ts → rendering/editor-panels.d.ts} +2 -2
- package/dist/app/{editor-panels.js → rendering/editor-panels.js} +4 -4
- package/dist/app/{message-content.d.ts → rendering/message-content.d.ts} +1 -1
- package/dist/app/{message-content.js → rendering/message-content.js} +66 -8
- package/dist/app/{render-controller.d.ts → rendering/render-controller.d.ts} +6 -6
- package/dist/app/{render-controller.js → rendering/render-controller.js} +11 -6
- package/dist/app/{render-text.d.ts → rendering/render-text.d.ts} +5 -2
- package/dist/app/{render-text.js → rendering/render-text.js} +53 -5
- package/dist/app/{status-line-renderer.d.ts → rendering/status-line-renderer.d.ts} +8 -4
- package/dist/app/{status-line-renderer.js → rendering/status-line-renderer.js} +73 -29
- package/dist/app/{tab-line-renderer.d.ts → rendering/tab-line-renderer.d.ts} +3 -3
- package/dist/app/{tab-line-renderer.js → rendering/tab-line-renderer.js} +2 -2
- package/dist/app/{toast-controller.d.ts → rendering/toast-controller.d.ts} +1 -1
- package/dist/app/{toast-controller.js → rendering/toast-controller.js} +2 -2
- package/dist/app/{toast-renderer.d.ts → rendering/toast-renderer.d.ts} +3 -3
- package/dist/app/{toast-renderer.js → rendering/toast-renderer.js} +3 -3
- package/dist/app/{tool-block-renderer.d.ts → rendering/tool-block-renderer.d.ts} +5 -5
- package/dist/app/{tool-block-renderer.js → rendering/tool-block-renderer.js} +15 -33
- package/dist/app/runtime.d.ts +6 -1
- package/dist/app/runtime.js +35 -2
- package/dist/app/{blink-controller.js → screen/blink-controller.js} +1 -1
- package/dist/app/{clipboard.d.ts → screen/clipboard.d.ts} +2 -2
- package/dist/app/{clipboard.js → screen/clipboard.js} +13 -18
- package/dist/app/{image-click-targets.d.ts → screen/image-click-targets.d.ts} +2 -2
- package/dist/app/{image-opener.d.ts → screen/image-opener.d.ts} +1 -1
- package/dist/app/{mouse-controller.d.ts → screen/mouse-controller.d.ts} +17 -10
- package/dist/app/{mouse-controller.js → screen/mouse-controller.js} +72 -29
- package/dist/app/{screen-selection.d.ts → screen/screen-selection.d.ts} +1 -1
- package/dist/app/{screen-styler.d.ts → screen/screen-styler.d.ts} +6 -3
- package/dist/app/{screen-styler.js → screen/screen-styler.js} +7 -6
- package/dist/app/{scroll-controller.d.ts → screen/scroll-controller.d.ts} +3 -3
- package/dist/app/{scroll-controller.js → screen/scroll-controller.js} +1 -1
- package/dist/app/{status-controller.d.ts → screen/status-controller.d.ts} +5 -2
- package/dist/app/{status-controller.js → screen/status-controller.js} +24 -9
- package/dist/app/{queued-message-controller.d.ts → session/queued-message-controller.d.ts} +9 -3
- package/dist/app/{queued-message-controller.js → session/queued-message-controller.js} +34 -23
- package/dist/app/{request-history.js → session/request-history.js} +2 -2
- package/dist/app/session/resume-session-loader.d.ts +15 -0
- package/dist/app/session/resume-session-loader.js +204 -0
- package/dist/app/{session-event-controller.d.ts → session/session-event-controller.d.ts} +8 -4
- package/dist/app/{session-event-controller.js → session/session-event-controller.js} +75 -8
- package/dist/app/{session-history.d.ts → session/session-history.d.ts} +1 -1
- package/dist/app/{session-history.js → session/session-history.js} +7 -6
- package/dist/app/{session-lifecycle-controller.d.ts → session/session-lifecycle-controller.d.ts} +7 -2
- package/dist/app/{session-lifecycle-controller.js → session/session-lifecycle-controller.js} +13 -5
- package/dist/app/{session-search.d.ts → session/session-search.d.ts} +1 -1
- package/dist/app/{session-search.js → session/session-search.js} +3 -3
- package/dist/app/{tabs-controller.d.ts → session/tabs-controller.d.ts} +11 -2
- package/dist/app/{tabs-controller.js → session/tabs-controller.js} +105 -9
- package/dist/app/{subagents-files.d.ts → subagents/subagents-files.d.ts} +1 -1
- package/dist/app/{subagents-files.js → subagents/subagents-files.js} +1 -1
- package/dist/app/{subagents-model.d.ts → subagents/subagents-model.d.ts} +1 -1
- package/dist/app/{subagents-model.js → subagents/subagents-model.js} +4 -4
- package/dist/app/{subagents-widget-controller.d.ts → subagents/subagents-widget-controller.d.ts} +1 -1
- package/dist/app/{subagents-widget-controller.js → subagents/subagents-widget-controller.js} +2 -2
- package/dist/app/{nerd-font-controller.js → terminal/nerd-font-controller.js} +16 -17
- package/dist/app/{terminal-bell-sound-controller.js → terminal/terminal-bell-sound-controller.js} +1 -1
- package/dist/app/{terminal-controller.d.ts → terminal/terminal-controller.d.ts} +1 -0
- package/dist/app/{terminal-controller.js → terminal/terminal-controller.js} +3 -2
- package/dist/app/{todo-model.d.ts → todo/todo-model.d.ts} +1 -1
- package/dist/app/{todo-model.js → todo/todo-model.js} +3 -3
- package/dist/app/{todo-widget-controller.d.ts → todo/todo-widget-controller.d.ts} +1 -1
- package/dist/app/{todo-widget-controller.js → todo/todo-widget-controller.js} +2 -2
- package/dist/app/types.d.ts +16 -2
- package/dist/app/{workspace-actions-controller.d.ts → workspace/workspace-actions-controller.d.ts} +2 -2
- package/dist/app/{workspace-actions-controller.js → workspace/workspace-actions-controller.js} +6 -6
- package/dist/app/{workspace-undo.d.ts → workspace/workspace-undo.d.ts} +1 -1
- package/dist/app/{workspace-undo.js → workspace/workspace-undo.js} +22 -20
- package/dist/config.d.ts +27 -0
- package/dist/config.js +174 -1
- package/dist/default-pix-config.js +38 -353
- package/dist/input-editor.d.ts +7 -1
- package/dist/input-editor.js +47 -6
- package/dist/main.js +2 -2
- package/dist/markdown-format.d.ts +1 -0
- package/dist/markdown-format.js +26 -1
- package/external/pi-tools-suite/README.md +78 -0
- package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +4 -0
- package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +6 -1
- package/external/pi-tools-suite/src/dcp/compression-blocks.ts +1 -0
- package/external/pi-tools-suite/src/dcp/prompts.ts +5 -0
- package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +314 -193
- package/external/pi-tools-suite/src/index.ts +1 -0
- package/external/pi-tools-suite/src/lib/lsp.ts +2 -1
- package/external/pi-tools-suite/src/lsp/_shared/output.ts +8 -7
- package/external/pi-tools-suite/src/lsp/manager.ts +4 -4
- package/external/pi-tools-suite/src/opencode-import/commands.ts +86 -0
- package/external/pi-tools-suite/src/opencode-import/importer.ts +208 -0
- package/external/pi-tools-suite/src/opencode-import/index.ts +25 -0
- package/external/pi-tools-suite/src/repo-discovery/index.ts +49 -2
- package/external/pi-tools-suite/src/todo/tool/response-envelope.ts +9 -1
- package/external/pi-tools-suite/src/tool-descriptions.ts +1 -1
- package/package.json +1 -1
- /package/dist/app/{startup-checks.d.ts → cli/startup-checks.d.ts} +0 -0
- /package/dist/app/{startup-checks.js → cli/startup-checks.js} +0 -0
- /package/dist/app/{startup-info.d.ts → cli/startup-info.d.ts} +0 -0
- /package/dist/app/{startup-info.js → cli/startup-info.js} +0 -0
- /package/dist/app/{update.d.ts → cli/update.d.ts} +0 -0
- /package/dist/app/{update.js → cli/update.js} +0 -0
- /package/dist/app/{command-host.js → commands/command-host.js} +0 -0
- /package/dist/app/{command-runtime.d.ts → commands/command-runtime.d.ts} +0 -0
- /package/dist/app/{shell-command.d.ts → commands/shell-command.d.ts} +0 -0
- /package/dist/app/{shell-command.js → commands/shell-command.js} +0 -0
- /package/dist/app/{extension-event-bus.d.ts → extensions/extension-event-bus.d.ts} +0 -0
- /package/dist/app/{extension-event-bus.js → extensions/extension-event-bus.js} +0 -0
- /package/dist/app/{native-modifiers.d.ts → input/native-modifiers.d.ts} +0 -0
- /package/dist/app/{terminal-edit-shortcuts.d.ts → input/terminal-edit-shortcuts.d.ts} +0 -0
- /package/dist/app/{terminal-edit-shortcuts.js → input/terminal-edit-shortcuts.js} +0 -0
- /package/dist/app/{model-usage-controller.d.ts → model/model-usage-controller.d.ts} +0 -0
- /package/dist/app/{conversation-viewport.js → rendering/conversation-viewport.js} +0 -0
- /package/dist/app/{dcp-stats.d.ts → rendering/dcp-stats.d.ts} +0 -0
- /package/dist/app/{blink-controller.d.ts → screen/blink-controller.d.ts} +0 -0
- /package/dist/app/{file-link-opener.d.ts → screen/file-link-opener.d.ts} +0 -0
- /package/dist/app/{file-link-opener.js → screen/file-link-opener.js} +0 -0
- /package/dist/app/{file-links.d.ts → screen/file-links.d.ts} +0 -0
- /package/dist/app/{file-links.js → screen/file-links.js} +0 -0
- /package/dist/app/{image-click-targets.js → screen/image-click-targets.js} +0 -0
- /package/dist/app/{image-opener.js → screen/image-opener.js} +0 -0
- /package/dist/app/{screen-selection.js → screen/screen-selection.js} +0 -0
- /package/dist/app/{request-history.d.ts → session/request-history.d.ts} +0 -0
- /package/dist/app/{nerd-font-controller.d.ts → terminal/nerd-font-controller.d.ts} +0 -0
- /package/dist/app/{terminal-bell-sound-controller.d.ts → terminal/terminal-bell-sound-controller.d.ts} +0 -0
- /package/dist/app/{terminal-output-buffer.d.ts → terminal/terminal-output-buffer.d.ts} +0 -0
- /package/dist/app/{terminal-output-buffer.js → terminal/terminal-output-buffer.js} +0 -0
package/dist/app/{conversation-entry-renderer.js → rendering/conversation-entry-renderer.js}
RENAMED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { applyOutputFilters } from "
|
|
2
|
-
import { renderMarkdownTextLines } from "
|
|
3
|
-
import { attachImageClickTargets } from "
|
|
1
|
+
import { applyOutputFilters } from "../../config.js";
|
|
2
|
+
import { renderMarkdownTextLines } from "../../markdown-format.js";
|
|
3
|
+
import { attachImageClickTargets } from "../screen/image-click-targets.js";
|
|
4
|
+
import { APP_ICONS } from "../icons.js";
|
|
4
5
|
import { horizontalPaddingLayout, padHorizontalText, wrapText } from "./render-text.js";
|
|
5
6
|
import { renderConversationShellEntry } from "./conversation-shell-renderer.js";
|
|
6
7
|
import { renderConversationToolEntry, renderThinkingEntry } from "./conversation-tool-renderer.js";
|
|
@@ -14,10 +15,11 @@ export function renderConversationEntry(entry, width, options) {
|
|
|
14
15
|
...(syntaxHighlight === undefined ? {} : { syntaxHighlight }),
|
|
15
16
|
...(entryId === undefined ? {} : { target: { kind: "user-message", id: entryId } }),
|
|
16
17
|
});
|
|
17
|
-
const queuedLine = (text, entryId) => ({
|
|
18
|
+
const queuedLine = (text, entryId, segments) => ({
|
|
18
19
|
text: padHorizontalText(text, width),
|
|
19
20
|
variant: "muted",
|
|
20
21
|
backgroundOverride: options.colors.userMessageBackground,
|
|
22
|
+
...(segments && segments.length > 0 ? { segments: segments.map((segment) => ({ ...segment, start: segment.start + userContentLeft, end: segment.end + userContentLeft })) } : {}),
|
|
21
23
|
target: { kind: "queue-message", id: entryId },
|
|
22
24
|
});
|
|
23
25
|
const userMessageLines = (userEntry) => {
|
|
@@ -29,11 +31,20 @@ export function renderConversationEntry(entry, width, options) {
|
|
|
29
31
|
lines.push(userLine("", userEntry.id));
|
|
30
32
|
return attachImageClickTargets(lines, userEntry.id, userEntry.images, { foreground: options.colors.info, underline: true });
|
|
31
33
|
};
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
const queuedMessagePrefix = (queuedEntry) => {
|
|
35
|
+
const label = queuedEntry.queueSource === "sdk-steering"
|
|
36
|
+
? "steer"
|
|
37
|
+
: queuedEntry.queueSource === "sdk-follow-up"
|
|
38
|
+
? "follow"
|
|
39
|
+
: "queued";
|
|
40
|
+
return `${APP_ICONS.timerSand} ${label}:`;
|
|
41
|
+
};
|
|
42
|
+
const queuedMessageLines = (queuedEntry) => {
|
|
43
|
+
const icon = APP_ICONS.timerSand;
|
|
44
|
+
const prefix = queuedMessagePrefix(queuedEntry);
|
|
45
|
+
const contentLines = wrapText(`${prefix} ${queuedEntry.text}`, userContentWidth);
|
|
46
|
+
return contentLines.map((text, index) => queuedLine(text, queuedEntry.id, index === 0 ? [{ start: 0, end: icon.length, foreground: options.colors.info }] : undefined));
|
|
47
|
+
};
|
|
37
48
|
switch (entry.kind) {
|
|
38
49
|
case "system":
|
|
39
50
|
return wrapText(`system: ${entry.text}`, width).map((text) => ({ text, variant: "muted" }));
|
package/dist/app/{conversation-shell-renderer.d.ts → rendering/conversation-shell-renderer.d.ts}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Entry, RenderedLine } from "
|
|
1
|
+
import type { Entry, RenderedLine } from "../types.js";
|
|
2
2
|
import type { ConversationToolRenderOptions } from "./conversation-tool-renderer.js";
|
|
3
3
|
export declare function renderConversationShellEntry(entry: Extract<Entry, {
|
|
4
4
|
kind: "shell";
|
package/dist/app/{conversation-shell-renderer.js → rendering/conversation-shell-renderer.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveToolRule } from "
|
|
1
|
+
import { resolveToolRule } from "../../config.js";
|
|
2
2
|
import { renderToolBlock } from "./tool-block-renderer.js";
|
|
3
3
|
export function renderConversationShellEntry(entry, width, options) {
|
|
4
4
|
const body = shellEntryBody(entry);
|
package/dist/app/{conversation-tool-renderer.d.ts → rendering/conversation-tool-renderer.d.ts}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type PixConfig } from "
|
|
2
|
-
import type { Theme } from "
|
|
3
|
-
import type { Entry, RenderedLine } from "
|
|
1
|
+
import { type PixConfig } from "../../config.js";
|
|
2
|
+
import type { Theme } from "../../theme.js";
|
|
3
|
+
import type { Entry, RenderedLine } from "../types.js";
|
|
4
4
|
export type ConversationToolRenderOptions = {
|
|
5
5
|
cwd: string;
|
|
6
6
|
pixConfig: PixConfig;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { resolveColor, resolveToolRule } from "
|
|
2
|
-
import { formatMarkdownTables, markdownSyntaxHighlightsForText } from "
|
|
3
|
-
import { renderToolDisplay } from "
|
|
4
|
-
import { DEFAULT_THINKING_TOOL_RULE, SUBAGENT_STATUSES, THINKING_TOOL_NAME, TODO_TOOL_NAME } from "
|
|
5
|
-
import { attachImageClickTargets } from "
|
|
1
|
+
import { resolveColor, resolveToolRule } from "../../config.js";
|
|
2
|
+
import { formatMarkdownTables, markdownSyntaxHighlightsForText } from "../../markdown-format.js";
|
|
3
|
+
import { renderToolDisplay } from "../../tool-renderers/index.js";
|
|
4
|
+
import { DEFAULT_THINKING_TOOL_RULE, SUBAGENT_STATUSES, THINKING_TOOL_NAME, TODO_TOOL_NAME } from "../constants.js";
|
|
5
|
+
import { attachImageClickTargets } from "../screen/image-click-targets.js";
|
|
6
6
|
import { formatStructuredText } from "./message-content.js";
|
|
7
|
-
import { formatSubagentTimestamp, isSubagentRunRenderDetails, isSubagentsToolName, subagentRunName, subagentStatusIcon, taskPreviewMap, } from "
|
|
8
|
-
import { formatTodoTaskLine, isTodoDetails, visibleTodoTasks } from "
|
|
7
|
+
import { formatSubagentTimestamp, isSubagentRunRenderDetails, isSubagentsToolName, subagentRunName, subagentStatusIcon, taskPreviewMap, } from "../subagents/subagents-model.js";
|
|
8
|
+
import { formatTodoTaskLine, isTodoDetails, visibleTodoTasks } from "../todo/todo-model.js";
|
|
9
9
|
import { renderToolBlock } from "./tool-block-renderer.js";
|
|
10
10
|
export function renderConversationToolEntry(entry, width, options) {
|
|
11
11
|
const todoLines = renderTodoToolEntry(entry, width, options);
|
|
@@ -49,12 +49,13 @@ export function renderThinkingEntry(entry, width, options) {
|
|
|
49
49
|
const rule = resolveThinkingToolRule(options.pixConfig);
|
|
50
50
|
const markdownText = entry.text ? formatMarkdownTables(entry.text, Math.max(1, width - 2)) : "";
|
|
51
51
|
const expandedText = trimTrailingBlankLines(markdownText);
|
|
52
|
-
const compactExpandedText = options.superCompactTools ? removeBlankLines(expandedText) : expandedText;
|
|
53
52
|
const forceExpanded = Boolean(options.allThinkingExpanded);
|
|
53
|
+
const compactExpandedText = options.superCompactTools && forceExpanded ? removeBlankLines(expandedText) : expandedText;
|
|
54
|
+
const expanded = forceExpanded || (entry.expanded && expandedText.trim().length > 0);
|
|
54
55
|
return renderToolBlock({
|
|
55
56
|
id: entry.id,
|
|
56
57
|
toolName: THINKING_TOOL_NAME,
|
|
57
|
-
expanded
|
|
58
|
+
expanded,
|
|
58
59
|
status: entry.status,
|
|
59
60
|
isError: false,
|
|
60
61
|
output: markdownText,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type { PixConfig } from "
|
|
3
|
-
import type { Theme } from "
|
|
2
|
+
import type { PixConfig } from "../../config.js";
|
|
3
|
+
import type { Theme } from "../../theme.js";
|
|
4
4
|
import { type InlineUserMessageMenuContext } from "./conversation-entry-renderer.js";
|
|
5
|
-
import type { ConversationBlockCache, Entry, RenderedLine, SubmittedUserMessage } from "
|
|
5
|
+
import type { ConversationBlockCache, Entry, RenderedLine, SubmittedUserMessage } from "../types.js";
|
|
6
6
|
export type ConversationViewportHost = {
|
|
7
7
|
readonly entries: readonly Entry[];
|
|
8
8
|
readonly session: AgentSession | undefined;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { normalizeToolName, parseArgsText } from "
|
|
1
|
+
import { normalizeToolName, parseArgsText } from "../../tool-renderers/utils.js";
|
|
2
2
|
const NUDGE_TYPES = ["turn", "iteration", "context-soft", "context-strong"];
|
|
3
3
|
export function formatDcpStatsToast(session) {
|
|
4
4
|
const stats = collectDcpSessionStats(session);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { InputEditor } from "
|
|
2
|
-
import type { Theme } from "
|
|
3
|
-
import type { EditorLayout, ExtensionWidgetRegistration, ExtensionWidgetTheme, SubagentsWidgetState, TodoDetails, WidgetTuiHandle } from "
|
|
1
|
+
import type { InputEditor } from "../../input-editor.js";
|
|
2
|
+
import type { Theme } from "../../theme.js";
|
|
3
|
+
import type { EditorLayout, ExtensionWidgetRegistration, ExtensionWidgetTheme, SubagentsWidgetState, TodoDetails, WidgetTuiHandle } from "../types.js";
|
|
4
4
|
export type EditorLayoutRendererHost = {
|
|
5
5
|
readonly theme: Theme;
|
|
6
6
|
readonly inputEditor: InputEditor;
|
|
@@ -10,6 +10,7 @@ export type EditorLayoutRendererHost = {
|
|
|
10
10
|
readonly subagentsPanelExpanded: boolean;
|
|
11
11
|
readonly subagentsWidgetState: SubagentsWidgetState | undefined;
|
|
12
12
|
readonly voicePartialText: string | undefined;
|
|
13
|
+
readonly autocompleteSuggestion: string | undefined;
|
|
13
14
|
renderExtensionInputComponent(width: number): string[] | undefined;
|
|
14
15
|
extensionInputUsesEditor(): boolean;
|
|
15
16
|
widgetTuiHandle(): WidgetTuiHandle;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { ABOVE_EDITOR_WIDGET_KEY_GROUPS, BUILT_IN_SUBAGENTS_WIDGET_KEYS, INPUT_MAX_ROWS, LEGACY_TODO_WIDGET_KEYS, } from "
|
|
1
|
+
import { ABOVE_EDITOR_WIDGET_KEY_GROUPS, BUILT_IN_SUBAGENTS_WIDGET_KEYS, INPUT_MAX_ROWS, LEGACY_TODO_WIDGET_KEYS, } from "../constants.js";
|
|
2
2
|
import { renderSubagentsPanel, renderTodoPanel } from "./editor-panels.js";
|
|
3
3
|
import { ellipsizeDisplay, horizontalPaddingLayout, padHorizontalText, sanitizeText } from "./render-text.js";
|
|
4
|
-
import { APP_ICONS } from "
|
|
4
|
+
import { APP_ICONS } from "../icons.js";
|
|
5
5
|
const INPUT_FRAME_VERTICAL = "│";
|
|
6
6
|
export class EditorLayoutRenderer {
|
|
7
7
|
host;
|
|
@@ -145,7 +145,7 @@ export class EditorLayoutRenderer {
|
|
|
145
145
|
? this.limitExtensionInputLines(extensionLines, Math.max(0, maxRows - (usesEditor ? 1 : 0)))
|
|
146
146
|
: [];
|
|
147
147
|
const editorMaxRows = usesEditor ? Math.max(1, maxRows - customLines.length) : 1;
|
|
148
|
-
const rendered = this.host.inputEditor.render(contentWidth, editorMaxRows, "", "");
|
|
148
|
+
const rendered = this.host.inputEditor.render(contentWidth, editorMaxRows, "", "", usesEditor ? this.host.autocompleteSuggestion ?? "" : "");
|
|
149
149
|
const visibleLines = rendered.visualLines.slice(rendered.scrollOffset, rendered.scrollOffset + editorMaxRows);
|
|
150
150
|
const scrollBar = usesEditor
|
|
151
151
|
? inputScrollBarMetrics(rendered.visualLines.length, visibleLines.length, rendered.scrollOffset)
|
|
@@ -157,6 +157,12 @@ export class EditorLayoutRenderer {
|
|
|
157
157
|
end: span.end + left,
|
|
158
158
|
})))
|
|
159
159
|
: [];
|
|
160
|
+
const editorSuggestionSpans = usesEditor
|
|
161
|
+
? visibleLines.map((vl) => (vl.suggestionSpans ?? []).map((span) => ({
|
|
162
|
+
start: span.start + left,
|
|
163
|
+
end: span.end + left,
|
|
164
|
+
})))
|
|
165
|
+
: [];
|
|
160
166
|
const paddedCustomLines = customLines.map((line) => frameInputLine(padHorizontalText(line, width)));
|
|
161
167
|
return {
|
|
162
168
|
lines: [...paddedCustomLines, ...editorLines],
|
|
@@ -172,6 +178,10 @@ export class EditorLayoutRenderer {
|
|
|
172
178
|
...paddedCustomLines.map(() => []),
|
|
173
179
|
...editorTagSpans,
|
|
174
180
|
],
|
|
181
|
+
suggestionSpans: [
|
|
182
|
+
...paddedCustomLines.map(() => []),
|
|
183
|
+
...editorSuggestionSpans,
|
|
184
|
+
],
|
|
175
185
|
};
|
|
176
186
|
}
|
|
177
187
|
limitExtensionInputLines(lines, maxRows) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Theme } from "
|
|
2
|
-
import type { RenderedLine, SubagentsWidgetState, TodoDetails } from "
|
|
1
|
+
import type { Theme } from "../../theme.js";
|
|
2
|
+
import type { RenderedLine, SubagentsWidgetState, TodoDetails } from "../types.js";
|
|
3
3
|
export declare function renderTodoPanel(details: TodoDetails | undefined, expanded: boolean, width: number, colors: Theme["colors"]): RenderedLine[];
|
|
4
4
|
export declare function renderSubagentsPanel(state: SubagentsWidgetState | undefined, expanded: boolean, width: number, colors: Theme["colors"]): RenderedLine[];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { stringDisplayWidth } from "
|
|
2
|
-
import { SUBAGENTS_WIDGET_MAX_ROWS } from "
|
|
1
|
+
import { stringDisplayWidth } from "../../terminal-width.js";
|
|
2
|
+
import { SUBAGENTS_WIDGET_MAX_ROWS } from "../constants.js";
|
|
3
3
|
import { ellipsizeDisplay, padOrTrimPlain, wrapLine } from "./render-text.js";
|
|
4
|
-
import { activeSubagentStates, formatElapsedSince, formatSubagentsPanelStats, subagentModelThinkingLabel, subagentRunName, subagentStatusIcon, taskPreviewMap, } from "
|
|
5
|
-
import { formatTodoPanelStats, formatTodoTaskLine, hasOpenTodoTasks, shiftSegmentsToSlice, todoTaskLineSegments, visibleTodoTaskRows, visibleTodoTasks, } from "
|
|
4
|
+
import { activeSubagentStates, formatElapsedSince, formatSubagentsPanelStats, subagentModelThinkingLabel, subagentRunName, subagentStatusIcon, taskPreviewMap, } from "../subagents/subagents-model.js";
|
|
5
|
+
import { formatTodoPanelStats, formatTodoTaskLine, hasOpenTodoTasks, shiftSegmentsToSlice, todoTaskLineSegments, visibleTodoTaskRows, visibleTodoTasks, } from "../todo/todo-model.js";
|
|
6
6
|
export function renderTodoPanel(details, expanded, width, colors) {
|
|
7
7
|
if (!details)
|
|
8
8
|
return [];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ImageContent } from "
|
|
1
|
+
import type { ImageContent } from "../../input-editor.js";
|
|
2
2
|
export declare function stringifyUnknown(value: unknown): string;
|
|
3
3
|
export declare function formatStructuredText(value: unknown): string;
|
|
4
4
|
export declare function renderContent(content: readonly unknown[]): string;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import { isRecord } from "
|
|
1
|
+
import { isRecord } from "../guards.js";
|
|
2
|
+
const MAX_FORMAT_STRING_CHARS = 256 * 1024;
|
|
3
|
+
const MAX_RENDERED_CONTENT_CHARS = 512 * 1024;
|
|
4
|
+
const MAX_STRUCTURED_DEPTH = 8;
|
|
5
|
+
const MAX_STRUCTURED_ARRAY_ITEMS = 200;
|
|
6
|
+
const MAX_STRUCTURED_OBJECT_KEYS = 200;
|
|
7
|
+
const TRUNCATED_MARKER = "\n[… truncated …]";
|
|
2
8
|
export function stringifyUnknown(value) {
|
|
3
9
|
if (typeof value === "string")
|
|
4
10
|
return value;
|
|
@@ -13,7 +19,7 @@ export function stringifyUnknown(value) {
|
|
|
13
19
|
return name;
|
|
14
20
|
}
|
|
15
21
|
try {
|
|
16
|
-
return JSON.stringify(value, null, 2);
|
|
22
|
+
return JSON.stringify(normalizeStructuredValue(value), null, 2);
|
|
17
23
|
}
|
|
18
24
|
catch {
|
|
19
25
|
return String(value);
|
|
@@ -24,8 +30,10 @@ export function formatStructuredText(value) {
|
|
|
24
30
|
const trimmed = value.trim();
|
|
25
31
|
if (!trimmed)
|
|
26
32
|
return "(empty)";
|
|
33
|
+
if (trimmed.length > MAX_FORMAT_STRING_CHARS)
|
|
34
|
+
return truncateText(value, MAX_FORMAT_STRING_CHARS);
|
|
27
35
|
try {
|
|
28
|
-
return JSON.stringify(JSON.parse(trimmed), null, 2);
|
|
36
|
+
return JSON.stringify(normalizeStructuredValue(JSON.parse(trimmed)), null, 2);
|
|
29
37
|
}
|
|
30
38
|
catch {
|
|
31
39
|
return value;
|
|
@@ -36,25 +44,40 @@ export function formatStructuredText(value) {
|
|
|
36
44
|
export function renderContent(content) {
|
|
37
45
|
const parts = [];
|
|
38
46
|
let imageCount = 0;
|
|
47
|
+
let renderedChars = 0;
|
|
48
|
+
const pushPart = (part) => {
|
|
49
|
+
const remaining = MAX_RENDERED_CONTENT_CHARS - renderedChars;
|
|
50
|
+
if (remaining <= 0)
|
|
51
|
+
return false;
|
|
52
|
+
const next = part.length > remaining ? truncateText(part, remaining) : part;
|
|
53
|
+
parts.push(next);
|
|
54
|
+
renderedChars += next.length;
|
|
55
|
+
return part.length <= remaining;
|
|
56
|
+
};
|
|
39
57
|
for (const item of content) {
|
|
40
58
|
if (!isRecord(item)) {
|
|
41
|
-
|
|
59
|
+
if (!pushPart(stringifyUnknown(item)))
|
|
60
|
+
break;
|
|
42
61
|
continue;
|
|
43
62
|
}
|
|
44
63
|
if (isImageContent(item)) {
|
|
45
64
|
imageCount += 1;
|
|
46
|
-
|
|
65
|
+
if (!pushPart(imageContentLabel(item, imageCount)))
|
|
66
|
+
break;
|
|
47
67
|
continue;
|
|
48
68
|
}
|
|
49
69
|
if (typeof item.text === "string") {
|
|
50
|
-
|
|
70
|
+
if (!pushPart(item.text))
|
|
71
|
+
break;
|
|
51
72
|
continue;
|
|
52
73
|
}
|
|
53
74
|
if (typeof item.thinking === "string") {
|
|
54
|
-
|
|
75
|
+
if (!pushPart(item.thinking))
|
|
76
|
+
break;
|
|
55
77
|
continue;
|
|
56
78
|
}
|
|
57
|
-
|
|
79
|
+
if (!pushPart(stringifyUnknown(item)))
|
|
80
|
+
break;
|
|
58
81
|
}
|
|
59
82
|
return parts.join("\n");
|
|
60
83
|
}
|
|
@@ -113,3 +136,38 @@ export function submittedUserDisplayText(displayText, promptText, images) {
|
|
|
113
136
|
return userImageLabels(images.length);
|
|
114
137
|
return promptText.trimEnd();
|
|
115
138
|
}
|
|
139
|
+
function truncateText(text, maxChars) {
|
|
140
|
+
if (text.length <= maxChars)
|
|
141
|
+
return text;
|
|
142
|
+
return `${text.slice(0, Math.max(0, maxChars))}${TRUNCATED_MARKER}`;
|
|
143
|
+
}
|
|
144
|
+
function normalizeStructuredValue(value, depth = 0, seen = new WeakSet()) {
|
|
145
|
+
if (typeof value === "string")
|
|
146
|
+
return truncateText(value, MAX_FORMAT_STRING_CHARS);
|
|
147
|
+
if (!value || typeof value !== "object")
|
|
148
|
+
return value;
|
|
149
|
+
if (depth >= MAX_STRUCTURED_DEPTH)
|
|
150
|
+
return "[… truncated: depth limit …]";
|
|
151
|
+
if (seen.has(value))
|
|
152
|
+
return "[… circular …]";
|
|
153
|
+
seen.add(value);
|
|
154
|
+
if (Array.isArray(value)) {
|
|
155
|
+
const items = value.slice(0, MAX_STRUCTURED_ARRAY_ITEMS).map((item) => normalizeStructuredValue(item, depth + 1, seen));
|
|
156
|
+
if (value.length > MAX_STRUCTURED_ARRAY_ITEMS)
|
|
157
|
+
items.push(`[… ${value.length - MAX_STRUCTURED_ARRAY_ITEMS} more items …]`);
|
|
158
|
+
return items;
|
|
159
|
+
}
|
|
160
|
+
if (value instanceof Error)
|
|
161
|
+
return value.message || value.name;
|
|
162
|
+
const output = {};
|
|
163
|
+
let count = 0;
|
|
164
|
+
for (const [key, child] of Object.entries(value)) {
|
|
165
|
+
if (count >= MAX_STRUCTURED_OBJECT_KEYS) {
|
|
166
|
+
output["…"] = "truncated: object key limit";
|
|
167
|
+
break;
|
|
168
|
+
}
|
|
169
|
+
output[key] = normalizeStructuredValue(child, depth + 1, seen);
|
|
170
|
+
count += 1;
|
|
171
|
+
}
|
|
172
|
+
return output;
|
|
173
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import type { EditorLayoutRenderer } from "./editor-layout-renderer.js";
|
|
2
|
-
import type { AppMouseController } from "
|
|
3
|
-
import type { AppPopupMenuController } from "
|
|
4
|
-
import type { AppScrollController } from "
|
|
5
|
-
import type { ScreenStyler } from "
|
|
2
|
+
import type { AppMouseController } from "../screen/mouse-controller.js";
|
|
3
|
+
import type { AppPopupMenuController } from "../popup/popup-menu-controller.js";
|
|
4
|
+
import type { AppScrollController } from "../screen/scroll-controller.js";
|
|
5
|
+
import type { ScreenStyler } from "../screen/screen-styler.js";
|
|
6
6
|
import type { StatusLineRenderer } from "./status-line-renderer.js";
|
|
7
7
|
import type { TabLineRenderer } from "./tab-line-renderer.js";
|
|
8
8
|
import type { AppToastController } from "./toast-controller.js";
|
|
9
|
-
import { TerminalOutputBuffer } from "
|
|
10
|
-
import { type Theme } from "
|
|
9
|
+
import { TerminalOutputBuffer } from "../terminal/terminal-output-buffer.js";
|
|
10
|
+
import { type Theme } from "../../theme.js";
|
|
11
11
|
export type AppRenderControllerHost = {
|
|
12
12
|
isRunning(): boolean;
|
|
13
13
|
terminalColumns(): number;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { DISABLE_TERMINAL_WRAP, HIDE_CURSOR, SHOW_CURSOR } from "
|
|
2
|
-
import { APP_ICONS } from "
|
|
1
|
+
import { DISABLE_TERMINAL_WRAP, HIDE_CURSOR, SHOW_CURSOR } from "../constants.js";
|
|
2
|
+
import { APP_ICONS } from "../icons.js";
|
|
3
3
|
import { renderToastOverlays } from "./toast-renderer.js";
|
|
4
|
-
import { TerminalOutputBuffer } from "
|
|
5
|
-
import { ANSI_RESET, colorLine, colorize } from "
|
|
6
|
-
import { stringDisplayWidth } from "
|
|
4
|
+
import { TerminalOutputBuffer } from "../terminal/terminal-output-buffer.js";
|
|
5
|
+
import { ANSI_RESET, colorLine, colorize } from "../../theme.js";
|
|
6
|
+
import { stringDisplayWidth } from "../../terminal-width.js";
|
|
7
7
|
import { padOrTrimPlain } from "./render-text.js";
|
|
8
8
|
const INPUT_FRAME = {
|
|
9
9
|
topLeft: "╭",
|
|
@@ -68,8 +68,11 @@ export class AppRenderController {
|
|
|
68
68
|
this.deps.mouseController.statusThinkingTarget = undefined;
|
|
69
69
|
this.deps.mouseController.statusContextTarget = undefined;
|
|
70
70
|
this.deps.mouseController.statusModelUsageTarget = undefined;
|
|
71
|
+
this.deps.mouseController.statusDraftQueueTarget = undefined;
|
|
72
|
+
this.deps.mouseController.statusUserJumpTarget = undefined;
|
|
71
73
|
this.deps.mouseController.statusThinkingExpandTarget = undefined;
|
|
72
74
|
this.deps.mouseController.statusCompactToolsTarget = undefined;
|
|
75
|
+
this.deps.mouseController.statusTerminalBellSoundTarget = undefined;
|
|
73
76
|
this.deps.mouseController.statusSessionTarget = undefined;
|
|
74
77
|
this.deps.mouseController.statusPromptEnhancerTarget = undefined;
|
|
75
78
|
this.deps.mouseController.statusVoiceMicTarget = undefined;
|
|
@@ -165,10 +168,11 @@ export class AppRenderController {
|
|
|
165
168
|
for (let index = 0; index < renderedInput.lines.length; index += 1) {
|
|
166
169
|
const inputLine = renderedInput.lines[index] ?? "";
|
|
167
170
|
const tagSpans = renderedInput.tagSpans[index];
|
|
171
|
+
const suggestionSpans = renderedInput.suggestionSpans?.[index] ?? [];
|
|
168
172
|
const row = toScreenRow(inputStartRow + index);
|
|
169
173
|
this.deps.mouseController.renderedRowTexts.set(row, inputLine);
|
|
170
174
|
const tagColor = this.deps.theme.colors.accent;
|
|
171
|
-
const styledLine = this.deps.screenStyler.styleInputLine(row, inputLine, tagSpans, columns, tagColor, this.deps.theme.colors.inputBorder);
|
|
175
|
+
const styledLine = this.deps.screenStyler.styleInputLine(row, inputLine, tagSpans, suggestionSpans, columns, tagColor, this.deps.theme.colors.muted, this.deps.theme.colors.inputBorder);
|
|
172
176
|
appendFrameOutput("inputStatus", row, this.renderFrameRow(row, styledLine));
|
|
173
177
|
}
|
|
174
178
|
if (renderedInput.scrollBar && columns > 0) {
|
|
@@ -291,6 +295,7 @@ export class AppRenderController {
|
|
|
291
295
|
this.deps.mouseController.statusThinkingTarget = this.deps.statusLineRenderer.thinkingTarget(statusLayout.text, statusRow);
|
|
292
296
|
this.deps.mouseController.statusContextTarget = this.deps.statusLineRenderer.contextTarget(statusLayout.text, statusRow, statusLayout);
|
|
293
297
|
this.deps.mouseController.statusModelUsageTarget = this.deps.statusLineRenderer.modelUsageTarget(statusLayout.text, statusRow, statusLayout);
|
|
298
|
+
this.deps.mouseController.statusDraftQueueTarget = this.deps.statusLineRenderer.draftQueueTarget?.(statusLayout, statusRow);
|
|
294
299
|
this.deps.mouseController.statusUserJumpTarget = this.deps.statusLineRenderer.userJumpTarget?.(statusLayout, statusRow);
|
|
295
300
|
this.deps.mouseController.statusThinkingExpandTarget = this.deps.statusLineRenderer.thinkingExpandTarget?.(statusLayout, statusRow);
|
|
296
301
|
this.deps.mouseController.statusCompactToolsTarget = this.deps.statusLineRenderer.compactToolsTarget?.(statusLayout, statusRow);
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
-
import type { Theme } from "
|
|
2
|
-
import type { ToolStatusEntry } from "
|
|
1
|
+
import type { Theme } from "../../theme.js";
|
|
2
|
+
import type { ToolStatusEntry } from "../types.js";
|
|
3
3
|
export declare function sanitizeText(text: string): string;
|
|
4
|
+
export declare function alertIconPrefixLength(text: string): number | undefined;
|
|
4
5
|
export declare function normalizePastedTextForDuplicateKey(text: string): string;
|
|
5
6
|
export declare function shortHash(text: string): string;
|
|
6
7
|
export declare function hasLspDiagnosticsAfterMutation(output: string): boolean;
|
|
7
8
|
export declare function hasToolLspDiagnosticsAfterMutation(entry: ToolStatusEntry): boolean;
|
|
9
|
+
export declare function lspDiagnosticSeverityForLine(line: string): "error" | "warning" | "hint" | undefined;
|
|
10
|
+
export declare function toolLspDiagnosticsAfterMutationSeverity(entry: ToolStatusEntry): "error" | "warning" | undefined;
|
|
8
11
|
export declare function toolStatusIcon(entry: ToolStatusEntry): string;
|
|
9
12
|
export declare function toolStatusIconColor(entry: ToolStatusEntry, colors: Theme["colors"]): string;
|
|
10
13
|
export declare function wrapLine(text: string, width: number): string[];
|
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import { expandTabs, padOrTrimDisplay, sliceByDisplayWidth, stringDisplayWidth, wrapDisplayLine } from "
|
|
3
|
-
import { APP_ICONS } from "
|
|
2
|
+
import { expandTabs, padOrTrimDisplay, sliceByDisplayWidth, stringDisplayWidth, wrapDisplayLine } from "../../terminal-width.js";
|
|
3
|
+
import { APP_ICONS } from "../icons.js";
|
|
4
|
+
const LSP_DIAGNOSTIC_ICON = "\u{f0026}";
|
|
4
5
|
export function sanitizeText(text) {
|
|
5
|
-
return expandTabs(text.replace(/\x1b/g, "␛").replace(/\r/g, ""));
|
|
6
|
+
return expandTabs(text.replace(/⚠️?|\u{f0026}/gu, APP_ICONS.alert).replace(/\x1b/g, "␛").replace(/\r/g, ""));
|
|
7
|
+
}
|
|
8
|
+
export function alertIconPrefixLength(text) {
|
|
9
|
+
if (text.startsWith(APP_ICONS.alert))
|
|
10
|
+
return APP_ICONS.alert.length;
|
|
11
|
+
if (text.startsWith(LSP_DIAGNOSTIC_ICON))
|
|
12
|
+
return LSP_DIAGNOSTIC_ICON.length;
|
|
13
|
+
return /^⚠️?/u.exec(text)?.[0].length;
|
|
6
14
|
}
|
|
7
15
|
export function normalizePastedTextForDuplicateKey(text) {
|
|
8
16
|
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
@@ -17,12 +25,49 @@ const LSP_DIAGNOSTIC_MUTATION_TOOLS = new Set(["apply_patch", "ast_apply"]);
|
|
|
17
25
|
export function hasToolLspDiagnosticsAfterMutation(entry) {
|
|
18
26
|
return LSP_DIAGNOSTIC_MUTATION_TOOLS.has(entry.toolName.toLowerCase()) && hasLspDiagnosticsAfterMutation(entry.output);
|
|
19
27
|
}
|
|
28
|
+
export function lspDiagnosticSeverityForLine(line) {
|
|
29
|
+
const counts = lspDiagnosticCounts(line);
|
|
30
|
+
const countSeverity = lspDiagnosticCountSeverity(counts);
|
|
31
|
+
if (countSeverity)
|
|
32
|
+
return countSeverity;
|
|
33
|
+
if (counts.length > 0)
|
|
34
|
+
return undefined;
|
|
35
|
+
const severityMatch = /(?:^|[^\p{L}\p{N}_])(?:diagnosticseverity\.)?(errors?|warnings?|warn|hints?)(?=$|[^\p{L}\p{N}_])/iu.exec(line);
|
|
36
|
+
const severity = severityMatch?.[1]?.toLowerCase();
|
|
37
|
+
if (!severity)
|
|
38
|
+
return undefined;
|
|
39
|
+
if (severity.startsWith("error"))
|
|
40
|
+
return "error";
|
|
41
|
+
if (severity.startsWith("warn"))
|
|
42
|
+
return "warning";
|
|
43
|
+
return "hint";
|
|
44
|
+
}
|
|
45
|
+
function lspDiagnosticCounts(line) {
|
|
46
|
+
return [...line.matchAll(/\b(\d+)\s+(errors?|warnings?|hints?)\b/giu)];
|
|
47
|
+
}
|
|
48
|
+
function lspDiagnosticCountSeverity(counts) {
|
|
49
|
+
for (const severity of ["error", "warning", "hint"]) {
|
|
50
|
+
if (counts.some((match) => Number(match[1]) > 0 && match[2]?.toLowerCase().startsWith(severity)))
|
|
51
|
+
return severity;
|
|
52
|
+
}
|
|
53
|
+
return undefined;
|
|
54
|
+
}
|
|
55
|
+
export function toolLspDiagnosticsAfterMutationSeverity(entry) {
|
|
56
|
+
if (!hasToolLspDiagnosticsAfterMutation(entry))
|
|
57
|
+
return undefined;
|
|
58
|
+
if (/\blsp\s+errors?\s+after\s+mutation\b/i.test(entry.output))
|
|
59
|
+
return "error";
|
|
60
|
+
const diagnosticLines = entry.output.split("\n").map((line) => line.trim());
|
|
61
|
+
if (diagnosticLines.some((line) => lspDiagnosticSeverityForLine(line) === "error"))
|
|
62
|
+
return "error";
|
|
63
|
+
return "warning";
|
|
64
|
+
}
|
|
20
65
|
export function toolStatusIcon(entry) {
|
|
21
66
|
if (entry.status === "running")
|
|
22
67
|
return APP_ICONS.timerSand;
|
|
23
68
|
if (entry.isError)
|
|
24
69
|
return APP_ICONS.closeCircle;
|
|
25
|
-
if (
|
|
70
|
+
if (toolLspDiagnosticsAfterMutationSeverity(entry))
|
|
26
71
|
return APP_ICONS.alert;
|
|
27
72
|
return APP_ICONS.checkCircle;
|
|
28
73
|
}
|
|
@@ -31,7 +76,10 @@ export function toolStatusIconColor(entry, colors) {
|
|
|
31
76
|
return colors.muted;
|
|
32
77
|
if (entry.isError)
|
|
33
78
|
return colors.error;
|
|
34
|
-
|
|
79
|
+
const lspSeverity = toolLspDiagnosticsAfterMutationSeverity(entry);
|
|
80
|
+
if (lspSeverity === "error")
|
|
81
|
+
return colors.error;
|
|
82
|
+
if (lspSeverity === "warning")
|
|
35
83
|
return colors.warning;
|
|
36
84
|
return colors.success;
|
|
37
85
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { AgentSession } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import type { Theme } from "
|
|
3
|
-
import type { SessionActivity, StatusCompactToolsTarget, StatusContextTarget, StatusLineLayout, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "
|
|
4
|
-
import type { ScreenStyler } from "
|
|
5
|
-
import { type ModelColorsConfig } from "
|
|
2
|
+
import type { Theme } from "../../theme.js";
|
|
3
|
+
import type { SessionActivity, StatusCompactToolsTarget, StatusContextTarget, StatusDraftQueueTarget, StatusLineLayout, StatusModelTarget, StatusModelUsageTarget, StatusPromptEnhancerTarget, StatusSessionTarget, StatusTerminalBellSoundTarget, StatusThinkingExpandTarget, StatusThinkingTarget, StatusUserJumpTarget, StatusVoiceLanguageTarget, StatusVoiceMicTarget } from "../types.js";
|
|
4
|
+
import type { ScreenStyler } from "../screen/screen-styler.js";
|
|
5
|
+
import { type ModelColorsConfig } from "../../config.js";
|
|
6
6
|
export type StatusLineRendererHost = {
|
|
7
7
|
readonly theme: Theme;
|
|
8
8
|
readonly screenStyler: ScreenStyler;
|
|
@@ -26,6 +26,7 @@ export type StatusLineRendererHost = {
|
|
|
26
26
|
terminalBellSoundStatusWidgetEnabled(): boolean;
|
|
27
27
|
voiceStatusWidgetText(): string;
|
|
28
28
|
voiceStatusWidgetActive(): boolean;
|
|
29
|
+
queueableInputActive?(): boolean;
|
|
29
30
|
userMessageJumpMenuActive?(): boolean;
|
|
30
31
|
allThinkingExpandedActive?(): boolean;
|
|
31
32
|
superCompactToolsActive?(): boolean;
|
|
@@ -43,6 +44,7 @@ export declare class StatusLineRenderer {
|
|
|
43
44
|
voiceMicTarget(layout: StatusLineLayout, row: number): StatusVoiceMicTarget | undefined;
|
|
44
45
|
voiceLanguageTarget(layout: StatusLineLayout, row: number): StatusVoiceLanguageTarget | undefined;
|
|
45
46
|
userJumpTarget(layout: StatusLineLayout, row: number): StatusUserJumpTarget | undefined;
|
|
47
|
+
draftQueueTarget(layout: StatusLineLayout, row: number): StatusDraftQueueTarget | undefined;
|
|
46
48
|
thinkingExpandTarget(layout: StatusLineLayout, row: number): StatusThinkingExpandTarget | undefined;
|
|
47
49
|
compactToolsTarget(layout: StatusLineLayout, row: number): StatusCompactToolsTarget | undefined;
|
|
48
50
|
terminalBellSoundTarget(layout: StatusLineLayout, row: number): StatusTerminalBellSoundTarget | undefined;
|
|
@@ -50,6 +52,8 @@ export declare class StatusLineRenderer {
|
|
|
50
52
|
private segments;
|
|
51
53
|
private pushPromptEnhancerWidgetSegment;
|
|
52
54
|
private pushUserJumpWidgetSegment;
|
|
55
|
+
private pushDraftQueueWidgetSegment;
|
|
56
|
+
private draftQueueWidgetText;
|
|
53
57
|
private pushThinkingExpandWidgetSegment;
|
|
54
58
|
private pushCompactToolsWidgetSegment;
|
|
55
59
|
private pushTerminalBellSoundWidgetSegment;
|