@visual-z/xeno 0.1.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.
Files changed (180) hide show
  1. package/README.md +498 -0
  2. package/docs/install.md +130 -0
  3. package/package.json +43 -0
  4. package/src/apps/approve.ts +49 -0
  5. package/src/apps/cli.ts +37 -0
  6. package/src/apps/commands.ts +226 -0
  7. package/src/apps/completions.ts +28 -0
  8. package/src/apps/input.ts +297 -0
  9. package/src/apps/render.ts +207 -0
  10. package/src/apps/shell.ts +2353 -0
  11. package/src/apps/startup.ts +1302 -0
  12. package/src/core/benchmark.ts +195 -0
  13. package/src/core/boundary.ts +174 -0
  14. package/src/core/churn.ts +59 -0
  15. package/src/core/completion-review.ts +66 -0
  16. package/src/core/context-policy.ts +60 -0
  17. package/src/core/context-window.ts +54 -0
  18. package/src/core/continuation.ts +114 -0
  19. package/src/core/cycle.ts +17 -0
  20. package/src/core/data-query.ts +201 -0
  21. package/src/core/deadline.ts +39 -0
  22. package/src/core/derive.ts +489 -0
  23. package/src/core/edit-plan.ts +200 -0
  24. package/src/core/environment.ts +29 -0
  25. package/src/core/event-validation.ts +99 -0
  26. package/src/core/events.ts +486 -0
  27. package/src/core/evidence-links.ts +71 -0
  28. package/src/core/evidence.ts +89 -0
  29. package/src/core/execution.ts +12 -0
  30. package/src/core/exhaustive.ts +18 -0
  31. package/src/core/experiment.ts +40 -0
  32. package/src/core/export.ts +169 -0
  33. package/src/core/file-references.ts +35 -0
  34. package/src/core/frontmatter.ts +213 -0
  35. package/src/core/handoff.ts +397 -0
  36. package/src/core/harness-comparison.ts +90 -0
  37. package/src/core/history-query.ts +103 -0
  38. package/src/core/history.ts +100 -0
  39. package/src/core/json-event.ts +135 -0
  40. package/src/core/json-pointer.ts +46 -0
  41. package/src/core/keymap.ts +241 -0
  42. package/src/core/observation-view.ts +87 -0
  43. package/src/core/outcome.ts +45 -0
  44. package/src/core/overflow.ts +59 -0
  45. package/src/core/permissions.ts +182 -0
  46. package/src/core/policy-evaluation.ts +55 -0
  47. package/src/core/progress.ts +101 -0
  48. package/src/core/project.ts +372 -0
  49. package/src/core/prompts.ts +83 -0
  50. package/src/core/queue.ts +60 -0
  51. package/src/core/read-bounds.ts +15 -0
  52. package/src/core/recall-analysis.ts +90 -0
  53. package/src/core/recall-trial.ts +153 -0
  54. package/src/core/response-recovery.ts +46 -0
  55. package/src/core/scheduling.ts +8 -0
  56. package/src/core/settings.ts +174 -0
  57. package/src/core/skills.ts +121 -0
  58. package/src/core/stall.ts +48 -0
  59. package/src/core/text-normalize.ts +81 -0
  60. package/src/core/theme.ts +179 -0
  61. package/src/core/tokens.ts +149 -0
  62. package/src/core/tool-contract.ts +102 -0
  63. package/src/core/tool-input.ts +38 -0
  64. package/src/core/transcript.ts +60 -0
  65. package/src/core/window-trial.ts +65 -0
  66. package/src/core/work-state.ts +103 -0
  67. package/src/core/yaml.ts +282 -0
  68. package/src/index.ts +10 -0
  69. package/src/runtime/auth.ts +255 -0
  70. package/src/runtime/benchmark.ts +187 -0
  71. package/src/runtime/catalog.ts +365 -0
  72. package/src/runtime/evidence-notes.ts +33 -0
  73. package/src/runtime/exec-sessions.ts +214 -0
  74. package/src/runtime/execution-control.ts +39 -0
  75. package/src/runtime/harness-comparison.ts +356 -0
  76. package/src/runtime/history-tools.ts +108 -0
  77. package/src/runtime/loop.ts +1983 -0
  78. package/src/runtime/model.ts +614 -0
  79. package/src/runtime/models-fetch.ts +155 -0
  80. package/src/runtime/oauth-device.ts +86 -0
  81. package/src/runtime/oauth.ts +759 -0
  82. package/src/runtime/openai-responses.ts +286 -0
  83. package/src/runtime/openai.ts +675 -0
  84. package/src/runtime/provider.ts +498 -0
  85. package/src/runtime/recall-trial.ts +226 -0
  86. package/src/runtime/resume.ts +66 -0
  87. package/src/runtime/retry.ts +297 -0
  88. package/src/runtime/tools.ts +1193 -0
  89. package/src/runtime/usage.ts +225 -0
  90. package/src/runtime/window-trial.ts +140 -0
  91. package/src/runtime/working-notes.ts +30 -0
  92. package/src/store/atomic.ts +31 -0
  93. package/src/store/auth-store.ts +50 -0
  94. package/src/store/blobs.ts +142 -0
  95. package/src/store/command.ts +75 -0
  96. package/src/store/config.ts +69 -0
  97. package/src/store/context-files.ts +356 -0
  98. package/src/store/file-index.ts +81 -0
  99. package/src/store/git-branch.ts +35 -0
  100. package/src/store/history-search.ts +19 -0
  101. package/src/store/log.ts +642 -0
  102. package/src/store/models.ts +41 -0
  103. package/src/store/observations.ts +181 -0
  104. package/src/store/query-source.ts +44 -0
  105. package/src/store/recovery.ts +39 -0
  106. package/src/store/replay.ts +63 -0
  107. package/src/store/resources.ts +361 -0
  108. package/src/store/restore.ts +302 -0
  109. package/src/store/search.ts +644 -0
  110. package/src/store/serial.ts +13 -0
  111. package/src/store/sessions.ts +463 -0
  112. package/src/store/trust.ts +69 -0
  113. package/src/store/workspace.ts +256 -0
  114. package/src/store/worktree.ts +233 -0
  115. package/src/tui/ansi.ts +67 -0
  116. package/src/tui/autocomplete.ts +29 -0
  117. package/src/tui/complete.ts +87 -0
  118. package/src/tui/diff.ts +160 -0
  119. package/src/tui/editor.ts +893 -0
  120. package/src/tui/exhaustive.ts +14 -0
  121. package/src/tui/fuzzy.ts +75 -0
  122. package/src/tui/host.ts +223 -0
  123. package/src/tui/input.ts +69 -0
  124. package/src/tui/keys.ts +378 -0
  125. package/src/tui/markdown.ts +17 -0
  126. package/src/tui/render.ts +153 -0
  127. package/src/tui/select.ts +240 -0
  128. package/src/tui/settings.ts +40 -0
  129. package/src/tui/statusline.ts +162 -0
  130. package/src/tui/style.ts +205 -0
  131. package/src/tui/terminal.ts +30 -0
  132. package/src/tui/text.ts +52 -0
  133. package/src/tui/toolview.ts +386 -0
  134. package/src/tui/transcript.ts +71 -0
  135. package/src/tui/tree.ts +405 -0
  136. package/src/tui/width.ts +567 -0
  137. package/src/vendor/pi-tui/LICENSE.upstream +21 -0
  138. package/src/vendor/pi-tui/VENDOR.md +23 -0
  139. package/src/vendor/pi-tui/alt-screen-search.ts +327 -0
  140. package/src/vendor/pi-tui/autocomplete.ts +835 -0
  141. package/src/vendor/pi-tui/components/alt-screen-flash.ts +51 -0
  142. package/src/vendor/pi-tui/components/box.ts +167 -0
  143. package/src/vendor/pi-tui/components/cancellable-loader.ts +40 -0
  144. package/src/vendor/pi-tui/components/editor.ts +2470 -0
  145. package/src/vendor/pi-tui/components/h-stack.ts +44 -0
  146. package/src/vendor/pi-tui/components/image.ts +127 -0
  147. package/src/vendor/pi-tui/components/input.ts +494 -0
  148. package/src/vendor/pi-tui/components/loader.ts +101 -0
  149. package/src/vendor/pi-tui/components/markdown.ts +1015 -0
  150. package/src/vendor/pi-tui/components/mouse-region.ts +33 -0
  151. package/src/vendor/pi-tui/components/scroll-view.ts +224 -0
  152. package/src/vendor/pi-tui/components/select-list.ts +273 -0
  153. package/src/vendor/pi-tui/components/settings-list.ts +328 -0
  154. package/src/vendor/pi-tui/components/spacer.ts +28 -0
  155. package/src/vendor/pi-tui/components/stack.ts +154 -0
  156. package/src/vendor/pi-tui/components/text.ts +107 -0
  157. package/src/vendor/pi-tui/components/truncated-text.ts +65 -0
  158. package/src/vendor/pi-tui/components/v-stack.ts +33 -0
  159. package/src/vendor/pi-tui/editor-component.ts +74 -0
  160. package/src/vendor/pi-tui/fuzzy.ts +138 -0
  161. package/src/vendor/pi-tui/index.ts +156 -0
  162. package/src/vendor/pi-tui/keybindings.ts +320 -0
  163. package/src/vendor/pi-tui/keys.ts +1401 -0
  164. package/src/vendor/pi-tui/kill-ring.ts +46 -0
  165. package/src/vendor/pi-tui/latex.ts +1506 -0
  166. package/src/vendor/pi-tui/layout-node.ts +51 -0
  167. package/src/vendor/pi-tui/layout.ts +449 -0
  168. package/src/vendor/pi-tui/native-modifiers.ts +13 -0
  169. package/src/vendor/pi-tui/native-module-path.ts +31 -0
  170. package/src/vendor/pi-tui/native-platform.ts +63 -0
  171. package/src/vendor/pi-tui/stdin-buffer.ts +444 -0
  172. package/src/vendor/pi-tui/terminal-colors.ts +73 -0
  173. package/src/vendor/pi-tui/terminal-image.ts +696 -0
  174. package/src/vendor/pi-tui/terminal.ts +547 -0
  175. package/src/vendor/pi-tui/tui-alt-screen.ts +1742 -0
  176. package/src/vendor/pi-tui/tui-main-screen.ts +655 -0
  177. package/src/vendor/pi-tui/tui.ts +1456 -0
  178. package/src/vendor/pi-tui/undo-stack.ts +28 -0
  179. package/src/vendor/pi-tui/utils.ts +1345 -0
  180. package/src/vendor/pi-tui/word-navigation.ts +117 -0
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Loop events become lines. The shell prints them; this file does not
3
+ * touch a terminal, so "what a tool call looks like" can be asserted
4
+ * without starting one.
5
+ *
6
+ * Colour is a parameter, not a global. Piped and CI runs have no tty,
7
+ * and a CSI 2026 (or even a dim code) in `-p` output is a parse error
8
+ * waiting for a script.
9
+ */
10
+
11
+ import { assertNever } from "../core/exhaustive.ts";
12
+ import type { LoopEvent } from "../runtime/loop.ts";
13
+ import { renderMarkdown } from "../tui/markdown.ts";
14
+ import { ANSI as ANSI_STYLE, IDENTITY, type Style } from "../tui/style.ts";
15
+ import { renderToolView, type ToolViewEvent } from "../tui/toolview.ts";
16
+
17
+ export interface Palette {
18
+ dim: (s: string) => string;
19
+ bold: (s: string) => string;
20
+ red: (s: string) => string;
21
+ green: (s: string) => string;
22
+ yellow: (s: string) => string;
23
+ cyan: (s: string) => string;
24
+ }
25
+
26
+ const identity = (s: string): string => s;
27
+
28
+ const ANSI: Palette = {
29
+ dim: (s) => `\x1b[2m${s}\x1b[0m`,
30
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
31
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
32
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
33
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
34
+ cyan: (s) => `\x1b[36m${s}\x1b[0m`,
35
+ };
36
+
37
+ const PLAIN: Palette = {
38
+ dim: identity,
39
+ bold: identity,
40
+ red: identity,
41
+ green: identity,
42
+ yellow: identity,
43
+ cyan: identity,
44
+ };
45
+
46
+ export function createPalette(color: boolean): Palette {
47
+ return color ? ANSI : PLAIN;
48
+ }
49
+
50
+ /**
51
+ * Colour is a tty AND not NO_COLOR. A theme that still emits ESC in a pipe
52
+ * or under NO_COLOR is the same class of bug as createPalette(true) on a
53
+ * redirected stdout.
54
+ */
55
+ export function colorEnabled(): boolean {
56
+ const noColor = process.env["NO_COLOR"];
57
+ if (noColor !== undefined && noColor !== "") return false;
58
+ return stdoutIsTty();
59
+ }
60
+
61
+ /** True only for a real tty. `undefined` (piped, CI) must not count. */
62
+ export function stdoutIsTty(): boolean {
63
+ return process.stdout.isTTY === true;
64
+ }
65
+
66
+ export function stdinIsTty(): boolean {
67
+ return process.stdin.isTTY === true;
68
+ }
69
+
70
+ /**
71
+ * One readable line from whatever was thrown.
72
+ *
73
+ * Never a stack. A stack is for whoever wrote the harness; the person running
74
+ * it needs the status and the provider's own sentence, which is the part that
75
+ * says whether this is their key, their quota, or the provider being down.
76
+ */
77
+ export function describeError(error: unknown): string {
78
+ if (error instanceof Error) {
79
+ const status = (error as { status?: unknown }).status;
80
+ const prefix = typeof status === "number" ? `HTTP ${status}: ` : "";
81
+ return error.message.startsWith("HTTP ") ? error.message : prefix + error.message;
82
+ }
83
+ return String(error);
84
+ }
85
+
86
+ export function indent(text: string, pad: string): string {
87
+ return text.split("\n").map((l) => pad + l).join("\n");
88
+ }
89
+
90
+ export function wrap(text: string, width: number): string {
91
+ const out: string[] = [];
92
+ let line = "";
93
+ for (const word of text.split(/\s+/)) {
94
+ if (line && line.length + word.length + 1 > width) { out.push(line); line = word; }
95
+ else line = line ? `${line} ${word}` : word;
96
+ }
97
+ if (line) out.push(line);
98
+ return out.join("\n");
99
+ }
100
+
101
+ export function firstLine(text: string, width: number): string {
102
+ const line = text.split("\n")[0] ?? "";
103
+ return line.length > width ? line.slice(0, width - 1) + "…" : line;
104
+ }
105
+
106
+ /**
107
+ * Zero or more lines that the shell will print, matching the previous
108
+ * inline switch one-for-one -- including the leading newline on
109
+ * stop_and_ask, which is a blank line in the transcript.
110
+ *
111
+ * Kinds the old CLI ignored stay silent so this extraction cannot change
112
+ * what a piped run prints.
113
+ */
114
+ function markdownStyle(C: Palette, style?: Style): Style {
115
+ if (style !== undefined) return style;
116
+ // Palette has no colour flag; identity wrappers are how -p and pipes
117
+ // already opt out of CSI. A sentinel that round-trips is that same gate.
118
+ return C.bold("\0") === "\0" ? IDENTITY : ANSI_STYLE;
119
+ }
120
+
121
+ export interface FormatFlags {
122
+ readonly toolsExpanded?: boolean;
123
+ readonly thinkingExpanded?: boolean;
124
+ }
125
+
126
+ export function toToolView(e: LoopEvent): ToolViewEvent | null {
127
+ switch (e.kind) {
128
+ case "thinking":
129
+ return { kind: "thinking", text: e.text ?? "" };
130
+ case "tool_call":
131
+ return { kind: "tool_call", tool: e.tool ?? { name: "", input: {} } };
132
+ case "tool_result":
133
+ return {
134
+ kind: "tool_result",
135
+ text: e.text ?? "",
136
+ ok: e.ok !== false,
137
+ ...(e.tool !== undefined ? { tool: e.tool } : {}),
138
+ };
139
+ default:
140
+ return null;
141
+ }
142
+ }
143
+
144
+ export function formatEvent(
145
+ e: LoopEvent,
146
+ C: Palette,
147
+ width = 80,
148
+ flags: FormatFlags = {},
149
+ style?: Style,
150
+ ): string[] {
151
+ const md = markdownStyle(C, style);
152
+ switch (e.kind) {
153
+ case "thinking":
154
+ return renderToolView(
155
+ { kind: "thinking", text: e.text ?? "" },
156
+ flags.thinkingExpanded === true,
157
+ width,
158
+ md,
159
+ );
160
+ case "assistant_text":
161
+ return renderMarkdown(e.text ?? "", width, md);
162
+ case "tool_call":
163
+ return renderToolView(
164
+ { kind: "tool_call", tool: e.tool ?? { name: "", input: {} } },
165
+ flags.toolsExpanded === true,
166
+ width,
167
+ md,
168
+ );
169
+ case "tool_result":
170
+ return renderToolView(
171
+ {
172
+ kind: "tool_result",
173
+ text: e.text ?? "",
174
+ ok: e.ok !== false,
175
+ ...(e.tool !== undefined ? { tool: e.tool } : {}),
176
+ },
177
+ flags.toolsExpanded === true,
178
+ width,
179
+ md,
180
+ );
181
+ case "usage": {
182
+ const u = e.usage!;
183
+ const line =
184
+ ` ${u.input_tokens} new ${u.cache_read_input_tokens} cached ` +
185
+ `${u.cache_creation_input_tokens} written ${u.output_tokens} out ${u.ms}ms`;
186
+ return [e.ok ? C.dim(line) : C.yellow(line + ` ⚠ ${e.prefix}`)];
187
+ }
188
+ case "cut":
189
+ return [C.yellow(` ── node ${e.node} closed (${e.reason}); handoff written`)];
190
+ case "stop_and_ask":
191
+ return [C.red(`\n stopping: ${e.reason}`)];
192
+ case "done":
193
+ if (e.reason && e.reason !== "end_turn") return [C.dim(` [${e.reason}]`)];
194
+ return [];
195
+ case "turn_start":
196
+ case "branch_start":
197
+ case "branch_done":
198
+ case "snapshot_failed":
199
+ case "undeclared_change":
200
+ case "text_delta":
201
+ case "thinking_delta":
202
+ case "discard":
203
+ return [];
204
+ default:
205
+ return assertNever(e.kind, "formatEvent");
206
+ }
207
+ }