@oxbit/cli 0.11.2 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent/dist/assets/{index-hc_7c2Gx.js → index-DU-a4mnM.js} +215 -27
- package/agent/dist/index.js +6 -3
- package/package.json +1 -1
- package/runtime/dist/index.js +1 -1
- package/runtime/package.json +1 -1
- package/web/dist/assets/{index-BW3klpDi.js → index-C8DIIrnZ.js} +170 -170
- package/web/dist/assets/{typescript-_U0BOK1e.js → typescript-Z_qrZEol.js} +2 -2
- package/web/dist/index.html +1 -1
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
3
|
import { Box, Text, renderToString, useAnimation, measureElement, useInput, useWindowSize, usePaste, Static, render } from "ink";
|
|
4
|
-
import { createContext, useContext, useMemo, useState, useRef, useEffect, useSyncExternalStore } from "react";
|
|
4
|
+
import { createContext, useContext, useMemo, useState, useRef, useEffect, memo, useSyncExternalStore } from "react";
|
|
5
5
|
import { c as contextLegend, a as contextGrid, f as formatTokens, b as contextNotes, d as formatPercent, M as MODES } from "../index.js";
|
|
6
|
+
import { writeFile } from "node:fs/promises";
|
|
7
|
+
import { homedir } from "node:os";
|
|
8
|
+
import { resolve } from "node:path";
|
|
6
9
|
import { memoryTuiConnection, fileHistory } from "./memory-Bdy8hvTl.js";
|
|
7
10
|
import "node:util";
|
|
8
11
|
import "node:readline";
|
|
9
|
-
import "node:fs/promises";
|
|
10
|
-
import "node:path";
|
|
11
12
|
import "node:crypto";
|
|
12
|
-
import "node:os";
|
|
13
13
|
import "node:child_process";
|
|
14
14
|
import "node:http";
|
|
15
15
|
import "node:fs";
|
|
@@ -1212,6 +1212,7 @@ class SessionController {
|
|
|
1212
1212
|
draft: emptyDraft,
|
|
1213
1213
|
running: false,
|
|
1214
1214
|
queued: [],
|
|
1215
|
+
generation: 0,
|
|
1215
1216
|
status: emptyStatus(),
|
|
1216
1217
|
info: connection.info()
|
|
1217
1218
|
};
|
|
@@ -1263,9 +1264,9 @@ class SessionController {
|
|
|
1263
1264
|
};
|
|
1264
1265
|
commandsChanged() {
|
|
1265
1266
|
}
|
|
1266
|
-
onPermission = (request) => new Promise((
|
|
1267
|
-
if (this.rules.has(ruleKey(request))) return
|
|
1268
|
-
this.permissions.push({ request, resolve, index: 0 });
|
|
1267
|
+
onPermission = (request) => new Promise((resolve2) => {
|
|
1268
|
+
if (this.rules.has(ruleKey(request))) return resolve2(outcomeOf(request, "once").outcome);
|
|
1269
|
+
this.permissions.push({ request, resolve: resolve2, index: 0 });
|
|
1269
1270
|
if (this.permissions.length === 1) this.set({ permission: this.permissions[0] });
|
|
1270
1271
|
});
|
|
1271
1272
|
/** Opens `sessionId` (or a new session) and replays updates that arrived before the response. */
|
|
@@ -1575,9 +1576,53 @@ class PanelController extends SessionController {
|
|
|
1575
1576
|
this.closeOverlay();
|
|
1576
1577
|
}
|
|
1577
1578
|
}
|
|
1579
|
+
const joined = (items) => items.reduce((text, item) => item.part || !text ? text + item.text : `${text.trimEnd()}
|
|
1580
|
+
|
|
1581
|
+
${item.text}`, "").trim();
|
|
1582
|
+
function lastReply(items) {
|
|
1583
|
+
const end2 = items.findLastIndex((item) => item.type === "assistant" && item.text.trim());
|
|
1584
|
+
if (end2 < 0) return void 0;
|
|
1585
|
+
const start = items.slice(0, end2).findLastIndex((item) => item.type === "user") + 1;
|
|
1586
|
+
return joined(items.slice(start, end2 + 1).filter((item) => item.type === "assistant")) || void 0;
|
|
1587
|
+
}
|
|
1588
|
+
function toMarkdown(items, title, sessionId) {
|
|
1589
|
+
const blocks = [`# ${title || "Oxbit Agent session"}`, ...sessionId ? [`Session \`${sessionId}\``] : []];
|
|
1590
|
+
let reply = [];
|
|
1591
|
+
let agent = false;
|
|
1592
|
+
const close = () => {
|
|
1593
|
+
const text = joined(reply);
|
|
1594
|
+
if (text) blocks.push(text);
|
|
1595
|
+
reply = [];
|
|
1596
|
+
};
|
|
1597
|
+
for (const item of items) {
|
|
1598
|
+
if (item.type === "user") {
|
|
1599
|
+
close();
|
|
1600
|
+
agent = false;
|
|
1601
|
+
blocks.push(item.continuation ? "## User (continuation)" : "## User", item.text.trim());
|
|
1602
|
+
continue;
|
|
1603
|
+
}
|
|
1604
|
+
if (item.type !== "assistant" && item.type !== "tool") continue;
|
|
1605
|
+
if (!agent) blocks.push("## Agent");
|
|
1606
|
+
agent = true;
|
|
1607
|
+
if (item.type === "assistant") {
|
|
1608
|
+
if (!item.part) close();
|
|
1609
|
+
reply.push(item);
|
|
1610
|
+
} else {
|
|
1611
|
+
close();
|
|
1612
|
+
blocks.push(`- Tool: ${item.tool.title} (${item.tool.status})`);
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
close();
|
|
1616
|
+
return `${blocks.join("\n\n")}
|
|
1617
|
+
`;
|
|
1618
|
+
}
|
|
1619
|
+
const osc52 = (text) => `\x1B]52;c;${Buffer.from(text).toString("base64")}\x07`;
|
|
1620
|
+
const oscTitle = (title) => `\x1B]2;${title.replace(/[\x00-\x1f\x7f]/g, " ")}\x07`;
|
|
1621
|
+
const windowTitle = (title, running) => `${running ? "● " : ""}${title || "Oxbit Agent"}`;
|
|
1578
1622
|
const LOCAL_COMMANDS = [
|
|
1579
1623
|
{ name: "model", description: "Choose the model and reasoning effort", hint: "[model]" },
|
|
1580
1624
|
{ name: "new", description: "Start a new session" },
|
|
1625
|
+
{ name: "clear", description: "Clear the conversation and the screen, and start a new session" },
|
|
1581
1626
|
{ name: "resume", description: "Resume a saved session" },
|
|
1582
1627
|
{ name: "config", description: "Settings: permission mode, auto-compact, hooks and MCP trust" },
|
|
1583
1628
|
{ name: "skills", description: "Turn skills on or off, or start a prompt with one" },
|
|
@@ -1585,9 +1630,13 @@ const LOCAL_COMMANDS = [
|
|
|
1585
1630
|
{ name: "mcp", description: "Add, remove, trust and sign in to MCP servers" },
|
|
1586
1631
|
{ name: "instructions", description: "Choose which AGENTS.md and CLAUDE.md files load" },
|
|
1587
1632
|
{ name: "providers", description: "Sign in to providers and set API keys" },
|
|
1633
|
+
{ name: "copy", description: "Copy the last agent reply to the clipboard" },
|
|
1634
|
+
{ name: "export", description: "Write the conversation to a Markdown file", hint: "[path]" },
|
|
1635
|
+
{ name: "init", description: "Ask the agent to create or update AGENTS.md for this repository" },
|
|
1588
1636
|
{ name: "help", description: "Show keys and commands" },
|
|
1589
1637
|
{ name: "exit", description: "Quit" }
|
|
1590
1638
|
];
|
|
1639
|
+
const INIT_PROMPT = "Inspect this repository and create or update AGENTS.md at its root. Document the build, test and lint commands, the project layout, and the coding conventions an agent needs to work here. Keep existing content that is still accurate.";
|
|
1591
1640
|
const picker = (overlay) => overlay?.kind === "models" || overlay?.kind === "sessions" ? overlay : void 0;
|
|
1592
1641
|
function overlayItems(state) {
|
|
1593
1642
|
const overlay = state.overlay;
|
|
@@ -1611,6 +1660,8 @@ class Controller extends PanelController {
|
|
|
1611
1660
|
fileTimer;
|
|
1612
1661
|
files = /* @__PURE__ */ new Map();
|
|
1613
1662
|
lastInterrupt = 0;
|
|
1663
|
+
/** Set by the fullscreen transcript view; reads the current layout. */
|
|
1664
|
+
viewport;
|
|
1614
1665
|
/** Server commands, then local ones; a panel command shows the server command's hint, since arguments go to the server. */
|
|
1615
1666
|
commands() {
|
|
1616
1667
|
const server = this.state.status.commands;
|
|
@@ -1631,6 +1682,9 @@ class Controller extends PanelController {
|
|
|
1631
1682
|
this.dismissed = void 0;
|
|
1632
1683
|
this.set({ draft: emptyDraft, completion: void 0 });
|
|
1633
1684
|
if (text.startsWith("/") && this.local(text)) return;
|
|
1685
|
+
this.prompt(text);
|
|
1686
|
+
}
|
|
1687
|
+
prompt(text) {
|
|
1634
1688
|
if (this.state.running) this.set({ queued: [...this.state.queued, text] });
|
|
1635
1689
|
else void this.send(text);
|
|
1636
1690
|
}
|
|
@@ -1645,6 +1699,18 @@ class Controller extends PanelController {
|
|
|
1645
1699
|
case "new":
|
|
1646
1700
|
void this.open(void 0, "New session");
|
|
1647
1701
|
return true;
|
|
1702
|
+
case "clear":
|
|
1703
|
+
void this.clear();
|
|
1704
|
+
return true;
|
|
1705
|
+
case "copy":
|
|
1706
|
+
this.copyReply();
|
|
1707
|
+
return true;
|
|
1708
|
+
case "export":
|
|
1709
|
+
void this.exportTo(args);
|
|
1710
|
+
return true;
|
|
1711
|
+
case "init":
|
|
1712
|
+
this.prompt(INIT_PROMPT);
|
|
1713
|
+
return true;
|
|
1648
1714
|
case "resume":
|
|
1649
1715
|
if (!this.connection.listSessions && !args) return false;
|
|
1650
1716
|
if (args) void this.open(args, "Resumed session");
|
|
@@ -1772,6 +1838,49 @@ class Controller extends PanelController {
|
|
|
1772
1838
|
const next = items[Math.min(items.length - 1, Math.max(0, at + step - (overlay?.kind === "details" ? 0 : 1)))];
|
|
1773
1839
|
this.set({ overlay: { kind: "details", id: next.id } });
|
|
1774
1840
|
}
|
|
1841
|
+
/** /clear: empties the transcript, queue and screen, then opens a new session. */
|
|
1842
|
+
async clear() {
|
|
1843
|
+
if (this.state.running) return this.notice("Wait for the agent to finish, or press Esc to stop it", "warn");
|
|
1844
|
+
this.options.screen?.clear();
|
|
1845
|
+
this.set({ transcript: emptyTranscript(), queued: [], overlay: void 0, completion: void 0, scroll: void 0, generation: this.state.generation + 1 });
|
|
1846
|
+
await this.open();
|
|
1847
|
+
}
|
|
1848
|
+
/** Ctrl+L: clears the terminal and draws the current frame again at the newest output. */
|
|
1849
|
+
redraw() {
|
|
1850
|
+
this.options.screen?.clear();
|
|
1851
|
+
this.set({ scroll: void 0 });
|
|
1852
|
+
}
|
|
1853
|
+
copyReply() {
|
|
1854
|
+
const { flushed, live } = this.state.transcript;
|
|
1855
|
+
const reply = lastReply([...flushed, ...live]);
|
|
1856
|
+
if (!reply) return this.flash("There is no agent reply to copy yet");
|
|
1857
|
+
this.options.screen?.write(osc52(reply));
|
|
1858
|
+
this.flash("Copied the last reply to the clipboard");
|
|
1859
|
+
}
|
|
1860
|
+
/** Writes the conversation as Markdown; an existing file is left alone. */
|
|
1861
|
+
async exportTo(path) {
|
|
1862
|
+
const { transcript: { flushed, live }, status: { sessionId, title } } = this.state;
|
|
1863
|
+
const target = resolve(this.options.cwd, path.replace(/^~(?=$|\/)/, homedir()) || `oxbit-session-${sessionId?.slice(0, 8) ?? "new"}.md`);
|
|
1864
|
+
try {
|
|
1865
|
+
await writeFile(target, toMarkdown([...flushed, ...live], title, sessionId), { flag: "wx" });
|
|
1866
|
+
this.notice(`Exported the conversation to ${target}`);
|
|
1867
|
+
} catch (error) {
|
|
1868
|
+
this.notice(error.code === "EEXIST" ? `${target} already exists. Choose another path.` : message(error), "error");
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
/** PageUp and PageDown in fullscreen; reaching the bottom follows the newest output again. */
|
|
1872
|
+
scrollBy(pages) {
|
|
1873
|
+
const viewport = this.viewport?.();
|
|
1874
|
+
if (!viewport) return;
|
|
1875
|
+
const { total, height, first } = viewport;
|
|
1876
|
+
const max = Math.max(0, total - height);
|
|
1877
|
+
const scroll = this.state.scroll;
|
|
1878
|
+
const top = Math.min(max, Math.max(0, Math.min(scroll?.top ?? max, max) + pages * Math.max(1, height - 2)));
|
|
1879
|
+
this.set({ scroll: top >= max ? void 0 : { top, from: scroll?.from ?? first } });
|
|
1880
|
+
}
|
|
1881
|
+
scrollEnd() {
|
|
1882
|
+
if (this.state.scroll) this.set({ scroll: void 0 });
|
|
1883
|
+
}
|
|
1775
1884
|
/** Ctrl+C: stop the turn, close or clear, and exit on a second press within two seconds. */
|
|
1776
1885
|
interrupt() {
|
|
1777
1886
|
const now = Date.now();
|
|
@@ -1797,6 +1906,8 @@ const KEYS = [
|
|
|
1797
1906
|
["ctrl+o", "show tool output, diffs and thinking in full"],
|
|
1798
1907
|
["ctrl+p, /model", "choose the model"],
|
|
1799
1908
|
["/ and @", "complete commands and files"],
|
|
1909
|
+
["pgup pgdn, end", "scroll the transcript, then return to the latest (fullscreen)"],
|
|
1910
|
+
["ctrl+l", "clear and redraw the screen"],
|
|
1800
1911
|
["ctrl+a e u k w", "line editing"]
|
|
1801
1912
|
];
|
|
1802
1913
|
function windowOf(items, index, size) {
|
|
@@ -1879,7 +1990,7 @@ function OverlayView({ state, width: width2 }) {
|
|
|
1879
1990
|
] }, mode.id)),
|
|
1880
1991
|
/* @__PURE__ */ jsxs(Text, { color: theme.muted, children: [
|
|
1881
1992
|
"\n",
|
|
1882
|
-
"Type / to list commands. esc closes this help."
|
|
1993
|
+
"Type / to list commands: /clear, /copy, /export [path], /init and more. esc closes this help."
|
|
1883
1994
|
] })
|
|
1884
1995
|
] });
|
|
1885
1996
|
}
|
|
@@ -1972,8 +2083,11 @@ function handleKey(controller, input, key) {
|
|
|
1972
2083
|
const draft = state.draft;
|
|
1973
2084
|
const edit = controller.setDraft.bind(controller);
|
|
1974
2085
|
if (key.ctrl && input === "c") return controller.interrupt();
|
|
2086
|
+
if (key.ctrl && input === "l") return controller.redraw();
|
|
1975
2087
|
if (state.permission) return permissionKey(controller, input, key);
|
|
1976
2088
|
if (state.overlay) return overlayKey(controller, input, key);
|
|
2089
|
+
if (key.pageUp || key.pageDown) return controller.scrollBy(key.pageUp ? -1 : 1);
|
|
2090
|
+
if (key.end && !draft.text && state.scroll) return controller.scrollEnd();
|
|
1977
2091
|
if (key.tab && key.shift) return controller.cycleMode();
|
|
1978
2092
|
if (key.ctrl && input === "o") return controller.showDetails();
|
|
1979
2093
|
if (key.ctrl && input === "p") return controller.openModels();
|
|
@@ -2191,7 +2305,7 @@ function StatusLine({ state, width: width$1 }) {
|
|
|
2191
2305
|
status.loop.interval ? ` · every ${status.loop.interval}` : ""
|
|
2192
2306
|
].join("");
|
|
2193
2307
|
const left2 = fitSegments([
|
|
2194
|
-
hint ? { text: hint, color: theme.warning, priority: 0 } : { text: `${MODE_LABELS[status.mode] ?? status.mode}${width$1 >= 80 ? " (shift+tab)" : ""}`, color: theme.modes[status.mode], priority: 0 },
|
|
2308
|
+
hint ? { text: hint, color: theme.warning, priority: 0 } : state.scroll ? { text: "↑ scrolled up · pgdn or end returns to the latest", color: theme.warning, priority: 0 } : { text: `${MODE_LABELS[status.mode] ?? status.mode}${width$1 >= 80 ? " (shift+tab)" : ""}`, color: theme.modes[status.mode], priority: 0 },
|
|
2195
2309
|
...status.goal ? [{ text: `◎ goal ${status.goal.status}`, color: theme.accent, priority: 1 }] : [],
|
|
2196
2310
|
...loopText ? [{ text: loopText, color: theme.accent, priority: 2 }] : []
|
|
2197
2311
|
], budget, " ");
|
|
@@ -2216,17 +2330,46 @@ function StatusLine({ state, width: width$1 }) {
|
|
|
2216
2330
|
] }, index)) })
|
|
2217
2331
|
] });
|
|
2218
2332
|
}
|
|
2219
|
-
|
|
2220
|
-
|
|
2333
|
+
const TRANSCRIPT_LIMIT = 200;
|
|
2334
|
+
const same = (a, b) => a.item === b.item && a.live === b.live && Object.keys(a.context).every((key) => a.context[key] === b.context[key]);
|
|
2335
|
+
const Entry = memo(function Entry2({ item, live, context }) {
|
|
2336
|
+
return /* @__PURE__ */ jsx(Box, { width: context.width, flexDirection: "column", flexShrink: 0, children: /* @__PURE__ */ jsx(ItemView, { item, live, context }) });
|
|
2337
|
+
}, same);
|
|
2338
|
+
const heightOf = (ref) => ref.current ? measureElement(ref.current).height : 0;
|
|
2339
|
+
function Viewport({ controller, state, context }) {
|
|
2340
|
+
const outer = useRef(null);
|
|
2341
|
+
const inner = useRef(null);
|
|
2342
|
+
const { flushed, live } = state.transcript;
|
|
2343
|
+
const items = [...flushed, ...live];
|
|
2344
|
+
const { scroll } = state;
|
|
2345
|
+
const pinned = scroll ? items.findIndex((item) => item.id === scroll.from) : -1;
|
|
2346
|
+
const start = pinned >= 0 ? pinned : Math.max(0, items.length - TRANSCRIPT_LIMIT);
|
|
2347
|
+
const first = items[start]?.id ?? 0;
|
|
2348
|
+
useEffect(() => {
|
|
2349
|
+
controller.viewport = () => ({ total: heightOf(inner), height: heightOf(outer), first });
|
|
2350
|
+
});
|
|
2351
|
+
useEffect(() => () => {
|
|
2352
|
+
controller.viewport = void 0;
|
|
2353
|
+
}, [controller]);
|
|
2354
|
+
const max = inner.current && outer.current ? Math.max(0, heightOf(inner) - heightOf(outer)) : Infinity;
|
|
2355
|
+
return /* @__PURE__ */ jsx(
|
|
2356
|
+
Box,
|
|
2357
|
+
{
|
|
2358
|
+
ref: outer,
|
|
2359
|
+
flexDirection: "column",
|
|
2360
|
+
flexGrow: 1,
|
|
2361
|
+
flexShrink: 1,
|
|
2362
|
+
overflow: "hidden",
|
|
2363
|
+
justifyContent: scroll ? "flex-start" : "flex-end",
|
|
2364
|
+
contentOffsetY: scroll ? Math.min(scroll.top, max) : 0,
|
|
2365
|
+
children: /* @__PURE__ */ jsx(Box, { ref: inner, flexDirection: "column", flexGrow: 1, flexShrink: 0, children: items.slice(start).map((item, at) => /* @__PURE__ */ jsx(Entry, { item, live: start + at >= flushed.length, context }, item.id)) })
|
|
2366
|
+
}
|
|
2367
|
+
);
|
|
2368
|
+
}
|
|
2369
|
+
function Bottom({ controller, state, context }) {
|
|
2221
2370
|
const theme = useTheme();
|
|
2222
|
-
const {
|
|
2223
|
-
|
|
2224
|
-
useInput((input, key) => handleKey(controller, input, key));
|
|
2225
|
-
usePaste((text) => controller.paste(text));
|
|
2226
|
-
const context = { width: width2, rows, expanded: false, cwd: state.cwd, version, awaiting: state.permission?.request.toolCall.toolCallId };
|
|
2227
|
-
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: width2, children: [
|
|
2228
|
-
/* @__PURE__ */ jsx(Static, { items: state.transcript.flushed, children: (item) => /* @__PURE__ */ jsx(Box, { width: width2, flexDirection: "column", children: /* @__PURE__ */ jsx(ItemView, { item, context }) }, item.id) }),
|
|
2229
|
-
state.transcript.live.map((item) => /* @__PURE__ */ jsx(ItemView, { item, live: true, context }, item.id)),
|
|
2371
|
+
const { width: width2 } = context;
|
|
2372
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: width2, flexShrink: 0, children: [
|
|
2230
2373
|
state.permission ? /* @__PURE__ */ jsx(PermissionDialog, { pending: state.permission, controller, width: width2, cwd: state.cwd }) : state.overlay?.kind === "details" ? /* @__PURE__ */ jsx(Details, { id: state.overlay.id, transcript: state.transcript, context }, state.overlay.id) : state.overlay?.kind === "panel" ? /* @__PURE__ */ jsx(PanelView, { overlay: state.overlay, width: width2 }) : state.overlay ? /* @__PURE__ */ jsx(OverlayView, { state, width: width2 }) : /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
2231
2374
|
state.running ? /* @__PURE__ */ jsx(Working, { state }) : null,
|
|
2232
2375
|
/* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
|
|
@@ -2241,18 +2384,58 @@ function Screen({ controller, version }) {
|
|
|
2241
2384
|
/* @__PURE__ */ jsx(StatusLine, { state, width: width2 })
|
|
2242
2385
|
] });
|
|
2243
2386
|
}
|
|
2244
|
-
function
|
|
2245
|
-
|
|
2387
|
+
function Screen({ controller, version, fullscreen }) {
|
|
2388
|
+
const state = useSyncExternalStore(controller.subscribe, controller.getState);
|
|
2389
|
+
const { columns, rows } = useWindowSize();
|
|
2390
|
+
const width2 = Math.max(20, columns);
|
|
2391
|
+
useInput((input, key) => handleKey(controller, input, key));
|
|
2392
|
+
usePaste((text) => controller.paste(text));
|
|
2393
|
+
const context = { width: width2, rows, expanded: false, cwd: state.cwd, version, awaiting: state.permission?.request.toolCall.toolCallId };
|
|
2394
|
+
if (fullscreen) {
|
|
2395
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: width2, height: rows, children: [
|
|
2396
|
+
/* @__PURE__ */ jsx(Viewport, { controller, state, context }),
|
|
2397
|
+
/* @__PURE__ */ jsx(Bottom, { controller, state, context })
|
|
2398
|
+
] });
|
|
2399
|
+
}
|
|
2400
|
+
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: width2, children: [
|
|
2401
|
+
/* @__PURE__ */ jsx(Static, { items: state.transcript.flushed, children: (item) => /* @__PURE__ */ jsx(Box, { width: width2, flexDirection: "column", children: /* @__PURE__ */ jsx(ItemView, { item, context }) }, item.id) }, state.generation),
|
|
2402
|
+
state.transcript.live.map((item) => /* @__PURE__ */ jsx(ItemView, { item, live: true, context }, item.id)),
|
|
2403
|
+
/* @__PURE__ */ jsx(Bottom, { controller, state, context })
|
|
2404
|
+
] });
|
|
2405
|
+
}
|
|
2406
|
+
function App({ controller, theme, version, fullscreen = false }) {
|
|
2407
|
+
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: theme, children: /* @__PURE__ */ jsx(Screen, { controller, version, fullscreen }) });
|
|
2246
2408
|
}
|
|
2409
|
+
const CLEAR = "\x1B[2J\x1B[H";
|
|
2410
|
+
const CLEAR_SCROLLBACK = "\x1B[2J\x1B[3J\x1B[H";
|
|
2247
2411
|
async function run(connection, options) {
|
|
2248
|
-
const
|
|
2249
|
-
const
|
|
2250
|
-
|
|
2412
|
+
const stdout = options.stdout ?? process.stdout;
|
|
2413
|
+
const tty = !!stdout.isTTY;
|
|
2414
|
+
const fullscreen = options.fullscreen ?? (tty && !options.debug);
|
|
2415
|
+
const screen = {
|
|
2416
|
+
write: (sequence) => void stdout.write(sequence),
|
|
2417
|
+
clear: () => {
|
|
2418
|
+
instance.clear();
|
|
2419
|
+
stdout.write(fullscreen ? CLEAR : CLEAR_SCROLLBACK);
|
|
2420
|
+
}
|
|
2421
|
+
};
|
|
2422
|
+
const controller = new Controller(connection, { cwd: options.cwd, history: options.history, screen });
|
|
2423
|
+
const exited = new Promise((resolve2) => {
|
|
2424
|
+
controller.onExit = resolve2;
|
|
2251
2425
|
});
|
|
2426
|
+
let title;
|
|
2427
|
+
const showTitle = () => {
|
|
2428
|
+
const { status, running } = controller.getState();
|
|
2429
|
+
const next = windowTitle(status.title, running);
|
|
2430
|
+
if (tty && next !== title) stdout.write(oscTitle(title = next));
|
|
2431
|
+
};
|
|
2432
|
+
const unsubscribe = controller.subscribe(showTitle);
|
|
2433
|
+
showTitle();
|
|
2252
2434
|
const streams = Object.fromEntries(Object.entries({ stdin: options.stdin, stdout: options.stdout, stderr: options.stderr }).filter(([, value]) => value));
|
|
2253
|
-
const instance = render(/* @__PURE__ */ jsx(App, { controller, theme: resolveTheme(options.theme), version: options.version }), {
|
|
2435
|
+
const instance = render(/* @__PURE__ */ jsx(App, { controller, theme: resolveTheme(options.theme), version: options.version, fullscreen }), {
|
|
2254
2436
|
...streams,
|
|
2255
2437
|
exitOnCtrlC: false,
|
|
2438
|
+
alternateScreen: fullscreen,
|
|
2256
2439
|
...options.debug ? { debug: true } : { kittyKeyboard: { mode: "auto" } }
|
|
2257
2440
|
});
|
|
2258
2441
|
void controller.open(options.sessionId).then(() => {
|
|
@@ -2263,8 +2446,12 @@ async function run(connection, options) {
|
|
|
2263
2446
|
try {
|
|
2264
2447
|
await Promise.race([exited, instance.waitUntilExit()]);
|
|
2265
2448
|
} finally {
|
|
2449
|
+
unsubscribe();
|
|
2266
2450
|
controller.dispose();
|
|
2267
2451
|
instance.unmount();
|
|
2452
|
+
await instance.waitUntilExit().catch(() => {
|
|
2453
|
+
});
|
|
2454
|
+
if (title !== void 0) stdout.write(oscTitle(""));
|
|
2268
2455
|
}
|
|
2269
2456
|
return { sessionId: controller.getState().status.sessionId };
|
|
2270
2457
|
}
|
|
@@ -2281,7 +2468,8 @@ async function runTui(options) {
|
|
|
2281
2468
|
history: options.historyPath ? fileHistory(options.historyPath) : void 0,
|
|
2282
2469
|
stdin: options.stdin,
|
|
2283
2470
|
stdout: options.stdout,
|
|
2284
|
-
stderr: options.stderr
|
|
2471
|
+
stderr: options.stderr,
|
|
2472
|
+
fullscreen: options.fullscreen
|
|
2285
2473
|
});
|
|
2286
2474
|
if (sessionId) (options.stderr ?? process.stderr).write(`Resume this session with: oxbit-agent -r ${sessionId}
|
|
2287
2475
|
`);
|
|
@@ -2292,4 +2480,4 @@ export {
|
|
|
2292
2480
|
run,
|
|
2293
2481
|
runTui
|
|
2294
2482
|
};
|
|
2295
|
-
//# sourceMappingURL=index-
|
|
2483
|
+
//# sourceMappingURL=index-DU-a4mnM.js.map
|
package/agent/dist/index.js
CHANGED
|
@@ -4796,7 +4796,7 @@ class FileCatalogCache {
|
|
|
4796
4796
|
}
|
|
4797
4797
|
}
|
|
4798
4798
|
function agentVersion() {
|
|
4799
|
-
return "0.11.
|
|
4799
|
+
return "0.11.3";
|
|
4800
4800
|
}
|
|
4801
4801
|
const clone = (message2) => JSON.parse(JSON.stringify(message2));
|
|
4802
4802
|
class MemoryConnection {
|
|
@@ -6812,6 +6812,7 @@ Options:
|
|
|
6812
6812
|
--mode <mode> ${MODES.map((mode) => mode.id).join(", ")}
|
|
6813
6813
|
-c, --continue Continue the latest session in this directory
|
|
6814
6814
|
-r, --resume <id> Resume a saved session
|
|
6815
|
+
--inline Render the terminal UI inline instead of fullscreen
|
|
6815
6816
|
-v, --version Print the version
|
|
6816
6817
|
-h, --help Print this help
|
|
6817
6818
|
|
|
@@ -6824,6 +6825,7 @@ const OPTIONS = {
|
|
|
6824
6825
|
mode: { type: "string" },
|
|
6825
6826
|
continue: { type: "boolean", short: "c" },
|
|
6826
6827
|
resume: { type: "string", short: "r" },
|
|
6828
|
+
inline: { type: "boolean" },
|
|
6827
6829
|
version: { type: "boolean", short: "v" },
|
|
6828
6830
|
help: { type: "boolean", short: "h" }
|
|
6829
6831
|
};
|
|
@@ -6899,7 +6901,7 @@ ${USAGE}`);
|
|
|
6899
6901
|
}
|
|
6900
6902
|
}
|
|
6901
6903
|
if (!io.stdout.isTTY) throw new UsageError("stdout is not a terminal. Use -p <prompt> for one reply or `oxbit-agent acp` for ACP");
|
|
6902
|
-
const [tui, memory] = await Promise.all([import("./assets/index-
|
|
6904
|
+
const [tui, memory] = await Promise.all([import("./assets/index-DU-a4mnM.js"), import("./assets/memory-Bdy8hvTl.js")]);
|
|
6903
6905
|
const label = () => ({ provider: provider2.runtime.label, usingChatGPTPlan: provider2.runtime.method === "chatgpt" });
|
|
6904
6906
|
const panels = createSettingsManager({ ...deps, rebuild: async (id2) => {
|
|
6905
6907
|
await config.reload();
|
|
@@ -6915,7 +6917,8 @@ ${USAGE}`);
|
|
|
6915
6917
|
sessionId,
|
|
6916
6918
|
prompt: positionals.join(" ") || void 0,
|
|
6917
6919
|
version: agentVersion(),
|
|
6918
|
-
history: memory.fileHistory(config.paths.history)
|
|
6920
|
+
history: memory.fileHistory(config.paths.history),
|
|
6921
|
+
fullscreen: !values.inline
|
|
6919
6922
|
});
|
|
6920
6923
|
if (last) io.stderr.write(`Resume this session with: oxbit-agent -r ${last}
|
|
6921
6924
|
`);
|
package/package.json
CHANGED
package/runtime/dist/index.js
CHANGED
|
@@ -7590,7 +7590,7 @@ class SubagentRegistry {
|
|
|
7590
7590
|
let cached;
|
|
7591
7591
|
function runtimeVersion() {
|
|
7592
7592
|
if (cached) return cached;
|
|
7593
|
-
return cached = "0.11.
|
|
7593
|
+
return cached = "0.11.3";
|
|
7594
7594
|
}
|
|
7595
7595
|
const MAX_REQUEST_BYTES = 1024 * 1024;
|
|
7596
7596
|
const MAX_CONCURRENT_REQUESTS = 16;
|