@alisio/alisio-code 0.1.0-alpha.21 → 0.1.0-alpha.23

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/README.md CHANGED
@@ -80,7 +80,7 @@ Other global flags: `--cwd`, `--config`, `--model`, `--base-url`, `--api-mode`,
80
80
  ## In the TUI
81
81
 
82
82
  `/connect` adds a provider; `/model` picks a saved provider/model; `/compact`, `/stats`, `/clear`,
83
- `/sessions`, `/resume` manage conversations; `/plugins`, `/skills`, `/mcp`, `/settings` manage
83
+ `/sessions`, `/resume` manage conversations; `/plugins`, `/skills`, `/mcps`, `/settings` manage
84
84
  extensions and preferences; `/memory` and `/agents` drive the built-in plugins; `/init` writes
85
85
  `AGENTS.md`.
86
86
 
package/dist/main.js CHANGED
@@ -200,7 +200,7 @@ async function run(cmd, prompt, sessionId) {
200
200
  process.stderr.write(`[startup] ${JSON.stringify(d)}\n`);
201
201
  }
202
202
  if (!opts.quiet)
203
- console.log("Alisio · /exit /new /skill:name /command plugin.id:name args");
203
+ console.log("Alisio · /exit /new /btw question /skill:name /command plugin.id:name args");
204
204
  process.stdout.write("\nalisio › ");
205
205
  try {
206
206
  for await (const rawLine of rl) {
@@ -217,6 +217,22 @@ async function run(cmd, prompt, sessionId) {
217
217
  process.stdout.write("\nalisio › ");
218
218
  continue;
219
219
  }
220
+ if (line === "/btw" || line.startsWith("/btw ")) {
221
+ // Side question: printed here only, never added to the conversation.
222
+ try {
223
+ const { CommandCatalog } = await import("@alisio/core");
224
+ const result = await new CommandCatalog(app).execute("btw", line.slice(4), {
225
+ sessionId: session,
226
+ signal: controller.signal,
227
+ });
228
+ console.log(result.text ?? "");
229
+ }
230
+ catch (e) {
231
+ console.error(e instanceof Error ? e.message : String(e));
232
+ }
233
+ process.stdout.write("\nalisio › ");
234
+ continue;
235
+ }
220
236
  if (line.startsWith("/command ")) {
221
237
  const [name, ...args] = line.slice(9).split(" ");
222
238
  const handler = app.plugins.commands.get(name ?? "");
package/dist/tui/app.js CHANGED
@@ -3,8 +3,9 @@ import { CombinedAutocompleteProvider, Container, Editor, getImageDimensions, ge
3
3
  import { loadVersion } from "../version.js";
4
4
  import { activeAgentCatalog, agentPickerItems, agentRunOptions, mainAgentFromRecord, resolveActiveAgent, } from "./agents.js";
5
5
  import { MAX_ATTACHMENTS_PER_MESSAGE, MAX_IMAGE_BYTES, pasteImageFromClipboard, removeLastAttachment, toApiAttachment, } from "./attachments.js";
6
+ import { BTW_DESCRIPTION, BTW_USAGE, btwBrowser, btwPending } from "./btw.js";
6
7
  import { copyText, nodeSpawn } from "./clipboard.js";
7
- import { AttachmentsBar, BannerBlock, ContentInset, clock, contentInnerWidth, Footer, Header, QuestionPanel, Switch, TranscriptSync, TreePanel, } from "./components.js";
8
+ import { AttachmentsBar, BannerBlock, BtwPanel, ContentInset, clock, contentInnerWidth, Footer, Header, QuestionPanel, Switch, TranscriptSync, TreePanel, } from "./components.js";
8
9
  import { ConnectInputPrompt } from "./connect-input.js";
9
10
  import { bounded, EXIT_PENDING_CAP_MS, EXIT_SESSION_END_CAP_MS } from "./exit.js";
10
11
  import { BRANCH_REFRESH_MS, createBranchCache } from "./git-branch.js";
@@ -1295,7 +1296,7 @@ export async function runTui(options) {
1295
1296
  const consent = value === true ? app.rememberGlobalMcpConsent() : app.revokeGlobalMcpConsent();
1296
1297
  void consent
1297
1298
  .then(() => notice(value === true
1298
- ? "MCP consent remembered globally (mcp.allow); enabled servers will auto-connect on every start. Use /mcp to connect them now."
1299
+ ? "MCP consent remembered globally (mcp.allow); enabled servers will auto-connect on every start. Use /mcps to connect them now."
1299
1300
  : "Global MCP consent revoked: runtime permission dropped and configured servers disconnected."))
1300
1301
  .catch(error)
1301
1302
  .finally(settle);
@@ -1440,13 +1441,64 @@ export async function runTui(options) {
1440
1441
  "**Keys**: Enter send · Shift+Enter / Alt+Enter / Ctrl+J newline · Tab complete · ↑↓ history · Esc interrupt · Ctrl+C clear input (twice to exit) · Ctrl+D exit on empty input · c / y copy last response (empty input) · x expand/collapse latest thought/tool batch/output (empty input) · click a collapsible header row to toggle it · PgUp/PgDn or mouse wheel scroll · Ctrl+X agent panel · Ctrl+B background running agents",
1441
1442
  `**Paste**: multi-line text pastes as one block automatically · Ctrl+V attach a clipboard image (PNG/JPEG/GIF/WebP, up to ${(MAX_IMAGE_BYTES / (1024 * 1024)).toFixed(0)} MB, up to ${MAX_ATTACHMENTS_PER_MESSAGE} per message) · Ctrl+R remove the last attached image`,
1442
1443
  ].join("\n");
1444
+ // `/btw` side questions: answered in the picker slot, never appended to the transcript. One
1445
+ // question is in flight at a time; Esc cancels it (independent of the run's controller, so a
1446
+ // side question also works, and is cancelled on its own, while a turn is running).
1447
+ let btwController;
1448
+ let btwPanel;
1449
+ const btwHeight = () => Math.max(4, Math.floor((process.stdout.rows ?? 30) / 2) - 6);
1450
+ const closeBtw = () => {
1451
+ btwController?.abort(new Error("Cancelled"));
1452
+ btwController = undefined;
1453
+ if (btwPanel && picker === btwPanel)
1454
+ closePicker();
1455
+ btwPanel = undefined;
1456
+ };
1457
+ const sideQuestion = async (question) => {
1458
+ const asked = session;
1459
+ const entries = app.sideQuestions.history(asked);
1460
+ if (!question) {
1461
+ const state = btwBrowser(entries);
1462
+ if (!state)
1463
+ return notice(`${BTW_USAGE}\n${BTW_DESCRIPTION}`);
1464
+ btwPanel = new BtwPanel(state, closeBtw, btwHeight);
1465
+ return showPicker(btwPanel);
1466
+ }
1467
+ btwController?.abort(new Error("Cancelled"));
1468
+ const controller = new AbortController();
1469
+ btwController = controller;
1470
+ const panel = new BtwPanel(btwPending(entries, question), closeBtw, btwHeight);
1471
+ btwPanel = panel;
1472
+ showPicker(panel);
1473
+ try {
1474
+ await app.sideQuestions.ask(asked, question, { signal: controller.signal });
1475
+ if (controller.signal.aborted)
1476
+ return;
1477
+ panel.dispatch({ type: "answered", entries: app.sideQuestions.history(asked) });
1478
+ // An approval may have taken the slot meanwhile: the answer is in the history anyway.
1479
+ if (picker !== panel)
1480
+ flashHint("Side answer ready: /btw to view it", 4000);
1481
+ }
1482
+ catch (e) {
1483
+ if (controller.signal.aborted)
1484
+ return;
1485
+ panel.dispatch({ type: "failed", message: e instanceof Error ? e.message : String(e) });
1486
+ if (picker !== panel)
1487
+ error(e);
1488
+ }
1489
+ finally {
1490
+ if (btwController === controller)
1491
+ btwController = undefined;
1492
+ tui.requestRender();
1493
+ }
1494
+ };
1443
1495
  const commandCatalog = new CommandCatalog(app);
1444
1496
  const mutating = new Set([
1445
1497
  "connect",
1446
1498
  "model",
1447
1499
  "plugins",
1448
1500
  "skills",
1449
- "mcp",
1501
+ "mcps",
1450
1502
  "settings",
1451
1503
  "compact",
1452
1504
  "clear",
@@ -1506,7 +1558,7 @@ export async function runTui(options) {
1506
1558
  return managePlugins();
1507
1559
  case "skills":
1508
1560
  return manageSkills();
1509
- case "mcp":
1561
+ case "mcps":
1510
1562
  return manageMcp();
1511
1563
  case "settings":
1512
1564
  return openSettings();
@@ -1521,6 +1573,8 @@ export async function runTui(options) {
1521
1573
  tui.flash(message);
1522
1574
  return result.ok ? undefined : notice(message);
1523
1575
  }
1576
+ case "btw":
1577
+ return await sideQuestion(parsed.args);
1524
1578
  case "ask": {
1525
1579
  if (!parsed.args)
1526
1580
  return notice("Usage: /ask <question>");
@@ -1834,6 +1888,7 @@ export async function runTui(options) {
1834
1888
  const ticker = setInterval(() => {
1835
1889
  clock.now = Date.now();
1836
1890
  if (busy ||
1891
+ btwPanel?.pending ||
1837
1892
  view.items.some((i) => i.kind === "tool" && i.status === "running") ||
1838
1893
  panelNodes().some((n) => n.status === "running")) {
1839
1894
  clock.frame++;
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Pure state of the TUI `/btw` panel: a pending side question, its answer, and browsing earlier
3
+ * answers of the session. The panel lives in the picker slot and never touches the transcript.
4
+ *
5
+ * Keys: ←/→ earlier/later answer, ↑/↓ (and PgUp/PgDn) scroll a long answer, Esc cancels a pending
6
+ * question or closes the panel.
7
+ */
8
+ import type { SideQuestionEntry } from "@alisio/sdk";
9
+ export declare const BTW_USAGE = "Usage: /btw <question>";
10
+ export declare const BTW_DESCRIPTION = "Ask a side question about the current session without adding to the conversation.";
11
+ export interface BtwState {
12
+ entries: SideQuestionEntry[];
13
+ /** Index of the entry on screen (ignored while `pending`). */
14
+ index: number;
15
+ /** A question waiting for its answer. */
16
+ pending?: {
17
+ question: string;
18
+ startedAt: number;
19
+ };
20
+ /** Why the last question failed (shown until the user navigates). */
21
+ error?: {
22
+ question: string;
23
+ message: string;
24
+ };
25
+ /** First answer line on screen. */
26
+ scroll: number;
27
+ }
28
+ export type BtwAction = {
29
+ type: "prev";
30
+ } | {
31
+ type: "next";
32
+ } | {
33
+ type: "scroll";
34
+ lines: number;
35
+ } | {
36
+ type: "answered";
37
+ entries: SideQuestionEntry[];
38
+ } | {
39
+ type: "failed";
40
+ message: string;
41
+ };
42
+ /** The browser for `/btw` without a question: the newest entry, or undefined when none. */
43
+ export declare function btwBrowser(entries: SideQuestionEntry[]): BtwState | undefined;
44
+ /** The panel while `question` is being answered (earlier entries stay browsable afterwards). */
45
+ export declare function btwPending(entries: SideQuestionEntry[], question: string, now?: number): BtwState;
46
+ export declare function reduceBtw(state: BtwState, action: BtwAction): BtwState;
47
+ /** The entry on screen, if the panel is not pending or showing an error. */
48
+ export declare function btwCurrent(state: BtwState): SideQuestionEntry | undefined;
49
+ /** "2/5" for the entry on screen; empty while pending or on an error. */
50
+ export declare function btwPosition(state: BtwState): string;
51
+ /** Footer hints for the current state. */
52
+ export declare function btwHints(state: BtwState, overflow: boolean): string;
53
+ /** "model · 12 in · 3 out tokens" for an entry. */
54
+ export declare function btwUsageLine(entry: SideQuestionEntry): string;
55
+ /** The visible slice of `lines` for `scroll` (clamped) and whether more lines exist. */
56
+ export declare function btwWindow(lines: string[], scroll: number, height: number): {
57
+ lines: string[];
58
+ scroll: number;
59
+ above: boolean;
60
+ below: boolean;
61
+ };
@@ -0,0 +1,84 @@
1
+ export const BTW_USAGE = "Usage: /btw <question>";
2
+ export const BTW_DESCRIPTION = "Ask a side question about the current session without adding to the conversation.";
3
+ /** The browser for `/btw` without a question: the newest entry, or undefined when none. */
4
+ export function btwBrowser(entries) {
5
+ return entries.length ? { entries, index: entries.length - 1, scroll: 0 } : undefined;
6
+ }
7
+ /** The panel while `question` is being answered (earlier entries stay browsable afterwards). */
8
+ export function btwPending(entries, question, now = Date.now()) {
9
+ return {
10
+ entries,
11
+ index: Math.max(0, entries.length - 1),
12
+ pending: { question, startedAt: now },
13
+ scroll: 0,
14
+ };
15
+ }
16
+ export function reduceBtw(state, action) {
17
+ switch (action.type) {
18
+ case "prev":
19
+ case "next": {
20
+ if (state.pending || !state.entries.length)
21
+ return state;
22
+ const step = action.type === "prev" ? -1 : 1;
23
+ // Leaving an error shows the stored entries again (the newest first).
24
+ const from = state.error ? state.entries.length : state.index;
25
+ const index = Math.min(state.entries.length - 1, Math.max(0, from + step));
26
+ if (index === state.index && !state.error)
27
+ return state;
28
+ return { entries: state.entries, index, scroll: 0 };
29
+ }
30
+ case "scroll":
31
+ return { ...state, scroll: Math.max(0, state.scroll + action.lines) };
32
+ case "answered":
33
+ return {
34
+ entries: action.entries,
35
+ index: Math.max(0, action.entries.length - 1),
36
+ scroll: 0,
37
+ };
38
+ case "failed": {
39
+ const { pending: _pending, ...rest } = state;
40
+ return {
41
+ ...rest,
42
+ error: { question: state.pending?.question ?? "", message: action.message },
43
+ scroll: 0,
44
+ };
45
+ }
46
+ }
47
+ }
48
+ /** The entry on screen, if the panel is not pending or showing an error. */
49
+ export function btwCurrent(state) {
50
+ return state.pending || state.error ? undefined : state.entries[state.index];
51
+ }
52
+ /** "2/5" for the entry on screen; empty while pending or on an error. */
53
+ export function btwPosition(state) {
54
+ return btwCurrent(state) ? `${state.index + 1}/${state.entries.length}` : "";
55
+ }
56
+ /** Footer hints for the current state. */
57
+ export function btwHints(state, overflow) {
58
+ if (state.pending)
59
+ return "Esc cancel";
60
+ const current = btwCurrent(state);
61
+ const hints = [
62
+ ...(state.entries.length > 1 || (state.error && state.entries.length)
63
+ ? ["←/→ earlier/later"]
64
+ : []),
65
+ ...(overflow ? ["↑/↓ scroll"] : []),
66
+ "Esc close",
67
+ ];
68
+ return current || state.error ? hints.join(" · ") : "Esc close";
69
+ }
70
+ /** "model · 12 in · 3 out tokens" for an entry. */
71
+ export function btwUsageLine(entry) {
72
+ return `${entry.model} · ${entry.usage.input} in · ${entry.usage.output} out tokens${entry.truncated ? " · truncated" : ""}`;
73
+ }
74
+ /** The visible slice of `lines` for `scroll` (clamped) and whether more lines exist. */
75
+ export function btwWindow(lines, scroll, height) {
76
+ const max = Math.max(0, lines.length - height);
77
+ const start = Math.min(Math.max(0, scroll), max);
78
+ return {
79
+ lines: lines.slice(start, start + height),
80
+ scroll: start,
81
+ above: start > 0,
82
+ below: start + height < lines.length,
83
+ };
84
+ }
@@ -1,6 +1,7 @@
1
1
  import type { PanelNode, TreeNode, UiBlock } from "@alisio/sdk";
2
2
  import { type Component, Container } from "@earendil-works/pi-tui";
3
3
  import { type PendingAttachment } from "./attachments.ts";
4
+ import { type BtwAction, type BtwState } from "./btw.ts";
4
5
  import { type QuestionPanelState, type QuestionSpec } from "./questions.ts";
5
6
  import { type ContextBudget, type FoldableKind, type FoldCandidate, type GroupedTool, type IdentityInput, type TranscriptEntry, type TranscriptItem, type ViewState } from "./state.ts";
6
7
  export declare const SPINNER: string[];
@@ -255,3 +256,21 @@ export declare class QuestionPanel implements Component {
255
256
  handleInput(data: string): void;
256
257
  render(width: number): string[];
257
258
  }
259
+ /**
260
+ * The `/btw` side-question panel (picker slot, never the transcript): a pending question with a
261
+ * spinner, then the answer rendered as Markdown like assistant text, scrollable, with ←/→ through
262
+ * the session's earlier side answers. `onClose` runs on Esc (the app cancels a pending question).
263
+ */
264
+ export declare class BtwPanel implements Component {
265
+ private state;
266
+ private readonly onClose;
267
+ private readonly height;
268
+ private markdown?;
269
+ constructor(state: BtwState, onClose: () => void, height: () => number);
270
+ get pending(): boolean;
271
+ dispatch(action: BtwAction): void;
272
+ invalidate(): void;
273
+ handleInput(data: string): void;
274
+ private answerLines;
275
+ render(width: number): string[];
276
+ }
@@ -1,6 +1,7 @@
1
1
  import { Container, getCapabilities, getImageDimensions, Image, Key, Markdown, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi, } from "@earendil-works/pi-tui";
2
2
  import { terminalCapabilities } from "../banner.js";
3
3
  import { attachmentCaption, MAX_ATTACHMENTS_PER_MESSAGE, } from "./attachments.js";
4
+ import { btwCurrent, btwHints, btwPosition, btwUsageLine, btwWindow, reduceBtw, } from "./btw.js";
4
5
  import { branchDisplay } from "./git-branch.js";
5
6
  import { initialQuestionState, reduceQuestions, } from "./questions.js";
6
7
  import { contextLevel, contextPercent, editSummary, entryKeyOf, fitIdentityParts, fitSegments, foldCandidateOf, formatContext, formatDuration, formatTokens, groupIdentity, groupToolEntries, humanizeToolName, isUiBlock, previewLinesFor, previewRows, REASONING_EXPAND_MAX_LINES, reasoningDurationMs, } from "./state.js";
@@ -1113,3 +1114,89 @@ export class QuestionPanel {
1113
1114
  return fit(lines, width);
1114
1115
  }
1115
1116
  }
1117
+ /**
1118
+ * The `/btw` side-question panel (picker slot, never the transcript): a pending question with a
1119
+ * spinner, then the answer rendered as Markdown like assistant text, scrollable, with ←/→ through
1120
+ * the session's earlier side answers. `onClose` runs on Esc (the app cancels a pending question).
1121
+ */
1122
+ export class BtwPanel {
1123
+ state;
1124
+ onClose;
1125
+ height;
1126
+ markdown;
1127
+ constructor(state, onClose, height) {
1128
+ this.state = state;
1129
+ this.onClose = onClose;
1130
+ this.height = height;
1131
+ }
1132
+ get pending() {
1133
+ return !!this.state.pending;
1134
+ }
1135
+ dispatch(action) {
1136
+ this.state = reduceBtw(this.state, action);
1137
+ }
1138
+ invalidate() {
1139
+ this.markdown = undefined;
1140
+ }
1141
+ handleInput(data) {
1142
+ if (matchesKey(data, Key.escape))
1143
+ return this.onClose();
1144
+ if (matchesKey(data, Key.left))
1145
+ return this.dispatch({ type: "prev" });
1146
+ if (matchesKey(data, Key.right))
1147
+ return this.dispatch({ type: "next" });
1148
+ if (matchesKey(data, Key.up))
1149
+ return this.dispatch({ type: "scroll", lines: -1 });
1150
+ if (matchesKey(data, Key.down))
1151
+ return this.dispatch({ type: "scroll", lines: 1 });
1152
+ if (matchesKey(data, Key.pageUp))
1153
+ return this.dispatch({ type: "scroll", lines: -this.height() });
1154
+ if (matchesKey(data, Key.pageDown))
1155
+ return this.dispatch({ type: "scroll", lines: this.height() });
1156
+ }
1157
+ answerLines(id, text, width) {
1158
+ if (this.markdown?.id === id && this.markdown.width === width)
1159
+ return this.markdown.lines;
1160
+ const lines = new Markdown(text, 0, 0, markdownTheme, markdownDefaultTextStyle, {
1161
+ transform: markdownTransform,
1162
+ }).render(Math.max(1, width));
1163
+ this.markdown = { id, width, lines };
1164
+ return lines;
1165
+ }
1166
+ render(width) {
1167
+ const s = this.state;
1168
+ const inner = Math.max(1, width - 2);
1169
+ const bar = style.gray("│");
1170
+ const current = btwCurrent(s);
1171
+ const position = btwPosition(s);
1172
+ const lines = [
1173
+ "",
1174
+ `${style.bold(style.yellow("btw"))}${position ? ` ${style.dim(position)}` : ""}${style.dim(" · side question, not added to the conversation")}`,
1175
+ ];
1176
+ const question = s.pending?.question ?? s.error?.question ?? current?.question ?? "";
1177
+ lines.push(...wrap(question, inner).map((l) => `${bar} ${style.bold(l)}`));
1178
+ let overflow = false;
1179
+ if (s.pending) {
1180
+ const spinner = SPINNER[clock.frame % SPINNER.length] ?? "…";
1181
+ lines.push(`${bar} ${style.cyan(spinner)} Thinking… ${style.dim(formatDuration(clock.now - s.pending.startedAt))}`);
1182
+ }
1183
+ else if (s.error) {
1184
+ lines.push(...wrap(s.error.message, inner).map((l) => `${bar} ${style.red(l)}`));
1185
+ }
1186
+ else if (current) {
1187
+ const body = this.answerLines(current.id, current.answer, inner);
1188
+ const view = btwWindow(body, s.scroll, Math.max(3, this.height()));
1189
+ if (view.scroll !== s.scroll)
1190
+ this.state = { ...s, scroll: view.scroll };
1191
+ overflow = view.above || view.below;
1192
+ if (view.above)
1193
+ lines.push(`${bar} ${style.dim("↑ more")}`);
1194
+ lines.push(...view.lines.map((l) => `${bar} ${l}`));
1195
+ if (view.below)
1196
+ lines.push(`${bar} ${style.dim("↓ more")}`);
1197
+ lines.push(`${bar} ${style.dim(btwUsageLine(current))}`);
1198
+ }
1199
+ lines.push(style.dim(` ${btwHints(this.state, overflow)}`));
1200
+ return fit(lines, width);
1201
+ }
1202
+ }
@@ -97,7 +97,7 @@ interface SettingDefinition {
97
97
  export declare const SETTINGS_DEFINITIONS: readonly SettingDefinition[];
98
98
  /**
99
99
  * Builds the full settings menu: the real, wired setting rows followed by the navigation rows the
100
- * host wires to the existing managers (`/model`, `/connect`, `/plugins`, `/skills`, `/mcp`, ...).
100
+ * host wires to the existing managers (`/model`, `/connect`, `/plugins`, `/skills`, `/mcps`, ...).
101
101
  * Under `--read-only` every setting row is marked read-only: nothing can be persisted.
102
102
  */
103
103
  export declare function settingsMenuRows(input: SettingsMenuInput, navigation: SettingsNavigationAction[]): SettingRow[];
@@ -104,7 +104,7 @@ export const SETTINGS_DEFINITIONS = [
104
104
  valueType: "boolean",
105
105
  values: [false, true],
106
106
  read: (_config, mcpAllowPersisted) => mcpAllowPersisted,
107
- description: "Persist process/network consent for MCP servers in your user configuration (mcp.allow). On: every start grants permission and auto-connects enabled servers; use /mcp to connect now. Off: revokes the persisted consent and disconnects servers.",
107
+ description: "Persist process/network consent for MCP servers in your user configuration (mcp.allow). On: every start grants permission and auto-connects enabled servers; use /mcps to connect now. Off: revokes the persisted consent and disconnects servers.",
108
108
  },
109
109
  {
110
110
  id: "limits.maxTurns",
@@ -182,7 +182,7 @@ export const SETTINGS_DEFINITIONS = [
182
182
  ];
183
183
  /**
184
184
  * Builds the full settings menu: the real, wired setting rows followed by the navigation rows the
185
- * host wires to the existing managers (`/model`, `/connect`, `/plugins`, `/skills`, `/mcp`, ...).
185
+ * host wires to the existing managers (`/model`, `/connect`, `/plugins`, `/skills`, `/mcps`, ...).
186
186
  * Under `--read-only` every setting row is marked read-only: nothing can be persisted.
187
187
  */
188
188
  export function settingsMenuRows(input, navigation) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alisio/alisio-code",
3
- "version": "0.1.0-alpha.21",
3
+ "version": "0.1.0-alpha.23",
4
4
  "description": "Alisio: an extensible, provider-agnostic coding-agent harness for your terminal. TUI, OpenAI-compatible providers, permissioned local tools, context compaction, persistent memory and a typed plugin SDK.",
5
5
  "author": "Gustavo Gutiérrez",
6
6
  "license": "MIT",
@@ -45,12 +45,12 @@
45
45
  "alisio": "./dist/main.js"
46
46
  },
47
47
  "dependencies": {
48
- "@alisio/core": "0.1.0-alpha.18",
48
+ "@alisio/core": "0.1.0-alpha.20",
49
49
  "@alisio/plugin-memory": "0.1.0-alpha.9",
50
50
  "@alisio/plugin-openai-compatible": "0.1.0-alpha.9",
51
51
  "@alisio/plugin-subagents": "0.1.0-alpha.10",
52
- "@alisio/sdk": "0.1.0-alpha.15",
53
- "@alisio/server": "0.1.0-alpha.1",
52
+ "@alisio/sdk": "0.1.0-alpha.16",
53
+ "@alisio/server": "0.1.0-alpha.3",
54
54
  "@earendil-works/pi-tui": "0.87.1",
55
55
  "commander": "15.0.0"
56
56
  },