@vincemakes/kiso-code 0.44.0 → 0.45.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/chat.d.ts +3 -1
- package/dist/chat.js +92 -10
- package/dist/index.js +4 -0
- package/dist/state.d.ts +3 -0
- package/package.json +14 -14
package/dist/chat.d.ts
CHANGED
|
@@ -369,7 +369,9 @@ export declare function consumeRun(session: AgentSession, run: Run, input: LineI
|
|
|
369
369
|
/** W21: the amend words ("Yes + feedback") ride the NEXT user turn —
|
|
370
370
|
* threaded from chat's submitTurn; absent in the recovery flow
|
|
371
371
|
* (resume) where a dropped amend is noticed instead. */
|
|
372
|
-
submitTurn?: (line: string) => void
|
|
372
|
+
submitTurn?: (line: string) => void,
|
|
373
|
+
/** ADR-0057: a steer landed — an input after the run's own. */
|
|
374
|
+
onInputLanded?: () => void): Promise<import("@vincemakes/kiso-core").Event | undefined>;
|
|
373
375
|
/** Interactive REPL: stream events, pause for approvals, Ctrl+C aborts. */
|
|
374
376
|
/** The chat loop's ENDING: exit closes the process's REPL for good; a
|
|
375
377
|
* switch hands main another session id to re-enter chat with — the
|
package/dist/chat.js
CHANGED
|
@@ -10,7 +10,7 @@ import { askView, coldResumeLine, coldResumeView, deletionRiskHint, editFileDiff
|
|
|
10
10
|
import { canonicalTargetPath, isProtectedPath, protectedIdentity, shellProgressPath } from "@vincemakes/kiso-tools-node";
|
|
11
11
|
import { queuedSwitchLines } from "./state.js";
|
|
12
12
|
import { echoText } from "@vincemakes/kiso-tui-cells/render";
|
|
13
|
-
import { canonicalizeUsage } from "@vincemakes/kiso-runtime";
|
|
13
|
+
import { canonicalizeUsage, RunClosedError } from "@vincemakes/kiso-runtime";
|
|
14
14
|
import { canonicalizeUsageForModel, requestBudget } from "@vincemakes/kiso-runtime/internal";
|
|
15
15
|
import { dispatch, abortBangCommand } from "./dispatch.js";
|
|
16
16
|
import { paintWindowTitle } from "./window-title.js";
|
|
@@ -854,8 +854,11 @@ export async function consumeRun(session, run, input, turnNo, faux, statusCb,
|
|
|
854
854
|
/** W21: the amend words ("Yes + feedback") ride the NEXT user turn —
|
|
855
855
|
* threaded from chat's submitTurn; absent in the recovery flow
|
|
856
856
|
* (resume) where a dropped amend is noticed instead. */
|
|
857
|
-
submitTurn
|
|
857
|
+
submitTurn,
|
|
858
|
+
/** ADR-0057: a steer landed — an input after the run's own. */
|
|
859
|
+
onInputLanded) {
|
|
858
860
|
let last;
|
|
861
|
+
let inputsSeen = 0;
|
|
859
862
|
// W22: the TURN's usage — null until a call settles, then the sum of
|
|
860
863
|
// every call in this turn (accumulateUsage). Null rather than an empty
|
|
861
864
|
// accumulator, so the first call is the sum rather than an addition to
|
|
@@ -931,6 +934,9 @@ submitTurn) {
|
|
|
931
934
|
// construction (ADR-0040).
|
|
932
935
|
switch (ev.type) {
|
|
933
936
|
case "user_input":
|
|
937
|
+
inputsSeen += 1;
|
|
938
|
+
if (inputsSeen > 1)
|
|
939
|
+
onInputLanded?.();
|
|
934
940
|
// The window title is re-derived here because THIS is when a
|
|
935
941
|
// session stops being nameless: the tab opened as `kiso —
|
|
936
942
|
// <workspace>` and the first substantive prompt is what gives
|
|
@@ -1294,10 +1300,11 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1294
1300
|
(async () => {
|
|
1295
1301
|
let last;
|
|
1296
1302
|
try {
|
|
1297
|
-
last = await consumeRun(session, run, input, myTurn, faux, statusCb, submitTurn);
|
|
1303
|
+
last = await consumeRun(session, run, input, myTurn, faux, statusCb, submitTurn, landed);
|
|
1298
1304
|
stopSpinner();
|
|
1299
1305
|
paintIdle();
|
|
1300
1306
|
currentRun = null;
|
|
1307
|
+
handBack(run);
|
|
1301
1308
|
// 0.40.5: the kiso on disk may no longer be the one this
|
|
1302
1309
|
// session runs (an upgrade since it started) — said once per
|
|
1303
1310
|
// installed version (stale-version.ts).
|
|
@@ -1335,6 +1342,7 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1335
1342
|
}
|
|
1336
1343
|
console.error(`\n[run failed] ${err instanceof Error ? err.message : String(err)}\n`);
|
|
1337
1344
|
currentRun = null;
|
|
1345
|
+
handBack(run);
|
|
1338
1346
|
input.prompt();
|
|
1339
1347
|
resolve();
|
|
1340
1348
|
}
|
|
@@ -1347,6 +1355,7 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1347
1355
|
// aborted terminal, which the consumer keeps consuming.
|
|
1348
1356
|
console.log("\n[aborting run]");
|
|
1349
1357
|
pendingAsk?.();
|
|
1358
|
+
giveBack();
|
|
1350
1359
|
currentRun.abort();
|
|
1351
1360
|
}
|
|
1352
1361
|
else if (pendingAsk !== null) {
|
|
@@ -1379,6 +1388,7 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1379
1388
|
if (currentRun) {
|
|
1380
1389
|
console.log("\n[aborting run]");
|
|
1381
1390
|
pendingAsk?.();
|
|
1391
|
+
giveBack();
|
|
1382
1392
|
currentRun.abort();
|
|
1383
1393
|
}
|
|
1384
1394
|
});
|
|
@@ -1392,6 +1402,9 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1392
1402
|
return dispatch(line, dispatchCtx);
|
|
1393
1403
|
console.log("\n[redirecting run]");
|
|
1394
1404
|
pendingAsk?.();
|
|
1405
|
+
// ADR-0057: steers that had not landed ride the correction — one next
|
|
1406
|
+
// message, not a queue; the correction first (§3: it corrects them).
|
|
1407
|
+
const unsent = handed(currentRun.retract().length);
|
|
1395
1408
|
currentRun.abort();
|
|
1396
1409
|
// §3: a correction must run BEFORE the follow-ups queued earlier —
|
|
1397
1410
|
// it is a correction OF them. The existing slot mechanics compose
|
|
@@ -1406,9 +1419,9 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1406
1419
|
const jumped = pendingTurns.map((s) => ({ content: s.content, via: s.via }));
|
|
1407
1420
|
for (let i = jumped.length; i > 0; i -= 1)
|
|
1408
1421
|
popQueue();
|
|
1409
|
-
|
|
1422
|
+
queueTurn(unsent.length > 0 ? [line, ...unsent.map((u) => u.content)].join("\n\n") : line);
|
|
1410
1423
|
for (const j of jumped)
|
|
1411
|
-
|
|
1424
|
+
queueTurn(j.content, j.via);
|
|
1412
1425
|
});
|
|
1413
1426
|
// round 5 (P1-11): the PERSISTENT line listener is installed BEFORE the
|
|
1414
1427
|
// startup recovery — a cancelled question's re-emitted "line" needs a
|
|
@@ -1541,7 +1554,7 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1541
1554
|
return;
|
|
1542
1555
|
spentUsd = (spentUsd ?? 0) + usd;
|
|
1543
1556
|
};
|
|
1544
|
-
const
|
|
1557
|
+
const queueTurn = (line, via) => {
|
|
1545
1558
|
const slot = { line: via?.line ?? line, content: line, ...(via !== undefined ? { via } : {}), cancelled: false };
|
|
1546
1559
|
pendingTurns.push(slot);
|
|
1547
1560
|
queued += 1;
|
|
@@ -1588,10 +1601,78 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1588
1601
|
queued = Math.max(0, queued - 1);
|
|
1589
1602
|
return slot.line;
|
|
1590
1603
|
};
|
|
1604
|
+
// ADR-0057 (the owner's ruling, 2026-09-28): Enter while a run is live
|
|
1605
|
+
// is a STEER — there is no queue. `steering` mirrors what the run holds
|
|
1606
|
+
// and has not admitted; the run takes ALL of it at its next quiescent
|
|
1607
|
+
// boundary, and the landed user_input clears the rows. Piped and
|
|
1608
|
+
// task-file input keep one turn per line: a script has nobody steering.
|
|
1609
|
+
const steerable = process.stdin.isTTY === true && input.literal !== true;
|
|
1610
|
+
let steering = [];
|
|
1611
|
+
const steer = (line, via) => {
|
|
1612
|
+
if (!steerable || currentRun === null)
|
|
1613
|
+
return false;
|
|
1614
|
+
try {
|
|
1615
|
+
currentRun.steer(via !== undefined ? line : attachImages(line, input.attachments?.(), protectedFiles()));
|
|
1616
|
+
}
|
|
1617
|
+
catch (err) {
|
|
1618
|
+
if (err instanceof RunClosedError)
|
|
1619
|
+
return false; // the run is ending: this is the next turn
|
|
1620
|
+
throw err;
|
|
1621
|
+
}
|
|
1622
|
+
steering.push({ line: via?.line ?? line, content: line, ...(via !== undefined ? { via } : {}) });
|
|
1623
|
+
return true;
|
|
1624
|
+
};
|
|
1625
|
+
const submitTurn = (line, via) => {
|
|
1626
|
+
if (!steer(line, via))
|
|
1627
|
+
queueTurn(line, via);
|
|
1628
|
+
};
|
|
1629
|
+
/** The mirror of the last `n` steers the run handed back; clears it. */
|
|
1630
|
+
const handed = (n) => {
|
|
1631
|
+
const out = n > 0 ? steering.slice(-n) : [];
|
|
1632
|
+
steering = [];
|
|
1633
|
+
return out;
|
|
1634
|
+
};
|
|
1635
|
+
const landed = () => {
|
|
1636
|
+
steering = [];
|
|
1637
|
+
};
|
|
1638
|
+
/** A run sealed with steers still pending (max_turns, an END_TURN
|
|
1639
|
+
* result, an error): they are the person's next message, sent now. */
|
|
1640
|
+
const handBack = (run) => {
|
|
1641
|
+
const left = handed(run.unadmitted().length);
|
|
1642
|
+
if (left.length === 1)
|
|
1643
|
+
queueTurn(left[0].content, left[0].via);
|
|
1644
|
+
else if (left.length > 1)
|
|
1645
|
+
queueTurn(left.map((s) => s.content).join("\n\n"));
|
|
1646
|
+
};
|
|
1647
|
+
/** Esc / ctrl+c: a stop is not a send — steers that have not landed
|
|
1648
|
+
* go back to the editor. */
|
|
1649
|
+
const giveBack = () => {
|
|
1650
|
+
if (currentRun === null)
|
|
1651
|
+
return;
|
|
1652
|
+
const back = handed(currentRun.retract().length);
|
|
1653
|
+
if (back.length > 0)
|
|
1654
|
+
input.restore?.(back.map((s) => s.line).join("\n"));
|
|
1655
|
+
};
|
|
1656
|
+
/** ↑ takes back the LAST steer that has not landed (the others go back
|
|
1657
|
+
* in, in order); with none, the pipe-era queue pop. */
|
|
1658
|
+
const popPending = () => {
|
|
1659
|
+
if (currentRun !== null && steering.length > 0) {
|
|
1660
|
+
const back = currentRun.retract();
|
|
1661
|
+
const mine = handed(back.length);
|
|
1662
|
+
const last = mine.pop();
|
|
1663
|
+
for (const c of back.slice(0, -1))
|
|
1664
|
+
currentRun.steer(c);
|
|
1665
|
+
steering = mine;
|
|
1666
|
+
if (last !== undefined)
|
|
1667
|
+
return last.line;
|
|
1668
|
+
}
|
|
1669
|
+
return popQueue();
|
|
1670
|
+
};
|
|
1591
1671
|
// W22: the visibility invariant's binds — the dock renders the
|
|
1592
|
-
// pending chips
|
|
1593
|
-
|
|
1594
|
-
|
|
1672
|
+
// pending chips, the editor routes the pop keys.
|
|
1673
|
+
const pendingLines = () => [...steering.map((s) => s.line), ...pendingTurns.map((s) => s.line)];
|
|
1674
|
+
dock.bindQueue(pendingLines);
|
|
1675
|
+
input.bindQueue(pendingLines, popPending);
|
|
1595
1676
|
const dispatchCtx = {
|
|
1596
1677
|
session,
|
|
1597
1678
|
input,
|
|
@@ -1717,8 +1798,9 @@ export async function chat(session, faux, input, autoCompact, nav, seed) {
|
|
|
1717
1798
|
runStart = Date.now();
|
|
1718
1799
|
runUsage = { in: null, out: null, cache: null, known: false };
|
|
1719
1800
|
lastTokPerSec = null; // TPS-1: nothing has settled in THIS turn yet
|
|
1720
|
-
const last = await consumeRun(session, recoveryRun, input, turnNo, faux, statusCb, submitTurn);
|
|
1801
|
+
const last = await consumeRun(session, recoveryRun, input, turnNo, faux, statusCb, submitTurn, landed);
|
|
1721
1802
|
currentRun = null;
|
|
1803
|
+
handBack(recoveryRun);
|
|
1722
1804
|
failOnFauxExhaustion(last, faux, input);
|
|
1723
1805
|
// E group (the graceful-exit gate ③): the same deferred re-check
|
|
1724
1806
|
// as the turn path — the recovery run's end is also a safe point.
|
package/dist/index.js
CHANGED
|
@@ -319,6 +319,10 @@ function editorInput(editor) {
|
|
|
319
319
|
bindQueue(state, pop) {
|
|
320
320
|
editor.bindQueue(state, pop);
|
|
321
321
|
},
|
|
322
|
+
// ADR-0057: the steers a stop handed back return to the buffer.
|
|
323
|
+
restore(text) {
|
|
324
|
+
editor.restore(text);
|
|
325
|
+
},
|
|
322
326
|
// R3a: cross-session history — the CLI owns the file I/O.
|
|
323
327
|
bindHistory(seed, persist) {
|
|
324
328
|
editor.bindHistory(seed, persist);
|
package/dist/state.d.ts
CHANGED
|
@@ -179,6 +179,9 @@ export interface LineInput {
|
|
|
179
179
|
* live slots (each pop cancels the turn), esc ends the walk after
|
|
180
180
|
* one more pop. The chips are the compositor's own bindQueue. */
|
|
181
181
|
bindQueue(state: () => readonly string[], pop: () => string | null): void;
|
|
182
|
+
/** ADR-0057: put text back into the editor — the steers a stop handed
|
|
183
|
+
* back before they landed. The pipe path has no editor; optional. */
|
|
184
|
+
restore?(text: string): void;
|
|
182
185
|
/** R3a: cross-session history — seed the recall buffer, register the
|
|
183
186
|
* append sink. The pipe path has no recall keys; optional. */
|
|
184
187
|
bindHistory?(seed: readonly string[], persist: (line: string) => void): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.45.0",
|
|
4
4
|
"description": "kiso-code \u2014 the coding agent on kiso, the durable runtime for AI agents: kiso chat / kiso resume / kiso sessions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,19 +18,19 @@
|
|
|
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-tools-node": "0.
|
|
32
|
-
"@vincemakes/kiso-tui": "0.
|
|
33
|
-
"@vincemakes/kiso-tui-cells": "0.
|
|
21
|
+
"@vincemakes/kiso-ask-ext": "0.45.0",
|
|
22
|
+
"@vincemakes/kiso-core": "0.45.0",
|
|
23
|
+
"@vincemakes/kiso-evals": "0.45.0",
|
|
24
|
+
"@vincemakes/kiso-mcp-ext": "0.45.0",
|
|
25
|
+
"@vincemakes/kiso-provider-anthropic": "0.45.0",
|
|
26
|
+
"@vincemakes/kiso-provider-openai": "0.45.0",
|
|
27
|
+
"@vincemakes/kiso-provider-openai-responses": "0.45.0",
|
|
28
|
+
"@vincemakes/kiso-runtime": "0.45.0",
|
|
29
|
+
"@vincemakes/kiso-skills-ext": "0.45.0",
|
|
30
|
+
"@vincemakes/kiso-subagent-ext": "0.45.0",
|
|
31
|
+
"@vincemakes/kiso-tools-node": "0.45.0",
|
|
32
|
+
"@vincemakes/kiso-tui": "0.45.0",
|
|
33
|
+
"@vincemakes/kiso-tui-cells": "0.45.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^26.1.2",
|