@vincemakes/kiso-code 0.8.0 → 0.9.0

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/chat.d.ts CHANGED
@@ -45,6 +45,10 @@ export interface UsageDelta {
45
45
  * recovers on the next known event). */
46
46
  readonly total: number | null;
47
47
  readonly missed: number | null;
48
+ /** TUI2-R1 (E): the CANONICAL cost of this request — null when the
49
+ * pricing table has no rate for the route (the R5b-④c absent stamp).
50
+ * Null is carried, never zeroed: a missing rate is not a free call. */
51
+ readonly costUsd: number | null;
48
52
  }
49
53
  /**
50
54
  * The CLI's usage consumer (E2 1.3.0, the R2a-1 ruling 2026-08-13) — the
@@ -76,6 +80,7 @@ export declare function usageFromEvent(route: string | undefined, ev: import("@v
76
80
  * is gone) — docked only, 200ms rotation between the request and the
77
81
  * first event. */
78
82
  export declare function startStatusSpinner(onTick: (glyph: string) => void): () => void;
83
+ export declare function startShellTail(sessionId: string, callId: string, command: string, startedAt: number): () => void;
79
84
  /**
80
85
  * Consume a run, answering approval pauses as they arrive. `resumeMode`
81
86
  * marks a session.resume() continuation. `faux` picks the status line's
@@ -84,7 +89,7 @@ export declare function startStatusSpinner(onTick: (glyph: string) => void): ()
84
89
  * echo is UI, the chip is the record; the momentary double-render is
85
90
  * the design's explicit point).
86
91
  */
87
- export declare function consumeRun(session: AgentSession, run: Run, input: LineInput, turnNo: number, faux: boolean, statusCb: ((usage: RunUsage, ctxRatio: number) => void) | null,
92
+ export declare function consumeRun(session: AgentSession, run: Run, input: LineInput, turnNo: number, faux: boolean, statusCb: ((usage: RunUsage, ctxRatio: number, costUsd?: number | null) => void) | null,
88
93
  /** W21: the amend words ("Yes + feedback") ride the NEXT user turn —
89
94
  * threaded from chat's submitTurn; absent in the recovery flow
90
95
  * (resume) where a dropped amend is noticed instead. */
package/dist/chat.js CHANGED
@@ -4,10 +4,10 @@
4
4
  * approval-moment mini-diff, the status spinner, and the context
5
5
  * estimates. All bodies moved verbatim from index.ts.
6
6
  */
7
- import { readFileSync } from "node:fs";
8
- import { escapeTerminal, idleStatus, palette, renderEvent, renderRecap, runningStatus, toolTarget, STATUS_GLYPHS, } from "@vincemakes/kiso-tui";
7
+ import { readFileSync, statSync } from "node:fs";
8
+ import { escapeTerminal, cacheHitPct, idleStatus, palette, renderEvent, renderRecap, runningStatus, toolTarget, STATUS_GLYPHS, } from "@vincemakes/kiso-tui";
9
9
  import { editFileDiff, writeFileDiff } from "@vincemakes/kiso-tui";
10
- import { canonicalTargetPath } from "@vincemakes/kiso-tools-node";
10
+ import { canonicalTargetPath, shellProgressPath } from "@vincemakes/kiso-tools-node";
11
11
  import { canonicalizeUsage } from "@vincemakes/kiso-runtime";
12
12
  import { dispatch } from "./dispatch.js";
13
13
  import { agentModel, body, bodyLog, configuredWindow, dock } from "./state.js";
@@ -89,7 +89,7 @@ export function usageFromEvent(route, ev, prevTotal) {
89
89
  const m = Math.min(prevTotal, total) - c.cacheRead;
90
90
  missed = m > CACHE_MISS_FLOOR ? m : null;
91
91
  }
92
- return { usage: { in: c.input, out: c.output, cache: c.cacheRead, known: ev.known }, total, missed };
92
+ return { usage: { in: c.input, out: c.output, cache: c.cacheRead, known: ev.known }, total, missed, costUsd: c.costUsd };
93
93
  }
94
94
  /** v2b: the spinner merged into the STATUS BAR (the v2a standalone glyph
95
95
  * is gone) — docked only, 200ms rotation between the request and the
@@ -105,6 +105,45 @@ export function startStatusSpinner(onTick) {
105
105
  timer.unref();
106
106
  return () => clearInterval(timer);
107
107
  }
108
+ /**
109
+ * TUI2-R1 (C) — the shell tailer: the READER half of the progress
110
+ * sidecar (the writer is the shell tool, tools-node).
111
+ *
112
+ * The CLI is the only place that holds both facts the derived key needs
113
+ * — the session's id and the running call's command — so the tail is
114
+ * read here and handed to the cell. A poll, not a watcher: fs.watch's
115
+ * behaviour on a file being appended to differs by platform, and the
116
+ * one thing this must never do is misbehave in a way that costs the run.
117
+ *
118
+ * THE FRESHNESS GUARD is the part that makes a kill -9 leftover
119
+ * harmless. A sidecar the writer never got to remove keeps its old
120
+ * mtime; a tail is read only from a file modified AT OR AFTER the call
121
+ * started. A ghost from a previous process cannot be shown as this
122
+ * call's output — and since the tail is display-only, showing nothing is
123
+ * always the safe answer.
124
+ */
125
+ const TAIL_POLL_MS = 250;
126
+ const TAIL_BYTES = 4096; // the last lines are all the window can hold
127
+ export function startShellTail(sessionId, callId, command, startedAt) {
128
+ const path = shellProgressPath(sessionId, command);
129
+ const read = () => {
130
+ try {
131
+ const stat = statSync(path);
132
+ if (stat.mtimeMs + 1000 < startedAt)
133
+ return; // a ghost from a killed run — never this call's
134
+ const text = readFileSync(path, "utf8");
135
+ body.toolProgress(callId, text.slice(-TAIL_BYTES).trimEnd());
136
+ }
137
+ catch {
138
+ // no sidecar yet, removed at settle, or unreadable — the tail
139
+ // is an observation, and its absence is never an error
140
+ }
141
+ };
142
+ read();
143
+ const timer = setInterval(read, TAIL_POLL_MS);
144
+ timer.unref();
145
+ return () => clearInterval(timer);
146
+ }
108
147
  /** v2e: the approval-moment mini-diff — edit_file/write_file changes as
109
148
  * ± lines; other tools get null (no diff, no cost). The file read is
110
149
  * best-effort: an unreadable file yields NO diff, never a failure —
@@ -128,7 +167,9 @@ function approvalDiff(name, input) {
128
167
  const replace = typeof input.replace === "string" ? input.replace : "";
129
168
  if (search === "")
130
169
  return null;
131
- return editFileDiff(oldContent ?? "", search, replace);
170
+ // TUI2-R1.5 ② (VD-2): the path rides along so a miss can name the
171
+ // file in its honest note instead of fabricating a diff.
172
+ return editFileDiff(oldContent ?? "", search, replace, path);
132
173
  }
133
174
  const content = typeof input.content === "string" ? input.content : "";
134
175
  return writeFileDiff(oldContent, content);
@@ -268,6 +309,16 @@ submitTurn) {
268
309
  // at the first non-thinking event (the fold needs the seconds).
269
310
  let thoughtSeconds = 0;
270
311
  let thinkingSince = null;
312
+ // TUI2-R1 (C): the shell commands seen this run, and the tailers
313
+ // running for them. A tailer is started when the execution starts and
314
+ // stopped at the call's result — and the finally below stops any that
315
+ // an abort left behind, so a poller can never outlive its run.
316
+ const shellCommands = new Map();
317
+ const tailers = new Map();
318
+ const stopTail = (callId) => {
319
+ tailers.get(callId)?.();
320
+ tailers.delete(callId);
321
+ };
271
322
  try {
272
323
  for await (const ev of run) {
273
324
  last = ev;
@@ -295,10 +346,18 @@ submitTurn) {
295
346
  if (ev.name === "edit_file")
296
347
  editCount += 1;
297
348
  body.toolStart(ev.name, ev.callId, ev.input ?? {});
349
+ // TUI2-R1 (C): the command is the sidecar key's other half —
350
+ // remembered here, used when the execution actually starts.
351
+ if (ev.name === "shell" && typeof ev.input?.command === "string")
352
+ shellCommands.set(ev.callId, ev.input.command);
298
353
  break;
299
- case "tool_execution_started":
354
+ case "tool_execution_started": {
300
355
  body.toolRunning(ev.callId);
356
+ const command = shellCommands.get(ev.callId);
357
+ if (command !== undefined)
358
+ tailers.set(ev.callId, startShellTail(session.id, ev.callId, command, Date.now()));
301
359
  break;
360
+ }
302
361
  case "tool_execution_succeeded":
303
362
  body.toolSucceeded(ev.callId);
304
363
  break;
@@ -306,6 +365,9 @@ submitTurn) {
306
365
  body.toolFailed(ev.callId, ev.error);
307
366
  break;
308
367
  case "tool_result": {
368
+ // TUI2-R1 (C): the observation window closes the instant the
369
+ // real result exists — the tail must never race it.
370
+ stopTail(ev.callId);
309
371
  const text = typeof ev.content === "string" ? ev.content : "";
310
372
  // W19: a DENIED call carries its reason — extracted from the
311
373
  // result's "[Permission denied] " prefix, keyed on the
@@ -340,7 +402,9 @@ submitTurn) {
340
402
  usage = delta.usage;
341
403
  prevTotal = delta.total;
342
404
  missed = delta.missed;
343
- statusCb?.(usage, estimateCtxRatio(session));
405
+ // TUI2-R1 (E): the request's canonical cost rides the same
406
+ // callback the usage does — one settled request, one addition.
407
+ statusCb?.(usage, estimateCtxRatio(session), delta.costUsd);
344
408
  break;
345
409
  }
346
410
  case "uncertain_pending":
@@ -471,6 +535,11 @@ submitTurn) {
471
535
  body.thinkingEnd(); // a trailing thinking block folds at the run's end
472
536
  }
473
537
  finally {
538
+ // TUI2-R1 (C): an abort or a throw leaves the loop without a
539
+ // tool_result — every tailer stops here regardless, so no poller
540
+ // outlives the run that started it.
541
+ for (const callId of [...tailers.keys()])
542
+ stopTail(callId);
474
543
  }
475
544
  return last;
476
545
  }
@@ -639,6 +708,11 @@ export async function chat(session, faux, input, autoCompact) {
639
708
  // glyph (▖▘▝▗ — the spinner drives it) + wall seconds + ↓ out tokens
640
709
  // + the interrupt hint. ctx left is the live estimate everywhere.
641
710
  let runUsage = { in: null, out: null, cache: null, known: false };
711
+ // TUI2-R1 (E): the session's spend so far — the CANONICAL cost of every
712
+ // request this process has seen, summed. Null stays null: a route with
713
+ // no rate in the pricing table contributes nothing and the row shows no
714
+ // $ at all, because a partial total presented as a total is a lie.
715
+ let spentUsd = null;
642
716
  let runGlyph = "▖";
643
717
  let runStart = Date.now();
644
718
  // KC2 §5: the STATE (the glyph, the run's start, the usage, the dock)
@@ -651,13 +725,29 @@ export async function chat(session, faux, input, autoCompact) {
651
725
  // parentheses idiom names the read-only constraint. The tier is the
652
726
  // CALLER's word (the recovery flow passes the bare mode).
653
727
  const paintIdle = () => {
654
- if (dock.active)
655
- dock.setStatus(idleStatus(getMode() === "plan" ? "plan (read-only)" : getMode(), agentModel, estimateCtxRatio(session)));
728
+ if (!dock.active)
729
+ return;
730
+ // TUI2-R1 (E): the meter rides the idle row — both fields omitted
731
+ // when unknown, so a session that has not called the model paints
732
+ // exactly the pre-round row.
733
+ dock.setStatus(idleStatus(getMode() === "plan" ? "plan (read-only)" : getMode(), agentModel, estimateCtxRatio(session), {
734
+ cacheHitPct: cacheHitPct(runUsage),
735
+ costUsd: spentUsd,
736
+ }));
656
737
  };
657
- const statusCb = (u, ctx) => {
738
+ const statusCb = (u, ctx, costUsd) => {
658
739
  runUsage = u;
740
+ addCost(costUsd ?? null);
659
741
  paintRunning();
660
742
  };
743
+ // TUI2-R1 (E): the canonical cost of one settled request, added to the
744
+ // session's running total. A null cost (no rate for the route) adds
745
+ // nothing and leaves the total as it was.
746
+ const addCost = (usd) => {
747
+ if (usd === null)
748
+ return;
749
+ spentUsd = (spentUsd ?? 0) + usd;
750
+ };
661
751
  const submitTurn = (line) => {
662
752
  const slot = { line, cancelled: false };
663
753
  pendingTurns.push(slot);
@@ -717,6 +807,7 @@ export async function chat(session, faux, input, autoCompact) {
717
807
  paintIdle,
718
808
  submitTurn,
719
809
  estimateCtx: () => estimateCtxRatio(session),
810
+ contextWindow: () => contextWindowTokens(),
720
811
  };
721
812
  // the ergonomics batch C8: the auto-compact check — the /compact FULL path via the
722
813
  // shared dispatch (same notices, same chain ordering, same mid-run
@@ -756,6 +847,15 @@ export async function chat(session, faux, input, autoCompact) {
756
847
  const recoveryRun = session.resume();
757
848
  currentRun = recoveryRun;
758
849
  turnNo += 1;
850
+ // TUI2-R1.5 ③ (VD-3 family): stamp the run's start AT the run's
851
+ // entry. Every other run path does; this one inherited the value
852
+ // from the process's own startup, so its "working Ns" was the
853
+ // session's age rather than the recovery's. The drift is small
854
+ // today (recovery follows startup closely) and unbounded in
855
+ // principle — a slow MCP connect is seconds the recovery never
856
+ // spent, reported as seconds it did.
857
+ runStart = Date.now();
858
+ runUsage = { in: null, out: null, cache: null, known: false };
759
859
  const last = await consumeRun(session, recoveryRun, input, turnNo, faux, statusCb, submitTurn);
760
860
  currentRun = null;
761
861
  failOnFauxExhaustion(last, faux, input);
@@ -22,6 +22,9 @@ export interface DispatchCtx {
22
22
  readonly submitTurn: (line: string) => void;
23
23
  /** the /status context estimate. */
24
24
  readonly estimateCtx: () => number;
25
+ /** TUI2-R1 (E): the model's context window, as the session is
26
+ * configured — the /context ledger's denominator. */
27
+ readonly contextWindow: () => number;
25
28
  }
26
29
  /** The ONE dispatcher — slash commands, exit, and turns. The recovery
27
30
  * replay routes through it too — a queued "/last" must never become a
package/dist/dispatch.js CHANGED
@@ -3,10 +3,10 @@
3
3
  * turns. The bodies moved verbatim from chat()'s closure; chat provides
4
4
  * the context (the chain, the run state, the prompt arming).
5
5
  */
6
- import { escapeTerminal, helpRows, kUnit, palette } from "@vincemakes/kiso-tui";
6
+ import { contextRows, contextUnavailableRows, escapeTerminal, helpRows, kUnit, palette } from "@vincemakes/kiso-tui";
7
7
  import { buildAdapter } from "@vincemakes/kiso-runtime/internal";
8
8
  import { MODES, getMode, setMode } from "./mode.js";
9
- import { agentModel, body, bodyLog, configModels, dock, setAgentModel, setCurrentModelName } from "./state.js";
9
+ import { agentModel, body, bodyLog, configModels, dock, readContextLedger, setAgentModel, setCurrentModelName } from "./state.js";
10
10
  import { directWriteProfile, profileAvailable } from "./config.js";
11
11
  /** The ONE dispatcher — slash commands, exit, and turns. The recovery
12
12
  * replay routes through it too — a queued "/last" must never become a
@@ -23,8 +23,10 @@ export function dispatch(line, ctx) {
23
23
  // the last one still carries its own \n, so `exit` and `keys`
24
24
  // land as two rows from one call (bodyLog splits on \n).
25
25
  ctx.chainRef.current = ctx.chainRef.current.then(async () => {
26
+ // TUI2-R1.5 9 (VD-10): /help is sentences for a human — the keys
27
+ // row in particular is one long line that hard-folded mid-word.
26
28
  for (const row of helpRows())
27
- bodyLog(row);
29
+ bodyLog(row, "words");
28
30
  ctx.input.prompt();
29
31
  });
30
32
  return;
@@ -92,6 +94,30 @@ export function dispatch(line, ctx) {
92
94
  ctx.chainRef.current = ctx.chainRef.current.then(land);
93
95
  return;
94
96
  }
97
+ if (trimmed === "/context") {
98
+ // TUI2-R1 (E): the rent-ledger attribution — where the context went,
99
+ // read from the session's TRACE SIDECAR (the observation file E1/E3
100
+ // already write, per request).
101
+ //
102
+ // THE PURITY GATE IS UNTOUCHED and this is why: the trace surface is
103
+ // an OBSERVATION surface (ADR-0051 §6, ruling R7) and correctness
104
+ // never reads it. /context is a DISPLAY command — nothing it reads
105
+ // reaches a recovery plan, a projection, or a request. The read is
106
+ // best-effort by construction: a missing, partial or unparseable
107
+ // ledger renders the honest fallback, never an error and never a
108
+ // guess. recovery-purity.test.ts's probes are unaffected: the
109
+ // derivation still does zero I/O and still ignores trace-shaped data.
110
+ ctx.chainRef.current = ctx.chainRef.current.then(async () => {
111
+ const ledger = readContextLedger(ctx.session.id, ctx.contextWindow());
112
+ for (const row of ledger === null
113
+ ? contextUnavailableRows("the ledger is written per request — run a turn, then ask again")
114
+ : contextRows(ledger)) {
115
+ bodyLog(row);
116
+ }
117
+ ctx.input.prompt();
118
+ });
119
+ return;
120
+ }
95
121
  if (trimmed === "/status") {
96
122
  // B area: session id, durable event count, and the ~ context
97
123
  // estimate — all read straight from the live session, nothing
package/dist/index.js CHANGED
@@ -199,6 +199,7 @@ function makeLineInput() {
199
199
  editor.bindAtItems(atFiles); // KC3 §5: the file source — listed per OPEN
200
200
  dock.bindAt(() => editor.atState()); // KC3 §4: the picker's band
201
201
  dock.bindApproval(() => editor.panelState()); // W21: the panel's bound state
202
+ dock.bindSheet(() => editor.sheetOpen()); // TUI2-R1 (D): the ? keys sheet
202
203
  return editorInput(editor);
203
204
  }
204
205
  return readlineInput(createInterface({ input: process.stdin, output: process.stdout }));
package/dist/state.d.ts CHANGED
@@ -15,6 +15,22 @@ export declare function kisoHome(): string;
15
15
  export declare function sessionsDir(): string;
16
16
  /** E1: the extension scan directory — KISO_EXTENSIONS_DIR overrides. */
17
17
  export declare function extensionsDir(): string;
18
+ /**
19
+ * TUI2-R1 (E) — the /context ledger, read from the session's TRACE
20
+ * SIDECAR (<sessions>/traces/<id>.jsonl).
21
+ *
22
+ * THE PURITY GATE (ADR-0051 §6, ruling R7) IS UNTOUCHED. The trace
23
+ * surface is an observation surface; correctness never reads it, and
24
+ * this reader is on the DISPLAY path only — nothing it returns reaches a
25
+ * recovery plan, a projection or a request. The proof of that is the
26
+ * shape of this function: it is best-effort end to end, and its failure
27
+ * mode is `null`, which renders a sentence rather than a number.
28
+ *
29
+ * The LAST request line is the one that matters: rent is per request,
30
+ * and what the reader wants to know is what the NEXT request will cost,
31
+ * which is what the previous one cost.
32
+ */
33
+ export declare function readContextLedger(sessionId: string, window: number): import("@vincemakes/kiso-tui").ContextLedger | null;
18
34
  /**
19
35
  * KC3 §5 — the @ picker's file source. Computed PER OPEN: no index, no
20
36
  * daemon, no watcher, nothing to invalidate and nothing to go stale.
@@ -90,7 +106,7 @@ export declare let body: Body;
90
106
  export declare function setBody(value: Body): void;
91
107
  /** v2d: body output routes through the cell renderer — the single writer.
92
108
  * bodyLog adds the trailing newline; internal newlines are preserved. */
93
- export declare function bodyLog(text: string): void;
109
+ export declare function bodyLog(text: string, wrap?: "words"): void;
94
110
  /** The model name for the status bar — set by makeAgent. */
95
111
  export declare let agentModel: string;
96
112
  export declare function setAgentModel(value: string): void;
package/dist/state.js CHANGED
@@ -25,6 +25,71 @@ export function sessionsDir() {
25
25
  export function extensionsDir() {
26
26
  return process.env.KISO_EXTENSIONS_DIR ?? join(kisoHome(), "extensions");
27
27
  }
28
+ /**
29
+ * TUI2-R1 (E) — the /context ledger, read from the session's TRACE
30
+ * SIDECAR (<sessions>/traces/<id>.jsonl).
31
+ *
32
+ * THE PURITY GATE (ADR-0051 §6, ruling R7) IS UNTOUCHED. The trace
33
+ * surface is an observation surface; correctness never reads it, and
34
+ * this reader is on the DISPLAY path only — nothing it returns reaches a
35
+ * recovery plan, a projection or a request. The proof of that is the
36
+ * shape of this function: it is best-effort end to end, and its failure
37
+ * mode is `null`, which renders a sentence rather than a number.
38
+ *
39
+ * The LAST request line is the one that matters: rent is per request,
40
+ * and what the reader wants to know is what the NEXT request will cost,
41
+ * which is what the previous one cost.
42
+ */
43
+ export function readContextLedger(sessionId, window) {
44
+ let last = null;
45
+ try {
46
+ const text = readFileSync(join(sessionsDir(), "traces", `${sessionId}.jsonl`), "utf8");
47
+ for (const line of text.split("\n")) {
48
+ if (line === "")
49
+ continue;
50
+ try {
51
+ const parsed = JSON.parse(line);
52
+ if (parsed.kind === "request")
53
+ last = parsed;
54
+ }
55
+ catch {
56
+ // a torn last line (the writer was mid-append) — the ledger is
57
+ // an observation, and a partial one is simply not the answer
58
+ }
59
+ }
60
+ }
61
+ catch {
62
+ return null; // no sidecar — a session that has not called the model
63
+ }
64
+ if (last === null)
65
+ return null;
66
+ const rent = Array.isArray(last.rent) ? last.rent : [];
67
+ if (rent.length === 0)
68
+ return null; // a v1/v2 sidecar carries no rent block (R2-1)
69
+ const sum = (pred) => rent.filter((l) => typeof l.surface === "string" && pred(l.surface)).reduce((a, l) => a + (l.estTokens ?? 0), 0);
70
+ const count = (pred) => rent.filter((l) => typeof l.surface === "string" && pred(l.surface)).length;
71
+ // the skills index is broken out: it is an INDEX of workspace content,
72
+ // not an instruction, and it is the one append whose size is the
73
+ // reader's own doing.
74
+ const isSkills = (s) => s === "system:ext:skills";
75
+ const manifest = Array.isArray(last.contextManifest) ? last.contextManifest : [];
76
+ const turnSegments = manifest.filter((s) => s.role === "turn" || s.role === "current_turn");
77
+ return {
78
+ window,
79
+ systemPrompt: sum((s) => s === "system:base" || (s.startsWith("system:ext:") && !isSkills(s))),
80
+ systemBase: sum((s) => s === "system:base"),
81
+ appends: count((s) => s.startsWith("system:ext:") && !isSkills(s)),
82
+ toolTable: sum((s) => s.startsWith("tool:")),
83
+ tools: count((s) => s.startsWith("tool:")),
84
+ skillsIndex: sum(isSkills),
85
+ // the ledger records the SURFACE, never its contents — the number
86
+ // of skills is not in it, and 0 tells the renderer to say so.
87
+ skills: 0,
88
+ envelope: sum((s) => s === "envelope"),
89
+ messages: turnSegments.reduce((a, s) => a + (s.estTokens ?? 0), 0),
90
+ turns: turnSegments.length,
91
+ };
92
+ }
28
93
  /**
29
94
  * KC3 §5 — the @ picker's file source. Computed PER OPEN: no index, no
30
95
  * daemon, no watcher, nothing to invalidate and nothing to go stale.
@@ -95,8 +160,8 @@ export function setBody(value) {
95
160
  }
96
161
  /** v2d: body output routes through the cell renderer — the single writer.
97
162
  * bodyLog adds the trailing newline; internal newlines are preserved. */
98
- export function bodyLog(text) {
99
- body.raw(text.split("\n"));
163
+ export function bodyLog(text, wrap) {
164
+ body.raw(text.split("\n"), wrap);
100
165
  }
101
166
  /** The model name for the status bar — set by makeAgent. */
102
167
  export let agentModel = "faux";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-code",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "kiso CLI — the durable coding agent that survives kill -9: kiso chat / kiso resume / kiso sessions.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -18,19 +18,19 @@
18
18
  "test": "vitest run"
19
19
  },
20
20
  "dependencies": {
21
- "@vincemakes/kiso-ask-ext": "0.8.0",
22
- "@vincemakes/kiso-core": "0.8.0",
23
- "@vincemakes/kiso-evals": "0.8.0",
24
- "@vincemakes/kiso-mcp-ext": "0.8.0",
25
- "@vincemakes/kiso-provider-anthropic": "0.8.0",
26
- "@vincemakes/kiso-provider-openai": "0.8.0",
27
- "@vincemakes/kiso-runtime": "0.8.0",
28
- "@vincemakes/kiso-skills-ext": "0.8.0",
29
- "@vincemakes/kiso-subagent-ext": "0.8.0",
30
- "@vincemakes/kiso-task-ext": "0.8.0",
31
- "@vincemakes/kiso-tools-node": "0.8.0",
32
- "@vincemakes/kiso-tui": "0.8.0",
33
- "@vincemakes/kiso-tui-cells": "0.8.0"
21
+ "@vincemakes/kiso-ask-ext": "0.9.0",
22
+ "@vincemakes/kiso-core": "0.9.0",
23
+ "@vincemakes/kiso-evals": "0.9.0",
24
+ "@vincemakes/kiso-mcp-ext": "0.9.0",
25
+ "@vincemakes/kiso-provider-anthropic": "0.9.0",
26
+ "@vincemakes/kiso-provider-openai": "0.9.0",
27
+ "@vincemakes/kiso-runtime": "0.9.0",
28
+ "@vincemakes/kiso-skills-ext": "0.9.0",
29
+ "@vincemakes/kiso-subagent-ext": "0.9.0",
30
+ "@vincemakes/kiso-task-ext": "0.9.0",
31
+ "@vincemakes/kiso-tools-node": "0.9.0",
32
+ "@vincemakes/kiso-tui": "0.9.0",
33
+ "@vincemakes/kiso-tui-cells": "0.9.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^26.1.2",