@vincemakes/kiso-code 0.39.0 → 0.39.2

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.js CHANGED
@@ -12,6 +12,7 @@ import { echoText } from "@vincemakes/kiso-tui-cells/render";
12
12
  import { canonicalizeUsage } from "@vincemakes/kiso-runtime";
13
13
  import { canonicalizeUsageForModel, requestBudget } from "@vincemakes/kiso-runtime/internal";
14
14
  import { dispatch, abortBangCommand } from "./dispatch.js";
15
+ import { paintWindowTitle } from "./window-title.js";
15
16
  import { agentBaseUrl, agentModel, body, bodyLog, configuredWindow, dock } from "./state.js";
16
17
  import { attachImages } from "./attachments.js";
17
18
  import { lookupModelMetadata } from "@vincemakes/kiso-runtime/internal";
@@ -781,6 +782,13 @@ submitTurn) {
781
782
  // construction (ADR-0040).
782
783
  switch (ev.type) {
783
784
  case "user_input":
785
+ // The window title is re-derived here because THIS is when a
786
+ // session stops being nameless: the tab opened as `kiso —
787
+ // <workspace>` and the first substantive prompt is what gives
788
+ // it a name. Re-derived rather than set, so the opener rule is
789
+ // `sessionTitle`'s and a greeting-first session upgrades when
790
+ // the real prompt lands instead of keeping "hi" forever.
791
+ paintWindowTitle(session.log.all);
784
792
  // TV-1B: a system-sourced input is PRODUCT MACHINERY — visible
785
793
  // (every durable input renders) but never painted as the
786
794
  // user's words. Provenance is honest on screen, not only in
package/dist/config.js CHANGED
@@ -102,6 +102,19 @@ export function parseConfig(text, source) {
102
102
  fail(`models.${name}.promptCaching`, "expected a boolean");
103
103
  if (p.streamIdleMs !== undefined && (typeof p.streamIdleMs !== "number" || !Number.isFinite(p.streamIdleMs) || p.streamIdleMs < 0))
104
104
  fail(`models.${name}.streamIdleMs`, "expected a non-negative number of milliseconds (0 disables the stream watchdog)");
105
+ // 0.39.2: `contextWindow` was DECLARED on this type, VALIDATED at
106
+ // the top level, and CONSUMED by resolveContextWindow — which
107
+ // prefers it over the global figure, with a comment saying why —
108
+ // and it was never copied here. So it never reached anything: 70
109
+ // of 70 profiles that declared one lost it in this object
110
+ // literal. The cost was not the `ctx ?` on the status row but the
111
+ // compaction threshold, which fell through to the 200k default
112
+ // for every model the registry does not carry — a 1M-window model
113
+ // compacting as though it had a fifth of its window. The
114
+ // documented workaround for exactly that ("set contextWindow in
115
+ // your profile") had never done anything.
116
+ if (p.contextWindow !== undefined && (typeof p.contextWindow !== "number" || !Number.isFinite(p.contextWindow) || p.contextWindow <= 0))
117
+ fail(`models.${name}.contextWindow`, "expected a positive token count");
105
118
  models[name] = {
106
119
  kind: p.kind,
107
120
  model: p.model,
@@ -109,6 +122,7 @@ export function parseConfig(text, source) {
109
122
  ...(typeof p.baseUrl === "string" ? { baseUrl: p.baseUrl } : {}),
110
123
  ...(typeof p.promptCaching === "boolean" ? { promptCaching: p.promptCaching } : {}),
111
124
  ...(typeof p.streamIdleMs === "number" ? { streamIdleMs: p.streamIdleMs } : {}),
125
+ ...(typeof p.contextWindow === "number" ? { contextWindow: p.contextWindow } : {}),
112
126
  };
113
127
  }
114
128
  out.models = models;
package/dist/dispatch.js CHANGED
@@ -3,7 +3,7 @@
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 { contextRows, contextUnavailableRows, displayVerb, escapeTerminal, helpRows, kUnit, modePickView, modelPickView, palette } from "@vincemakes/kiso-tui";
6
+ import { contextRows, contextUnavailableRows, displayVerb, escapeTerminal, helpRows, kUnit, modePickView, modelPickView, palette, renderEvent, settledLabel, slashCommandNames } from "@vincemakes/kiso-tui";
7
7
  import { newSessionId } from "./session-id.js";
8
8
  import { buildAdapter, lookupModelMetadata, resolveContinuationScope, resolveReasoning } from "@vincemakes/kiso-runtime/internal";
9
9
  import { MODES, MODE_NOTE, getMode, setMode } from "./mode.js";
@@ -19,6 +19,17 @@ import { join } from "node:path";
19
19
  * — kiso never silently drops a level, and now it shows the ones it takes.
20
20
  * A model the registry does not know shows `unknown` (nothing is guessed);
21
21
  * it must not read `none`, which is a REAL level since the Responses rows. */
22
+ /** A context figure for a NOTICE, in the status row's own form.
23
+ *
24
+ * `displayCtxRatio` returns NaN as its honest "nobody states this model's
25
+ * window", and the status row renders that as `ctx ?`. The `/compact`
26
+ * recap multiplied it and interpolated the result, so the same unknown
27
+ * reached the screen as `ctx NaN% → NaN%`: one value with a contract, and
28
+ * a second consumer that had not read it. The `%` moves inside, because
29
+ * the unknown form does not carry one. */
30
+ function ctxPercent(ratio) {
31
+ return Number.isFinite(ratio) ? `${Math.round(ratio * 100)}%` : "?";
32
+ }
22
33
  function effortNote(p) {
23
34
  const reasoning = lookupModelMetadata(p.model, p.baseUrl)?.capabilities.reasoning ?? null;
24
35
  const effort = reasoning?.effort ?? null;
@@ -732,7 +743,7 @@ export function dispatch(line, ctx) {
732
743
  const compacting = (info) => {
733
744
  const text = (elapsed) => `▘ compacting · ${info.rounds} rounds · ~${kUnit(info.tokens)} tokens · ${Math.max(0, elapsed)}s`;
734
745
  compactStart = Date.now();
735
- ctxBefore = Math.round(ctx.estimateCtx() * 100);
746
+ ctxBefore = ctxPercent(ctx.estimateCtx());
736
747
  dock.setStatus(text(0), "esc to cancel");
737
748
  compactTimer = setInterval(() => {
738
749
  dock.setStatus(text(Math.round((Date.now() - compactStart) / 1000)), "esc to cancel");
@@ -745,6 +756,12 @@ export function dispatch(line, ctx) {
745
756
  const focus = trimmed.slice(8).trim();
746
757
  const result = await ctx.session.summarize({
747
758
  signal: abort.signal,
759
+ // 0.39.2: the gesture gets the measured output budget and
760
+ // thinking off where the registry can vouch for turning it
761
+ // off. A fixed 4,000 was failing live sessions with "the
762
+ // summary turn ended with max_tokens"; a complete checkpoint
763
+ // of the reported size measured 18,837.
764
+ manualBudget: true,
748
765
  ...(focus !== "" ? { focus } : {}),
749
766
  onStart: (info) => {
750
767
  compactInfo = info;
@@ -760,11 +777,29 @@ export function dispatch(line, ctx) {
760
777
  // rounds, the one summary, the savings, the ctx drop
761
778
  // (the estimate BEFORE vs AFTER — the same chars/4
762
779
  // proxy the status bar shows, marked ~), and the time.
763
- const ctxAfter = Math.round(ctx.estimateCtx() * 100);
764
- const elapsed = compactStart > 0 ? ((Date.now() - compactStart) / 1000).toFixed(1) : "?";
780
+ const ctxAfter = ctxPercent(ctx.estimateCtx());
781
+ const elapsed = compactStart > 0 ? settledLabel((Date.now() - compactStart) / 1000) : "?s";
765
782
  // a non-null result implies onStart ran — the "?" is
766
783
  // reachable only at the type level
767
- body.notice(`[/compact] ✦ compacted · ${compactInfo?.rounds ?? "?"} rounds → 1 summary · saved ~${kUnit(result.savedTokens)} · ctx ${ctxBefore ?? "?"}% → ${ctxAfter}% · ${elapsed}s`);
784
+ body.notice(`[/compact] ✦ compacted · ${compactInfo?.rounds ?? "?"} rounds → 1 summary · saved ~${kUnit(result.savedTokens)} · ctx ${ctxBefore ?? "?"} → ${ctxAfter} · ${elapsed}`);
785
+ // 0.39.1 — the boundary row, under the recap.
786
+ //
787
+ // `summarized` is appended OFF-LOOP: session.summarize()
788
+ // writes it to the log and persists it, and no hook
789
+ // carries it to a renderer. So the row that marks where
790
+ // the transcript was cut had exactly one producer — a
791
+ // `case "summarized"` in lines.ts whose own comment says
792
+ // it is there "for the switch's completeness only" — and
793
+ // zero callers. The durable log said a compaction
794
+ // happened at seq N; no screen ever did.
795
+ //
796
+ // Rendered THROUGH that case rather than written again
797
+ // here: the line a resumed or replayed view would draw is
798
+ // the line drawn now, by construction, and the row cannot
799
+ // drift into two spellings of one fact.
800
+ const boundary = renderEvent({ type: "summarized", coversToSeq: result.coversToSeq });
801
+ if (boundary.text !== "")
802
+ body.raw(boundary.text.replace(/\n$/, "").split("\n"));
768
803
  }
769
804
  }
770
805
  catch (err) {
@@ -774,7 +809,22 @@ export function dispatch(line, ctx) {
774
809
  body.notice("[/compact] cancelled — nothing was persisted");
775
810
  }
776
811
  else {
777
- body.notice(`[/compact] failed: ${err instanceof Error ? err.message : String(err)}`);
812
+ // 0.39.1 — two repairs on one line. A failure the ADAPTER
813
+ // classified is a plain object, not an Error: `String(err)`
814
+ // rendered it `[object Object]`, which became reachable the
815
+ // moment the adapters started THROWING the
816
+ // transport-failure class instead of stopping with it. And
817
+ // a transport failure is worth saying so about: summarize
818
+ // already retried it once (it has no kernel behind it to do
819
+ // that), so a second failure means the gateway is still
820
+ // dropping the stream — the run is fine and the gesture is
821
+ // worth repeating. A permanent failure is not, and must not
822
+ // be dressed up as one that is.
823
+ const e = err;
824
+ const classified = typeof e.code === "string" && typeof e.message === "string";
825
+ const detail = classified ? String(e.message) : err instanceof Error ? err.message : String(err);
826
+ const again = classified && e.retryable === true ? " — the connection dropped again; /compact is worth another try" : "";
827
+ body.notice(`[/compact] failed: ${escapeTerminal(detail)}${again}`);
778
828
  }
779
829
  }
780
830
  finally {
@@ -902,7 +952,21 @@ export function dispatch(line, ctx) {
902
952
  // still submits.
903
953
  if (trimmed.startsWith("/") && !trimmed.includes("\n")) {
904
954
  ctx.chainRef.current = ctx.chainRef.current.then(async () => {
905
- bodyLog(`unknown command: ${escapeTerminal(trimmed.split(" ")[0] ?? trimmed)} — /help lists the commands`);
955
+ // The word, not the line: a command that EXISTS but was handed an
956
+ // argument it does not take reaches here too, and calling it
957
+ // unknown is a lie the user cannot get past — `/help` lists it,
958
+ // they typed what `/help` said, and kiso answers that there is no
959
+ // such command. (Reported on `/reload extensions`, 0.39.1.) The
960
+ // commands that DO take an argument matched on their own prefix
961
+ // far above, so a known word arriving here means exactly one
962
+ // thing: it takes none. `slashCommandNames` is the help sheet's
963
+ // own table, so this line cannot drift from the list the user was
964
+ // reading when they typed it.
965
+ const word = trimmed.split(/\s+/)[0] ?? trimmed;
966
+ const known = slashCommandNames().includes(word);
967
+ bodyLog(known
968
+ ? `${escapeTerminal(word)} takes no arguments — /help says what it does`
969
+ : `unknown command: ${escapeTerminal(word)} — /help lists the commands`);
906
970
  ctx.input.prompt();
907
971
  });
908
972
  return;
package/dist/index.js CHANGED
@@ -47,6 +47,7 @@ import { loadProjectConfig, loadUserConfig, mergeConfigs, resolveAutoCompact, re
47
47
  import { checkForUpdate, knownUpdate, updateCardLines } from "./update-check.js";
48
48
  import { tmuxMouseHint } from "./tmux-hint.js";
49
49
  import { resume } from "./resume.js";
50
+ import { paintWindowTitle } from "./window-title.js";
50
51
  import { resumeTail } from "./resume-tail.js";
51
52
  import { armByteTrace } from "./byte-trace.js";
52
53
  import { tmpdir, homedir } from "node:os";
@@ -1125,6 +1126,11 @@ async function chatLoop(first, firstId, input, autoCompact) {
1125
1126
  bindRestoredSession(session);
1126
1127
  setCurrentModelName(session.model);
1127
1128
  paintBootStatus(session);
1129
+ // The terminal's window title, HERE for the same reason the three
1130
+ // lines above are here: this is the one step all three entry points
1131
+ // share (first start, `/resume <id>`, a switch), so a tab can never
1132
+ // be left naming the session the user just left.
1133
+ paintWindowTitle(session.log.all);
1128
1134
  const nav = {
1129
1135
  sessions: () => agent.sessions().map((m) => m.id),
1130
1136
  ...(process.stdin.isTTY ? { pick: () => pickSession(agent, input) } : {}),
@@ -0,0 +1,76 @@
1
+ /**
2
+ * The terminal's window title (0.39.1, the owner's call).
3
+ *
4
+ * kiso set none, so a tab read whatever the shell left there — the
5
+ * directory the shell happened to be in and the absolute path of a node
6
+ * binary, identically for every kiso in every tab. The title is the one
7
+ * place a terminal shows which session a tab holds without the user
8
+ * switching to it, and it was the only screen kiso never wrote to.
9
+ *
10
+ * `kiso — <workspace>` at the start, `kiso — <session title> —
11
+ * <workspace>` once the session has one. The session's title is
12
+ * `sessionTitle`'s — the SAME projection the resume picker and `kiso
13
+ * sessions` print, so a tab and the picker can never disagree about what
14
+ * a session is called. That is also why an opener does not become the
15
+ * title: the rule for "substantive" lives in one place and this is a
16
+ * consumer of it, not a second opinion.
17
+ *
18
+ * WHAT IT WRITES. OSC 0, BEL-terminated — icon name and window title in
19
+ * one sequence, the form every terminal that supports either accepts. It
20
+ * goes STRAIGHT to stdout, deliberately outside the compositor: a title
21
+ * occupies no cell and no column, so it is not in the width accounting
22
+ * and must not be a cell that the repaint could move, cut, or scroll.
23
+ *
24
+ * WHAT IT NEVER WRITES. Anything at all when stdout is not a TTY. An OSC
25
+ * into a pipe is bytes in someone's output, and the pipe-identity gates
26
+ * exist because that has been a real defect before.
27
+ *
28
+ * NO RESTORE ON EXIT. Putting back what was there first requires reading
29
+ * it, which no terminal reliably answers; the shell repaints its own
30
+ * title on the next prompt anyway. A guess written on the way out would
31
+ * be a title kiso invented, which is worse than one it left.
32
+ *
33
+ * AND NO `process.title`. The reference implementation sets one; kiso
34
+ * does not, because two gates in this repo said no and the benefit was
35
+ * that `ps` would print `kiso` instead of a node path.
36
+ *
37
+ * - It overwrites the process's ARGV memory, so a renamed process shows
38
+ * as `kiso` with its arguments simply gone. The subagent's
39
+ * concurrency probe counts live children by matching `chat
40
+ * sub-parent-` in the command column; six renamed children were
41
+ * indistinguishable from each other and from nothing.
42
+ * - Setting it is not free on this platform: 14 ms measured for the
43
+ * first assignment on the machine this was written on, 7 ms for the
44
+ * second. A synchronous stall of that size on the main thread while a
45
+ * 3,000-line paste is arriving wedges the PTY in both directions —
46
+ * the UD-1 byte-exact paste gate deadlocked reproducibly and passed
47
+ * the moment the assignment was removed.
48
+ *
49
+ * The window title is what was asked for; the process name was a detail
50
+ * that came with it, and it costs more than it is worth.
51
+ */
52
+ import type { Event } from "@vincemakes/kiso-core";
53
+ /** OSC 0 — "set icon name and window title". */
54
+ export declare const OSC_TITLE_PREFIX = "\u001B]0;";
55
+ /** BEL, the terminator the reference form uses (ST works too; BEL is the
56
+ * one older terminals accept without argument). */
57
+ export declare const OSC_TITLE_SUFFIX = "\u0007";
58
+ /**
59
+ * The text of the title, with no IO — the whole rule, testable.
60
+ *
61
+ * Every part is passed through `escapeTerminal` before it can reach the
62
+ * sequence. A title is whatever a human typed or PASTED: a BEL in it
63
+ * would end the sequence early and an ESC would begin another one, and
64
+ * the title would stop being a title and start being commands to the
65
+ * terminal. The same stripper the rendered surfaces use — one definition
66
+ * of "what is safe to put on a terminal", not a second.
67
+ */
68
+ export declare function windowTitleText(events: readonly Event[], workspace: string): string;
69
+ /**
70
+ * Write the title for this session's state. Called where the session is
71
+ * BOUND (which is one place for all three entry points — first start,
72
+ * `/resume <id>`, and a switch) and again as the session's own title
73
+ * becomes knowable, so a tab named before the first prompt is renamed by
74
+ * it rather than keeping a name that was only ever a placeholder.
75
+ */
76
+ export declare function paintWindowTitle(events: readonly Event[], cwd?: string): void;
@@ -0,0 +1,114 @@
1
+ /**
2
+ * The terminal's window title (0.39.1, the owner's call).
3
+ *
4
+ * kiso set none, so a tab read whatever the shell left there — the
5
+ * directory the shell happened to be in and the absolute path of a node
6
+ * binary, identically for every kiso in every tab. The title is the one
7
+ * place a terminal shows which session a tab holds without the user
8
+ * switching to it, and it was the only screen kiso never wrote to.
9
+ *
10
+ * `kiso — <workspace>` at the start, `kiso — <session title> —
11
+ * <workspace>` once the session has one. The session's title is
12
+ * `sessionTitle`'s — the SAME projection the resume picker and `kiso
13
+ * sessions` print, so a tab and the picker can never disagree about what
14
+ * a session is called. That is also why an opener does not become the
15
+ * title: the rule for "substantive" lives in one place and this is a
16
+ * consumer of it, not a second opinion.
17
+ *
18
+ * WHAT IT WRITES. OSC 0, BEL-terminated — icon name and window title in
19
+ * one sequence, the form every terminal that supports either accepts. It
20
+ * goes STRAIGHT to stdout, deliberately outside the compositor: a title
21
+ * occupies no cell and no column, so it is not in the width accounting
22
+ * and must not be a cell that the repaint could move, cut, or scroll.
23
+ *
24
+ * WHAT IT NEVER WRITES. Anything at all when stdout is not a TTY. An OSC
25
+ * into a pipe is bytes in someone's output, and the pipe-identity gates
26
+ * exist because that has been a real defect before.
27
+ *
28
+ * NO RESTORE ON EXIT. Putting back what was there first requires reading
29
+ * it, which no terminal reliably answers; the shell repaints its own
30
+ * title on the next prompt anyway. A guess written on the way out would
31
+ * be a title kiso invented, which is worse than one it left.
32
+ *
33
+ * AND NO `process.title`. The reference implementation sets one; kiso
34
+ * does not, because two gates in this repo said no and the benefit was
35
+ * that `ps` would print `kiso` instead of a node path.
36
+ *
37
+ * - It overwrites the process's ARGV memory, so a renamed process shows
38
+ * as `kiso` with its arguments simply gone. The subagent's
39
+ * concurrency probe counts live children by matching `chat
40
+ * sub-parent-` in the command column; six renamed children were
41
+ * indistinguishable from each other and from nothing.
42
+ * - Setting it is not free on this platform: 14 ms measured for the
43
+ * first assignment on the machine this was written on, 7 ms for the
44
+ * second. A synchronous stall of that size on the main thread while a
45
+ * 3,000-line paste is arriving wedges the PTY in both directions —
46
+ * the UD-1 byte-exact paste gate deadlocked reproducibly and passed
47
+ * the moment the assignment was removed.
48
+ *
49
+ * The window title is what was asked for; the process name was a detail
50
+ * that came with it, and it costs more than it is worth.
51
+ */
52
+ import { basename } from "node:path";
53
+ import { sessionTitle } from "@vincemakes/kiso-runtime/internal";
54
+ import { displayWidth, widthCut } from "@vincemakes/kiso-tui-cells/width";
55
+ import { escapeTerminal } from "@vincemakes/kiso-tui-cells/render";
56
+ /** OSC 0 — "set icon name and window title". */
57
+ export const OSC_TITLE_PREFIX = "\u001b]0;";
58
+ /** BEL, the terminator the reference form uses (ST works too; BEL is the
59
+ * one older terminals accept without argument). */
60
+ export const OSC_TITLE_SUFFIX = "\u0007";
61
+ /** The session title's share of the tab, in CELLS. A tab strip gives a
62
+ * title far less than a row, and the workspace — which says WHERE, the
63
+ * thing a human scanning tabs is usually after — must survive the cut. */
64
+ const TITLE_CELLS = 40;
65
+ /** The title a session with no title yet has. `sessionTitle` returns this
66
+ * when nothing has been asked; it is not a label, so it is not shown. */
67
+ const NO_TITLE = "(no prompt)";
68
+ /**
69
+ * The text of the title, with no IO — the whole rule, testable.
70
+ *
71
+ * Every part is passed through `escapeTerminal` before it can reach the
72
+ * sequence. A title is whatever a human typed or PASTED: a BEL in it
73
+ * would end the sequence early and an ESC would begin another one, and
74
+ * the title would stop being a title and start being commands to the
75
+ * terminal. The same stripper the rendered surfaces use — one definition
76
+ * of "what is safe to put on a terminal", not a second.
77
+ */
78
+ export function windowTitleText(events, workspace) {
79
+ const place = escapeTerminal(workspace);
80
+ // Filtered BEFORE the wrap, so the cost is one object per user turn
81
+ // rather than one per event — this is re-derived on every turn of a
82
+ // session whose log may hold thousands. `sessionTitle` filters again;
83
+ // it is the authority on what counts and this is not a second opinion.
84
+ const inputs = events.filter((e) => e.type === "user_input");
85
+ const raw = sessionTitle(inputs.map((event) => ({ runId: "", ts: 0, event })));
86
+ if (raw === NO_TITLE)
87
+ return `kiso — ${place}`;
88
+ const safe = escapeTerminal(raw);
89
+ // Cut by CELLS, not code points: a title of wide characters counts
90
+ // two columns each, and a count of characters would overflow the tab
91
+ // by as much again. The mark is inside the budget, never added to it.
92
+ const shown = displayWidth(safe) > TITLE_CELLS ? `${widthCut(safe, TITLE_CELLS - 1)}…` : safe;
93
+ return `kiso — ${shown} — ${place}`;
94
+ }
95
+ /** What was last written, so a repaint of the same title writes nothing.
96
+ * The title is re-derived on every bind and every user turn; most of
97
+ * those derive what is already on screen. */
98
+ let shown = null;
99
+ /**
100
+ * Write the title for this session's state. Called where the session is
101
+ * BOUND (which is one place for all three entry points — first start,
102
+ * `/resume <id>`, and a switch) and again as the session's own title
103
+ * becomes knowable, so a tab named before the first prompt is renamed by
104
+ * it rather than keeping a name that was only ever a placeholder.
105
+ */
106
+ export function paintWindowTitle(events, cwd = process.cwd()) {
107
+ if (process.stdout.isTTY !== true)
108
+ return;
109
+ const text = windowTitleText(events, basename(cwd) || cwd);
110
+ if (text === shown)
111
+ return;
112
+ shown = text;
113
+ process.stdout.write(`${OSC_TITLE_PREFIX}${text}${OSC_TITLE_SUFFIX}`);
114
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-code",
3
- "version": "0.39.0",
3
+ "version": "0.39.2",
4
4
  "description": "kiso-code \u2014 the coding agent on kiso, the durable runtime for AI agents: kiso chat / kiso resume / kiso sessions.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -18,20 +18,20 @@
18
18
  "test": "vitest run"
19
19
  },
20
20
  "dependencies": {
21
- "@vincemakes/kiso-ask-ext": "0.39.0",
22
- "@vincemakes/kiso-core": "0.39.0",
23
- "@vincemakes/kiso-evals": "0.39.0",
24
- "@vincemakes/kiso-mcp-ext": "0.39.0",
25
- "@vincemakes/kiso-provider-anthropic": "0.39.0",
26
- "@vincemakes/kiso-provider-openai": "0.39.0",
27
- "@vincemakes/kiso-provider-openai-responses": "0.39.0",
28
- "@vincemakes/kiso-runtime": "0.39.0",
29
- "@vincemakes/kiso-skills-ext": "0.39.0",
30
- "@vincemakes/kiso-subagent-ext": "0.39.0",
31
- "@vincemakes/kiso-task-ext": "0.39.0",
32
- "@vincemakes/kiso-tools-node": "0.39.0",
33
- "@vincemakes/kiso-tui": "0.39.0",
34
- "@vincemakes/kiso-tui-cells": "0.39.0"
21
+ "@vincemakes/kiso-ask-ext": "0.39.2",
22
+ "@vincemakes/kiso-core": "0.39.2",
23
+ "@vincemakes/kiso-evals": "0.39.2",
24
+ "@vincemakes/kiso-mcp-ext": "0.39.2",
25
+ "@vincemakes/kiso-provider-anthropic": "0.39.2",
26
+ "@vincemakes/kiso-provider-openai": "0.39.2",
27
+ "@vincemakes/kiso-provider-openai-responses": "0.39.2",
28
+ "@vincemakes/kiso-runtime": "0.39.2",
29
+ "@vincemakes/kiso-skills-ext": "0.39.2",
30
+ "@vincemakes/kiso-subagent-ext": "0.39.2",
31
+ "@vincemakes/kiso-task-ext": "0.39.2",
32
+ "@vincemakes/kiso-tools-node": "0.39.2",
33
+ "@vincemakes/kiso-tui": "0.39.2",
34
+ "@vincemakes/kiso-tui-cells": "0.39.2"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "^26.1.2",