@alisio/alisio-code 0.1.0-alpha.14 → 0.1.0-alpha.16
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/dist/main.js +21 -2
- package/dist/tui/agents.d.ts +66 -0
- package/dist/tui/agents.js +113 -0
- package/dist/tui/app.js +260 -15
- package/dist/tui/components.d.ts +77 -12
- package/dist/tui/components.js +490 -63
- package/dist/tui/state.d.ts +204 -1
- package/dist/tui/state.js +501 -12
- package/dist/tui/theme.d.ts +42 -1
- package/dist/tui/theme.js +516 -1
- package/package.json +6 -6
package/dist/tui/state.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Pure presentation logic for the TUI: formatting, command parsing and the reduction of
|
|
3
3
|
* versioned runner events into a view model. No terminal or pi-tui imports here.
|
|
4
4
|
*/
|
|
5
|
-
import type { Message, ModelInfo, RunEvent } from "@alisio/sdk";
|
|
5
|
+
import type { Message, ModelInfo, RunEvent, ToolResult, TreeNode, UiBlock } from "@alisio/sdk";
|
|
6
6
|
export type Level = "ok" | "warn" | "danger";
|
|
7
7
|
export declare function formatTokens(n: number): string;
|
|
8
8
|
/** Prefixes every model with its owning provider so identical model ids are never ambiguous. */
|
|
@@ -124,6 +124,44 @@ export declare function parseCommand(input: string): {
|
|
|
124
124
|
name: string;
|
|
125
125
|
args: string;
|
|
126
126
|
} | undefined;
|
|
127
|
+
/** Reasoning-effort capability advertised by a model's catalog entry (`ModelInfo.effort`). */
|
|
128
|
+
export interface EffortCapability {
|
|
129
|
+
supportedLevels: string[];
|
|
130
|
+
defaultLevel?: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* The effective reasoning effort to send for a model: the persisted level when the model
|
|
134
|
+
* supports it, otherwise the model's default level (silent fallback), and nothing when the
|
|
135
|
+
* model advertises no effort levels at all.
|
|
136
|
+
*/
|
|
137
|
+
export declare function effectiveEffort(persisted: string | undefined, capability: EffortCapability | undefined): string | undefined;
|
|
138
|
+
/** Validates a `/effort <level>` argument against the active model; returns an error or nothing. */
|
|
139
|
+
export declare function validateEffortLevel(level: string, capability: EffortCapability | undefined): string | undefined;
|
|
140
|
+
export declare function effortPickerItems(capability: EffortCapability, active: string | undefined): Array<{
|
|
141
|
+
value: string;
|
|
142
|
+
label: string;
|
|
143
|
+
description?: string;
|
|
144
|
+
}>;
|
|
145
|
+
/** Role of a status-line identity part; the renderer maps each role to a distinct color. */
|
|
146
|
+
export type IdentityRole = "agent" | "model" | "provider" | "effort";
|
|
147
|
+
export interface IdentityPart extends Segment {
|
|
148
|
+
role: IdentityRole;
|
|
149
|
+
}
|
|
150
|
+
export interface IdentityInput {
|
|
151
|
+
agent: string;
|
|
152
|
+
model: string;
|
|
153
|
+
provider?: string;
|
|
154
|
+
effort?: string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* The ordered identity parts for the status line below the editor:
|
|
158
|
+
* `agent: <name> · <model> · <provider> · <effort>`, with the effort part omitted when the
|
|
159
|
+
* active model advertises no supported levels (`effort === undefined`). Colors are applied by
|
|
160
|
+
* the renderer per role; this module stays terminal-free and testable.
|
|
161
|
+
*/
|
|
162
|
+
export declare function identityParts(input: IdentityInput): IdentityPart[];
|
|
163
|
+
/** Drops the lowest-priority identity parts until the line fits `width`; truncates the survivor. */
|
|
164
|
+
export declare function fitIdentityParts(input: IdentityInput, width: number): IdentityPart[];
|
|
127
165
|
/** Minimal structural view of a skill for slash autocompletion (subset of the core catalog entry). */
|
|
128
166
|
export interface SkillCompletionEntry {
|
|
129
167
|
id: string;
|
|
@@ -208,6 +246,8 @@ export interface EditSummary {
|
|
|
208
246
|
}
|
|
209
247
|
export declare function editSummary(name: string, args: string): EditSummary | undefined;
|
|
210
248
|
export type ToolStatus = "running" | "approval" | "ok" | "error";
|
|
249
|
+
/** Capability kind of a tool call; drives grouping labels and batch display. */
|
|
250
|
+
export type ToolKind = "read" | "write" | "process" | "mcp" | "internal" | "other";
|
|
211
251
|
export type TranscriptItem = {
|
|
212
252
|
kind: "user";
|
|
213
253
|
text: string;
|
|
@@ -216,6 +256,10 @@ export type TranscriptItem = {
|
|
|
216
256
|
text: string;
|
|
217
257
|
reasoning: string;
|
|
218
258
|
done: boolean;
|
|
259
|
+
/** Epoch ms of the first reasoning delta; with `reasoningDoneAt` it approximates the thinking interval. */
|
|
260
|
+
reasoningStartedAt?: number;
|
|
261
|
+
/** Epoch ms of the last reasoning delta (the end of the visible thought section). */
|
|
262
|
+
reasoningDoneAt?: number;
|
|
219
263
|
} | {
|
|
220
264
|
kind: "tool";
|
|
221
265
|
id: string;
|
|
@@ -225,6 +269,17 @@ export type TranscriptItem = {
|
|
|
225
269
|
status: ToolStatus;
|
|
226
270
|
durationMs?: number;
|
|
227
271
|
preview?: string;
|
|
272
|
+
/** Structured block rendered natively by the TUI (from a `{type:"ui"}` result part). */
|
|
273
|
+
ui?: UiBlock;
|
|
274
|
+
/** Base64 image rendered inline by the TUI when the terminal supports it (from a `{type:"image"}` part). */
|
|
275
|
+
image?: {
|
|
276
|
+
mimeType: string;
|
|
277
|
+
data: string;
|
|
278
|
+
};
|
|
279
|
+
/** Effect-derived kind (grouping label); name-heuristic fallback for replayed history. */
|
|
280
|
+
toolKind?: ToolKind;
|
|
281
|
+
/** Exit code derived safely from the JSON preview when the tool reports one (run_process/shell/search_text). */
|
|
282
|
+
exitCode?: number;
|
|
228
283
|
} | {
|
|
229
284
|
kind: "notice";
|
|
230
285
|
text: string;
|
|
@@ -264,7 +319,155 @@ export interface ViewState {
|
|
|
264
319
|
}
|
|
265
320
|
export declare function initialViewState(model: string, now?: number): ViewState;
|
|
266
321
|
export declare function addItem(state: ViewState, item: TranscriptItem): ViewState;
|
|
322
|
+
/** Approximated thinking interval of a completed reasoning section, when the events carried timestamps. */
|
|
323
|
+
export declare function reasoningDurationMs(item: {
|
|
324
|
+
reasoningStartedAt?: number;
|
|
325
|
+
reasoningDoneAt?: number;
|
|
326
|
+
}): number | undefined;
|
|
267
327
|
export declare function reduceEvent(state: ViewState, event: RunEvent): ViewState;
|
|
268
328
|
export declare function lastAssistantText(items: TranscriptItem[]): string | undefined;
|
|
329
|
+
/**
|
|
330
|
+
* True when a printable key should copy the last assistant response instead of typing: bound to
|
|
331
|
+
* `c`/`y` (and uppercase) on an EMPTY editor line, while no autocomplete is showing and no turn
|
|
332
|
+
* is running — the same "empty input" convention Enter and Ctrl+D already use. A non-empty input
|
|
333
|
+
* never triggers, so typing `c` or `y` mid-message is unaffected.
|
|
334
|
+
*/
|
|
335
|
+
export declare function editorCopyKey(data: string, input: {
|
|
336
|
+
text: string;
|
|
337
|
+
autocomplete: boolean;
|
|
338
|
+
busy: boolean;
|
|
339
|
+
}): boolean;
|
|
340
|
+
/** True when an unknown event value is a `Node` of a tree UI block. */
|
|
341
|
+
export declare function isTreeNode(value: unknown): value is TreeNode;
|
|
342
|
+
/** True when an unknown event value is an Alisio `UiBlock` (validated defensively). */
|
|
343
|
+
export declare function isUiBlock(value: unknown): value is UiBlock;
|
|
344
|
+
/** True when an unknown event value is a `{type:"image"}`-style part (mime + base64 data). */
|
|
345
|
+
export declare function isImagePart(value: unknown): value is {
|
|
346
|
+
mimeType: string;
|
|
347
|
+
data: string;
|
|
348
|
+
};
|
|
349
|
+
/** Rich (ui/image) parts of a persisted tool result, if any. */
|
|
350
|
+
export declare function richPartsOf(result: ToolResult | undefined): {
|
|
351
|
+
ui?: UiBlock;
|
|
352
|
+
image?: {
|
|
353
|
+
mimeType: string;
|
|
354
|
+
data: string;
|
|
355
|
+
};
|
|
356
|
+
};
|
|
357
|
+
/**
|
|
358
|
+
* `read_file` → `Read File`, `search_text` → `Search Text`, `mcp_devforge_time_diff` →
|
|
359
|
+
* `MCP · Devforge Time Diff`. Splits on `_`/`-`/`.`/spaces, keeps known acronyms (MCP, HTTP…)
|
|
360
|
+
* and bare numeric suffixes (`read_file_2` → `Read File 2`). The machine name stays available
|
|
361
|
+
* dimmed in grouped detail rows and in the `/tools` and `/stats` reports.
|
|
362
|
+
*/
|
|
363
|
+
export declare function humanizeToolName(name: string): string;
|
|
364
|
+
/** Verb and count noun used by grouped batch rows per tool kind. */
|
|
365
|
+
export declare const TOOL_KIND_VERB: Record<ToolKind, string>;
|
|
366
|
+
export declare const TOOL_KIND_WORD: Record<ToolKind, string>;
|
|
367
|
+
/**
|
|
368
|
+
* Capability kind of a tool call. Live events carry the registry `effect` (exact); replayed
|
|
369
|
+
* history falls back to conservative name heuristics. `mcp_*` is always the mcp kind.
|
|
370
|
+
*/
|
|
371
|
+
export declare function toolKindOf(name: string, effect?: string): ToolKind;
|
|
372
|
+
/** Terminal-preview caps for collapsed rows (same values the renderer always used). */
|
|
373
|
+
export declare const OUTPUT_PREVIEW_LINES_OK = 3;
|
|
374
|
+
export declare const OUTPUT_PREVIEW_LINES_ERROR = 6;
|
|
375
|
+
export declare const previewLinesFor: (status: ToolStatus) => number;
|
|
376
|
+
/** Preview rows as the renderer shows them: blank lines dropped, tabs kept for the caller to expand. */
|
|
377
|
+
export declare const previewRows: (preview: string) => string[];
|
|
378
|
+
/** True when the preview exceeds the collapsed cap (the row becomes a collapsible "output"). */
|
|
379
|
+
export declare function previewTruncated(preview: string | undefined, status: ToolStatus): boolean;
|
|
380
|
+
/**
|
|
381
|
+
* Exit code derived safely from a text preview. `run_process`/`shell`/`search_text` return
|
|
382
|
+
* `{stdout, stderr, exitCode, truncated}` JSON; read-effect tools may carry an appended
|
|
383
|
+
* `\n<instructions>…` block, retried on the JSON prefix. Any other shape yields nothing.
|
|
384
|
+
*/
|
|
385
|
+
export declare function exitCodeOf(preview: string | undefined): number | undefined;
|
|
386
|
+
/** Renderable view of one tool call (singleton row, or a member of a grouped batch). */
|
|
387
|
+
export interface ToolItemView {
|
|
388
|
+
id: string;
|
|
389
|
+
/** Machine name (kept for dimmed detail display). */
|
|
390
|
+
name: string;
|
|
391
|
+
/** Humanized display name. */
|
|
392
|
+
humanName: string;
|
|
393
|
+
kind: ToolKind;
|
|
394
|
+
summary: string;
|
|
395
|
+
status: ToolStatus;
|
|
396
|
+
durationMs?: number;
|
|
397
|
+
preview?: string;
|
|
398
|
+
ui?: UiBlock;
|
|
399
|
+
image?: {
|
|
400
|
+
mimeType: string;
|
|
401
|
+
data: string;
|
|
402
|
+
};
|
|
403
|
+
exitCode?: number;
|
|
404
|
+
}
|
|
405
|
+
/** A batch of consecutive same-kind, finished tool calls rendered as ONE collapsible row. */
|
|
406
|
+
export interface GroupedTool {
|
|
407
|
+
/** Id of the first member call (stable fold key while the batch grows). */
|
|
408
|
+
id: string;
|
|
409
|
+
members: ToolItemView[];
|
|
410
|
+
kind: ToolKind;
|
|
411
|
+
/** Aggregate: `error` when any member failed, else `ok` (members are all terminal). */
|
|
412
|
+
status: ToolStatus;
|
|
413
|
+
/** Sum of member durations. */
|
|
414
|
+
totalMs: number;
|
|
415
|
+
/** Header name: the shared humanized tool name, or the kind verb for mixed batches. */
|
|
416
|
+
label: string;
|
|
417
|
+
/** Count noun matching `label` (`reads`, `files`, `commands`…). */
|
|
418
|
+
word: string;
|
|
419
|
+
}
|
|
420
|
+
/** Everything the transcript renders: a plain item, or one grouped batch row. */
|
|
421
|
+
export type TranscriptEntry = TranscriptItem | {
|
|
422
|
+
kind: "group";
|
|
423
|
+
group: GroupedTool;
|
|
424
|
+
};
|
|
425
|
+
export declare function toolItemView(item: Extract<TranscriptItem, {
|
|
426
|
+
kind: "tool";
|
|
427
|
+
}>): ToolItemView;
|
|
428
|
+
/**
|
|
429
|
+
* Consecutive tool calls of the same kind whose statuses are ALL terminal (ok/error) merge into
|
|
430
|
+
* one `group` entry; running/approval calls always stay singleton so their spinner and live state
|
|
431
|
+
* stay visible. A kind change splits the run (`read` never merges with `shell`). Order is
|
|
432
|
+
* preserved; every entry carries its index within `items` (fold keys for assistant items need
|
|
433
|
+
* it). One linear pass — called on state changes only, never per frame.
|
|
434
|
+
*/
|
|
435
|
+
export declare function groupToolEntries(items: TranscriptItem[]): Array<{
|
|
436
|
+
entry: TranscriptEntry;
|
|
437
|
+
at: number;
|
|
438
|
+
}>;
|
|
439
|
+
/** Content identity of a group (fold/diff purposes): member ids, statuses and durations. */
|
|
440
|
+
export declare function groupIdentity(group: GroupedTool): string;
|
|
441
|
+
export type FoldableKind = "reasoning" | "group" | "output";
|
|
442
|
+
/** A collapsible region of the transcript and how to address it (fold key, toggle target). */
|
|
443
|
+
export interface FoldCandidate {
|
|
444
|
+
/** Stable key for the fold state map (`a:` assistant index, `g:`/`t:` tool ids). */
|
|
445
|
+
key: string;
|
|
446
|
+
kind: FoldableKind;
|
|
447
|
+
/** Running/live content defaults expanded; finished reasoning, batches and long output collapse. */
|
|
448
|
+
defaultExpanded: boolean;
|
|
449
|
+
}
|
|
450
|
+
/** Cap for the reasoning text when expanded; longer sections show a truncation note. */
|
|
451
|
+
export declare const REASONING_EXPAND_MAX_LINES = 40;
|
|
452
|
+
/**
|
|
453
|
+
* The fold contract of one transcript entry: nothing (not collapsible), or a candidate with its
|
|
454
|
+
* default state. `at` is the entry's index within the ORIGINAL items array (assistant fold keys
|
|
455
|
+
* are stable because transcript items are append-only).
|
|
456
|
+
*/
|
|
457
|
+
export declare function foldCandidateOf(entry: TranscriptEntry, at: number): FoldCandidate | undefined;
|
|
458
|
+
/** Stable key of a transcript entry (used by the component sync to reuse row instances). */
|
|
459
|
+
export declare function entryKeyOf(entry: TranscriptEntry, at: number): string;
|
|
460
|
+
/** Every fold candidate of the transcript in display order; the keybinding targets the last one. */
|
|
461
|
+
export declare function foldCandidates(items: TranscriptItem[]): FoldCandidate[];
|
|
462
|
+
/**
|
|
463
|
+
* True when a printable key should toggle the nearest collapsible transcript row instead of
|
|
464
|
+
* typing: bound to `x`/`X` on an EMPTY editor line (no autocomplete), the same "empty input"
|
|
465
|
+
* convention Enter, Ctrl+D and `c`/`y` already use. Unlike copy, it also works while a turn runs
|
|
466
|
+
* (the nearest candidate may still exist mid-stream). A non-empty input never triggers.
|
|
467
|
+
*/
|
|
468
|
+
export declare function foldToggleKey(data: string, input: {
|
|
469
|
+
text: string;
|
|
470
|
+
autocomplete: boolean;
|
|
471
|
+
}): boolean;
|
|
269
472
|
/** Rebuilds transcript items from persisted history (used by /resume). */
|
|
270
473
|
export declare function itemsFromHistory(messages: Message[]): TranscriptItem[];
|