koneck 2.27.0 → 2.28.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/doctor.d.ts +13 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +43 -2
- package/dist/doctor.js.map +1 -1
- package/dist/ink-chat.d.ts +9 -0
- package/dist/ink-chat.d.ts.map +1 -1
- package/dist/ink-chat.js +113 -6
- package/dist/ink-chat.js.map +1 -1
- package/dist/web/api.d.ts.map +1 -1
- package/dist/web/api.js +66 -5
- package/dist/web/api.js.map +1 -1
- package/dist/web/files.d.ts +43 -0
- package/dist/web/files.d.ts.map +1 -0
- package/dist/web/files.js +131 -0
- package/dist/web/files.js.map +1 -0
- package/dist/web/search.d.ts +45 -0
- package/dist/web/search.d.ts.map +1 -0
- package/dist/web/search.js +147 -0
- package/dist/web/search.js.map +1 -0
- package/dist/web/ui-client.d.ts.map +1 -1
- package/dist/web/ui-client.js +0 -0
- 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 +45 -0
- package/dist/web/ui-css.js.map +1 -1
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +29 -0
- package/dist/web/ui.js.map +1 -1
- package/dist/workspace-trust.d.ts +8 -0
- package/dist/workspace-trust.d.ts.map +1 -1
- package/dist/workspace-trust.js +11 -0
- package/dist/workspace-trust.js.map +1 -1
- package/package.json +1 -1
package/dist/doctor.d.ts
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
|
+
import { type ProviderDef } from './providers.js';
|
|
1
2
|
export type DoctorStatus = 'pass' | 'warn' | 'fail';
|
|
2
3
|
export interface DoctorCheck {
|
|
3
4
|
status: DoctorStatus;
|
|
4
5
|
name: string;
|
|
5
6
|
reason?: string;
|
|
6
7
|
}
|
|
8
|
+
type FetchLike = (input: string, init?: RequestInit) => Promise<{
|
|
9
|
+
ok: boolean;
|
|
10
|
+
status: number;
|
|
11
|
+
}>;
|
|
12
|
+
/**
|
|
13
|
+
* Verify that an OpenAI-compatible endpoint is reachable without spending tokens or changing
|
|
14
|
+
* anything. A successful `/models` response proves the whole route; an HTTP response still
|
|
15
|
+
* distinguishes a reachable-but-misconfigured endpoint from a dead network.
|
|
16
|
+
*/
|
|
17
|
+
export declare function providerConnectionCheck(def: ProviderDef, apiKey?: string, fetcher?: FetchLike): Promise<DoctorCheck>;
|
|
7
18
|
/**
|
|
8
19
|
* Inspect the environment needed for a useful coding session.
|
|
9
20
|
*
|
|
10
21
|
* Kept separate from printing so the same truthful diagnosis can be used before startup and
|
|
11
22
|
* from an already-running chat, where the selected provider may differ from global config.
|
|
12
23
|
*/
|
|
13
|
-
export declare function doctorChecks(cwd: string, activeProvider?: string): Promise<DoctorCheck[]>;
|
|
24
|
+
export declare function doctorChecks(cwd: string, activeProvider?: string, activeBaseURL?: string, activeApiKey?: string, fetcher?: FetchLike): Promise<DoctorCheck[]>;
|
|
14
25
|
/** A compact, colour-free report for the interactive terminal and testable UI surfaces. */
|
|
15
26
|
export declare function doctorReport(results: readonly DoctorCheck[]): string;
|
|
16
27
|
export declare function runDoctor(cwd: string): Promise<void>;
|
|
28
|
+
export {};
|
|
17
29
|
//# sourceMappingURL=doctor.d.ts.map
|
package/dist/doctor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAyC,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGzF,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,CAoBtB;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,CA0FxB;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,8 +3,40 @@ 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 } from './providers.js';
|
|
6
|
+
import { PROVIDERS, getApiKey, resolveProvider } from './providers.js';
|
|
7
7
|
import { loadGlobalConfig } from './config.js';
|
|
8
|
+
/**
|
|
9
|
+
* Verify that an OpenAI-compatible endpoint is reachable without spending tokens or changing
|
|
10
|
+
* anything. A successful `/models` response proves the whole route; an HTTP response still
|
|
11
|
+
* distinguishes a reachable-but-misconfigured endpoint from a dead network.
|
|
12
|
+
*/
|
|
13
|
+
export async function providerConnectionCheck(def, apiKey, fetcher = fetch) {
|
|
14
|
+
let key;
|
|
15
|
+
try {
|
|
16
|
+
key = getApiKey(def, apiKey);
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return { status: 'warn', name: 'Provider connection', reason: 'not checked — no API key available' };
|
|
20
|
+
}
|
|
21
|
+
const url = def.baseURL.replace(/\/+$/, '') + '/models';
|
|
22
|
+
try {
|
|
23
|
+
const response = await fetcher(url, {
|
|
24
|
+
method: 'GET',
|
|
25
|
+
headers: { ...def.extraHeaders, Authorization: `Bearer ${key}` },
|
|
26
|
+
signal: AbortSignal.timeout(5_000),
|
|
27
|
+
});
|
|
28
|
+
if (response.ok)
|
|
29
|
+
return { status: 'pass', name: 'Provider connection', reason: def.baseURL };
|
|
30
|
+
if (response.status === 401 || response.status === 403) {
|
|
31
|
+
return { status: 'fail', name: 'Provider connection', reason: `endpoint rejected the credential (HTTP ${response.status})` };
|
|
32
|
+
}
|
|
33
|
+
return { status: 'warn', name: 'Provider connection', reason: `endpoint responded HTTP ${response.status} at ${def.baseURL}` };
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
37
|
+
return { status: 'fail', name: 'Provider connection', reason: `could not reach ${def.baseURL} — ${message}` };
|
|
38
|
+
}
|
|
39
|
+
}
|
|
8
40
|
function printResult(r) {
|
|
9
41
|
if (r.status === 'pass') {
|
|
10
42
|
console.log(chalk.green(` ✔ ${r.name}`));
|
|
@@ -22,7 +54,7 @@ function printResult(r) {
|
|
|
22
54
|
* Kept separate from printing so the same truthful diagnosis can be used before startup and
|
|
23
55
|
* from an already-running chat, where the selected provider may differ from global config.
|
|
24
56
|
*/
|
|
25
|
-
export async function doctorChecks(cwd, activeProvider) {
|
|
57
|
+
export async function doctorChecks(cwd, activeProvider, activeBaseURL, activeApiKey, fetcher) {
|
|
26
58
|
const results = [];
|
|
27
59
|
const nodeVersion = parseInt(process.version.slice(1), 10);
|
|
28
60
|
results.push(nodeVersion >= 20
|
|
@@ -56,6 +88,15 @@ export async function doctorChecks(cwd, activeProvider) {
|
|
|
56
88
|
results.push(apiKeyFound
|
|
57
89
|
? { status: 'pass', name: 'API key' }
|
|
58
90
|
: { status: 'warn', name: 'API key', reason: 'no API key found in environment' });
|
|
91
|
+
// The running chat can be aimed at a session-only endpoint/key. Doctor must test what the
|
|
92
|
+
// developer is actually using, rather than silently falling back to a global config value.
|
|
93
|
+
if (providerDef) {
|
|
94
|
+
const resolved = resolveProvider(provider, activeBaseURL);
|
|
95
|
+
results.push(await providerConnectionCheck(resolved, activeApiKey, fetcher));
|
|
96
|
+
}
|
|
97
|
+
else if (provider) {
|
|
98
|
+
results.push({ status: 'warn', name: 'Provider connection', reason: `cannot probe unknown provider "${provider}"` });
|
|
99
|
+
}
|
|
59
100
|
try {
|
|
60
101
|
await execa('git', ['--version']);
|
|
61
102
|
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,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/ink-chat.d.ts
CHANGED
|
@@ -116,6 +116,15 @@ export declare function pickerRowLimit(kind: PickerKind, itemCount: number, term
|
|
|
116
116
|
* ignored so "/mo" and "mo" behave the same.
|
|
117
117
|
*/
|
|
118
118
|
export declare function filterPickerItems(items: PickerItem[], query: string): PickerItem[];
|
|
119
|
+
/**
|
|
120
|
+
* Turns a near-miss slash command into a direct recovery path.
|
|
121
|
+
*
|
|
122
|
+
* We deliberately do not guess at distant names: a wrong suggestion steals attention, while
|
|
123
|
+
* catching one or two transposed/omitted characters makes command use feel forgiving.
|
|
124
|
+
*/
|
|
125
|
+
export declare function commandSuggestion(command: string, commands?: string[]): string | undefined;
|
|
126
|
+
/** Keep a small, useful recall buffer without repeating the same submitted task. */
|
|
127
|
+
export declare function appendDraftHistory(history: readonly string[], draft: string, limit?: number): string[];
|
|
119
128
|
/** One answer to a permission question: what it says, what it grants, and whether it permits. */
|
|
120
129
|
interface AskOption {
|
|
121
130
|
key: string;
|
package/dist/ink-chat.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ink-chat.d.ts","sourceRoot":"","sources":["../src/ink-chat.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ink-chat.d.ts","sourceRoot":"","sources":["../src/ink-chat.tsx"],"names":[],"mappings":"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"}
|
package/dist/ink-chat.js
CHANGED
|
@@ -623,6 +623,61 @@ export function filterPickerItems(items, query) {
|
|
|
623
623
|
}
|
|
624
624
|
return [...starts, ...contains];
|
|
625
625
|
}
|
|
626
|
+
/** The smallest number of character edits that turns one command into another. */
|
|
627
|
+
function commandDistance(a, b) {
|
|
628
|
+
// A transposed neighbouring pair is the commonest command typo (`/modle`). Treat it as one
|
|
629
|
+
// edit before using the ordinary insertion/deletion/substitution matrix below.
|
|
630
|
+
if (a.length === b.length) {
|
|
631
|
+
const mismatches = [...a].map((char, index) => char === b[index] ? -1 : index).filter(index => index >= 0);
|
|
632
|
+
if (mismatches.length === 2 && mismatches[1] === mismatches[0] + 1
|
|
633
|
+
&& a[mismatches[0]] === b[mismatches[1]]
|
|
634
|
+
&& a[mismatches[1]] === b[mismatches[0]])
|
|
635
|
+
return 1;
|
|
636
|
+
}
|
|
637
|
+
const previous = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
638
|
+
for (let i = 1; i <= a.length; i++) {
|
|
639
|
+
const current = [i];
|
|
640
|
+
for (let j = 1; j <= b.length; j++) {
|
|
641
|
+
current[j] = a[i - 1] === b[j - 1]
|
|
642
|
+
? previous[j - 1]
|
|
643
|
+
: 1 + Math.min(previous[j - 1], previous[j], current[j - 1]);
|
|
644
|
+
}
|
|
645
|
+
for (let j = 0; j <= b.length; j++)
|
|
646
|
+
previous[j] = current[j];
|
|
647
|
+
}
|
|
648
|
+
return previous[b.length];
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Turns a near-miss slash command into a direct recovery path.
|
|
652
|
+
*
|
|
653
|
+
* We deliberately do not guess at distant names: a wrong suggestion steals attention, while
|
|
654
|
+
* catching one or two transposed/omitted characters makes command use feel forgiving.
|
|
655
|
+
*/
|
|
656
|
+
export function commandSuggestion(command, commands = COMMANDS.map(item => item.cmd)) {
|
|
657
|
+
const wanted = command.trim().toLowerCase();
|
|
658
|
+
if (!wanted.startsWith('/'))
|
|
659
|
+
return undefined;
|
|
660
|
+
const maxDistance = wanted.length <= 5 ? 1 : wanted.length <= 9 ? 2 : 3;
|
|
661
|
+
let best;
|
|
662
|
+
let distance = Number.POSITIVE_INFINITY;
|
|
663
|
+
for (const candidate of commands) {
|
|
664
|
+
const d = commandDistance(wanted, candidate.toLowerCase());
|
|
665
|
+
// At the same edit distance, preserve as much of what the user typed as possible. For
|
|
666
|
+
// `/modle`, `/model` is more likely than the shorter `/mode` even though both are two edits.
|
|
667
|
+
if (d < distance || (d === distance && (!best || Math.abs(candidate.length - wanted.length) < Math.abs(best.length - wanted.length)))) {
|
|
668
|
+
best = candidate;
|
|
669
|
+
distance = d;
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
return distance <= maxDistance ? best : undefined;
|
|
673
|
+
}
|
|
674
|
+
/** Keep a small, useful recall buffer without repeating the same submitted task. */
|
|
675
|
+
export function appendDraftHistory(history, draft, limit = 100) {
|
|
676
|
+
const entry = draft.trim();
|
|
677
|
+
if (entry === '' || history.at(-1) === entry)
|
|
678
|
+
return [...history];
|
|
679
|
+
return [...history, entry].slice(-Math.max(1, limit));
|
|
680
|
+
}
|
|
626
681
|
/**
|
|
627
682
|
* The choices offered for one waiting tool call.
|
|
628
683
|
*
|
|
@@ -1116,6 +1171,11 @@ function App({ config: initialConfig, clearFrame }) {
|
|
|
1116
1171
|
}))[0];
|
|
1117
1172
|
const [rows, setRows] = useState([{ role: 'header' }]);
|
|
1118
1173
|
const [draft, setDraft] = useState('');
|
|
1174
|
+
// Recall is deliberately session-local. It is for quick retries and refinements, not another
|
|
1175
|
+
// persistence channel for prompts (which may contain sensitive project context).
|
|
1176
|
+
const draftHistoryRef = useRef([]);
|
|
1177
|
+
const historyIndexRef = useRef(null);
|
|
1178
|
+
const historyDraftRef = useRef('');
|
|
1119
1179
|
/** Caret offset into `draft`. Kept beside it so every edit can place the caret deliberately. */
|
|
1120
1180
|
const [caret, setCaret] = useState(0);
|
|
1121
1181
|
const [busy, setBusy] = useState(false);
|
|
@@ -1571,6 +1631,37 @@ function App({ config: initialConfig, clearFrame }) {
|
|
|
1571
1631
|
useEffect(() => { void snapshotTree(cfg.cwd).then(t => { baseTreeRef.current = t; }); }, [cfg.cwd]);
|
|
1572
1632
|
const addRow = (row) => setRows(prev => [...prev, row]);
|
|
1573
1633
|
const addSystem = (text) => addRow({ role: 'system', text });
|
|
1634
|
+
/** Walk submitted composer entries without losing whatever was being typed now. */
|
|
1635
|
+
function recallDraft(direction) {
|
|
1636
|
+
const history = draftHistoryRef.current;
|
|
1637
|
+
if (history.length === 0)
|
|
1638
|
+
return;
|
|
1639
|
+
const current = historyIndexRef.current;
|
|
1640
|
+
if (direction === -1) {
|
|
1641
|
+
if (current === null)
|
|
1642
|
+
historyDraftRef.current = draft;
|
|
1643
|
+
const next = current === null ? history.length - 1 : Math.max(0, current - 1);
|
|
1644
|
+
historyIndexRef.current = next;
|
|
1645
|
+
const recalled = history[next];
|
|
1646
|
+
setDraft(recalled);
|
|
1647
|
+
setCaret(recalled.length);
|
|
1648
|
+
return;
|
|
1649
|
+
}
|
|
1650
|
+
if (current === null)
|
|
1651
|
+
return;
|
|
1652
|
+
const next = current + 1;
|
|
1653
|
+
if (next >= history.length) {
|
|
1654
|
+
historyIndexRef.current = null;
|
|
1655
|
+
const restored = historyDraftRef.current;
|
|
1656
|
+
setDraft(restored);
|
|
1657
|
+
setCaret(restored.length);
|
|
1658
|
+
return;
|
|
1659
|
+
}
|
|
1660
|
+
historyIndexRef.current = next;
|
|
1661
|
+
const recalled = history[next];
|
|
1662
|
+
setDraft(recalled);
|
|
1663
|
+
setCaret(recalled.length);
|
|
1664
|
+
}
|
|
1574
1665
|
async function getSession() {
|
|
1575
1666
|
return activeSession.p;
|
|
1576
1667
|
}
|
|
@@ -2149,7 +2240,7 @@ function App({ config: initialConfig, clearFrame }) {
|
|
|
2149
2240
|
// rather than a stale global default.
|
|
2150
2241
|
addSystem(`**KONECK Doctor** — checking ${cfg.provider} and this workspace…`);
|
|
2151
2242
|
try {
|
|
2152
|
-
const checks = await doctorChecks(cfg.cwd, cfg.provider);
|
|
2243
|
+
const checks = await doctorChecks(cfg.cwd, cfg.provider, cfg.baseURL, cfg.apiKey);
|
|
2153
2244
|
setRows(prev => prev.slice(0, -1));
|
|
2154
2245
|
addSystem(`**KONECK Doctor**\n\n${doctorReport(checks)}`);
|
|
2155
2246
|
}
|
|
@@ -2912,7 +3003,12 @@ function App({ config: initialConfig, clearFrame }) {
|
|
|
2912
3003
|
return;
|
|
2913
3004
|
}
|
|
2914
3005
|
default:
|
|
2915
|
-
|
|
3006
|
+
{
|
|
3007
|
+
const suggestion = commandSuggestion(cmd);
|
|
3008
|
+
addSystem(suggestion
|
|
3009
|
+
? `Unknown command: ${cmd}. Did you mean \`${suggestion}\`?`
|
|
3010
|
+
: `Unknown command: ${cmd}. Type /help for the full list.`);
|
|
3011
|
+
}
|
|
2916
3012
|
}
|
|
2917
3013
|
}
|
|
2918
3014
|
/**
|
|
@@ -3358,6 +3454,14 @@ function App({ config: initialConfig, clearFrame }) {
|
|
|
3358
3454
|
// The composer used to be append-and-backspace only, so fixing a typo near the start of a
|
|
3359
3455
|
// long prompt meant deleting everything after it. Everything below is the readline set a
|
|
3360
3456
|
// shell gives you, so an edit costs one keystroke rather than a retype.
|
|
3457
|
+
if (key.upArrow) {
|
|
3458
|
+
recallDraft(-1);
|
|
3459
|
+
return;
|
|
3460
|
+
}
|
|
3461
|
+
if (key.downArrow) {
|
|
3462
|
+
recallDraft(1);
|
|
3463
|
+
return;
|
|
3464
|
+
}
|
|
3361
3465
|
if (key.leftArrow) {
|
|
3362
3466
|
const step = 1 + takeBurst('left');
|
|
3363
3467
|
setCaret(c => (key.ctrl || key.meta ? wordStart(draft, c) : Math.max(0, c - step)));
|
|
@@ -4014,12 +4118,15 @@ function App({ config: initialConfig, clearFrame }) {
|
|
|
4014
4118
|
// right-hand side at a constant made "Reference a file or directory" wrap onto two rows.
|
|
4015
4119
|
const countText = pickerCountText(pickIndex, list.length, picker.items.length);
|
|
4016
4120
|
const headWidth = title.length + countText.length + 3;
|
|
4017
|
-
|
|
4121
|
+
// Measure the filtered list, not just its current scroll window. A palette whose right
|
|
4122
|
+
// edge breathes as the highlight crosses a long description feels broken even when the
|
|
4123
|
+
// selection itself is correct.
|
|
4124
|
+
const rowWidth = Math.max(headWidth, ...list.map(it => 38 + (it.current ? 10 : 0) + it.desc.length + (it.group?.length ?? 0) + 3));
|
|
4018
4125
|
const boxWidth = Math.max(40, Math.min(barWidth, rowWidth + 4));
|
|
4019
4126
|
const width = boxWidth - 4;
|
|
4020
4127
|
// Room for the longest label the list actually holds, rather than a constant. A session
|
|
4021
4128
|
// title is what identifies the row, and 36 cells cut most of them in half.
|
|
4022
|
-
const labelWidth = pickerLabelWidth(
|
|
4129
|
+
const labelWidth = pickerLabelWidth(list.map(it => it.label), list.map(it => it.desc), width);
|
|
4023
4130
|
let lastGroup;
|
|
4024
4131
|
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: CYAN, paddingX: 1, marginTop: 1, width: boxWidth, children: [_jsxs(Box, { justifyContent: "space-between", children: [_jsx(Text, { color: CYAN, bold: true, children: title }), _jsx(Text, { color: DIM, children: countText })] }), _jsxs(Box, { children: [_jsxs(Text, { color: DIM, children: [G.search, " "] }), pickQuery === ''
|
|
4025
4132
|
? _jsx(Text, { color: DIM, children: "type to search" })
|
|
@@ -4029,8 +4136,8 @@ function App({ config: initialConfig, clearFrame }) {
|
|
|
4029
4136
|
const header = item.group && item.group !== lastGroup ? item.group : null;
|
|
4030
4137
|
lastGroup = item.group;
|
|
4031
4138
|
const label = item.label.length > 34 ? item.label.slice(0, 31) + '...' : item.label;
|
|
4032
|
-
return (
|
|
4033
|
-
|
|
4139
|
+
return (_jsx(Box, { flexDirection: "column", children: _jsx(Text, { backgroundColor: selected ? CYAN : undefined, color: selected ? '#10222A' : INK, bold: selected, children: fitCells(`${selected ? G.caret + ' ' : ' '}${fitCells(label, labelWidth)}` +
|
|
4140
|
+
`${item.current ? '(current) ' : ''}${header ? `${header} · ` : ''}${item.desc}`, width) }) }, item.value + absolute));
|
|
4034
4141
|
}), list.length > pickerRows && (_jsxs(Text, { color: DIM, children: ["\u2191\u2193 navigate \u00B7 pgup/pgdn jump \u00B7 enter select \u00B7 showing ", Math.max(0, start) + 1, "\u2013", Math.max(0, start) + shown.length, " of ", list.length] }))] }));
|
|
4035
4142
|
})(), keyPrompt && (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: AMBER, paddingX: 1, marginTop: 1, width: barWidth, children: [_jsxs(Text, { color: AMBER, bold: true, children: ["API key for ", keyPrompt.provider] }), _jsx(Text, { color: MUTED, children: "Paste it and press enter. Held in memory for this session only; esc to cancel." }), _jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: MUTED, children: [keyPrompt.env, ": "] }), _jsx(Text, { color: INK, children: '*'.repeat(Math.min(keyPrompt.value.length, 48)) }), _jsx(Text, { color: CYAN, children: "\u2588" })] })] })), ask && (() => {
|
|
4036
4143
|
let detail = '';
|