@vincemakes/kiso-code 0.15.0 → 0.15.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/dist/chat.d.ts CHANGED
@@ -158,4 +158,20 @@ export declare function consumeRun(session: AgentSession, run: Run, input: LineI
158
158
  * (resume) where a dropped amend is noticed instead. */
159
159
  submitTurn?: (line: string) => void): Promise<import("@vincemakes/kiso-core").Event | undefined>;
160
160
  /** Interactive REPL: stream events, pause for approvals, Ctrl+C aborts. */
161
- export declare function chat(session: AgentSession, faux: boolean, input: LineInput, autoCompact?: AutoCompact): Promise<void>;
161
+ /** The chat loop's ENDING: exit closes the process's REPL for good; a
162
+ * switch hands main another session id to re-enter chat with — the
163
+ * editor survives, the durable law is untouched (the /resume+/clear
164
+ * mini-spec). */
165
+ export type ChatEnd = {
166
+ readonly next: "exit";
167
+ } | {
168
+ readonly next: "switch";
169
+ readonly id: string;
170
+ };
171
+ /** The session-navigation seam main provides: the OTHER sessions'
172
+ * ids, and (when a dock is up) the existing picker. */
173
+ export interface ChatNav {
174
+ readonly sessions: () => readonly string[];
175
+ readonly pick?: () => Promise<string | null>;
176
+ }
177
+ export declare function chat(session: AgentSession, faux: boolean, input: LineInput, autoCompact?: AutoCompact, nav?: ChatNav): Promise<ChatEnd>;
package/dist/chat.js CHANGED
@@ -793,8 +793,14 @@ submitTurn) {
793
793
  }
794
794
  return last;
795
795
  }
796
- /** Interactive REPL: stream events, pause for approvals, Ctrl+C aborts. */
797
- export async function chat(session, faux, input, autoCompact) {
796
+ export async function chat(session, faux, input, autoCompact, nav) {
797
+ // the switch directive set once by dispatch's /clear or /resume,
798
+ // resolved through the end signal so the final awaits still run
799
+ let switchTo = null;
800
+ let resolveEnd = () => { };
801
+ const endSignal = new Promise((r) => {
802
+ resolveEnd = r;
803
+ });
798
804
  let currentRun = null;
799
805
  let cancelled = false;
800
806
  // E group (the graceful-exit gate ③, R-G 0.1.48): the terminal can
@@ -1114,6 +1120,15 @@ export async function chat(session, faux, input, autoCompact) {
1114
1120
  submitTurn,
1115
1121
  estimateCtx: () => estimateCtxRatio(session),
1116
1122
  contextWindow: () => contextWindowTokens(),
1123
+ // the /resume+/clear mini-spec: the switch directive and the
1124
+ // session-navigation seam (absent nav = the commands degrade to
1125
+ // an honest refusal in dispatch)
1126
+ requestSwitch: (id) => {
1127
+ switchTo = id;
1128
+ resolveEnd();
1129
+ },
1130
+ sessions: () => nav?.sessions() ?? [],
1131
+ ...(nav?.pick !== undefined ? { pickSession: nav.pick } : {}),
1117
1132
  };
1118
1133
  // the ergonomics batch C8: the auto-compact check — the /compact FULL path via the
1119
1134
  // shared dispatch (same notices, same chain ordering, same mid-run
@@ -1143,6 +1158,15 @@ export async function chat(session, faux, input, autoCompact) {
1143
1158
  // chain action (the sentinel's control char marks the key, so a typed
1144
1159
  // "expand" turn is never intercepted).
1145
1160
  input.onExpand(() => dispatch("\x12expand", dispatchCtx));
1161
+ // R3a — Shift+Tab: the approval-tier cycle (the /mode ring, in the
1162
+ // MODES order). The switch is the SAME live-extension flip /mode
1163
+ // performs; the status row repaints at once with a one-line notice.
1164
+ input.onModeCycle?.(() => {
1165
+ const next = MODES[(MODES.indexOf(getMode()) + 1) % MODES.length];
1166
+ setMode(next);
1167
+ paintIdle();
1168
+ body.notice(`mode → ${next} (shift+tab cycles)`);
1169
+ });
1146
1170
  // Recovery first: a session with a dangling pause or uncertain
1147
1171
  // executions must resolve them BEFORE the REPL accepts new turns —
1148
1172
  // otherwise the interrupted run dangles while a new one starts.
@@ -1174,7 +1198,7 @@ export async function chat(session, faux, input, autoCompact) {
1174
1198
  if (cancelled) {
1175
1199
  input.close();
1176
1200
  await input.closed;
1177
- return;
1201
+ return { next: "exit" };
1178
1202
  }
1179
1203
  // The REPL is ready: replay anything that arrived during recovery.
1180
1204
  replReady = true;
@@ -1188,7 +1212,9 @@ export async function chat(session, faux, input, autoCompact) {
1188
1212
  }
1189
1213
  queuedLines.length = 0;
1190
1214
  input.prompt();
1191
- await input.closed;
1215
+ // the REPL ends by CLOSE (exit) or by SWITCH (/clear, /resume) — the
1216
+ // switch leaves the editor alive for the next chat() entry
1217
+ await Promise.race([input.closed, endSignal]);
1192
1218
  await chainRef.current; // never exit while a turn is in flight
1193
1219
  // the ergonomics batch C8: the auto-compact may have appended ITS segment inside the
1194
1220
  // turn (the check runs at the turn's end, after the exit-await above
@@ -1196,4 +1222,5 @@ export async function chat(session, faux, input, autoCompact) {
1196
1222
  // runs before the exit or the chain is already settled. One level is
1197
1223
  // enough: the /compact segment appends nothing of its own.
1198
1224
  await chainRef.current;
1225
+ return switchTo === null ? { next: "exit" } : { next: "switch", id: switchTo };
1199
1226
  }
@@ -25,6 +25,13 @@ export interface DispatchCtx {
25
25
  /** TUI2-R1 (E): the model's context window, as the session is
26
26
  * configured — the /context ledger's denominator. */
27
27
  readonly contextWindow: () => number;
28
+ /** the /resume+/clear mini-spec: end this chat() with a switch to
29
+ * another session — main re-enters chat there; the editor survives. */
30
+ readonly requestSwitch: (id: string) => void;
31
+ /** every durable session id (the /resume validation + listing). */
32
+ readonly sessions: () => readonly string[];
33
+ /** the dock's session picker, when one exists (bare /resume). */
34
+ readonly pickSession?: () => Promise<string | null>;
28
35
  }
29
36
  /** The ONE dispatcher — slash commands, exit, and turns. The recovery
30
37
  * replay routes through it too — a queued "/last" must never become a
package/dist/dispatch.js CHANGED
@@ -263,7 +263,7 @@ export function dispatch(line, ctx) {
263
263
  });
264
264
  return;
265
265
  }
266
- if (trimmed === "/compact") {
266
+ if (trimmed === "/compact" || trimmed.startsWith("/compact ")) {
267
267
  // /compact (ADR-0044): the older conversation becomes one
268
268
  // model summary — an OFF-LOOP call through the session's own
269
269
  // adapter, so it must never race a running turn: refused
@@ -306,8 +306,13 @@ export function dispatch(line, ctx) {
306
306
  }, 1000);
307
307
  };
308
308
  try {
309
+ // R3a: /compact <focus> — the words after the command steer
310
+ // the summary ("keep the auth details"); bare /compact is
311
+ // byte-identical to the pre-round call.
312
+ const focus = trimmed.slice(8).trim();
309
313
  const result = await ctx.session.summarize({
310
314
  signal: abort.signal,
315
+ ...(focus !== "" ? { focus } : {}),
311
316
  onStart: (info) => {
312
317
  compactInfo = info;
313
318
  compacting(info);
@@ -369,6 +374,68 @@ export function dispatch(line, ctx) {
369
374
  ctx.input.close();
370
375
  return;
371
376
  }
377
+ if (trimmed === "/clear") {
378
+ // the mini-spec: /clear = a FRESH conversation. The old session
379
+ // stays on disk, resumable — the append-only law does not move;
380
+ // what clears is the CONTEXT, never the history.
381
+ if (ctx.isRunning()) {
382
+ body.notice("[/clear] a run is in flight — let it finish (esc stops it), then clear");
383
+ ctx.input.prompt();
384
+ return;
385
+ }
386
+ ctx.requestSwitch(new Date().toISOString().replace(/[:.]/g, "-").slice(0, 16));
387
+ return;
388
+ }
389
+ if (trimmed === "/resume" || trimmed.startsWith("/resume ")) {
390
+ // the mini-spec: the in-session door to the durable sessions —
391
+ // /resume <id> switches directly; bare /resume opens the SAME
392
+ // picker `kiso resume` owns (dock), or lists ids (no dock).
393
+ if (ctx.isRunning()) {
394
+ body.notice("[/resume] a run is in flight — let it finish (esc stops it), then switch");
395
+ ctx.input.prompt();
396
+ return;
397
+ }
398
+ const arg = trimmed.slice(7).trim();
399
+ if (arg !== "") {
400
+ // a switch never silently CREATES a session — agent.session()
401
+ // would; the validation is the difference
402
+ if (!ctx.sessions().includes(arg)) {
403
+ ctx.chainRef.current = ctx.chainRef.current.then(async () => {
404
+ bodyLog(`no such session: ${escapeTerminal(arg)} — /resume lists them`);
405
+ ctx.input.prompt();
406
+ });
407
+ return;
408
+ }
409
+ ctx.requestSwitch(arg);
410
+ return;
411
+ }
412
+ const others = ctx.sessions().filter((id) => id !== ctx.session.id);
413
+ if (others.length === 0) {
414
+ ctx.chainRef.current = ctx.chainRef.current.then(async () => {
415
+ bodyLog("no other sessions — /clear starts a fresh one");
416
+ ctx.input.prompt();
417
+ });
418
+ return;
419
+ }
420
+ if (ctx.pickSession !== undefined && dock.active) {
421
+ ctx.chainRef.current = ctx.chainRef.current.then(async () => {
422
+ const picked = await ctx.pickSession();
423
+ if (picked === null) {
424
+ ctx.input.prompt(); // esc — nothing switched, nothing said
425
+ return;
426
+ }
427
+ ctx.requestSwitch(picked);
428
+ });
429
+ return;
430
+ }
431
+ ctx.chainRef.current = ctx.chainRef.current.then(async () => {
432
+ for (const id of others)
433
+ bodyLog(` ${escapeTerminal(id)}`);
434
+ bodyLog("switch with /resume <id>");
435
+ ctx.input.prompt();
436
+ });
437
+ return;
438
+ }
372
439
  // PH-1a (finding PH-F1): an unrecognized slash command is an ERROR,
373
440
  // never a turn — the fallthrough used to hand "/clear", "/exit", or a
374
441
  // typo to the model, burning a request on text the user meant as a
package/dist/index.js CHANGED
@@ -23,7 +23,7 @@
23
23
  * index.ts keeps the entry: banner, input sources, the A area prompt,
24
24
  * makeAgent, and main.
25
25
  */
26
- import { readFileSync, realpathSync, rmSync } from "node:fs";
26
+ import { appendFileSync, mkdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
27
27
  import { createInterface } from "node:readline";
28
28
  import { fileURLToPath } from "node:url";
29
29
  import { join } from "node:path";
@@ -33,7 +33,7 @@ import { createFauxProvider } from "@vincemakes/kiso-evals";
33
33
  import { createCodingTools } from "@vincemakes/kiso-tools-node";
34
34
  import { MODES, getMode, modeExtensions, modeFromEnv, modeSystemPrompt, setMode } from "./mode.js";
35
35
  import { builtInLayer } from "./builtin.js";
36
- import { agentModel, atFiles, body, bodyLog, builtInExtensions, currentFaux, dock, extensionsDir, loadedExtensions, mergedConfig, mergedTempPaths, projectExtensions, sessionStoreRef, sessionsDir, setAgentModel, setBody, setConfigModels, setConfiguredWindow, setCurrentAgentExtensions, setCurrentFaux, setCurrentModelName, setExtensionLists, setMergedConfig, setSessionStore, userExtensions, VERSION } from "./state.js";
36
+ import { agentModel, atFiles, body, bodyLog, kisoHome, builtInExtensions, currentFaux, dock, extensionsDir, loadedExtensions, mergedConfig, mergedTempPaths, projectExtensions, sessionStoreRef, sessionsDir, setAgentModel, setBody, setConfigModels, setConfiguredWindow, setCurrentAgentExtensions, setCurrentFaux, setCurrentModelName, setExtensionLists, setMergedConfig, setSessionStore, userExtensions, VERSION } from "./state.js";
37
37
  import { askUi, resolveProjectTrust } from "./trust-ui.js";
38
38
  import { isFirstRun, scaffoldFirstRun } from "./first-run.js";
39
39
  import { fauxSkip, readFauxScript } from "./faux-glue.js";
@@ -188,6 +188,13 @@ function editorInput(editor) {
188
188
  bindQueue(state, pop) {
189
189
  editor.bindQueue(state, pop);
190
190
  },
191
+ // R3a: cross-session history — the CLI owns the file I/O.
192
+ bindHistory(seed, persist) {
193
+ editor.bindHistory(seed, persist);
194
+ },
195
+ onModeCycle(cb) {
196
+ editor.onModeCycle(cb);
197
+ },
191
198
  emitLine() {
192
199
  /* the editor's buffer survives a cancelled question — its text
193
200
  * becomes the next turn on Enter (the readline re-emit
@@ -570,6 +577,38 @@ function paintBootStatus(session) {
570
577
  class CliUsageError extends Error {
571
578
  exitCode = 2;
572
579
  }
580
+ /** The /resume+/clear mini-spec — the chat LOOP: chat() ends with a
581
+ * directive; a switch re-enters it on another session with the SAME
582
+ * editor. First entry paints the banner; a switch paints one notice
583
+ * line (the previous conversation stays resumable — clear/switch
584
+ * never erase history). Faux sessions re-arm the scripted adapter at
585
+ * the NEW session's durable position, exactly like the picker path. */
586
+ async function chatLoop(agent, firstId, input, autoCompact) {
587
+ let id = firstId;
588
+ let prev = null;
589
+ for (;;) {
590
+ const session = await agent.session({ id });
591
+ if (prev === null) {
592
+ bodyLog(`session ${id}\n`);
593
+ extensionsBanner(await recentSessions(id, agent));
594
+ }
595
+ else {
596
+ bodyLog(`session ${id} (switched — previous: ${prev}, /resume ${prev} returns)\n`);
597
+ if (currentFaux)
598
+ session.setAdapter(createFauxProvider(readFauxScript().slice(fauxSkip(id))));
599
+ }
600
+ paintBootStatus(session);
601
+ const nav = {
602
+ sessions: () => agent.sessions().map((m) => m.id),
603
+ ...(process.stdin.isTTY ? { pick: () => pickSession(agent, input) } : {}),
604
+ };
605
+ const end = await chat(session, currentFaux, input, autoCompact, nav);
606
+ if (end.next === "exit")
607
+ return;
608
+ prev = id;
609
+ id = end.id;
610
+ }
611
+ }
573
612
  async function main() {
574
613
  // E group (the graceful-exit gate ③, R-G 0.1.48): a terminal closing
575
614
  // turns the in-flight stdout/stderr writes into EIO, and node's
@@ -598,6 +637,22 @@ async function main() {
598
637
  console.log(VERSION);
599
638
  return;
600
639
  }
640
+ // R3a: -p/--print — the one-shot prompt mode (the F3 adjudication's
641
+ // forward path: a bare quoted argument stays a session id; the
642
+ // PROMPT is explicit). `kiso -p "fix the bug"` runs one turn on a
643
+ // fresh session and exits; an optional trailing session id continues
644
+ // that session one-shot instead. Exit code: 0 only when the turn's
645
+ // terminal is `completed` — scripts can trust it.
646
+ let printPrompt;
647
+ const printIdx = args.findIndex((a) => a === "-p" || a === "--print");
648
+ if (printIdx !== -1) {
649
+ printPrompt = args[printIdx + 1];
650
+ if (printPrompt === undefined) {
651
+ console.error('usage: kiso -p "prompt" [sessionId]');
652
+ process.exit(2);
653
+ }
654
+ args.splice(printIdx, 2);
655
+ }
601
656
  // merge round B: --model <profile|provider/model> — the top of the model
602
657
  // precedence chain; the value flows into makeAgent's config resolution.
603
658
  let modelFlag;
@@ -638,6 +693,33 @@ async function main() {
638
693
  // readline elsewhere. The trust question, chat, and resume all read
639
694
  // through it; main's finally closes it on every exit path.
640
695
  const input = makeLineInput();
696
+ // R3a — cross-session input history: ~/.kiso/history, one line per
697
+ // entry, appended on submit, tail-500 at load (truncated by REWRITE
698
+ // at startup so the file never grows unbounded). Unreadable file =
699
+ // an empty history, silently — recall is a convenience, never a
700
+ // startup risk. Control-character lines never enter the file (the
701
+ // editor's own recall excludes them by construction: a submitted
702
+ // line is printable input).
703
+ if (input.bindHistory !== undefined) {
704
+ const historyPath = join(kisoHome(), "history");
705
+ let seed = [];
706
+ try {
707
+ seed = readFileSync(historyPath, "utf8").split("\n").filter((l) => l !== "").slice(-500);
708
+ writeFileSync(historyPath, seed.length > 0 ? seed.join("\n") + "\n" : "");
709
+ }
710
+ catch {
711
+ // no file yet, or unreadable — start empty
712
+ }
713
+ input.bindHistory(seed, (line) => {
714
+ try {
715
+ mkdirSync(kisoHome(), { recursive: true });
716
+ appendFileSync(historyPath, line.replaceAll("\n", " ") + "\n");
717
+ }
718
+ catch {
719
+ // best-effort — a full disk never breaks a submit
720
+ }
721
+ });
722
+ }
641
723
  // PH-1a (finding PH-F6, RESOLVED AS WON'T-FIX-IN-JS — the tcsetattr
642
724
  // ruling): SIGTERM/SIGHUP deliberately keep their DEFAULT disposition.
643
725
  // A JS handler that restored the terminal was built and then reverted
@@ -670,6 +752,19 @@ async function main() {
670
752
  if (modeFlag === -1 && process.env.KISO_MODE === undefined && mergedConfig.mode !== undefined)
671
753
  setMode(mergedConfig.mode);
672
754
  };
755
+ if (printPrompt !== undefined) {
756
+ // the -p flow: recovery-first one-shot, the resume() machinery
757
+ // verbatim (a fresh id makes the recovery a no-op)
758
+ const id = command ?? new Date().toISOString().replace(/[:.]/g, "-").slice(0, 16);
759
+ agent = await makeAgent(id, input, modelFlag);
760
+ applyConfigMode();
761
+ const session = await agent.session({ id });
762
+ faux = currentFaux;
763
+ await resume(session, printPrompt, faux, input);
764
+ const last = [...session.log.all].reverse().find((e) => e.type === "terminal");
765
+ process.exitCode = last !== undefined && last.outcome.kind === "completed" ? 0 : 1;
766
+ return;
767
+ }
673
768
  switch (command) {
674
769
  case "chat": {
675
770
  const id = arg ?? new Date().toISOString().replace(/[:.]/g, "-").slice(0, 16);
@@ -680,12 +775,8 @@ async function main() {
680
775
  // position — never restarts it (fauxSkip).
681
776
  agent = await makeAgent(id, input, modelFlag);
682
777
  applyConfigMode();
683
- const session = await agent.session({ id });
684
- bodyLog(`session ${id}\n`);
685
- extensionsBanner(await recentSessions(id, agent));
686
778
  faux = currentFaux;
687
- paintBootStatus(session); // TUI2-R2 ⑥: the idle-fresh screen says what it is
688
- await chat(session, faux, input, resolveAutoCompact(mergedConfig));
779
+ await chatLoop(agent, id, input, resolveAutoCompact(mergedConfig));
689
780
  break;
690
781
  }
691
782
  case "resume": {
@@ -712,7 +803,14 @@ async function main() {
712
803
  // an error, never a session started behind their back.
713
804
  if (picked === null)
714
805
  break;
715
- id = picked;
806
+ // the mini-spec (a DECLARED SUPERSESSION of the one-shot
807
+ // picker flow): a PICKED session enters the full REPL —
808
+ // "resume and keep working" no longer requires knowing to
809
+ // type `kiso chat <id>`. The explicit-id one-shot form
810
+ // (`kiso resume <id> ["prompt"]`) keeps its exact bytes.
811
+ faux = currentFaux;
812
+ await chatLoop(agent, picked, input, resolveAutoCompact(mergedConfig));
813
+ break;
716
814
  }
717
815
  const session = await agent.session({ id });
718
816
  faux = currentFaux;
@@ -795,17 +893,9 @@ async function main() {
795
893
  // undefined" at the ask (panelAsk with the dock, question on
796
894
  // the dock-less fallback).
797
895
  agent = await makeAgent(id, input, modelFlag);
798
- const session = await agent.session({ id });
799
- bodyLog(`session ${id}\n`);
800
- extensionsBanner(await recentSessions(id, agent));
801
- // finding E4-1: the same faux resolution the chat/resume cases
802
- // carry (faux = currentFaux) — pre-patch the initial faux=true
803
- // was passed here, so ANY provider failure in a bare-command
804
- // session surfaced as "[faux mode] the scripted model failed:
805
- // <real error>" (a false accusation of the keyless demo).
896
+ // finding E4-1's faux resolution rides chatLoop (currentFaux).
806
897
  faux = currentFaux;
807
- paintBootStatus(session); // TUI2-R2 ⑥: the same row on the bare command
808
- await chat(session, faux, input, autoCompactFromEnv());
898
+ await chatLoop(agent, id, input, autoCompactFromEnv());
809
899
  break;
810
900
  }
811
901
  }
@@ -869,7 +959,7 @@ function exitFlushed(code) {
869
959
  }
870
960
  if (process.argv[1] !== undefined && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {
871
961
  main()
872
- .then(() => exitFlushed(0))
962
+ .then(() => exitFlushed(typeof process.exitCode === "number" ? process.exitCode : 0))
873
963
  .catch((err) => {
874
964
  // round 10: top-level errors are terminal-escaped. v2a: the exit is EXPLICIT
875
965
  // — natural drain is racy on a TTY (readline leaves the stdio handles
package/dist/state.d.ts CHANGED
@@ -100,6 +100,11 @@ export interface LineInput {
100
100
  * live slots (each pop cancels the turn), esc ends the walk after
101
101
  * one more pop. The chips are the compositor's own bindQueue. */
102
102
  bindQueue(state: () => readonly string[], pop: () => string | null): void;
103
+ /** R3a: cross-session history — seed the recall buffer, register the
104
+ * append sink. The pipe path has no recall keys; optional. */
105
+ bindHistory?(seed: readonly string[], persist: (line: string) => void): void;
106
+ /** R3a: Shift+Tab cycles the approval tier (TTY editor only). */
107
+ onModeCycle?(cb: () => void): void;
103
108
  emitLine(line: string): void;
104
109
  line(): string;
105
110
  clearLine(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-code",
3
- "version": "0.15.0",
3
+ "version": "0.15.1",
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.15.0",
22
- "@vincemakes/kiso-core": "0.15.0",
23
- "@vincemakes/kiso-evals": "0.15.0",
24
- "@vincemakes/kiso-mcp-ext": "0.15.0",
25
- "@vincemakes/kiso-provider-anthropic": "0.15.0",
26
- "@vincemakes/kiso-provider-openai": "0.15.0",
27
- "@vincemakes/kiso-runtime": "0.15.0",
28
- "@vincemakes/kiso-skills-ext": "0.15.0",
29
- "@vincemakes/kiso-subagent-ext": "0.15.0",
30
- "@vincemakes/kiso-task-ext": "0.15.0",
31
- "@vincemakes/kiso-tools-node": "0.15.0",
32
- "@vincemakes/kiso-tui": "0.15.0",
33
- "@vincemakes/kiso-tui-cells": "0.15.0"
21
+ "@vincemakes/kiso-ask-ext": "0.15.1",
22
+ "@vincemakes/kiso-core": "0.15.1",
23
+ "@vincemakes/kiso-evals": "0.15.1",
24
+ "@vincemakes/kiso-mcp-ext": "0.15.1",
25
+ "@vincemakes/kiso-provider-anthropic": "0.15.1",
26
+ "@vincemakes/kiso-provider-openai": "0.15.1",
27
+ "@vincemakes/kiso-runtime": "0.15.1",
28
+ "@vincemakes/kiso-skills-ext": "0.15.1",
29
+ "@vincemakes/kiso-subagent-ext": "0.15.1",
30
+ "@vincemakes/kiso-task-ext": "0.15.1",
31
+ "@vincemakes/kiso-tools-node": "0.15.1",
32
+ "@vincemakes/kiso-tui": "0.15.1",
33
+ "@vincemakes/kiso-tui-cells": "0.15.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^26.1.2",