@vincemakes/kiso-code 0.34.0 → 0.36.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/auth/adapter-options.d.ts +22 -0
- package/dist/auth/adapter-options.js +52 -0
- package/dist/auth/credentials.d.ts +23 -0
- package/dist/auth/credentials.js +39 -9
- package/dist/builtin.d.ts +6 -1
- package/dist/builtin.js +7 -2
- package/dist/config.js +42 -20
- package/dist/dispatch.js +6 -13
- package/dist/index.d.ts +1 -1
- package/dist/index.js +85 -22
- package/dist/mode.d.ts +10 -1
- package/dist/mode.js +15 -6
- package/dist/state.d.ts +10 -0
- package/dist/state.js +16 -1
- package/package.json +16 -16
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ModelProfile } from "../config.js";
|
|
2
|
+
/** The credential shape both call sites can produce: `authForProfile`'s
|
|
3
|
+
* return value, and the startup path's already-narrowed `resolved`. */
|
|
4
|
+
export type AdapterAuth = {
|
|
5
|
+
readonly type: "oauth";
|
|
6
|
+
readonly providerId: string;
|
|
7
|
+
} | {
|
|
8
|
+
readonly type: "api-key";
|
|
9
|
+
readonly apiKey: string;
|
|
10
|
+
};
|
|
11
|
+
/** Exactly the runtime `buildAdapter` option set. */
|
|
12
|
+
export interface AdapterOptions {
|
|
13
|
+
readonly apiKey?: string;
|
|
14
|
+
readonly baseUrl?: string;
|
|
15
|
+
readonly promptCaching?: boolean;
|
|
16
|
+
readonly oauth?: () => Promise<{
|
|
17
|
+
readonly access: string;
|
|
18
|
+
readonly accountId: string;
|
|
19
|
+
}>;
|
|
20
|
+
readonly promptCacheKey?: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function adapterOptionsFor(profile: ModelProfile, auth: AdapterAuth, sessionId?: string): AdapterOptions;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Astra F1 (P0) — THE ONE PLACE THE ADAPTER'S WIRE CONFIG IS BUILT.
|
|
3
|
+
*
|
|
4
|
+
* The P0's mechanism is a single sentence: the CLI hands the adapter an
|
|
5
|
+
* EXPLICIT endpoint, so the provider SDKs never read `ANTHROPIC_BASE_URL` /
|
|
6
|
+
* `OPENAI_BASE_URL` for themselves while `authForProfile` has already
|
|
7
|
+
* chosen the STORED VENDOR KEY for the vendor's own origin.
|
|
8
|
+
*
|
|
9
|
+
* That sentence had no home. It was a spread written out twice — at startup
|
|
10
|
+
* in index.ts and on the `/model` switch in dispatch.ts — which is F1's own
|
|
11
|
+
* defect class: one rule, two copies, and the copies drift. The first fix
|
|
12
|
+
* for this finding edited both copies. This gives the rule somewhere to
|
|
13
|
+
* live, and a test somewhere to point.
|
|
14
|
+
*
|
|
15
|
+
* The extraction found the two sites had ALREADY drifted:
|
|
16
|
+
*
|
|
17
|
+
* - `promptCacheKey` was passed at startup whenever the session had an
|
|
18
|
+
* id, but on `/model` only for an OAuth profile. It reaches the wire in
|
|
19
|
+
* the openai-responses adapter alone (runtime resolveAdapter), where it
|
|
20
|
+
* becomes `prompt_cache_key`. So a first-party Responses profile got a
|
|
21
|
+
* cache key when you started with it and none when you switched to it —
|
|
22
|
+
* the same session, two cache lanes, decided by how you arrived. The
|
|
23
|
+
* startup rule is the one kept: the cache lane is the SESSION (OR-1).
|
|
24
|
+
* - `streamIdleMs` is set at startup and not on `/model`. It is NOT an
|
|
25
|
+
* adapter option — it is an agent-definition field the runtime reads —
|
|
26
|
+
* so it is out of this function's scope and stays where it is, noted
|
|
27
|
+
* here so the next reader does not think it was missed.
|
|
28
|
+
*/
|
|
29
|
+
import { effectiveBaseUrl } from "./credentials.js";
|
|
30
|
+
import { oauthTokenThunk } from "./token.js";
|
|
31
|
+
export function adapterOptionsFor(profile, auth, sessionId) {
|
|
32
|
+
// OR-1: exactly one sign-in shape reaches the adapter. An OAuth profile
|
|
33
|
+
// has no key to pass — it passes the thunk the adapter re-resolves per
|
|
34
|
+
// request instead. PH-1c (PH-F19): a keyless profile is an
|
|
35
|
+
// unauthenticated endpoint and its placeholder satisfies the SDK's ctor.
|
|
36
|
+
const credential = auth.type === "oauth" ? { oauth: oauthTokenThunk(auth.providerId) } : { apiKey: auth.apiKey };
|
|
37
|
+
// Astra F1 (P0): ALWAYS EXPLICIT. Passing nothing let the SDK read its
|
|
38
|
+
// own environment variable, and a profile with no baseUrl then sent the
|
|
39
|
+
// stored vendor key wherever that variable pointed.
|
|
40
|
+
const url = effectiveBaseUrl(profile.kind, profile.baseUrl);
|
|
41
|
+
return {
|
|
42
|
+
...credential,
|
|
43
|
+
...(url !== undefined ? { baseUrl: url } : {}),
|
|
44
|
+
// OR-1: the ChatGPT backend's cache lane is the SESSION — one
|
|
45
|
+
// conversation's requests share a key, different conversations never
|
|
46
|
+
// do. The one entry point with no session id is `kiso sessions`, a
|
|
47
|
+
// read-only listing that streams nothing, so its absence costs no
|
|
48
|
+
// cache.
|
|
49
|
+
...(sessionId !== undefined ? { promptCacheKey: sessionId } : {}),
|
|
50
|
+
...(profile.promptCaching !== undefined ? { promptCaching: profile.promptCaching } : {}),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -23,6 +23,29 @@ export declare class AuthError extends Error {
|
|
|
23
23
|
export declare const KNOWN_PROVIDERS: readonly string[];
|
|
24
24
|
/** The providers whose sign-in is an OAuth flow rather than a key. */
|
|
25
25
|
export declare const OAUTH_PROVIDERS: readonly string[];
|
|
26
|
+
/**
|
|
27
|
+
* Astra F1 (P0) — THE ONE RESOLVED EFFECTIVE ENDPOINT.
|
|
28
|
+
*
|
|
29
|
+
* `providerIdOf` read an ABSENT `baseUrl` as the vendor's own endpoint and
|
|
30
|
+
* returned the vendor id, so `authForProfile` handed back the STORED vendor
|
|
31
|
+
* key. Correct in isolation. But the adapter factories passed `baseURL` to the
|
|
32
|
+
* SDK only when the profile NAMED one, and with none named the Anthropic and
|
|
33
|
+
* OpenAI SDKs read `ANTHROPIC_BASE_URL` / `OPENAI_BASE_URL` from the
|
|
34
|
+
* environment themselves — so the saved official key went to whatever the
|
|
35
|
+
* environment named.
|
|
36
|
+
*
|
|
37
|
+
* Two sides disagreed about what "no baseUrl" meant. THE FIX IS TO RESOLVE IT
|
|
38
|
+
* ONCE, here, and give both sides the same answer: the credential resolver
|
|
39
|
+
* decides which key may go, the adapter is handed an EXPLICIT url so the SDK
|
|
40
|
+
* never consults its environment.
|
|
41
|
+
*
|
|
42
|
+
* 0.32.2's R1 bound the explicit-URL path. This is the absent-URL path, which
|
|
43
|
+
* is the common configuration.
|
|
44
|
+
*/
|
|
45
|
+
export declare const VENDOR_DEFAULT: Readonly<Record<string, string>>;
|
|
46
|
+
/** The endpoint a profile ACTUALLY talks to: its own, or the vendor's
|
|
47
|
+
* default for its kind. Never the environment's — that is the defect. */
|
|
48
|
+
export declare function effectiveBaseUrl(kind: string, baseUrl?: string): string | undefined;
|
|
26
49
|
/** The provider identity a profile's credential is stored under, or null
|
|
27
50
|
* for an origin nobody recognizes (custom: env var only). */
|
|
28
51
|
export declare function providerIdOf(kind: string, baseUrl?: string): string | null;
|
package/dist/auth/credentials.js
CHANGED
|
@@ -50,6 +50,35 @@ const CHATGPT_ORIGIN = "https://chatgpt.com";
|
|
|
50
50
|
* the dialect it speaks. */
|
|
51
51
|
const ANTHROPIC_ORIGIN = "https://api.anthropic.com";
|
|
52
52
|
const OPENAI_ORIGIN = "https://api.openai.com";
|
|
53
|
+
/**
|
|
54
|
+
* Astra F1 (P0) — THE ONE RESOLVED EFFECTIVE ENDPOINT.
|
|
55
|
+
*
|
|
56
|
+
* `providerIdOf` read an ABSENT `baseUrl` as the vendor's own endpoint and
|
|
57
|
+
* returned the vendor id, so `authForProfile` handed back the STORED vendor
|
|
58
|
+
* key. Correct in isolation. But the adapter factories passed `baseURL` to the
|
|
59
|
+
* SDK only when the profile NAMED one, and with none named the Anthropic and
|
|
60
|
+
* OpenAI SDKs read `ANTHROPIC_BASE_URL` / `OPENAI_BASE_URL` from the
|
|
61
|
+
* environment themselves — so the saved official key went to whatever the
|
|
62
|
+
* environment named.
|
|
63
|
+
*
|
|
64
|
+
* Two sides disagreed about what "no baseUrl" meant. THE FIX IS TO RESOLVE IT
|
|
65
|
+
* ONCE, here, and give both sides the same answer: the credential resolver
|
|
66
|
+
* decides which key may go, the adapter is handed an EXPLICIT url so the SDK
|
|
67
|
+
* never consults its environment.
|
|
68
|
+
*
|
|
69
|
+
* 0.32.2's R1 bound the explicit-URL path. This is the absent-URL path, which
|
|
70
|
+
* is the common configuration.
|
|
71
|
+
*/
|
|
72
|
+
export const VENDOR_DEFAULT = {
|
|
73
|
+
anthropic: ANTHROPIC_ORIGIN,
|
|
74
|
+
"openai-compat": `${OPENAI_ORIGIN}/v1`,
|
|
75
|
+
"openai-responses": `${OPENAI_ORIGIN}/v1`,
|
|
76
|
+
};
|
|
77
|
+
/** The endpoint a profile ACTUALLY talks to: its own, or the vendor's
|
|
78
|
+
* default for its kind. Never the environment's — that is the defect. */
|
|
79
|
+
export function effectiveBaseUrl(kind, baseUrl) {
|
|
80
|
+
return baseUrl ?? VENDOR_DEFAULT[kind];
|
|
81
|
+
}
|
|
53
82
|
/** The provider identity a profile's credential is stored under, or null
|
|
54
83
|
* for an origin nobody recognizes (custom: env var only). */
|
|
55
84
|
export function providerIdOf(kind, baseUrl) {
|
|
@@ -74,23 +103,24 @@ export function providerIdOf(kind, baseUrl) {
|
|
|
74
103
|
// The compat kind was already right — an unrecognized origin resolves
|
|
75
104
|
// to null and the env var pays — so this makes the other two agree with
|
|
76
105
|
// the one that had the rule.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
106
|
+
//
|
|
107
|
+
// Astra F1: THE SAME RESOLVER THE ADAPTER USES. An absent baseUrl used to
|
|
108
|
+
// be a special case here — three `if (baseUrl === undefined) return "<the
|
|
109
|
+
// vendor>"` branches — and a DIFFERENT special case at the adapter, where
|
|
110
|
+
// it meant "let the SDK read the environment". Two copies of one rule is
|
|
111
|
+
// how the two sides came to disagree. Resolved once, this function is left
|
|
112
|
+
// with the single question it exists to ask: does that origin belong to
|
|
113
|
+
// the vendor?
|
|
114
|
+
const origin = originOf(effectiveBaseUrl(kind, baseUrl));
|
|
115
|
+
if (kind === "anthropic")
|
|
81
116
|
return origin === ANTHROPIC_ORIGIN ? "anthropic" : null;
|
|
82
|
-
}
|
|
83
117
|
if (kind === "openai-responses") {
|
|
84
|
-
if (baseUrl === undefined)
|
|
85
|
-
return "openai"; // the vendor's own default endpoint
|
|
86
118
|
if (origin === CHATGPT_ORIGIN)
|
|
87
119
|
return "chatgpt";
|
|
88
120
|
return origin === OPENAI_ORIGIN ? "openai" : null;
|
|
89
121
|
}
|
|
90
122
|
if (kind !== "openai-compat")
|
|
91
123
|
return null;
|
|
92
|
-
if (baseUrl === undefined)
|
|
93
|
-
return "openai";
|
|
94
124
|
return origin === null ? null : (ORIGIN_TO_PROVIDER[origin] ?? null);
|
|
95
125
|
}
|
|
96
126
|
function originOf(baseUrl) {
|
package/dist/builtin.d.ts
CHANGED
|
@@ -5,4 +5,9 @@ export declare function builtInLayer(user: readonly KisoExtension[], project: re
|
|
|
5
5
|
* bridge exists (an interactive TTY). No bridge, no fourth built-in:
|
|
6
6
|
* a headless session never pays the rent for a question nobody could
|
|
7
7
|
* answer, and its tool table cannot mention ask_user. */
|
|
8
|
-
ask?: AskUI
|
|
8
|
+
ask?: AskUI,
|
|
9
|
+
/** Astra F7: the env-var NAMES the configured profiles authenticate with.
|
|
10
|
+
* The mcp extension spawns its stdio children while it is being
|
|
11
|
+
* constructed, so the names have to arrive here — after construction is
|
|
12
|
+
* too late. Only the config knows them; nothing else can. */
|
|
13
|
+
secretEnvNames?: readonly string[]): Promise<readonly KisoExtension[]>;
|
package/dist/builtin.js
CHANGED
|
@@ -30,8 +30,13 @@ export async function builtInLayer(user, project,
|
|
|
30
30
|
* bridge exists (an interactive TTY). No bridge, no fourth built-in:
|
|
31
31
|
* a headless session never pays the rent for a question nobody could
|
|
32
32
|
* answer, and its tool table cannot mention ask_user. */
|
|
33
|
-
ask
|
|
34
|
-
|
|
33
|
+
ask,
|
|
34
|
+
/** Astra F7: the env-var NAMES the configured profiles authenticate with.
|
|
35
|
+
* The mcp extension spawns its stdio children while it is being
|
|
36
|
+
* constructed, so the names have to arrive here — after construction is
|
|
37
|
+
* too late. Only the config knows them; nothing else can. */
|
|
38
|
+
secretEnvNames = []) {
|
|
39
|
+
const all = await Promise.all([createMcp({ secretEnvNames }), createSkills(), createSubagent(), ...(ask === undefined ? [] : [createAsk(ask)])]);
|
|
35
40
|
const shadowed = all.filter((b) => user.some((u) => u.name === b.name));
|
|
36
41
|
for (const s of shadowed) {
|
|
37
42
|
console.error(`[extensions] user extension "${s.name}" shadows the built-in — the built-in is not loaded`);
|
package/dist/config.js
CHANGED
|
@@ -296,31 +296,53 @@ export function resolveModel(modelFlag, merged) {
|
|
|
296
296
|
return resolveProfile(modelFlag, p);
|
|
297
297
|
}
|
|
298
298
|
// env beats config: a key in the environment names the provider.
|
|
299
|
+
//
|
|
300
|
+
// Astra F2: the credential goes through authForProfile like every other
|
|
301
|
+
// route. This returned process.env.OPENAI_API_KEY directly, so the two
|
|
302
|
+
// ways into the same adapter disagreed about which key a profile uses.
|
|
303
|
+
// The safety property held by accident — the env key is not the stored
|
|
304
|
+
// one — and an accident is not a rule. Now: the stored key at the
|
|
305
|
+
// vendor's origin, the env key at a custom one, and a stored vendor key
|
|
306
|
+
// is never forwarded to a custom environment URL.
|
|
307
|
+
//
|
|
308
|
+
// The env var is folded into the profile EXPLICITLY, so the resolved
|
|
309
|
+
// endpoint is the profile's and the SDK never reads it again (F1).
|
|
299
310
|
if (process.env.OPENAI_API_KEY !== undefined) {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
...(process.env.OPENAI_BASE_URL !== undefined ? { baseUrl: process.env.OPENAI_BASE_URL } : {}),
|
|
306
|
-
apiKeyEnv: "OPENAI_API_KEY",
|
|
307
|
-
},
|
|
308
|
-
apiKey: process.env.OPENAI_API_KEY,
|
|
311
|
+
const profile = {
|
|
312
|
+
kind: "openai-compat",
|
|
313
|
+
model: process.env.OPENAI_MODEL ?? "gpt-4o",
|
|
314
|
+
...(process.env.OPENAI_BASE_URL !== undefined ? { baseUrl: process.env.OPENAI_BASE_URL } : {}),
|
|
315
|
+
apiKeyEnv: "OPENAI_API_KEY",
|
|
309
316
|
};
|
|
317
|
+
const auth = authForProfile(process.env.OPENAI_MODEL ?? "gpt-4o", profile);
|
|
318
|
+
// The same total shape the config route returns (resolveProfile).
|
|
319
|
+
// The `oauth` arm is unreachable from HERE — authForProfile returns
|
|
320
|
+
// oauth only for an openai-responses profile and this route builds
|
|
321
|
+
// an openai-compat one — but writing the union out beats a fallback
|
|
322
|
+
// to the raw env var, which is the very disagreement F2 removes.
|
|
323
|
+
return auth.type === "oauth"
|
|
324
|
+
? { name: process.env.OPENAI_MODEL ?? "gpt-4o", profile, oauthProviderId: auth.providerId }
|
|
325
|
+
: { name: process.env.OPENAI_MODEL ?? "gpt-4o", profile, apiKey: auth.apiKey };
|
|
310
326
|
}
|
|
311
327
|
if (process.env.ANTHROPIC_API_KEY !== undefined) {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
...(process.env.ANTHROPIC_BASE_URL !== undefined ? { baseUrl: process.env.ANTHROPIC_BASE_URL } : {}),
|
|
321
|
-
},
|
|
322
|
-
apiKey: process.env.ANTHROPIC_API_KEY,
|
|
328
|
+
// Astra F2, the sibling. Same rule, same reason.
|
|
329
|
+
const profile = {
|
|
330
|
+
kind: "anthropic",
|
|
331
|
+
model: process.env.ANTHROPIC_MODEL ?? "claude-sonnet-5",
|
|
332
|
+
apiKeyEnv: "ANTHROPIC_API_KEY",
|
|
333
|
+
// PH-1c (finding PH-F19): symmetric with OPENAI_BASE_URL —
|
|
334
|
+
// proxies and compat gateways serve the anthropic dialect too.
|
|
335
|
+
...(process.env.ANTHROPIC_BASE_URL !== undefined ? { baseUrl: process.env.ANTHROPIC_BASE_URL } : {}),
|
|
323
336
|
};
|
|
337
|
+
const auth = authForProfile(process.env.ANTHROPIC_MODEL ?? "claude-sonnet-5", profile);
|
|
338
|
+
// The same total shape the config route returns (resolveProfile).
|
|
339
|
+
// The `oauth` arm is unreachable from HERE — authForProfile returns
|
|
340
|
+
// oauth only for an openai-responses profile and this route builds
|
|
341
|
+
// an anthropic one — but writing the union out beats a fallback
|
|
342
|
+
// to the raw env var, which is the very disagreement F2 removes.
|
|
343
|
+
return auth.type === "oauth"
|
|
344
|
+
? { name: process.env.ANTHROPIC_MODEL ?? "claude-sonnet-5", profile, oauthProviderId: auth.providerId }
|
|
345
|
+
: { name: process.env.ANTHROPIC_MODEL ?? "claude-sonnet-5", profile, apiKey: auth.apiKey };
|
|
324
346
|
}
|
|
325
347
|
// config (project wins over user) names a model; default is faux.
|
|
326
348
|
const configured = merged.model;
|
package/dist/dispatch.js
CHANGED
|
@@ -9,6 +9,7 @@ import { buildAdapter, lookupModelMetadata, resolveContinuationScope, resolveRea
|
|
|
9
9
|
import { MODES, MODE_NOTE, getMode, setMode } from "./mode.js";
|
|
10
10
|
import { clipboardWrite, lastAnswer } from "./clipboard.js";
|
|
11
11
|
import { agentModel, body, bodyLog, codingToolOptions, kisoHome, configModels, dock, lastBinding, readContextLedger, sessionsDir, setAgentModel, setCurrentModelName, setModelChoice, setLastBinding } from "./state.js";
|
|
12
|
+
import { adapterOptionsFor } from "./auth/adapter-options.js";
|
|
12
13
|
import { authForProfile, directWriteProfile, profileAvailable, unavailableReason } from "./config.js";
|
|
13
14
|
import { shellTool } from "@vincemakes/kiso-tools-node";
|
|
14
15
|
import { join } from "node:path";
|
|
@@ -74,7 +75,6 @@ function signInNote(p) {
|
|
|
74
75
|
}
|
|
75
76
|
return p.apiKeyEnv ?? "no key";
|
|
76
77
|
}
|
|
77
|
-
import { oauthTokenThunk } from "./auth/token.js";
|
|
78
78
|
/** The ONE dispatcher — slash commands, exit, and turns. The recovery
|
|
79
79
|
* replay routes through it too — a queued "/last" must never become a
|
|
80
80
|
* user turn (v2c: the rl lives in main, so lines arrive earlier and the
|
|
@@ -601,18 +601,11 @@ export function dispatch(line, ctx) {
|
|
|
601
601
|
}
|
|
602
602
|
else {
|
|
603
603
|
const auth = authForProfile(profName, profile);
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
// token per request.
|
|
610
|
-
...(auth.type === "oauth"
|
|
611
|
-
? { oauth: oauthTokenThunk(auth.providerId), ...(ctx.session.id !== undefined ? { promptCacheKey: ctx.session.id } : {}) }
|
|
612
|
-
: { apiKey: auth.apiKey }),
|
|
613
|
-
...(profile.baseUrl !== undefined ? { baseUrl: profile.baseUrl } : {}),
|
|
614
|
-
...(profile.promptCaching !== undefined ? { promptCaching: profile.promptCaching } : {}),
|
|
615
|
-
});
|
|
604
|
+
// Astra F1 (P0): the wire config is built in ONE place
|
|
605
|
+
// (auth/adapter-options.ts) — this site and the startup
|
|
606
|
+
// site were the same spread written twice, which is the
|
|
607
|
+
// finding's own defect class.
|
|
608
|
+
const adapter = await buildAdapter(profile.kind, adapterOptionsFor(profile, auth, ctx.session.id));
|
|
616
609
|
// PH-1a (finding PH-F8, P0): the switch is ATOMIC —
|
|
617
610
|
// adapter, model id, and provider route move together.
|
|
618
611
|
// setAdapter alone left the session's frozen config
|
package/dist/index.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export { applyProjectMerges } from "./trust-ui.js";
|
|
|
31
31
|
*/
|
|
32
32
|
/** The built-in prompt. Exported for scripts/request-surface.mjs — the
|
|
33
33
|
* model-side token-rent counter measures the REAL bytes, never a copy. */
|
|
34
|
-
export declare const SYSTEM_PROMPT = "You are kiso, a coding agent. You work in a workspace\ndirectory and change code with tools. Be concise: answer in a few lines\nunless the task genuinely needs more. Never claim a file was changed\nunless a tool confirmed it.\n\nTool discipline:\n- READ BEFORE YOU EDIT. For any file you are about to change, read it\n first \u2014 never guess its content.\n- Use edit_file for targeted changes and write_file for full rewrites.\n Prefer many small edits over one large write.\n- shell is for commands: builds, tests, git, grep. Be careful \u2014 shell has\n side effects and may take time. Run one command at a time and inspect\n the output before continuing.\n- Batch independent tool calls into one reply \u2014 they run in parallel.\n- search_text and list_dir are cheap \u2014 locate first, then read ranges\n with read_file offset/limit; never read a whole large file in one call.\n- Do not re-read a file you already read unchanged \u2014 rely on the earlier\n result.\n- When a tool fails, read the error and adjust; do not repeat the same\n call blindly.\n\nWorkflow: understand the request, find the relevant code, make the\nsmallest change that works, then verify with a command (tests/build).\nReport what you did in one or two lines per change.";
|
|
34
|
+
export declare const SYSTEM_PROMPT = "You are kiso, a coding agent. You work in a workspace\ndirectory and change code with tools. Be concise: answer in a few lines\nunless the task genuinely needs more. Never claim a file was changed\nunless a tool confirmed it.\n\nWhat you can reach:\n- The workspace: read_file, list_dir, search_text, write_file, edit_file.\n- This machine and the network: shell \u2014 builds, tests, git, package\n managers, curl for HTTP, system queries. A request one command can\n answer is answered by running it.\n- The human: ask_user, for a decision that is theirs.\n\nTool discipline:\n- READ BEFORE YOU EDIT. For any file you are about to change, read it\n first \u2014 never guess its content.\n- Use edit_file for targeted changes and write_file for full rewrites.\n Prefer many small edits over one large write.\n- shell is for commands: builds, tests, git, grep. Be careful \u2014 shell has\n side effects and may take time. Run one command at a time and inspect\n the output before continuing.\n- Batch independent tool calls into one reply \u2014 they run in parallel.\n- search_text and list_dir are cheap \u2014 locate first, then read ranges\n with read_file offset/limit; never read a whole large file in one call.\n- Do not re-read a file you already read unchanged \u2014 rely on the earlier\n result.\n- When a tool fails, read the error and adjust; do not repeat the same\n call blindly.\n\nAn authorization covers what it NAMES: when the scope is not named \u2014\nwhich files, which branches, whether to push \u2014 ask before acting.\nDelivering, sharing or handing over changes means committing locally and\nstopping; pushing, publishing or sending happens only when the human\nnames it.\n\nWorkflow: understand the request, find the relevant code, make the\nsmallest change that works, then verify with a command (tests/build).\nReport what you did in one or two lines per change.";
|
|
35
35
|
/** Hard cap for injected instructions — truncate and say so. */
|
|
36
36
|
/**
|
|
37
37
|
* A area: read the FIRST present instruction file (AGENTS.md preferred) and
|
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
44
|
import { chat, contextWindowTokens, displayCtxRatio, 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.
|
|
@@ -555,6 +603,12 @@ Tool discipline:
|
|
|
555
603
|
- When a tool fails, read the error and adjust; do not repeat the same
|
|
556
604
|
call blindly.
|
|
557
605
|
|
|
606
|
+
An authorization covers what it NAMES: when the scope is not named —
|
|
607
|
+
which files, which branches, whether to push — ask before acting.
|
|
608
|
+
Delivering, sharing or handing over changes means committing locally and
|
|
609
|
+
stopping; pushing, publishing or sending happens only when the human
|
|
610
|
+
names it.
|
|
611
|
+
|
|
558
612
|
Workflow: understand the request, find the relevant code, make the
|
|
559
613
|
smallest change that works, then verify with a command (tests/build).
|
|
560
614
|
Report what you did in one or two lines per change.`;
|
|
@@ -664,16 +718,21 @@ async function makeAgent(sessionId, input, modelFlag) {
|
|
|
664
718
|
// the panel bridge is the argument, and a non-TTY session has none to
|
|
665
719
|
// give. A piped run's composed tool table therefore cannot contain
|
|
666
720
|
// ask_user (T-Q3: the bench's structural byte-identity proof).
|
|
667
|
-
|
|
721
|
+
// Astra F7: the config is READ here — a pure read, its setters still run
|
|
722
|
+
// below with the rest of merge round B — because the mcp extension spawns
|
|
723
|
+
// its stdio children while it is being constructed, and the strip needs
|
|
724
|
+
// the configured secret names by then.
|
|
725
|
+
const userCfg = loadUserConfig();
|
|
726
|
+
const projectCfg = loadProjectConfig(process.cwd(), project !== null);
|
|
727
|
+
const merged = mergeConfigs(userCfg, projectCfg);
|
|
728
|
+
const secretEnvNames = secretEnvNamesOf(merged.models ?? {});
|
|
729
|
+
const builtIn = await builtInLayer(user, proj, input !== undefined && process.stdin.isTTY ? askUi(input) : undefined, secretEnvNames);
|
|
668
730
|
setExtensionLists(builtIn, user, proj, [...builtIn, ...user, ...proj]);
|
|
669
731
|
// merge round B — the config surface: user config + (trusted) project config,
|
|
670
732
|
// resolved with flags > env > project > user > default. The CLI never
|
|
671
733
|
// imports provider SDKs directly — the runtime's lazy provider
|
|
672
734
|
// resolution owns them (a config profile only ever NAMES an env var for
|
|
673
735
|
// 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
736
|
setMergedConfig(merged);
|
|
678
737
|
// DT-1a: what a delegated task may NAME — the configured checks and the
|
|
679
738
|
// model profiles — handed to the (in-process) subagent extension through
|
|
@@ -741,21 +800,18 @@ async function makeAgent(sessionId, input, modelFlag) {
|
|
|
741
800
|
...(resolved !== null
|
|
742
801
|
? {
|
|
743
802
|
provider: resolved.profile.kind,
|
|
744
|
-
//
|
|
745
|
-
//
|
|
746
|
-
// the
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
//
|
|
753
|
-
//
|
|
754
|
-
//
|
|
755
|
-
|
|
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
|
|
803
|
+
// Astra F1 (P0): the wire config is built in ONE place
|
|
804
|
+
// (auth/adapter-options.ts) — credential shape, the ALWAYS
|
|
805
|
+
// EXPLICIT endpoint, the session's cache key and the
|
|
806
|
+
// profile's caching flag. This site and the `/model` site
|
|
807
|
+
// were the same spread written twice.
|
|
808
|
+
...adapterOptionsFor(resolved.profile, resolved.oauthProviderId !== undefined
|
|
809
|
+
? { type: "oauth", providerId: resolved.oauthProviderId }
|
|
810
|
+
: { type: "api-key", apiKey: resolved.apiKey ?? "none" }, sessionId),
|
|
811
|
+
// LT-1: the profile's stream watchdog bound, if it states one.
|
|
812
|
+
// NOT an adapter option — an agent-definition field the
|
|
813
|
+
// runtime reads — so it stays here rather than moving into
|
|
814
|
+
// adapterOptionsFor.
|
|
759
815
|
...(resolved.profile.streamIdleMs !== undefined ? { streamIdleMs: resolved.profile.streamIdleMs } : {}),
|
|
760
816
|
}
|
|
761
817
|
: { adapter: createFauxProvider(readFauxScript().slice(fauxSkipTurns)) }),
|
|
@@ -1296,7 +1352,12 @@ async function main() {
|
|
|
1296
1352
|
input.onClipboardPaste?.(() => {
|
|
1297
1353
|
const shot = clipboardImage(tmpdir());
|
|
1298
1354
|
if (shot === null) {
|
|
1299
|
-
|
|
1355
|
+
// Astra F8: on a platform with no clipboard reader kiso never
|
|
1356
|
+
// LOOKED, so "no image on the clipboard" blamed the clipboard for
|
|
1357
|
+
// a limit of the build. Say which of the two it is.
|
|
1358
|
+
bodyLog(process.platform === "darwin"
|
|
1359
|
+
? "[no image on the clipboard — ctrl+V attaches one; a file dragged into the window works too]"
|
|
1360
|
+
: "[clipboard images are macOS-only — put the image's path in your message instead; a file dragged into the window leaves one]");
|
|
1300
1361
|
return null;
|
|
1301
1362
|
}
|
|
1302
1363
|
return shot;
|
|
@@ -1465,6 +1526,7 @@ async function main() {
|
|
|
1465
1526
|
});
|
|
1466
1527
|
setCredential(provider, cred);
|
|
1467
1528
|
process.stdout.write(`signed in to ${provider} (${chatgptFlow.label}) — account ${cred.accountId ?? "?"}, expires ${new Date(cred.expires).toISOString()} — stored in ${authPath()}\n`);
|
|
1529
|
+
process.stdout.write(nextStepAfterLogin(provider));
|
|
1468
1530
|
}
|
|
1469
1531
|
finally {
|
|
1470
1532
|
rl.close();
|
|
@@ -1476,6 +1538,7 @@ async function main() {
|
|
|
1476
1538
|
throw new CliUsageError(`kiso login ${provider}: no key given`);
|
|
1477
1539
|
setCredential(provider, { type: "api-key", key, savedAt: Date.now() });
|
|
1478
1540
|
process.stdout.write(`signed in to ${provider} with an API key (${maskSecret(key)}) — stored in ${authPath()}\n`);
|
|
1541
|
+
process.stdout.write(nextStepAfterLogin(provider));
|
|
1479
1542
|
break;
|
|
1480
1543
|
}
|
|
1481
1544
|
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
|
|
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.
|
|
4
|
-
"description": "kiso-code
|
|
3
|
+
"version": "0.36.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.
|
|
22
|
-
"@vincemakes/kiso-core": "0.
|
|
23
|
-
"@vincemakes/kiso-evals": "0.
|
|
24
|
-
"@vincemakes/kiso-mcp-ext": "0.
|
|
25
|
-
"@vincemakes/kiso-provider-anthropic": "0.
|
|
26
|
-
"@vincemakes/kiso-provider-openai": "0.
|
|
27
|
-
"@vincemakes/kiso-provider-openai-responses": "0.
|
|
28
|
-
"@vincemakes/kiso-runtime": "0.
|
|
29
|
-
"@vincemakes/kiso-skills-ext": "0.
|
|
30
|
-
"@vincemakes/kiso-subagent-ext": "0.
|
|
31
|
-
"@vincemakes/kiso-task-ext": "0.
|
|
32
|
-
"@vincemakes/kiso-tools-node": "0.
|
|
33
|
-
"@vincemakes/kiso-tui": "0.
|
|
34
|
-
"@vincemakes/kiso-tui-cells": "0.
|
|
21
|
+
"@vincemakes/kiso-ask-ext": "0.36.0",
|
|
22
|
+
"@vincemakes/kiso-core": "0.36.0",
|
|
23
|
+
"@vincemakes/kiso-evals": "0.36.0",
|
|
24
|
+
"@vincemakes/kiso-mcp-ext": "0.36.0",
|
|
25
|
+
"@vincemakes/kiso-provider-anthropic": "0.36.0",
|
|
26
|
+
"@vincemakes/kiso-provider-openai": "0.36.0",
|
|
27
|
+
"@vincemakes/kiso-provider-openai-responses": "0.36.0",
|
|
28
|
+
"@vincemakes/kiso-runtime": "0.36.0",
|
|
29
|
+
"@vincemakes/kiso-skills-ext": "0.36.0",
|
|
30
|
+
"@vincemakes/kiso-subagent-ext": "0.36.0",
|
|
31
|
+
"@vincemakes/kiso-task-ext": "0.36.0",
|
|
32
|
+
"@vincemakes/kiso-tools-node": "0.36.0",
|
|
33
|
+
"@vincemakes/kiso-tui": "0.36.0",
|
|
34
|
+
"@vincemakes/kiso-tui-cells": "0.36.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "^26.1.2",
|