@linxiraos/pi-tui 1.1.17 → 1.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -3
- package/dist/types/i18n.d.ts +32 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/overlays/agent-hub.d.ts +6 -1
- package/dist/types/overlays/agent-transcript-viewer.d.ts +1 -1
- package/dist/types/overlays/btw-panel.d.ts +1 -0
- package/dist/types/overlays/composer-shape-registry.d.ts +11 -35
- package/dist/types/overlays/history-search.d.ts +2 -0
- package/dist/types/overlays/login-dialog.d.ts +1 -0
- package/dist/types/overlays/logout-account-selector.d.ts +1 -0
- package/dist/types/overlays/move-overlay.d.ts +0 -7
- package/dist/types/overlays/oauth-selector.d.ts +1 -0
- package/dist/types/overlays/queue-mode-selector.d.ts +1 -0
- package/dist/types/overlays/reset-usage-selector.d.ts +1 -0
- package/dist/types/overlays/settings-defs.d.ts +0 -1
- package/dist/types/overlays/show-images-selector.d.ts +1 -0
- package/dist/types/overlays/theme-selector.d.ts +1 -0
- package/dist/types/overlays/thinking-selector.d.ts +1 -0
- package/dist/types/overlays/tree-selector.d.ts +2 -0
- package/dist/types/setup/scenes/sign-in.d.ts +1 -1
- package/dist/types/setup/scenes/web-search.d.ts +1 -1
- package/package.json +10 -10
- package/src/apps/git/diff-pane.ts +28 -15
- package/src/apps/git/git-tui.ts +129 -34
- package/src/apps/git/sidebar.ts +34 -20
- package/src/apps/ps-top.ts +73 -23
- package/src/chat/compaction-summary-message.ts +32 -11
- package/src/chat/execution-shared.ts +11 -5
- package/src/chat/late-diagnostics-message.ts +2 -1
- package/src/chat/messages.ts +11 -3
- package/src/chat/skill-message.ts +18 -3
- package/src/chat/todo-reminder.ts +8 -2
- package/src/chat/tool-execution.ts +9 -1
- package/src/chat/user-message.ts +5 -2
- package/src/components/form.ts +3 -2
- package/src/components/select-list.ts +8 -3
- package/src/components/settings-list.ts +21 -6
- package/src/i18n.ts +46 -0
- package/src/index.ts +2 -0
- package/src/overlays/advisor-config.ts +124 -62
- package/src/overlays/agent-activity.ts +4 -3
- package/src/overlays/agent-hub.ts +189 -61
- package/src/overlays/agent-transcript-viewer.ts +32 -14
- package/src/overlays/agents-hub.ts +236 -76
- package/src/overlays/ask-dialog.ts +47 -25
- package/src/overlays/btw-history-panel.ts +101 -33
- package/src/overlays/btw-panel.ts +30 -12
- package/src/overlays/cleanse-panel.ts +19 -6
- package/src/overlays/codex-reset-fireworks.ts +12 -4
- package/src/overlays/composer-shape-preview.ts +6 -2
- package/src/overlays/composer-shape-registry.ts +58 -18
- package/src/overlays/copy-selector.ts +61 -27
- package/src/overlays/error-banner.ts +8 -1
- package/src/overlays/extensions/extension-dashboard.ts +7 -2
- package/src/overlays/extensions/extension-list.ts +20 -18
- package/src/overlays/extensions/inspector-model.ts +23 -16
- package/src/overlays/extensions/inspector-panel.ts +76 -35
- package/src/overlays/extensions/mcp-runtime.ts +29 -10
- package/src/overlays/extensions/state-manager.ts +12 -11
- package/src/overlays/history-search.ts +28 -7
- package/src/overlays/login-dialog.ts +46 -11
- package/src/overlays/logout-account-selector.ts +18 -4
- package/src/overlays/mcp-add-wizard.ts +190 -109
- package/src/overlays/model-browser.ts +5 -1
- package/src/overlays/model-hub.ts +188 -68
- package/src/overlays/model-picker.ts +39 -14
- package/src/overlays/move-overlay.ts +14 -5
- package/src/overlays/oauth-selector.ts +46 -12
- package/src/overlays/omfg-panel.ts +39 -13
- package/src/overlays/pause-screen.ts +19 -9
- package/src/overlays/plan-review-overlay.ts +49 -23
- package/src/overlays/plan-save-overlay.ts +8 -3
- package/src/overlays/plugin-selector.ts +9 -6
- package/src/overlays/plugin-settings.ts +127 -36
- package/src/overlays/queue-mode-selector.ts +13 -3
- package/src/overlays/reset-usage-selector.ts +28 -7
- package/src/overlays/rewind-selector.ts +18 -4
- package/src/overlays/session-info-overlay.ts +6 -2
- package/src/overlays/session-selector.ts +51 -26
- package/src/overlays/settings-defs.ts +61 -10
- package/src/overlays/settings-selector.ts +55 -25
- package/src/overlays/show-images-selector.ts +17 -3
- package/src/overlays/theme-selector.ts +8 -2
- package/src/overlays/thinking-selector.ts +7 -1
- package/src/overlays/tiny-title-download-progress.ts +10 -8
- package/src/overlays/tree-selector.ts +86 -33
- package/src/overlays/usage-dashboard.ts +38 -15
- package/src/prompt/prompt-action-autocomplete.ts +28 -9
- package/src/prompt/tools-markdown.ts +15 -4
- package/src/prompt/welcome.ts +5 -1
- package/src/setup/lazy.ts +2 -1
- package/src/setup/scenes/composer.ts +16 -5
- package/src/setup/scenes/glyph.ts +19 -4
- package/src/setup/scenes/model.ts +15 -6
- package/src/setup/scenes/outro.ts +5 -2
- package/src/setup/scenes/providers.ts +18 -5
- package/src/setup/scenes/sign-in.ts +70 -15
- package/src/setup/scenes/splash.ts +8 -5
- package/src/setup/scenes/theme.ts +87 -22
- package/src/setup/scenes/web-search.ts +25 -8
- package/src/setup/wizard-overlay.ts +13 -3
- package/src/status-line/context-usage.ts +32 -11
- package/src/status-line/footer.ts +2 -1
- package/src/status-line/loop.ts +2 -1
- package/src/tools/ask.ts +32 -12
- package/src/tools/ast-grep.ts +28 -13
- package/src/tools/glob.ts +62 -13
- package/src/tools/grep.ts +29 -10
- package/src/tools/hub.ts +47 -14
- package/src/tools/resolve.ts +19 -6
- package/src/tools/task.ts +9 -8
- package/src/tools/todo.ts +17 -4
- package/src/tools/web-search.ts +15 -5
package/CHANGELOG.md
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
-
## [1.1.
|
|
5
|
+
## [1.1.19] - 2026-09-22
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- 主题、覆盖层、chat、工具渲染器与 apps 组件自 coding-agent 迁入本包(模块迁移)。
|
|
7
|
+
- 版本线推进;本版无独立用户可见变化。
|
|
9
8
|
|
|
10
9
|
## [9.8.0] - 2026-02-01
|
|
11
10
|
|
|
@@ -381,6 +380,15 @@ Initial release under @oh-my-pi scope. See previous releases at [badlogic/pi-mon
|
|
|
381
380
|
|
|
382
381
|
- Added `getText()` method to Text component for retrieving current text content
|
|
383
382
|
|
|
383
|
+
## [1.1.18] - 2026-09-22
|
|
384
|
+
|
|
385
|
+
- 新增宿主可注入文本层:`setTuiTextSource` / `tuiText` / `tuiTextFmt`——内联英文为永久 fallback,宿主(coding-agent)注入活翻译代理,面板文本随 `/language` 即时切换;pi-tui 独立使用零依赖。
|
|
386
|
+
|
|
387
|
+
## [1.1.16] - 2026-09-19
|
|
388
|
+
|
|
389
|
+
- 上游 v18.2.5 同步:每击键/每帧渲染浪费削减、billing 摘要重构、stream 状态分段、paint-listener 通知管线。
|
|
390
|
+
- 主题、覆盖层、chat、工具渲染器与 apps 组件自 coding-agent 迁入本包(模块迁移)。
|
|
391
|
+
|
|
384
392
|
## [0.50.0] - 2026-01-26
|
|
385
393
|
|
|
386
394
|
### Added
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Host-injectable UI text source for @linxiraos/pi-tui.
|
|
3
|
+
*
|
|
4
|
+
* pi-tui must not depend on the coding-agent i18n bundle (dependency
|
|
5
|
+
* direction: coding-agent -> pi-tui). Instead, every user-visible string in
|
|
6
|
+
* a tui component goes through `tuiText(key, englishFallback)`: the inline
|
|
7
|
+
* English is the permanent fallback, and the host (coding-agent) registers
|
|
8
|
+
* a text source that resolves keys against its localised catalogue. The
|
|
9
|
+
* source is consulted on every call, so a runtime language switch takes
|
|
10
|
+
* effect immediately without rebuilding components.
|
|
11
|
+
*
|
|
12
|
+
* Key naming: reuse the coding-agent Messages key verbatim when one exists
|
|
13
|
+
* (e.g. `ssFooterSuffix`); otherwise add a new flat camelCase key namespaced
|
|
14
|
+
* by the panel (e.g. `mcpAddStepTransport`) to Messages/en/zh.
|
|
15
|
+
*/
|
|
16
|
+
export type TuiTextSource = (key: string) => string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Register the host text source. Pass `undefined` to reset to English
|
|
19
|
+
* fallbacks (the default; also the headless behavior — no rendering surface
|
|
20
|
+
* exists without the interactive CLI host).
|
|
21
|
+
*/
|
|
22
|
+
export declare function setTuiTextSource(source: TuiTextSource | undefined): void;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve a UI string: host catalogue first, inline English fallback second.
|
|
25
|
+
* Called per render, so language switches apply live.
|
|
26
|
+
*/
|
|
27
|
+
export declare function tuiText(key: string, fallback: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Resolve a formatted UI string (`*Fmt` keys). `%s` / `%d` placeholders in
|
|
30
|
+
* the resolved text are substituted positionally with `args`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function tuiTextFmt(key: string, fallback: string, ...args: (string | number)[]): string;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ import { type AgentActivitySource } from "./agent-activity.js";
|
|
|
20
20
|
import type { KeyId } from "../app-keybindings.js";
|
|
21
21
|
import type { MessageRenderer } from "../chat/extension-types.js";
|
|
22
22
|
import type { AgentLifecycleLike, IrcBusLike } from "./agent-hub-types.js";
|
|
23
|
-
import { type AgentRecordLike, type AgentHubRegistry } from "./agent-hub-types.js";
|
|
23
|
+
import { type AgentRecordLike, type AgentHubRegistry, type AgentStatus } from "./agent-hub-types.js";
|
|
24
24
|
import type { SessionObserverRegistry } from "./session-observer-registry.js";
|
|
25
25
|
import { type AgentTranscriptSource } from "./agent-transcript-viewer.js";
|
|
26
26
|
import type { AgentRoleDisplay } from "./agent-hub-renderer.js";
|
|
@@ -40,6 +40,11 @@ export interface AgentHubRemote {
|
|
|
40
40
|
/** Mirrors readFileIncremental: text from fromByte (complete JSONL lines), newSize = next fromByte base; null = temporarily unavailable. */
|
|
41
41
|
readTranscript(id: string, fromByte: number): Promise<AgentHubRemoteTranscript | null>;
|
|
42
42
|
}
|
|
43
|
+
/** Localizable status words; keys resolve per render so /language switches live. */
|
|
44
|
+
export declare const AGENT_STATUS_TEXT: Record<AgentStatus, {
|
|
45
|
+
key: string;
|
|
46
|
+
fallback: string;
|
|
47
|
+
}>;
|
|
43
48
|
export interface AgentHubDeps<TRecord extends AgentRecordLike = AgentRecordLike> {
|
|
44
49
|
/** Progress/status snapshot source (task lifecycle + progress channels). */
|
|
45
50
|
observers: SessionObserverRegistry;
|
|
@@ -22,7 +22,7 @@ import type { AgentLifecycleLike } from "./agent-hub-types.js";
|
|
|
22
22
|
import type { AgentHubRegistry } from "./agent-hub-types.js";
|
|
23
23
|
import type { SessionMessageEntryLike } from "../chat/transcript-entry.js";
|
|
24
24
|
import type { SessionObserverRegistry } from "./session-observer-registry.js";
|
|
25
|
-
import type
|
|
25
|
+
import { type AgentHubRemote } from "./agent-hub.js";
|
|
26
26
|
/** Parsed message and model metadata relevant to a transcript viewer. */
|
|
27
27
|
export type AgentTranscriptEntry = SessionMessageEntryLike | {
|
|
28
28
|
type: "model_change";
|
|
@@ -14,6 +14,7 @@ export declare class BtwPanelComponent extends OverlayPanel {
|
|
|
14
14
|
markComplete(): void;
|
|
15
15
|
/** Visual confirmation that `c` copied the answer to the clipboard. */
|
|
16
16
|
markCopied(): void;
|
|
17
|
+
render(width: number): readonly string[];
|
|
17
18
|
/** Shows that the completed answer is being promoted into the chat session. */
|
|
18
19
|
markBranching(): void;
|
|
19
20
|
markAborted(): void;
|
|
@@ -2,42 +2,18 @@ import { type ComposerStyle } from "../index.js";
|
|
|
2
2
|
import type { SubmenuOption } from "./settings-defs.js";
|
|
3
3
|
/** Composer shape id; extensions may register additional values at runtime. */
|
|
4
4
|
export type ComposerShape = string;
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
readonly label:
|
|
13
|
-
readonly description:
|
|
14
|
-
}
|
|
15
|
-
readonly value: "claude";
|
|
16
|
-
readonly label: "Claude Code";
|
|
17
|
-
readonly description: "Full-width horizontal rules above and below, status line at bottom";
|
|
18
|
-
}, {
|
|
19
|
-
readonly value: "pi";
|
|
20
|
-
readonly label: "Pi";
|
|
21
|
-
readonly description: "Framed horizontal rules with status line at bottom";
|
|
22
|
-
}, {
|
|
23
|
-
readonly value: "borderless";
|
|
24
|
-
readonly label: "Borderless";
|
|
25
|
-
readonly description: "Clean prompt glyph with status line at bottom, no box borders";
|
|
26
|
-
}, {
|
|
27
|
-
readonly value: "rule";
|
|
28
|
-
readonly label: "Top Rule Dock";
|
|
29
|
-
readonly description: "Single top rule with status docked onto it and below";
|
|
30
|
-
}, {
|
|
31
|
-
readonly value: "field";
|
|
32
|
-
readonly label: "Compact Field";
|
|
33
|
-
readonly description: "Filled one-row field with accent end caps";
|
|
34
|
-
}, {
|
|
35
|
-
readonly value: "rail";
|
|
36
|
-
readonly label: "Accent Rail";
|
|
37
|
-
readonly description: "Filled one-row field anchored by a single accent rail";
|
|
38
|
-
}];
|
|
5
|
+
/**
|
|
6
|
+
* Built-in composer choices and their shared settings/setup copy. Labels and
|
|
7
|
+
* descriptions resolve through `tuiText` on every read (getter, not cached
|
|
8
|
+
* field) so a runtime language switch applies to the next rendered selector.
|
|
9
|
+
*/
|
|
10
|
+
export declare const BUILTIN_COMPOSER_SHAPES: {
|
|
11
|
+
value: string;
|
|
12
|
+
readonly label: string;
|
|
13
|
+
readonly description: string;
|
|
14
|
+
}[];
|
|
39
15
|
/** Built-in composer ids used by tests and non-runtime consumers. */
|
|
40
|
-
export declare const COMPOSER_SHAPE_VALUES:
|
|
16
|
+
export declare const COMPOSER_SHAPE_VALUES: string[];
|
|
41
17
|
/** Visual composer style and selector copy registered by an extension. */
|
|
42
18
|
export interface ComposerShapeDefinition {
|
|
43
19
|
label: string;
|
|
@@ -12,5 +12,7 @@ import { OverlayPanel } from "../chrome/overlay-box.js";
|
|
|
12
12
|
export declare class HistorySearchComponent extends OverlayPanel {
|
|
13
13
|
#private;
|
|
14
14
|
constructor(historyStorage: HistorySource, onSelect: (prompt: string) => void, onCancel: () => void);
|
|
15
|
+
/** Re-resolve the panel title every render so a live language switch applies. */
|
|
16
|
+
render(width: number): readonly string[];
|
|
15
17
|
handleInput(keyData: string): void;
|
|
16
18
|
}
|
|
@@ -12,4 +12,5 @@ export declare class LogoutAccountSelectorComponent extends OverlayPanel {
|
|
|
12
12
|
#private;
|
|
13
13
|
constructor(providerName: string, accounts: LogoutAccount[], onSelect: (account: LogoutAccount) => void, onCancel: () => void);
|
|
14
14
|
handleInput(keyData: string): void;
|
|
15
|
+
render(width: number): readonly string[];
|
|
15
16
|
}
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* `/move` overlay: a path input with live directory autocomplete.
|
|
3
|
-
*
|
|
4
|
-
* Rendered as a centered modal via `showHookCustom(..., { overlay: true })`.
|
|
5
|
-
* The user types a path, Tab autocompletes the highlighted directory, and Enter
|
|
6
|
-
* confirms — yielding the resolved directory string (or `undefined` on cancel).
|
|
7
|
-
*/
|
|
8
1
|
import { type Component, type Focusable } from "../index.js";
|
|
9
2
|
export interface MoveOverlayResult {
|
|
10
3
|
directory: string;
|
|
@@ -38,4 +38,5 @@ export declare class OAuthSelectorComponent extends OverlayPanel {
|
|
|
38
38
|
* drives the hover band, and a left click selects and confirms like Enter.
|
|
39
39
|
*/
|
|
40
40
|
routeMouse(event: SgrMouseEvent, line: number, _col: number): void;
|
|
41
|
+
render(width: number): readonly string[];
|
|
41
42
|
}
|
|
@@ -8,4 +8,5 @@ export declare class QueueModeSelectorComponent extends OverlayPanel {
|
|
|
8
8
|
constructor(currentMode: "all" | "one-at-a-time", onSelect: (mode: "all" | "one-at-a-time") => void, onCancel: () => void);
|
|
9
9
|
getSelectList(): SelectList;
|
|
10
10
|
routeMouse(event: SgrMouseEvent, line: number, col: number): void;
|
|
11
|
+
render(width: number): readonly string[];
|
|
11
12
|
}
|
|
@@ -20,4 +20,5 @@ export declare class ResetUsageSelectorComponent extends OverlayPanel {
|
|
|
20
20
|
#private;
|
|
21
21
|
constructor(accounts: ResetUsageAccount[], onSelect: (account: ResetUsageAccount) => void, onCancel: () => void);
|
|
22
22
|
handleInput(keyData: string): void;
|
|
23
|
+
render(width: number): readonly string[];
|
|
23
24
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/** Schema-independent display definitions for the settings overlay. */
|
|
2
1
|
import type { SymbolKey } from "../theme/symbols.js";
|
|
3
2
|
export type SettingTab = "appearance" | "model" | "interaction" | "context" | "memory" | "files" | "shell" | "tools" | "tasks" | "providers";
|
|
4
3
|
/** Tab display metadata - icon is resolved via theme.symbol() */
|
|
@@ -8,4 +8,5 @@ export declare class ShowImagesSelectorComponent extends OverlayPanel {
|
|
|
8
8
|
constructor(currentValue: boolean, onSelect: (show: boolean) => void, onCancel: () => void);
|
|
9
9
|
getSelectList(): SelectList;
|
|
10
10
|
routeMouse(event: SgrMouseEvent, line: number, col: number): void;
|
|
11
|
+
render(width: number): readonly string[];
|
|
11
12
|
}
|
|
@@ -9,4 +9,5 @@ export declare class ThemeSelectorComponent extends OverlayPanel {
|
|
|
9
9
|
constructor(currentTheme: string, themes: string[], onSelect: (themeName: string) => void, onCancel: () => void, onPreview: (themeName: string) => void);
|
|
10
10
|
getSelectList(): SelectList;
|
|
11
11
|
routeMouse(event: SgrMouseEvent, line: number, col: number): void;
|
|
12
|
+
render(width: number): readonly string[];
|
|
12
13
|
}
|
|
@@ -9,4 +9,5 @@ export declare class ThinkingSelectorComponent extends OverlayPanel {
|
|
|
9
9
|
constructor(currentLevel: Effort, availableLevels: Effort[], onSelect: (level: Effort) => void, onCancel: () => void);
|
|
10
10
|
getSelectList(): SelectList;
|
|
11
11
|
routeMouse(event: SgrMouseEvent, line: number, col: number): void;
|
|
12
|
+
render(width: number): readonly string[];
|
|
12
13
|
}
|
|
@@ -86,6 +86,8 @@ export declare class TreeSelectorComponent extends OverlayPanel {
|
|
|
86
86
|
constructor(tree: TreeSelectorNode[], currentLeafId: string | null, terminalHeight: number, onSelect: (entryId: string, options: {
|
|
87
87
|
summarize: boolean;
|
|
88
88
|
}) => void, onCancel: () => void, onLabelChangeCallback?: ((entryId: string, label: string | undefined) => void) | undefined, initialFilterMode?: FilterMode);
|
|
89
|
+
/** Re-resolve the panel title every render so a live language switch applies. */
|
|
90
|
+
render(width: number): readonly string[];
|
|
89
91
|
handleInput(keyData: string): void;
|
|
90
92
|
getTreeList(): TreeList;
|
|
91
93
|
}
|
|
@@ -8,7 +8,7 @@ import type { SetupSceneHost, SetupTab } from "./types.js";
|
|
|
8
8
|
export declare class SignInTab implements SetupTab {
|
|
9
9
|
#private;
|
|
10
10
|
readonly id = "sign-in";
|
|
11
|
-
|
|
11
|
+
get label(): string;
|
|
12
12
|
constructor(host: SetupSceneHost);
|
|
13
13
|
/** Modal while an OAuth flow is running so the scene won't switch tabs or finish. */
|
|
14
14
|
get modal(): boolean;
|
|
@@ -9,7 +9,7 @@ import type { SetupSceneHost, SetupTab } from "./types.js";
|
|
|
9
9
|
export declare class WebSearchTab implements SetupTab {
|
|
10
10
|
#private;
|
|
11
11
|
readonly id = "web-search";
|
|
12
|
-
|
|
12
|
+
get label(): string;
|
|
13
13
|
readonly modal = false;
|
|
14
14
|
constructor(host: SetupSceneHost);
|
|
15
15
|
onActivate(): void;
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@linxiraos/pi-tui",
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.19",
|
|
5
5
|
"description": "Terminal User Interface library with differential rendering for efficient text-based applications",
|
|
6
6
|
"homepage": "https://linxira-os.github.io/zeta/",
|
|
7
|
-
"author": "
|
|
7
|
+
"author": "Linxira-OS",
|
|
8
8
|
"contributors": [
|
|
9
9
|
"Mario Zechner"
|
|
10
10
|
],
|
|
@@ -37,14 +37,14 @@
|
|
|
37
37
|
"fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@linxiraos/pi-natives": "1.1.
|
|
41
|
-
"@linxiraos/pi-utils": "1.1.
|
|
42
|
-
"@linxiraos/pi-omptype": "1.1.
|
|
43
|
-
"@linxiraos/pi-agent-core": "1.1.
|
|
44
|
-
"@linxiraos/pi-ai": "1.1.
|
|
45
|
-
"@linxiraos/pi-catalog": "1.1.
|
|
46
|
-
"@linxiraos/pi-wire": "1.1.
|
|
47
|
-
"@linxiraos/pi-snapcompact": "1.1.
|
|
40
|
+
"@linxiraos/pi-natives": "1.1.19",
|
|
41
|
+
"@linxiraos/pi-utils": "1.1.19",
|
|
42
|
+
"@linxiraos/pi-omptype": "1.1.19",
|
|
43
|
+
"@linxiraos/pi-agent-core": "1.1.19",
|
|
44
|
+
"@linxiraos/pi-ai": "1.1.19",
|
|
45
|
+
"@linxiraos/pi-catalog": "1.1.19",
|
|
46
|
+
"@linxiraos/pi-wire": "1.1.19",
|
|
47
|
+
"@linxiraos/pi-snapcompact": "1.1.19"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"kitty-vt-wasm": "^0.2.0"
|
|
@@ -24,6 +24,7 @@ import { getLanguageFromPath } from "../../lang-from-path";
|
|
|
24
24
|
import { createHighlightStream, theme } from "../../theme/theme";
|
|
25
25
|
import { bgAnsiHex, canvasHex, fgAnsiHex, mixHex, pill, selectionBgAnsi, textHex, withBg } from "./colors";
|
|
26
26
|
import { DIFF_CONTEXT_LINES, type FileAssetSide, type FileStreamUpdate } from "./state";
|
|
27
|
+
import { tuiText } from "../../i18n";
|
|
27
28
|
|
|
28
29
|
/** Column ranges (inclusive start, exclusive end) carrying intraline emphasis. */
|
|
29
30
|
type MarkRanges = readonly (readonly [number, number])[];
|
|
@@ -1033,7 +1034,7 @@ export class DiffPane {
|
|
|
1033
1034
|
if (this.state === "streaming" && this.#streaming) return this.#renderStreaming(width, height);
|
|
1034
1035
|
if (this.state === "asset" && this.#asset) return this.#renderAsset(width, height);
|
|
1035
1036
|
if (!doc || this.state !== "ready") {
|
|
1036
|
-
const message = this.state === "loading" ? "Loading diff…" : this.emptyMessage;
|
|
1037
|
+
const message = this.state === "loading" ? tuiText("gitLoadingDiff", "Loading diff…") : this.emptyMessage;
|
|
1037
1038
|
const lines: string[] = [];
|
|
1038
1039
|
for (let i = 0; i < height; i++) {
|
|
1039
1040
|
lines.push(
|
|
@@ -1084,11 +1085,17 @@ export class DiffPane {
|
|
|
1084
1085
|
for (let index = 0; index < height; index++) {
|
|
1085
1086
|
const leftSource =
|
|
1086
1087
|
index === 0
|
|
1087
|
-
? centerLine(
|
|
1088
|
+
? centerLine(
|
|
1089
|
+
theme.bold(this.#assetTitle(tuiText("gitAssetBefore", "Before"), asset.old)),
|
|
1090
|
+
leftWidth,
|
|
1091
|
+
).trimEnd()
|
|
1088
1092
|
: (oldLines[index - 1] ?? "");
|
|
1089
1093
|
const rightSource =
|
|
1090
1094
|
index === 0
|
|
1091
|
-
? centerLine(
|
|
1095
|
+
? centerLine(
|
|
1096
|
+
theme.bold(this.#assetTitle(tuiText("gitAssetAfter", "After"), asset.new)),
|
|
1097
|
+
rightWidth,
|
|
1098
|
+
).trimEnd()
|
|
1092
1099
|
: (newLines[index - 1] ?? "");
|
|
1093
1100
|
const left = truncateToWidth(leftSource, leftWidth);
|
|
1094
1101
|
const right = truncateToWidth(rightSource, rightWidth);
|
|
@@ -1121,26 +1128,30 @@ export class DiffPane {
|
|
|
1121
1128
|
let details: string[];
|
|
1122
1129
|
switch (side.kind) {
|
|
1123
1130
|
case "empty":
|
|
1124
|
-
details = ["No file"];
|
|
1131
|
+
details = [tuiText("gitNoFile", "No file")];
|
|
1125
1132
|
break;
|
|
1126
1133
|
case "text":
|
|
1127
|
-
details = ["Text object", formatBytes(side.byteLength)];
|
|
1134
|
+
details = [tuiText("gitTextObject", "Text object"), formatBytes(side.byteLength)];
|
|
1128
1135
|
break;
|
|
1129
1136
|
case "binary":
|
|
1130
1137
|
details = [
|
|
1131
|
-
"Binary object",
|
|
1132
|
-
side.byteLength === undefined
|
|
1138
|
+
tuiText("gitBinaryObject", "Binary object"),
|
|
1139
|
+
side.byteLength === undefined
|
|
1140
|
+
? tuiText("gitSizeUnavailable", "Size unavailable")
|
|
1141
|
+
: formatBytes(side.byteLength),
|
|
1133
1142
|
];
|
|
1134
1143
|
break;
|
|
1135
1144
|
case "tooLarge":
|
|
1136
1145
|
details = [
|
|
1137
|
-
"Object too large to preview",
|
|
1138
|
-
side.byteLength === undefined
|
|
1146
|
+
tuiText("gitObjectTooLarge", "Object too large to preview"),
|
|
1147
|
+
side.byteLength === undefined
|
|
1148
|
+
? tuiText("gitExceedsPreviewLimit", "Exceeds preview limit")
|
|
1149
|
+
: formatBytes(side.byteLength),
|
|
1139
1150
|
];
|
|
1140
1151
|
break;
|
|
1141
1152
|
case "lfsMissing":
|
|
1142
1153
|
details = [
|
|
1143
|
-
"Git LFS object unavailable",
|
|
1154
|
+
tuiText("gitLfsObjectUnavailable", "Git LFS object unavailable"),
|
|
1144
1155
|
`sha256:${side.oid.slice(0, 12)}… · ${formatBytes(side.byteLength)}`,
|
|
1145
1156
|
];
|
|
1146
1157
|
break;
|
|
@@ -1165,19 +1176,19 @@ export class DiffPane {
|
|
|
1165
1176
|
lfs = side.image.lfsOid !== undefined;
|
|
1166
1177
|
break;
|
|
1167
1178
|
case "text":
|
|
1168
|
-
kind = "Text";
|
|
1179
|
+
kind = tuiText("gitKindText", "Text");
|
|
1169
1180
|
lfs = side.lfsOid !== undefined;
|
|
1170
1181
|
break;
|
|
1171
1182
|
case "binary":
|
|
1172
|
-
kind = "Binary";
|
|
1183
|
+
kind = tuiText("gitKindBinary", "Binary");
|
|
1173
1184
|
lfs = side.lfsOid !== undefined;
|
|
1174
1185
|
break;
|
|
1175
1186
|
case "tooLarge":
|
|
1176
|
-
kind = "Too large";
|
|
1187
|
+
kind = tuiText("gitKindTooLarge", "Too large");
|
|
1177
1188
|
lfs = side.lfsOid !== undefined;
|
|
1178
1189
|
break;
|
|
1179
1190
|
case "lfsMissing":
|
|
1180
|
-
kind = "LFS missing";
|
|
1191
|
+
kind = tuiText("gitKindLfsMissing", "LFS missing");
|
|
1181
1192
|
lfs = true;
|
|
1182
1193
|
break;
|
|
1183
1194
|
}
|
|
@@ -1190,7 +1201,9 @@ export class DiffPane {
|
|
|
1190
1201
|
const total = this.#total();
|
|
1191
1202
|
if (total === 0) {
|
|
1192
1203
|
return Array.from({ length: height }, (_, index) =>
|
|
1193
|
-
index === Math.floor(height / 2)
|
|
1204
|
+
index === Math.floor(height / 2)
|
|
1205
|
+
? centerLine(theme.fg("dim", tuiText("gitStreamingFile", "Streaming file…")), width).trimEnd()
|
|
1206
|
+
: "",
|
|
1194
1207
|
);
|
|
1195
1208
|
}
|
|
1196
1209
|
this.#clampScroll();
|