@visual-z/xeno 0.8.4 → 0.9.1
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 +19 -0
- package/README.md +31 -746
- package/bin/xeno.exe +26 -0
- package/install.cjs +88 -0
- package/package.json +18 -48
- package/docs/app-server.md +0 -115
- package/docs/foundations.md +0 -88
- package/docs/install.md +0 -244
- package/docs/providers.md +0 -172
- package/docs/research/foundation-clients-2026-10-09.md +0 -27
- package/docs/research/foundation-editing-2026-10-09.md +0 -56
- package/docs/research/foundation-network-2026-10-09.md +0 -37
- package/docs/research/foundation-workflow-2026-10-09.md +0 -37
- package/src/apps/acp-server.ts +0 -41
- package/src/apps/agent-profiles.ts +0 -19
- package/src/apps/app-server.ts +0 -30
- package/src/apps/approve.ts +0 -49
- package/src/apps/cli.ts +0 -99
- package/src/apps/commands.ts +0 -319
- package/src/apps/completions.ts +0 -87
- package/src/apps/control-transport.ts +0 -90
- package/src/apps/export-cli.ts +0 -24
- package/src/apps/goal-flow.ts +0 -70
- package/src/apps/image-draft.ts +0 -46
- package/src/apps/input.ts +0 -312
- package/src/apps/model-catalog.ts +0 -69
- package/src/apps/preferences.ts +0 -20
- package/src/apps/project-trust.ts +0 -9
- package/src/apps/provider-connect.ts +0 -346
- package/src/apps/question-ui.ts +0 -27
- package/src/apps/render.ts +0 -181
- package/src/apps/resources.ts +0 -66
- package/src/apps/review.ts +0 -109
- package/src/apps/session-hub.ts +0 -96
- package/src/apps/session-lifecycle.ts +0 -64
- package/src/apps/shell.ts +0 -2071
- package/src/apps/startup-input.ts +0 -135
- package/src/apps/startup.ts +0 -1677
- package/src/apps/ui/app.ts +0 -1818
- package/src/apps/ui/control-model.ts +0 -43
- package/src/apps/ui/extension-host.ts +0 -194
- package/src/apps/ui/image-cache.ts +0 -121
- package/src/apps/ui/palette.ts +0 -88
- package/src/apps/ui/project.ts +0 -127
- package/src/apps/ui/standalone.ts +0 -148
- package/src/apps/ui/status-model.ts +0 -68
- package/src/apps/ui/surface.ts +0 -91
- package/src/apps/ui/theme.ts +0 -86
- package/src/apps/update-check.ts +0 -112
- package/src/apps/workflow.ts +0 -58
- package/src/core/acceptance.ts +0 -139
- package/src/core/action-defaults.ts +0 -58
- package/src/core/activity-status.ts +0 -52
- package/src/core/agent-profile.ts +0 -130
- package/src/core/attachment-input.ts +0 -17
- package/src/core/blind-checks.ts +0 -72
- package/src/core/boundary.ts +0 -174
- package/src/core/branch-receipt.ts +0 -26
- package/src/core/catalog-merge.ts +0 -19
- package/src/core/checkpoints.ts +0 -85
- package/src/core/churn.ts +0 -61
- package/src/core/command-artifacts.ts +0 -94
- package/src/core/command-contract.ts +0 -151
- package/src/core/completion-action.ts +0 -20
- package/src/core/completion-review.ts +0 -98
- package/src/core/context-detail.ts +0 -37
- package/src/core/context-policy.ts +0 -133
- package/src/core/context-window.ts +0 -54
- package/src/core/continuation.ts +0 -130
- package/src/core/control-protocol.ts +0 -69
- package/src/core/control-view.ts +0 -39
- package/src/core/cycle.ts +0 -17
- package/src/core/data-query.ts +0 -201
- package/src/core/deadline.ts +0 -40
- package/src/core/derive.ts +0 -516
- package/src/core/draft-images.ts +0 -56
- package/src/core/edit-plan.ts +0 -200
- package/src/core/environment.ts +0 -181
- package/src/core/event-validation.ts +0 -220
- package/src/core/events.ts +0 -670
- package/src/core/evidence-ladder.ts +0 -62
- package/src/core/evidence-links.ts +0 -68
- package/src/core/evidence.ts +0 -240
- package/src/core/execution.ts +0 -18
- package/src/core/exhaustive.ts +0 -18
- package/src/core/export.ts +0 -179
- package/src/core/extension-flags.ts +0 -14
- package/src/core/external-effects.ts +0 -488
- package/src/core/failure-recovery.ts +0 -173
- package/src/core/file-precondition.ts +0 -78
- package/src/core/file-references.ts +0 -35
- package/src/core/frontmatter.ts +0 -213
- package/src/core/git-status.ts +0 -29
- package/src/core/goal-view.ts +0 -64
- package/src/core/goal.ts +0 -200
- package/src/core/handoff.ts +0 -479
- package/src/core/history-query.ts +0 -139
- package/src/core/history.ts +0 -237
- package/src/core/image-limits.ts +0 -72
- package/src/core/images.ts +0 -46
- package/src/core/integration-health.ts +0 -34
- package/src/core/json-event.ts +0 -131
- package/src/core/json-pointer.ts +0 -46
- package/src/core/keymap.ts +0 -153
- package/src/core/lsp-framing.ts +0 -34
- package/src/core/mcp-config.ts +0 -68
- package/src/core/model-picker.ts +0 -64
- package/src/core/model-preferences.ts +0 -28
- package/src/core/model-replay.ts +0 -22
- package/src/core/model-scope.ts +0 -53
- package/src/core/note-guidance.ts +0 -34
- package/src/core/oauth-fields.ts +0 -44
- package/src/core/observation-view.ts +0 -152
- package/src/core/outcome.ts +0 -44
- package/src/core/overflow.ts +0 -59
- package/src/core/packages.ts +0 -47
- package/src/core/patch.ts +0 -130
- package/src/core/path-suggestions.ts +0 -59
- package/src/core/permissions.ts +0 -410
- package/src/core/process-receipt.ts +0 -105
- package/src/core/process-state.ts +0 -37
- package/src/core/program-status.ts +0 -40
- package/src/core/progress.ts +0 -150
- package/src/core/project.ts +0 -431
- package/src/core/prompt-policy.ts +0 -46
- package/src/core/prompts.ts +0 -111
- package/src/core/question.ts +0 -94
- package/src/core/queue.ts +0 -78
- package/src/core/read-bounds.ts +0 -24
- package/src/core/read-observation.ts +0 -106
- package/src/core/recovery-sources.ts +0 -74
- package/src/core/regex-dialect.ts +0 -25
- package/src/core/request-budget.ts +0 -23
- package/src/core/request-progress.ts +0 -87
- package/src/core/request-state.ts +0 -273
- package/src/core/resource-selection.ts +0 -36
- package/src/core/response-recovery.ts +0 -59
- package/src/core/resume.ts +0 -59
- package/src/core/review.ts +0 -68
- package/src/core/ripgrep-release.ts +0 -64
- package/src/core/runtime-target.ts +0 -94
- package/src/core/scheduling.ts +0 -8
- package/src/core/search-observation.ts +0 -97
- package/src/core/secrets.ts +0 -188
- package/src/core/session-archive.ts +0 -4
- package/src/core/session-browser.ts +0 -82
- package/src/core/session-entry.ts +0 -61
- package/src/core/session-exit.ts +0 -42
- package/src/core/session-format.ts +0 -169
- package/src/core/session-position.ts +0 -26
- package/src/core/session-tree.ts +0 -147
- package/src/core/settings.ts +0 -192
- package/src/core/skills.ts +0 -165
- package/src/core/sql-query.ts +0 -211
- package/src/core/stall.ts +0 -128
- package/src/core/stop-report.ts +0 -68
- package/src/core/text-normalize.ts +0 -81
- package/src/core/theme.ts +0 -166
- package/src/core/thinking.ts +0 -26
- package/src/core/tokens.ts +0 -151
- package/src/core/tool-contract.ts +0 -153
- package/src/core/tool-discovery.ts +0 -87
- package/src/core/tool-failure.ts +0 -81
- package/src/core/tool-input.ts +0 -44
- package/src/core/transcript.ts +0 -108
- package/src/core/tui-mode.ts +0 -29
- package/src/core/update-check.ts +0 -157
- package/src/core/version.ts +0 -55
- package/src/core/web-content.ts +0 -80
- package/src/core/work-state.ts +0 -154
- package/src/core/workflow-mode.ts +0 -34
- package/src/core/working-set.ts +0 -119
- package/src/core/yaml.ts +0 -282
- package/src/runtime/acp-agent.ts +0 -289
- package/src/runtime/agent-profiles.ts +0 -21
- package/src/runtime/auth.ts +0 -367
- package/src/runtime/blind-check.ts +0 -36
- package/src/runtime/branch-jobs.ts +0 -36
- package/src/runtime/catalog.ts +0 -285
- package/src/runtime/clipboard.ts +0 -125
- package/src/runtime/command-artifacts.ts +0 -64
- package/src/runtime/connection-reuse.ts +0 -40
- package/src/runtime/control-client.ts +0 -149
- package/src/runtime/control-connection.ts +0 -139
- package/src/runtime/counter-check.ts +0 -74
- package/src/runtime/environment-tools.ts +0 -60
- package/src/runtime/evidence-notes.ts +0 -35
- package/src/runtime/exec-sessions.ts +0 -456
- package/src/runtime/execution-control.ts +0 -40
- package/src/runtime/extension-loader.ts +0 -37
- package/src/runtime/extension-ui.ts +0 -47
- package/src/runtime/extensions.ts +0 -370
- package/src/runtime/formatter-tool.ts +0 -38
- package/src/runtime/formatter.ts +0 -50
- package/src/runtime/foundation.ts +0 -116
- package/src/runtime/history-cache.ts +0 -57
- package/src/runtime/history-tools.ts +0 -168
- package/src/runtime/images.ts +0 -80
- package/src/runtime/integrations.ts +0 -216
- package/src/runtime/loop.ts +0 -3108
- package/src/runtime/lsp-client.ts +0 -201
- package/src/runtime/mcp-client.ts +0 -264
- package/src/runtime/mcp-oauth.ts +0 -168
- package/src/runtime/mcp-schema.ts +0 -51
- package/src/runtime/model-config.ts +0 -232
- package/src/runtime/model-data.LICENSE +0 -27
- package/src/runtime/model-data.ts +0 -21
- package/src/runtime/model-discovery.ts +0 -208
- package/src/runtime/model-replay.ts +0 -10
- package/src/runtime/model-scope.ts +0 -20
- package/src/runtime/model-sources.ts +0 -151
- package/src/runtime/model.ts +0 -686
- package/src/runtime/models-fetch.ts +0 -57
- package/src/runtime/oauth-device.ts +0 -86
- package/src/runtime/oauth.ts +0 -853
- package/src/runtime/open-image.ts +0 -42
- package/src/runtime/openai-responses.ts +0 -304
- package/src/runtime/openai.ts +0 -697
- package/src/runtime/output-schema.ts +0 -26
- package/src/runtime/package-manager.ts +0 -125
- package/src/runtime/patch-tool.ts +0 -38
- package/src/runtime/permission-resources.ts +0 -18
- package/src/runtime/pi-provider.ts +0 -423
- package/src/runtime/program-status.ts +0 -38
- package/src/runtime/progress.ts +0 -26
- package/src/runtime/provider-access.ts +0 -21
- package/src/runtime/provider-connect.ts +0 -109
- package/src/runtime/provider-presets.ts +0 -98
- package/src/runtime/provider-protocols.ts +0 -29
- package/src/runtime/provider-request.ts +0 -87
- package/src/runtime/provider-tool-policy.ts +0 -33
- package/src/runtime/provider.ts +0 -580
- package/src/runtime/question-tool.ts +0 -62
- package/src/runtime/retry.ts +0 -447
- package/src/runtime/review-tool.ts +0 -48
- package/src/runtime/rich-text.ts +0 -36
- package/src/runtime/runtime-target.ts +0 -149
- package/src/runtime/secrets.ts +0 -79
- package/src/runtime/self-update.ts +0 -74
- package/src/runtime/session-control.ts +0 -265
- package/src/runtime/session-hub.ts +0 -85
- package/src/runtime/stream-idle.ts +0 -80
- package/src/runtime/tool-broker.ts +0 -137
- package/src/runtime/tool-discovery.ts +0 -58
- package/src/runtime/tool-queue.ts +0 -77
- package/src/runtime/tools.ts +0 -1820
- package/src/runtime/turn-effects.ts +0 -31
- package/src/runtime/update-check.ts +0 -48
- package/src/runtime/usage.ts +0 -253
- package/src/runtime/version.ts +0 -12
- package/src/runtime/web-http.ts +0 -56
- package/src/runtime/web-tools.ts +0 -88
- package/src/runtime/working-notes.ts +0 -60
- package/src/runtime/workspace-lifecycle.ts +0 -141
- package/src/store/acceptance.ts +0 -15
- package/src/store/agent-profile-files.ts +0 -13
- package/src/store/atomic.ts +0 -31
- package/src/store/auth-store.ts +0 -50
- package/src/store/blind-checks.ts +0 -32
- package/src/store/blobs.ts +0 -143
- package/src/store/checkpoint-history.ts +0 -32
- package/src/store/command-artifacts.ts +0 -96
- package/src/store/command.ts +0 -111
- package/src/store/config.ts +0 -69
- package/src/store/context-files.ts +0 -436
- package/src/store/file-checkpoints.ts +0 -108
- package/src/store/file-index.ts +0 -174
- package/src/store/foundation-config.ts +0 -24
- package/src/store/git-checkpoints.ts +0 -67
- package/src/store/git-status.ts +0 -15
- package/src/store/history-search.ts +0 -19
- package/src/store/log.ts +0 -725
- package/src/store/lsp-document.ts +0 -30
- package/src/store/mcp-credentials.ts +0 -85
- package/src/store/models.ts +0 -60
- package/src/store/observations.ts +0 -224
- package/src/store/packages.ts +0 -98
- package/src/store/patch.ts +0 -92
- package/src/store/permission-paths.ts +0 -34
- package/src/store/process-receipts.ts +0 -34
- package/src/store/query-source.ts +0 -49
- package/src/store/recovery.ts +0 -44
- package/src/store/replay.ts +0 -76
- package/src/store/resource-index.ts +0 -170
- package/src/store/resources.ts +0 -285
- package/src/store/restore.ts +0 -110
- package/src/store/review.ts +0 -109
- package/src/store/runtime-target.ts +0 -64
- package/src/store/search.ts +0 -728
- package/src/store/secrets.ts +0 -44
- package/src/store/serial.ts +0 -13
- package/src/store/session-archive.ts +0 -165
- package/src/store/session-browser.ts +0 -68
- package/src/store/session-position.ts +0 -27
- package/src/store/sessions.ts +0 -525
- package/src/store/source-cancellation.ts +0 -6
- package/src/store/tool-binaries.ts +0 -90
- package/src/store/trust.ts +0 -82
- package/src/store/update-cache.ts +0 -36
- package/src/store/user-settings.ts +0 -30
- package/src/store/workspace-clone.ts +0 -42
- package/src/store/workspace-observation.ts +0 -113
- package/src/store/workspace.ts +0 -115
- package/src/store/worktree.ts +0 -278
- package/src/tui/ansi-spans.ts +0 -126
- package/src/tui/diff.ts +0 -160
- package/src/tui/exhaustive.ts +0 -14
- package/src/tui/fuzzy.ts +0 -75
- package/src/tui/style.ts +0 -208
- package/src/tui/ui/atomic-draft.ts +0 -121
- package/src/tui/ui/branch-panel.ts +0 -47
- package/src/tui/ui/canvas.ts +0 -96
- package/src/tui/ui/colors.ts +0 -70
- package/src/tui/ui/composer.ts +0 -199
- package/src/tui/ui/control-panel.ts +0 -25
- package/src/tui/ui/control-sidebar.ts +0 -49
- package/src/tui/ui/dialog.ts +0 -398
- package/src/tui/ui/draft.ts +0 -23
- package/src/tui/ui/duration.ts +0 -16
- package/src/tui/ui/edge.ts +0 -186
- package/src/tui/ui/image-size.ts +0 -44
- package/src/tui/ui/ink.ts +0 -210
- package/src/tui/ui/items.ts +0 -42
- package/src/tui/ui/keys.ts +0 -40
- package/src/tui/ui/layout.ts +0 -74
- package/src/tui/ui/list-model.ts +0 -86
- package/src/tui/ui/list-view.ts +0 -172
- package/src/tui/ui/mascot.ts +0 -67
- package/src/tui/ui/messages.ts +0 -518
- package/src/tui/ui/motion.ts +0 -28
- package/src/tui/ui/paths.ts +0 -10
- package/src/tui/ui/pictures.ts +0 -108
- package/src/tui/ui/prompt-history.ts +0 -60
- package/src/tui/ui/screen.ts +0 -579
- package/src/tui/ui/status.ts +0 -403
- package/src/tui/ui/styled.ts +0 -85
- package/src/tui/ui/tool-card.ts +0 -150
- package/src/tui/width.ts +0 -567
- package/src/vendor/pi-rich/LICENSE.upstream +0 -21
- package/src/vendor/pi-rich/UPSTREAM.json +0 -17
- package/src/vendor/pi-rich/clipboard-command.ts +0 -44
- package/src/vendor/pi-rich/exif-orientation.ts +0 -182
- package/src/vendor/pi-rich/html.ts +0 -51
- package/src/vendor/pi-rich/image-convert.ts +0 -49
- package/src/vendor/pi-rich/image-resize-core.ts +0 -164
- package/src/vendor/pi-rich/image-resize-worker.ts +0 -42
- package/src/vendor/pi-rich/image-resize.ts +0 -123
- package/src/vendor/pi-rich/mime.ts +0 -116
- package/src/vendor/pi-rich/photon.ts +0 -139
- package/src/vendor/pi-rich/syntax-highlight.ts +0 -214
package/src/tui/style.ts
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SGR composition for markdown.
|
|
3
|
-
*
|
|
4
|
-
* Terminals do not keep attributes across a newline, and the differential
|
|
5
|
-
* renderer rewrites by line (`src/tui/render.ts`). A wrap-the-whole-string
|
|
6
|
-
* helper would leave only the first row with an open code, so a later
|
|
7
|
-
* rewrite of row 2 paints in the default style. Every output row therefore
|
|
8
|
-
* carries its own open and close.
|
|
9
|
-
*
|
|
10
|
-
* Identity emits no ESC bytes: `-p` and pipes parse the transcript, and a
|
|
11
|
-
* CSI in that stream is a parse error waiting for a script (D17, same
|
|
12
|
-
* reason `createPalette(false)` exists).
|
|
13
|
-
*
|
|
14
|
-
* Colours are data: createStyle reads token → SGR params. Hard-coding a
|
|
15
|
-
* CSI colour here would be a colour the theme cannot reach.
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
export interface Attrs {
|
|
19
|
-
readonly bold: boolean;
|
|
20
|
-
readonly italic: boolean;
|
|
21
|
-
readonly dim: boolean;
|
|
22
|
-
readonly code: boolean;
|
|
23
|
-
readonly heading: boolean;
|
|
24
|
-
readonly link: boolean;
|
|
25
|
-
/** Optional: tool diffs and exit codes. Absent keeps markdown Attrs unchanged. */
|
|
26
|
-
readonly red?: boolean;
|
|
27
|
-
readonly green?: boolean;
|
|
28
|
-
readonly yellow?: boolean;
|
|
29
|
-
readonly thinking?: boolean;
|
|
30
|
-
readonly tool?: boolean;
|
|
31
|
-
readonly result?: boolean;
|
|
32
|
-
readonly error?: boolean;
|
|
33
|
-
readonly status?: boolean;
|
|
34
|
-
readonly prompt?: boolean;
|
|
35
|
-
readonly selected?: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export const PLAIN_ATTRS: Attrs = {
|
|
39
|
-
bold: false,
|
|
40
|
-
italic: false,
|
|
41
|
-
dim: false,
|
|
42
|
-
code: false,
|
|
43
|
-
heading: false,
|
|
44
|
-
link: false,
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
export interface Style {
|
|
48
|
-
open(attrs: Attrs): string;
|
|
49
|
-
close(attrs: Attrs): string;
|
|
50
|
-
token?(name: string, text: string): string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Token → SGR colour params. Same names as core/theme.ts; duplicated so
|
|
55
|
-
* tui never imports core. Empty string is the terminal default.
|
|
56
|
-
*/
|
|
57
|
-
export type ColorTokens = {
|
|
58
|
-
readonly text: string;
|
|
59
|
-
readonly thinkingText: string;
|
|
60
|
-
readonly toolTitle: string;
|
|
61
|
-
readonly toolOutput: string;
|
|
62
|
-
readonly error: string;
|
|
63
|
-
readonly toolDiffAdded: string;
|
|
64
|
-
readonly toolDiffRemoved: string;
|
|
65
|
-
readonly status: string;
|
|
66
|
-
readonly prompt: string;
|
|
67
|
-
readonly selectedBg: string;
|
|
68
|
-
readonly muted: string;
|
|
69
|
-
readonly warning: string;
|
|
70
|
-
readonly mdHeading: string;
|
|
71
|
-
readonly mdCode: string;
|
|
72
|
-
readonly mdLink: string;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Must stay in lockstep with core/theme.ts dark builtin: terminal slots only,
|
|
77
|
-
* no truecolor, no background, no SGR faint for muted text.
|
|
78
|
-
*/
|
|
79
|
-
export const DEFAULT_COLORS: ColorTokens = {
|
|
80
|
-
"text": "",
|
|
81
|
-
"thinkingText": "95",
|
|
82
|
-
"toolTitle": "",
|
|
83
|
-
"toolOutput": "37",
|
|
84
|
-
"error": "91",
|
|
85
|
-
"toolDiffAdded": "92",
|
|
86
|
-
"toolDiffRemoved": "91",
|
|
87
|
-
"status": "37",
|
|
88
|
-
"prompt": "",
|
|
89
|
-
"selectedBg": "",
|
|
90
|
-
"muted": "37",
|
|
91
|
-
"warning": "93",
|
|
92
|
-
"mdHeading": "94",
|
|
93
|
-
"mdCode": "96",
|
|
94
|
-
"mdLink": "94"
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
function anyAttr(a: Attrs, color: string): boolean {
|
|
98
|
-
return (
|
|
99
|
-
a.bold ||
|
|
100
|
-
a.italic ||
|
|
101
|
-
a.dim ||
|
|
102
|
-
a.code ||
|
|
103
|
-
a.heading ||
|
|
104
|
-
a.link ||
|
|
105
|
-
a.red === true ||
|
|
106
|
-
a.green === true ||
|
|
107
|
-
a.yellow === true ||
|
|
108
|
-
a.thinking === true ||
|
|
109
|
-
a.tool === true ||
|
|
110
|
-
a.result === true ||
|
|
111
|
-
a.error === true ||
|
|
112
|
-
a.status === true ||
|
|
113
|
-
a.prompt === true ||
|
|
114
|
-
a.selected === true ||
|
|
115
|
-
color.length > 0
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function pickColor(attrs: Attrs, colors: ColorTokens): string {
|
|
120
|
-
if (attrs.selected === true) return colors.selectedBg;
|
|
121
|
-
if (attrs.prompt === true) return colors.prompt;
|
|
122
|
-
if (attrs.status === true) return colors.status;
|
|
123
|
-
if (attrs.thinking === true) return colors.thinkingText;
|
|
124
|
-
if (attrs.error === true) return colors.error;
|
|
125
|
-
if (attrs.red === true) return colors.toolDiffRemoved;
|
|
126
|
-
if (attrs.green === true) return colors.toolDiffAdded;
|
|
127
|
-
if (attrs.yellow === true) return colors.warning;
|
|
128
|
-
if (attrs.tool === true) return colors.toolTitle;
|
|
129
|
-
if (attrs.result === true) return colors.toolOutput;
|
|
130
|
-
if (attrs.code) return colors.mdCode;
|
|
131
|
-
if (attrs.heading) return colors.mdHeading;
|
|
132
|
-
if (attrs.link) return colors.mdLink;
|
|
133
|
-
if (attrs.dim) return colors.muted;
|
|
134
|
-
return colors.text;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/** Full reset, not a stacked 22/23/24. Nested closes would drop a wrapping attr on wrap. */
|
|
138
|
-
const RESET = "\x1b[0m";
|
|
139
|
-
|
|
140
|
-
export const IDENTITY: Style = {
|
|
141
|
-
open: () => "",
|
|
142
|
-
close: () => "",
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Build a Style from theme tokens. `enabled` is the NO_COLOR / non-tty gate:
|
|
147
|
-
* a themed Style that still emits ESC in a pipe is the same class of bug as
|
|
148
|
-
* createPalette(true) on stdout that is not a tty.
|
|
149
|
-
*/
|
|
150
|
-
export function createStyle(colors: { readonly [token: string]: string }, enabled = true): Style {
|
|
151
|
-
if (!enabled) return IDENTITY;
|
|
152
|
-
const tokens: ColorTokens = {
|
|
153
|
-
text: colors["text"] ?? "",
|
|
154
|
-
thinkingText: colors["thinkingText"] ?? "",
|
|
155
|
-
toolTitle: colors["toolTitle"] ?? "",
|
|
156
|
-
toolOutput: colors["toolOutput"] ?? "",
|
|
157
|
-
error: colors["error"] ?? "",
|
|
158
|
-
toolDiffAdded: colors["toolDiffAdded"] ?? "",
|
|
159
|
-
toolDiffRemoved: colors["toolDiffRemoved"] ?? "",
|
|
160
|
-
status: colors["status"] ?? "",
|
|
161
|
-
prompt: colors["prompt"] ?? "",
|
|
162
|
-
selectedBg: colors["selectedBg"] ?? "",
|
|
163
|
-
muted: colors["muted"] ?? "",
|
|
164
|
-
warning: colors["warning"] ?? "",
|
|
165
|
-
mdHeading: colors["mdHeading"] ?? "",
|
|
166
|
-
mdCode: colors["mdCode"] ?? "",
|
|
167
|
-
mdLink: colors["mdLink"] ?? "",
|
|
168
|
-
};
|
|
169
|
-
return {
|
|
170
|
-
token(name, text) {
|
|
171
|
-
const color = colors[name];
|
|
172
|
-
return color ? `\x1b[${color}m${text}${RESET}` : text;
|
|
173
|
-
},
|
|
174
|
-
open(attrs) {
|
|
175
|
-
const color = pickColor(attrs, tokens);
|
|
176
|
-
if (!anyAttr(attrs, color)) return "";
|
|
177
|
-
const params: string[] = [];
|
|
178
|
-
if (attrs.bold || attrs.heading) params.push("1");
|
|
179
|
-
if (attrs.italic) params.push("3");
|
|
180
|
-
if (attrs.link) params.push("4");
|
|
181
|
-
if (color.length > 0) params.push(...color.split(";"));
|
|
182
|
-
const dim = attrs.dim ? "\x1b[2m" : "";
|
|
183
|
-
return dim + (params.length > 0 ? `\x1b[${params.join(";")}m` : "");
|
|
184
|
-
},
|
|
185
|
-
close(attrs) {
|
|
186
|
-
const color = pickColor(attrs, tokens);
|
|
187
|
-
return anyAttr(attrs, color) ? RESET : "";
|
|
188
|
-
},
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
export const ANSI: Style = createStyle(DEFAULT_COLORS);
|
|
193
|
-
|
|
194
|
-
export function withDim(base: Style): Style {
|
|
195
|
-
return {
|
|
196
|
-
open(attrs) {
|
|
197
|
-
return base.open({ ...attrs, dim: true });
|
|
198
|
-
},
|
|
199
|
-
close(attrs) {
|
|
200
|
-
return base.close({ ...attrs, dim: true });
|
|
201
|
-
},
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export function paint(text: string, attrs: Attrs, style: Style): string {
|
|
206
|
-
if (text.length === 0) return text;
|
|
207
|
-
return style.open(attrs) + text + style.close(attrs);
|
|
208
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { TextareaRenderable, type OptimizedBuffer, type KeyEvent } from "@opentui/core";
|
|
2
|
-
|
|
3
|
-
/** D20: the native editor owns text and undo; this adapter only protects registered ASCII tokens.
|
|
4
|
-
* Offsets in OpenTUI are terminal cells, while app projections use UTF-16. Resolve token starts
|
|
5
|
-
* through the native buffer, so wide glyphs, combining marks, tabs and newlines stay its concern.
|
|
6
|
-
* Native virtual extmarks in 0.5.14 subtract one on left navigation and do not expand word or
|
|
7
|
-
* selection deletion; use one range policy for every edit rather than patching their internals.
|
|
8
|
-
*/
|
|
9
|
-
export interface DraftAtom { readonly start: number; readonly end: number }
|
|
10
|
-
|
|
11
|
-
export class AtomicDraftArea extends TextareaRenderable {
|
|
12
|
-
atoms: ((text: string) => readonly DraftAtom[]) | undefined;
|
|
13
|
-
onRendered: (() => void) | undefined;
|
|
14
|
-
private killed = "";
|
|
15
|
-
|
|
16
|
-
get textCursor(): number { return this.editBuffer.getTextRange(0, this.cursorOffset).length; }
|
|
17
|
-
|
|
18
|
-
private ranges(): DraftAtom[] {
|
|
19
|
-
const text = this.plainText;
|
|
20
|
-
return (this.atoms?.(text) ?? []).map(atom => {
|
|
21
|
-
// Every token starts with one ASCII character. The first native prefix containing it
|
|
22
|
-
// ends exactly one cell after its start, irrespective of the preceding Unicode text.
|
|
23
|
-
let low = 0, high = text.length * Math.max(2, this.editBuffer.getTabWidth()) + 1;
|
|
24
|
-
while (low < high) {
|
|
25
|
-
const middle = Math.floor((low + high) / 2);
|
|
26
|
-
if (this.editBuffer.getTextRange(0, middle).length > atom.start) high = middle;
|
|
27
|
-
else low = middle + 1;
|
|
28
|
-
}
|
|
29
|
-
const start = Math.max(0, low - 1);
|
|
30
|
-
return { start, end: start + atom.end - atom.start };
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
private snap(direction = 0): void {
|
|
35
|
-
if (this.hasSelection()) return;
|
|
36
|
-
const cursor = this.cursorOffset;
|
|
37
|
-
const atom = this.ranges().find(range => cursor > range.start && cursor < range.end);
|
|
38
|
-
if (!atom) return;
|
|
39
|
-
this.editorView.setCursorByOffset(direction < 0 ? atom.start : direction > 0 ? atom.end :
|
|
40
|
-
cursor - atom.start < atom.end - cursor ? atom.start : atom.end);
|
|
41
|
-
this.requestRender();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
private move(action: () => boolean, direction: number): boolean {
|
|
45
|
-
const result = action(); this.snap(direction); return result;
|
|
46
|
-
}
|
|
47
|
-
override moveCursorLeft(options?: { select?: boolean }): boolean { return this.move(() => super.moveCursorLeft(options), -1); }
|
|
48
|
-
override moveCursorRight(options?: { select?: boolean }): boolean { return this.move(() => super.moveCursorRight(options), 1); }
|
|
49
|
-
override moveCursorUp(options?: { select?: boolean }): boolean { return this.move(() => super.moveCursorUp(options), 0); }
|
|
50
|
-
override moveCursorDown(options?: { select?: boolean }): boolean { return this.move(() => super.moveCursorDown(options), 0); }
|
|
51
|
-
override moveWordBackward(options?: { select?: boolean }): boolean { return this.move(() => super.moveWordBackward(options), -1); }
|
|
52
|
-
override moveWordForward(options?: { select?: boolean }): boolean { return this.move(() => super.moveWordForward(options), 1); }
|
|
53
|
-
override gotoVisualLineHome(options?: { select?: boolean }): boolean { return this.move(() => super.gotoVisualLineHome(options), -1); }
|
|
54
|
-
override gotoVisualLineEnd(options?: { select?: boolean }): boolean { return this.move(() => super.gotoVisualLineEnd(options), 1); }
|
|
55
|
-
override setCursor(row: number, col: number): void { super.setCursor(row, col); this.snap(); }
|
|
56
|
-
|
|
57
|
-
private erase(start: number, end: number, kill = false): boolean {
|
|
58
|
-
if (start > end) [start, end] = [end, start];
|
|
59
|
-
if (start === end) return true;
|
|
60
|
-
for (const atom of this.ranges()) {
|
|
61
|
-
if (atom.start < end && atom.end > start) { start = Math.min(start, atom.start); end = Math.max(end, atom.end); }
|
|
62
|
-
}
|
|
63
|
-
if (kill) this.killed = this.editBuffer.getTextRange(start, end);
|
|
64
|
-
const a = this.editBuffer.offsetToPosition(start), b = this.editBuffer.offsetToPosition(end);
|
|
65
|
-
if (!a || !b) return false;
|
|
66
|
-
this.clearSelection();
|
|
67
|
-
this.editBuffer.deleteRange(a.row, a.col, b.row, b.col);
|
|
68
|
-
this.requestRender();
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
override deleteSelection(): boolean {
|
|
72
|
-
const selection = this.getSelection();
|
|
73
|
-
return selection ? this.erase(selection.start, selection.end) : false;
|
|
74
|
-
}
|
|
75
|
-
override deleteCharBackward(): boolean {
|
|
76
|
-
if (this.hasSelection()) return this.deleteSelection();
|
|
77
|
-
const atom = this.ranges().find(range => this.cursorOffset > range.start && this.cursorOffset <= range.end);
|
|
78
|
-
return atom ? this.erase(atom.start, atom.end) : super.deleteCharBackward();
|
|
79
|
-
}
|
|
80
|
-
override deleteChar(): boolean {
|
|
81
|
-
if (this.hasSelection()) return this.deleteSelection();
|
|
82
|
-
const atom = this.ranges().find(range => this.cursorOffset >= range.start && this.cursorOffset < range.end);
|
|
83
|
-
return atom ? this.erase(atom.start, atom.end) : super.deleteChar();
|
|
84
|
-
}
|
|
85
|
-
override deleteWordBackward(): boolean {
|
|
86
|
-
if (this.hasSelection()) return this.deleteSelection();
|
|
87
|
-
return this.erase(this.editBuffer.getPrevWordBoundary().offset, this.cursorOffset, true);
|
|
88
|
-
}
|
|
89
|
-
override deleteWordForward(): boolean {
|
|
90
|
-
if (this.hasSelection()) return this.deleteSelection();
|
|
91
|
-
return this.erase(this.cursorOffset, this.editBuffer.getNextWordBoundary().offset, true);
|
|
92
|
-
}
|
|
93
|
-
override deleteToLineStart(): boolean {
|
|
94
|
-
const cursor = this.editBuffer.getCursorPosition();
|
|
95
|
-
return cursor.col ? this.erase(this.editBuffer.getLineStartOffset(cursor.row), cursor.offset, true) : super.deleteToLineStart();
|
|
96
|
-
}
|
|
97
|
-
override deleteToLineEnd(): boolean {
|
|
98
|
-
const end = this.editBuffer.getEOL().offset;
|
|
99
|
-
return end > this.cursorOffset ? this.erase(this.cursorOffset, end, true) : super.deleteToLineEnd();
|
|
100
|
-
}
|
|
101
|
-
override insertText(text: string): void {
|
|
102
|
-
if (this.hasSelection()) this.deleteSelection();
|
|
103
|
-
this.snap(); super.insertText(text);
|
|
104
|
-
}
|
|
105
|
-
override insertChar(char: string): void {
|
|
106
|
-
if (this.hasSelection()) this.deleteSelection();
|
|
107
|
-
this.snap(); super.insertChar(char);
|
|
108
|
-
}
|
|
109
|
-
override newLine(): boolean {
|
|
110
|
-
if (this.hasSelection()) this.deleteSelection();
|
|
111
|
-
this.snap(); return super.newLine();
|
|
112
|
-
}
|
|
113
|
-
override handleKeyPress(event: KeyEvent): boolean {
|
|
114
|
-
if (event.ctrl && event.name === "y" && this.killed) { this.insertText(this.killed); return true; }
|
|
115
|
-
return super.handleKeyPress(event);
|
|
116
|
-
}
|
|
117
|
-
clearKilledText(): void { this.killed = ""; }
|
|
118
|
-
override render(buffer: OptimizedBuffer, deltaTime: number): void {
|
|
119
|
-
this.snap(); super.render(buffer, deltaTime); this.onRendered?.();
|
|
120
|
-
}
|
|
121
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The rows under the input box, one per unresolved branch (feat-branch-panel).
|
|
3
|
-
* View-only: the controller owns which branches exist and what keys do (D20).
|
|
4
|
-
* Claude Code's precedent: background subagents sit below the prompt, ↑/↓
|
|
5
|
-
* select, Enter opens, x stops, Esc returns to the prompt.
|
|
6
|
-
*/
|
|
7
|
-
import type { Line } from "./status.ts";
|
|
8
|
-
import type { Seg } from "./edge.ts";
|
|
9
|
-
|
|
10
|
-
export type BranchRowState = "running" | "done" | "stopped" | "failed" | "cancelled" | "unknown";
|
|
11
|
-
export interface BranchRow { readonly node: number; readonly purpose: string; readonly state: BranchRowState }
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Rows shown before the rest fold into "+N more". Assumed, not measured: three
|
|
15
|
-
* keeps the transcript in view on a 24-row terminal; more branches than that
|
|
16
|
-
* at once is rare because branch capacity is itself small.
|
|
17
|
-
*/
|
|
18
|
-
export const BRANCH_ROWS = 3;
|
|
19
|
-
|
|
20
|
-
const MARK: Record<BranchRowState, Seg> = {
|
|
21
|
-
running: { text: "●", role: "accent" },
|
|
22
|
-
done: { text: "✓", role: "success" },
|
|
23
|
-
stopped: { text: "◆", role: "warning" },
|
|
24
|
-
failed: { text: "✗", role: "error" },
|
|
25
|
-
cancelled: { text: "■", role: "muted" },
|
|
26
|
-
unknown: { text: "?", role: "muted" },
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
/** `selected` is the focused row, or undefined while the prompt has focus. The window keeps it visible. */
|
|
30
|
-
export function branchPanelLines(rows: readonly BranchRow[], selected: number | undefined): Line[] {
|
|
31
|
-
if (rows.length === 0) return [];
|
|
32
|
-
const start = selected === undefined ? 0 : Math.max(0, Math.min(selected - BRANCH_ROWS + 1, rows.length - BRANCH_ROWS));
|
|
33
|
-
const shown = rows.slice(start, start + BRANCH_ROWS);
|
|
34
|
-
const lines: Line[] = shown.map((row, k) => {
|
|
35
|
-
const focused = start + k === selected;
|
|
36
|
-
return [
|
|
37
|
-
{ text: focused ? "› " : " ", role: "accent", bold: true },
|
|
38
|
-
MARK[row.state],
|
|
39
|
-
{ text: ` ${row.purpose}`, role: focused ? "text" : "muted", bold: focused },
|
|
40
|
-
{ text: ` · ${row.state}`, role: row.state === "failed" ? "error" : "muted" },
|
|
41
|
-
...(focused ? [{ text: row.state === "running" ? " enter open · x stop · esc back" : " enter open · x clear · esc back", role: "muted" as const }] : []),
|
|
42
|
-
];
|
|
43
|
-
});
|
|
44
|
-
const hidden = rows.length - shown.length;
|
|
45
|
-
if (hidden > 0) lines.push([{ text: ` +${hidden} more`, role: "muted" }]);
|
|
46
|
-
return lines;
|
|
47
|
-
}
|
package/src/tui/ui/canvas.ts
DELETED
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rows of styled segments drawn straight into the frame buffer.
|
|
3
|
-
*
|
|
4
|
-
* Chrome (input box edges, top bar, sidebar, greeting, completion list)
|
|
5
|
-
* changes often and never needs wrapping or selection, so it skips the text
|
|
6
|
-
* layout machinery: setting a TextRenderable's content re-measures the node
|
|
7
|
-
* and dirties Yoga, even for an identical string (OpenTUI 0.5.14,
|
|
8
|
-
* TextBufferRenderable). A Canvas only stores rows and requests a frame;
|
|
9
|
-
* the activity glyph is read at paint time, so a spinner tick touches no
|
|
10
|
-
* node at all (docs/tasks/refactor-tui-dock-layout.md DoD 9).
|
|
11
|
-
*/
|
|
12
|
-
import { Renderable, TextAttributes, type OptimizedBuffer, type RenderContext, type RenderableOptions, type RGBA } from "@opentui/core";
|
|
13
|
-
import type { UiColors } from "./colors.ts";
|
|
14
|
-
import type { Role } from "./edge.ts";
|
|
15
|
-
import type { Line } from "./status.ts";
|
|
16
|
-
import { displayWidth } from "../width.ts";
|
|
17
|
-
|
|
18
|
-
export interface CanvasOptions extends RenderableOptions<Canvas> {
|
|
19
|
-
readonly colors: UiColors;
|
|
20
|
-
/** The current activity glyph for `spin` segments. */
|
|
21
|
-
readonly glyph?: () => string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function roleColor(colors: UiColors, role: Role): RGBA {
|
|
25
|
-
switch (role) {
|
|
26
|
-
case "text": return colors.text;
|
|
27
|
-
case "muted": return colors.muted;
|
|
28
|
-
case "edge": return colors.edge;
|
|
29
|
-
case "line": return colors.line;
|
|
30
|
-
case "accent": return colors.accent;
|
|
31
|
-
case "success": return colors.success;
|
|
32
|
-
case "error": return colors.error;
|
|
33
|
-
case "warning": return colors.warning;
|
|
34
|
-
case "reasoning": return colors.reasoning;
|
|
35
|
-
case "code": return colors.code;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export class Canvas extends Renderable {
|
|
40
|
-
private rows: readonly Line[] = [];
|
|
41
|
-
private colors: UiColors;
|
|
42
|
-
private readonly glyph: () => string;
|
|
43
|
-
|
|
44
|
-
constructor(ctx: RenderContext, options: CanvasOptions) {
|
|
45
|
-
super(ctx, options);
|
|
46
|
-
this.colors = options.colors;
|
|
47
|
-
this.glyph = options.glyph ?? (() => "●");
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
get lines(): readonly Line[] { return this.rows; }
|
|
51
|
-
/** Plain text of what is drawn (tests, /debug). */
|
|
52
|
-
get text(): string { return this.rows.map(row => row.map(seg => seg.spin ? this.glyph() : seg.text).join("")).join("\n"); }
|
|
53
|
-
|
|
54
|
-
/** Store new rows; an identical set requests nothing. */
|
|
55
|
-
setRows(rows: readonly Line[]): void {
|
|
56
|
-
if (sameRows(rows, this.rows)) return;
|
|
57
|
-
this.rows = rows;
|
|
58
|
-
this.requestRender();
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
setColors(colors: UiColors): void { this.colors = colors; this.requestRender(); }
|
|
62
|
-
|
|
63
|
-
protected override renderSelf(buffer: OptimizedBuffer): void {
|
|
64
|
-
const x0 = this.screenX, y0 = this.screenY, width = this.width, height = this.height;
|
|
65
|
-
for (let row = 0; row < Math.min(height, this.rows.length); row++) {
|
|
66
|
-
// Rows scrolled above the buffer must be skipped here: the native drawText
|
|
67
|
-
// clamps a negative row to 0, where the scissor (the scroll viewport) lets it through.
|
|
68
|
-
const y = y0 + row;
|
|
69
|
-
if (y < 0 || y >= buffer.height) continue;
|
|
70
|
-
let x = x0;
|
|
71
|
-
for (const seg of this.rows[row]!) {
|
|
72
|
-
const text = seg.spin ? this.glyph() : seg.text;
|
|
73
|
-
if (!text) continue;
|
|
74
|
-
const w = seg.spin ? 1 : displayWidth(text);
|
|
75
|
-
if (x - x0 + w > width) break;
|
|
76
|
-
const attributes = (seg.bold ? TextAttributes.BOLD : 0) | (seg.italic ? TextAttributes.ITALIC : 0);
|
|
77
|
-
buffer.drawText(text, x, y, roleColor(this.colors, seg.role), undefined, attributes);
|
|
78
|
-
x += w;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function sameRows(a: readonly Line[], b: readonly Line[]): boolean {
|
|
85
|
-
if (a === b) return true;
|
|
86
|
-
if (a.length !== b.length) return false;
|
|
87
|
-
for (let i = 0; i < a.length; i++) {
|
|
88
|
-
const x = a[i]!, y = b[i]!;
|
|
89
|
-
if (x.length !== y.length) return false;
|
|
90
|
-
for (let j = 0; j < x.length; j++) {
|
|
91
|
-
const p = x[j]!, q = y[j]!;
|
|
92
|
-
if (p.text !== q.text || p.role !== q.role || p.bold !== q.bold || p.italic !== q.italic || p.spin !== q.spin) return false;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return true;
|
|
96
|
-
}
|
package/src/tui/ui/colors.ts
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The view's colour vocabulary, as OpenTUI colours ready to draw with.
|
|
3
|
-
*
|
|
4
|
-
* Built-in appearances come from the terminal's own palette (ink.ts): the
|
|
5
|
-
* background is never painted and body text is the terminal's foreground.
|
|
6
|
-
* A custom theme file supplies explicit colours instead. `src/tui` may not
|
|
7
|
-
* import core, so the app maps its Theme into this record (apps/ui/theme.ts).
|
|
8
|
-
*
|
|
9
|
-
* Colour carries a stable role: one accent for navigation, success/error
|
|
10
|
-
* only for logged outcomes (D11), warning for things waiting on the user.
|
|
11
|
-
*/
|
|
12
|
-
import { RGBA } from "@opentui/core";
|
|
13
|
-
import { terminalInks, type InkSet, type InkSpec } from "./ink.ts";
|
|
14
|
-
|
|
15
|
-
export interface UiColors {
|
|
16
|
-
/** The terminal default unless a custom theme sets one explicitly. */
|
|
17
|
-
readonly background: RGBA;
|
|
18
|
-
readonly text: RGBA;
|
|
19
|
-
readonly muted: RGBA;
|
|
20
|
-
/** The input box border. */
|
|
21
|
-
readonly edge: RGBA;
|
|
22
|
-
/** Rules, separators and scrollbar tracks. */
|
|
23
|
-
readonly line: RGBA;
|
|
24
|
-
readonly accent: RGBA;
|
|
25
|
-
readonly success: RGBA;
|
|
26
|
-
readonly error: RGBA;
|
|
27
|
-
readonly warning: RGBA;
|
|
28
|
-
readonly reasoning: RGBA;
|
|
29
|
-
readonly code: RGBA;
|
|
30
|
-
/** Mouse-selected text (feat-tui-copy-selection). */
|
|
31
|
-
readonly selectionBg: RGBA;
|
|
32
|
-
readonly selectionFg: RGBA;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const cache = new Map<string, RGBA>();
|
|
36
|
-
function cached(key: string, make: () => RGBA): RGBA {
|
|
37
|
-
let value = cache.get(key);
|
|
38
|
-
if (!value) { value = make(); cache.set(key, value); }
|
|
39
|
-
return value;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function inkColor(spec: InkSpec): RGBA {
|
|
43
|
-
switch (spec.kind) {
|
|
44
|
-
case "default": return cached("default:fg", () => RGBA.defaultForeground());
|
|
45
|
-
case "index": return cached(`index:${spec.index}`, () => RGBA.fromIndex(spec.index));
|
|
46
|
-
case "rgb": return rgba(spec.hex);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/** The terminal's own background: SGR 49, so transparency and blur survive. */
|
|
51
|
-
export const TERMINAL_BACKGROUND: RGBA = RGBA.defaultBackground();
|
|
52
|
-
/** Nothing at all (OpenTUI skips the cell's background). */
|
|
53
|
-
export const CLEAR: RGBA = RGBA.fromValues(0, 0, 0, 0);
|
|
54
|
-
|
|
55
|
-
export function colorsFromInks(inks: InkSet): UiColors {
|
|
56
|
-
return {
|
|
57
|
-
background: inks.background.kind === "default" ? TERMINAL_BACKGROUND : inkColor(inks.background),
|
|
58
|
-
text: inkColor(inks.text), muted: inkColor(inks.muted), edge: inkColor(inks.edge), line: inkColor(inks.line),
|
|
59
|
-
accent: inkColor(inks.accent), success: inkColor(inks.success), error: inkColor(inks.error),
|
|
60
|
-
warning: inkColor(inks.warning), reasoning: inkColor(inks.reasoning), code: inkColor(inks.code),
|
|
61
|
-
selectionBg: inkColor(inks.selectionBg), selectionFg: inkColor(inks.selectionFg),
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/** Before the terminal answers (or when it never does). */
|
|
66
|
-
export const FALLBACK_COLORS: UiColors = colorsFromInks(terminalInks(null, "dark"));
|
|
67
|
-
|
|
68
|
-
export function rgba(hex: string): RGBA {
|
|
69
|
-
return cached(`hex:${hex}`, () => RGBA.fromHex(hex));
|
|
70
|
-
}
|