@vincemakes/kiso-code 0.12.0 → 0.14.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 +48 -1
- package/dist/chat.js +207 -19
- package/dist/state.d.ts +5 -3
- package/dist/trust-ui.d.ts +2 -2
- package/package.json +14 -14
package/dist/chat.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* estimates. All bodies moved verbatim from index.ts.
|
|
6
6
|
*/
|
|
7
7
|
import { type RunUsage } from "@vincemakes/kiso-tui";
|
|
8
|
-
import { type SaferOption } from "@vincemakes/kiso-tui";
|
|
8
|
+
import { type SaferFailure, type SaferOption } from "@vincemakes/kiso-tui";
|
|
9
9
|
import type { AgentSession, Run } from "@vincemakes/kiso-runtime";
|
|
10
10
|
import { type LineInput } from "./state.js";
|
|
11
11
|
/**
|
|
@@ -82,6 +82,45 @@ export declare function usageFromEvent(route: string | undefined, ev: import("@v
|
|
|
82
82
|
* first event. */
|
|
83
83
|
export declare function startStatusSpinner(onTick: (glyph: string) => void): () => void;
|
|
84
84
|
export declare function startShellTail(sessionId: string, callId: string, command: string, startedAt: number): () => void;
|
|
85
|
+
/**
|
|
86
|
+
* R3v2-F1: the format contract, stated FIRMLY. The first cut asked for
|
|
87
|
+
* "JSON ONLY" and left it there, which a verbose model reads as a
|
|
88
|
+
* preference — it wrote three sentences of preamble, opened a fence, and
|
|
89
|
+
* the cap ended the reply mid-string. Forbidding prose, naming the exact
|
|
90
|
+
* schema, and giving the nothing-is-safer case its own literal answer
|
|
91
|
+
* are all the same instruction: there is one thing to emit and no room
|
|
92
|
+
* to be helpful in the margins.
|
|
93
|
+
*
|
|
94
|
+
* The schema is an ENVELOPE rather than a bare array because a single
|
|
95
|
+
* top-level object leaves the model nowhere to put a preamble.
|
|
96
|
+
*/
|
|
97
|
+
export declare const SAFER_SYSTEM_PROMPT: string;
|
|
98
|
+
/**
|
|
99
|
+
* R3v2-F1: the side query's output ceiling — raised from 500, which was
|
|
100
|
+
* the cap the live failures hit EXACTLY.
|
|
101
|
+
*
|
|
102
|
+
* The JSON-only reply the prompt now asks for is about 200 tokens for
|
|
103
|
+
* three alternatives, so this ceiling is a runaway guard and not a
|
|
104
|
+
* budget the answer is expected to approach: it exists so a model that
|
|
105
|
+
* ignores the contract and writes an essay still stops, not so the
|
|
106
|
+
* answer has room. Output is billed only when generated, and the query
|
|
107
|
+
* fires only on a press, so the raise costs nothing on the path that
|
|
108
|
+
* works and removes the one that could not.
|
|
109
|
+
*/
|
|
110
|
+
export declare const SAFER_MAX_TOKENS = 1500;
|
|
111
|
+
/**
|
|
112
|
+
* R3v2-F1: WHY the ask failed, when the reply's own text can prove it.
|
|
113
|
+
*
|
|
114
|
+
* This side reports the cause and never the copy — the sentences live in
|
|
115
|
+
* the panel package, next to each other, so there is one place where the
|
|
116
|
+
* words are chosen and one place they can drift from.
|
|
117
|
+
*
|
|
118
|
+
* "Cut short" is a DIAGNOSIS, so it is only claimed when the text shows
|
|
119
|
+
* it: a reply that closed its JSON and then failed our SHAPE returns
|
|
120
|
+
* null and gets the unqualified line, because telling that human their
|
|
121
|
+
* reply was truncated would be a confident wrong answer.
|
|
122
|
+
*/
|
|
123
|
+
export declare function saferFailure(text: string): SaferFailure | null;
|
|
85
124
|
/**
|
|
86
125
|
* Parse the model's answer DEFENSIVELY — anything unexpected is a
|
|
87
126
|
* failure, and a failure degrades honestly.
|
|
@@ -95,6 +134,14 @@ export declare function startShellTail(sessionId: string, callId: string, comman
|
|
|
95
134
|
*
|
|
96
135
|
* A fenced code block is the one accommodation, because models emit it
|
|
97
136
|
* constantly and it changes no content.
|
|
137
|
+
*
|
|
138
|
+
* R3v2-F1 widens that accommodation and NOTHING else. Unwrapping the
|
|
139
|
+
* named `alternatives` envelope, and reading `reason` as the spelling of
|
|
140
|
+
* `why` the prompt now asks for, are transport details: the entries that
|
|
141
|
+
* come out are verbatim the entries the model put in. That is the line
|
|
142
|
+
* between an accommodation and the salvage this parser refuses — a
|
|
143
|
+
* salvage changes WHICH alternatives are shown, and every rule that does
|
|
144
|
+
* that is still here. One bad entry still poisons the batch.
|
|
98
145
|
*/
|
|
99
146
|
export declare function parseSaferOptions(text: string): SaferOption[] | null;
|
|
100
147
|
/**
|
package/dist/chat.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* estimates. All bodies moved verbatim from index.ts.
|
|
6
6
|
*/
|
|
7
7
|
import { readFileSync, statSync } from "node:fs";
|
|
8
|
-
import { escapeTerminal, cacheHitPct, idleStatus, palette, renderEvent, renderRecap, runningStatus, toolTarget, STATUS_GLYPHS, } from "@vincemakes/kiso-tui";
|
|
8
|
+
import { escapeTerminal, cacheHitPct, idleStatus, palette, renderEvent, renderRecap, runningStatus, toolTarget, verifyOfferView, STATUS_GLYPHS, } from "@vincemakes/kiso-tui";
|
|
9
9
|
import { deletionRiskHint, editFileDiff, writeFileDiff } from "@vincemakes/kiso-tui";
|
|
10
10
|
import { canonicalTargetPath, shellProgressPath } from "@vincemakes/kiso-tools-node";
|
|
11
11
|
import { canonicalizeUsage } from "@vincemakes/kiso-runtime";
|
|
@@ -191,12 +191,106 @@ function approvalDiff(name, input) {
|
|
|
191
191
|
* refusal — the "(amended)" marker's source. Per process, cleared as
|
|
192
192
|
* soon as it is shown: the marker describes ONE call, not a mode. */
|
|
193
193
|
const amendedCalls = new Set();
|
|
194
|
-
|
|
194
|
+
/**
|
|
195
|
+
* R3v2-F1: the format contract, stated FIRMLY. The first cut asked for
|
|
196
|
+
* "JSON ONLY" and left it there, which a verbose model reads as a
|
|
197
|
+
* preference — it wrote three sentences of preamble, opened a fence, and
|
|
198
|
+
* the cap ended the reply mid-string. Forbidding prose, naming the exact
|
|
199
|
+
* schema, and giving the nothing-is-safer case its own literal answer
|
|
200
|
+
* are all the same instruction: there is one thing to emit and no room
|
|
201
|
+
* to be helpful in the margins.
|
|
202
|
+
*
|
|
203
|
+
* The schema is an ENVELOPE rather than a bare array because a single
|
|
204
|
+
* top-level object leaves the model nowhere to put a preamble.
|
|
205
|
+
*/
|
|
206
|
+
export const SAFER_SYSTEM_PROMPT = [
|
|
195
207
|
"You propose safer alternatives to a single shell/tool call a human is being asked to approve.",
|
|
196
|
-
"
|
|
197
|
-
'
|
|
198
|
-
"
|
|
208
|
+
"Reply with JSON ONLY — no prose, no preamble, no code fence, nothing before or after the JSON.",
|
|
209
|
+
'The exact schema is {"alternatives":[{"command":"...","reason":"..."}]}, with 2-3 entries.',
|
|
210
|
+
'"command" is the full replacement call. "reason" is ONE line of plain language saying what it does differently.',
|
|
211
|
+
'Prefer alternatives that avoid irreversible deletion. If you cannot improve on it, reply {"alternatives":[]}.',
|
|
199
212
|
].join(" ");
|
|
213
|
+
/**
|
|
214
|
+
* R3v2-F1: the side query's output ceiling — raised from 500, which was
|
|
215
|
+
* the cap the live failures hit EXACTLY.
|
|
216
|
+
*
|
|
217
|
+
* The JSON-only reply the prompt now asks for is about 200 tokens for
|
|
218
|
+
* three alternatives, so this ceiling is a runaway guard and not a
|
|
219
|
+
* budget the answer is expected to approach: it exists so a model that
|
|
220
|
+
* ignores the contract and writes an essay still stops, not so the
|
|
221
|
+
* answer has room. Output is billed only when generated, and the query
|
|
222
|
+
* fires only on a press, so the raise costs nothing on the path that
|
|
223
|
+
* works and removes the one that could not.
|
|
224
|
+
*/
|
|
225
|
+
export const SAFER_MAX_TOKENS = 1500;
|
|
226
|
+
/**
|
|
227
|
+
* R3v2-F1: WHY the ask failed, when the reply's own text can prove it.
|
|
228
|
+
*
|
|
229
|
+
* This side reports the cause and never the copy — the sentences live in
|
|
230
|
+
* the panel package, next to each other, so there is one place where the
|
|
231
|
+
* words are chosen and one place they can drift from.
|
|
232
|
+
*
|
|
233
|
+
* "Cut short" is a DIAGNOSIS, so it is only claimed when the text shows
|
|
234
|
+
* it: a reply that closed its JSON and then failed our SHAPE returns
|
|
235
|
+
* null and gets the unqualified line, because telling that human their
|
|
236
|
+
* reply was truncated would be a confident wrong answer.
|
|
237
|
+
*/
|
|
238
|
+
export function saferFailure(text) {
|
|
239
|
+
return jsonBody(text) === "truncated" ? { reason: "truncated" } : null;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* R3v2-F1: find the reply's JSON body by BALANCING brackets rather than
|
|
243
|
+
* by first-and-last.
|
|
244
|
+
*
|
|
245
|
+
* `indexOf("[")` / `lastIndexOf("]")` had two failure modes a verbose
|
|
246
|
+
* model hits constantly: a bracket in the trailing prose moved the end
|
|
247
|
+
* past the array, and a reply the cap cut in half had no end at all.
|
|
248
|
+
* Both returned null, and null could not say which — which is why the
|
|
249
|
+
* degradation line could not either.
|
|
250
|
+
*
|
|
251
|
+
* Returns the balanced slice, `"truncated"` when a value opens and the
|
|
252
|
+
* text ends before it closes, or null when there is no JSON value at
|
|
253
|
+
* all.
|
|
254
|
+
*/
|
|
255
|
+
function jsonBody(text) {
|
|
256
|
+
// a CLOSED fence is content-preserving to strip. An OPEN one means
|
|
257
|
+
// the reply ended inside the block — drop the opener and let the scan
|
|
258
|
+
// below reach the same verdict from the content.
|
|
259
|
+
const closed = text.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
260
|
+
const body = closed?.[1] ?? text.replace(/^[\s\S]*?```(?:json)?[ \t]*\r?\n/, "");
|
|
261
|
+
const start = body.search(/[[{]/);
|
|
262
|
+
if (start < 0)
|
|
263
|
+
return null;
|
|
264
|
+
let depth = 0;
|
|
265
|
+
let inString = false;
|
|
266
|
+
let escaped = false;
|
|
267
|
+
for (let i = start; i < body.length; i += 1) {
|
|
268
|
+
const c = body[i];
|
|
269
|
+
if (escaped) {
|
|
270
|
+
escaped = false;
|
|
271
|
+
}
|
|
272
|
+
else if (inString) {
|
|
273
|
+
if (c === "\\")
|
|
274
|
+
escaped = true;
|
|
275
|
+
else if (c === '"')
|
|
276
|
+
inString = false;
|
|
277
|
+
}
|
|
278
|
+
else if (c === '"') {
|
|
279
|
+
inString = true;
|
|
280
|
+
}
|
|
281
|
+
else if (c === "[" || c === "{") {
|
|
282
|
+
depth += 1;
|
|
283
|
+
}
|
|
284
|
+
else if (c === "]" || c === "}") {
|
|
285
|
+
depth -= 1;
|
|
286
|
+
if (depth === 0)
|
|
287
|
+
return body.slice(start, i + 1);
|
|
288
|
+
if (depth < 0)
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return "truncated";
|
|
293
|
+
}
|
|
200
294
|
/**
|
|
201
295
|
* Parse the model's answer DEFENSIVELY — anything unexpected is a
|
|
202
296
|
* failure, and a failure degrades honestly.
|
|
@@ -210,34 +304,59 @@ const SAFER_SYSTEM_PROMPT = [
|
|
|
210
304
|
*
|
|
211
305
|
* A fenced code block is the one accommodation, because models emit it
|
|
212
306
|
* constantly and it changes no content.
|
|
307
|
+
*
|
|
308
|
+
* R3v2-F1 widens that accommodation and NOTHING else. Unwrapping the
|
|
309
|
+
* named `alternatives` envelope, and reading `reason` as the spelling of
|
|
310
|
+
* `why` the prompt now asks for, are transport details: the entries that
|
|
311
|
+
* come out are verbatim the entries the model put in. That is the line
|
|
312
|
+
* between an accommodation and the salvage this parser refuses — a
|
|
313
|
+
* salvage changes WHICH alternatives are shown, and every rule that does
|
|
314
|
+
* that is still here. One bad entry still poisons the batch.
|
|
213
315
|
*/
|
|
214
316
|
export function parseSaferOptions(text) {
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (start < 0 || end <= start)
|
|
317
|
+
const body = jsonBody(text);
|
|
318
|
+
// truncation and absence part ways in saferFailureNote(), which reads
|
|
319
|
+
// the same scan; for the list itself both are the same nothing.
|
|
320
|
+
if (body === null || body === "truncated")
|
|
220
321
|
return null;
|
|
221
322
|
let parsed;
|
|
222
323
|
try {
|
|
223
|
-
parsed = JSON.parse(body
|
|
324
|
+
parsed = JSON.parse(body);
|
|
224
325
|
}
|
|
225
326
|
catch {
|
|
226
327
|
return null;
|
|
227
328
|
}
|
|
228
|
-
|
|
329
|
+
const envelope = typeof parsed === "object" && parsed !== null ? parsed.alternatives : undefined;
|
|
330
|
+
const list = Array.isArray(parsed) ? parsed : Array.isArray(envelope) ? envelope : null;
|
|
331
|
+
if (list === null || list.length === 0)
|
|
229
332
|
return null;
|
|
230
333
|
const out = [];
|
|
231
|
-
for (const item of
|
|
334
|
+
for (const item of list.slice(0, 3)) {
|
|
232
335
|
if (typeof item !== "object" || item === null)
|
|
233
336
|
return null;
|
|
234
|
-
const { command, why } = item;
|
|
337
|
+
const { command, reason, why } = item;
|
|
235
338
|
if (typeof command !== "string" || command.trim() === "")
|
|
236
339
|
return null;
|
|
237
|
-
|
|
340
|
+
const line = typeof reason === "string" ? reason : typeof why === "string" ? why : "";
|
|
341
|
+
out.push({ command: command.trim(), why: line.trim() });
|
|
238
342
|
}
|
|
239
343
|
return out.length === 0 ? null : out;
|
|
240
344
|
}
|
|
345
|
+
/** TV-1B — the plain-word verdict tail for the settled checklist.
|
|
346
|
+
* "no passing check yet" covers both never-ran and ran-and-failed
|
|
347
|
+
* without lying; "outdated" claims only what the trajectory proves. */
|
|
348
|
+
function taskVerdictWords(kind) {
|
|
349
|
+
switch (kind) {
|
|
350
|
+
case "verified":
|
|
351
|
+
return "checked \u2713";
|
|
352
|
+
case "stale":
|
|
353
|
+
return "check outdated \u2014 work may have changed after it";
|
|
354
|
+
case "none":
|
|
355
|
+
return "no passing check yet";
|
|
356
|
+
case "unreadable":
|
|
357
|
+
return "task list unreadable";
|
|
358
|
+
}
|
|
359
|
+
}
|
|
241
360
|
/** W21 — the panel view for a permission_requested: the rule line (the
|
|
242
361
|
* why-asked speaker + the §3.5 fix hint), the toolTarget title, the
|
|
243
362
|
* "▸ run paused" status, and the ALWAYS-verbose args. */
|
|
@@ -406,6 +525,15 @@ submitTurn) {
|
|
|
406
525
|
// construction (ADR-0040).
|
|
407
526
|
switch (ev.type) {
|
|
408
527
|
case "user_input":
|
|
528
|
+
// TV-1B: a system-sourced input is PRODUCT MACHINERY — visible
|
|
529
|
+
// (every durable input renders) but never painted as the
|
|
530
|
+
// user's words. Provenance is honest on screen, not only in
|
|
531
|
+
// the log.
|
|
532
|
+
if (ev.source === "system") {
|
|
533
|
+
body.notice("\u25c6 verification pass");
|
|
534
|
+
body.notice(` ${typeof ev.content === "string" ? ev.content : ""}`);
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
409
537
|
body.userLine(typeof ev.content === "string" ? ev.content : "");
|
|
410
538
|
break;
|
|
411
539
|
case "thinking":
|
|
@@ -512,9 +640,13 @@ submitTurn) {
|
|
|
512
640
|
purpose: "safer-options",
|
|
513
641
|
systemPrompt: SAFER_SYSTEM_PROMPT,
|
|
514
642
|
prompt: `the pending call is: ${name} ${JSON.stringify(ev.input ?? {})}`,
|
|
515
|
-
maxTokens:
|
|
643
|
+
maxTokens: SAFER_MAX_TOKENS,
|
|
516
644
|
});
|
|
517
|
-
|
|
645
|
+
// R3v2-F1: a failure reports its CAUSE when the reply can
|
|
646
|
+
// prove one, so the panel can say which failure this was.
|
|
647
|
+
// saferFailure() returns null for every cause we cannot
|
|
648
|
+
// demonstrate, which is the unqualified line — unchanged.
|
|
649
|
+
return parseSaferOptions(answer) ?? saferFailure(answer);
|
|
518
650
|
};
|
|
519
651
|
const verdict = await askPanel(input, approvalView(name, ev, amendedCalls.has(name)), { safer });
|
|
520
652
|
amendedCalls.delete(name);
|
|
@@ -579,6 +711,19 @@ submitTurn) {
|
|
|
579
711
|
// events (zero tokens). The dock's status bar still paints.
|
|
580
712
|
statusCb?.(usage, estimateCtxRatio(session));
|
|
581
713
|
const ratio = estimateCtxRatio(session);
|
|
714
|
+
// TV-1B: the settle verdict — the checklist stops lying. When
|
|
715
|
+
// every item is CLAIMED done, the settled block's tail says
|
|
716
|
+
// what the projection actually proves ("no passing check yet"
|
|
717
|
+
// covers never-ran AND ran-and-failed; "may have changed"
|
|
718
|
+
// claims trajectory knowledge, never filesystem knowledge).
|
|
719
|
+
// A run that emitted no task_set still gets the block: the
|
|
720
|
+
// claims live in the durable log, and the settle SYNTHESIZES
|
|
721
|
+
// the display from session.assessTasks() — a UI projection,
|
|
722
|
+
// never a new durable fact.
|
|
723
|
+
const tv = session.assessTasks();
|
|
724
|
+
if (tv.claims.length > 0 && tv.allClaimedDone) {
|
|
725
|
+
body.checklist(taskVerdictWords(tv.evidence.kind), tv.claims.map((c) => ({ text: c.text, status: c.status })));
|
|
726
|
+
}
|
|
582
727
|
// W14: the turn record closes HERE — before the recap logs, so
|
|
583
728
|
// the commit loop folds the quiet turn's held cells first (the
|
|
584
729
|
// fold line lands above the recap, natural cell order).
|
|
@@ -651,9 +796,9 @@ export async function chat(session, faux, input, autoCompact) {
|
|
|
651
796
|
console.log("\n[exit requested]");
|
|
652
797
|
input.close();
|
|
653
798
|
};
|
|
654
|
-
const turn = (text) => new Promise((resolve, reject) => {
|
|
799
|
+
const turn = (text, seedSource) => new Promise((resolve, reject) => {
|
|
655
800
|
queued = Math.max(0, queued - 1); // a queued turn starts
|
|
656
|
-
const run = session.run(text);
|
|
801
|
+
const run = seedSource !== undefined ? session.run(text, { source: seedSource }) : session.run(text);
|
|
657
802
|
currentRun = run;
|
|
658
803
|
turnNo += 1;
|
|
659
804
|
const myTurn = turnNo;
|
|
@@ -684,6 +829,41 @@ export async function chat(session, faux, input, autoCompact) {
|
|
|
684
829
|
// exit, so the release always runs.
|
|
685
830
|
if (eotSeen)
|
|
686
831
|
exitAtEmptyPrompt();
|
|
832
|
+
// TV-1B — the thin task driver. A VERIFICATION turn settling
|
|
833
|
+
// consumes the task-set identity it produced (a verifier's
|
|
834
|
+
// own task_set belongs to the SAME accepted offer) and never
|
|
835
|
+
// opens another offer. A normal COMPLETED settle may offer —
|
|
836
|
+
// gated so the suggestion always yields to human intent.
|
|
837
|
+
if (seedSource === "system") {
|
|
838
|
+
const after = session.assessTasks();
|
|
839
|
+
if (after.lastTaskSetSeq !== null)
|
|
840
|
+
offeredTaskSeqs.add(after.lastTaskSetSeq);
|
|
841
|
+
}
|
|
842
|
+
else if (last?.type === "terminal" &&
|
|
843
|
+
last.outcome.kind === "completed" &&
|
|
844
|
+
process.stdin.isTTY &&
|
|
845
|
+
!cancelled &&
|
|
846
|
+
!eotSeen &&
|
|
847
|
+
pendingAsk === null &&
|
|
848
|
+
pendingTurns.length === 0 &&
|
|
849
|
+
input.line() === "") {
|
|
850
|
+
const tv = session.assessTasks();
|
|
851
|
+
if (tv.claims.length > 0 &&
|
|
852
|
+
tv.allClaimedDone &&
|
|
853
|
+
(tv.evidence.kind === "none" || tv.evidence.kind === "stale") &&
|
|
854
|
+
tv.lastTaskSetSeq !== null &&
|
|
855
|
+
!offeredTaskSeqs.has(tv.lastTaskSetSeq)) {
|
|
856
|
+
const verdict = await askPanel(input, verifyOfferView());
|
|
857
|
+
// an explicit answer — Yes, Not now, OR Esc — consumes
|
|
858
|
+
// the offer for THIS claims-set; only gate-suppression
|
|
859
|
+
// (above) leaves it live for a later settle.
|
|
860
|
+
offeredTaskSeqs.add(tv.lastTaskSetSeq);
|
|
861
|
+
if (verdict.action === "allow") {
|
|
862
|
+
queued += 1; // turn() decrements — keep the ledger honest
|
|
863
|
+
chainRef.current = chainRef.current.then(() => turn(VERIFY_SEED, "system"));
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
}
|
|
687
867
|
// round 8: after EVERY turn the prompt is re-armed — the human
|
|
688
868
|
// never types blind after the first turn.
|
|
689
869
|
input.prompt();
|
|
@@ -788,6 +968,14 @@ export async function chat(session, faux, input, autoCompact) {
|
|
|
788
968
|
// A slot leaves the queue when its turn STARTS or when the user
|
|
789
969
|
// pops it (cancelled — the chain segment skips it).
|
|
790
970
|
const pendingTurns = [];
|
|
971
|
+
// TV-1B — the offer memory: session-local BY DESIGN (a dead process's
|
|
972
|
+
// "not now" should not silence a live one; resume re-offers once,
|
|
973
|
+
// honestly), keyed by the assessed claims' identity.
|
|
974
|
+
const offeredTaskSeqs = new Set();
|
|
975
|
+
// The fixed verification seed — durable with source:"system": WHO asked
|
|
976
|
+
// is provenance in the log; on the provider wire it stays an ordinary
|
|
977
|
+
// user-role message (never a system-prompt escalation).
|
|
978
|
+
const VERIFY_SEED = "Verify the completed work: run the project's checks and report what passes and what fails.";
|
|
791
979
|
// v2b: the live status bar (docked only). Modes: /mode switches repaint
|
|
792
980
|
// it immediately through paintStatus (the last turn stats are kept).
|
|
793
981
|
// v3 §03: the status bar has TWO states. Idle: the mode is ALWAYS
|
package/dist/state.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* creates the mutable ones (setBody / setAgentModel / setExtensionLists);
|
|
6
6
|
* the moved modules read and mutate at call time.
|
|
7
7
|
*/
|
|
8
|
-
import { Dock, type AtItem, type Body, type PanelVerdict, type PanelView, type
|
|
8
|
+
import { Dock, type AtItem, type Body, type PanelVerdict, type PanelView, type SaferAnswer, type SessionCardView } from "@vincemakes/kiso-tui";
|
|
9
9
|
import type { KisoExtension, StoreRecord } from "@vincemakes/kiso-runtime";
|
|
10
10
|
/** finding #11: KISO_HOME is the ONE root — every default path derives from
|
|
11
11
|
* it (sessions, trust, extensions, mcp config, skills). The dedicated
|
|
@@ -82,9 +82,11 @@ export interface LineInput {
|
|
|
82
82
|
* the tab-amend), the compositor renders the block + the leads. */
|
|
83
83
|
/** TUI2-R3v2 ③: `opts.safer` is the on-demand alternatives provider —
|
|
84
84
|
* absent for every panel that has no such option (the ask, the pick,
|
|
85
|
-
* the trust gate), so those buttons cannot exist to be pressed.
|
|
85
|
+
* the trust gate), so those buttons cannot exist to be pressed.
|
|
86
|
+
* R3v2-F1: it resolves a SaferAnswer, so a failure that can name its
|
|
87
|
+
* cause does — `null` still means a failure with nothing to add. */
|
|
86
88
|
panelAsk(view: PanelView, onCommit: (v: PanelVerdict) => void, opts?: {
|
|
87
|
-
safer?: () => Promise<
|
|
89
|
+
safer?: () => Promise<SaferAnswer>;
|
|
88
90
|
}): void;
|
|
89
91
|
/** W21: cancel the panel — the SIGINT pair to panelAsk. */
|
|
90
92
|
panelCancel(): void;
|
package/dist/trust-ui.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* chat.ts), the don't-ask-again rule writer, and the uncertain-execution
|
|
6
6
|
* decisions. All bodies moved verbatim from index.ts.
|
|
7
7
|
*/
|
|
8
|
-
import { type PanelVerdict, type PanelView, type
|
|
8
|
+
import { type PanelVerdict, type PanelView, type SaferAnswer } from "@vincemakes/kiso-tui";
|
|
9
9
|
import type { AskUI } from "@vincemakes/kiso-ask-ext";
|
|
10
10
|
import { type ProjectArtifacts } from "@vincemakes/kiso-runtime";
|
|
11
11
|
import type { AgentSession } from "@vincemakes/kiso-runtime";
|
|
@@ -35,7 +35,7 @@ import { type LineInput } from "./state.js";
|
|
|
35
35
|
*/
|
|
36
36
|
export declare let pendingAsk: (() => void) | null;
|
|
37
37
|
export declare function askPanel(input: LineInput, view: PanelView, opts?: {
|
|
38
|
-
safer?: () => Promise<
|
|
38
|
+
safer?: () => Promise<SaferAnswer>;
|
|
39
39
|
}): Promise<PanelVerdict>;
|
|
40
40
|
/**
|
|
41
41
|
* KC3.5 — the AskUI bridge: the panel the ask extension asks through.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "kiso CLI — the durable coding agent that survives kill -9: 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-runtime": "0.
|
|
28
|
-
"@vincemakes/kiso-skills-ext": "0.
|
|
29
|
-
"@vincemakes/kiso-subagent-ext": "0.
|
|
30
|
-
"@vincemakes/kiso-task-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.14.0",
|
|
22
|
+
"@vincemakes/kiso-core": "0.14.0",
|
|
23
|
+
"@vincemakes/kiso-evals": "0.14.0",
|
|
24
|
+
"@vincemakes/kiso-mcp-ext": "0.14.0",
|
|
25
|
+
"@vincemakes/kiso-provider-anthropic": "0.14.0",
|
|
26
|
+
"@vincemakes/kiso-provider-openai": "0.14.0",
|
|
27
|
+
"@vincemakes/kiso-runtime": "0.14.0",
|
|
28
|
+
"@vincemakes/kiso-skills-ext": "0.14.0",
|
|
29
|
+
"@vincemakes/kiso-subagent-ext": "0.14.0",
|
|
30
|
+
"@vincemakes/kiso-task-ext": "0.14.0",
|
|
31
|
+
"@vincemakes/kiso-tools-node": "0.14.0",
|
|
32
|
+
"@vincemakes/kiso-tui": "0.14.0",
|
|
33
|
+
"@vincemakes/kiso-tui-cells": "0.14.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "^26.1.2",
|