@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.
@@ -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((resolve) => {
1267
- if (this.rules.has(ruleKey(request))) return resolve(outcomeOf(request, "once").outcome);
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
- function Screen({ controller, version }) {
2220
- const state = useSyncExternalStore(controller.subscribe, controller.getState);
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 { columns, rows } = useWindowSize();
2223
- const width2 = Math.max(20, columns);
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 App({ controller, theme, version }) {
2245
- return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: theme, children: /* @__PURE__ */ jsx(Screen, { controller, version }) });
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 controller = new Controller(connection, { cwd: options.cwd, history: options.history });
2249
- const exited = new Promise((resolve) => {
2250
- controller.onExit = resolve;
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-hc_7c2Gx.js.map
2483
+ //# sourceMappingURL=index-DU-a4mnM.js.map
@@ -4796,7 +4796,7 @@ class FileCatalogCache {
4796
4796
  }
4797
4797
  }
4798
4798
  function agentVersion() {
4799
- return "0.11.2";
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-hc_7c2Gx.js"), import("./assets/memory-Bdy8hvTl.js")]);
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxbit/cli",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "description": "The oxbit command: runs the Oxbit runtime and opens the editor in a browser",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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.2";
7593
+ return cached = "0.11.3";
7594
7594
  }
7595
7595
  const MAX_REQUEST_BYTES = 1024 * 1024;
7596
7596
  const MAX_CONCURRENT_REQUESTS = 16;
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxbit/runtime",
3
- "version": "0.11.2",
3
+ "version": "0.11.3",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }