@deepseek-harness-tui/dsh-tui 0.8.1 → 0.8.3
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 +30 -15
- package/bin/dsh-tui.js +43 -7
- package/dsh-ecosystem-spec/protocols/profile-definitions.d.ts +13 -0
- package/dsh-ecosystem-spec/protocols/profile-definitions.js +59 -0
- package/dsh-ecosystem-spec/protocols/tui-channel-http.d.ts +15 -0
- package/dsh-ecosystem-spec/protocols/tui-channel-http.js +32 -0
- package/dsh-ecosystem-spec/protocols/tui-channel.d.ts +59 -0
- package/dsh-ecosystem-spec/protocols/tui-channel.js +166 -0
- package/dsh-ecosystem-spec/protocols/tui-contributions.d.ts +42 -0
- package/dsh-ecosystem-spec/protocols/tui-contributions.js +143 -0
- package/dsh-ecosystem-spec/registry/README.md +14 -0
- package/dsh-ecosystem-spec/registry/contracts/scene-v1alpha1.json +13 -0
- package/dsh-ecosystem-spec/registry/contracts/settings-section-v1alpha1.json +13 -0
- package/dsh-ecosystem-spec/registry/contracts/tui-channel-v1alpha1.json +30 -0
- package/dsh-ecosystem-spec/registry/contracts/workspace-provider-v1alpha1.json +6 -0
- package/{ecosystem-spec → dsh-ecosystem-spec}/registry/permissions-0.1.json +1 -1
- package/dsh-ecosystem-spec/registry/registry-0.15.json +149 -0
- package/lib/types/command-trees.d.ts +2 -1
- package/lib/types/command-trees.d.ts.map +1 -1
- package/lib/types/command-trees.js +1 -1
- package/lib/types/components/LoadedContextPanel.d.ts +10 -5
- package/lib/types/components/LoadedContextPanel.d.ts.map +1 -1
- package/lib/types/components/LoadedContextPanel.js +18 -7
- package/lib/types/components/LogoV2.d.ts.map +1 -1
- package/lib/types/components/LogoV2.js +16 -7
- package/lib/types/components/Markdown.d.ts +13 -1
- package/lib/types/components/Markdown.d.ts.map +1 -1
- package/lib/types/components/Markdown.js +15 -1
- package/lib/types/components/MessageList.d.ts +3 -1
- package/lib/types/components/MessageList.d.ts.map +1 -1
- package/lib/types/components/MessageList.js +90 -9
- package/lib/types/components/PromptInput.d.ts.map +1 -1
- package/lib/types/components/PromptInput.js +26 -12
- package/lib/types/components/StreamingMarkdown.d.ts +2 -8
- package/lib/types/components/StreamingMarkdown.d.ts.map +1 -1
- package/lib/types/components/StreamingMarkdown.js +51 -9
- package/lib/types/components/activityFrames.d.ts +1 -1
- package/lib/types/components/activityFrames.d.ts.map +1 -1
- package/lib/types/components/activityFrames.js +4 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts +5 -1
- package/lib/types/components/messages/AssistantThinkingMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantThinkingMessage.js +26 -3
- package/lib/types/components/messages/AssistantToolUseMessage.d.ts.map +1 -1
- package/lib/types/components/messages/AssistantToolUseMessage.js +12 -1
- package/lib/types/dsh-adapter/channel.d.ts +31 -4
- package/lib/types/dsh-adapter/channel.d.ts.map +1 -1
- package/lib/types/dsh-adapter/channel.js +267 -102
- package/lib/types/dsh-adapter/childStderr.d.ts.map +1 -1
- package/lib/types/dsh-adapter/childStderr.js +10 -0
- package/lib/types/dsh-adapter/command-attribution.d.ts.map +1 -1
- package/lib/types/dsh-adapter/command-attribution.js +2 -2
- package/lib/types/dsh-adapter/command-trees.d.ts +7 -1
- package/lib/types/dsh-adapter/command-trees.d.ts.map +1 -1
- package/lib/types/dsh-adapter/command-trees.js +70 -20
- package/lib/types/dsh-adapter/component-identity.d.ts +5 -0
- package/lib/types/dsh-adapter/component-identity.d.ts.map +1 -1
- package/lib/types/dsh-adapter/component-identity.js +14 -14
- package/lib/types/dsh-adapter/decision-guard.d.ts.map +1 -1
- package/lib/types/dsh-adapter/decision-guard.js +10 -16
- package/lib/types/dsh-adapter/dialogs.d.ts +2 -3
- package/lib/types/dsh-adapter/dialogs.d.ts.map +1 -1
- package/lib/types/dsh-adapter/dialogs.js +114 -60
- package/lib/types/dsh-adapter/effect-ledger.d.ts +0 -8
- package/lib/types/dsh-adapter/effect-ledger.d.ts.map +1 -1
- package/lib/types/dsh-adapter/effect-ledger.js +73 -53
- package/lib/types/dsh-adapter/extension-events.d.ts.map +1 -1
- package/lib/types/dsh-adapter/extension-events.js +39 -1
- package/lib/types/dsh-adapter/grants.d.ts.map +1 -1
- package/lib/types/dsh-adapter/grants.js +43 -14
- package/lib/types/dsh-adapter/host-access.d.ts +37 -0
- package/lib/types/dsh-adapter/host-access.d.ts.map +1 -0
- package/lib/types/dsh-adapter/host-access.js +652 -0
- package/lib/types/dsh-adapter/host-descriptor.d.ts +2 -2
- package/lib/types/dsh-adapter/host-descriptor.d.ts.map +1 -1
- package/lib/types/dsh-adapter/host-descriptor.js +31 -8
- package/lib/types/dsh-adapter/index.d.ts +4 -0
- package/lib/types/dsh-adapter/index.d.ts.map +1 -1
- package/lib/types/dsh-adapter/index.js +1 -0
- package/lib/types/dsh-adapter/message-observer.d.ts +10 -15
- package/lib/types/dsh-adapter/message-observer.d.ts.map +1 -1
- package/lib/types/dsh-adapter/message-observer.js +114 -70
- package/lib/types/dsh-adapter/plugin-host.d.ts +39 -6
- package/lib/types/dsh-adapter/plugin-host.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin-host.js +139 -44
- package/lib/types/dsh-adapter/plugin-storage.d.ts +0 -5
- package/lib/types/dsh-adapter/plugin-storage.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin-storage.js +48 -36
- package/lib/types/dsh-adapter/plugin.d.ts.map +1 -1
- package/lib/types/dsh-adapter/plugin.js +97 -16
- package/lib/types/dsh-adapter/promptDebug.d.ts +0 -6
- package/lib/types/dsh-adapter/promptDebug.d.ts.map +1 -1
- package/lib/types/dsh-adapter/promptDebug.js +13 -4
- package/lib/types/dsh-adapter/renderers.d.ts +6 -14
- package/lib/types/dsh-adapter/renderers.d.ts.map +1 -1
- package/lib/types/dsh-adapter/renderers.js +81 -46
- package/lib/types/dsh-adapter/scenes.d.ts +8 -4
- package/lib/types/dsh-adapter/scenes.d.ts.map +1 -1
- package/lib/types/dsh-adapter/scenes.js +136 -37
- package/lib/types/dsh-adapter/settings-sections.d.ts +7 -3
- package/lib/types/dsh-adapter/settings-sections.d.ts.map +1 -1
- package/lib/types/dsh-adapter/settings-sections.js +106 -26
- package/lib/types/dsh-adapter/shortcuts.d.ts +8 -10
- package/lib/types/dsh-adapter/shortcuts.d.ts.map +1 -1
- package/lib/types/dsh-adapter/shortcuts.js +108 -36
- package/lib/types/dsh-adapter/status.d.ts +6 -7
- package/lib/types/dsh-adapter/status.d.ts.map +1 -1
- package/lib/types/dsh-adapter/status.js +88 -22
- package/lib/types/dsh-adapter/workspaces.d.ts +16 -5
- package/lib/types/dsh-adapter/workspaces.d.ts.map +1 -1
- package/lib/types/dsh-adapter/workspaces.js +287 -170
- package/lib/types/extensions.d.ts +10 -5
- package/lib/types/extensions.d.ts.map +1 -1
- package/lib/types/extensions.js +11 -5
- package/lib/types/force-production-react.d.ts +1 -0
- package/lib/types/force-production-react.d.ts.map +1 -0
- package/lib/types/force-production-react.js +12 -0
- package/lib/types/i18n.d.ts +22 -6
- package/lib/types/i18n.d.ts.map +1 -1
- package/lib/types/i18n.js +14 -2
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +1 -0
- package/lib/types/ink/components/App.d.ts +2 -0
- package/lib/types/ink/components/App.d.ts.map +1 -1
- package/lib/types/ink/components/App.js +4 -0
- package/lib/types/ink/ink.d.ts +20 -3
- package/lib/types/ink/ink.d.ts.map +1 -1
- package/lib/types/ink/ink.js +57 -5
- package/lib/types/ink/log-update.d.ts.map +1 -1
- package/lib/types/ink/log-update.js +128 -9
- package/lib/types/ink/output.d.ts +28 -2
- package/lib/types/ink/output.d.ts.map +1 -1
- package/lib/types/ink/output.js +158 -12
- package/lib/types/ink/screen.d.ts +39 -0
- package/lib/types/ink/screen.d.ts.map +1 -1
- package/lib/types/ink/screen.js +117 -0
- package/lib/types/ink/terminal.d.ts.map +1 -1
- package/lib/types/ink/terminal.js +10 -2
- package/lib/types/ink/wrapAnsi.d.ts +1 -1
- package/lib/types/ink/wrapAnsi.d.ts.map +1 -1
- package/lib/types/ink/wrapAnsi.js +29 -2
- package/lib/types/plugin-host.d.ts +13 -11
- package/lib/types/plugin-host.d.ts.map +1 -1
- package/lib/types/plugin-host.js +16 -16
- package/lib/types/plugin-spec/registry.d.ts +2 -2
- package/lib/types/plugin-spec/registry.d.ts.map +1 -1
- package/lib/types/plugin-spec/registry.js +113 -18
- package/lib/types/plugin-spec/tui-extension.d.ts.map +1 -1
- package/lib/types/plugin-spec/tui-extension.js +2 -0
- package/lib/types/plugin-spec/validate.d.ts.map +1 -1
- package/lib/types/plugin-spec/validate.js +20 -1
- package/lib/types/scenes.d.ts +2 -1
- package/lib/types/scenes.d.ts.map +1 -1
- package/lib/types/scenes.js +1 -1
- package/lib/types/screens/Chat.d.ts +3 -3
- package/lib/types/screens/Chat.d.ts.map +1 -1
- package/lib/types/screens/Chat.js +38 -17
- package/lib/types/screens/SessionBrowser.d.ts.map +1 -1
- package/lib/types/screens/SessionBrowser.js +10 -3
- package/lib/types/sessions/view.d.ts +3 -2
- package/lib/types/sessions/view.d.ts.map +1 -1
- package/lib/types/sessions/view.js +18 -0
- package/lib/types/settings-sections.d.ts +2 -1
- package/lib/types/settings-sections.d.ts.map +1 -1
- package/lib/types/settings-sections.js +1 -1
- package/lib/types/utils/execFileNoThrow.d.ts.map +1 -1
- package/lib/types/utils/execFileNoThrow.js +3 -0
- package/lib/types/workspaces.d.ts +2 -1
- package/lib/types/workspaces.d.ts.map +1 -1
- package/lib/types/workspaces.js +1 -1
- package/node_modules/@dsh-std/command/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/command/package.json +1 -1
- package/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/connection/lib/memory.d.ts +1 -1
- package/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -1
- package/node_modules/@dsh-std/connection/lib/memory.js +1 -0
- package/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/node_modules/@dsh-std/connection/package.json +1 -1
- package/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/core/package.json +1 -1
- package/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
- package/node_modules/@dsh-std/manifest/package.json +1 -1
- package/node_modules/@dsh-std/messages/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/messages/package.json +1 -1
- package/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
- package/node_modules/@dsh-std/presentation/README.md +2 -1
- package/node_modules/@dsh-std/presentation/README.zh.md +2 -1
- package/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
- package/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
- package/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
- package/node_modules/@dsh-std/presentation/lib/index.d.ts +44 -1
- package/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -1
- package/node_modules/@dsh-std/presentation/lib/index.js +6 -3
- package/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/node_modules/@dsh-std/presentation/package.json +7 -3
- package/node_modules/@dsh-std/storage/CHANGELOG.md +8 -0
- package/node_modules/@dsh-std/storage/package.json +1 -1
- package/package.json +10 -5
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/connection/package.json +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/CHANGELOG.md +9 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/manifest/package.json +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/CHANGELOG.md +9 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.md +2 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/README.zh.md +2 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.d.ts +2 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js +179 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/callback.js.map +1 -0
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts +44 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.d.ts.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js +6 -3
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/lib/index.js.map +1 -1
- package/vendor/dsh-std/packages/command/node_modules/@dsh-std/presentation/package.json +7 -3
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/connection/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/manifest/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/messages/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.d.ts.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js +1 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/lib/memory.js.map +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/connection/package.json +1 -1
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/presentation/node_modules/@dsh-std/core/package.json +1 -1
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/CHANGELOG.md +8 -0
- package/vendor/dsh-std/packages/storage/node_modules/@dsh-std/core/package.json +1 -1
- package/ecosystem-spec/registry/registry-0.15.json +0 -57
- /package/{ecosystem-spec → dsh-ecosystem-spec}/registry/contracts/decision-events-v1alpha1.json +0 -0
- /package/{ecosystem-spec → dsh-ecosystem-spec}/registry/host-descriptor.tui.example.json +0 -0
- /package/{ecosystem-spec → dsh-ecosystem-spec}/schemas/conformance-claim.schema.json +0 -0
- /package/{ecosystem-spec → dsh-ecosystem-spec}/schemas/effect-ledger-record.schema.json +0 -0
- /package/{ecosystem-spec → dsh-ecosystem-spec}/schemas/host-descriptor.schema.json +0 -0
package/lib/types/ink/output.js
CHANGED
|
@@ -4,7 +4,7 @@ import { getGraphemeSegmenter } from '../utils/intl.js';
|
|
|
4
4
|
import sliceAnsi from '../utils/sliceAnsi.js';
|
|
5
5
|
import { reorderBidi } from './bidi.js';
|
|
6
6
|
import { unionRect } from './layout/geometry.js';
|
|
7
|
-
import { blitRegion, extractHyperlinkFromStyles, filterOutHyperlinkStyles, markNoSelectRegion, OSC8_PREFIX, resetScreen, setCellAt, shiftRows, } from './screen.js';
|
|
7
|
+
import { blitRegion, cellRunSpan, createCellRun, extractHyperlinkFromStyles, filterOutHyperlinkStyles, markNoSelectRegion, OSC8_PREFIX, recordCellRunEntry, recordSpacerRunEntry, replayCellRun, resetScreen, setCellAt, shiftRows, } from './screen.js';
|
|
8
8
|
import { stringWidth } from './stringWidth.js';
|
|
9
9
|
import { widestLine } from './widest-line.js';
|
|
10
10
|
/**
|
|
@@ -29,6 +29,11 @@ import { widestLine } from './widest-line.js';
|
|
|
29
29
|
const MAX_CACHEABLE_LINE = 500;
|
|
30
30
|
const CHAR_CACHE_MAX_ENTRIES = 16384;
|
|
31
31
|
const CHAR_CACHE_MAX_CHARS = 100_000;
|
|
32
|
+
/** Packed-run line cap: runs are three integers per cell (no per-char
|
|
33
|
+
* objects like charCache entries), so long ANSI-art lines (the whale
|
|
34
|
+
* logo, ~700 chars) are worth caching — they would otherwise
|
|
35
|
+
* re-tokenize and re-cluster every frame. */
|
|
36
|
+
const PACKED_MAX_LINE = 4000;
|
|
32
37
|
/** Copy a string into a fresh flat string with no parent references. */
|
|
33
38
|
function detachString(s) {
|
|
34
39
|
// Buffer round-trip guarantees a newly allocated flat string; cheaper
|
|
@@ -41,28 +46,58 @@ function detachString(s) {
|
|
|
41
46
|
* no caller can accidentally grow it unboundedly.
|
|
42
47
|
*/
|
|
43
48
|
export class CharCache {
|
|
49
|
+
/**
|
|
50
|
+
* LRU of line → clustered characters. A full clear on overflow
|
|
51
|
+
* (the original behavior) thrashes during long-session streaming: the
|
|
52
|
+
* mounted window's static lines alone approach the char budget, so the
|
|
53
|
+
* streaming row's per-frame new keys tip it over every frame or two,
|
|
54
|
+
* nuking the cache and forcing ~1800 line re-tokenizations per frame
|
|
55
|
+
* (measured ~100ms/frame at a 175-row session). Evicting oldest-first
|
|
56
|
+
* keeps the hot mounted lines resident while streaming churn falls out
|
|
57
|
+
* the back. Recency is refreshed on hit (delete + re-insert) so lines
|
|
58
|
+
* read every frame are never evicted by one-shot churn.
|
|
59
|
+
*/
|
|
44
60
|
map = new Map();
|
|
45
61
|
chars = 0;
|
|
46
62
|
/**
|
|
47
|
-
* Return the cached clustered characters for a line, if present
|
|
63
|
+
* Return the cached clustered characters for a line, if present, and
|
|
64
|
+
* refresh the entry's recency.
|
|
48
65
|
* @param line - the line to look up.
|
|
49
66
|
* @returns the cached characters, or undefined on a miss.
|
|
50
67
|
*/
|
|
51
68
|
get(line) {
|
|
52
|
-
|
|
69
|
+
const hit = this.map.get(line);
|
|
70
|
+
if (hit !== undefined) {
|
|
71
|
+
this.map.delete(line);
|
|
72
|
+
this.map.set(line, hit);
|
|
73
|
+
}
|
|
74
|
+
return hit;
|
|
53
75
|
}
|
|
54
76
|
/**
|
|
55
|
-
* Cache clustered characters for a line, enforcing the cache bounds
|
|
77
|
+
* Cache clustered characters for a line, enforcing the cache bounds by
|
|
78
|
+
* evicting least-recently-used entries (never a full clear).
|
|
56
79
|
* @param line - the line key.
|
|
57
80
|
* @param characters - the clustered characters to cache.
|
|
58
81
|
*/
|
|
59
82
|
set(line, characters) {
|
|
60
83
|
if (line.length > MAX_CACHEABLE_LINE)
|
|
61
84
|
return;
|
|
62
|
-
if (this.map.
|
|
85
|
+
if (this.map.has(line)) {
|
|
86
|
+
this.map.delete(line);
|
|
87
|
+
this.chars -= line.length;
|
|
88
|
+
}
|
|
89
|
+
// Evict oldest entries until the new one fits. A single line longer
|
|
90
|
+
// than the whole budget cannot fit even empty — skip caching it.
|
|
91
|
+
if (line.length > CHAR_CACHE_MAX_CHARS)
|
|
92
|
+
return;
|
|
93
|
+
while (this.map.size >= CHAR_CACHE_MAX_ENTRIES ||
|
|
63
94
|
this.chars + line.length > CHAR_CACHE_MAX_CHARS) {
|
|
64
|
-
this.map.
|
|
65
|
-
|
|
95
|
+
const oldest = this.map.keys().next();
|
|
96
|
+
if (oldest.done === true)
|
|
97
|
+
break;
|
|
98
|
+
const oldestKey = oldest.value;
|
|
99
|
+
this.chars -= oldestKey.length;
|
|
100
|
+
this.map.delete(oldestKey);
|
|
66
101
|
}
|
|
67
102
|
this.map.set(detachString(line), characters);
|
|
68
103
|
this.chars += line.length;
|
|
@@ -106,6 +141,13 @@ function minDefined(a, b) {
|
|
|
106
141
|
return a;
|
|
107
142
|
return Math.min(a, b);
|
|
108
143
|
}
|
|
144
|
+
/**
|
|
145
|
+
* Slot-reuse ceiling: the clustered array is a second full memory image of
|
|
146
|
+
* the line, and pathological single-line output (base64 blobs, minified
|
|
147
|
+
* code) would pin it across frames on top of the string itself. Past this
|
|
148
|
+
* length every frame takes the full path — transient, GC-able.
|
|
149
|
+
*/
|
|
150
|
+
const STREAMING_SLOT_MAX_LINE = 65_536;
|
|
109
151
|
/**
|
|
110
152
|
* Classify the tail of the line relative to its LAST ESC character.
|
|
111
153
|
* - 'none': no ESC at all
|
|
@@ -172,6 +214,7 @@ function hasRtlChars(text) {
|
|
|
172
214
|
* The slot is only kept when the line can safely be extended next frame. */
|
|
173
215
|
function updateStreamingSlot(slot, line, clustered, chars) {
|
|
174
216
|
if (line.length <= MAX_CACHEABLE_LINE ||
|
|
217
|
+
line.length > STREAMING_SLOT_MAX_LINE ||
|
|
175
218
|
endsWithOpenGrapheme(line) ||
|
|
176
219
|
hasRtlChars(line)) {
|
|
177
220
|
// Short lines are served by CharCache; complex tails always take the
|
|
@@ -234,6 +277,41 @@ export default class Output {
|
|
|
234
277
|
screen;
|
|
235
278
|
operations = [];
|
|
236
279
|
charCache = new CharCache();
|
|
280
|
+
/**
|
|
281
|
+
* LRU of line → recorded packed cell run, mirroring charCache's bounds.
|
|
282
|
+
* The main-screen architecture repaints every settled line each frame;
|
|
283
|
+
* the recorded run replays as raw two-word stores (no interning, no
|
|
284
|
+
* packing, no guard branches) — the long-session streaming fix. Runs are
|
|
285
|
+
* validated against the screen they were interned on and die with it.
|
|
286
|
+
*/
|
|
287
|
+
packedLines = new Map();
|
|
288
|
+
packedChars = 0;
|
|
289
|
+
/** Stable owner handle passed to writeLineToScreen (no per-call closure). */
|
|
290
|
+
packedOwner = {
|
|
291
|
+
lines: this.packedLines,
|
|
292
|
+
commit: (line, run) => {
|
|
293
|
+
this.setPackedLine(line, run);
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
/** Insert into the packed-lines LRU, evicting oldest entries on budget. */
|
|
297
|
+
setPackedLine(line, run) {
|
|
298
|
+
if (line.length > PACKED_MAX_LINE)
|
|
299
|
+
return;
|
|
300
|
+
if (this.packedLines.has(line)) {
|
|
301
|
+
this.packedLines.delete(line);
|
|
302
|
+
this.packedChars -= line.length;
|
|
303
|
+
}
|
|
304
|
+
while (this.packedLines.size >= CHAR_CACHE_MAX_ENTRIES ||
|
|
305
|
+
this.packedChars + line.length > CHAR_CACHE_MAX_CHARS) {
|
|
306
|
+
const oldest = this.packedLines.keys().next();
|
|
307
|
+
if (oldest.done === true)
|
|
308
|
+
break;
|
|
309
|
+
this.packedChars -= oldest.value.length;
|
|
310
|
+
this.packedLines.delete(oldest.value);
|
|
311
|
+
}
|
|
312
|
+
this.packedLines.set(detachString(line), run);
|
|
313
|
+
this.packedChars += line.length;
|
|
314
|
+
}
|
|
237
315
|
/**
|
|
238
316
|
* Streaming-tail slot, shared by every writeLineToScreen call of this
|
|
239
317
|
* Output (only one line grows per frame during streaming). Survives reset()
|
|
@@ -482,6 +560,12 @@ export default class Output {
|
|
|
482
560
|
const from = x < clip.x1 ? clip.x1 - x : 0;
|
|
483
561
|
const width = stringWidth(line);
|
|
484
562
|
const to = x + width > clip.x2 ? clip.x2 - x : width;
|
|
563
|
+
// Fast path: the line sits entirely inside the clip — no
|
|
564
|
+
// slice needed. sliceAnsi re-tokenizes the line (the
|
|
565
|
+
// dominant per-frame cost of long sessions otherwise:
|
|
566
|
+
// every settled line, every frame).
|
|
567
|
+
if (from === 0 && to === width)
|
|
568
|
+
return line;
|
|
485
569
|
let sliced = sliceAnsi(line, from, to);
|
|
486
570
|
// Wide chars (CJK, emoji) occupy 2 cells. When `to` lands
|
|
487
571
|
// on the first cell of a wide char, sliceAnsi includes the
|
|
@@ -524,7 +608,7 @@ export default class Output {
|
|
|
524
608
|
if (lineY >= screenHeight) {
|
|
525
609
|
break;
|
|
526
610
|
}
|
|
527
|
-
const contentEnd = writeLineToScreen(screen, line, x, lineY, screenWidth, this.stylePool, this.charCache, this.streamingSlot);
|
|
611
|
+
const contentEnd = writeLineToScreen(screen, line, x, lineY, screenWidth, this.stylePool, this.charCache, this.streamingSlot, this.packedOwner);
|
|
528
612
|
writeCells += contentEnd - x;
|
|
529
613
|
// See Screen.softWrap docstring for the encoding. contentEnd
|
|
530
614
|
// from writeLineToScreen is tab-expansion-aware, unlike
|
|
@@ -641,12 +725,45 @@ function flushBuffer(buffer, styles, stylePool, out) {
|
|
|
641
725
|
* the caller can record it in screen.softWrap without re-walking the
|
|
642
726
|
* line via stringWidth(). Caller computes the debug cell-count as end-x.
|
|
643
727
|
*/
|
|
644
|
-
function writeLineToScreen(screen, line, x, y, screenWidth, stylePool, charCache, streamingSlot) {
|
|
728
|
+
function writeLineToScreen(screen, line, x, y, screenWidth, stylePool, charCache, streamingSlot, packed) {
|
|
729
|
+
// Fast path: replay the recorded packed run for this exact line — two
|
|
730
|
+
// typed-array stores per cell, no interning/packing/guard work. The run
|
|
731
|
+
// dies with its screen; a width transition needs the slow path's guards
|
|
732
|
+
// and replayCellRun reports that.
|
|
733
|
+
if (packed !== undefined) {
|
|
734
|
+
const run = packed.lines.get(line);
|
|
735
|
+
if (run !== undefined &&
|
|
736
|
+
run.charPool === screen.charPool &&
|
|
737
|
+
x >= 0 &&
|
|
738
|
+
x + cellRunSpan(run) <= screenWidth) {
|
|
739
|
+
if (replayCellRun(screen, x, y, run)) {
|
|
740
|
+
// LRU refresh (chars budget unchanged: same key length).
|
|
741
|
+
packed.lines.delete(line);
|
|
742
|
+
packed.lines.set(line, run);
|
|
743
|
+
return x + cellRunSpan(run);
|
|
744
|
+
}
|
|
745
|
+
// fall through to the slow path for this line this frame
|
|
746
|
+
}
|
|
747
|
+
}
|
|
645
748
|
let characters = charCache.get(line);
|
|
646
749
|
if (!characters) {
|
|
647
750
|
characters = buildClusteredChars(line, stylePool, streamingSlot);
|
|
648
751
|
charCache.set(line, characters);
|
|
649
752
|
}
|
|
753
|
+
// Recording for the packed fast path: only plain single/wide char cells
|
|
754
|
+
// are recordable — control chars (tab expansion is x-relative), edge
|
|
755
|
+
// SpacerHead substitution, and y/x off-screen abort it. The packed-run
|
|
756
|
+
// limit is far above the charCache's MAX_CACHEABLE_LINE: a run costs
|
|
757
|
+
// three small integers per cell (no per-char objects), so even the
|
|
758
|
+
// ~700-char ANSI-art whale lines belong — without this they
|
|
759
|
+
// re-tokenize and re-cluster EVERY frame.
|
|
760
|
+
const recordable = packed !== undefined &&
|
|
761
|
+
line.length <= PACKED_MAX_LINE &&
|
|
762
|
+
x >= 0 &&
|
|
763
|
+
y >= 0 &&
|
|
764
|
+
y < screen.height;
|
|
765
|
+
let run = recordable ? createCellRun(screen) : undefined;
|
|
766
|
+
let runAlive = run !== undefined;
|
|
650
767
|
let offsetX = x;
|
|
651
768
|
for (let charIdx = 0; charIdx < characters.length; charIdx++) {
|
|
652
769
|
const character = characters[charIdx];
|
|
@@ -655,6 +772,8 @@ function writeLineToScreen(screen, line, x, y, screenWidth, stylePool, charCache
|
|
|
655
772
|
// mismatches. stringWidth treats these as width 0, but terminals may
|
|
656
773
|
// move the cursor differently.
|
|
657
774
|
if (codePoint !== undefined && codePoint <= 0x1f) {
|
|
775
|
+
// Not recordable: tab expansion is x-relative, ESC handling varies.
|
|
776
|
+
runAlive = false;
|
|
658
777
|
// Tab (0x09): expand to spaces to reach next tab stop
|
|
659
778
|
if (codePoint === 0x09) {
|
|
660
779
|
const tabWidth = 8;
|
|
@@ -757,9 +876,10 @@ function writeLineToScreen(screen, line, x, y, screenWidth, stylePool, charCache
|
|
|
757
876
|
}
|
|
758
877
|
const isWideCharacter = charWidth >= 2;
|
|
759
878
|
// Wide char at last column can't fit — terminal would wrap it to
|
|
760
|
-
// the next line, desyncing our cursor model. Place a SpacerHead
|
|
761
|
-
//
|
|
879
|
+
// the next line, desyncing our cursor model. Place a SpacerHead to
|
|
880
|
+
// mark the blank column, matching terminal behavior.
|
|
762
881
|
if (isWideCharacter && offsetX + 2 > screenWidth) {
|
|
882
|
+
runAlive = false;
|
|
763
883
|
setCellAt(screen, offsetX, y, {
|
|
764
884
|
char: ' ',
|
|
765
885
|
styleId: stylePool.none,
|
|
@@ -772,13 +892,39 @@ function writeLineToScreen(screen, line, x, y, screenWidth, stylePool, charCache
|
|
|
772
892
|
// styleId + hyperlink were precomputed during clustering (once per
|
|
773
893
|
// style run, cached via charCache). Hot loop is now just property
|
|
774
894
|
// reads — no intern, no extract, no filter per frame.
|
|
895
|
+
const cellWidth = isWideCharacter ? 1 /* CellWidth.Wide */ : 0 /* CellWidth.Narrow */;
|
|
775
896
|
setCellAt(screen, offsetX, y, {
|
|
776
897
|
char: character.value,
|
|
777
898
|
styleId: character.styleId,
|
|
778
|
-
width:
|
|
899
|
+
width: cellWidth,
|
|
779
900
|
hyperlink: character.hyperlink,
|
|
780
901
|
});
|
|
902
|
+
if (runAlive && run !== undefined) {
|
|
903
|
+
recordCellRunEntry(run, screen, offsetX, {
|
|
904
|
+
char: character.value,
|
|
905
|
+
styleId: character.styleId,
|
|
906
|
+
width: cellWidth,
|
|
907
|
+
hyperlink: character.hyperlink,
|
|
908
|
+
});
|
|
909
|
+
// setCellAt also writes a SpacerTail after a wide char (when it
|
|
910
|
+
// fits); record that deterministic write too, or abort at the edge.
|
|
911
|
+
if (isWideCharacter) {
|
|
912
|
+
if (offsetX + 1 < screenWidth) {
|
|
913
|
+
recordSpacerRunEntry(run, offsetX + 1);
|
|
914
|
+
}
|
|
915
|
+
else {
|
|
916
|
+
runAlive = false;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}
|
|
781
920
|
offsetX += isWideCharacter ? 2 : 1;
|
|
782
921
|
}
|
|
922
|
+
// Commit the recording for the packed fast path. Complete NON-EMPTY
|
|
923
|
+
// runs only: an empty line ('' from split('\n'), zero-width-only lines)
|
|
924
|
+
// records zero entries and would commit a degenerate run whose replay
|
|
925
|
+
// writes NaN damage (gaps[0] undefined) and poisons the whole frame diff.
|
|
926
|
+
if (runAlive && run !== undefined && packed !== undefined && run.gaps.length > 0) {
|
|
927
|
+
packed.commit(line, run);
|
|
928
|
+
}
|
|
783
929
|
return offsetX;
|
|
784
930
|
}
|
|
@@ -339,6 +339,45 @@ export declare function charInCellAt(screen: Screen, x: number, y: number): stri
|
|
|
339
339
|
* @param cell - the cell data to write.
|
|
340
340
|
*/
|
|
341
341
|
export declare function setCellAt(screen: Screen, x: number, y: number, cell: Cell): void;
|
|
342
|
+
/** A recorded run of packed cell writes for one screen line. */
|
|
343
|
+
export interface CellRun {
|
|
344
|
+
/** Char pool the words were interned against. Screens ping-pong
|
|
345
|
+
* (front/back double buffering) but SHARE their pools for a whole
|
|
346
|
+
* session, so pool identity — not screen identity — is the validation
|
|
347
|
+
* token; runs survive the screen swap and die only with the pools
|
|
348
|
+
* (renderer recreation/resize). */
|
|
349
|
+
charPool: CharPool;
|
|
350
|
+
/** The shared stylePool.none — the spacer cells' style word. */
|
|
351
|
+
emptyStyleId: number;
|
|
352
|
+
/** Column gap from the previous written cell; the first entry's gap is
|
|
353
|
+
* 0 (its absolute column is the run's base). */
|
|
354
|
+
gaps: number[];
|
|
355
|
+
charIdxs: number[];
|
|
356
|
+
word1s: number[];
|
|
357
|
+
/** Absolute column of the first written cell (record time). */
|
|
358
|
+
baseX: number;
|
|
359
|
+
/** Absolute column of the last written cell (record time). */
|
|
360
|
+
lastX: number;
|
|
361
|
+
}
|
|
362
|
+
/** Begin recording a run for the given screen. */
|
|
363
|
+
export declare function createCellRun(screen: Screen): CellRun;
|
|
364
|
+
/** Record the cell the slow path is about to write at column x. */
|
|
365
|
+
export declare function recordCellRunEntry(run: CellRun, screen: Screen, x: number, cell: Cell): void;
|
|
366
|
+
/** Record the deterministic SpacerTail that setCellAt writes after a wide
|
|
367
|
+
* char at column x (only when x < screen.width - 1). */
|
|
368
|
+
export declare function recordSpacerRunEntry(run: CellRun, x: number): void;
|
|
369
|
+
/**
|
|
370
|
+
* Replay a recorded run at (x, y): plain two-word stores, with the damage
|
|
371
|
+
* rect extended over the written span. Mirrors setCellAt's guard-fire
|
|
372
|
+
* conditions exactly — a replay is only valid when none of the three
|
|
373
|
+
* state-dependent fixups (wide-overwrite spacer cleanup, spacer-tail
|
|
374
|
+
* orphan cleanup, wide's next-cell orphan cleanup) would trigger; any
|
|
375
|
+
* other width transition is a plain overwrite. Returns false so the
|
|
376
|
+
* caller falls back to the slow path when a guard WOULD fire.
|
|
377
|
+
*/
|
|
378
|
+
export declare function replayCellRun(screen: Screen, x: number, y: number, run: CellRun): boolean;
|
|
379
|
+
/** Column just past the last written cell — the run's content end. */
|
|
380
|
+
export declare function cellRunSpan(run: CellRun): number;
|
|
342
381
|
/**
|
|
343
382
|
* Replace the styleId of a cell in-place without disturbing char, width,
|
|
344
383
|
* or hyperlink. Preserves empty cells as-is (char stays ' '). Tracks damage
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../src/ink/screen.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../src/ink/screen.ts"],"names":[],"mappings":"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"}
|
package/lib/types/ink/screen.js
CHANGED
|
@@ -721,6 +721,123 @@ export function setCellAt(screen, x, y, cell) {
|
|
|
721
721
|
}
|
|
722
722
|
}
|
|
723
723
|
}
|
|
724
|
+
/** Begin recording a run for the given screen. */
|
|
725
|
+
export function createCellRun(screen) {
|
|
726
|
+
return {
|
|
727
|
+
charPool: screen.charPool,
|
|
728
|
+
emptyStyleId: screen.emptyStyleId,
|
|
729
|
+
gaps: [],
|
|
730
|
+
charIdxs: [],
|
|
731
|
+
word1s: [],
|
|
732
|
+
baseX: -1,
|
|
733
|
+
lastX: -1,
|
|
734
|
+
};
|
|
735
|
+
}
|
|
736
|
+
/** Record the cell the slow path is about to write at column x. */
|
|
737
|
+
export function recordCellRunEntry(run, screen, x, cell) {
|
|
738
|
+
if (run.baseX < 0)
|
|
739
|
+
run.baseX = x;
|
|
740
|
+
run.gaps.push(run.lastX < 0 ? 0 : x - run.lastX);
|
|
741
|
+
run.charIdxs.push(internCharString(screen, cell.char));
|
|
742
|
+
run.word1s.push(packWord1(cell.styleId, internHyperlink(screen, cell.hyperlink), cell.width));
|
|
743
|
+
run.lastX = x;
|
|
744
|
+
}
|
|
745
|
+
/** Record the deterministic SpacerTail that setCellAt writes after a wide
|
|
746
|
+
* char at column x (only when x < screen.width - 1). */
|
|
747
|
+
export function recordSpacerRunEntry(run, x) {
|
|
748
|
+
run.gaps.push(x - run.lastX);
|
|
749
|
+
run.charIdxs.push(SPACER_CHAR_INDEX);
|
|
750
|
+
run.word1s.push(packWord1(run.emptyStyleId, 0, 2 /* CellWidth.SpacerTail */));
|
|
751
|
+
run.lastX = x;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Replay a recorded run at (x, y): plain two-word stores, with the damage
|
|
755
|
+
* rect extended over the written span. Mirrors setCellAt's guard-fire
|
|
756
|
+
* conditions exactly — a replay is only valid when none of the three
|
|
757
|
+
* state-dependent fixups (wide-overwrite spacer cleanup, spacer-tail
|
|
758
|
+
* orphan cleanup, wide's next-cell orphan cleanup) would trigger; any
|
|
759
|
+
* other width transition is a plain overwrite. Returns false so the
|
|
760
|
+
* caller falls back to the slow path when a guard WOULD fire.
|
|
761
|
+
*/
|
|
762
|
+
export function replayCellRun(screen, x, y, run) {
|
|
763
|
+
if (x < 0 || y < 0 || y >= screen.height || x >= screen.width)
|
|
764
|
+
return false;
|
|
765
|
+
// Defensive: an empty run has no cells and no span — its damage math
|
|
766
|
+
// would be NaN. Callers never cache empty runs, but a future one might.
|
|
767
|
+
if (run.gaps.length === 0)
|
|
768
|
+
return false;
|
|
769
|
+
const cells = screen.cells;
|
|
770
|
+
const width = screen.width;
|
|
771
|
+
let ox = x;
|
|
772
|
+
const gaps = run.gaps;
|
|
773
|
+
for (let i = 0; i < gaps.length; i++) {
|
|
774
|
+
ox += gaps[i];
|
|
775
|
+
if (ox >= width)
|
|
776
|
+
return false;
|
|
777
|
+
const ci = ((y * width) + ox) << 1;
|
|
778
|
+
const w1 = run.word1s[i];
|
|
779
|
+
const newW = w1 & WIDTH_MASK;
|
|
780
|
+
const prevW = cells[ci + 1] & WIDTH_MASK;
|
|
781
|
+
if (newW === 0 /* CellWidth.Narrow */) {
|
|
782
|
+
// G1 (prev Wide → narrow overwrite cleans the spacer at x+1) and
|
|
783
|
+
// G2 (prev SpacerTail → clears the orphan wide at x-1) would fire.
|
|
784
|
+
if (prevW !== 0 /* CellWidth.Narrow */)
|
|
785
|
+
return false;
|
|
786
|
+
}
|
|
787
|
+
else if (newW === 1 /* CellWidth.Wide */) {
|
|
788
|
+
// G2: a SpacerTail under a Wide write clears the orphan at x-1.
|
|
789
|
+
if (prevW === 2 /* CellWidth.SpacerTail */)
|
|
790
|
+
return false;
|
|
791
|
+
// G3: the spacer this write puts at x+1 would stomp a Wide cell
|
|
792
|
+
// and needs its orphan cleanup.
|
|
793
|
+
if (ox + 1 < width && (cells[ci + 3] & WIDTH_MASK) === 1 /* CellWidth.Wide */) {
|
|
794
|
+
return false;
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
else {
|
|
798
|
+
// SpacerTail: G1 fires when it overwrites a Wide cell; G2's
|
|
799
|
+
// SpacerHead variant (prev SpacerTail under a non-SpacerTail write)
|
|
800
|
+
// can't occur in a recorded run — SpacerHead is never recorded — but
|
|
801
|
+
// keep the guard honest for that day soft-wrap starts recording it.
|
|
802
|
+
if (prevW === 1 /* CellWidth.Wide */ ||
|
|
803
|
+
(newW !== 2 /* CellWidth.SpacerTail */ && prevW === 2 /* CellWidth.SpacerTail */)) {
|
|
804
|
+
return false;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
cells[ci] = run.charIdxs[i];
|
|
808
|
+
cells[ci + 1] = w1;
|
|
809
|
+
}
|
|
810
|
+
// Damage: the full written span, matching what per-cell updates in
|
|
811
|
+
// setCellAt would have accumulated.
|
|
812
|
+
const firstX = x + gaps[0];
|
|
813
|
+
const endX = ox + 1;
|
|
814
|
+
const damage = screen.damage;
|
|
815
|
+
if (damage !== undefined) {
|
|
816
|
+
const right = damage.x + damage.width;
|
|
817
|
+
if (firstX < damage.x) {
|
|
818
|
+
damage.width += damage.x - firstX;
|
|
819
|
+
damage.x = firstX;
|
|
820
|
+
}
|
|
821
|
+
else if (endX > right) {
|
|
822
|
+
damage.width += endX - right;
|
|
823
|
+
}
|
|
824
|
+
if (y < damage.y) {
|
|
825
|
+
damage.height += damage.y - y;
|
|
826
|
+
damage.y = y;
|
|
827
|
+
}
|
|
828
|
+
else if (y >= damage.y + damage.height) {
|
|
829
|
+
damage.height = y - damage.y + 1;
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
else {
|
|
833
|
+
screen.damage = { x: firstX, y, width: endX - firstX, height: 1 };
|
|
834
|
+
}
|
|
835
|
+
return true;
|
|
836
|
+
}
|
|
837
|
+
/** Column just past the last written cell — the run's content end. */
|
|
838
|
+
export function cellRunSpan(run) {
|
|
839
|
+
return run.lastX - run.baseX + 1;
|
|
840
|
+
}
|
|
724
841
|
/**
|
|
725
842
|
* Replace the styleId of a cell in-place without disturbing char, width,
|
|
726
843
|
* or hyperlink. Preserves empty cells as-is (char stays ' '). Tracks damage
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/ink/terminal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAKtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../../src/ink/terminal.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAKtC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAYtC;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,eAAe,CAAA;IAC1D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,IAAI,OAAO,CAuCtD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI,OAAO,CAwDvD;AAcD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAGnC;AAyBD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAG9C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,WAAW,GAAE,MAAM,GAAG,SAAoC,EAC1D,kBAAkB,GAAE,MAAM,GAAG,SAA4C,GACxE,OAAO,CAOT;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,SAAkC,CAAA;AAEpE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAuBD;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACrB,MAAM,EAAE,QAAQ,CAAA;IAChB,MAAM,EAAE,QAAQ,CAAA;CACjB,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,IAAI,EACV,eAAe,UAAQ,GACtB,IAAI,CAwFN"}
|
|
@@ -2,7 +2,7 @@ import { coerce } from 'semver';
|
|
|
2
2
|
import { appendFileSync } from 'node:fs';
|
|
3
3
|
import { env } from '../utils/env.js';
|
|
4
4
|
import { gte } from '../utils/semver.js';
|
|
5
|
-
import { CURSOR_HOME, cursorMove, cursorTo, ERASE_SCREEN,
|
|
5
|
+
import { CURSOR_HOME, cursorMove, cursorTo, ERASE_SCREEN, eraseLines, SGR_RESET, } from './termio/csi.js';
|
|
6
6
|
import { BSU, ESU, HIDE_CURSOR, SHOW_CURSOR } from './termio/dec.js';
|
|
7
7
|
import { link } from './termio/osc.js';
|
|
8
8
|
/**
|
|
@@ -321,11 +321,19 @@ export function writeDiffToTerminal(terminal, diff, skipSyncMarkers = false) {
|
|
|
321
321
|
// scrollback snapshots (the duplicated whale-logo class of bugs);
|
|
322
322
|
// the old soft clear (CSI n S) PUSHED the live viewport into the
|
|
323
323
|
// scrollback instead, depositing a fresh full-UI copy per reset.
|
|
324
|
+
// Screen-only hard clear: 2J + home, NO 3J. Erasing the scrollback
|
|
325
|
+
// here destroyed the user's entire visible history on every settle
|
|
326
|
+
// shrink (the "context lost / cannot scroll" reports) — the inline
|
|
327
|
+
// transcript IS the scrollback; wiping it to avoid duplicate
|
|
328
|
+
// snapshots is never an acceptable trade. 2J clears the screen for
|
|
329
|
+
// the repaint while everything above the viewport survives.
|
|
330
|
+
// Executed OUTSIDE the DEC 2026 sync block (split begin/end): WT
|
|
331
|
+
// yanks the viewport to top when 2J runs inside a synchronized
|
|
332
|
+
// update (claude-code#35580).
|
|
324
333
|
buffer +=
|
|
325
334
|
(useSync ? ESU : '') +
|
|
326
335
|
SGR_RESET +
|
|
327
336
|
ERASE_SCREEN +
|
|
328
|
-
ERASE_SCROLLBACK +
|
|
329
337
|
CURSOR_HOME +
|
|
330
338
|
(useSync ? BSU : '');
|
|
331
339
|
break;
|
|
@@ -7,7 +7,7 @@ type WrapAnsiOptions = {
|
|
|
7
7
|
* Wrap a string to a maximum column width, preserving ANSI escape sequences.
|
|
8
8
|
*
|
|
9
9
|
* Uses Bun.wrapAnsi when available; otherwise falls back to the wrap-ansi
|
|
10
|
-
* package.
|
|
10
|
+
* package (with the incremental fast path for growing streaming inputs).
|
|
11
11
|
* @param input - the string to wrap.
|
|
12
12
|
* @param columns - the maximum width in columns.
|
|
13
13
|
* @param options - wrap options: hard breaks long words, wordWrap splits on word boundaries, trim strips trailing whitespace.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapAnsi.d.ts","sourceRoot":"","sources":["../../../src/ink/wrapAnsi.ts"],"names":[],"mappings":"AAEA,KAAK,eAAe,GAAG;IACrB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;
|
|
1
|
+
{"version":3,"file":"wrapAnsi.d.ts","sourceRoot":"","sources":["../../../src/ink/wrapAnsi.ts"],"names":[],"mappings":"AAEA,KAAK,eAAe,GAAG;IACrB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAA;AA0DD;;;;;;;;;GASG;AACH,QAAA,MAAM,QAAQ,EAAE,CACd,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,eAAe,KACtB,MAEmB,CAAA;AAExB,OAAO,EAAE,QAAQ,EAAE,CAAA"}
|
|
@@ -2,15 +2,42 @@ import wrapAnsiNpm from 'wrap-ansi';
|
|
|
2
2
|
const wrapAnsiBun = typeof Bun !== 'undefined' && typeof Bun.wrapAnsi === 'function'
|
|
3
3
|
? Bun.wrapAnsi
|
|
4
4
|
: null;
|
|
5
|
+
const SLOT_MIN_LENGTH = 2048;
|
|
6
|
+
let slot = null;
|
|
7
|
+
function slotOptionsApply(options) {
|
|
8
|
+
return options?.hard === true && (options?.trim ?? false) === false;
|
|
9
|
+
}
|
|
10
|
+
function wrapAnsiNpmIncremental(input, columns, options) {
|
|
11
|
+
const slottable = input.length > SLOT_MIN_LENGTH && slotOptionsApply(options);
|
|
12
|
+
if (slottable && slot !== null && slot.columns === columns && input.startsWith(slot.input)) {
|
|
13
|
+
const suffix = input.slice(slot.input.length);
|
|
14
|
+
if (!suffix.includes('\x1b') && !slot.remainder.includes('\x1b')) {
|
|
15
|
+
const tail = wrapAnsiNpm(slot.remainder + suffix, columns, options).split('\n');
|
|
16
|
+
const rows = [...slot.headRows, ...tail];
|
|
17
|
+
slot = { columns, input, headRows: rows.slice(0, -1), remainder: rows[rows.length - 1] ?? '' };
|
|
18
|
+
return rows.join('\n');
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const result = wrapAnsiNpm(input, columns, options);
|
|
22
|
+
if (slottable && !input.includes('\x1b')) {
|
|
23
|
+
const rows = result.split('\n');
|
|
24
|
+
slot = { columns, input, headRows: rows.slice(0, -1), remainder: rows[rows.length - 1] ?? '' };
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
slot = null;
|
|
28
|
+
}
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
5
31
|
/**
|
|
6
32
|
* Wrap a string to a maximum column width, preserving ANSI escape sequences.
|
|
7
33
|
*
|
|
8
34
|
* Uses Bun.wrapAnsi when available; otherwise falls back to the wrap-ansi
|
|
9
|
-
* package.
|
|
35
|
+
* package (with the incremental fast path for growing streaming inputs).
|
|
10
36
|
* @param input - the string to wrap.
|
|
11
37
|
* @param columns - the maximum width in columns.
|
|
12
38
|
* @param options - wrap options: hard breaks long words, wordWrap splits on word boundaries, trim strips trailing whitespace.
|
|
13
39
|
* @returns the wrapped string.
|
|
14
40
|
*/
|
|
15
|
-
const wrapAnsi = wrapAnsiBun ??
|
|
41
|
+
const wrapAnsi = wrapAnsiBun ??
|
|
42
|
+
wrapAnsiNpmIncremental;
|
|
16
43
|
export { wrapAnsi };
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export
|
|
4
|
-
export
|
|
5
|
-
export
|
|
6
|
-
export
|
|
7
|
-
export
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
1
|
+
export { name, apply } from './dsh-adapter/plugin-host.js';
|
|
2
|
+
export type { TuiPluginHost } from './dsh-adapter/plugin-host.js';
|
|
3
|
+
export type { GrantPrincipal, GrantStore } from './dsh-adapter/grants.js';
|
|
4
|
+
export type { HostContract, HostDescriptor, ContractCoordinate, ContractRef, NegotiationDecision, PermissionEntry, PermissionRegistry } from './plugin-spec/types.js';
|
|
5
|
+
export type { TuiPluginStorage, PluginStorageErrorCode, TuiPluginStorageRuntime } from './dsh-adapter/plugin-storage.js';
|
|
6
|
+
export { PluginStorageError, STORAGE_KEY_MAX_LENGTH, STORAGE_MAX_BYTES, STORAGE_MAX_KEYS } from './dsh-adapter/plugin-storage.js';
|
|
7
|
+
export { OBSERVE_CALLBACK_QUEUE_LIMIT, OBSERVE_CALLBACK_TIMEOUT_MS, OBSERVE_CONTENT_MAX_CHARS, OBSERVE_ID_MAX_CHARS, OBSERVE_IMAGE_BASE64_MAX_CHARS, OBSERVE_IMAGE_MAX_BYTES, OBSERVE_SCOPE_MAX_CHARS, OBSERVE_SUMMARY_CELLS, } from './dsh-adapter/message-observer.js';
|
|
8
|
+
export type { MessagesObserveContentBlock, MessagesObserveEnvelope, MessagesObserveListener, MessagesObservePayload, TuiMessageObserverRuntime, } from './dsh-adapter/message-observer.js';
|
|
9
|
+
export type { LedgerEntry, LedgerOperation, LedgerResult, TuiEffectLedgerRuntime } from './dsh-adapter/effect-ledger.js';
|
|
10
|
+
export { COMMAND_ERROR_CODES, hasCommandErrorCode, mapCommandError, withCommandErrorMapping, } from './dsh-adapter/command-errors.js';
|
|
11
|
+
export type { CommandErrorCode, CodedCommandError } from './dsh-adapter/command-errors.js';
|
|
12
|
+
export { DECISION_EVENT_PERMISSIONS, } from './dsh-adapter/decision-guard.js';
|
|
13
|
+
export { DECISION_HANDLER_TIMEOUT_MS, DECISION_TOTAL_TIMEOUT_MS, } from './dsh-adapter/extension-events.js';
|
|
11
14
|
export { DECISION_EVENTS_COORDINATE, TUI_EXTENSION_API_VERSION, TUI_DECISION_EVENT_NAMES, TUI_EXTENSION_PERMISSION_NAMES, createAdmissionCatalog, } from './plugin-spec/tui-extension.js';
|
|
12
|
-
export type { ContractCoordinate, ContractRef, HostContract, HostDescriptor, NegotiationDecision, PermissionEntry, PermissionRegistry, } from './plugin-spec/types.js';
|
|
13
15
|
//# sourceMappingURL=plugin-host.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-host.d.ts","sourceRoot":"","sources":["../../src/plugin-host.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"plugin-host.d.ts","sourceRoot":"","sources":["../../src/plugin-host.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AAC1D,YAAY,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAA;AACjE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAA;AACzE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,kBAAkB,EAAE,WAAW,EAAE,mBAAmB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAA;AACrK,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AACxH,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAIjI,OAAO,EACL,4BAA4B,EAC5B,2BAA2B,EAC3B,yBAAyB,EACzB,oBAAoB,EACpB,8BAA8B,EAC9B,uBAAuB,EACvB,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,mCAAmC,CAAA;AAC1C,YAAY,EACV,2BAA2B,EAC3B,uBAAuB,EACvB,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,mCAAmC,CAAA;AAE1C,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AACxH,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EACf,uBAAuB,GACxB,MAAM,iCAAiC,CAAA;AACxC,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AAK1F,OAAO,EACL,0BAA0B,GAC3B,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,wBAAwB,EACxB,8BAA8B,EAC9B,sBAAsB,GACvB,MAAM,gCAAgC,CAAA"}
|