koneck 2.25.56 → 2.25.58
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/glyphs.d.ts +2 -0
- package/dist/glyphs.d.ts.map +1 -1
- package/dist/glyphs.js +2 -0
- package/dist/glyphs.js.map +1 -1
- package/dist/ink-chat.d.ts +28 -0
- package/dist/ink-chat.d.ts.map +1 -1
- package/dist/ink-chat.js +88 -9
- package/dist/ink-chat.js.map +1 -1
- package/dist/logo.d.ts +5 -1
- package/dist/logo.d.ts.map +1 -1
- package/dist/logo.js +5 -5
- package/dist/logo.js.map +1 -1
- package/dist/redact.d.ts +21 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +61 -0
- package/dist/redact.js.map +1 -0
- package/dist/session.d.ts +14 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +8 -4
- package/dist/session.js.map +1 -1
- package/package.json +1 -1
package/dist/glyphs.d.ts
CHANGED
package/dist/glyphs.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glyphs.d.ts","sourceRoot":"","sources":["../src/glyphs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,yFAAyF;IACzF,KAAK,EAAE,OAAO,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"glyphs.d.ts","sourceRoot":"","sources":["../src/glyphs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,QAAQ;IACvB,oCAAoC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,kDAAkD;IAClD,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB,4BAA4B;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,yFAAyF;IACzF,KAAK,EAAE,OAAO,CAAC;CAChB;AA6BD;;;;;;GAMG;AACH,wBAAgB,UAAU,CACxB,QAAQ,GAAE,MAAyB,EACnC,QAAQ,GAAE,MAAM,GAAG,SAAwC,EAC3D,IAAI,GAAE,MAAM,GAAG,SAA+B,GAC7C,QAAQ,CAKV;AAED,eAAO,MAAM,CAAC,EAAE,QAAuB,CAAC"}
|
package/dist/glyphs.js
CHANGED
|
@@ -18,6 +18,7 @@ const UNICODE = {
|
|
|
18
18
|
ok: '✓',
|
|
19
19
|
fail: '✖',
|
|
20
20
|
ellipsis: '…',
|
|
21
|
+
search: '⌕',
|
|
21
22
|
left: '←',
|
|
22
23
|
right: '→',
|
|
23
24
|
spinner: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],
|
|
@@ -30,6 +31,7 @@ const ASCII = {
|
|
|
30
31
|
ok: '+',
|
|
31
32
|
fail: 'x',
|
|
32
33
|
ellipsis: '...',
|
|
34
|
+
search: '/',
|
|
33
35
|
left: '<',
|
|
34
36
|
right: '>',
|
|
35
37
|
spinner: ['|', '/', '-', '\\'],
|
package/dist/glyphs.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"glyphs.js","sourceRoot":"","sources":["../src/glyphs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"glyphs.js","sourceRoot":"","sources":["../src/glyphs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAuBH,MAAM,OAAO,GAAa;IACxB,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,GAAG;IACV,EAAE,EAAE,GAAG;IACP,IAAI,EAAE,GAAG;IACT,QAAQ,EAAE,GAAG;IACb,MAAM,EAAE,GAAG;IACX,IAAI,EAAE,GAAG;IACT,KAAK,EAAE,GAAG;IACV,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;IAC3D,KAAK,EAAE,KAAK;CACb,CAAC;AAEF,MAAM,KAAK,GAAa;IACtB,iGAAiG;IACjG,KAAK,EAAE,IAAI;IACX,KAAK,EAAE,GAAG;IACV,EAAE,EAAE,GAAG;IACP,IAAI,EAAE,GAAG;IACT,QAAQ,EAAE,KAAK;IACf,MAAM,EAAE,GAAG;IACX,IAAI,EAAE,GAAG;IACT,KAAK,EAAE,GAAG;IACV,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC;IAC9B,KAAK,EAAE,IAAI;CACZ,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CACxB,WAAmB,OAAO,CAAC,QAAQ,EACnC,WAA+B,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,EAC3D,OAA2B,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;IAE9C,IAAI,QAAQ,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,OAAO,CAAC;IAC3C,IAAI,IAAI,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAClC,OAAO,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,MAAM,CAAC,GAAa,UAAU,EAAE,CAAC"}
|
package/dist/ink-chat.d.ts
CHANGED
|
@@ -143,6 +143,34 @@ export declare function pasteTarget(open: {
|
|
|
143
143
|
picker?: boolean;
|
|
144
144
|
ask?: boolean;
|
|
145
145
|
}): PasteTarget;
|
|
146
|
+
/** Bytes as a person reads them, for a session listing. */
|
|
147
|
+
export declare function humanBytes(bytes: number): string;
|
|
148
|
+
/**
|
|
149
|
+
* What to call a session in a list.
|
|
150
|
+
*
|
|
151
|
+
* A name if one was given, otherwise the first thing asked of it — which is what people remember
|
|
152
|
+
* a piece of work by. The id is the last resort, because a timestamp identifies nothing.
|
|
153
|
+
*/
|
|
154
|
+
export declare function sessionTitle(meta: {
|
|
155
|
+
name?: string;
|
|
156
|
+
task?: string;
|
|
157
|
+
id: string;
|
|
158
|
+
}): string;
|
|
159
|
+
/**
|
|
160
|
+
* The line at the top right of a picker.
|
|
161
|
+
*
|
|
162
|
+
* Says where you are, not merely how many rows exist — and says when a filter is hiding some,
|
|
163
|
+
* which "9 matches" cannot. A list that silently narrowed as you typed was indistinguishable
|
|
164
|
+
* from one that had mysteriously changed.
|
|
165
|
+
*/
|
|
166
|
+
export declare function pickerCountText(selected: number, shown: number, total: number): string;
|
|
167
|
+
/**
|
|
168
|
+
* How much of a row belongs to the label.
|
|
169
|
+
*
|
|
170
|
+
* Sized from the rows actually on screen rather than fixed: a session title is what identifies
|
|
171
|
+
* its row, and the constant 36 that was here cut most of them in half.
|
|
172
|
+
*/
|
|
173
|
+
export declare function pickerLabelWidth(labels: readonly string[], descs: readonly string[], width: number): number;
|
|
146
174
|
export declare function runInkChatMode(config: AgentConfig): Promise<void>;
|
|
147
175
|
export {};
|
|
148
176
|
//# sourceMappingURL=ink-chat.d.ts.map
|
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":"AAgDA,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
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
|
@@ -36,6 +36,7 @@ import { AskQueue } from './ask-queue.js';
|
|
|
36
36
|
import { planSummary } from './plan.js';
|
|
37
37
|
import { logoFor } from './logo.js';
|
|
38
38
|
import { describeActivity } from './activity.js';
|
|
39
|
+
import { redactSecrets, containsSecret } from './redact.js';
|
|
39
40
|
import { renderTrajectory } from './trajectory.js';
|
|
40
41
|
import { describeSandbox, resolveSandbox } from './sandbox.js';
|
|
41
42
|
const CYAN = '#54D7E7';
|
|
@@ -571,6 +572,53 @@ export function pasteTarget(open) {
|
|
|
571
572
|
return 'drop';
|
|
572
573
|
return 'composer';
|
|
573
574
|
}
|
|
575
|
+
/** Bytes as a person reads them, for a session listing. */
|
|
576
|
+
export function humanBytes(bytes) {
|
|
577
|
+
if (bytes < 1024)
|
|
578
|
+
return `${bytes}B`;
|
|
579
|
+
if (bytes < 1024 * 1024)
|
|
580
|
+
return `${(bytes / 1024).toFixed(1)}KB`;
|
|
581
|
+
return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* What to call a session in a list.
|
|
585
|
+
*
|
|
586
|
+
* A name if one was given, otherwise the first thing asked of it — which is what people remember
|
|
587
|
+
* a piece of work by. The id is the last resort, because a timestamp identifies nothing.
|
|
588
|
+
*/
|
|
589
|
+
export function sessionTitle(meta) {
|
|
590
|
+
if (meta.name)
|
|
591
|
+
return meta.name;
|
|
592
|
+
const task = redactSecrets(meta.task ?? '').replace(/\s+/g, ' ').trim();
|
|
593
|
+
if (!task || task === '(chat session)')
|
|
594
|
+
return meta.id;
|
|
595
|
+
return task.length > 64 ? task.slice(0, 63) + '…' : task;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* The line at the top right of a picker.
|
|
599
|
+
*
|
|
600
|
+
* Says where you are, not merely how many rows exist — and says when a filter is hiding some,
|
|
601
|
+
* which "9 matches" cannot. A list that silently narrowed as you typed was indistinguishable
|
|
602
|
+
* from one that had mysteriously changed.
|
|
603
|
+
*/
|
|
604
|
+
export function pickerCountText(selected, shown, total) {
|
|
605
|
+
if (shown === 0)
|
|
606
|
+
return 'no matches · esc to close';
|
|
607
|
+
return `${selected + 1} of ${shown}` +
|
|
608
|
+
(shown < total ? ` (filtered from ${total})` : '') +
|
|
609
|
+
' · esc to close';
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* How much of a row belongs to the label.
|
|
613
|
+
*
|
|
614
|
+
* Sized from the rows actually on screen rather than fixed: a session title is what identifies
|
|
615
|
+
* its row, and the constant 36 that was here cut most of them in half.
|
|
616
|
+
*/
|
|
617
|
+
export function pickerLabelWidth(labels, descs, width) {
|
|
618
|
+
const longestDesc = Math.max(0, ...descs.map(d => d.length));
|
|
619
|
+
const longestLabel = Math.max(18, ...labels.map(l => l.length));
|
|
620
|
+
return Math.max(18, Math.min(longestLabel, width - longestDesc - 4));
|
|
621
|
+
}
|
|
574
622
|
const MODES = MODE_SPECS.map(m => m.name);
|
|
575
623
|
const HELP_TEXT = `
|
|
576
624
|
Type / on an empty line to browse every command; keep typing to filter.
|
|
@@ -1242,8 +1290,12 @@ function App({ config: initialConfig }) {
|
|
|
1242
1290
|
async function doSave() {
|
|
1243
1291
|
const s = await activeSession.p.catch(() => null);
|
|
1244
1292
|
const firstUser = s?.messages.find((m) => m.role === 'user');
|
|
1293
|
+
// Masked before it is written. A key pasted into the composer became the first user message,
|
|
1294
|
+
// which is where this title comes from — so it was persisted to disk and then printed in the
|
|
1295
|
+
// resume picker in full.
|
|
1245
1296
|
const task = firstUser && typeof firstUser.content === 'string'
|
|
1246
|
-
? firstUser.content.slice(0, 120)
|
|
1297
|
+
? redactSecrets(firstUser.content).slice(0, 120)
|
|
1298
|
+
: '(chat session)';
|
|
1247
1299
|
// Both of these come from the live session rather than from React state: a save fired at the
|
|
1248
1300
|
// end of a turn runs inside a closure that captured state as it was when the turn began, so
|
|
1249
1301
|
// reading `stats` here recorded turn counts one behind and, after a resume, the wrong id.
|
|
@@ -1253,8 +1305,14 @@ function App({ config: initialConfig }) {
|
|
|
1253
1305
|
// runs every turn would otherwise wipe a name the moment the agent replied.
|
|
1254
1306
|
const existing = await loadSession(cfg.cwd, id).then(r => r.meta).catch(() => null);
|
|
1255
1307
|
const livePlan = s?.plan?.steps.length ? { steps: s.plan.steps } : undefined;
|
|
1308
|
+
// Captured when saving, because a branch cannot be recovered from the file later — by then the
|
|
1309
|
+
// checkout has moved on.
|
|
1310
|
+
const branch = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: cfg.cwd, reject: false })
|
|
1311
|
+
.then(r => r.stdout.trim())
|
|
1312
|
+
.catch(() => '');
|
|
1256
1313
|
return saveSession(cfg.cwd, id, {
|
|
1257
1314
|
...(livePlan ? { plan: livePlan } : {}),
|
|
1315
|
+
...(branch && branch !== 'HEAD' ? { branch } : {}),
|
|
1258
1316
|
...(existing?.name ? { name: existing.name } : {}),
|
|
1259
1317
|
...(existing?.archived ? { archived: existing.archived } : {}),
|
|
1260
1318
|
...(existing?.forkedFrom ? { forkedFrom: existing.forkedFrom } : {}),
|
|
@@ -1950,13 +2008,21 @@ function App({ config: initialConfig }) {
|
|
|
1950
2008
|
return;
|
|
1951
2009
|
}
|
|
1952
2010
|
if (pick === '') {
|
|
2011
|
+
// The title comes first because that is what tells two sessions apart; the id is a
|
|
2012
|
+
// timestamp and says only when. Everything under it is context: how long ago, which
|
|
2013
|
+
// branch, how much work. Masked on display as well as on write, since the files already
|
|
2014
|
+
// on disk were written before that existed and one of them holds a key.
|
|
1953
2015
|
openPicker('resume', saved.slice(0, 20).map((x, i) => ({
|
|
1954
2016
|
value: x.id,
|
|
1955
|
-
label: x
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
2017
|
+
label: sessionTitle(x),
|
|
2018
|
+
desc: [
|
|
2019
|
+
i === 0 ? 'latest' : relativeAge(x.updatedAt),
|
|
2020
|
+
...(i === 0 ? [relativeAge(x.updatedAt)] : []),
|
|
2021
|
+
...(x.branch ? [x.branch] : []),
|
|
2022
|
+
`${x.turns} turn${x.turns === 1 ? '' : 's'}`,
|
|
2023
|
+
...(x.totalTokens > 0 ? [`${humanTokens(x.totalTokens)} tok`] : []),
|
|
2024
|
+
...(x.sizeBytes ? [humanBytes(x.sizeBytes)] : []),
|
|
2025
|
+
].join(' · '),
|
|
1960
2026
|
})));
|
|
1961
2027
|
return;
|
|
1962
2028
|
}
|
|
@@ -2783,6 +2849,13 @@ function App({ config: initialConfig }) {
|
|
|
2783
2849
|
setPasteCount(0);
|
|
2784
2850
|
// Paths that really exist are shortened to their name for the transcript only. The model
|
|
2785
2851
|
// still receives the full path, which it needs in order to open the file.
|
|
2852
|
+
// Said out loud rather than quietly sent. A key in a prompt reaches the provider, the
|
|
2853
|
+
// session file and the scrollback, and the only useful moment to mention it is now.
|
|
2854
|
+
if (containsSecret(task)) {
|
|
2855
|
+
addSystem('That looks like an API key or token. It has been sent as typed — treat it as exposed ' +
|
|
2856
|
+
'and rotate it. Keys belong in /key or an environment variable, where they are not ' +
|
|
2857
|
+
'written into the session log.');
|
|
2858
|
+
}
|
|
2786
2859
|
const mentions = findMentions(task, pathKind);
|
|
2787
2860
|
const forDisplay = pasteForDisplay(mentions.length ? shortenMentions(task, mentions) : task);
|
|
2788
2861
|
addRow({ role: 'user', text: forDisplay });
|
|
@@ -3270,19 +3343,25 @@ function App({ config: initialConfig }) {
|
|
|
3270
3343
|
// screen a list of short model names in a full-width box is mostly empty box.
|
|
3271
3344
|
// The header is a title on the left and a count on the right, on one line. Estimating the
|
|
3272
3345
|
// right-hand side at a constant made "Reference a file or directory" wrap onto two rows.
|
|
3273
|
-
const countText =
|
|
3346
|
+
const countText = pickerCountText(pickIndex, list.length, picker.items.length);
|
|
3274
3347
|
const headWidth = title.length + countText.length + 3;
|
|
3275
3348
|
const rowWidth = Math.max(headWidth, ...shown.map(it => 38 + (it.current ? 10 : 0) + it.desc.length));
|
|
3276
3349
|
const boxWidth = Math.max(40, Math.min(barWidth, rowWidth + 4));
|
|
3277
3350
|
const width = boxWidth - 4;
|
|
3351
|
+
// Room for the longest label the list actually holds, rather than a constant. A session
|
|
3352
|
+
// title is what identifies the row, and 36 cells cut most of them in half.
|
|
3353
|
+
const labelWidth = pickerLabelWidth(shown.map(it => it.label), shown.map(it => it.desc), width);
|
|
3278
3354
|
let lastGroup;
|
|
3279
|
-
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 })] }),
|
|
3355
|
+
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 === ''
|
|
3356
|
+
? _jsx(Text, { color: DIM, children: "type to search" })
|
|
3357
|
+
: _jsx(Text, { color: INK, children: pickQuery }), _jsx(Text, { color: CYAN, children: pickQuery === '' ? '' : '▌' })] }), list.length === 0 && _jsxs(Text, { color: MUTED, children: ["Nothing matches \"", pickQuery, "\""] }), shown.map((item, i) => {
|
|
3280
3358
|
const absolute = Math.max(0, start) + i;
|
|
3281
3359
|
const selected = absolute === pickIndex;
|
|
3282
3360
|
const header = item.group && item.group !== lastGroup ? item.group : null;
|
|
3283
3361
|
lastGroup = item.group;
|
|
3284
3362
|
const label = item.label.length > 34 ? item.label.slice(0, 31) + '...' : item.label;
|
|
3285
|
-
return (_jsxs(Box, { flexDirection: "column", children: [header && _jsx(Text, { color: DIM, children: header }), _jsx(Text, { backgroundColor: selected ? CYAN : undefined, color: selected ? '#10222A' : INK, bold: selected, children: fitCells(`${selected ? G.caret + ' ' : ' '}${fitCells(label,
|
|
3363
|
+
return (_jsxs(Box, { flexDirection: "column", children: [header && _jsx(Text, { color: DIM, children: header }), _jsx(Text, { backgroundColor: selected ? CYAN : undefined, color: selected ? '#10222A' : INK, bold: selected, children: fitCells(`${selected ? G.caret + ' ' : ' '}${fitCells(label, labelWidth)}` +
|
|
3364
|
+
`${item.current ? '(current) ' : ''}${item.desc}`, width) })] }, item.value + absolute));
|
|
3286
3365
|
}), list.length > PICKER_ROWS && (_jsxs(Text, { color: DIM, children: ["\u2191\u2193 navigate \u00B7 enter select \u00B7 showing ", Math.max(0, start) + 1, "\u2013", Math.max(0, start) + shown.length, " of ", list.length] }))] }));
|
|
3287
3366
|
})(), 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 && (() => {
|
|
3288
3367
|
let detail = '';
|