@vincemakes/kiso-code 0.40.4 → 0.40.6
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/auth/credentials.d.ts +12 -0
- package/dist/auth/credentials.js +25 -0
- package/dist/chat.d.ts +3 -4
- package/dist/chat.js +12 -8
- package/dist/config.js +24 -2
- package/dist/dispatch.js +50 -25
- package/dist/index.js +41 -4
- package/dist/preferences.d.ts +14 -0
- package/dist/preferences.js +64 -0
- package/dist/settings.d.ts +37 -0
- package/dist/settings.js +79 -0
- package/dist/stale-version.d.ts +14 -0
- package/dist/stale-version.js +52 -0
- package/dist/state.d.ts +10 -0
- package/dist/state.js +4 -0
- package/package.json +15 -15
|
@@ -49,6 +49,18 @@ export declare function effectiveBaseUrl(kind: string, baseUrl?: string): string
|
|
|
49
49
|
/** The provider identity a profile's credential is stored under, or null
|
|
50
50
|
* for an origin nobody recognizes (custom: env var only). */
|
|
51
51
|
export declare function providerIdOf(kind: string, baseUrl?: string): string | null;
|
|
52
|
+
/**
|
|
53
|
+
* 0.40.6 — the store id for a GATEWAY's own key: `endpoint:<origin>`.
|
|
54
|
+
*
|
|
55
|
+
* A vendor's credential is stored under the vendor and only ever reaches
|
|
56
|
+
* the vendor's origin (R1 above). A gateway has no vendor identity, so its
|
|
57
|
+
* key is stored under the one thing that names where it may go — its
|
|
58
|
+
* ORIGIN (scheme, host, port). `kiso login --endpoint <url>` writes it; a
|
|
59
|
+
* profile whose endpoint has exactly that origin reads it; no other origin
|
|
60
|
+
* ever does, a local forwarder in front of the gateway included. Null for
|
|
61
|
+
* anything that is not an http(s) URL — never a guess.
|
|
62
|
+
*/
|
|
63
|
+
export declare function endpointCredentialId(url: string | undefined): string | null;
|
|
52
64
|
export declare function authPath(): string;
|
|
53
65
|
export declare function readAuthFile(path?: string): AuthFile;
|
|
54
66
|
export declare function getCredential(providerId: string, path?: string): Credential | undefined;
|
package/dist/auth/credentials.js
CHANGED
|
@@ -133,6 +133,31 @@ function originOf(baseUrl) {
|
|
|
133
133
|
return null;
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* 0.40.6 — the store id for a GATEWAY's own key: `endpoint:<origin>`.
|
|
138
|
+
*
|
|
139
|
+
* A vendor's credential is stored under the vendor and only ever reaches
|
|
140
|
+
* the vendor's origin (R1 above). A gateway has no vendor identity, so its
|
|
141
|
+
* key is stored under the one thing that names where it may go — its
|
|
142
|
+
* ORIGIN (scheme, host, port). `kiso login --endpoint <url>` writes it; a
|
|
143
|
+
* profile whose endpoint has exactly that origin reads it; no other origin
|
|
144
|
+
* ever does, a local forwarder in front of the gateway included. Null for
|
|
145
|
+
* anything that is not an http(s) URL — never a guess.
|
|
146
|
+
*/
|
|
147
|
+
export function endpointCredentialId(url) {
|
|
148
|
+
if (url === undefined)
|
|
149
|
+
return null;
|
|
150
|
+
let u;
|
|
151
|
+
try {
|
|
152
|
+
u = new URL(url);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
if (u.protocol !== "https:" && u.protocol !== "http:")
|
|
158
|
+
return null;
|
|
159
|
+
return `endpoint:${u.origin}`;
|
|
160
|
+
}
|
|
136
161
|
export function authPath() {
|
|
137
162
|
return join(kisoHome(), "auth.json");
|
|
138
163
|
}
|
package/dist/chat.d.ts
CHANGED
|
@@ -87,10 +87,9 @@ export declare function statedContextWindow(of?: {
|
|
|
87
87
|
/** CW-1: a window as the displays write it — `1M`, `1.05M`, `272K`,
|
|
88
88
|
* `1,048,576` (a figure that is not round is shown whole). */
|
|
89
89
|
export declare function windowLabel(tokens: number): string;
|
|
90
|
-
/** CW-1: the source, said
|
|
91
|
-
* form
|
|
92
|
-
|
|
93
|
-
export declare function windowSourceNote(w: StatedWindow | null, form: "short" | "long"): string;
|
|
90
|
+
/** CW-1: the window and its source, said — /status's line (0.40.6: the
|
|
91
|
+
* short form that rode each /model row is gone with its caller). */
|
|
92
|
+
export declare function windowSourceNote(w: StatedWindow | null): string;
|
|
94
93
|
export declare function contextWindowTokens(of?: {
|
|
95
94
|
readonly model: string;
|
|
96
95
|
readonly baseUrl?: string;
|
package/dist/chat.js
CHANGED
|
@@ -14,8 +14,9 @@ import { canonicalizeUsage } from "@vincemakes/kiso-runtime";
|
|
|
14
14
|
import { canonicalizeUsageForModel, requestBudget } from "@vincemakes/kiso-runtime/internal";
|
|
15
15
|
import { dispatch, abortBangCommand } from "./dispatch.js";
|
|
16
16
|
import { paintWindowTitle } from "./window-title.js";
|
|
17
|
-
import { agentBaseUrl, agentModel, body, bodyLog, configuredWindow, dock, retryOnRow, retryShown, setRetryShown, floorOn, protectedFiles, upstreamOf } from "./state.js";
|
|
17
|
+
import { agentBaseUrl, agentModel, body, bodyLog, configuredWindow, dock, retryOnRow, retryShown, setRetryShown, floorOn, protectedFiles, upstreamOf, VERSION } from "./state.js";
|
|
18
18
|
import { attachImages } from "./attachments.js";
|
|
19
|
+
import { installedVersion, staleVersionNotice } from "./stale-version.js";
|
|
19
20
|
import { learnedWindowFor } from "./learned-windows.js";
|
|
20
21
|
import { lookupContextWindow, lookupModelMetadata } from "@vincemakes/kiso-runtime/internal";
|
|
21
22
|
import { addDontAskAgainRule, askPanel, fixHintFor, pendingAsk, resolveUncertains } from "./trust-ui.js";
|
|
@@ -121,15 +122,12 @@ export function windowLabel(tokens) {
|
|
|
121
122
|
return `${tokens / 1000}K`;
|
|
122
123
|
return tokens.toLocaleString("en-US");
|
|
123
124
|
}
|
|
124
|
-
/** CW-1: the source, said
|
|
125
|
-
* form
|
|
126
|
-
|
|
127
|
-
export function windowSourceNote(w, form) {
|
|
125
|
+
/** CW-1: the window and its source, said — /status's line (0.40.6: the
|
|
126
|
+
* short form that rode each /model row is gone with its caller). */
|
|
127
|
+
export function windowSourceNote(w) {
|
|
128
128
|
if (w === null)
|
|
129
|
-
return
|
|
129
|
+
return `window unknown — compaction assumes ${windowLabel(DEFAULT_CONTEXT_WINDOW)}; set contextWindow on the profile to state it`;
|
|
130
130
|
const size = windowLabel(w.tokens);
|
|
131
|
-
if (form === "short")
|
|
132
|
-
return w.source === "model" ? `ctx ${size} inferred` : `ctx ${size}`;
|
|
133
131
|
switch (w.source) {
|
|
134
132
|
case "set":
|
|
135
133
|
return `window ${size}, as you set it`;
|
|
@@ -1365,6 +1363,12 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1365
1363
|
stopSpinner();
|
|
1366
1364
|
paintIdle();
|
|
1367
1365
|
currentRun = null;
|
|
1366
|
+
// 0.40.5: the kiso on disk may no longer be the one this
|
|
1367
|
+
// session runs (an upgrade since it started) — said once per
|
|
1368
|
+
// installed version (stale-version.ts).
|
|
1369
|
+
const stale = staleVersionNotice(installedVersion(), VERSION, session.id);
|
|
1370
|
+
if (stale !== null)
|
|
1371
|
+
body.notice(stale);
|
|
1368
1372
|
// round 8: a faux script that ran out of declared turns exits
|
|
1369
1373
|
// loudly with a non-zero status — never a silent status 0.
|
|
1370
1374
|
// round 4 (adversarial): the exhaustion is a CONTROLLED rejection of
|
package/dist/config.js
CHANGED
|
@@ -32,7 +32,7 @@ import { readFileSync, statSync } from "node:fs";
|
|
|
32
32
|
import { homedir } from "node:os";
|
|
33
33
|
import { join } from "node:path";
|
|
34
34
|
import { kisoHome } from "./state.js";
|
|
35
|
-
import { AuthError, getCredential, providerIdOf } from "./auth/credentials.js";
|
|
35
|
+
import { AuthError, effectiveBaseUrl, endpointCredentialId, getCredential, providerIdOf } from "./auth/credentials.js";
|
|
36
36
|
import { BUILTIN_MANIFESTS } from "@vincemakes/kiso-runtime/internal";
|
|
37
37
|
/** Header names a profile may not set: credentials (a key never lives in the
|
|
38
38
|
* config file) and the framing the adapter owns. */
|
|
@@ -294,12 +294,34 @@ export function authForProfile(name, p) {
|
|
|
294
294
|
if (providerId !== null && !manifestTakesKey(providerId)) {
|
|
295
295
|
throw new ConfigError(`model ${name}: unavailable — not signed in: run \`kiso login ${providerId}\` (this provider takes no API key)`);
|
|
296
296
|
}
|
|
297
|
+
// 0.40.6: a GATEWAY's own key, stored for exactly this profile's origin
|
|
298
|
+
// (`kiso login --endpoint <url>`). The rule a vendor credential follows:
|
|
299
|
+
// stored first, the env var only when nothing is stored — and it goes to
|
|
300
|
+
// that origin alone (credentials.ts endpointCredentialId).
|
|
301
|
+
const endpointId = providerId === null ? endpointCredentialId(effectiveBaseUrl(p.kind, p.baseUrl)) : null;
|
|
302
|
+
if (endpointId !== null) {
|
|
303
|
+
let stored;
|
|
304
|
+
try {
|
|
305
|
+
stored = getCredential(endpointId);
|
|
306
|
+
}
|
|
307
|
+
catch (err) {
|
|
308
|
+
if (err instanceof AuthError)
|
|
309
|
+
throw new ConfigError(`model ${name}: ${err.message}`);
|
|
310
|
+
throw err;
|
|
311
|
+
}
|
|
312
|
+
if (stored?.type === "api-key")
|
|
313
|
+
return { type: "api-key", apiKey: stored.key, source: "store" };
|
|
314
|
+
}
|
|
297
315
|
if (p.apiKeyEnv === undefined)
|
|
298
316
|
return { type: "api-key", apiKey: "none", source: "none" };
|
|
299
317
|
const fromEnv = process.env[p.apiKeyEnv];
|
|
300
318
|
if (fromEnv !== undefined)
|
|
301
319
|
return { type: "api-key", apiKey: fromEnv, source: "env" };
|
|
302
|
-
const hint = providerId !== null
|
|
320
|
+
const hint = providerId !== null
|
|
321
|
+
? `run \`kiso login ${providerId}\` or set the env var ${p.apiKeyEnv}`
|
|
322
|
+
: endpointId !== null
|
|
323
|
+
? `set the env var ${p.apiKeyEnv}, or run \`kiso login --endpoint ${endpointId.slice("endpoint:".length)}\``
|
|
324
|
+
: `set the env var ${p.apiKeyEnv}`;
|
|
303
325
|
throw new ConfigError(`model ${name}: unavailable — no credential: ${hint} (configs never store keys, only the env-var name)`);
|
|
304
326
|
}
|
|
305
327
|
/** OR-2: does the provider's manifest admit an API key (or no auth at all)?
|
package/dist/dispatch.js
CHANGED
|
@@ -9,9 +9,14 @@ import { buildAdapter, lookupModelMetadata, resolveContinuationScope, resolveRea
|
|
|
9
9
|
import { MODES, MODE_NOTE, OFFERED_MODES, getMode, setMode } from "./mode.js";
|
|
10
10
|
import { clipboardWrite, lastAnswer } from "./clipboard.js";
|
|
11
11
|
import { protectedBangReason, protectedShellVerdict } from "./protected-shell.js";
|
|
12
|
-
import { agentBaseUrl, currentProfileName, setCurrentProfileName, currentModelName, agentModel, body, bodyLog, codingToolOptions, protectedFiles, kisoHome, configModels, dock, lastBinding, loadedSkillsCatalog, mergedConfig, readContextLedger, retryOnRow, sessionsDir, setAgentModel, setConfiguredWindow, setCurrentModelName, setModelChoice, setRetryShown, upstreamOf, setLastBinding } from "./state.js";
|
|
12
|
+
import { agentBaseUrl, currentProfileName, setCurrentProfileName, currentModelName, agentModel, body, bodyLog, codingToolOptions, protectedFiles, kisoHome, configModels, dock, lastBinding, loadedSkillsCatalog, mergedConfig, readContextLedger, retryOnRow, sessionsDir, setAgentModel, setConfiguredWindow, setCurrentModelName, setModelChoice, setRetryShown, upstreamOf, VERSION, setLastBinding } from "./state.js";
|
|
13
13
|
import { adapterOptionsFor } from "./auth/adapter-options.js";
|
|
14
14
|
import { profileProviderLabel, providerLabel } from "./provider-label.js";
|
|
15
|
+
import { installedVersion, versionStatusLine } from "./stale-version.js";
|
|
16
|
+
import { preferences, setPreference } from "./preferences.js";
|
|
17
|
+
import { settingsRows } from "./settings.js";
|
|
18
|
+
import { floorOn, settingsLayers } from "./state.js";
|
|
19
|
+
import { currentGround } from "@vincemakes/kiso-tui-cells/render";
|
|
15
20
|
import { queuedSwitchLines } from "./state.js";
|
|
16
21
|
import { contextWindowTokens, microcompactThresholdFor, startStatusSpinner, statedContextWindow, windowSourceNote } from "./chat.js";
|
|
17
22
|
import { authForProfile, directWriteProfile, profileAvailable, resolveContextWindow, unavailableReason } from "./config.js";
|
|
@@ -109,14 +114,6 @@ function signInNote(p) {
|
|
|
109
114
|
}
|
|
110
115
|
return p.apiKeyEnv ?? "no key";
|
|
111
116
|
}
|
|
112
|
-
/** CW-1 (owner, 2026-09-23): a profile's window on its /model row — the
|
|
113
|
-
* profile's own stated figure first, then the registry's chain for its
|
|
114
|
-
* model, endpoint and upstream; `inferred` marks the one no row states
|
|
115
|
-
* for that endpoint. */
|
|
116
|
-
function windowNoteOf(p) {
|
|
117
|
-
const w = statedContextWindow({ model: p.model, ...(p.baseUrl !== undefined ? { baseUrl: p.baseUrl } : {}), ...(p.upstream !== undefined ? { upstream: p.upstream } : {}) }, { configured: resolveContextWindow(mergedConfig, p) });
|
|
118
|
-
return windowSourceNote(w, "short");
|
|
119
|
-
}
|
|
120
117
|
/** The ONE dispatcher — slash commands, exit, and turns. The recovery
|
|
121
118
|
* replay routes through it too — a queued "/last" must never become a
|
|
122
119
|
* user turn (v2c: the rl lives in main, so lines arrive earlier and the
|
|
@@ -382,18 +379,15 @@ export function dispatch(line, ctx) {
|
|
|
382
379
|
return;
|
|
383
380
|
}
|
|
384
381
|
if (trimmed === "\x14think") {
|
|
385
|
-
// §2.3 — ctrl+t
|
|
386
|
-
//
|
|
387
|
-
// session is reprinted, so the blocks already on
|
|
388
|
-
// switch
|
|
389
|
-
//
|
|
390
|
-
//
|
|
391
|
-
//
|
|
392
|
-
// and the pipe's byte-identity gate is this row's gate too.
|
|
393
|
-
//
|
|
394
|
-
// The live `thinking…` placeholder is NOT touched: it belongs to
|
|
395
|
-
// the live region, and this switch is about committed blocks.
|
|
382
|
+
// §2.3 / 0.40.6 — ctrl+t hides thinking (one italic line per block,
|
|
383
|
+
// the open one included) and shows it again. DC-50's mechanism: one
|
|
384
|
+
// boolean, then the session is reprinted, so the blocks already on
|
|
385
|
+
// screen obey the switch. The choice is REMEMBERED (preferences.json)
|
|
386
|
+
// — the owner, 2026-09-23, after the reference implementation's
|
|
387
|
+
// persisted toggle; shown stays the default. The pipe keeps its own
|
|
388
|
+
// one-line fold whatever the choice.
|
|
396
389
|
body.toggleThinking();
|
|
390
|
+
setPreference("thinking", body.thinkingHidden() ? "hidden" : "shown");
|
|
397
391
|
ctx.input.prompt();
|
|
398
392
|
return;
|
|
399
393
|
}
|
|
@@ -486,6 +480,31 @@ export function dispatch(line, ctx) {
|
|
|
486
480
|
});
|
|
487
481
|
return;
|
|
488
482
|
}
|
|
483
|
+
if (trimmed === "/settings") {
|
|
484
|
+
// 0.40.6 — what kiso runs with, each value's layer, and how to change
|
|
485
|
+
// it (settings.ts). Read-only: the config file stays the human's.
|
|
486
|
+
ctx.chainRef.current = ctx.chainRef.current.then(async () => {
|
|
487
|
+
const w = statedContextWindow();
|
|
488
|
+
const profile = currentProfileName;
|
|
489
|
+
bodyLog(settingsRows({
|
|
490
|
+
user: settingsLayers.user,
|
|
491
|
+
project: settingsLayers.project,
|
|
492
|
+
env: process.env,
|
|
493
|
+
...(settingsLayers.modeFlag !== undefined ? { modeFlag: settingsLayers.modeFlag } : {}),
|
|
494
|
+
...(settingsLayers.modelFlag !== undefined ? { modelFlag: settingsLayers.modelFlag } : {}),
|
|
495
|
+
mode: getMode(),
|
|
496
|
+
model: { label: `${agentModel}${providerLabel(agentBaseUrl, upstreamOf(agentBaseUrl))}${profile === null ? "" : ` · profile ${profile}`}`, profile, switched: settingsLayers.modelSwitched },
|
|
497
|
+
ground: currentGround(),
|
|
498
|
+
floorOn,
|
|
499
|
+
window: windowSourceNote(w).replace(/^window /, ""),
|
|
500
|
+
thinkingHidden: body.thinkingHidden(),
|
|
501
|
+
thinkingRemembered: preferences().thinking !== undefined,
|
|
502
|
+
version: versionStatusLine(installedVersion(), VERSION).replace(/^version /, ""),
|
|
503
|
+
}).join("\n\n"), "words");
|
|
504
|
+
ctx.input.prompt();
|
|
505
|
+
});
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
489
508
|
if (trimmed === "/status") {
|
|
490
509
|
// B area: session id, durable event count, and the ~ context
|
|
491
510
|
// estimate — all read straight from the live session, nothing
|
|
@@ -498,7 +517,7 @@ export function dispatch(line, ctx) {
|
|
|
498
517
|
// CW-1: the percentage names its denominator and who stated it — a
|
|
499
518
|
// window inferred from the model reads differently from one the
|
|
500
519
|
// registry states for this endpoint.
|
|
501
|
-
bodyLog(`ctx ${ctxPct} · ${windowSourceNote(statedContextWindow()
|
|
520
|
+
bodyLog(`ctx ${ctxPct} · ${windowSourceNote(statedContextWindow())}`);
|
|
502
521
|
// The owner, 2026-09-21: /status is where "what am I actually
|
|
503
522
|
// running on" is answered, so the identity is spelled out HERE —
|
|
504
523
|
// the model, the host the request goes to, the profile it came
|
|
@@ -514,6 +533,9 @@ export function dispatch(line, ctx) {
|
|
|
514
533
|
// variable; until then, a label that cannot lie.)
|
|
515
534
|
const profileOf = currentProfileName === null ? "" : ` · profile ${currentProfileName}`;
|
|
516
535
|
bodyLog(`model ${agentModel}${providerLabel(agentBaseUrl, upstreamOf(agentBaseUrl))}${profileOf}`);
|
|
536
|
+
// 0.40.5: the version this session RUNS, and the installed one when
|
|
537
|
+
// an upgrade (or a rollback) since start-up made them differ.
|
|
538
|
+
bodyLog(versionStatusLine(installedVersion(), VERSION));
|
|
517
539
|
ctx.input.prompt();
|
|
518
540
|
});
|
|
519
541
|
return;
|
|
@@ -618,9 +640,11 @@ export function dispatch(line, ctx) {
|
|
|
618
640
|
// profile key is what `/model <name>` takes, not what a chooser
|
|
619
641
|
// reading a list needs. What remains is what the chooser CANNOT
|
|
620
642
|
// infer: availability, and which one is live.
|
|
621
|
-
//
|
|
622
|
-
//
|
|
623
|
-
|
|
643
|
+
// 0.40.6 (the owner, 2026-09-23: "who told you to write ctx"):
|
|
644
|
+
// the window rode here in 0.40.3–0.40.5 and cut `unavailable`
|
|
645
|
+
// to `unavailabl…` on the owner's rows. It lives on /status and
|
|
646
|
+
// /settings, where there is room to say it and its source.
|
|
647
|
+
const marks = [...(profileAvailable(profile) ? [] : ["unavailable"]), ...(name === currentProfileName ? ["current"] : [])];
|
|
624
648
|
const host = profileProviderLabel(profile.kind, profile.baseUrl, profile.upstream);
|
|
625
649
|
return { label: `${profile.kind}/${profile.model}${host === "" ? "" : ` ${host}`}`, note: marks.join(" · "), ...effortAxis(profile) };
|
|
626
650
|
}),
|
|
@@ -672,7 +696,7 @@ export function dispatch(line, ctx) {
|
|
|
672
696
|
for (const name of names) {
|
|
673
697
|
const p = configModels[name];
|
|
674
698
|
const hostOf = profileProviderLabel(p.kind, p.baseUrl, p.upstream);
|
|
675
|
-
bodyLog(` ${name} → ${p.kind}/${p.model}${hostOf === "" ? "" : ` ${hostOf}`} · ${signInNote(p)} ${profileAvailable(p) ? "(available)" : "(unavailable)"} · ${effortNote(p)}
|
|
699
|
+
bodyLog(` ${name} → ${p.kind}/${p.model}${hostOf === "" ? "" : ` ${hostOf}`} · ${signInNote(p)} ${profileAvailable(p) ? "(available)" : "(unavailable)"} · ${effortNote(p)}`);
|
|
676
700
|
}
|
|
677
701
|
}
|
|
678
702
|
bodyLog("switch with /model <profile-name|provider/model>");
|
|
@@ -769,6 +793,7 @@ export function dispatch(line, ctx) {
|
|
|
769
793
|
setAgentModel(profile.model, profile.baseUrl);
|
|
770
794
|
setCurrentModelName(arg);
|
|
771
795
|
setCurrentProfileName(direct === null ? null : profName);
|
|
796
|
+
settingsLayers.modelSwitched = true;
|
|
772
797
|
// §2.5: the ONE source a reload reads for the model — a
|
|
773
798
|
// switch made here must survive the rebuild.
|
|
774
799
|
setModelChoice(arg);
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,8 @@ import { isFirstRun, scaffoldFirstRun } from "./first-run.js";
|
|
|
53
53
|
import { fauxSkip, readFauxScript } from "./faux-glue.js";
|
|
54
54
|
import { chat, compactionDiscardedNotice, contextWindowTokens, displayCtxRatio, knownContextWindow, microcompactThresholdFor, statusModelLabel, unknownWindowNotice, windowLearnedNotice } from "./chat.js";
|
|
55
55
|
import { recordLearnedWindow, useLearnedWindows } from "./learned-windows.js";
|
|
56
|
+
import { preferences, usePreferences } from "./preferences.js";
|
|
57
|
+
import { settingsLayers } from "./state.js";
|
|
56
58
|
import { providerHost } from "./provider-label.js";
|
|
57
59
|
import { adapterOptionsFor } from "./auth/adapter-options.js";
|
|
58
60
|
import { loadProjectConfig, loadUserConfig, mergeConfigs, resolveAutoCompact, resolveContextWindow, resolveModel } from "./config.js";
|
|
@@ -759,6 +761,10 @@ async function makeAgent(sessionId, input, modelFlag) {
|
|
|
759
761
|
const userCfg = loadUserConfig();
|
|
760
762
|
const projectCfg = loadProjectConfig(process.cwd(), project !== null);
|
|
761
763
|
const merged = mergeConfigs(userCfg, projectCfg);
|
|
764
|
+
// 0.40.6: /settings names each value's layer from these
|
|
765
|
+
settingsLayers.user = userCfg;
|
|
766
|
+
settingsLayers.project = projectCfg;
|
|
767
|
+
settingsLayers.modelFlag = modelFlag;
|
|
762
768
|
const secretEnvNames = secretEnvNamesOf(merged.models ?? {});
|
|
763
769
|
const builtIn = await builtInLayer(user, proj, input !== undefined && process.stdin.isTTY ? askUi(input) : undefined, secretEnvNames);
|
|
764
770
|
setExtensionLists(builtIn, user, proj, [...builtIn, ...user, ...proj]);
|
|
@@ -1643,6 +1649,7 @@ async function main() {
|
|
|
1643
1649
|
process.exit(2);
|
|
1644
1650
|
}
|
|
1645
1651
|
setMode(m);
|
|
1652
|
+
settingsLayers.modeFlag = m;
|
|
1646
1653
|
args.splice(modeFlag, 2);
|
|
1647
1654
|
}
|
|
1648
1655
|
else {
|
|
@@ -1790,6 +1797,10 @@ async function main() {
|
|
|
1790
1797
|
editCol: () => dock.editCol(),
|
|
1791
1798
|
onDock: () => dock.redraw(), // v2d-B: the freeze scrolls the dock up — re-pin it
|
|
1792
1799
|
}));
|
|
1800
|
+
// 0.40.6: the choices kiso remembers (preferences.json) — today ctrl+t's
|
|
1801
|
+
// thinking display, restored before the first block can be drawn.
|
|
1802
|
+
usePreferences();
|
|
1803
|
+
body.setThinkingHidden(preferences().thinking === "hidden");
|
|
1793
1804
|
// REL-0152-D11: pasting an image sends no bytes, so an empty paste is
|
|
1794
1805
|
// the signal to go and look at the clipboard. What comes back is a
|
|
1795
1806
|
// PATH, which the turn's attachment scan then picks up exactly as it
|
|
@@ -2001,8 +2012,33 @@ async function main() {
|
|
|
2001
2012
|
// `login <provider>` reads the key from a hidden prompt on a TTY
|
|
2002
2013
|
// or from stdin otherwise (never from an argument — shell history);
|
|
2003
2014
|
// `logout <provider>` deletes; `auth` lists, keys masked.
|
|
2004
|
-
const { KNOWN_PROVIDERS, OAUTH_PROVIDERS, authPath, deleteCredential, maskSecret, readAuthFile, setCredential } = await import("./auth/credentials.js");
|
|
2015
|
+
const { KNOWN_PROVIDERS, OAUTH_PROVIDERS, authPath, deleteCredential, endpointCredentialId, maskSecret, providerIdOf, readAuthFile, setCredential } = await import("./auth/credentials.js");
|
|
2005
2016
|
const provider = arg;
|
|
2017
|
+
if (provider === "--endpoint" && command !== "auth") {
|
|
2018
|
+
// 0.40.6: a gateway's own key, stored for its ORIGIN and sent
|
|
2019
|
+
// there alone (credentials.ts endpointCredentialId) — so a
|
|
2020
|
+
// gateway profile starts from plain `kiso`, no env var on the
|
|
2021
|
+
// command line. The key still never comes from an argument.
|
|
2022
|
+
const url = args[2];
|
|
2023
|
+
const id = endpointCredentialId(url);
|
|
2024
|
+
if (id === null)
|
|
2025
|
+
throw new CliUsageError(`kiso ${command} --endpoint <url> — an http(s) URL, e.g. https://gateway.example/v1`);
|
|
2026
|
+
const origin = id.slice("endpoint:".length);
|
|
2027
|
+
const vendor = ["openai-compat", "anthropic", "openai-responses"].map((k) => providerIdOf(k, url)).find((v) => v !== null);
|
|
2028
|
+
if (vendor !== undefined && vendor !== null)
|
|
2029
|
+
throw new CliUsageError(`${origin} is ${vendor}'s own endpoint — run \`kiso ${command} ${vendor}\``);
|
|
2030
|
+
if (command === "logout") {
|
|
2031
|
+
const had = deleteCredential(id);
|
|
2032
|
+
process.stdout.write(had ? `removed the key for ${origin}\n` : `nothing stored for ${origin}\n`);
|
|
2033
|
+
break;
|
|
2034
|
+
}
|
|
2035
|
+
const key = (await readSecret(`API key for ${origin}: `)).trim();
|
|
2036
|
+
if (key === "")
|
|
2037
|
+
throw new CliUsageError(`kiso login --endpoint ${origin}: no key given`);
|
|
2038
|
+
setCredential(id, { type: "api-key", key, savedAt: Date.now() });
|
|
2039
|
+
process.stdout.write(`stored an API key for ${origin} (${maskSecret(key)}) in ${authPath()} — sent to that origin only; every profile whose baseUrl is on it uses this key before its env var\n`);
|
|
2040
|
+
break;
|
|
2041
|
+
}
|
|
2006
2042
|
if (command === "auth") {
|
|
2007
2043
|
const file = readAuthFile();
|
|
2008
2044
|
const rows = Object.entries(file.credentials);
|
|
@@ -2019,7 +2055,7 @@ async function main() {
|
|
|
2019
2055
|
break;
|
|
2020
2056
|
}
|
|
2021
2057
|
if (provider === undefined || !KNOWN_PROVIDERS.includes(provider)) {
|
|
2022
|
-
throw new CliUsageError(`kiso ${command} <provider> — one of: ${KNOWN_PROVIDERS.join(", ")}`);
|
|
2058
|
+
throw new CliUsageError(`kiso ${command} <provider> — one of: ${KNOWN_PROVIDERS.join(", ")}; or kiso ${command} --endpoint <url> for a gateway`);
|
|
2023
2059
|
}
|
|
2024
2060
|
if (command === "logout") {
|
|
2025
2061
|
const had = deleteCredential(provider);
|
|
@@ -2096,7 +2132,8 @@ async function main() {
|
|
|
2096
2132
|
" kiso sessions [--all|--current] list durable sessions (a terminal shows this workspace's by default)\n" +
|
|
2097
2133
|
" kiso login <provider> anthropic|openai|deepseek|zai: store an API key (hidden prompt, or stdin when piped);\n" +
|
|
2098
2134
|
" chatgpt: sign in with a ChatGPT subscription (browser; unofficial third-party flow)\n" +
|
|
2099
|
-
" kiso
|
|
2135
|
+
" kiso login --endpoint <url> a gateway: store its API key for that URL's origin only\n" +
|
|
2136
|
+
" kiso logout <provider> remove the stored credential (or --endpoint <url>)\n" +
|
|
2100
2137
|
" kiso auth list stored credentials (keys masked)\n" +
|
|
2101
2138
|
" kiso update install the latest release (npm i -g @vincemakes/kiso-code@latest)\n" +
|
|
2102
2139
|
" kiso help this help\n\n" +
|
|
@@ -2109,7 +2146,7 @@ async function main() {
|
|
|
2109
2146
|
" OPENAI_API_KEY OpenAI-compatible (OPENAI_MODEL, default gpt-4o;\n" +
|
|
2110
2147
|
" OPENAI_BASE_URL for DeepSeek/compat endpoints) — checked first\n" +
|
|
2111
2148
|
" ANTHROPIC_API_KEY Anthropic (ANTHROPIC_MODEL, default claude-sonnet-5)\n" +
|
|
2112
|
-
" ~/.kiso/config.json named model profiles (keys stay in env vars; see the README)\n");
|
|
2149
|
+
" ~/.kiso/config.json named model profiles (keys stay in env vars or kiso login; see the README)\n");
|
|
2113
2150
|
break;
|
|
2114
2151
|
}
|
|
2115
2152
|
case undefined:
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface Preferences {
|
|
2
|
+
/** ctrl+t: the thinking blocks as one italic line each. Absent = shown. */
|
|
3
|
+
readonly thinking?: "shown" | "hidden";
|
|
4
|
+
}
|
|
5
|
+
export declare function preferencesPath(home?: string): string;
|
|
6
|
+
/** Startup: read the file, and keep choices made from here on in it. */
|
|
7
|
+
export declare function usePreferences(path?: string): void;
|
|
8
|
+
/** The remembered choices; empty before startup names the file. */
|
|
9
|
+
export declare function preferences(): Preferences;
|
|
10
|
+
/** Remember a choice. Returns false when no file was named. The file is
|
|
11
|
+
* re-read before the write, so another process's choice is kept. */
|
|
12
|
+
export declare function setPreference<K extends keyof Preferences>(key: K, value: NonNullable<Preferences[K]>): boolean;
|
|
13
|
+
/** Tests: back to the state before startup. */
|
|
14
|
+
export declare function resetPreferences(): void;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.40.6 — the choices kiso remembers for you, in
|
|
3
|
+
* `<KISO_HOME>/preferences.json`.
|
|
4
|
+
*
|
|
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
|
|
8
|
+
* (0600, tmp + rename), and read back at start-up. A missing or unreadable
|
|
9
|
+
* file is an empty one; an unknown value is ignored rather than guessed.
|
|
10
|
+
*
|
|
11
|
+
* Nothing is read until the CLI's startup names the file
|
|
12
|
+
* (`usePreferences`) — the same rule as learned-windows.ts, so in-process
|
|
13
|
+
* tests never read a home directory.
|
|
14
|
+
*/
|
|
15
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { dirname, join } from "node:path";
|
|
17
|
+
import { kisoHome } from "./state.js";
|
|
18
|
+
let prefs = null;
|
|
19
|
+
let prefsPath = null;
|
|
20
|
+
export function preferencesPath(home = kisoHome()) {
|
|
21
|
+
return join(home, "preferences.json");
|
|
22
|
+
}
|
|
23
|
+
function read(path) {
|
|
24
|
+
try {
|
|
25
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
26
|
+
return raw.thinking === "shown" || raw.thinking === "hidden" ? { thinking: raw.thinking } : {};
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return {};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Startup: read the file, and keep choices made from here on in it. */
|
|
33
|
+
export function usePreferences(path = preferencesPath()) {
|
|
34
|
+
prefsPath = path;
|
|
35
|
+
prefs = read(path);
|
|
36
|
+
}
|
|
37
|
+
/** The remembered choices; empty before startup names the file. */
|
|
38
|
+
export function preferences() {
|
|
39
|
+
return prefs ?? {};
|
|
40
|
+
}
|
|
41
|
+
/** Remember a choice. Returns false when no file was named. The file is
|
|
42
|
+
* re-read before the write, so another process's choice is kept. */
|
|
43
|
+
export function setPreference(key, value) {
|
|
44
|
+
const path = prefsPath;
|
|
45
|
+
if (path === null)
|
|
46
|
+
return false;
|
|
47
|
+
const next = { ...read(path), [key]: value };
|
|
48
|
+
prefs = next;
|
|
49
|
+
try {
|
|
50
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
51
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
52
|
+
writeFileSync(tmp, `${JSON.stringify(next, null, 2)}\n`, { mode: 0o600 });
|
|
53
|
+
renameSync(tmp, path);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// an unwritable home: the choice still holds for this process
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
/** Tests: back to the state before startup. */
|
|
61
|
+
export function resetPreferences() {
|
|
62
|
+
prefs = null;
|
|
63
|
+
prefsPath = null;
|
|
64
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.40.6 — `/settings`: what kiso is running with, where each value came
|
|
3
|
+
* from, and how to change it.
|
|
4
|
+
*
|
|
5
|
+
* The owner, 2026-09-23, asked whether kiso has a help for what can be
|
|
6
|
+
* configured. `/help` lists the commands and `?` the keys; the settings
|
|
7
|
+
* lived only in docs/configuration.md and in files the user had to open.
|
|
8
|
+
*
|
|
9
|
+
* READ-ONLY by design: the config file stays the human's. The layers are
|
|
10
|
+
* the documented precedence — flag > env > project config > user config >
|
|
11
|
+
* default — and a value that no layer explains was set in this session
|
|
12
|
+
* (`/mode`, `/model`). Pure: every input is passed in, so each row is
|
|
13
|
+
* testable without a session.
|
|
14
|
+
*/
|
|
15
|
+
import type { KisoConfig } from "./config.js";
|
|
16
|
+
export interface SettingsInput {
|
|
17
|
+
readonly user: KisoConfig | null;
|
|
18
|
+
readonly project: KisoConfig | null;
|
|
19
|
+
readonly env: Readonly<Record<string, string | undefined>>;
|
|
20
|
+
/** the --mode / --model values on the command line, when given */
|
|
21
|
+
readonly modeFlag?: string;
|
|
22
|
+
readonly modelFlag?: string;
|
|
23
|
+
/** what is live now */
|
|
24
|
+
readonly mode: string;
|
|
25
|
+
readonly model: {
|
|
26
|
+
readonly label: string;
|
|
27
|
+
readonly profile: string | null;
|
|
28
|
+
readonly switched: boolean;
|
|
29
|
+
};
|
|
30
|
+
readonly ground: string;
|
|
31
|
+
readonly floorOn: boolean;
|
|
32
|
+
readonly window: string;
|
|
33
|
+
readonly thinkingHidden: boolean;
|
|
34
|
+
readonly thinkingRemembered: boolean;
|
|
35
|
+
readonly version: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function settingsRows(i: SettingsInput): string[];
|
package/dist/settings.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
function modeRow(i) {
|
|
2
|
+
const change = "/mode or shift+tab; \"mode\" in ~/.kiso/config.json";
|
|
3
|
+
const from = i.modeFlag === i.mode
|
|
4
|
+
? "--mode"
|
|
5
|
+
: i.env.KISO_MODE === i.mode
|
|
6
|
+
? "env KISO_MODE"
|
|
7
|
+
: i.project?.mode === i.mode
|
|
8
|
+
? "project config"
|
|
9
|
+
: i.user?.mode === i.mode
|
|
10
|
+
? "user config"
|
|
11
|
+
: i.mode === "default"
|
|
12
|
+
? "default"
|
|
13
|
+
: "set in this session";
|
|
14
|
+
return { name: "mode", value: i.mode, from, change };
|
|
15
|
+
}
|
|
16
|
+
function modelRow(i) {
|
|
17
|
+
const change = "/model; \"model\" in ~/.kiso/config.json";
|
|
18
|
+
const p = i.model.profile;
|
|
19
|
+
const from = i.model.switched
|
|
20
|
+
? "set in this session"
|
|
21
|
+
: i.modelFlag !== undefined
|
|
22
|
+
? "--model"
|
|
23
|
+
: p !== null && i.project?.model === p
|
|
24
|
+
? "project config"
|
|
25
|
+
: p !== null && i.user?.model === p
|
|
26
|
+
? "user config"
|
|
27
|
+
: i.env.OPENAI_API_KEY !== undefined && p === null
|
|
28
|
+
? "env OPENAI_API_KEY"
|
|
29
|
+
: "default";
|
|
30
|
+
return { name: "model", value: i.model.label, from, change };
|
|
31
|
+
}
|
|
32
|
+
function themeRow(i) {
|
|
33
|
+
const change = "\"theme\": \"dark\" | \"light\" in ~/.kiso/config.json; KISO_THEME for one run";
|
|
34
|
+
if (i.env.KISO_THEME !== undefined)
|
|
35
|
+
return { name: "theme", value: i.env.KISO_THEME, from: "env KISO_THEME", change };
|
|
36
|
+
if (i.user?.theme !== undefined)
|
|
37
|
+
return { name: "theme", value: i.user.theme, from: "user config", change };
|
|
38
|
+
return { name: "theme", value: i.ground, from: "the terminal (detected)", change };
|
|
39
|
+
}
|
|
40
|
+
function layered(i, key) {
|
|
41
|
+
if (i.project?.[key] !== undefined)
|
|
42
|
+
return { value: i.project[key], from: "project config" };
|
|
43
|
+
if (i.user?.[key] !== undefined)
|
|
44
|
+
return { value: i.user[key], from: "user config" };
|
|
45
|
+
return { value: undefined, from: "default" };
|
|
46
|
+
}
|
|
47
|
+
export function settingsRows(i) {
|
|
48
|
+
const trust = layered(i, "projectTrust");
|
|
49
|
+
const auto = i.env.KISO_AUTO_COMPACT !== undefined ? { value: i.env.KISO_AUTO_COMPACT, from: "env KISO_AUTO_COMPACT" } : layered(i, "autoCompact");
|
|
50
|
+
const rows = [
|
|
51
|
+
modelRow(i),
|
|
52
|
+
modeRow(i),
|
|
53
|
+
themeRow(i),
|
|
54
|
+
{
|
|
55
|
+
name: "floor",
|
|
56
|
+
value: i.floorOn ? "on — irrecoverable deletes are refused in every mode" : "off",
|
|
57
|
+
from: i.user?.floor !== undefined ? "user config" : "default",
|
|
58
|
+
change: "\"floor\": \"off\" in ~/.kiso/config.json (user config only)",
|
|
59
|
+
},
|
|
60
|
+
{ name: "window", value: i.window, from: "the window chain (see /status)", change: "\"contextWindow\" on the profile; KISO_CONTEXT_WINDOW for one run" },
|
|
61
|
+
{ name: "compaction", value: "in-run: past half the window at a phase end, past 80% at once", from: "built in", change: "/compact on demand" },
|
|
62
|
+
{
|
|
63
|
+
name: "auto-compact",
|
|
64
|
+
value: auto.value === undefined ? "off" : typeof auto.value === "object" ? `at ${auto.value.thresholdRatio} of the window, at a run's start` : String(auto.value),
|
|
65
|
+
from: auto.from,
|
|
66
|
+
change: "\"autoCompact\" in config; KISO_AUTO_COMPACT",
|
|
67
|
+
},
|
|
68
|
+
{ name: "project trust", value: trust.value ?? "ask", from: trust.from, change: "\"projectTrust\": \"ask\" | \"never\" in config" },
|
|
69
|
+
{
|
|
70
|
+
name: "thinking",
|
|
71
|
+
value: i.thinkingHidden ? "hidden — one line per block" : "shown",
|
|
72
|
+
from: i.thinkingRemembered ? "ctrl+t (remembered)" : "default",
|
|
73
|
+
change: "ctrl+t",
|
|
74
|
+
},
|
|
75
|
+
{ name: "version", value: i.version, from: "running", change: "kiso update" },
|
|
76
|
+
];
|
|
77
|
+
const width = Math.max(...rows.map((r) => r.name.length)) + 2;
|
|
78
|
+
return rows.map((r) => `${r.name.padEnd(width)}${r.value}\n${" ".repeat(width)}from ${r.from} · change: ${r.change}`);
|
|
79
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** The version of the kiso installed where this one was loaded from, read
|
|
2
|
+
* now — null on any failure, never a guess. KISO_INSTALLED_PACKAGE_JSON
|
|
3
|
+
* names another file: the test rigs' knob (like KISO_FAUX_SCRIPT), so an
|
|
4
|
+
* end-to-end run can "upgrade" underneath a live session without touching
|
|
5
|
+
* the checkout's own package.json. */
|
|
6
|
+
export declare function installedVersion(pkgPath?: string): string | null;
|
|
7
|
+
/** The transcript notice, once per installed version that differs from the
|
|
8
|
+
* running one (a newer install, or a rollback); null otherwise. */
|
|
9
|
+
export declare function staleVersionNotice(installed: string | null, running: string, sessionId: string): string | null;
|
|
10
|
+
/** /status's version line: the running version, and the installed one when
|
|
11
|
+
* they differ. */
|
|
12
|
+
export declare function versionStatusLine(installed: string | null, running: string): string;
|
|
13
|
+
/** Tests: forget which version was noticed. */
|
|
14
|
+
export declare function resetStaleVersionNotice(): void;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 0.40.5 — a session says when the kiso on disk is not the kiso it runs.
|
|
3
|
+
*
|
|
4
|
+
* The owner, 2026-09-23: "I am on 0.40.3 — why does edit_file still fail?"
|
|
5
|
+
* The session's process had started at 13:03 on 0.40.2; 0.40.3 was
|
|
6
|
+
* installed at ~14:05. The process kept the code it loaded, so its
|
|
7
|
+
* edit_file still refused overlapping hunks, while `kiso --version` in
|
|
8
|
+
* another shell printed the version ON DISK. Nothing in the session said
|
|
9
|
+
* otherwise. A process that loads a module lazily after an upgrade (a
|
|
10
|
+
* provider on its first /model switch) would also mix the new version with
|
|
11
|
+
* the old — the notice is the cue to restart before that.
|
|
12
|
+
*
|
|
13
|
+
* `VERSION` (state.ts) is read once at start-up from the package.json next
|
|
14
|
+
* to the build; a global install replaces that file, so reading it AGAIN
|
|
15
|
+
* sees what a new start would run. One small read per turn and per
|
|
16
|
+
* /status; no timer, no watcher, no network.
|
|
17
|
+
*/
|
|
18
|
+
import { readFileSync } from "node:fs";
|
|
19
|
+
import { dirname, join } from "node:path";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
21
|
+
/** The version of the kiso installed where this one was loaded from, read
|
|
22
|
+
* now — null on any failure, never a guess. KISO_INSTALLED_PACKAGE_JSON
|
|
23
|
+
* names another file: the test rigs' knob (like KISO_FAUX_SCRIPT), so an
|
|
24
|
+
* end-to-end run can "upgrade" underneath a live session without touching
|
|
25
|
+
* the checkout's own package.json. */
|
|
26
|
+
export function installedVersion(pkgPath = process.env.KISO_INSTALLED_PACKAGE_JSON ?? join(dirname(fileURLToPath(import.meta.url)), "..", "package.json")) {
|
|
27
|
+
try {
|
|
28
|
+
const v = JSON.parse(readFileSync(pkgPath, "utf8")).version;
|
|
29
|
+
return typeof v === "string" && v !== "" ? v : null;
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
let lastNoticed = null;
|
|
36
|
+
/** The transcript notice, once per installed version that differs from the
|
|
37
|
+
* running one (a newer install, or a rollback); null otherwise. */
|
|
38
|
+
export function staleVersionNotice(installed, running, sessionId) {
|
|
39
|
+
if (installed === null || installed === running || running === "?" || installed === lastNoticed)
|
|
40
|
+
return null;
|
|
41
|
+
lastNoticed = installed;
|
|
42
|
+
return `✦ kiso ${installed} is installed — this session runs ${running}; exit and resume it (kiso resume ${sessionId}) to use it`;
|
|
43
|
+
}
|
|
44
|
+
/** /status's version line: the running version, and the installed one when
|
|
45
|
+
* they differ. */
|
|
46
|
+
export function versionStatusLine(installed, running) {
|
|
47
|
+
return installed === null || installed === running ? `version ${running}` : `version ${running} (running) · ${installed} installed — restart to use it`;
|
|
48
|
+
}
|
|
49
|
+
/** Tests: forget which version was noticed. */
|
|
50
|
+
export function resetStaleVersionNotice() {
|
|
51
|
+
lastNoticed = null;
|
|
52
|
+
}
|
package/dist/state.d.ts
CHANGED
|
@@ -295,6 +295,16 @@ export declare const queuedSwitchLines: string[];
|
|
|
295
295
|
/** E1: the extensions loaded by makeAgent — their names feed the banner. */
|
|
296
296
|
/** 0.40.0: whether the catastrophe floor is on (floor.ts) — the user
|
|
297
297
|
* config's `floor`, read where the chain is assembled. */
|
|
298
|
+
/** 0.40.6: what /settings needs to name each value's layer — the two config
|
|
299
|
+
* files as read, the command-line flags as given, and whether /model
|
|
300
|
+
* changed the binding in this session. */
|
|
301
|
+
export declare const settingsLayers: {
|
|
302
|
+
user: import("./config.js").KisoConfig | null;
|
|
303
|
+
project: import("./config.js").KisoConfig | null;
|
|
304
|
+
modeFlag: string | undefined;
|
|
305
|
+
modelFlag: string | undefined;
|
|
306
|
+
modelSwitched: boolean;
|
|
307
|
+
};
|
|
298
308
|
export declare let floorOn: boolean;
|
|
299
309
|
export declare function setFloorOn(value: boolean): void;
|
|
300
310
|
/** 0.40.0: the calls a saved allow never carries (protected-writes.ts) —
|
package/dist/state.js
CHANGED
|
@@ -397,6 +397,10 @@ export const queuedSwitchLines = [];
|
|
|
397
397
|
/** E1: the extensions loaded by makeAgent — their names feed the banner. */
|
|
398
398
|
/** 0.40.0: whether the catastrophe floor is on (floor.ts) — the user
|
|
399
399
|
* config's `floor`, read where the chain is assembled. */
|
|
400
|
+
/** 0.40.6: what /settings needs to name each value's layer — the two config
|
|
401
|
+
* files as read, the command-line flags as given, and whether /model
|
|
402
|
+
* changed the binding in this session. */
|
|
403
|
+
export const settingsLayers = { user: null, project: null, modeFlag: undefined, modelFlag: undefined, modelSwitched: false };
|
|
400
404
|
export let floorOn = true;
|
|
401
405
|
export function setFloorOn(value) {
|
|
402
406
|
floorOn = value;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-code",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.6",
|
|
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.40.
|
|
22
|
-
"@vincemakes/kiso-core": "0.40.
|
|
23
|
-
"@vincemakes/kiso-evals": "0.40.
|
|
24
|
-
"@vincemakes/kiso-mcp-ext": "0.40.
|
|
25
|
-
"@vincemakes/kiso-provider-anthropic": "0.40.
|
|
26
|
-
"@vincemakes/kiso-provider-openai": "0.40.
|
|
27
|
-
"@vincemakes/kiso-provider-openai-responses": "0.40.
|
|
28
|
-
"@vincemakes/kiso-runtime": "0.40.
|
|
29
|
-
"@vincemakes/kiso-skills-ext": "0.40.
|
|
30
|
-
"@vincemakes/kiso-subagent-ext": "0.40.
|
|
31
|
-
"@vincemakes/kiso-task-ext": "0.40.
|
|
32
|
-
"@vincemakes/kiso-tools-node": "0.40.
|
|
33
|
-
"@vincemakes/kiso-tui": "0.40.
|
|
34
|
-
"@vincemakes/kiso-tui-cells": "0.40.
|
|
21
|
+
"@vincemakes/kiso-ask-ext": "0.40.6",
|
|
22
|
+
"@vincemakes/kiso-core": "0.40.6",
|
|
23
|
+
"@vincemakes/kiso-evals": "0.40.6",
|
|
24
|
+
"@vincemakes/kiso-mcp-ext": "0.40.6",
|
|
25
|
+
"@vincemakes/kiso-provider-anthropic": "0.40.6",
|
|
26
|
+
"@vincemakes/kiso-provider-openai": "0.40.6",
|
|
27
|
+
"@vincemakes/kiso-provider-openai-responses": "0.40.6",
|
|
28
|
+
"@vincemakes/kiso-runtime": "0.40.6",
|
|
29
|
+
"@vincemakes/kiso-skills-ext": "0.40.6",
|
|
30
|
+
"@vincemakes/kiso-subagent-ext": "0.40.6",
|
|
31
|
+
"@vincemakes/kiso-task-ext": "0.40.6",
|
|
32
|
+
"@vincemakes/kiso-tools-node": "0.40.6",
|
|
33
|
+
"@vincemakes/kiso-tui": "0.40.6",
|
|
34
|
+
"@vincemakes/kiso-tui-cells": "0.40.6"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "^26.1.2",
|