@alisio/alisio-code 0.1.0-alpha.9 → 0.1.1
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 +95 -16
- package/dist/analysis.d.ts +27 -0
- package/dist/analysis.js +145 -0
- package/dist/banner.js +2 -1
- package/dist/builtin.d.ts +3 -1
- package/dist/builtin.js +0 -24
- package/dist/main.js +133 -6
- package/dist/serve.d.ts +15 -0
- package/dist/serve.js +99 -0
- package/dist/tui/agent-manager.d.ts +105 -0
- package/dist/tui/agent-manager.js +269 -0
- package/dist/tui/agents.d.ts +5 -0
- package/dist/tui/agents.js +5 -0
- package/dist/tui/app.d.ts +42 -1
- package/dist/tui/app.js +1895 -97
- package/dist/tui/artifact-preview.d.ts +52 -0
- package/dist/tui/artifact-preview.js +212 -0
- package/dist/tui/artifacts.d.ts +54 -0
- package/dist/tui/artifacts.js +207 -0
- package/dist/tui/btw.d.ts +57 -0
- package/dist/tui/btw.js +76 -0
- package/dist/tui/components.d.ts +174 -12
- package/dist/tui/components.js +962 -66
- package/dist/tui/connect-input.d.ts +2 -0
- package/dist/tui/connect-input.js +1 -1
- package/dist/tui/exit.d.ts +10 -0
- package/dist/tui/exit.js +15 -0
- package/dist/tui/git-branch.d.ts +48 -0
- package/dist/tui/git-branch.js +99 -0
- package/dist/tui/goal.d.ts +75 -0
- package/dist/tui/goal.js +171 -0
- package/dist/tui/modes.d.ts +71 -0
- package/dist/tui/modes.js +90 -0
- package/dist/tui/open-path.d.ts +38 -0
- package/dist/tui/open-path.js +80 -0
- package/dist/tui/plan-review.d.ts +48 -0
- package/dist/tui/plan-review.js +76 -0
- package/dist/tui/queue.d.ts +2 -0
- package/dist/tui/queue.js +5 -1
- package/dist/tui/scroll.d.ts +8 -0
- package/dist/tui/scroll.js +12 -0
- package/dist/tui/settings-menu.d.ts +40 -0
- package/dist/tui/settings-menu.js +132 -0
- package/dist/tui/settings.d.ts +194 -0
- package/dist/tui/settings.js +482 -0
- package/dist/tui/state.d.ts +343 -7
- package/dist/tui/state.js +823 -54
- package/dist/tui/tasks.d.ts +123 -0
- package/dist/tui/tasks.js +369 -0
- package/dist/tui/theme.d.ts +42 -1
- package/dist/tui/theme.js +516 -1
- package/dist/tui/viewer-state.d.ts +7 -0
- package/dist/tui/viewer-state.js +36 -0
- package/dist/version.d.ts +7 -5
- package/dist/version.js +44 -8
- package/package.json +7 -9
package/dist/tui/state.d.ts
CHANGED
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Pure presentation logic for the TUI: formatting, command parsing and the reduction of
|
|
3
|
-
* versioned runner events into a view model. No terminal or pi-tui imports here.
|
|
4
|
-
*/
|
|
5
|
-
import type { Message, ModelInfo, RunEvent } from "@alisio/sdk";
|
|
1
|
+
import type { Message, ModelInfo, RunEvent, ToolResult, TreeNode, UiBlock } from "@alisio/sdk";
|
|
6
2
|
export type Level = "ok" | "warn" | "danger";
|
|
7
3
|
export declare function formatTokens(n: number): string;
|
|
8
4
|
/** Prefixes every model with its owning provider so identical model ids are never ambiguous. */
|
|
@@ -39,11 +35,46 @@ export interface PluginCatalogView {
|
|
|
39
35
|
}
|
|
40
36
|
/** Text markers remain meaningful without color: [x] active, [ ] inactive, [!] failed, [*] pending. */
|
|
41
37
|
/** Group headings are derived from the primary category (or "General") of each plugin. */
|
|
42
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Reserved value prefix marking a non-selectable group-header row in picker item lists. It can
|
|
40
|
+
* never collide with real entry ids (plugin ids, server names), which never start with "_".
|
|
41
|
+
*/
|
|
42
|
+
export declare const GROUP_HEADER_PREFIX = "__group:";
|
|
43
|
+
/** True when the item is a group header emitted under GROUP_HEADER_PREFIX (never selectable). */
|
|
44
|
+
export declare const isGroupHeader: (item: {
|
|
45
|
+
value: string;
|
|
46
|
+
}) => boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Nearest non-header index from `index` stepping `dir` (1 = down, -1 = up), wrapping at the
|
|
49
|
+
* edges exactly like a plain list would, so navigation skips header rows in both directions and
|
|
50
|
+
* never stops on one. Returns -1 for an empty list and `index` unchanged when every item is a
|
|
51
|
+
* header (callers then treat it as "no move").
|
|
52
|
+
*/
|
|
53
|
+
export declare function skipGroupHeaders(items: readonly {
|
|
54
|
+
value: string;
|
|
55
|
+
}[], index: number, dir: 1 | -1): number;
|
|
56
|
+
/**
|
|
57
|
+
* The display sequence a picker should render for a filter: rows matching SelectList's own
|
|
58
|
+
* prefix semantics, plus the group header of every group that still has at least one visible
|
|
59
|
+
* row, in original order. Groups with no match emit no header.
|
|
60
|
+
*/
|
|
61
|
+
export declare function visibleGroupedItems(items: ReadonlyArray<{
|
|
62
|
+
value: string;
|
|
63
|
+
label: string;
|
|
64
|
+
description?: string;
|
|
65
|
+
}>, filter: string): Array<{
|
|
66
|
+
value: string;
|
|
67
|
+
label: string;
|
|
68
|
+
description?: string;
|
|
69
|
+
}>;
|
|
70
|
+
export declare function pluginCatalogItems(entries: PluginCatalogView[]): ({
|
|
71
|
+
value: string;
|
|
72
|
+
label: string;
|
|
73
|
+
} | {
|
|
43
74
|
value: string;
|
|
44
75
|
label: string;
|
|
45
76
|
description: string;
|
|
46
|
-
}[];
|
|
77
|
+
})[];
|
|
47
78
|
export declare const pluginToggleNeedsConfirmation: (entry: PluginCatalogView) => boolean;
|
|
48
79
|
export interface McpServerView {
|
|
49
80
|
name: string;
|
|
@@ -116,6 +147,10 @@ export interface CommandSpec {
|
|
|
116
147
|
argumentHint?: string;
|
|
117
148
|
aliases?: string[];
|
|
118
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Built-in slash commands the TUI offers, derived from the core `CommandCatalog` (the TUI
|
|
152
|
+
* surface of `BUILTIN_COMMANDS`). Kept as `COMMANDS` for compatibility.
|
|
153
|
+
*/
|
|
119
154
|
export declare const COMMANDS: CommandSpec[];
|
|
120
155
|
/** Every TUI slash name (commands, aliases and routing prefixes); templates cannot take them. */
|
|
121
156
|
export declare function reservedCommandNames(): string[];
|
|
@@ -124,6 +159,117 @@ export declare function parseCommand(input: string): {
|
|
|
124
159
|
name: string;
|
|
125
160
|
args: string;
|
|
126
161
|
} | undefined;
|
|
162
|
+
/** Reasoning-effort capability advertised by a model's catalog entry (`ModelInfo.effort`). */
|
|
163
|
+
export interface EffortCapability {
|
|
164
|
+
supportedLevels: string[];
|
|
165
|
+
defaultLevel?: string;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The effective reasoning effort to send for a model: the persisted level when the model
|
|
169
|
+
* supports it, otherwise the model's default level (silent fallback), and nothing when the
|
|
170
|
+
* model advertises no effort levels at all.
|
|
171
|
+
*/
|
|
172
|
+
export declare function effectiveEffort(persisted: string | undefined, capability: EffortCapability | undefined): string | undefined;
|
|
173
|
+
/** Validates a `/effort <level>` argument against the active model; returns an error or nothing. */
|
|
174
|
+
export declare function validateEffortLevel(level: string, capability: EffortCapability | undefined): string | undefined;
|
|
175
|
+
export declare function effortPickerItems(capability: EffortCapability, active: string | undefined): Array<{
|
|
176
|
+
value: string;
|
|
177
|
+
label: string;
|
|
178
|
+
description?: string;
|
|
179
|
+
}>;
|
|
180
|
+
/** Role of a status-line identity part; the renderer maps each role to a distinct color. */
|
|
181
|
+
export type IdentityRole = "agent" | "mode" | "model" | "provider" | "effort";
|
|
182
|
+
export interface IdentityPart extends Segment {
|
|
183
|
+
role: IdentityRole;
|
|
184
|
+
}
|
|
185
|
+
export interface IdentityInput {
|
|
186
|
+
agent: string;
|
|
187
|
+
/** Permission mode (`ask`, `auto`, `full`, `custom`, `read-only`); omitted when unknown. */
|
|
188
|
+
mode?: string;
|
|
189
|
+
model: string;
|
|
190
|
+
provider?: string;
|
|
191
|
+
effort?: string;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* The ordered identity parts for the status line below the editor:
|
|
195
|
+
* `agent: <name> · <model> · <provider> · <effort>`, with the effort part omitted when the
|
|
196
|
+
* active model advertises no supported levels (`effort === undefined`). Colors are applied by
|
|
197
|
+
* the renderer per role; this module stays terminal-free and testable.
|
|
198
|
+
*/
|
|
199
|
+
export declare function identityParts(input: IdentityInput): IdentityPart[];
|
|
200
|
+
/** Drops the lowest-priority identity parts until the line fits `width`; truncates the survivor. */
|
|
201
|
+
export declare function fitIdentityParts(input: IdentityInput, width: number): IdentityPart[];
|
|
202
|
+
/** Minimal structural view of a skill for slash autocompletion (subset of the core catalog entry). */
|
|
203
|
+
export interface SkillCompletionEntry {
|
|
204
|
+
id: string;
|
|
205
|
+
name: string;
|
|
206
|
+
displayId: string;
|
|
207
|
+
description: string;
|
|
208
|
+
/** Catalog scope of the skill: user | project | config | plugin (drives the [u]/[p]/[c]/[l] marker). */
|
|
209
|
+
scope?: string;
|
|
210
|
+
enabled: boolean;
|
|
211
|
+
locked: boolean;
|
|
212
|
+
effective: boolean;
|
|
213
|
+
}
|
|
214
|
+
export interface SlashCompletionItem {
|
|
215
|
+
value: string;
|
|
216
|
+
label: string;
|
|
217
|
+
description?: string;
|
|
218
|
+
}
|
|
219
|
+
export declare const SKILL_COMPLETION_DESCRIPTION_LIMIT = 80;
|
|
220
|
+
/**
|
|
221
|
+
* OpenCode-style scope marker for a skill's slash entry, mirroring the catalog scopes the /skills
|
|
222
|
+
* manager shows: user, project, config and plugin (plugin skills are locked by their owner plugin).
|
|
223
|
+
*/
|
|
224
|
+
export declare const skillScopeMarker: (skill: SkillCompletionEntry) => string | undefined;
|
|
225
|
+
/**
|
|
226
|
+
* Description for a skill's first-class `skill:<id>` slash entry: scope marker, status hint, then
|
|
227
|
+
* the skill description truncated to the shared limit. The marker and status are prepended before
|
|
228
|
+
* truncating, so they survive the cap just like the /skills argument completions.
|
|
229
|
+
*/
|
|
230
|
+
export declare function skillSlashDescription(skill: SkillCompletionEntry): string;
|
|
231
|
+
/**
|
|
232
|
+
* Suggested completions for `/skills <prefix>`: every entry the /skills manager shows, filtered by
|
|
233
|
+
* prefix (case-insensitive) on name or description. Selecting a suggestion only fills the argument;
|
|
234
|
+
* submitting still opens the skills manager.
|
|
235
|
+
*/
|
|
236
|
+
export declare function skillCompletions(catalog: SkillCompletionEntry[], prefix: string, limit?: number): SlashCompletionItem[];
|
|
237
|
+
export interface SlashCompletionSource {
|
|
238
|
+
name: string;
|
|
239
|
+
description?: string;
|
|
240
|
+
argumentHint?: string;
|
|
241
|
+
aliases?: string[];
|
|
242
|
+
}
|
|
243
|
+
export interface SlashCompletionContext {
|
|
244
|
+
/** Live session rows for `/resume`: already filtered to the typed prefix and mapped. */
|
|
245
|
+
sessions?: (prefix: string) => SlashCompletionItem[];
|
|
246
|
+
/** Effective skill catalog backing `/skills` (the same entries the skills manager shows). */
|
|
247
|
+
skills: SkillCompletionEntry[];
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Builds the editor slash-autocomplete command list. Aliases get their own entries with the same
|
|
251
|
+
* description and argument completions, because the provider matches commands by fuzzy name.
|
|
252
|
+
* Effective skills are appended as first-class `skill:<id>` entries so `/ski…`, `/skill:b…` and
|
|
253
|
+
* even `/branch…` all surface them; submitting already routes `skill:` commands to skill load, so
|
|
254
|
+
* selecting an entry only needs to insert the command name. `options.skillEntries: false` gates
|
|
255
|
+
* ONLY those standalone `skill:` entries (e.g. the `tui.skillSlashCommands` toggle): the `/skills`
|
|
256
|
+
* manager and its argument completion keep working, since `context.skills` still feeds both.
|
|
257
|
+
*/
|
|
258
|
+
export interface SlashCompletionOptions {
|
|
259
|
+
/** Include first-class `skill:<id>` entries for effective skills (default true). */
|
|
260
|
+
skillEntries?: boolean;
|
|
261
|
+
}
|
|
262
|
+
export declare function slashCompletionCommands(sources: SlashCompletionSource[], context: SlashCompletionContext, options?: SlashCompletionOptions): ({
|
|
263
|
+
getArgumentCompletions: (prefix: string) => SlashCompletionItem[];
|
|
264
|
+
name: string;
|
|
265
|
+
description: string | undefined;
|
|
266
|
+
argumentHint?: string | undefined;
|
|
267
|
+
} | {
|
|
268
|
+
getArgumentCompletions?: undefined;
|
|
269
|
+
name: string;
|
|
270
|
+
description: string | undefined;
|
|
271
|
+
argumentHint?: string | undefined;
|
|
272
|
+
})[];
|
|
127
273
|
export declare function summarizeToolArgs(name: string, args: string): string;
|
|
128
274
|
export interface DiffLine {
|
|
129
275
|
sign: "+" | "-";
|
|
@@ -137,6 +283,8 @@ export interface EditSummary {
|
|
|
137
283
|
}
|
|
138
284
|
export declare function editSummary(name: string, args: string): EditSummary | undefined;
|
|
139
285
|
export type ToolStatus = "running" | "approval" | "ok" | "error";
|
|
286
|
+
/** Capability kind of a tool call; drives grouping labels and batch display. */
|
|
287
|
+
export type ToolKind = "read" | "write" | "process" | "mcp" | "internal" | "other";
|
|
140
288
|
export type TranscriptItem = {
|
|
141
289
|
kind: "user";
|
|
142
290
|
text: string;
|
|
@@ -145,6 +293,10 @@ export type TranscriptItem = {
|
|
|
145
293
|
text: string;
|
|
146
294
|
reasoning: string;
|
|
147
295
|
done: boolean;
|
|
296
|
+
/** Epoch ms of the first reasoning delta; with `reasoningDoneAt` it approximates the thinking interval. */
|
|
297
|
+
reasoningStartedAt?: number;
|
|
298
|
+
/** Epoch ms of the last reasoning delta (the end of the visible thought section). */
|
|
299
|
+
reasoningDoneAt?: number;
|
|
148
300
|
} | {
|
|
149
301
|
kind: "tool";
|
|
150
302
|
id: string;
|
|
@@ -154,6 +306,17 @@ export type TranscriptItem = {
|
|
|
154
306
|
status: ToolStatus;
|
|
155
307
|
durationMs?: number;
|
|
156
308
|
preview?: string;
|
|
309
|
+
/** Structured block rendered natively by the TUI (from a `{type:"ui"}` result part). */
|
|
310
|
+
ui?: UiBlock;
|
|
311
|
+
/** Base64 image rendered inline by the TUI when the terminal supports it (from a `{type:"image"}` part). */
|
|
312
|
+
image?: {
|
|
313
|
+
mimeType: string;
|
|
314
|
+
data: string;
|
|
315
|
+
};
|
|
316
|
+
/** Effect-derived kind (grouping label); name-heuristic fallback for replayed history. */
|
|
317
|
+
toolKind?: ToolKind;
|
|
318
|
+
/** Exit code derived safely from the JSON preview when the tool reports one (run_process/shell/search_text). */
|
|
319
|
+
exitCode?: number;
|
|
157
320
|
} | {
|
|
158
321
|
kind: "notice";
|
|
159
322
|
text: string;
|
|
@@ -182,6 +345,16 @@ export interface ViewState {
|
|
|
182
345
|
items: TranscriptItem[];
|
|
183
346
|
streaming: boolean;
|
|
184
347
|
compacting: boolean;
|
|
348
|
+
/** The runner is sending a silent request again (`request_retry`); cleared by any output. */
|
|
349
|
+
retry?: {
|
|
350
|
+
attempt: number;
|
|
351
|
+
of: number;
|
|
352
|
+
};
|
|
353
|
+
/** The response was cut by the output limit and is requested again (`truncation_recovery`). */
|
|
354
|
+
recovery?: {
|
|
355
|
+
attempt: number;
|
|
356
|
+
of: number;
|
|
357
|
+
};
|
|
185
358
|
model: string;
|
|
186
359
|
/** Context size in tokens: provider-reported, or estimated (`~`). */
|
|
187
360
|
context?: {
|
|
@@ -189,11 +362,174 @@ export interface ViewState {
|
|
|
189
362
|
estimated: boolean;
|
|
190
363
|
};
|
|
191
364
|
runStartedAt?: number;
|
|
365
|
+
/** Epoch ms of the latest event of the live run (any type); undefined when no run is live. */
|
|
366
|
+
lastEventAt?: number;
|
|
192
367
|
stats: Stats;
|
|
193
368
|
}
|
|
194
369
|
export declare function initialViewState(model: string, now?: number): ViewState;
|
|
195
370
|
export declare function addItem(state: ViewState, item: TranscriptItem): ViewState;
|
|
371
|
+
/** Approximated thinking interval of a completed reasoning section, when the events carried timestamps. */
|
|
372
|
+
export declare function reasoningDurationMs(item: {
|
|
373
|
+
reasoningStartedAt?: number;
|
|
374
|
+
reasoningDoneAt?: number;
|
|
375
|
+
}): number | undefined;
|
|
196
376
|
export declare function reduceEvent(state: ViewState, event: RunEvent): ViewState;
|
|
377
|
+
/** No event for this long: the footer says how long the run has been quiet. */
|
|
378
|
+
export declare const QUIET_MS = 15000;
|
|
379
|
+
/** No event for this long: the footer marks the run as possibly stuck. */
|
|
380
|
+
export declare const STALLED_MS = 60000;
|
|
381
|
+
export interface RunPhase {
|
|
382
|
+
label: string;
|
|
383
|
+
/** Silence is expected here (the user's turn, or a sub-agent working in its own session). */
|
|
384
|
+
silentByDesign: boolean;
|
|
385
|
+
}
|
|
386
|
+
/** What the live run is doing, from the transcript items and flags the events already update. */
|
|
387
|
+
export declare function runPhase(view: ViewState): RunPhase;
|
|
388
|
+
/** Milliseconds of silence worth reporting (0 when the run is busy, or silent by design). */
|
|
389
|
+
export declare function quietFor(view: ViewState, now: number): number;
|
|
197
390
|
export declare function lastAssistantText(items: TranscriptItem[]): string | undefined;
|
|
391
|
+
/**
|
|
392
|
+
* True when a printable key should copy the last assistant response instead of typing: bound to
|
|
393
|
+
* `c`/`y` (and uppercase) on an EMPTY editor line, while no autocomplete is showing and no turn
|
|
394
|
+
* is running — the same "empty input" convention Enter and Ctrl+D already use. A non-empty input
|
|
395
|
+
* never triggers, so typing `c` or `y` mid-message is unaffected.
|
|
396
|
+
*/
|
|
397
|
+
export declare function editorCopyKey(data: string, input: {
|
|
398
|
+
text: string;
|
|
399
|
+
autocomplete: boolean;
|
|
400
|
+
busy: boolean;
|
|
401
|
+
}): boolean;
|
|
402
|
+
/** True when an unknown event value is a `Node` of a tree UI block. */
|
|
403
|
+
export declare function isTreeNode(value: unknown): value is TreeNode;
|
|
404
|
+
/** True when an unknown event value is an Alisio `UiBlock` (validated defensively). */
|
|
405
|
+
export declare function isUiBlock(value: unknown): value is UiBlock;
|
|
406
|
+
/** True when an unknown event value is a `{type:"image"}`-style part (mime + base64 data). */
|
|
407
|
+
export declare function isImagePart(value: unknown): value is {
|
|
408
|
+
mimeType: string;
|
|
409
|
+
data: string;
|
|
410
|
+
};
|
|
411
|
+
/** Rich (ui/image) parts of a persisted tool result, if any. */
|
|
412
|
+
export declare function richPartsOf(result: ToolResult | undefined, toolName?: string): {
|
|
413
|
+
ui?: UiBlock;
|
|
414
|
+
image?: {
|
|
415
|
+
mimeType: string;
|
|
416
|
+
data: string;
|
|
417
|
+
};
|
|
418
|
+
};
|
|
419
|
+
/**
|
|
420
|
+
* `read_file` → `Read File`, `search_text` → `Search Text`, `mcp_devforge_time_diff` →
|
|
421
|
+
* `MCP · Devforge Time Diff`. Splits on `_`/`-`/`.`/spaces, keeps known acronyms (MCP, HTTP…)
|
|
422
|
+
* and bare numeric suffixes (`read_file_2` → `Read File 2`). The machine name stays available
|
|
423
|
+
* dimmed in grouped detail rows and in the `/tools` and `/stats` reports.
|
|
424
|
+
*/
|
|
425
|
+
export declare function humanizeToolName(name: string): string;
|
|
426
|
+
/** Verb and count noun used by grouped batch rows per tool kind. */
|
|
427
|
+
export declare const TOOL_KIND_VERB: Record<ToolKind, string>;
|
|
428
|
+
export declare const TOOL_KIND_WORD: Record<ToolKind, string>;
|
|
429
|
+
/**
|
|
430
|
+
* Capability kind of a tool call. Live events carry the registry `effect` (exact); replayed
|
|
431
|
+
* history falls back to conservative name heuristics. `mcp_*` is always the mcp kind.
|
|
432
|
+
*/
|
|
433
|
+
export declare function toolKindOf(name: string, effect?: string): ToolKind;
|
|
434
|
+
/** Terminal-preview caps for collapsed rows (same values the renderer always used). */
|
|
435
|
+
export declare const OUTPUT_PREVIEW_LINES_OK = 3;
|
|
436
|
+
export declare const OUTPUT_PREVIEW_LINES_ERROR = 6;
|
|
437
|
+
export declare const previewLinesFor: (status: ToolStatus) => number;
|
|
438
|
+
/** Preview rows as the renderer shows them: blank lines dropped, tabs kept for the caller to expand. */
|
|
439
|
+
export declare const previewRows: (preview: string) => string[];
|
|
440
|
+
/** True when the preview exceeds the collapsed cap (the row becomes a collapsible "output"). */
|
|
441
|
+
export declare function previewTruncated(preview: string | undefined, status: ToolStatus): boolean;
|
|
442
|
+
/**
|
|
443
|
+
* Exit code derived safely from a text preview. `run_process`/`shell`/`search_text` return
|
|
444
|
+
* `{stdout, stderr, exitCode, truncated}` JSON; read-effect tools may carry an appended
|
|
445
|
+
* `\n<instructions>…` block, retried on the JSON prefix. Any other shape yields nothing.
|
|
446
|
+
*/
|
|
447
|
+
export declare function exitCodeOf(preview: string | undefined): number | undefined;
|
|
448
|
+
/** Renderable view of one tool call (singleton row, or a member of a grouped batch). */
|
|
449
|
+
export interface ToolItemView {
|
|
450
|
+
id: string;
|
|
451
|
+
/** Machine name (kept for dimmed detail display). */
|
|
452
|
+
name: string;
|
|
453
|
+
/** Humanized display name. */
|
|
454
|
+
humanName: string;
|
|
455
|
+
kind: ToolKind;
|
|
456
|
+
summary: string;
|
|
457
|
+
status: ToolStatus;
|
|
458
|
+
durationMs?: number;
|
|
459
|
+
preview?: string;
|
|
460
|
+
ui?: UiBlock;
|
|
461
|
+
image?: {
|
|
462
|
+
mimeType: string;
|
|
463
|
+
data: string;
|
|
464
|
+
};
|
|
465
|
+
exitCode?: number;
|
|
466
|
+
}
|
|
467
|
+
/** A batch of consecutive same-kind, finished tool calls rendered as ONE collapsible row. */
|
|
468
|
+
export interface GroupedTool {
|
|
469
|
+
/** Id of the first member call (stable fold key while the batch grows). */
|
|
470
|
+
id: string;
|
|
471
|
+
members: ToolItemView[];
|
|
472
|
+
kind: ToolKind;
|
|
473
|
+
/** Aggregate: `error` when any member failed, else `ok` (members are all terminal). */
|
|
474
|
+
status: ToolStatus;
|
|
475
|
+
/** Sum of member durations. */
|
|
476
|
+
totalMs: number;
|
|
477
|
+
/** Header name: the shared humanized tool name, or the kind verb for mixed batches. */
|
|
478
|
+
label: string;
|
|
479
|
+
/** Count noun matching `label` (`reads`, `files`, `commands`…). */
|
|
480
|
+
word: string;
|
|
481
|
+
}
|
|
482
|
+
/** Everything the transcript renders: a plain item, or one grouped batch row. */
|
|
483
|
+
export type TranscriptEntry = TranscriptItem | {
|
|
484
|
+
kind: "group";
|
|
485
|
+
group: GroupedTool;
|
|
486
|
+
};
|
|
487
|
+
export declare function toolItemView(item: Extract<TranscriptItem, {
|
|
488
|
+
kind: "tool";
|
|
489
|
+
}>): ToolItemView;
|
|
490
|
+
/**
|
|
491
|
+
* Consecutive tool calls of the same kind whose statuses are ALL terminal (ok/error) merge into
|
|
492
|
+
* one `group` entry; running/approval calls always stay singleton so their spinner and live state
|
|
493
|
+
* stay visible. A kind change splits the run (`read` never merges with `shell`). Order is
|
|
494
|
+
* preserved; every entry carries its index within `items` (fold keys for assistant items need
|
|
495
|
+
* it). One linear pass — called on state changes only, never per frame.
|
|
496
|
+
*/
|
|
497
|
+
export declare function groupToolEntries(items: TranscriptItem[]): Array<{
|
|
498
|
+
entry: TranscriptEntry;
|
|
499
|
+
at: number;
|
|
500
|
+
}>;
|
|
501
|
+
/** Content identity of a group (fold/diff purposes): member ids, statuses and durations. */
|
|
502
|
+
export declare function groupIdentity(group: GroupedTool): string;
|
|
503
|
+
export type FoldableKind = "reasoning" | "group" | "output";
|
|
504
|
+
/** A collapsible region of the transcript and how to address it (fold key, toggle target). */
|
|
505
|
+
export interface FoldCandidate {
|
|
506
|
+
/** Stable key for the fold state map (`a:` assistant index, `g:`/`t:` tool ids). */
|
|
507
|
+
key: string;
|
|
508
|
+
kind: FoldableKind;
|
|
509
|
+
/** Running/live content defaults expanded; finished reasoning, batches and long output collapse. */
|
|
510
|
+
defaultExpanded: boolean;
|
|
511
|
+
}
|
|
512
|
+
/** Cap for the reasoning text when expanded; longer sections show a truncation note. */
|
|
513
|
+
export declare const REASONING_EXPAND_MAX_LINES = 40;
|
|
514
|
+
/**
|
|
515
|
+
* The fold contract of one transcript entry: nothing (not collapsible), or a candidate with its
|
|
516
|
+
* default state. `at` is the entry's index within the ORIGINAL items array (assistant fold keys
|
|
517
|
+
* are stable because transcript items are append-only).
|
|
518
|
+
*/
|
|
519
|
+
export declare function foldCandidateOf(entry: TranscriptEntry, at: number): FoldCandidate | undefined;
|
|
520
|
+
/** Stable key of a transcript entry (used by the component sync to reuse row instances). */
|
|
521
|
+
export declare function entryKeyOf(entry: TranscriptEntry, at: number): string;
|
|
522
|
+
/** Every fold candidate of the transcript in display order; the keybinding targets the last one. */
|
|
523
|
+
export declare function foldCandidates(items: TranscriptItem[]): FoldCandidate[];
|
|
524
|
+
/**
|
|
525
|
+
* True when a printable key should toggle the nearest collapsible transcript row instead of
|
|
526
|
+
* typing: bound to `x`/`X` on an EMPTY editor line (no autocomplete), the same "empty input"
|
|
527
|
+
* convention Enter, Ctrl+D and `c`/`y` already use. Unlike copy, it also works while a turn runs
|
|
528
|
+
* (the nearest candidate may still exist mid-stream). A non-empty input never triggers.
|
|
529
|
+
*/
|
|
530
|
+
export declare function foldToggleKey(data: string, input: {
|
|
531
|
+
text: string;
|
|
532
|
+
autocomplete: boolean;
|
|
533
|
+
}): boolean;
|
|
198
534
|
/** Rebuilds transcript items from persisted history (used by /resume). */
|
|
199
535
|
export declare function itemsFromHistory(messages: Message[]): TranscriptItem[];
|