@vincemakes/kiso-code 0.46.0 → 0.46.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.
@@ -34,6 +34,7 @@ import { createFauxProvider } from "@vincemakes/kiso-evals";
34
34
  import { sweepStaleMergeDirs } from "./temp-sweep.js";
35
35
  import { CODING_TOOL_RULES, composeSystemPrompt } from "./coding-prompt.js";
36
36
  import { createAgent, loadExtensions, loadProjectExtensions, SessionStore } from "@vincemakes/kiso-runtime";
37
+ import { preferences, startingEffort } from "./preferences.js";
37
38
  /** LT-1: the stream watchdog's bound from the environment — a non-negative
38
39
  * number of milliseconds (0 disables it); anything else is ignored. The
39
40
  * PTY rigs use it to trip the watchdog in seconds against a stub that
@@ -265,6 +266,15 @@ export async function createCodingAgent(sessionId, input, modelFlag) {
265
266
  // config profile — a direct provider/model or an env key names none.
266
267
  workspace: workspaceRoot(),
267
268
  ...(resolved !== null && merged.models?.[resolved.name] === resolved.profile ? { profileName: resolved.name } : {}),
269
+ // B1: a NEW session of a config profile starts at the effort last
270
+ // picked for it (the picker's fallback applied); the runtime reads it
271
+ // for a new session only — a resumed one keeps its own
272
+ ...(() => {
273
+ if (resolved === null || merged.models?.[resolved.name] !== resolved.profile)
274
+ return {};
275
+ const effort = startingEffort(resolved.profile, preferences().effort?.[resolved.name]);
276
+ return effort === null ? {} : { reasoning: { thinking: "default", effort } };
277
+ })(),
268
278
  // Area 5: the coding tools are bound to the workspace — every path
269
279
  // they touch is canonicalized inside cwd, escapes are refused.
270
280
  tools: [...createCodingTools(codingToolOptions())], // DC-49 — the options live in state.ts, shared with the `!` command's runner
package/dist/dispatch.js CHANGED
@@ -13,7 +13,7 @@ import { agentBaseUrl, currentProfileName, setCurrentProfileName, currentModelNa
13
13
  import { adapterOptionsFor } from "./auth/adapter-options.js";
14
14
  import { profileProviderLabel, providerLabel } from "./provider-label.js";
15
15
  import { installedVersion, versionStatusLine } from "./stale-version.js";
16
- import { preferences, setPreference } from "./preferences.js";
16
+ import { preferences, rememberEffort, setPreference } from "./preferences.js";
17
17
  import { settingsRows } from "./settings.js";
18
18
  import { floorOn, settingsLayers } from "./state.js";
19
19
  import { currentGround } from "@vincemakes/kiso-tui-cells/render";
@@ -98,7 +98,7 @@ function effortAxis(p) {
98
98
  // the sentence the coordination note asked for: said only when the
99
99
  // cursor could NOT land where the previous selection asked.
100
100
  ...(carried !== undefined && carried !== "default" && carriedIdx < 0 && defaultIdx >= 0
101
- ? { levelNote: `effort ${carried} \u2192 ${levels[defaultIdx]}: the nearest this model supports` }
101
+ ? { levelNote: `effort ${carried} \u2192 ${levels[defaultIdx]}: this model's default (it has no ${carried})` }
102
102
  : {}),
103
103
  };
104
104
  }
@@ -867,6 +867,11 @@ export function dispatch(line, ctx) {
867
867
  // §2.5: the ONE source a reload reads for the model — a
868
868
  // switch made here must survive the rebuild.
869
869
  setModelChoice(arg);
870
+ // B1: an explicit effort (typed, or the panel's level) is
871
+ // remembered for the profile — where its next NEW session
872
+ // starts (preferences.json)
873
+ if (direct === null && effortTok !== undefined && reasoning !== undefined)
874
+ rememberEffort(profName, effortTok);
870
875
  // The window a PROFILE states travels with the switch,
871
876
  // like the model id and the endpoint. Leaving it behind
872
877
  // is CTX-1 one field over: the row would show a
@@ -1,6 +1,10 @@
1
+ import type { ModelProfile } from "./config.js";
1
2
  export interface Preferences {
2
3
  /** ctrl+t: the thinking blocks as one italic line each. Absent = shown. */
3
4
  readonly thinking?: "shown" | "hidden";
5
+ /** B1: the effort last picked for each profile (`/model <p> <e>`, or the
6
+ * panel with a level) — where a NEW session of that profile starts. */
7
+ readonly effort?: Readonly<Record<string, string>>;
4
8
  }
5
9
  export declare function preferencesPath(home?: string): string;
6
10
  /** Startup: read the file, and keep choices made from here on in it. */
@@ -10,5 +14,15 @@ export declare function preferences(): Preferences;
10
14
  /** Remember a choice. Returns false when no file was named. The file is
11
15
  * re-read before the write, so another process's choice is kept. */
12
16
  export declare function setPreference<K extends keyof Preferences>(key: K, value: NonNullable<Preferences[K]>): boolean;
17
+ /** B1: remember an explicit effort pick for a profile. */
18
+ export declare function rememberEffort(profile: string, effort: string): boolean;
19
+ /**
20
+ * B1: the effort a NEW session of `profile` starts at, from the one last
21
+ * picked — the picker's fallback: the level itself when the model has it,
22
+ * else the endpoint's registry default, else none (default/default, no
23
+ * reasoning key). Only a level that resolves for the model is returned, so
24
+ * the session never carries a setting its first request would refuse.
25
+ */
26
+ export declare function startingEffort(profile: Pick<ModelProfile, "model" | "baseUrl">, remembered: string | undefined): string | null;
13
27
  /** Tests: back to the state before startup. */
14
28
  export declare function resetPreferences(): void;
@@ -3,8 +3,8 @@
3
3
  * `<KISO_HOME>/preferences.json`.
4
4
  *
5
5
  * `config.json` is the human's file: kiso reads it and never writes it. A
6
- * choice made with a key — ctrl+t's thinking display, today the only one —
7
- * has to survive a restart, so it lands here instead: kiso-owned, private
6
+ * choice made with a key — ctrl+t's thinking display, and (B1) the effort
7
+ * last picked for each profile — has to survive a restart, so it lands here instead: kiso-owned, private
8
8
  * (0600, tmp + rename), and read back at start-up. A missing or unreadable
9
9
  * file is an empty one; an unknown value is ignored rather than guessed.
10
10
  *
@@ -14,6 +14,7 @@
14
14
  */
15
15
  import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
16
16
  import { dirname, join } from "node:path";
17
+ import { lookupModelMetadata, resolveReasoning } from "@vincemakes/kiso-runtime/internal";
17
18
  import { kisoHome } from "./state.js";
18
19
  let prefs = null;
19
20
  let prefsPath = null;
@@ -23,7 +24,15 @@ export function preferencesPath(home = kisoHome()) {
23
24
  function read(path) {
24
25
  try {
25
26
  const raw = JSON.parse(readFileSync(path, "utf8"));
26
- return raw.thinking === "shown" || raw.thinking === "hidden" ? { thinking: raw.thinking } : {};
27
+ const out = {};
28
+ if (raw.thinking === "shown" || raw.thinking === "hidden")
29
+ out.thinking = raw.thinking;
30
+ if (raw.effort !== null && typeof raw.effort === "object" && !Array.isArray(raw.effort)) {
31
+ const effort = Object.fromEntries(Object.entries(raw.effort).filter((e) => typeof e[1] === "string"));
32
+ if (Object.keys(effort).length > 0)
33
+ out.effort = effort;
34
+ }
35
+ return out;
27
36
  }
28
37
  catch {
29
38
  return {};
@@ -57,6 +66,28 @@ export function setPreference(key, value) {
57
66
  }
58
67
  return true;
59
68
  }
69
+ /** B1: remember an explicit effort pick for a profile. */
70
+ export function rememberEffort(profile, effort) {
71
+ return setPreference("effort", { ...(preferences().effort ?? {}), [profile]: effort });
72
+ }
73
+ /**
74
+ * B1: the effort a NEW session of `profile` starts at, from the one last
75
+ * picked — the picker's fallback: the level itself when the model has it,
76
+ * else the endpoint's registry default, else none (default/default, no
77
+ * reasoning key). Only a level that resolves for the model is returned, so
78
+ * the session never carries a setting its first request would refuse.
79
+ */
80
+ export function startingEffort(profile, remembered) {
81
+ if (remembered === undefined || remembered === "default")
82
+ return null;
83
+ const effort = lookupModelMetadata(profile.model, profile.baseUrl)?.capabilities.reasoning?.effort ?? null;
84
+ if (effort === null)
85
+ return null;
86
+ const legal = (level) => resolveReasoning(profile.model, { thinking: "default", effort: level }, profile.baseUrl).ok;
87
+ if (effort.levels.includes(remembered) && legal(remembered))
88
+ return remembered;
89
+ return effort.default !== null && legal(effort.default) ? effort.default : null;
90
+ }
60
91
  /** Tests: back to the state before startup. */
61
92
  export function resetPreferences() {
62
93
  prefs = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-code",
3
- "version": "0.46.0",
3
+ "version": "0.46.1",
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,19 +18,19 @@
18
18
  "test": "vitest run"
19
19
  },
20
20
  "dependencies": {
21
- "@vincemakes/kiso-ask-ext": "0.46.0",
22
- "@vincemakes/kiso-core": "0.46.0",
23
- "@vincemakes/kiso-evals": "0.46.0",
24
- "@vincemakes/kiso-mcp-ext": "0.46.0",
25
- "@vincemakes/kiso-provider-anthropic": "0.46.0",
26
- "@vincemakes/kiso-provider-openai": "0.46.0",
27
- "@vincemakes/kiso-provider-openai-responses": "0.46.0",
28
- "@vincemakes/kiso-runtime": "0.46.0",
29
- "@vincemakes/kiso-skills-ext": "0.46.0",
30
- "@vincemakes/kiso-subagent-ext": "0.46.0",
31
- "@vincemakes/kiso-tools-node": "0.46.0",
32
- "@vincemakes/kiso-tui": "0.46.0",
33
- "@vincemakes/kiso-tui-cells": "0.46.0"
21
+ "@vincemakes/kiso-ask-ext": "0.46.1",
22
+ "@vincemakes/kiso-core": "0.46.1",
23
+ "@vincemakes/kiso-evals": "0.46.1",
24
+ "@vincemakes/kiso-mcp-ext": "0.46.1",
25
+ "@vincemakes/kiso-provider-anthropic": "0.46.1",
26
+ "@vincemakes/kiso-provider-openai": "0.46.1",
27
+ "@vincemakes/kiso-provider-openai-responses": "0.46.1",
28
+ "@vincemakes/kiso-runtime": "0.46.1",
29
+ "@vincemakes/kiso-skills-ext": "0.46.1",
30
+ "@vincemakes/kiso-subagent-ext": "0.46.1",
31
+ "@vincemakes/kiso-tools-node": "0.46.1",
32
+ "@vincemakes/kiso-tui": "0.46.1",
33
+ "@vincemakes/kiso-tui-cells": "0.46.1"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "^26.1.2",