koneck 2.49.4 → 2.51.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/credentials.d.ts +53 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +137 -0
- package/dist/credentials.js.map +1 -0
- package/dist/doctor.d.ts +5 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +36 -4
- package/dist/doctor.js.map +1 -1
- package/dist/engine.d.ts +3 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +29 -6
- package/dist/engine.js.map +1 -1
- package/dist/ink-chat.d.ts.map +1 -1
- package/dist/ink-chat.js +28 -6
- package/dist/ink-chat.js.map +1 -1
- package/dist/providers.d.ts +30 -1
- package/dist/providers.d.ts.map +1 -1
- package/dist/providers.js +45 -3
- package/dist/providers.js.map +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +42 -6
- package/dist/web/api.js.map +1 -1
- package/dist/web/sessions.d.ts +3 -1
- package/dist/web/sessions.d.ts.map +1 -1
- package/dist/web/sessions.js +31 -5
- package/dist/web/sessions.js.map +1 -1
- package/dist/web/ui-client.d.ts.map +1 -1
- package/dist/web/ui-client.js +34 -3
- package/dist/web/ui-client.js.map +1 -1
- package/dist/web/ui-css.d.ts.map +1 -1
- package/dist/web/ui-css.js +6 -0
- package/dist/web/ui-css.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +10 -2
- package/dist/web/ui.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keys that survive closing the terminal.
|
|
3
|
+
*
|
|
4
|
+
* KONECK held a typed key in memory and said so proudly: "the key is held in memory only — KONECK
|
|
5
|
+
* has not written it anywhere", followed by advice to put an export line in a shell profile. That
|
|
6
|
+
* is a defensible position for a tool nobody has to use twice. In practice it meant entering the
|
|
7
|
+
* same key on every launch of the web UI, and a key that works in the terminal while the browser
|
|
8
|
+
* on the same machine reports none — because the two were keeping separate copies of something the
|
|
9
|
+
* user reasonably thought they had configured once.
|
|
10
|
+
*
|
|
11
|
+
* Every comparable tool persists. Claude Code keeps credentials under its own home directory or
|
|
12
|
+
* the OS keychain, Codex writes auth.json, the Gemini CLI keeps a file too. So this writes one as
|
|
13
|
+
* well, with the properties that make it defensible rather than merely convenient:
|
|
14
|
+
*
|
|
15
|
+
* - one file, `~/.koneck/credentials.json`, mode 0600 inside a 0700 directory, so a permissive
|
|
16
|
+
* umask on a shared machine cannot leave it group-readable;
|
|
17
|
+
* - written atomically through a temporary file and a rename, so a crash cannot leave half a
|
|
18
|
+
* credential behind and a symlink planted at the path is not followed;
|
|
19
|
+
* - keyed by provider, because a key belongs to the endpoint that issued it and there are
|
|
20
|
+
* several — the older single global apiKey could not express "OpenRouter but not OpenCode";
|
|
21
|
+
* - and never consulted ahead of the environment, so an exported variable still wins and a
|
|
22
|
+
* rotated key does not have to be hunted down in a file first.
|
|
23
|
+
*
|
|
24
|
+
* An environment variable fed from a password manager is still the better answer, and the notices
|
|
25
|
+
* keep saying so. This is the answer for the case where somebody has decided otherwise.
|
|
26
|
+
*/
|
|
27
|
+
/** Where the file lives. `home` is for tests, which must never touch the real one. */
|
|
28
|
+
export declare function credentialsPath(home?: string): string;
|
|
29
|
+
/** Which providers have a key stored. Names only — callers that want a value ask for one. */
|
|
30
|
+
export declare function storedProviders(home?: string): string[];
|
|
31
|
+
/** The stored key for a provider, if there is one. */
|
|
32
|
+
export declare function storedKeyFor(provider: string, home?: string): string | undefined;
|
|
33
|
+
/** Writes a key for one provider, leaving the others alone. Returns the file it went into. */
|
|
34
|
+
export declare function rememberKey(provider: string, key: string, home?: string): string;
|
|
35
|
+
/** Removes one provider's key. Returns whether there was one to remove. */
|
|
36
|
+
export declare function forgetKey(provider: string, home?: string): boolean;
|
|
37
|
+
/** Removes every stored key. What /logout means once there is more than one. */
|
|
38
|
+
export declare function forgetAllKeys(home?: string): string[];
|
|
39
|
+
/**
|
|
40
|
+
* The same key remembered for two different providers.
|
|
41
|
+
*
|
|
42
|
+
* Found on a real machine: one key stored under both `openrouter` and `agentrouter`, identical
|
|
43
|
+
* fingerprints. Whichever of the two was intended, the other entry means a credential issued by
|
|
44
|
+
* one company is sent to another company's endpoint the moment that provider is used — not a key
|
|
45
|
+
* that fails, a key that is disclosed. The usual cause is entering it while a different provider
|
|
46
|
+
* was selected, which is exactly the mis-filing that used to happen silently.
|
|
47
|
+
*
|
|
48
|
+
* Reported, not repaired: only the person who owns the key knows which entry was meant.
|
|
49
|
+
*/
|
|
50
|
+
export declare function crossFiledKeys(home?: string): Array<{
|
|
51
|
+
providers: string[];
|
|
52
|
+
}>;
|
|
53
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAOH,sFAAsF;AACtF,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAErD;AAqBD,6FAA6F;AAC7F,wBAAgB,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAEvD;AAED,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGhF;AAwBD,8FAA8F;AAC9F,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAOhF;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAOlE;AAED,gFAAgF;AAChF,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAIrD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAW5E"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keys that survive closing the terminal.
|
|
3
|
+
*
|
|
4
|
+
* KONECK held a typed key in memory and said so proudly: "the key is held in memory only — KONECK
|
|
5
|
+
* has not written it anywhere", followed by advice to put an export line in a shell profile. That
|
|
6
|
+
* is a defensible position for a tool nobody has to use twice. In practice it meant entering the
|
|
7
|
+
* same key on every launch of the web UI, and a key that works in the terminal while the browser
|
|
8
|
+
* on the same machine reports none — because the two were keeping separate copies of something the
|
|
9
|
+
* user reasonably thought they had configured once.
|
|
10
|
+
*
|
|
11
|
+
* Every comparable tool persists. Claude Code keeps credentials under its own home directory or
|
|
12
|
+
* the OS keychain, Codex writes auth.json, the Gemini CLI keeps a file too. So this writes one as
|
|
13
|
+
* well, with the properties that make it defensible rather than merely convenient:
|
|
14
|
+
*
|
|
15
|
+
* - one file, `~/.koneck/credentials.json`, mode 0600 inside a 0700 directory, so a permissive
|
|
16
|
+
* umask on a shared machine cannot leave it group-readable;
|
|
17
|
+
* - written atomically through a temporary file and a rename, so a crash cannot leave half a
|
|
18
|
+
* credential behind and a symlink planted at the path is not followed;
|
|
19
|
+
* - keyed by provider, because a key belongs to the endpoint that issued it and there are
|
|
20
|
+
* several — the older single global apiKey could not express "OpenRouter but not OpenCode";
|
|
21
|
+
* - and never consulted ahead of the environment, so an exported variable still wins and a
|
|
22
|
+
* rotated key does not have to be hunted down in a file first.
|
|
23
|
+
*
|
|
24
|
+
* An environment variable fed from a password manager is still the better answer, and the notices
|
|
25
|
+
* keep saying so. This is the answer for the case where somebody has decided otherwise.
|
|
26
|
+
*/
|
|
27
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, renameSync, chmodSync, rmSync } from 'fs';
|
|
28
|
+
import os from 'os';
|
|
29
|
+
import path from 'path';
|
|
30
|
+
import { randomUUID } from 'crypto';
|
|
31
|
+
/** Where the file lives. `home` is for tests, which must never touch the real one. */
|
|
32
|
+
export function credentialsPath(home) {
|
|
33
|
+
return path.join(home ?? os.homedir(), '.koneck', 'credentials.json');
|
|
34
|
+
}
|
|
35
|
+
function readFile(home) {
|
|
36
|
+
const file = credentialsPath(home);
|
|
37
|
+
if (!existsSync(file))
|
|
38
|
+
return {};
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(readFileSync(file, 'utf-8'));
|
|
41
|
+
if (!parsed || typeof parsed !== 'object')
|
|
42
|
+
return {};
|
|
43
|
+
const keys = parsed.keys;
|
|
44
|
+
return keys && typeof keys === 'object' ? { keys } : {};
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// A corrupt credential file must not stop a run that has a working environment variable.
|
|
48
|
+
return {};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Which providers have a key stored. Names only — callers that want a value ask for one. */
|
|
52
|
+
export function storedProviders(home) {
|
|
53
|
+
return Object.keys(readFile(home).keys ?? {}).sort();
|
|
54
|
+
}
|
|
55
|
+
/** The stored key for a provider, if there is one. */
|
|
56
|
+
export function storedKeyFor(provider, home) {
|
|
57
|
+
const key = (readFile(home).keys ?? {})[provider.trim().toLowerCase()];
|
|
58
|
+
return typeof key === 'string' && key.trim() !== '' ? key : undefined;
|
|
59
|
+
}
|
|
60
|
+
function write(all, home) {
|
|
61
|
+
const file = credentialsPath(home);
|
|
62
|
+
const directory = path.dirname(file);
|
|
63
|
+
// 0700, so the directory itself does not advertise what is in it.
|
|
64
|
+
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
65
|
+
try {
|
|
66
|
+
chmodSync(directory, 0o700);
|
|
67
|
+
}
|
|
68
|
+
catch { /* pre-existing directory owned as it is */ }
|
|
69
|
+
const temporary = path.join(directory, `.credentials.${randomUUID()}.tmp`);
|
|
70
|
+
try {
|
|
71
|
+
// `wx` fails rather than following anything already at that path.
|
|
72
|
+
writeFileSync(temporary, JSON.stringify(all, null, 2) + '\n', { encoding: 'utf-8', mode: 0o600, flag: 'wx' });
|
|
73
|
+
chmodSync(temporary, 0o600);
|
|
74
|
+
renameSync(temporary, file);
|
|
75
|
+
chmodSync(file, 0o600);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
try {
|
|
79
|
+
rmSync(temporary, { force: true });
|
|
80
|
+
}
|
|
81
|
+
catch { /* nothing to undo */ }
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
return file;
|
|
85
|
+
}
|
|
86
|
+
/** Writes a key for one provider, leaving the others alone. Returns the file it went into. */
|
|
87
|
+
export function rememberKey(provider, key, home) {
|
|
88
|
+
const name = provider.trim().toLowerCase();
|
|
89
|
+
const value = key.trim();
|
|
90
|
+
if (!name)
|
|
91
|
+
throw new Error('which provider is this key for?');
|
|
92
|
+
if (!value)
|
|
93
|
+
throw new Error('no key given');
|
|
94
|
+
const all = readFile(home);
|
|
95
|
+
return write({ ...all, keys: { ...(all.keys ?? {}), [name]: value } }, home);
|
|
96
|
+
}
|
|
97
|
+
/** Removes one provider's key. Returns whether there was one to remove. */
|
|
98
|
+
export function forgetKey(provider, home) {
|
|
99
|
+
const name = provider.trim().toLowerCase();
|
|
100
|
+
const all = readFile(home);
|
|
101
|
+
if (!all.keys || !(name in all.keys))
|
|
102
|
+
return false;
|
|
103
|
+
const { [name]: _gone, ...rest } = all.keys;
|
|
104
|
+
write({ ...all, keys: rest }, home);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
/** Removes every stored key. What /logout means once there is more than one. */
|
|
108
|
+
export function forgetAllKeys(home) {
|
|
109
|
+
const had = storedProviders(home);
|
|
110
|
+
if (had.length > 0)
|
|
111
|
+
write({ keys: {} }, home);
|
|
112
|
+
return had;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* The same key remembered for two different providers.
|
|
116
|
+
*
|
|
117
|
+
* Found on a real machine: one key stored under both `openrouter` and `agentrouter`, identical
|
|
118
|
+
* fingerprints. Whichever of the two was intended, the other entry means a credential issued by
|
|
119
|
+
* one company is sent to another company's endpoint the moment that provider is used — not a key
|
|
120
|
+
* that fails, a key that is disclosed. The usual cause is entering it while a different provider
|
|
121
|
+
* was selected, which is exactly the mis-filing that used to happen silently.
|
|
122
|
+
*
|
|
123
|
+
* Reported, not repaired: only the person who owns the key knows which entry was meant.
|
|
124
|
+
*/
|
|
125
|
+
export function crossFiledKeys(home) {
|
|
126
|
+
const keys = readFile(home).keys ?? {};
|
|
127
|
+
const byValue = new Map();
|
|
128
|
+
for (const [provider, value] of Object.entries(keys)) {
|
|
129
|
+
const seen = byValue.get(value) ?? [];
|
|
130
|
+
seen.push(provider);
|
|
131
|
+
byValue.set(value, seen);
|
|
132
|
+
}
|
|
133
|
+
return [...byValue.values()]
|
|
134
|
+
.filter(providers => providers.length > 1)
|
|
135
|
+
.map(providers => ({ providers: providers.sort() }));
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../src/credentials.ts"],"names":[],"mappings":"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"}
|
package/dist/doctor.d.ts
CHANGED
|
@@ -15,6 +15,11 @@ type FetchLike = (input: string, init?: RequestInit) => Promise<{
|
|
|
15
15
|
* distinguishes a reachable-but-misconfigured endpoint from a dead network.
|
|
16
16
|
*/
|
|
17
17
|
export declare function providerConnectionCheck(def: ProviderDef, apiKey?: string, fetcher?: FetchLike): Promise<DoctorCheck>;
|
|
18
|
+
/**
|
|
19
|
+
* One key remembered for two providers, which means one of them is receiving somebody else's
|
|
20
|
+
* credential. Reported rather than repaired: only the owner knows which entry was intended.
|
|
21
|
+
*/
|
|
22
|
+
export declare function credentialCrossFilingCheck(stateHome?: string): DoctorCheck;
|
|
18
23
|
/**
|
|
19
24
|
* Inspect the environment needed for a useful coding session.
|
|
20
25
|
*
|
package/dist/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAKA,OAAO,
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAwD,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAIxG,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjG;;;;GAIG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,WAAW,EAChB,MAAM,CAAC,EAAE,MAAM,EACf,OAAO,GAAE,SAAiB,GACzB,OAAO,CAAC,WAAW,CAAC,CAgCtB;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,CAa1E;AAYD;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,MAAM,EACX,cAAc,CAAC,EAAE,MAAM,EACvB,aAAa,CAAC,EAAE,MAAM,EACtB,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE,SAAS,GAClB,OAAO,CAAC,WAAW,EAAE,CAAC,CA6FxB;AAED,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CASpE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAc1D"}
|
package/dist/doctor.js
CHANGED
|
@@ -3,7 +3,8 @@ import { execa } from 'execa';
|
|
|
3
3
|
import fs from 'fs/promises';
|
|
4
4
|
import os from 'os';
|
|
5
5
|
import path from 'path';
|
|
6
|
-
import { PROVIDERS, getApiKey, resolveProvider } from './providers.js';
|
|
6
|
+
import { PROVIDERS, getApiKey, keyProvenance, resolveProvider } from './providers.js';
|
|
7
|
+
import { crossFiledKeys, credentialsPath } from './credentials.js';
|
|
7
8
|
import { loadGlobalConfig } from './config.js';
|
|
8
9
|
/**
|
|
9
10
|
* Verify that an OpenAI-compatible endpoint is reachable without spending tokens or changing
|
|
@@ -18,6 +19,15 @@ export async function providerConnectionCheck(def, apiKey, fetcher = fetch) {
|
|
|
18
19
|
catch {
|
|
19
20
|
return { status: 'warn', name: 'Provider connection', reason: 'not checked — no API key available' };
|
|
20
21
|
}
|
|
22
|
+
/*
|
|
23
|
+
* Which key, and from where — a fingerprint, never the key.
|
|
24
|
+
*
|
|
25
|
+
* The terminal and the browser once disagreed about whether a model worked, with identical
|
|
26
|
+
* requests on both sides. The difference was the credential, and neither side would say which
|
|
27
|
+
* one it held; comparing two fingerprints answers in a glance what took a request capture.
|
|
28
|
+
*/
|
|
29
|
+
const seen = keyProvenance(def, apiKey);
|
|
30
|
+
const using = seen.found ? ` · key ${seen.fingerprint}, from ${seen.source}` : '';
|
|
21
31
|
const url = def.baseURL.replace(/\/+$/, '') + '/models';
|
|
22
32
|
try {
|
|
23
33
|
const response = await fetcher(url, {
|
|
@@ -25,10 +35,12 @@ export async function providerConnectionCheck(def, apiKey, fetcher = fetch) {
|
|
|
25
35
|
headers: { ...def.extraHeaders, Authorization: `Bearer ${key}` },
|
|
26
36
|
signal: AbortSignal.timeout(5_000),
|
|
27
37
|
});
|
|
28
|
-
if (response.ok)
|
|
29
|
-
return { status: 'pass', name: 'Provider connection', reason: def.baseURL };
|
|
38
|
+
if (response.ok) {
|
|
39
|
+
return { status: 'pass', name: 'Provider connection', reason: def.baseURL + using };
|
|
40
|
+
}
|
|
30
41
|
if (response.status === 401 || response.status === 403) {
|
|
31
|
-
return { status: 'fail', name: 'Provider connection',
|
|
42
|
+
return { status: 'fail', name: 'Provider connection',
|
|
43
|
+
reason: `endpoint rejected the credential (HTTP ${response.status})${using}` };
|
|
32
44
|
}
|
|
33
45
|
return { status: 'warn', name: 'Provider connection', reason: `endpoint responded HTTP ${response.status} at ${def.baseURL}` };
|
|
34
46
|
}
|
|
@@ -37,6 +49,24 @@ export async function providerConnectionCheck(def, apiKey, fetcher = fetch) {
|
|
|
37
49
|
return { status: 'fail', name: 'Provider connection', reason: `could not reach ${def.baseURL} — ${message}` };
|
|
38
50
|
}
|
|
39
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* One key remembered for two providers, which means one of them is receiving somebody else's
|
|
54
|
+
* credential. Reported rather than repaired: only the owner knows which entry was intended.
|
|
55
|
+
*/
|
|
56
|
+
export function credentialCrossFilingCheck(stateHome) {
|
|
57
|
+
const shared = crossFiledKeys(stateHome);
|
|
58
|
+
if (shared.length === 0) {
|
|
59
|
+
return { status: 'pass', name: 'Remembered keys', reason: 'no key is shared between providers' };
|
|
60
|
+
}
|
|
61
|
+
const pairs = shared.map(s => s.providers.join(' and ')).join('; ');
|
|
62
|
+
return {
|
|
63
|
+
status: 'fail',
|
|
64
|
+
name: 'Remembered keys',
|
|
65
|
+
reason: `the same key is remembered for ${pairs} — one of those endpoints is being sent a `
|
|
66
|
+
+ `credential issued by the other. Forget whichever is wrong: /logout, or delete the `
|
|
67
|
+
+ `entry from ${credentialsPath(stateHome)}`,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
40
70
|
function printResult(r) {
|
|
41
71
|
if (r.status === 'pass') {
|
|
42
72
|
console.log(chalk.green(` ✔ ${r.name}`));
|
|
@@ -97,6 +127,8 @@ export async function doctorChecks(cwd, activeProvider, activeBaseURL, activeApi
|
|
|
97
127
|
else if (provider) {
|
|
98
128
|
results.push({ status: 'warn', name: 'Provider connection', reason: `cannot probe unknown provider "${provider}"` });
|
|
99
129
|
}
|
|
130
|
+
// Cheap, local, and the one credential problem that is a disclosure rather than a failure.
|
|
131
|
+
results.push(credentialCrossFilingCheck());
|
|
100
132
|
try {
|
|
101
133
|
await execa('git', ['--version']);
|
|
102
134
|
results.push({ status: 'pass', name: 'git available' });
|
package/dist/doctor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAoB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/engine.d.ts
CHANGED
|
@@ -24,6 +24,7 @@ export declare function describeProviderError(err: unknown, provider: string, mo
|
|
|
24
24
|
*/
|
|
25
25
|
about?: {
|
|
26
26
|
hadImage?: boolean;
|
|
27
|
+
credential?: string;
|
|
27
28
|
}): string;
|
|
28
29
|
/** Session totals as they stood before a request, so its usage can be added rather than assigned. */
|
|
29
30
|
export interface UsageBaseline {
|
|
@@ -178,6 +179,8 @@ export declare function mapWithLimit<T, R>(items: readonly T[], limit: number, f
|
|
|
178
179
|
* then advised removing the attachment — to people whose request contained no image at all. The
|
|
179
180
|
* cheapest way to stop asserting it was to be able to check it.
|
|
180
181
|
*/
|
|
182
|
+
/** The key a run will use, as a fingerprint and a source. Never the key. Never throws. */
|
|
183
|
+
export declare function describeCredential(config: AgentConfig): string | undefined;
|
|
181
184
|
export declare function carriesImage(messages: readonly Message[]): boolean;
|
|
182
185
|
export declare function stripImages(messages: Message[]): number;
|
|
183
186
|
/**
|
package/dist/engine.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAuB5B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAMvD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAWtC,OAAO,EAA2B,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAIL,KAAK,cAAc,EACpB,MAAM,UAAU,CAAC;AAWlB,OAAO,EAAE,kBAAkB,EAAuD,MAAM,iBAAiB,CAAC;AAI1G,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EACV,OAAO,EACP,WAAW,EAEX,UAAU,EAKX,MAAM,YAAY,CAAC;AAIpB;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;AAC7C;;;;GAIG;AACH,KAAK,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GACtD,MAAM,CAmFR;AAED,qGAAqG;AACrG,MAAM,WAAW,aAAa;IAAG,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE;AAEpF;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,UAAU,EACjB,QAAQ,EAAE,aAAa,EACvB,KAAK,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACxG,IAAI,CAQN;AAsBD;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAyC9D;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,eAAc,GAAG,MAAM,CAuBxF;AAED;;;;;;;GAOG;AACH;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGzD;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI5D;AAED,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAG/D;AAqCD;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAkB7D;AAMD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,OAAO,GAAG,OAAO,CAExF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAcvD;AAID,wBAAgB,WAAW,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAQvD;AAID;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,MAAM,CAOrE;AAiDD,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,SAAM,GAAG,MAAM,CAG/D;AAED,uEAAuE;AACvE,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AAEtC,6FAA6F;AAC7F,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,WAAW,CAAC,aAAa,CAAC,GAAG,MAAM,CAStF;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAmB,GAAG,MAAM,CAK/E;AAyID;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yDAAyD;IACzD,GAAG,EAAE,OAAO,CAAC;IACb,gDAAgD;IAChD,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,gBAAgB,GAC1B,MAAM,EAAE,CAMV;AAED,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE7E;AA+DD;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAG7E;AAQD;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,CAAC,EAAE,CAAC,EACrC,KAAK,EAAE,SAAS,CAAC,EAAE,EACnB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GACzC,OAAO,CAAC,CAAC,EAAE,CAAC,CAad;AAkJD;;;;;GAKG;AACH;;;;;;;GAOG;AACH,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS,CAM1E;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,OAAO,CAGlE;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAevD;AAGD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CASpE;AAGD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,OAAO,EACpB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CAiDR;AAED,wBAAsB,YAAY,CAChC,QAAQ,EAAE,OAAO,EAAE,EACnB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,WAAW,EACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,UAAU,EACjB,UAAU,EAAE,cAAc,EAAE,EAC5B,OAAO,EAAE,WAAW,EAAE,EAEtB,WAAW,EAAE,MAAM,CAAC,IAAI,CAAC,kBAAkB,EAAE,EAC7C,UAAU,SAAI,EACd,WAAW,CAAC,EAAE,WAAW,EACzB,UAAU,CAAC,EAAE,kBAAkB;AAC/B;;;;;;GAMG;AACH,OAAO,GAAE;IAAE,OAAO,EAAE,IAAI,CAAA;CAA4B;AACpD,2FAA2F;AAC3F,UAAU,CAAC,EAAE,UAAU;AACvB,4FAA4F;AAC5F,eAAe,GAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAmB,GACpD,OAAO,CAAC,OAAO,CAAC,CAquClB;AAID,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,SAAS,eAAe,EAAE,CAAC;IAChD,8FAA8F;IAC9F,QAAQ,CAAC,UAAU,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,SAAS;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,WAAW,CAAC,EAAE,MAAM,CAAA;SAAE,EAAE,CAAA;KAAE,EAAE,CAAC;IAC3G,6FAA6F;IAC7F,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAChG;AAGD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAarE;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,WAAW,EACnB,eAAe,CAAC,EAAE,OAAO,EAAE;AAC3B;;;;;;;GAOG;AACH,YAAY,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC;AAClC,iGAAiG;AACjG,WAAW,CAAC,EAAE,IAAI,GACjB,OAAO,CAAC,YAAY,CAAC,CAiOvB;AAwBD;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sFAAsF;IACtF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAGD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAExD;AAED,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,EACnB,eAAe,CAAC,EAAE,OAAO,EAAE,EAC3B,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,YAAY,CAAC,CAwKvB"}
|
package/dist/engine.js
CHANGED
|
@@ -7,7 +7,7 @@ import { execa } from 'execa';
|
|
|
7
7
|
import { TOOL_DEFINITIONS, dispatchTool, describeShell, unknownToolError, resolveToolAlias, aliasNotice, isToolFailure, } from './tools.js';
|
|
8
8
|
import { tui } from './tui.js';
|
|
9
9
|
import { hasWorkspaceOwnedGitRepo, gitScope, createWorktree, mergeWorktree, preservedWorktreeNotice } from './worktree.js';
|
|
10
|
-
import { resolveProvider, getApiKey, servesLocally, servesOwnWeights, isPrivateHost } from './providers.js';
|
|
10
|
+
import { resolveProvider, getApiKey, keyProvenance, servesLocally, servesOwnWeights, isPrivateHost } from './providers.js';
|
|
11
11
|
import { compressIfNeeded } from './compressor.js';
|
|
12
12
|
import { contextLimitFor, looksLikeContextOverflow, parseContextLimit, fetchModelContextLimit, ollamaServingLimit, fixedRequestTokens, overheadIsCrowded, crowdedWindowAdvice, probeOllamaContext, detectWindowPlateau, truncationNotice, } from './context-limit.js';
|
|
13
13
|
import { generateSessionId, saveSession } from './session.js';
|
|
@@ -85,7 +85,9 @@ about = {}) {
|
|
|
85
85
|
const hint = status === 429
|
|
86
86
|
? `Rate limited or out of quota on ${provider}. Check the plan and billing for that account.`
|
|
87
87
|
: status === 401 || status === 403
|
|
88
|
-
? `${provider} rejected the credential. Check the API key, and that it is enabled for this
|
|
88
|
+
? `${provider} rejected the credential. Check the API key, and that it is enabled for this `
|
|
89
|
+
+ `endpoint.`
|
|
90
|
+
+ (about.credential ? `\nThe key used: ${about.credential}` : '')
|
|
89
91
|
: status === 404
|
|
90
92
|
? `${provider} does not recognise model "${model}". Use /models to pick one it offers.`
|
|
91
93
|
: status === 400
|
|
@@ -119,7 +121,9 @@ about = {}) {
|
|
|
119
121
|
*/
|
|
120
122
|
const rerouted = readReroutedFailure(`${e?.message ?? ''}${detail ? '\n' + detail : ''}`, { model, ...(about.hadImage === undefined ? {} : { hadImage: about.hadImage }) });
|
|
121
123
|
if (rerouted) {
|
|
122
|
-
return [`${provider} could not serve this request.`, rerouted.advice
|
|
124
|
+
return [`${provider} could not serve this request.`, rerouted.advice,
|
|
125
|
+
about.credential ? `\nThe key used: ${about.credential}` : undefined]
|
|
126
|
+
.filter(Boolean).join('\n');
|
|
123
127
|
}
|
|
124
128
|
const router = readRouterFailure(`${e?.message ?? ''}`);
|
|
125
129
|
if (router) {
|
|
@@ -380,7 +384,7 @@ export function announcesMoreWork(text) {
|
|
|
380
384
|
// ─── Client ──────────────────────────────────────────────────────────────────
|
|
381
385
|
export function buildClient(config) {
|
|
382
386
|
const provider = resolveProvider(config.provider, config.baseURL);
|
|
383
|
-
const apiKey = getApiKey(provider, config.apiKey);
|
|
387
|
+
const apiKey = getApiKey(provider, config.apiKey, config.stateHome);
|
|
384
388
|
return new OpenAI({
|
|
385
389
|
baseURL: provider.baseURL,
|
|
386
390
|
apiKey,
|
|
@@ -838,6 +842,17 @@ parentStats) {
|
|
|
838
842
|
* then advised removing the attachment — to people whose request contained no image at all. The
|
|
839
843
|
* cheapest way to stop asserting it was to be able to check it.
|
|
840
844
|
*/
|
|
845
|
+
/** The key a run will use, as a fingerprint and a source. Never the key. Never throws. */
|
|
846
|
+
export function describeCredential(config) {
|
|
847
|
+
try {
|
|
848
|
+
const provider = resolveProvider(config.provider, config.baseURL);
|
|
849
|
+
const seen = keyProvenance(provider, config.apiKey, config.stateHome);
|
|
850
|
+
return seen.found ? `${seen.fingerprint}, from ${seen.source}` : seen.source;
|
|
851
|
+
}
|
|
852
|
+
catch {
|
|
853
|
+
return undefined;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
841
856
|
export function carriesImage(messages) {
|
|
842
857
|
return messages.some(m => Array.isArray(m.content)
|
|
843
858
|
&& m.content.some(part => part?.type === 'image_url'));
|
|
@@ -1569,7 +1584,15 @@ detectedContext = { current: 0 }) {
|
|
|
1569
1584
|
}
|
|
1570
1585
|
if (spinner)
|
|
1571
1586
|
spinner.fail('API error on turn ' + stats.turns);
|
|
1572
|
-
|
|
1587
|
+
/*
|
|
1588
|
+
* Which credential this run used, said only when the failure is about credentials.
|
|
1589
|
+
*
|
|
1590
|
+
* A fingerprint, never the key. The failure that prompted it looked like a gateway problem
|
|
1591
|
+
* and was a question about which of two keys was in play — unanswerable from anything that
|
|
1592
|
+
* was printed, on either side.
|
|
1593
|
+
*/
|
|
1594
|
+
const credential = describeCredential(config);
|
|
1595
|
+
throw new Error(describeProviderError(err, config.provider, config.model, { hadImage: carriesImage(messages), ...(credential ? { credential } : {}) }), { cause: err });
|
|
1573
1596
|
}
|
|
1574
1597
|
if (spinner && !spinnerStopped)
|
|
1575
1598
|
spinner.stop();
|
|
@@ -2336,7 +2359,7 @@ initialPlan) {
|
|
|
2336
2359
|
const detectedContext = { current: 0 };
|
|
2337
2360
|
if (!config.contextTokens) {
|
|
2338
2361
|
const provider = resolveProvider(config.provider, config.baseURL);
|
|
2339
|
-
void fetchModelContextLimit(provider.baseURL, config.apiKey ?? getApiKey(provider), config.model)
|
|
2362
|
+
void fetchModelContextLimit(provider.baseURL, config.apiKey ?? getApiKey(provider, undefined, config.stateHome), config.model)
|
|
2340
2363
|
.then(reported => {
|
|
2341
2364
|
if (!reported)
|
|
2342
2365
|
return;
|