@vincemakes/kiso-code 0.34.0 → 0.37.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/index.js CHANGED
@@ -37,13 +37,13 @@ import { createCodingTools } from "@vincemakes/kiso-tools-node";
37
37
  import { MODES, getMode, modeExtensions, modeFromEnv, modeSystemPrompt, setMode } from "./mode.js";
38
38
  import { breakerExtension } from "./breaker.js";
39
39
  import { builtInLayer } from "./builtin.js";
40
- import { agentModel, atFiles, body, bodyLog, codingToolOptions, kisoHome, builtInExtensions, currentFaux, dock, extensionsDir, loadedExtensions, mergedConfig, mergedTempPaths, modelChoice, projectExtensions, configModels, configuredWindow, agentBaseUrl, currentModelName, currentAgentExtensions, sessionStoreRef, sessionsDir, setAgentModel, setBody, setConfigModels, setConfiguredWindow, setCurrentAgentExtensions, setCurrentFaux, setCurrentModelName, setExtensionLists, setMergedConfig, setModelChoice, setSessionStore, userExtensions, VERSION, lastBinding, acceptDrift, setAcceptDrift } from "./state.js";
40
+ import { agentModel, atFiles, body, bodyLog, codingToolOptions, kisoHome, builtInExtensions, currentFaux, dock, extensionsDir, loadedExtensions, mergedConfig, mergedTempPaths, modelChoice, projectExtensions, configModels, configuredWindow, agentBaseUrl, currentModelName, currentAgentExtensions, sessionStoreRef, sessionsDir, setAgentModel, setBody, setConfigModels, setConfiguredWindow, setCurrentAgentExtensions, setCurrentFaux, setCurrentModelName, setExtensionLists, setMergedConfig, setModelChoice, setSessionStore, secretEnvNamesOf, userExtensions, VERSION, lastBinding, acceptDrift, setAcceptDrift } from "./state.js";
41
41
  import { askUi, resolveProjectTrust } from "./trust-ui.js";
42
42
  import { isFirstRun, scaffoldFirstRun } from "./first-run.js";
43
43
  import { fauxSkip, readFauxScript } from "./faux-glue.js";
44
- import { chat, contextWindowTokens, displayCtxRatio, statusModelLabel } from "./chat.js";
44
+ import { chat, displayCtxRatio, microcompactThresholdFor, statusModelLabel } from "./chat.js";
45
+ import { adapterOptionsFor } from "./auth/adapter-options.js";
45
46
  import { loadProjectConfig, loadUserConfig, mergeConfigs, resolveAutoCompact, resolveContextWindow, resolveModel } from "./config.js";
46
- import { oauthTokenThunk } from "./auth/token.js";
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";
@@ -96,6 +96,47 @@ function streamIdleFromEnv() {
96
96
  * OR-9 adds `update`: npm inherits the terminal for the install's own
97
97
  * progress and prompts, so no editor may hold stdin while it runs. */
98
98
  const CREDENTIAL_COMMANDS = new Set(["login", "logout", "auth", "update"]);
99
+ /**
100
+ * Astra F3 — A STORED CREDENTIAL IS NOT A SELECTED MODEL.
101
+ *
102
+ * `kiso login` exits 0, says the key is stored, and stops. With no profile
103
+ * the very next command still announces the demo and runs the scripted
104
+ * listing, so a person who has just signed in reasonably concludes that
105
+ * sign-in failed or is being ignored. Nothing was broken: a credential is
106
+ * stored under a PROVIDER, and a PROFILE is what selects the model that
107
+ * uses it. The gap was that nobody said so at the one moment it matters.
108
+ *
109
+ * These are onboarding EXAMPLES, not a resolution path — nothing here ever
110
+ * decides where a credential goes (that is `effectiveBaseUrl` and
111
+ * `providerIdOf`, and it stays there).
112
+ */
113
+ const PROFILE_EXAMPLE = {
114
+ anthropic: '{"model":"claude","models":{"claude":{"kind":"anthropic","model":"claude-sonnet-5"}}}',
115
+ openai: '{"model":"gpt","models":{"gpt":{"kind":"openai-compat","model":"gpt-4o"}}}',
116
+ chatgpt: '{"model":"codex","models":{"codex":{"kind":"openai-responses","model":"gpt-5-codex","baseUrl":"https://chatgpt.com/backend-api/codex"}}}',
117
+ deepseek: '{"model":"deepseek","models":{"deepseek":{"kind":"openai-compat","model":"deepseek-flash","baseUrl":"https://api.deepseek.com"}}}',
118
+ zai: '{"model":"glm","models":{"glm":{"kind":"openai-compat","model":"glm-5.3-flash","baseUrl":"https://api.z.ai"}}}',
119
+ };
120
+ /** The line a fresh sign-in needs, or nothing when profiles already exist.
121
+ * Read from the USER config alone: a credential command resolves no
122
+ * project trust, and profiles live in the user's own file. */
123
+ function nextStepAfterLogin(provider) {
124
+ let hasProfile = false;
125
+ try {
126
+ hasProfile = Object.keys(loadUserConfig()?.models ?? {}).length > 0;
127
+ }
128
+ catch {
129
+ // A config that cannot be read is its own loud error elsewhere; here
130
+ // it only means we cannot prove a profile exists, so we say the step.
131
+ }
132
+ if (hasProfile)
133
+ return "\nkiso already has profiles — `/model` in a session lists them and switches.\n";
134
+ const example = PROFILE_EXAMPLE[provider];
135
+ return (`\nThe key is stored, but nothing selects a model yet: a PROFILE does that,` +
136
+ ` and without one kiso stays in the keyless faux mode.\nPut one in ${join(kisoHome(), "config.json")}` +
137
+ (example === undefined ? ":\n" : `, for example:\n\n ${example}\n`) +
138
+ `\nThen run kiso. \`/model\` lists your profiles and switches between them.\n`);
139
+ }
99
140
  /** OR-9: the one install command the README gives, which `kiso update`
100
141
  * runs and the failure message names. */
101
142
  const INSTALL_COMMAND = ["npm", "i", "-g", "@vincemakes/kiso-code@latest"];
@@ -539,6 +580,13 @@ directory and change code with tools. Be concise: answer in a few lines
539
580
  unless the task genuinely needs more. Never claim a file was changed
540
581
  unless a tool confirmed it.
541
582
 
583
+ What you can reach:
584
+ - The workspace: read_file, list_dir, search_text, write_file, edit_file.
585
+ - This machine and the network: shell — builds, tests, git, package
586
+ managers, curl for HTTP, system queries. A request one command can
587
+ answer is answered by running it.
588
+ - The human: ask_user, for a decision that is theirs.
589
+
542
590
  Tool discipline:
543
591
  - READ BEFORE YOU EDIT. For any file you are about to change, read it
544
592
  first — never guess its content.
@@ -550,11 +598,18 @@ Tool discipline:
550
598
  - Batch independent tool calls into one reply — they run in parallel.
551
599
  - search_text and list_dir are cheap — locate first, then read ranges
552
600
  with read_file offset/limit; never read a whole large file in one call.
553
- - Do not re-read a file you already read unchanged — rely on the earlier
554
- result.
601
+ - Do not re-read a file you already read unchanged, or one you changed
602
+ yourself through a confirmed edit — rely on the earlier result and
603
+ on the change you just made.
555
604
  - When a tool fails, read the error and adjust; do not repeat the same
556
605
  call blindly.
557
606
 
607
+ An authorization covers what it NAMES: when the scope is not named —
608
+ which files, which branches, whether to push — ask before acting.
609
+ Delivering, sharing or handing over changes means committing locally and
610
+ stopping; pushing, publishing or sending happens only when the human
611
+ names it.
612
+
558
613
  Workflow: understand the request, find the relevant code, make the
559
614
  smallest change that works, then verify with a command (tests/build).
560
615
  Report what you did in one or two lines per change.`;
@@ -664,24 +719,33 @@ async function makeAgent(sessionId, input, modelFlag) {
664
719
  // the panel bridge is the argument, and a non-TTY session has none to
665
720
  // give. A piped run's composed tool table therefore cannot contain
666
721
  // ask_user (T-Q3: the bench's structural byte-identity proof).
667
- const builtIn = await builtInLayer(user, proj, input !== undefined && process.stdin.isTTY ? askUi(input) : undefined);
722
+ // Astra F7: the config is READ here — a pure read, its setters still run
723
+ // below with the rest of merge round B — because the mcp extension spawns
724
+ // its stdio children while it is being constructed, and the strip needs
725
+ // the configured secret names by then.
726
+ const userCfg = loadUserConfig();
727
+ const projectCfg = loadProjectConfig(process.cwd(), project !== null);
728
+ const merged = mergeConfigs(userCfg, projectCfg);
729
+ const secretEnvNames = secretEnvNamesOf(merged.models ?? {});
730
+ const builtIn = await builtInLayer(user, proj, input !== undefined && process.stdin.isTTY ? askUi(input) : undefined, secretEnvNames);
668
731
  setExtensionLists(builtIn, user, proj, [...builtIn, ...user, ...proj]);
669
732
  // merge round B — the config surface: user config + (trusted) project config,
670
733
  // resolved with flags > env > project > user > default. The CLI never
671
734
  // imports provider SDKs directly — the runtime's lazy provider
672
735
  // resolution owns them (a config profile only ever NAMES an env var for
673
736
  // its key; the key itself never sits in a config file).
674
- const userCfg = loadUserConfig();
675
- const projectCfg = loadProjectConfig(process.cwd(), project !== null);
676
- const merged = mergeConfigs(userCfg, projectCfg);
677
737
  setMergedConfig(merged);
678
738
  // DT-1a: what a delegated task may NAME — the configured checks and the
679
739
  // model profiles — handed to the (in-process) subagent extension through
680
740
  // the environment. A model never supplies a command; it names a check.
681
741
  process.env.KISO_DELEGATION_CONFIG_JSON = JSON.stringify({ checks: merged.checks ?? {}, profiles: Object.keys(merged.models ?? {}) });
682
742
  setConfigModels(merged.models ?? {});
683
- setConfiguredWindow(resolveContextWindow(merged));
684
743
  const resolved = resolveModel(modelFlag, merged);
744
+ // AFTER the model resolves: the window a PROFILE states is about that
745
+ // profile's model, so it cannot be read before we know which profile is
746
+ // selected. Reading it a line too early is how the compaction threshold
747
+ // ended up frozen at the wrong model's value (CTX-1).
748
+ setConfiguredWindow(resolveContextWindow(merged, resolved?.profile));
685
749
  const model = resolved === null ? "faux" : resolved.profile.model;
686
750
  if (resolved === null) {
687
751
  console.log("[faux mode — set ANTHROPIC_API_KEY or OPENAI_API_KEY, or configure models in ~/.kiso/config.json]\n");
@@ -725,7 +789,9 @@ async function makeAgent(sessionId, input, modelFlag) {
725
789
  // half the model window (KISO_CONTEXT_WINDOW override included;
726
790
  // 200k window → 100k tokens). Long sessions compact old read/list/
727
791
  // search/shell outputs instead of silently growing past the window.
728
- microcompact: { thresholdTokens: contextWindowTokens() / 2 },
792
+ // CTX-1: the startup value; `/model` recomputes it through the same
793
+ // function, so the two can never drift apart.
794
+ microcompact: { thresholdTokens: microcompactThresholdFor() },
729
795
  // E6: the run-start context policy — OFF unless env-armed (beats the microcompact default when both fire).
730
796
  ...(contextPolicy !== undefined ? { contextPolicy } : {}),
731
797
  // R3e (owner ruling, 2026-08-28): NO turn limit on an interactive
@@ -741,21 +807,18 @@ async function makeAgent(sessionId, input, modelFlag) {
741
807
  ...(resolved !== null
742
808
  ? {
743
809
  provider: resolved.profile.kind,
744
- // OR-1: exactly one sign-in shape reaches the adapter. An
745
- // OAuth profile has no key to pass — it passes the thunk
746
- // the adapter re-resolves per request instead.
747
- ...(resolved.oauthProviderId !== undefined
748
- ? { oauth: oauthTokenThunk(resolved.oauthProviderId) }
749
- : { apiKey: resolved.apiKey ?? "none" }),
750
- // OR-1: the ChatGPT backend's cache lane is the SESSION —
751
- // one conversation's requests share a key, different
752
- // conversations never do. The one entry point that hands
753
- // no session id is `kiso sessions`, a read-only listing
754
- // that streams nothing, so its absence costs no cache.
755
- ...(sessionId !== undefined ? { promptCacheKey: sessionId } : {}),
756
- ...(resolved.profile.baseUrl !== undefined ? { baseUrl: resolved.profile.baseUrl } : {}),
757
- ...(resolved.profile.promptCaching !== undefined ? { promptCaching: resolved.profile.promptCaching } : {}),
758
- // LT-1: the profile's stream watchdog bound, if it states one
810
+ // Astra F1 (P0): the wire config is built in ONE place
811
+ // (auth/adapter-options.ts) — credential shape, the ALWAYS
812
+ // EXPLICIT endpoint, the session's cache key and the
813
+ // profile's caching flag. This site and the `/model` site
814
+ // were the same spread written twice.
815
+ ...adapterOptionsFor(resolved.profile, resolved.oauthProviderId !== undefined
816
+ ? { type: "oauth", providerId: resolved.oauthProviderId }
817
+ : { type: "api-key", apiKey: resolved.apiKey ?? "none" }, sessionId),
818
+ // LT-1: the profile's stream watchdog bound, if it states one.
819
+ // NOT an adapter option — an agent-definition field the
820
+ // runtime reads — so it stays here rather than moving into
821
+ // adapterOptionsFor.
759
822
  ...(resolved.profile.streamIdleMs !== undefined ? { streamIdleMs: resolved.profile.streamIdleMs } : {}),
760
823
  }
761
824
  : { adapter: createFauxProvider(readFauxScript().slice(fauxSkipTurns)) }),
@@ -831,6 +894,33 @@ async function pickSession(agent, input) {
831
894
  * formatter — never a boot-time copy, which would drift from the real
832
895
  * row the moment either changed.
833
896
  */
897
+ /**
898
+ * CTX-1 (Astra F34-1): EVERY entry point that opens a session must bind the
899
+ * policy that follows the session's OWN model.
900
+ *
901
+ * `agent.session()` restores the model recorded in the durable profile —
902
+ * any model that session ever used, not necessarily the one this process
903
+ * started on. The display and the compaction threshold are both derived
904
+ * from it, so both belong here.
905
+ *
906
+ * The first fix put these two lines in chatLoop only. `kiso resume <id>`
907
+ * and `kiso -p <text> <id>` open through their own paths, restored the
908
+ * model, and kept the STARTUP threshold: a session recorded on a 1M model,
909
+ * resumed from a 200k start, cleared its tool results at 100,000 while the
910
+ * interactive entry point cleared at 500,000. Three doors, one of them
911
+ * fixed, is the same defect with a smaller blast radius.
912
+ *
913
+ * The pair is passed EXPLICITLY, never read back out of the display state
914
+ * set on the line above: depending on two lines staying in order is how the
915
+ * threshold got stuck in the first place.
916
+ */
917
+ function bindRestoredSession(session) {
918
+ setAgentModel(session.model, session.baseUrl);
919
+ session.setMicrocompactThreshold(microcompactThresholdFor({
920
+ model: session.model,
921
+ ...(session.baseUrl !== undefined ? { baseUrl: session.baseUrl } : {}),
922
+ }));
923
+ }
834
924
  function paintBootStatus(session) {
835
925
  if (!dock.active)
836
926
  return;
@@ -1033,7 +1123,9 @@ async function chatLoop(first, firstId, input, autoCompact) {
1033
1123
  // XP-1 §2.1: the switched-to session's OWN truth repaints the row —
1034
1124
  // the global display state never outlives the session it described
1035
1125
  // (pre-XP the row kept the previous session's /model selection).
1036
- setAgentModel(session.model, session.baseUrl);
1126
+ // CTX-1: the restored session's own model decides the display AND
1127
+ // the threshold. One step, shared by all three entry points.
1128
+ bindRestoredSession(session);
1037
1129
  setCurrentModelName(session.model);
1038
1130
  paintBootStatus(session);
1039
1131
  const nav = {
@@ -1296,7 +1388,12 @@ async function main() {
1296
1388
  input.onClipboardPaste?.(() => {
1297
1389
  const shot = clipboardImage(tmpdir());
1298
1390
  if (shot === null) {
1299
- bodyLog("[no image on the clipboard — ctrl+V attaches one; a file dragged into the window works too]");
1391
+ // Astra F8: on a platform with no clipboard reader kiso never
1392
+ // LOOKED, so "no image on the clipboard" blamed the clipboard for
1393
+ // a limit of the build. Say which of the two it is.
1394
+ bodyLog(process.platform === "darwin"
1395
+ ? "[no image on the clipboard — ctrl+V attaches one; a file dragged into the window works too]"
1396
+ : "[clipboard images are macOS-only — put the image's path in your message instead; a file dragged into the window leaves one]");
1300
1397
  return null;
1301
1398
  }
1302
1399
  return shot;
@@ -1316,6 +1413,7 @@ async function main() {
1316
1413
  agent = await makeAgent(id, input, modelFlag);
1317
1414
  applyConfigMode();
1318
1415
  const session = await agent.session({ id, ...(acceptDrift() ? { acceptDrift: true } : {}) });
1416
+ bindRestoredSession(session); // CTX-1 (F34-1): the -p door, too
1319
1417
  faux = currentFaux;
1320
1418
  await resume(session, printPrompt, faux, input);
1321
1419
  const last = [...session.log.all].reverse().find((e) => e.type === "terminal");
@@ -1370,6 +1468,7 @@ async function main() {
1370
1468
  break;
1371
1469
  }
1372
1470
  const session = await agent.session({ id, ...(acceptDrift() ? { acceptDrift: true } : {}) });
1471
+ bindRestoredSession(session); // CTX-1 (F34-1): the explicit-id door
1373
1472
  faux = currentFaux;
1374
1473
  // E area: the durable script position is computed from the
1375
1474
  // session id, and on the picker path the id did not exist when
@@ -1465,6 +1564,7 @@ async function main() {
1465
1564
  });
1466
1565
  setCredential(provider, cred);
1467
1566
  process.stdout.write(`signed in to ${provider} (${chatgptFlow.label}) — account ${cred.accountId ?? "?"}, expires ${new Date(cred.expires).toISOString()} — stored in ${authPath()}\n`);
1567
+ process.stdout.write(nextStepAfterLogin(provider));
1468
1568
  }
1469
1569
  finally {
1470
1570
  rl.close();
@@ -1476,6 +1576,7 @@ async function main() {
1476
1576
  throw new CliUsageError(`kiso login ${provider}: no key given`);
1477
1577
  setCredential(provider, { type: "api-key", key, savedAt: Date.now() });
1478
1578
  process.stdout.write(`signed in to ${provider} with an API key (${maskSecret(key)}) — stored in ${authPath()}\n`);
1579
+ process.stdout.write(nextStepAfterLogin(provider));
1479
1580
  break;
1480
1581
  }
1481
1582
  case "update": {
package/dist/mode.d.ts CHANGED
@@ -15,7 +15,16 @@ export declare const MODES: readonly Mode[];
15
15
  /** DC-36 — one line per tier, for the picker, TRANSCRIBED FROM decide()
16
16
  * below rather than written fresh. A description that drifts from the
17
17
  * behaviour is worse than none: this is the row a human reads before
18
- * handing over the approval gate. */
18
+ * handing over the approval gate.
19
+ *
20
+ * Astra F4: these describe THE TIER'S CONTRIBUTION TO THE CHAIN, not the
21
+ * chain's verdict. "every tool asks" read as a promise that manual is a
22
+ * revocation — pick it and you are asked about everything again — and it
23
+ * is not. A tier that ASKS abstains in favour of anything that ALLOWS, so
24
+ * a saved don't-ask-again rule still allows, and the side effect runs with
25
+ * no new question. The composition (deny > allow > ask) is the ruling and
26
+ * is unchanged; the copy was the thing that was wrong. `plan` needs no
27
+ * qualification because it DENIES, and a deny is what nothing overrides. */
19
28
  export declare const MODE_NOTE: Readonly<Record<Mode, string>>;
20
29
  export declare function getMode(): Mode;
21
30
  export declare function setMode(m: Mode): void;
package/dist/mode.js CHANGED
@@ -13,13 +13,22 @@ export const MODES = ["manual", "default", "accept-edits", "plan", "bypass"];
13
13
  /** DC-36 — one line per tier, for the picker, TRANSCRIBED FROM decide()
14
14
  * below rather than written fresh. A description that drifts from the
15
15
  * behaviour is worse than none: this is the row a human reads before
16
- * handing over the approval gate. */
16
+ * handing over the approval gate.
17
+ *
18
+ * Astra F4: these describe THE TIER'S CONTRIBUTION TO THE CHAIN, not the
19
+ * chain's verdict. "every tool asks" read as a promise that manual is a
20
+ * revocation — pick it and you are asked about everything again — and it
21
+ * is not. A tier that ASKS abstains in favour of anything that ALLOWS, so
22
+ * a saved don't-ask-again rule still allows, and the side effect runs with
23
+ * no new question. The composition (deny > allow > ask) is the ruling and
24
+ * is unchanged; the copy was the thing that was wrong. `plan` needs no
25
+ * qualification because it DENIES, and a deny is what nothing overrides. */
17
26
  export const MODE_NOTE = {
18
- manual: "every tool asks",
19
- default: "reads run; writes, edits and shell ask",
20
- "accept-edits": "reads, writes and edits run; shell asks",
21
- plan: "reads run; everything else is denied — read-only",
22
- bypass: "everything runs, nothing asks",
27
+ manual: "asks for every tool — a saved allow still allows",
28
+ default: "reads run; writes, edits and shell ask — a saved allow still allows",
29
+ "accept-edits": "reads, writes and edits run; shell asks — a saved allow still allows",
30
+ plan: "reads run; everything else is denied — read-only, and a deny wins",
31
+ bypass: "everything runs, nothing asks — a user deny still wins",
23
32
  };
24
33
  /** The read-only tool set (plan): reading is allowed, everything else
25
34
  * denied with the guiding reason. */
package/dist/state.d.ts CHANGED
@@ -16,9 +16,19 @@ export declare function kisoHome(): string;
16
16
  * is decided. The session's own tool set and the `!` command's runner both
17
17
  * need it, and two copies of a ruling-bearing literal is how a later DC-49
18
18
  * amendment reaches one caller and not the other. */
19
+ /**
20
+ * Astra F7 — every configured profile's `apiKeyEnv` NAME is a secret name.
21
+ * The strip's suffix rules cannot see `REVIEW_PROVIDER_TOKEN`, and only the
22
+ * config knows which names are keys, so the config says so. ONE derivation:
23
+ * the shell tool reads it through codingToolOptions, and startup reads it
24
+ * directly for the mcp extension, which spawns its stdio children before
25
+ * these state setters have run.
26
+ */
27
+ export declare function secretEnvNamesOf(models: Readonly<Record<string, unknown>>): readonly string[];
19
28
  export declare function codingToolOptions(): {
20
29
  readonly workspaceRoot: string;
21
30
  readonly excludeRoots: readonly string[];
31
+ readonly secretEnvNames: readonly string[];
22
32
  };
23
33
  export declare function sessionsDir(): string;
24
34
  /** E1: the extension scan directory — KISO_EXTENSIONS_DIR overrides. */
package/dist/state.js CHANGED
@@ -22,8 +22,23 @@ export function kisoHome() {
22
22
  * is decided. The session's own tool set and the `!` command's runner both
23
23
  * need it, and two copies of a ruling-bearing literal is how a later DC-49
24
24
  * amendment reaches one caller and not the other. */
25
+ /**
26
+ * Astra F7 — every configured profile's `apiKeyEnv` NAME is a secret name.
27
+ * The strip's suffix rules cannot see `REVIEW_PROVIDER_TOKEN`, and only the
28
+ * config knows which names are keys, so the config says so. ONE derivation:
29
+ * the shell tool reads it through codingToolOptions, and startup reads it
30
+ * directly for the mcp extension, which spawns its stdio children before
31
+ * these state setters have run.
32
+ */
33
+ export function secretEnvNamesOf(models) {
34
+ return [
35
+ ...new Set(Object.values(models)
36
+ .map((p) => p.apiKeyEnv)
37
+ .filter((n) => typeof n === "string" && n.length > 0)),
38
+ ];
39
+ }
25
40
  export function codingToolOptions() {
26
- return { workspaceRoot: process.cwd(), excludeRoots: [kisoHome()] };
41
+ return { workspaceRoot: process.cwd(), excludeRoots: [kisoHome()], secretEnvNames: secretEnvNamesOf(configModels) };
27
42
  }
28
43
  export function sessionsDir() {
29
44
  return join(kisoHome(), "sessions");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vincemakes/kiso-code",
3
- "version": "0.34.0",
4
- "description": "kiso-code — the coding agent on kiso, the durable runtime for AI agents: kiso chat / kiso resume / kiso sessions.",
3
+ "version": "0.37.0",
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",
7
7
  "bin": {
@@ -18,20 +18,20 @@
18
18
  "test": "vitest run"
19
19
  },
20
20
  "dependencies": {
21
- "@vincemakes/kiso-ask-ext": "0.34.0",
22
- "@vincemakes/kiso-core": "0.34.0",
23
- "@vincemakes/kiso-evals": "0.34.0",
24
- "@vincemakes/kiso-mcp-ext": "0.34.0",
25
- "@vincemakes/kiso-provider-anthropic": "0.34.0",
26
- "@vincemakes/kiso-provider-openai": "0.34.0",
27
- "@vincemakes/kiso-provider-openai-responses": "0.34.0",
28
- "@vincemakes/kiso-runtime": "0.34.0",
29
- "@vincemakes/kiso-skills-ext": "0.34.0",
30
- "@vincemakes/kiso-subagent-ext": "0.34.0",
31
- "@vincemakes/kiso-task-ext": "0.34.0",
32
- "@vincemakes/kiso-tools-node": "0.34.0",
33
- "@vincemakes/kiso-tui": "0.34.0",
34
- "@vincemakes/kiso-tui-cells": "0.34.0"
21
+ "@vincemakes/kiso-ask-ext": "0.37.0",
22
+ "@vincemakes/kiso-core": "0.37.0",
23
+ "@vincemakes/kiso-evals": "0.37.0",
24
+ "@vincemakes/kiso-mcp-ext": "0.37.0",
25
+ "@vincemakes/kiso-provider-anthropic": "0.37.0",
26
+ "@vincemakes/kiso-provider-openai": "0.37.0",
27
+ "@vincemakes/kiso-provider-openai-responses": "0.37.0",
28
+ "@vincemakes/kiso-runtime": "0.37.0",
29
+ "@vincemakes/kiso-skills-ext": "0.37.0",
30
+ "@vincemakes/kiso-subagent-ext": "0.37.0",
31
+ "@vincemakes/kiso-task-ext": "0.37.0",
32
+ "@vincemakes/kiso-tools-node": "0.37.0",
33
+ "@vincemakes/kiso-tui": "0.37.0",
34
+ "@vincemakes/kiso-tui-cells": "0.37.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "^26.1.2",