@visual-z/xeno 0.2.1 → 0.4.0
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 +18 -0
- package/README.md +126 -34
- package/docs/app-server.md +84 -0
- package/docs/install.md +51 -13
- package/docs/providers.md +24 -3
- package/package.json +7 -5
- package/src/apps/app-server.ts +28 -0
- package/src/apps/approve.ts +3 -3
- package/src/apps/cli.ts +25 -10
- package/src/apps/commands.ts +45 -8
- package/src/apps/completions.ts +78 -22
- package/src/apps/control-transport.ts +89 -0
- package/src/apps/image-draft.ts +46 -0
- package/src/apps/model-catalog.ts +2 -1
- package/src/apps/project-trust.ts +2 -42
- package/src/apps/provider-connect.ts +346 -0
- package/src/apps/render.ts +22 -47
- package/src/apps/resources.ts +5 -2
- package/src/apps/shell.ts +333 -1542
- package/src/apps/startup-input.ts +45 -9
- package/src/apps/startup.ts +149 -94
- package/src/apps/ui/app.ts +1553 -0
- package/src/apps/ui/control-model.ts +26 -0
- package/src/apps/ui/extension-host.ts +194 -0
- package/src/apps/ui/image-cache.ts +78 -0
- package/src/apps/ui/palette.ts +88 -0
- package/src/apps/ui/project.ts +127 -0
- package/src/apps/ui/standalone.ts +146 -0
- package/src/apps/ui/status-model.ts +68 -0
- package/src/apps/ui/surface.ts +86 -0
- package/src/apps/ui/theme.ts +86 -0
- package/src/core/acceptance.ts +107 -0
- package/src/core/action-defaults.ts +47 -295
- package/src/core/benchmark.ts +2 -2
- package/src/core/branch-receipt.ts +24 -0
- package/src/core/checkpoints.ts +64 -0
- package/src/core/churn.ts +2 -0
- package/src/core/command-artifacts.ts +94 -0
- package/src/core/command-contract.ts +35 -0
- package/src/core/completion-action.ts +20 -0
- package/src/core/completion-review.ts +37 -21
- package/src/core/context-detail.ts +37 -0
- package/src/core/context-policy.ts +74 -1
- package/src/core/continuation.ts +17 -2
- package/src/core/control-protocol.ts +62 -0
- package/src/core/control-view.ts +42 -0
- package/src/core/derive.ts +29 -3
- package/src/core/draft-images.ts +56 -0
- package/src/core/environment.ts +145 -0
- package/src/core/evaluation-coverage.ts +74 -0
- package/src/core/event-validation.ts +81 -6
- package/src/core/events.ts +99 -3
- package/src/core/evidence-links.ts +7 -0
- package/src/core/evidence.ts +13 -3
- package/src/core/execution.ts +8 -2
- package/src/core/experiment.ts +133 -0
- package/src/core/export.ts +9 -0
- package/src/core/failure-recovery.ts +173 -0
- package/src/core/file-precondition.ts +72 -0
- package/src/core/handoff.ts +65 -4
- package/src/core/harness-diagnostics.ts +206 -0
- package/src/core/history-query.ts +38 -2
- package/src/core/history.ts +38 -1
- package/src/core/integration-health.ts +34 -0
- package/src/core/keymap.ts +8 -20
- package/src/core/model-picker.ts +64 -0
- package/src/core/native-eval.ts +25 -0
- package/src/core/note-guidance.ts +34 -0
- package/src/core/oauth-fields.ts +44 -0
- package/src/core/observation-view.ts +49 -8
- package/src/core/permissions.ts +24 -2
- package/src/core/process-receipt.ts +105 -0
- package/src/core/process-state.ts +37 -0
- package/src/core/program-status.ts +31 -0
- package/src/core/project.ts +70 -19
- package/src/core/prompt-policy.ts +37 -0
- package/src/core/query-eval-contract.ts +14 -0
- package/src/core/read-observation.ts +82 -0
- package/src/core/recovery-corpus.ts +17 -0
- package/src/core/recovery-evaluation.ts +60 -0
- package/src/core/recovery-sources.ts +74 -0
- package/src/core/request-progress.ts +87 -0
- package/src/core/request-state.ts +114 -0
- package/src/core/runtime-target.ts +94 -0
- package/src/core/search-observation.ts +97 -0
- package/src/core/session-tree.ts +147 -0
- package/src/core/settings.ts +33 -10
- package/src/core/skills.ts +44 -0
- package/src/core/sql-query.ts +211 -0
- package/src/core/theme.ts +36 -58
- package/src/core/tool-contract.ts +51 -2
- package/src/core/tool-discovery.ts +87 -0
- package/src/core/tool-failure.ts +60 -0
- package/src/core/tool-input.ts +6 -0
- package/src/core/tool-mode-protocol.ts +25 -0
- package/src/core/transcript.ts +19 -4
- package/src/core/trial-lifecycle.ts +14 -0
- package/src/core/tui-mode.ts +29 -0
- package/src/core/update-check.ts +97 -0
- package/src/core/version.ts +55 -0
- package/src/core/work-state.ts +49 -3
- package/src/core/working-set.ts +91 -0
- package/src/runtime/auth.ts +11 -4
- package/src/runtime/branch-jobs.ts +36 -0
- package/src/runtime/catalog.ts +13 -3
- package/src/runtime/clipboard.ts +15 -4
- package/src/runtime/command-artifacts.ts +64 -0
- package/src/runtime/control-connection.ts +104 -0
- package/src/runtime/environment-tools.ts +60 -0
- package/src/runtime/evidence-notes.ts +4 -2
- package/src/runtime/exec-sessions.ts +206 -61
- package/src/runtime/execution-control.ts +1 -0
- package/src/runtime/extension-ui.ts +22 -30
- package/src/runtime/extensions.ts +95 -16
- package/src/runtime/harness-comparison.ts +27 -7
- package/src/runtime/harness-eval.ts +462 -0
- package/src/runtime/history-cache.ts +57 -0
- package/src/runtime/history-tools.ts +62 -12
- package/src/runtime/integrations.ts +210 -0
- package/src/runtime/loop.ts +1088 -282
- package/src/runtime/model-discovery.ts +208 -0
- package/src/runtime/model.ts +9 -0
- package/src/runtime/native-eval-fixtures.ts +33 -0
- package/src/runtime/native-eval.ts +146 -0
- package/src/runtime/oauth.ts +80 -3
- package/src/runtime/pi-provider.ts +169 -12
- package/src/runtime/program-status.ts +38 -0
- package/src/runtime/provider-connect.ts +109 -0
- package/src/runtime/provider-presets.ts +87 -0
- package/src/runtime/provider-request.ts +13 -2
- package/src/runtime/provider.ts +23 -9
- package/src/runtime/query-eval-verifier.ts +28 -0
- package/src/runtime/recovery-coverage.ts +71 -0
- package/src/runtime/recovery-evidence.ts +76 -0
- package/src/runtime/recovery-fixtures.ts +116 -0
- package/src/runtime/runtime-target.ts +149 -0
- package/src/runtime/session-control.ts +198 -0
- package/src/runtime/tool-broker.ts +137 -0
- package/src/runtime/tool-discovery.ts +57 -0
- package/src/runtime/tool-mode-eval.ts +146 -0
- package/src/runtime/tool-queue.ts +77 -0
- package/src/runtime/tools.ts +628 -183
- package/src/runtime/trial-control.ts +45 -0
- package/src/runtime/update-check.ts +47 -0
- package/src/runtime/window-trial.ts +2 -1
- package/src/runtime/working-notes.ts +33 -3
- package/src/runtime/workspace-lifecycle.ts +97 -0
- package/src/store/acceptance.ts +15 -0
- package/src/store/checkpoint-history.ts +43 -0
- package/src/store/command-artifacts.ts +96 -0
- package/src/store/command.ts +65 -37
- package/src/store/file-checkpoints.ts +104 -0
- package/src/store/file-index.ts +13 -1
- package/src/store/git-checkpoints.ts +67 -0
- package/src/store/observations.ts +61 -20
- package/src/store/process-receipts.ts +34 -0
- package/src/store/query-source.ts +13 -8
- package/src/store/recovery.ts +2 -3
- package/src/store/replay.ts +16 -4
- package/src/store/runtime-target.ts +64 -0
- package/src/store/search.ts +171 -132
- package/src/store/session-archive.ts +4 -0
- package/src/store/source-cancellation.ts +6 -0
- package/src/store/update-cache.ts +36 -0
- package/src/store/workspace-observation.ts +113 -0
- package/src/tui/ansi-spans.ts +126 -0
- package/src/tui/style.ts +19 -16
- package/src/tui/ui/atomic-draft.ts +121 -0
- package/src/tui/ui/canvas.ts +96 -0
- package/src/tui/ui/colors.ts +70 -0
- package/src/tui/ui/composer.ts +200 -0
- package/src/tui/ui/control-panel.ts +23 -0
- package/src/tui/ui/dialog.ts +379 -0
- package/src/tui/ui/draft.ts +23 -0
- package/src/tui/ui/edge.ts +186 -0
- package/src/tui/ui/image-size.ts +40 -0
- package/src/tui/ui/ink.ts +210 -0
- package/src/tui/ui/items.ts +40 -0
- package/src/tui/ui/keys.ts +40 -0
- package/src/tui/ui/layout.ts +74 -0
- package/src/tui/ui/list-model.ts +86 -0
- package/src/tui/ui/list-view.ts +172 -0
- package/src/tui/ui/mascot.ts +67 -0
- package/src/tui/ui/messages.ts +518 -0
- package/src/tui/ui/motion.ts +28 -0
- package/src/tui/ui/paths.ts +10 -0
- package/src/tui/ui/pictures.ts +78 -0
- package/src/tui/ui/screen.ts +421 -0
- package/src/tui/ui/status.ts +279 -0
- package/src/tui/ui/styled.ts +85 -0
- package/src/tui/ui/testing.ts +5 -0
- package/src/tui/ui/tool-card.ts +150 -0
- package/src/apps/extension-ui.ts +0 -330
- package/src/apps/resource-browser.ts +0 -75
- package/src/apps/session-browser.ts +0 -113
- package/src/apps/session-picker.ts +0 -55
- package/src/tui/ansi.ts +0 -67
- package/src/tui/autocomplete.ts +0 -29
- package/src/tui/chat-viewport.ts +0 -47
- package/src/tui/complete.ts +0 -87
- package/src/tui/editor.ts +0 -940
- package/src/tui/host.ts +0 -264
- package/src/tui/input.ts +0 -75
- package/src/tui/keys.ts +0 -378
- package/src/tui/markdown.ts +0 -17
- package/src/tui/render.ts +0 -153
- package/src/tui/select.ts +0 -258
- package/src/tui/settings.ts +0 -44
- package/src/tui/statusline.ts +0 -162
- package/src/tui/system-theme.ts +0 -700
- package/src/tui/terminal.ts +0 -30
- package/src/tui/text.ts +0 -52
- package/src/tui/toolview.ts +0 -386
- package/src/tui/transcript.ts +0 -123
- package/src/tui/tree.ts +0 -471
- package/src/vendor/pi-tui/LICENSE.upstream +0 -21
- package/src/vendor/pi-tui/UPSTREAM.json +0 -50
- package/src/vendor/pi-tui/VENDOR.md +0 -25
- package/src/vendor/pi-tui/alt-screen-search.ts +0 -327
- package/src/vendor/pi-tui/autocomplete.ts +0 -860
- package/src/vendor/pi-tui/colors.ts +0 -367
- package/src/vendor/pi-tui/components/alt-screen-flash.ts +0 -51
- package/src/vendor/pi-tui/components/box.ts +0 -166
- package/src/vendor/pi-tui/components/cancellable-loader.ts +0 -40
- package/src/vendor/pi-tui/components/editor.ts +0 -2472
- package/src/vendor/pi-tui/components/h-stack.ts +0 -44
- package/src/vendor/pi-tui/components/image.ts +0 -127
- package/src/vendor/pi-tui/components/input.ts +0 -494
- package/src/vendor/pi-tui/components/loader.ts +0 -101
- package/src/vendor/pi-tui/components/markdown.ts +0 -1021
- package/src/vendor/pi-tui/components/mouse-region.ts +0 -33
- package/src/vendor/pi-tui/components/scroll-view.ts +0 -224
- package/src/vendor/pi-tui/components/select-list.ts +0 -273
- package/src/vendor/pi-tui/components/settings-list.ts +0 -328
- package/src/vendor/pi-tui/components/spacer.ts +0 -28
- package/src/vendor/pi-tui/components/stack.ts +0 -154
- package/src/vendor/pi-tui/components/text.ts +0 -107
- package/src/vendor/pi-tui/components/truncated-text.ts +0 -65
- package/src/vendor/pi-tui/components/v-stack.ts +0 -33
- package/src/vendor/pi-tui/editor-component.ts +0 -74
- package/src/vendor/pi-tui/fuzzy.ts +0 -138
- package/src/vendor/pi-tui/index.ts +0 -186
- package/src/vendor/pi-tui/keybindings.ts +0 -320
- package/src/vendor/pi-tui/keys.ts +0 -1401
- package/src/vendor/pi-tui/kill-ring.ts +0 -46
- package/src/vendor/pi-tui/latex.ts +0 -1506
- package/src/vendor/pi-tui/layout-node.ts +0 -51
- package/src/vendor/pi-tui/layout.ts +0 -449
- package/src/vendor/pi-tui/native/UPSTREAM.json +0 -23
- package/src/vendor/pi-tui/native/clipboard.h +0 -208
- package/src/vendor/pi-tui/native/darwin/README.md +0 -22
- package/src/vendor/pi-tui/native/darwin/build.sh +0 -69
- package/src/vendor/pi-tui/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
- package/src/vendor/pi-tui/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
- package/src/vendor/pi-tui/native/darwin/src/darwin-platform.m +0 -132
- package/src/vendor/pi-tui/native/linux/README.md +0 -23
- package/src/vendor/pi-tui/native/linux/build.sh +0 -65
- package/src/vendor/pi-tui/native/linux/prebuilds/linux-arm64/linux-platform-x11.node +0 -0
- package/src/vendor/pi-tui/native/linux/prebuilds/linux-x64/linux-platform-x11.node +0 -0
- package/src/vendor/pi-tui/native/linux/src/clipboard-worker.h +0 -70
- package/src/vendor/pi-tui/native/linux/src/linux-platform-x11.c +0 -274
- package/src/vendor/pi-tui/native/napi.h +0 -91
- package/src/vendor/pi-tui/native/win32/README.md +0 -31
- package/src/vendor/pi-tui/native/win32/build.mjs +0 -232
- package/src/vendor/pi-tui/native/win32/prebuilds/win32-arm64/win32-platform.node +0 -0
- package/src/vendor/pi-tui/native/win32/prebuilds/win32-x64/win32-platform.node +0 -0
- package/src/vendor/pi-tui/native/win32/src/win32-platform.c +0 -241
- package/src/vendor/pi-tui/native-modifiers.ts +0 -13
- package/src/vendor/pi-tui/native-module-path.ts +0 -31
- package/src/vendor/pi-tui/native-platform.ts +0 -65
- package/src/vendor/pi-tui/oklab.ts +0 -233
- package/src/vendor/pi-tui/stdin-buffer.ts +0 -444
- package/src/vendor/pi-tui/terminal-colors.ts +0 -91
- package/src/vendor/pi-tui/terminal-image.ts +0 -731
- package/src/vendor/pi-tui/terminal.ts +0 -554
- package/src/vendor/pi-tui/tui-alt-screen.ts +0 -1750
- package/src/vendor/pi-tui/tui-main-screen.ts +0 -655
- package/src/vendor/pi-tui/tui.ts +0 -1493
- package/src/vendor/pi-tui/undo-stack.ts +0 -28
- package/src/vendor/pi-tui/utils.ts +0 -1385
- package/src/vendor/pi-tui/wheel-scroll.ts +0 -82
- package/src/vendor/pi-tui/word-navigation.ts +0 -117
package/src/tui/tree.ts
DELETED
|
@@ -1,471 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Session-tree layout and selection. Pure: renderTree(nodes, selection,
|
|
3
|
-
* width, style) → string[]. Collapse/filter/cursor never reach the log —
|
|
4
|
-
* the thing that happened is rewind, and that already has an event.
|
|
5
|
-
*
|
|
6
|
-
* Connectors (`├─` / `└─` / `│`) are kept before prompt text when the
|
|
7
|
-
* terminal is too narrow. A line that wraps would make the line-diff
|
|
8
|
-
* renderer count one row where the screen used two (PLAYBOOK width rule;
|
|
9
|
-
* same trap as toolview's `" → "` prefix).
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { assertNever } from "./exhaustive.ts";
|
|
13
|
-
import type { Key } from "./keys.ts";
|
|
14
|
-
import type { Component } from "./text.ts";
|
|
15
|
-
import { displayWidth } from "./width.ts";
|
|
16
|
-
import { PLAIN_ATTRS, paint, type Style } from "./style.ts";
|
|
17
|
-
import { Input } from "../vendor/pi-tui/components/input.ts";
|
|
18
|
-
import { encodeKey } from "./input.ts";
|
|
19
|
-
import { truncateToWidth } from "../vendor/pi-tui/utils.ts";
|
|
20
|
-
import { getKeybindings } from "../vendor/pi-tui/keybindings.ts";
|
|
21
|
-
|
|
22
|
-
/** Same mark /back uses for a branch the session rewound away from. */
|
|
23
|
-
export const LEFT_BRANCH_MARK = "↩";
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Why the live region is not a blank box. Named in the card: an empty
|
|
27
|
-
* frame looks like a render bug, and there is a real reason (no completed
|
|
28
|
-
* exchange to jump to).
|
|
29
|
-
*/
|
|
30
|
-
export const EMPTY_TREE_MESSAGE = "nothing to go back to -- no exchange has completed yet";
|
|
31
|
-
|
|
32
|
-
/** Filter toggle lives here so the key is not a hidden chord. */
|
|
33
|
-
export const TREE_HINT = "tab user/all · enter jump · esc cancel";
|
|
34
|
-
|
|
35
|
-
const BRANCH_MID = "├─ ";
|
|
36
|
-
const BRANCH_END = "└─ ";
|
|
37
|
-
const PIPE = "│ ";
|
|
38
|
-
const BLANK = " ";
|
|
39
|
-
const SELECTED = "→ ";
|
|
40
|
-
const UNSELECTED = " ";
|
|
41
|
-
const CURRENT_MARK = "● ";
|
|
42
|
-
const ON_PATH_MARK = " ";
|
|
43
|
-
const LEFT_MARK = `${LEFT_BRANCH_MARK} `;
|
|
44
|
-
|
|
45
|
-
export type TreeKind = "user" | "other";
|
|
46
|
-
export type TreeFilter = "user" | "default" | "no-tools" | "user-only" | "labeled-only" | "all";
|
|
47
|
-
|
|
48
|
-
export interface TreeNode {
|
|
49
|
-
readonly id: string;
|
|
50
|
-
readonly prompt: string;
|
|
51
|
-
readonly onPath: boolean;
|
|
52
|
-
readonly current: boolean;
|
|
53
|
-
readonly kind: TreeKind;
|
|
54
|
-
readonly children: readonly TreeNode[];
|
|
55
|
-
readonly category?: "tool" | "message" | "metadata";
|
|
56
|
-
readonly label?: string;
|
|
57
|
-
readonly labelAt?: string;
|
|
58
|
-
readonly at?: string;
|
|
59
|
-
readonly content?: string;
|
|
60
|
-
/** Exact event position; user messages navigate before themselves. */
|
|
61
|
-
readonly target?: string;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface TreeSelection {
|
|
65
|
-
readonly index: number;
|
|
66
|
-
readonly filter: TreeFilter;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export interface TreeState {
|
|
70
|
-
readonly nodes: readonly TreeNode[];
|
|
71
|
-
readonly selected: number;
|
|
72
|
-
readonly filter: TreeFilter;
|
|
73
|
-
readonly confirmed: TreeNode | null;
|
|
74
|
-
readonly cancelled: boolean;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface CreateTreeOptions {
|
|
78
|
-
readonly filter?: TreeFilter;
|
|
79
|
-
readonly style?: Style;
|
|
80
|
-
readonly bindings?: Readonly<Record<string, readonly string[]>>;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* A restore point as the log already knows it. parent pointers are a
|
|
85
|
-
* separate map so this file never imports store.
|
|
86
|
-
*/
|
|
87
|
-
export interface TreePoint {
|
|
88
|
-
readonly node: number;
|
|
89
|
-
readonly atEvent: string;
|
|
90
|
-
readonly prompt: string;
|
|
91
|
-
readonly onPath: boolean;
|
|
92
|
-
readonly kind?: TreeKind;
|
|
93
|
-
readonly category?: "tool" | "message" | "metadata";
|
|
94
|
-
readonly label?: string;
|
|
95
|
-
readonly labelAt?: string;
|
|
96
|
-
readonly at?: string;
|
|
97
|
-
readonly content?: string;
|
|
98
|
-
readonly target?: string;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export type NodeParent = { readonly node: number; readonly at_event?: string } | null;
|
|
102
|
-
|
|
103
|
-
export function createTree(
|
|
104
|
-
nodes: readonly TreeNode[],
|
|
105
|
-
opts: CreateTreeOptions = {},
|
|
106
|
-
): TreeState {
|
|
107
|
-
return {
|
|
108
|
-
nodes,
|
|
109
|
-
selected: 0,
|
|
110
|
-
filter: opts.filter ?? "all",
|
|
111
|
-
confirmed: null,
|
|
112
|
-
cancelled: false,
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export function applyTreeKey(state: TreeState, key: Key): TreeState {
|
|
117
|
-
switch (key.type) {
|
|
118
|
-
case "up":
|
|
119
|
-
return move(state, -1);
|
|
120
|
-
case "down":
|
|
121
|
-
return move(state, 1);
|
|
122
|
-
case "enter":
|
|
123
|
-
return confirm(state);
|
|
124
|
-
case "escape":
|
|
125
|
-
return { ...state, cancelled: true, confirmed: null };
|
|
126
|
-
case "tab":
|
|
127
|
-
return toggleFilter(state);
|
|
128
|
-
case "char":
|
|
129
|
-
case "backspace":
|
|
130
|
-
case "delete":
|
|
131
|
-
case "left":
|
|
132
|
-
case "right":
|
|
133
|
-
case "home":
|
|
134
|
-
case "end":
|
|
135
|
-
case "pageup":
|
|
136
|
-
case "pagedown":
|
|
137
|
-
case "ctrl":
|
|
138
|
-
case "alt":
|
|
139
|
-
return state;
|
|
140
|
-
default:
|
|
141
|
-
return assertNever(key, "applyTreeKey");
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
function visibleNodes(nodes: readonly TreeNode[], filter: TreeFilter): TreeNode[] {
|
|
146
|
-
if (filter === "all") return [...nodes];
|
|
147
|
-
const out: TreeNode[] = [];
|
|
148
|
-
const stack = [...nodes].reverse().map(node => ({ node, into: out }));
|
|
149
|
-
while (stack.length) {
|
|
150
|
-
const { node: n, into } = stack.pop()!;
|
|
151
|
-
const include = filter === "user" || filter === "user-only" ? n.kind === "user" :
|
|
152
|
-
filter === "labeled-only" ? Boolean(n.label) : filter === "no-tools" ? n.category !== "tool" && n.category !== "metadata" : n.category !== "metadata";
|
|
153
|
-
const children: TreeNode[] = [];
|
|
154
|
-
if (include) into.push({ ...n, children });
|
|
155
|
-
for (let i = n.children.length - 1; i >= 0; i--) stack.push({ node: n.children[i]!, into: include ? children : into });
|
|
156
|
-
}
|
|
157
|
-
return out;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function flatten(nodes: readonly TreeNode[]): TreeNode[] {
|
|
161
|
-
const out: TreeNode[] = [];
|
|
162
|
-
const stack = [...nodes].reverse();
|
|
163
|
-
while (stack.length) {
|
|
164
|
-
const n = stack.pop()!;
|
|
165
|
-
out.push(n);
|
|
166
|
-
for (let i = n.children.length - 1; i >= 0; i--) stack.push(n.children[i]!);
|
|
167
|
-
}
|
|
168
|
-
return out;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function move(state: TreeState, dir: -1 | 1): TreeState {
|
|
172
|
-
const n = flatten(visibleNodes(state.nodes, state.filter)).length;
|
|
173
|
-
if (n === 0) return state;
|
|
174
|
-
const selected = (state.selected + dir + n) % n;
|
|
175
|
-
return { ...state, selected, confirmed: null, cancelled: false };
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function confirm(state: TreeState): TreeState {
|
|
179
|
-
const item = flatten(visibleNodes(state.nodes, state.filter))[state.selected];
|
|
180
|
-
if (item === undefined) return state;
|
|
181
|
-
return { ...state, confirmed: item, cancelled: false };
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
function toggleFilter(state: TreeState): TreeState {
|
|
185
|
-
const filter: TreeFilter = state.filter === "all" || state.filter === "default" ? "user" : "all";
|
|
186
|
-
const n = flatten(visibleNodes(state.nodes, filter)).length;
|
|
187
|
-
const selected = n === 0 ? 0 : Math.min(state.selected, n - 1);
|
|
188
|
-
return { ...state, filter, selected, confirmed: null, cancelled: false };
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Truncate on display columns. Slicing with s.length would cut a CJK
|
|
193
|
-
* prompt in half and the next cell would paint garbage.
|
|
194
|
-
*/
|
|
195
|
-
function truncate(s: string, width: number): string {
|
|
196
|
-
if (width <= 0) return "";
|
|
197
|
-
if (displayWidth(s) <= width) return s;
|
|
198
|
-
let out = "";
|
|
199
|
-
let w = 0;
|
|
200
|
-
for (const ch of s) {
|
|
201
|
-
const cw = displayWidth(ch);
|
|
202
|
-
if (w + cw > width) break;
|
|
203
|
-
out += ch;
|
|
204
|
-
w += cw;
|
|
205
|
-
}
|
|
206
|
-
return out;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export function renderTree(
|
|
210
|
-
nodes: readonly TreeNode[],
|
|
211
|
-
selection: TreeSelection,
|
|
212
|
-
width: number,
|
|
213
|
-
style?: Style,
|
|
214
|
-
): string[] {
|
|
215
|
-
const w = Math.max(0, Math.floor(width));
|
|
216
|
-
const filtered = visibleNodes(nodes, selection.filter);
|
|
217
|
-
if (filtered.length === 0) {
|
|
218
|
-
return [truncate(EMPTY_TREE_MESSAGE, w)];
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const flat = flatten(filtered);
|
|
222
|
-
const selected = flat[selection.index] ?? flat[0];
|
|
223
|
-
const selectedId = selected?.id;
|
|
224
|
-
const lines: string[] = [];
|
|
225
|
-
walk(filtered, "", true, selectedId, w, style, lines);
|
|
226
|
-
const hint = truncate(TREE_HINT, w);
|
|
227
|
-
if (hint.length > 0) {
|
|
228
|
-
lines.push(style !== undefined ? paint(hint, { ...PLAIN_ATTRS, dim: true }, style) : hint);
|
|
229
|
-
}
|
|
230
|
-
return lines;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function walk(
|
|
234
|
-
nodes: readonly TreeNode[],
|
|
235
|
-
prefix: string,
|
|
236
|
-
isRoot: boolean,
|
|
237
|
-
selectedId: string | undefined,
|
|
238
|
-
width: number,
|
|
239
|
-
style: Style | undefined,
|
|
240
|
-
lines: string[],
|
|
241
|
-
): void {
|
|
242
|
-
const stack = nodes.map((node, i) => ({ node, prefix, root: isRoot, last: i === nodes.length - 1 })).reverse();
|
|
243
|
-
while (stack.length) {
|
|
244
|
-
const { node, prefix: indent, root, last } = stack.pop()!;
|
|
245
|
-
const branch = root ? "" : last ? BRANCH_END : BRANCH_MID;
|
|
246
|
-
const sel = node.id === selectedId ? SELECTED : UNSELECTED;
|
|
247
|
-
const mark = node.current ? CURRENT_MARK : node.onPath ? ON_PATH_MARK : LEFT_MARK;
|
|
248
|
-
// Left-to-right: connectors stay, prompt is what width drops first.
|
|
249
|
-
const raw = sel + indent + branch + mark + (node.label ? `[${node.label}] ` : "") + node.prompt;
|
|
250
|
-
const clipped = truncate(raw, width);
|
|
251
|
-
const chosen = node.id === selectedId;
|
|
252
|
-
lines.push(
|
|
253
|
-
chosen && style !== undefined
|
|
254
|
-
? paint(clipped, { ...PLAIN_ATTRS, selected: true }, style)
|
|
255
|
-
: clipped,
|
|
256
|
-
);
|
|
257
|
-
const nextPrefix = root ? "" : indent + (last ? BLANK : PIPE);
|
|
258
|
-
// Bound indentation to the display, independently of history depth.
|
|
259
|
-
const budget = Math.max(3, Math.min(30, width - 20));
|
|
260
|
-
const childPrefix = nextPrefix.length > budget ? "… " + nextPrefix.slice(-(budget - 2)) : nextPrefix;
|
|
261
|
-
for (let i = node.children.length - 1; i >= 0; i--) stack.push({ node: node.children[i]!, prefix: childPrefix, root: false, last: i === node.children.length - 1 });
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Restore points plus parent pointers → the tree the view paints.
|
|
267
|
-
*
|
|
268
|
-
* Same-node exchanges stay a chain. A child node whose parent.at_event
|
|
269
|
-
* matches a point hangs off that point as a sibling of the continuation,
|
|
270
|
-
* which is how a rewind becomes a visible fork instead of a missing row.
|
|
271
|
-
*/
|
|
272
|
-
export function treeFromPoints(
|
|
273
|
-
points: readonly TreePoint[],
|
|
274
|
-
parents: ReadonlyMap<number, NodeParent>,
|
|
275
|
-
currentNode: number,
|
|
276
|
-
): TreeNode[] {
|
|
277
|
-
const byNode = new Map<number, TreePoint[]>();
|
|
278
|
-
for (const p of points) {
|
|
279
|
-
const list = byNode.get(p.node) ?? [];
|
|
280
|
-
list.push(p);
|
|
281
|
-
byNode.set(p.node, list);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
const lastHere = [...points].reverse().find((p) => p.onPath && p.node === currentNode);
|
|
285
|
-
const lastOnPath = lastHere ?? [...points].reverse().find((p) => p.onPath);
|
|
286
|
-
|
|
287
|
-
function toNode(p: TreePoint, children: readonly TreeNode[]): TreeNode {
|
|
288
|
-
return {
|
|
289
|
-
...p,
|
|
290
|
-
id: `${p.node}:${p.atEvent}`,
|
|
291
|
-
prompt: p.prompt,
|
|
292
|
-
onPath: p.onPath,
|
|
293
|
-
current: lastOnPath !== undefined && lastOnPath.node === p.node && lastOnPath.atEvent === p.atEvent,
|
|
294
|
-
kind: p.kind ?? "user",
|
|
295
|
-
children,
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// Wire event chains and branch edges separately. Recursing once per event
|
|
300
|
-
// overflows the JS stack on otherwise valid long sessions.
|
|
301
|
-
type MutableNode = TreeNode & { children: TreeNode[] };
|
|
302
|
-
const chains = new Map<number, MutableNode[]>();
|
|
303
|
-
const events = new Map<string, MutableNode>();
|
|
304
|
-
for (const [id, pts] of byNode) {
|
|
305
|
-
const nodes = pts.map(p => toNode(p, []) as MutableNode);
|
|
306
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
307
|
-
events.set(nodes[i]!.id, nodes[i]!);
|
|
308
|
-
if (nodes[i + 1]) nodes[i]!.children.push(nodes[i + 1]!);
|
|
309
|
-
}
|
|
310
|
-
chains.set(id, nodes);
|
|
311
|
-
}
|
|
312
|
-
const forest: TreeNode[] = [];
|
|
313
|
-
for (const [id, nodes] of [...chains].sort(([a], [b]) => a - b)) {
|
|
314
|
-
const first = nodes[0];
|
|
315
|
-
if (!first) continue;
|
|
316
|
-
let parent = parents.get(id);
|
|
317
|
-
const visited = new Set<number>([id]);
|
|
318
|
-
while (parent && !chains.get(parent.node)?.length && !visited.has(parent.node)) {
|
|
319
|
-
visited.add(parent.node); parent = parents.get(parent.node);
|
|
320
|
-
}
|
|
321
|
-
const anchor = parent && !visited.has(parent.node) ? events.get(`${parent.node}:${parent.at_event}`) ?? chains.get(parent.node)?.at(-1) : undefined;
|
|
322
|
-
if (anchor) anchor.children.push(first); else forest.push(first);
|
|
323
|
-
}
|
|
324
|
-
return forest;
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
export class TreeList implements Component {
|
|
328
|
-
private current: TreeState;
|
|
329
|
-
private style: Style | undefined;
|
|
330
|
-
private readonly bindings: Readonly<Record<string, readonly string[]>> | undefined;
|
|
331
|
-
private readonly search = new Input({ prompt: "Search tree: " });
|
|
332
|
-
private readonly folded = new Set<string>();
|
|
333
|
-
private labelEditor: { node: TreeNode; input: Input } | undefined;
|
|
334
|
-
labelChange: { target: string; text: string } | undefined;
|
|
335
|
-
copyText: string | undefined;
|
|
336
|
-
showTimestamps = false;
|
|
337
|
-
onInput: ((data: string) => void) | undefined;
|
|
338
|
-
|
|
339
|
-
constructor(nodes: readonly TreeNode[], opts: CreateTreeOptions = {}) {
|
|
340
|
-
this.current = createTree(nodes, opts);
|
|
341
|
-
this.style = opts.style;
|
|
342
|
-
this.bindings = opts.bindings;
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
get state(): TreeState {
|
|
346
|
-
return { ...this.current, nodes: this.filtered() };
|
|
347
|
-
}
|
|
348
|
-
get selectedNode(): TreeNode | undefined { return flatten(this.filtered())[this.current.selected]; }
|
|
349
|
-
setNodes(nodes: readonly TreeNode[]): void {
|
|
350
|
-
const id = this.selectedNode?.id;
|
|
351
|
-
this.current = { ...this.current, nodes, selected: 0 };
|
|
352
|
-
this.current = { ...this.current, selected: Math.max(0, flatten(this.filtered()).findIndex(node => node.id === id)) };
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
applyKey(key: Key): TreeState {
|
|
356
|
-
return this.acceptInput(encodeKey(key));
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
get focused(): boolean { return (this.labelEditor?.input ?? this.search).focused; }
|
|
360
|
-
set focused(value: boolean) { (this.labelEditor?.input ?? this.search).focused = value; }
|
|
361
|
-
setStyle(style: Style): void { this.style = style; }
|
|
362
|
-
invalidate(): void { this.search.invalidate(); }
|
|
363
|
-
handleInput(data: string): void { if (this.onInput) this.onInput(data); else this.acceptInput(data); }
|
|
364
|
-
private filtered(): readonly TreeNode[] {
|
|
365
|
-
const tokens = this.search.getValue().toLowerCase().trim().split(/\s+/).filter(Boolean);
|
|
366
|
-
const nodes = visibleNodes(this.current.nodes, this.current.filter);
|
|
367
|
-
if (tokens.length) return flatten(nodes).filter(node => tokens.every(token => `${node.content ?? node.prompt} ${node.label ?? ""}`.toLowerCase().includes(token))).map(node => ({ ...node, children: [] }));
|
|
368
|
-
const out: TreeNode[] = [];
|
|
369
|
-
const stack = [...nodes].reverse().map(node => ({ node, into: out }));
|
|
370
|
-
while (stack.length) {
|
|
371
|
-
const { node, into } = stack.pop()!;
|
|
372
|
-
const children: TreeNode[] = [];
|
|
373
|
-
into.push({ ...node, prompt: `${this.showTimestamps && node.labelAt ? `${node.labelAt} ` : ""}${this.folded.has(node.id) ? "▸ " : ""}${node.prompt}`, children });
|
|
374
|
-
if (!this.folded.has(node.id)) for (let i = node.children.length - 1; i >= 0; i--) stack.push({ node: node.children[i]!, into: children });
|
|
375
|
-
}
|
|
376
|
-
return out;
|
|
377
|
-
}
|
|
378
|
-
acceptInput(data: string, action?: string): TreeState {
|
|
379
|
-
this.current = { ...this.current, confirmed: null, cancelled: false };
|
|
380
|
-
this.labelChange = undefined; this.copyText = undefined;
|
|
381
|
-
const kb = getKeybindings();
|
|
382
|
-
if (this.labelEditor) {
|
|
383
|
-
if (kb.matches(data, "tui.select.cancel")) this.labelEditor = undefined;
|
|
384
|
-
else if (kb.matches(data, "tui.select.confirm")) {
|
|
385
|
-
this.labelChange = { target: this.labelEditor.node.target ?? this.labelEditor.node.id, text: this.labelEditor.input.getValue() };
|
|
386
|
-
this.labelEditor = undefined;
|
|
387
|
-
} else this.labelEditor.input.handleInput(data);
|
|
388
|
-
return this.state;
|
|
389
|
-
}
|
|
390
|
-
const filters: TreeFilter[] = ["default", "no-tools", "user-only", "labeled-only", "all"];
|
|
391
|
-
const filterByAction: Record<string, TreeFilter> = { "app.tree.filter.default": "default", "app.tree.filter.noTools": "no-tools",
|
|
392
|
-
"app.tree.filter.userOnly": "user-only", "app.tree.filter.labeledOnly": "labeled-only", "app.tree.filter.all": "all" };
|
|
393
|
-
const filter = action ? filterByAction[action] : undefined;
|
|
394
|
-
if (filter) { this.folded.clear(); this.current = { ...this.current, filter: this.current.filter === filter ? "default" : filter, selected: 0 }; return this.state; }
|
|
395
|
-
if (action === "app.tree.filter.cycleForward" || action === "app.tree.filter.cycleBackward") {
|
|
396
|
-
const index = Math.max(0, filters.indexOf(this.current.filter));
|
|
397
|
-
this.folded.clear();
|
|
398
|
-
this.current = { ...this.current, filter: filters[(index + (action.endsWith("Forward") ? 1 : 4)) % 5]!, selected: 0 }; return this.state;
|
|
399
|
-
}
|
|
400
|
-
if (action === "app.tree.toggleLabelTimestamp") { this.showTimestamps = !this.showTimestamps; return this.state; }
|
|
401
|
-
const selected = this.selectedNode;
|
|
402
|
-
if (action === "app.tree.editLabel") {
|
|
403
|
-
if (selected) { const input = new Input({ prompt: "Label: " }); input.setValue(selected.label ?? ""); input.focused = this.focused; this.labelEditor = { node: selected, input }; }
|
|
404
|
-
return this.state;
|
|
405
|
-
}
|
|
406
|
-
if (action === "app.message.copy") { this.copyText = selected?.content ?? selected?.prompt; return this.state; }
|
|
407
|
-
if (selected && (action === "app.tree.foldOrUp" || action === "app.tree.unfoldOrDown")) {
|
|
408
|
-
const flat = flatten(this.filtered());
|
|
409
|
-
const parentOf = new Map<string, TreeNode>();
|
|
410
|
-
for (const node of flat) for (const child of node.children) parentOf.set(child.id, node);
|
|
411
|
-
const parent = parentOf.get(selected.id);
|
|
412
|
-
if (action === "app.tree.foldOrUp") {
|
|
413
|
-
if (selected.children.length && (!parent || parent.children.length > 1) && !this.folded.has(selected.id)) this.folded.add(selected.id);
|
|
414
|
-
else {
|
|
415
|
-
let target = selected;
|
|
416
|
-
while (parentOf.has(target.id)) {
|
|
417
|
-
const ancestor = parentOf.get(target.id)!;
|
|
418
|
-
if (ancestor.children.length > 1 && target.id !== selected.id) break;
|
|
419
|
-
target = ancestor;
|
|
420
|
-
}
|
|
421
|
-
this.current = { ...this.current, selected: flat.findIndex(node => node.id === target.id) };
|
|
422
|
-
}
|
|
423
|
-
} else if (this.folded.delete(selected.id)) { /* Expand in place before moving to a child. */ }
|
|
424
|
-
else {
|
|
425
|
-
let target = selected;
|
|
426
|
-
while (target.children.length) { const branch = target.children.length > 1; target = target.children[0]!; if (branch) break; }
|
|
427
|
-
this.current = { ...this.current, selected: flat.findIndex(node => node.id === target.id) };
|
|
428
|
-
}
|
|
429
|
-
return this.state;
|
|
430
|
-
}
|
|
431
|
-
if (kb.matches(data, "tui.select.cancel")) {
|
|
432
|
-
if (this.search.getValue()) { this.search.setValue(""); this.folded.clear(); this.current = { ...this.current, selected: 0 }; }
|
|
433
|
-
else this.current = { ...this.current, cancelled: true };
|
|
434
|
-
}
|
|
435
|
-
else if (kb.matches(data, "tui.select.confirm")) this.current = { ...this.current, confirmed: selected ?? null };
|
|
436
|
-
else if (kb.matches(data, "tui.select.up") || kb.matches(data, "tui.select.down")) {
|
|
437
|
-
const size = flatten(this.filtered()).length;
|
|
438
|
-
this.current = { ...this.current, selected: size ? (this.current.selected + (kb.matches(data, "tui.select.up") ? -1 : 1) + size) % size : 0 };
|
|
439
|
-
} else if (kb.matches(data, "tui.input.tab")) this.current = toggleFilter(this.current);
|
|
440
|
-
else if (kb.matches(data, "tui.select.pageUp") || kb.matches(data, "tui.select.pageDown") || kb.matches(data, "tui.editor.cursorLeft") || kb.matches(data, "tui.editor.cursorRight")) {
|
|
441
|
-
this.current = { ...this.current, selected: Math.max(0, Math.min(flatten(this.filtered()).length - 1,
|
|
442
|
-
this.current.selected + (kb.matches(data, "tui.select.pageUp") || kb.matches(data, "tui.editor.cursorLeft") ? -10 : 10))) };
|
|
443
|
-
} else {
|
|
444
|
-
const before = this.search.getValue(); this.search.handleInput(data);
|
|
445
|
-
if (before !== this.search.getValue()) this.folded.clear();
|
|
446
|
-
this.current = { ...this.current, selected: 0 };
|
|
447
|
-
}
|
|
448
|
-
return this.state;
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
render(width: number): string[] {
|
|
452
|
-
if (width <= 0) return [""];
|
|
453
|
-
if (this.labelEditor) return ["Edit label · empty removes it", ...this.labelEditor.input.render(width),
|
|
454
|
-
`${getKeybindings().getKeys("tui.select.confirm").join("/")} save · ${getKeybindings().getKeys("tui.select.cancel").join("/")} cancel`].map(line => truncateToWidth(line, width, ""));
|
|
455
|
-
const body = renderTree(
|
|
456
|
-
this.filtered(),
|
|
457
|
-
{ index: this.current.selected, filter: this.current.filter },
|
|
458
|
-
width,
|
|
459
|
-
this.style,
|
|
460
|
-
);
|
|
461
|
-
// This is a viewport, not a total result cap. Arrows/search can reach every row.
|
|
462
|
-
const start = Math.max(0, this.current.selected - 5);
|
|
463
|
-
const rows = body.slice(start, start + 10);
|
|
464
|
-
const hints = this.bindings ? [["app.tree.filter.cycleForward", "filters"], ["app.tree.foldOrUp", "branch"], ["app.tree.editLabel", "label"],
|
|
465
|
-
["app.tree.toggleLabelTimestamp", "label time"], ["app.message.copy", "copy"], ["tui.select.cancel", "cancel"]]
|
|
466
|
-
.flatMap(([action, label]) => this.bindings![action!]?.length ? [`${this.bindings![action!]!.join("/")} ${label}`] : []).join(" · ") : TREE_HINT;
|
|
467
|
-
return ["Session tree · Select an event to navigate", ...this.search.render(width),
|
|
468
|
-
...rows, `${this.current.filter} · ${hints}`]
|
|
469
|
-
.map((line) => truncateToWidth(line, width, ""));
|
|
470
|
-
}
|
|
471
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Mario Zechner
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"commit": "02eed88fd8912e54a804ddebd409e2e4c08ac5ef",
|
|
3
|
-
"files": {
|
|
4
|
-
"alt-screen-search.ts": "2ed3821323723515523075ac143ce5e25fdcd7c7",
|
|
5
|
-
"autocomplete.ts": "3ff45bf17a5def8d0bdf81e9eb1af264f1c5f768",
|
|
6
|
-
"colors.ts": "070a261344e307988f45e7c86d1728db5a00b8f3",
|
|
7
|
-
"components/alt-screen-flash.ts": "e4b823cd2bdd54696895cac93807cc6fcddaddd4",
|
|
8
|
-
"components/box.ts": "7c880d9145eff2c26db7969937223bb3776acced",
|
|
9
|
-
"components/cancellable-loader.ts": "7822cb04219440703a9100e02679725b3326fa1c",
|
|
10
|
-
"components/editor.ts": "c7fda44eb8288a10f518791f931cff4fc36c62b5",
|
|
11
|
-
"components/h-stack.ts": "07f8f8ffd055789d69266152f62ee97390bacf01",
|
|
12
|
-
"components/image.ts": "91d68016aae5d292e22a3e892631b7ed53b13e64",
|
|
13
|
-
"components/input.ts": "1bc26453098639991c22515cc94fee89b53f289d",
|
|
14
|
-
"components/loader.ts": "0c59e73a83bb4bd9978818b16bf556da53f48123",
|
|
15
|
-
"components/markdown.ts": "30c40c1715dfc374687b538d447988a81feb237f",
|
|
16
|
-
"components/mouse-region.ts": "a77ded0c1e59167fe2f0643e87531b95ed9e544d",
|
|
17
|
-
"components/scroll-view.ts": "b8f8a51ff0f8f93aabce0df072ee29c5a47c82b3",
|
|
18
|
-
"components/select-list.ts": "f4f4354dd850939e2e84ea8ce8a755206d3e8e43",
|
|
19
|
-
"components/settings-list.ts": "b1b8366bf349b30a1d93073a4cc1d0e2bfa9dc8a",
|
|
20
|
-
"components/spacer.ts": "7abe1551ca79a17bbb03d6b62f3ec18c50274a75",
|
|
21
|
-
"components/stack.ts": "68bde0368455646144a1dd3942b56a48e9d4f45a",
|
|
22
|
-
"components/text.ts": "7a50e2721028d544f641ab5f66ef1b752ff6d1f7",
|
|
23
|
-
"components/truncated-text.ts": "c26b8892967a8462a8828cfed4ea572a73af1602",
|
|
24
|
-
"components/v-stack.ts": "ce7b9292d6dfd0981650a1cf927f223b926f9714",
|
|
25
|
-
"editor-component.ts": "595645033a074d17b8190b73709c2623d3e479b5",
|
|
26
|
-
"fuzzy.ts": "1b5352c1c592956ea614a2ec3630cb6f606ccd83",
|
|
27
|
-
"index.ts": "93fb8b72777a3a4f8423cf4e7d5f74b8dbd982f0",
|
|
28
|
-
"keybindings.ts": "d6afb5ec39642c098b7d95e10ab6b57568e514b4",
|
|
29
|
-
"keys.ts": "8b6f8a0a708cc9a1c9b795ff1ec9766c4209114b",
|
|
30
|
-
"kill-ring.ts": "2292f91aa36baa1bf762df2890bdbed8ca17eb19",
|
|
31
|
-
"latex.ts": "060fd052d820b42903896e53053614e1c578a995",
|
|
32
|
-
"layout-node.ts": "a3c06b24564efaa35321f190641a80e95ce7c7ab",
|
|
33
|
-
"layout.ts": "897c51de2ffbc4c543e87399eaa4e8b6421449ef",
|
|
34
|
-
"native-modifiers.ts": "8cdc60d484717431bd5f1577b36f189275aa06d3",
|
|
35
|
-
"native-module-path.ts": "b75117feb7384da268cfd7d3a8c8fc6af0aeb10e",
|
|
36
|
-
"native-platform.ts": "3a6580a445d8a816225ed824d30e48a93268a761",
|
|
37
|
-
"oklab.ts": "83ddda42fca5bcd485464c74029c2f3db7a5cc6d",
|
|
38
|
-
"stdin-buffer.ts": "cc10c61a55196eb90d9da3e1858e48cab27e925f",
|
|
39
|
-
"terminal-colors.ts": "6a972a95bb5c3c0de65657f4861cdb3ad3579c41",
|
|
40
|
-
"terminal-image.ts": "a84d22c575599c55e5ea96c528e641e54df8511c",
|
|
41
|
-
"terminal.ts": "cce2dd116ca55b2c9f3add30b080a395e8f1f4bb",
|
|
42
|
-
"tui-alt-screen.ts": "bf8affb13ba1d3625711268c8b6f0956c9e5d90e",
|
|
43
|
-
"tui-main-screen.ts": "c079dd776984b23f5e0b4a833ac5b67fb31ff337",
|
|
44
|
-
"tui.ts": "7968a9e792375b9e8701ca4dbe89d18735aa387b",
|
|
45
|
-
"undo-stack.ts": "5b9a7e9cee03a08b5d7ee637b92834a3a28d7fd2",
|
|
46
|
-
"utils.ts": "f537ad7e37dcf35db1259aa05d43f1b45bdef7c7",
|
|
47
|
-
"wheel-scroll.ts": "a6c0018bd4caa9b5bc197d05d548bfdca4036172",
|
|
48
|
-
"word-navigation.ts": "7c7eced2b6ac3ff5b49418824c3ac00a1f0204a3"
|
|
49
|
-
}
|
|
50
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Vendored: pi TUI
|
|
2
|
-
|
|
3
|
-
Source: https://github.com/earendil-works/pi — `packages/tui/src`
|
|
4
|
-
License: MIT (see `LICENSE.upstream`), Copyright (c) 2025 Mario Zechner
|
|
5
|
-
Copied: 2026-09-30
|
|
6
|
-
Commit: `02eed88fd8912e54a804ddebd409e2e4c08ac5ef`
|
|
7
|
-
All 45 source files verified against upstream Git blob hashes in `UPSTREAM.json`.
|
|
8
|
-
|
|
9
|
-
The application also follows coding-agent's CustomEditor, searchable model
|
|
10
|
-
selector and interactive-mode composition. Those product behaviors are adapted
|
|
11
|
-
in `src/tui/` and `src/apps/`; Pi's AgentSession is not imported. Its dark/light
|
|
12
|
-
palette is mapped into `src/core/theme.ts` with attribution there.
|
|
13
|
-
|
|
14
|
-
This directory is an **unmodified copy**. Do not patch it in place: upgrade
|
|
15
|
-
by recopying from upstream. Behaviour changes belong in `src/tui/`, which
|
|
16
|
-
adapts this to xeno and is the only thing allowed to import from here.
|
|
17
|
-
|
|
18
|
-
`AGENTS.md` exempts `src/vendor/` from the import-shape and dependency
|
|
19
|
-
checks, because those exist to keep *our* code's layering decidable and
|
|
20
|
-
upstream organises its code its own way.
|
|
21
|
-
|
|
22
|
-
Native sources and all six upstream prebuilt `.node` binaries are included
|
|
23
|
-
under `native/`, verified by `native/UPSTREAM.json` at the same commit.
|
|
24
|
-
The upstream resolver loads them directly; unavailable platform capabilities
|
|
25
|
-
retain its optional fallback. No install script or startup download is required.
|