oharness 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 (76) hide show
  1. package/dist/bin/sync.d.ts +3 -0
  2. package/dist/bin/sync.js +4 -0
  3. package/dist/bin/sync.js.map +1 -0
  4. package/dist/bin/web.d.ts +10 -0
  5. package/dist/bin/web.js +11 -0
  6. package/dist/bin/web.js.map +1 -0
  7. package/dist/headless/main.d.ts +2 -0
  8. package/dist/headless/main.js +133 -0
  9. package/dist/headless/main.js.map +1 -0
  10. package/dist/index.d.ts +8 -0
  11. package/dist/index.js +9 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/providers.d.ts +2 -0
  14. package/dist/providers.js +3 -0
  15. package/dist/providers.js.map +1 -0
  16. package/dist/tools.d.ts +2 -0
  17. package/dist/tools.js +3 -0
  18. package/dist/tools.js.map +1 -0
  19. package/dist/ui/artifact.d.ts +32 -0
  20. package/dist/ui/artifact.js +49 -0
  21. package/dist/ui/artifact.js.map +1 -0
  22. package/dist/ui/auth.d.ts +14 -0
  23. package/dist/ui/auth.js +177 -0
  24. package/dist/ui/auth.js.map +1 -0
  25. package/dist/ui/colors.d.ts +21 -0
  26. package/dist/ui/colors.js +28 -0
  27. package/dist/ui/colors.js.map +1 -0
  28. package/dist/ui/ink/app.d.ts +13 -0
  29. package/dist/ui/ink/app.js +418 -0
  30. package/dist/ui/ink/app.js.map +1 -0
  31. package/dist/ui/ink/logo.d.ts +6 -0
  32. package/dist/ui/ink/logo.js +20 -0
  33. package/dist/ui/ink/logo.js.map +1 -0
  34. package/dist/ui/ink/main.d.ts +2 -0
  35. package/dist/ui/ink/main.js +55 -0
  36. package/dist/ui/ink/main.js.map +1 -0
  37. package/dist/ui/ink/screen.d.ts +15 -0
  38. package/dist/ui/ink/screen.js +76 -0
  39. package/dist/ui/ink/screen.js.map +1 -0
  40. package/dist/ui/ink/select.d.ts +24 -0
  41. package/dist/ui/ink/select.js +74 -0
  42. package/dist/ui/ink/select.js.map +1 -0
  43. package/dist/ui/main.d.ts +2 -0
  44. package/dist/ui/main.js +1062 -0
  45. package/dist/ui/main.js.map +1 -0
  46. package/dist/ui/render.d.ts +15 -0
  47. package/dist/ui/render.js +130 -0
  48. package/dist/ui/render.js.map +1 -0
  49. package/dist/ui/select.d.ts +26 -0
  50. package/dist/ui/select.js +107 -0
  51. package/dist/ui/select.js.map +1 -0
  52. package/dist/ui/tui/app.d.ts +96 -0
  53. package/dist/ui/tui/app.js +476 -0
  54. package/dist/ui/tui/app.js.map +1 -0
  55. package/dist/ui/tui/editor.d.ts +40 -0
  56. package/dist/ui/tui/editor.js +124 -0
  57. package/dist/ui/tui/editor.js.map +1 -0
  58. package/dist/ui/tui/keys.d.ts +25 -0
  59. package/dist/ui/tui/keys.js +133 -0
  60. package/dist/ui/tui/keys.js.map +1 -0
  61. package/dist/ui/tui/layout.d.ts +63 -0
  62. package/dist/ui/tui/layout.js +202 -0
  63. package/dist/ui/tui/layout.js.map +1 -0
  64. package/dist/ui/tui/logo.d.ts +18 -0
  65. package/dist/ui/tui/logo.js +33 -0
  66. package/dist/ui/tui/logo.js.map +1 -0
  67. package/dist/ui/tui/screen.d.ts +48 -0
  68. package/dist/ui/tui/screen.js +150 -0
  69. package/dist/ui/tui/screen.js.map +1 -0
  70. package/dist/ui/tui/width.d.ts +30 -0
  71. package/dist/ui/tui/width.js +197 -0
  72. package/dist/ui/tui/width.js.map +1 -0
  73. package/dist/ui/wordmark.d.ts +30 -0
  74. package/dist/ui/wordmark.js +63 -0
  75. package/dist/ui/wordmark.js.map +1 -0
  76. package/package.json +49 -0
@@ -0,0 +1,418 @@
1
+ import React from "react";
2
+ import { Box, Text, useApp, useInput, useStdout } from "ink";
3
+ import { MODE_DESCRIPTIONS, MODE_LABELS, PERMISSION_MODES, } from "@oharness/engine/agent/permissions.ts";
4
+ import { errorMessage } from "@oharness/engine/core/errors.ts";
5
+ import { previewJson } from "@oharness/engine/util/json.ts";
6
+ import { Select } from "./select.js";
7
+ import { useTerminalSize } from "./screen.js";
8
+ import { Logo } from "./logo.js";
9
+ /**
10
+ * The terminal interface, rendered with Ink.
11
+ *
12
+ * Written with `React.createElement` rather than JSX. Node's native TypeScript
13
+ * support strips types but does not transform JSX, and every command in this
14
+ * repo runs the source directly — `node src/ui/ink/main.ts`, `node --test`.
15
+ * JSX would mean adding a bundler to development and giving that up. `h` is
16
+ * verbose; a build step is worse.
17
+ *
18
+ * The dialog structure follows opencode: one filterable select behind every
19
+ * picker, and a command palette as the way to find them. Slash commands still
20
+ * work, but nothing depends on remembering them.
21
+ */
22
+ const h = React.createElement;
23
+ /** Entries kept in memory. Ink re-renders the tree, so this bounds the work. */
24
+ const WINDOW = 300;
25
+ export function App({ harness, session, agent, bindPrompt }) {
26
+ const { exit } = useApp();
27
+ const { rows, columns } = useTerminalSize();
28
+ const [entries, setEntries] = React.useState([]);
29
+ const [input, setInput] = React.useState("");
30
+ const [busy, setBusy] = React.useState(false);
31
+ const [label, setLabel] = React.useState("Thinking");
32
+ const [elapsed, setElapsed] = React.useState(0);
33
+ const [dialog, setDialog] = React.useState();
34
+ const [model, setModel] = React.useState(session.model.id);
35
+ const [mode, setMode] = React.useState(session.permissions.getMode());
36
+ const [sessions, setSessions] = React.useState([]);
37
+ const abort = React.useRef(undefined);
38
+ const history = React.useRef([]);
39
+ const historyAt = React.useRef(0);
40
+ const push = React.useCallback((entry) => {
41
+ setEntries((current) => [...current, entry].slice(-WINDOW));
42
+ }, []);
43
+ // Approval arrives from the engine on a different stack, so it is handed in
44
+ // as a promise the dialog resolves.
45
+ React.useEffect(() => {
46
+ bindPrompt((request) => new Promise((resolve) => {
47
+ setDialog({ kind: "permission", request, resolve });
48
+ }));
49
+ }, [bindPrompt]);
50
+ // Elapsed seconds answer "is it stuck?", which is the only question a user
51
+ // has while nothing is streaming.
52
+ React.useEffect(() => {
53
+ if (!busy)
54
+ return setElapsed(0);
55
+ const started = Date.now();
56
+ const timer = setInterval(() => setElapsed(Math.round((Date.now() - started) / 1000)), 1000);
57
+ return () => clearInterval(timer);
58
+ }, [busy]);
59
+ const run = React.useCallback(async (prompt) => {
60
+ setBusy(true);
61
+ setLabel("Thinking");
62
+ abort.current = new AbortController();
63
+ let streaming = false;
64
+ try {
65
+ for await (const event of agent.run(prompt, { signal: abort.current.signal })) {
66
+ switch (event.type) {
67
+ case "text_delta":
68
+ setLabel("Thinking");
69
+ // Appended to the open assistant entry: one row per token would
70
+ // make the transcript unreadable and the diff expensive.
71
+ setEntries((current) => {
72
+ const last = current.at(-1);
73
+ if (streaming && last && last.kind === "assistant") {
74
+ return [...current.slice(0, -1), { ...last, text: last.text + event.text }];
75
+ }
76
+ streaming = true;
77
+ const next = { kind: "assistant", text: event.text };
78
+ return [...current, next].slice(-WINDOW);
79
+ });
80
+ break;
81
+ case "thinking_delta":
82
+ setEntries((current) => {
83
+ const last = current.at(-1);
84
+ if (last && last.kind === "thinking") {
85
+ return [...current.slice(0, -1), { ...last, text: last.text + event.text }];
86
+ }
87
+ const next = { kind: "thinking", text: event.text };
88
+ return [...current, next].slice(-WINDOW);
89
+ });
90
+ break;
91
+ case "assistant_message":
92
+ streaming = false;
93
+ break;
94
+ case "tool_start":
95
+ streaming = false;
96
+ setLabel(event.toolName);
97
+ push({ kind: "tool", title: event.title, done: false });
98
+ break;
99
+ case "tool_end":
100
+ setLabel("Thinking");
101
+ setEntries((current) => {
102
+ const at = current.findLastIndex((entry) => entry.kind === "tool" && !entry.done);
103
+ if (at === -1)
104
+ return current;
105
+ const updated = [...current];
106
+ updated[at] = {
107
+ ...updated[at],
108
+ done: true,
109
+ ms: event.durationMs,
110
+ failed: Boolean(event.result.isError),
111
+ };
112
+ return updated;
113
+ });
114
+ break;
115
+ case "permission_result":
116
+ if (!event.allowed)
117
+ push({ kind: "error", text: event.reason ?? "denied" });
118
+ break;
119
+ case "compacted":
120
+ push({
121
+ kind: "notice",
122
+ text: `compacted ${event.droppedMessages} messages (${event.tokensBefore} → ${event.tokensAfter} tokens)`,
123
+ });
124
+ break;
125
+ case "model_changed":
126
+ setModel(event.to);
127
+ push({ kind: "notice", text: `${event.from} → ${event.to}` });
128
+ break;
129
+ case "notice":
130
+ push({ kind: "notice", text: event.message });
131
+ break;
132
+ case "error":
133
+ streaming = false;
134
+ push({ kind: "error", text: event.error });
135
+ break;
136
+ }
137
+ }
138
+ }
139
+ catch (err) {
140
+ push({ kind: "error", text: errorMessage(err) });
141
+ }
142
+ finally {
143
+ setBusy(false);
144
+ abort.current = undefined;
145
+ }
146
+ }, [agent, push]);
147
+ const submit = React.useCallback((text) => {
148
+ history.current = [...history.current.filter((entry) => entry !== text), text];
149
+ historyAt.current = history.current.length;
150
+ if (text.startsWith("/")) {
151
+ const command = text.slice(1).trim();
152
+ if (command === "exit" || command === "quit")
153
+ return exit();
154
+ if (command === "model")
155
+ return setDialog({ kind: "model" });
156
+ if (command === "mode")
157
+ return setDialog({ kind: "mode" });
158
+ if (command === "sessions")
159
+ return void openSessions();
160
+ if (command === "clear")
161
+ return setEntries([]);
162
+ push({ kind: "error", text: `unknown command: /${command}` });
163
+ return;
164
+ }
165
+ push({ kind: "user", text });
166
+ void run(text);
167
+ }, [exit, push, run]);
168
+ const openSessions = React.useCallback(async () => {
169
+ const list = await harness.listSessions(30);
170
+ setSessions(list.map((meta) => ({ id: meta.id, ...(meta.title ? { title: meta.title } : {}) })));
171
+ setDialog({ kind: "session" });
172
+ }, [harness]);
173
+ useInput((char, key) => {
174
+ if (key.ctrl && char === "c") {
175
+ // Interrupt while working; quit when idle — what a shell does.
176
+ if (busy) {
177
+ abort.current?.abort();
178
+ push({ kind: "notice", text: "(interrupted)" });
179
+ }
180
+ else
181
+ exit();
182
+ return;
183
+ }
184
+ if (key.ctrl && char === "d" && !input)
185
+ return exit();
186
+ // The palette is how everything is reached, so it works while busy.
187
+ if (key.ctrl && char === "k")
188
+ return setDialog({ kind: "palette" });
189
+ if (busy)
190
+ return;
191
+ if (key.return) {
192
+ const text = input.trim();
193
+ if (!text)
194
+ return;
195
+ setInput("");
196
+ submit(text);
197
+ return;
198
+ }
199
+ if (key.upArrow) {
200
+ if (historyAt.current === 0)
201
+ return;
202
+ historyAt.current -= 1;
203
+ return setInput(history.current[historyAt.current] ?? "");
204
+ }
205
+ if (key.downArrow) {
206
+ if (historyAt.current >= history.current.length)
207
+ return;
208
+ historyAt.current += 1;
209
+ return setInput(history.current[historyAt.current] ?? "");
210
+ }
211
+ if (key.backspace || key.delete) {
212
+ return setInput((value) => [...value].slice(0, -1).join(""));
213
+ }
214
+ if (key.escape || key.leftArrow || key.rightArrow || key.tab)
215
+ return;
216
+ if (char && !key.ctrl && !key.meta)
217
+ setInput((value) => value + char);
218
+ },
219
+ // Ink delivers input to every hook; the dialog owns the keyboard while open.
220
+ { isActive: !dialog });
221
+ const width = columns;
222
+ const close = () => setDialog(undefined);
223
+ const empty = entries.length === 0;
224
+ /*
225
+ * One root box the height of the terminal, so flexbox distributes the space
226
+ * instead of the app growing down the scrollback. The transcript takes what
227
+ * is left; the composer and the status bar keep their own rows.
228
+ */
229
+ return h(Box, { flexDirection: "column", width, height: rows }, dialog
230
+ ? h(Box, { flexDirection: "column", flexGrow: 1, justifyContent: "center", paddingX: 2 }, h(DialogView, {
231
+ dialog,
232
+ harness,
233
+ session,
234
+ model,
235
+ mode,
236
+ sessions,
237
+ close,
238
+ setDialog,
239
+ setModel,
240
+ setMode,
241
+ push,
242
+ exit,
243
+ }))
244
+ : empty
245
+ ? h(Home, { columns: width, cwd: session.cwd })
246
+ : h(Box, { flexDirection: "column", flexGrow: 1, overflow: "hidden", paddingX: 2 }, h(Transcript, { entries: entries.slice(-Math.max(1, rows - 8)) })), h(Box, { flexDirection: "column", paddingX: 2 }, h(Box, { borderStyle: "round", borderDimColor: true, paddingX: 1, flexDirection: "column" }, h(Box, null, h(Text, { color: "cyan" }, "› "), input
247
+ ? h(Text, null, input)
248
+ : h(Text, { dimColor: true }, "Ask anything… \"Where is the build entry?\"")), h(Box, { height: 1 }),
249
+ // One line, never wrapped. A discovered id like
250
+ // openrouter/inclusionai/ling-3.0-tiny:free is longer than the box, and
251
+ // letting it wrap broke the row apart — splitting even the mode label
252
+ // across two lines.
253
+ h(Box, { flexWrap: "nowrap" }, busy
254
+ ? h(Text, { color: "yellow", wrap: "truncate-end" }, `${label}…${elapsed > 1 ? ` ${elapsed}s` : ""}`)
255
+ : h(React.Fragment, null,
256
+ // The short labels never shrink. Letting flex compress them
257
+ // alongside the model id turned "Manual" into "Manua" — losing
258
+ // a character from a word that has no room to lose one.
259
+ h(Box, { flexShrink: 0 }, h(Text, { color: "cyan" }, MODE_LABELS[mode]), h(Text, { dimColor: true }, " · ")),
260
+ // Only the model id gives way, and from the front: the tail is
261
+ // what identifies it, the namespace is what can go.
262
+ h(Box, { flexShrink: 1, minWidth: 0 }, h(Text, { wrap: "truncate-start" }, model)), h(Box, { flexShrink: 0 }, h(Text, { dimColor: true }, ` ${session.model.provider}`))))), h(Box, { paddingX: 1 }, h(Text, null, "^K"), h(Text, { dimColor: true }, " commands "), h(Text, null, "^C"), h(Text, { dimColor: true }, busy ? " interrupt " : " quit "), h(Text, null, "↑"), h(Text, { dimColor: true }, " history"))),
263
+ // Pinned to the last row: the working directory is the one piece of
264
+ // context that stays true no matter what is on screen above it.
265
+ h(Box, { paddingX: 2, justifyContent: "space-between" }, h(Text, { dimColor: true, wrap: "truncate-start" }, session.cwd.replace(process.env["HOME"] ?? "", "~")), h(Text, { dimColor: true }, busy ? "working" : "ready")));
266
+ }
267
+ /**
268
+ * The home screen.
269
+ *
270
+ * A wordmark, one line saying what this is, and nothing else. The screen a
271
+ * user meets before they have asked anything should not be a control panel:
272
+ * everything reachable is one keystroke away and listed under the input.
273
+ */
274
+ function Home({ columns, cwd }) {
275
+ return h(Box, { flexDirection: "column", flexGrow: 1, justifyContent: "center", alignItems: "center" }, h(Logo, { columns }), h(Box, { height: 1 }), h(Text, { dimColor: true }, `a model-agnostic agent harness · ${short(cwd)}`));
276
+ }
277
+ // --- transcript ------------------------------------------------------------
278
+ function Transcript({ entries }) {
279
+ return h(Box, { flexDirection: "column", flexGrow: 1 }, ...entries.map((entry, i) => h(Row, { key: i, entry })));
280
+ }
281
+ function Row({ entry }) {
282
+ switch (entry.kind) {
283
+ case "user":
284
+ return h(Text, { bold: true }, `› ${entry.text}`);
285
+ case "assistant":
286
+ return h(Text, null, entry.text);
287
+ case "thinking":
288
+ return h(Text, { dimColor: true, italic: true }, entry.text);
289
+ case "tool":
290
+ return h(Text, { dimColor: true }, `${entry.done ? (entry.failed ? "✗" : "●") : "◐"} ${entry.title}` +
291
+ (entry.ms !== undefined ? ` ${entry.ms}ms` : ""));
292
+ case "notice":
293
+ return h(Text, { dimColor: true }, entry.text);
294
+ case "error":
295
+ return h(Text, { color: "red" }, `✗ ${entry.text}`);
296
+ }
297
+ }
298
+ function DialogView(props) {
299
+ const { dialog, harness, session, model, mode, sessions, close, setDialog } = props;
300
+ if (dialog.kind === "palette") {
301
+ const commands = [
302
+ { value: "model", label: "Switch model", hint: model },
303
+ { value: "mode", label: "Permission mode", hint: MODE_LABELS[mode] },
304
+ { value: "sessions", label: "Open a session" },
305
+ { value: "clear", label: "Clear the transcript" },
306
+ { value: "exit", label: "Quit", hint: "^D" },
307
+ ];
308
+ return h((Select), {
309
+ title: "Commands",
310
+ options: commands,
311
+ onCancel: close,
312
+ onPick: (value) => {
313
+ close();
314
+ if (value === "model")
315
+ return setDialog({ kind: "model" });
316
+ if (value === "mode")
317
+ return setDialog({ kind: "mode" });
318
+ if (value === "sessions")
319
+ return void openSessionList(props);
320
+ if (value === "clear")
321
+ return props.push({ kind: "notice", text: "(cleared)" });
322
+ if (value === "exit")
323
+ return props.exit();
324
+ },
325
+ });
326
+ }
327
+ if (dialog.kind === "model") {
328
+ const options = harness.listModels().map((spec) => ({
329
+ value: spec.id,
330
+ label: spec.id,
331
+ group: spec.provider,
332
+ ...(spec.contextWindow ? { hint: `${Math.round(spec.contextWindow / 1000)}k` } : {}),
333
+ current: spec.id === model,
334
+ }));
335
+ return h((Select), {
336
+ title: "Model",
337
+ options,
338
+ onCancel: close,
339
+ onPick: (id) => {
340
+ close();
341
+ try {
342
+ const change = session.setModel(id);
343
+ props.setModel(change.to.id);
344
+ props.push({ kind: "notice", text: `${change.from.id} → ${change.to.id}` });
345
+ }
346
+ catch (err) {
347
+ props.push({ kind: "error", text: errorMessage(err) });
348
+ }
349
+ },
350
+ });
351
+ }
352
+ if (dialog.kind === "mode") {
353
+ return h((Select), {
354
+ title: "Mode",
355
+ options: PERMISSION_MODES.map((value) => ({
356
+ value,
357
+ label: MODE_LABELS[value],
358
+ hint: MODE_DESCRIPTIONS[value],
359
+ current: value === mode,
360
+ })),
361
+ onCancel: close,
362
+ onPick: (value) => {
363
+ close();
364
+ session.permissions.setMode(value);
365
+ props.setMode(value);
366
+ props.push({ kind: "notice", text: `mode → ${MODE_LABELS[value]}` });
367
+ },
368
+ });
369
+ }
370
+ if (dialog.kind === "session") {
371
+ return h((Select), {
372
+ title: "Sessions",
373
+ options: sessions.map((entry) => ({
374
+ value: entry.id,
375
+ label: entry.title ?? entry.id,
376
+ hint: entry.id,
377
+ current: entry.id === session.id,
378
+ })),
379
+ onCancel: close,
380
+ onPick: (id) => {
381
+ close();
382
+ // Switching sessions needs a new agent; that belongs in main, so for
383
+ // now this reports rather than pretending to have done it.
384
+ props.push({ kind: "notice", text: `resume ${id} — not wired yet` });
385
+ },
386
+ });
387
+ }
388
+ const { request, resolve } = dialog;
389
+ return h((Select), {
390
+ title: `? ${request.title}`,
391
+ detail: [request.reason, previewJson(request.input, 160)].filter(Boolean),
392
+ filterFrom: 99,
393
+ options: [
394
+ { value: true, label: "Yes", hint: "just this once" },
395
+ { value: false, label: "No", hint: "tell the model what to do instead" },
396
+ ],
397
+ onCancel: () => {
398
+ // Cancelling is a refusal. Falling through to the highlighted row would
399
+ // approve something on a stray Escape.
400
+ close();
401
+ resolve(false);
402
+ },
403
+ onPick: (allow) => {
404
+ close();
405
+ resolve(allow);
406
+ },
407
+ });
408
+ }
409
+ async function openSessionList(props) {
410
+ const list = await props.harness.listSessions(30);
411
+ props.setDialog({ kind: "session" });
412
+ void list;
413
+ }
414
+ function short(dir) {
415
+ const parts = dir.replace(/\/+$/, "").split("/");
416
+ return parts[parts.length - 1] ?? dir;
417
+ }
418
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../../src/ui/ink/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ export interface LogoProps {
3
+ /** Below this width the logo is dropped for the mark and the plain name. */
4
+ columns: number;
5
+ }
6
+ export declare function Logo({ columns }: LogoProps): React.ReactElement;
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import { MARK, MARK_GAP, NAME, wordmark } from "../wordmark.js";
4
+ /**
5
+ * The mark and the name.
6
+ *
7
+ * Both live in `../wordmark.ts`, shared with the hand-written frontend; this
8
+ * module only decides how Ink paints them.
9
+ */
10
+ const h = React.createElement;
11
+ export function Logo({ columns }) {
12
+ const { rows, width } = wordmark();
13
+ // A wordmark wider than the terminal wraps into meaningless fragments, so
14
+ // below that it becomes the name in ordinary type.
15
+ if (columns < width + 4) {
16
+ return h(Box, { flexDirection: "column", alignItems: "center" }, h(Text, null, h(Text, { bold: true }, `● ${NAME}`)));
17
+ }
18
+ return h(Box, { flexDirection: "column", alignItems: "center" }, ...[0, 1, 2].map((row) => h(Box, { key: row }, h(Text, { bold: true }, MARK[row]), h(Text, null, " ".repeat(MARK_GAP)), h(Text, { bold: true }, rows[row]))));
19
+ }
20
+ //# sourceMappingURL=logo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logo.js","sourceRoot":"","sources":["../../../src/ui/ink/logo.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEhE;;;;;GAKG;AACH,MAAM,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC;AAO9B,MAAM,UAAU,IAAI,CAAC,EAAE,OAAO,EAAa;IACzC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,QAAQ,EAAE,CAAC;IAEnC,0EAA0E;IAC1E,mDAAmD;IACnD,IAAI,OAAO,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,CACN,GAAG,EACH,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,EACjD,CAAC,CACC,IAAI,EACJ,IAAI,EACJ,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,IAAI,EAAE,CAAC,CACrC,CACF,CAAC;IACJ,CAAC;IAED,OAAO,CAAC,CACN,GAAG,EACH,EAAE,aAAa,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,EACjD,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACvB,CAAC,CACC,GAAG,EACH,EAAE,GAAG,EAAE,GAAG,EAAE,EACZ,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,GAAG,CAAE,CAAC,EACnC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EACnC,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CACnC,CACF,CACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env node
2
+ import React from "react";
3
+ import { render } from "ink";
4
+ import { Harness } from "@oharness/engine/harness.ts";
5
+ import { errorMessage } from "@oharness/engine/core/errors.ts";
6
+ import { App } from "./app.js";
7
+ import { enterFullScreen } from "./screen.js";
8
+ /**
9
+ * The Ink terminal frontend.
10
+ *
11
+ * A second terminal entry point rather than a replacement, so the hand-written
12
+ * one stays runnable while this is judged. Both consume the same AgentEvent
13
+ * stream and neither required an engine change — which is the property that
14
+ * made trying this cheap.
15
+ */
16
+ async function main() {
17
+ if (!process.stdout.isTTY) {
18
+ console.error("oharness-ink needs a terminal; use --print or the headless runner");
19
+ process.exitCode = 1;
20
+ return;
21
+ }
22
+ // The component registers its dialog here once mounted. Until then there is
23
+ // nobody to ask, and defaulting to allow would make the startup window the
24
+ // weakest point in the whole permission system.
25
+ let ask;
26
+ const harness = await Harness.create({
27
+ permissionPrompt: async (request) => (ask ? ask(request) : false),
28
+ });
29
+ const session = await harness.createSession({});
30
+ const agent = harness.agent(session);
31
+ // Taken before the first frame, so nothing is written into the scrollback.
32
+ const screen = enterFullScreen();
33
+ const app = render(React.createElement(App, {
34
+ harness,
35
+ session,
36
+ agent,
37
+ bindPrompt: (prompt) => {
38
+ ask = prompt;
39
+ },
40
+ }),
41
+ // Ink installs its own exit handling; letting it own Ctrl-C would bypass
42
+ // the interrupt-then-quit behaviour the app implements.
43
+ { exitOnCtrlC: false });
44
+ await app.waitUntilExit();
45
+ // Restored before anything else prints, or the teardown messages land on a
46
+ // screen the user is about to lose.
47
+ screen.close();
48
+ await agent.end();
49
+ await harness.close();
50
+ }
51
+ main().catch((err) => {
52
+ console.error(`fatal: ${errorMessage(err)}`);
53
+ process.exitCode = 1;
54
+ });
55
+ //# sourceMappingURL=main.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../../../src/ui/ink/main.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAC;AAEtD,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;;;GAOG;AAEH,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,mEAAmE,CAAC,CAAC;QACnF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,4EAA4E;IAC5E,2EAA2E;IAC3E,gDAAgD;IAChD,IAAI,GAAmE,CAAC;IAExE,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC;QACnC,gBAAgB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;KAClE,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAErC,2EAA2E;IAC3E,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IAEjC,MAAM,GAAG,GAAG,MAAM,CAChB,KAAK,CAAC,aAAa,CAAC,GAAG,EAAE;QACvB,OAAO;QACP,OAAO;QACP,KAAK;QACL,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE;YACrB,GAAG,GAAG,MAAM,CAAC;QACf,CAAC;KACF,CAAC;IACF,yEAAyE;IACzE,wDAAwD;IACxD,EAAE,WAAW,EAAE,KAAK,EAAE,CACvB,CAAC;IAEF,MAAM,GAAG,CAAC,aAAa,EAAE,CAAC;IAC1B,2EAA2E;IAC3E,oCAAoC;IACpC,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC;IAClB,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;AACxB,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,UAAU,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,15 @@
1
+ export interface FullScreen {
2
+ close(): void;
3
+ }
4
+ export declare function enterFullScreen(out?: NodeJS.WriteStream): FullScreen;
5
+ /**
6
+ * The terminal's size, kept current.
7
+ *
8
+ * The root box is sized in rows so flexbox can distribute the space — which
9
+ * means a resize has to re-measure, or the layout keeps the old height and
10
+ * either clips or leaves a band of dead screen.
11
+ */
12
+ export declare function useTerminalSize(): {
13
+ rows: number;
14
+ columns: number;
15
+ };
@@ -0,0 +1,76 @@
1
+ import React from "react";
2
+ /**
3
+ * Full-screen mode for an Ink application.
4
+ *
5
+ * Ink writes into the scrollback by default: the app grows downward and the
6
+ * shell's history stays above it. A full-screen interface needs the alternate
7
+ * buffer instead, which Ink does not manage — so it is entered here, and, more
8
+ * importantly, left again on every exit path.
9
+ *
10
+ * Leaving it is the part that matters. A process that dies in the alternate
11
+ * buffer leaves the user staring at a frozen screen with their shell hidden
12
+ * behind it, and the only recovery is to type reset blind.
13
+ */
14
+ const ESC = "\u001b";
15
+ const ALT_ON = ESC + "[?1049h";
16
+ const ALT_OFF = ESC + "[?1049l";
17
+ const CURSOR_HIDE = ESC + "[?25l";
18
+ const CURSOR_SHOW = ESC + "[?25h";
19
+ const CLEAR = ESC + "[2J" + ESC + "[H";
20
+ export function enterFullScreen(out = process.stdout) {
21
+ let closed = false;
22
+ const close = () => {
23
+ if (closed)
24
+ return;
25
+ closed = true;
26
+ out.write(CURSOR_SHOW + ALT_OFF);
27
+ process.off("exit", close);
28
+ process.off("SIGINT", onSignal);
29
+ process.off("SIGTERM", onSignal);
30
+ process.off("SIGHUP", onSignal);
31
+ };
32
+ const onSignal = () => {
33
+ close();
34
+ // The conventional code for "ended by a signal", so a supervisor reading
35
+ // the status can tell this apart from a clean exit.
36
+ process.exit(130);
37
+ };
38
+ out.write(ALT_ON + CURSOR_HIDE + CLEAR);
39
+ process.on("exit", close);
40
+ process.on("SIGINT", onSignal);
41
+ process.on("SIGTERM", onSignal);
42
+ process.on("SIGHUP", onSignal);
43
+ process.on("uncaughtException", (err) => {
44
+ close();
45
+ console.error(err);
46
+ process.exit(1);
47
+ });
48
+ process.on("unhandledRejection", (err) => {
49
+ close();
50
+ console.error(err);
51
+ process.exit(1);
52
+ });
53
+ return { close };
54
+ }
55
+ /**
56
+ * The terminal's size, kept current.
57
+ *
58
+ * The root box is sized in rows so flexbox can distribute the space — which
59
+ * means a resize has to re-measure, or the layout keeps the old height and
60
+ * either clips or leaves a band of dead screen.
61
+ */
62
+ export function useTerminalSize() {
63
+ const [size, setSize] = React.useState(() => ({
64
+ rows: process.stdout.rows || 24,
65
+ columns: process.stdout.columns || 80,
66
+ }));
67
+ React.useEffect(() => {
68
+ const onResize = () => setSize({ rows: process.stdout.rows || 24, columns: process.stdout.columns || 80 });
69
+ process.stdout.on("resize", onResize);
70
+ return () => {
71
+ process.stdout.off("resize", onResize);
72
+ };
73
+ }, []);
74
+ return size;
75
+ }
76
+ //# sourceMappingURL=screen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screen.js","sourceRoot":"","sources":["../../../src/ui/ink/screen.ts"],"names":[],"mappings":"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"}