@vincemakes/kiso-code 0.6.0 → 0.7.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/dispatch.js +3 -1
- package/dist/index.js +5 -3
- package/dist/state.d.ts +25 -1
- package/dist/state.js +59 -2
- package/dist/trust-ui.d.ts +0 -5
- package/dist/trust-ui.js +6 -33
- package/package.json +13 -13
package/dist/dispatch.js
CHANGED
|
@@ -30,7 +30,9 @@ export function dispatch(line, ctx) {
|
|
|
30
30
|
// KC1: the composer's keys ride the SAME bodyLog call (it splits
|
|
31
31
|
// on \n) — the help gains a row, the cli source does not.
|
|
32
32
|
// KC2: the redirect joins the same row for the same reason.
|
|
33
|
-
|
|
33
|
+
// KC3: and so does the @ picker — the row is where a gesture is
|
|
34
|
+
// taught, and the row costs nothing.
|
|
35
|
+
bodyLog(`${cmd("exit", "leave the session")}\n${cmd("keys", "enter sends · ctrl+J newline (shift+enter where encoded) · esc stops the run · alt+⏎ stops it and sends this instead · @ files")}`);
|
|
34
36
|
ctx.input.prompt();
|
|
35
37
|
});
|
|
36
38
|
return;
|
package/dist/index.js
CHANGED
|
@@ -26,14 +26,14 @@ import { readFileSync, realpathSync, rmSync } from "node:fs";
|
|
|
26
26
|
import { createInterface } from "node:readline";
|
|
27
27
|
import { fileURLToPath } from "node:url";
|
|
28
28
|
import { join } from "node:path";
|
|
29
|
-
import { Body, Editor, bannerLines, escapeTerminal, palette, renderSessionLine } from "@vincemakes/kiso-tui";
|
|
29
|
+
import { Body, Editor, bannerLines, escapeTerminal, interactivePrompt, palette, renderSessionLine } from "@vincemakes/kiso-tui";
|
|
30
30
|
import { createAgent, disposeExtensions, loadExtensions, loadProjectExtensions, SessionStore, } from "@vincemakes/kiso-runtime";
|
|
31
31
|
import { createFauxProvider } from "@vincemakes/kiso-evals";
|
|
32
32
|
import { createCodingTools } from "@vincemakes/kiso-tools-node";
|
|
33
33
|
import { MODES, modeExtensions, modeFromEnv, modeSystemPrompt, setMode } from "./mode.js";
|
|
34
34
|
import { builtInLayer } from "./builtin.js";
|
|
35
|
-
import { body, bodyLog, builtInExtensions, currentFaux, dock, extensionsDir, loadedExtensions, mergedConfig, mergedTempPaths, projectExtensions, sessionsDir, setAgentModel, setBody, setConfigModels, setConfiguredWindow, setCurrentAgentExtensions, setCurrentFaux, setCurrentModelName, setExtensionLists, setMergedConfig, userExtensions, VERSION } from "./state.js";
|
|
36
|
-
import {
|
|
35
|
+
import { atFiles, body, bodyLog, builtInExtensions, currentFaux, dock, extensionsDir, loadedExtensions, mergedConfig, mergedTempPaths, projectExtensions, sessionsDir, setAgentModel, setBody, setConfigModels, setConfiguredWindow, setCurrentAgentExtensions, setCurrentFaux, setCurrentModelName, setExtensionLists, setMergedConfig, userExtensions, VERSION } from "./state.js";
|
|
36
|
+
import { resolveProjectTrust } from "./trust-ui.js";
|
|
37
37
|
import { isFirstRun, scaffoldFirstRun } from "./first-run.js";
|
|
38
38
|
import { fauxSkip, readFauxScript } from "./faux-glue.js";
|
|
39
39
|
import { autoCompactFromEnv, chat, contextWindowTokens } from "./chat.js";
|
|
@@ -196,6 +196,8 @@ function makeLineInput() {
|
|
|
196
196
|
// pipe bytes do not change)
|
|
197
197
|
dock.bindInput(() => editor.dockState(), "› ");
|
|
198
198
|
dock.bindMenu(() => editor.menuState()); // v3 §04: the slash-command menu
|
|
199
|
+
editor.bindAtItems(atFiles); // KC3 §5: the file source — listed per OPEN
|
|
200
|
+
dock.bindAt(() => editor.atState()); // KC3 §4: the picker's band
|
|
199
201
|
dock.bindApproval(() => editor.panelState()); // W21: the panel's bound state
|
|
200
202
|
return editorInput(editor);
|
|
201
203
|
}
|
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 Body, type PanelVerdict, type PanelView } from "@vincemakes/kiso-tui";
|
|
8
|
+
import { Dock, type AtItem, type Body, type PanelVerdict, type PanelView } from "@vincemakes/kiso-tui";
|
|
9
9
|
import type { KisoExtension } 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
|
|
@@ -15,6 +15,30 @@ export declare function kisoHome(): string;
|
|
|
15
15
|
export declare function sessionsDir(): string;
|
|
16
16
|
/** E1: the extension scan directory — KISO_EXTENSIONS_DIR overrides. */
|
|
17
17
|
export declare function extensionsDir(): string;
|
|
18
|
+
/**
|
|
19
|
+
* KC3 §5 — the @ picker's file source. Computed PER OPEN: no index, no
|
|
20
|
+
* daemon, no watcher, nothing to invalidate and nothing to go stale.
|
|
21
|
+
* (The editor snapshots the result for the life of one open, so this
|
|
22
|
+
* runs once per `@`, not once per keystroke.)
|
|
23
|
+
*
|
|
24
|
+
* In a git repo, git IS the answer. `ls-files -c -o --exclude-standard`
|
|
25
|
+
* is the tracked files AND the untracked ones that are not ignored, in
|
|
26
|
+
* ONE process: the same set the user's own tooling calls "the project",
|
|
27
|
+
* with every .gitignore in the tree already honoured — and honoured by
|
|
28
|
+
* git rather than by a reimplementation of git's rules. stderr is
|
|
29
|
+
* discarded because "not a git repository" must never land in a live
|
|
30
|
+
* TUI frame.
|
|
31
|
+
*
|
|
32
|
+
* Outside a repo — or with no git on PATH — the bounded walk stands
|
|
33
|
+
* in: it prunes AT_SKIP before descending and stops at AT_CAP + 1
|
|
34
|
+
* entries, the extra entry being what lets the panel's counter SAY it
|
|
35
|
+
* truncated instead of showing the first two thousand files as though
|
|
36
|
+
* they were all of them.
|
|
37
|
+
*
|
|
38
|
+
* Paths are forward-slashed on both branches (git's own format), so
|
|
39
|
+
* the fuzzy filter sees one alphabet whichever branch ran.
|
|
40
|
+
*/
|
|
41
|
+
export declare function atFiles(): readonly AtItem[];
|
|
18
42
|
/**
|
|
19
43
|
* v2c — the interactive input source. TTYs use the raw-mode Editor (the
|
|
20
44
|
* self-drawn input row — width-aware, the CJK-drift root cause retired,
|
package/dist/state.js
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
* creates the mutable ones (setBody / setAgentModel / setExtensionLists);
|
|
6
6
|
* the moved modules read and mutate at call time.
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { execFileSync } from "node:child_process";
|
|
9
|
+
import { readdirSync, readFileSync } from "node:fs";
|
|
9
10
|
import { homedir } from "node:os";
|
|
10
11
|
import { dirname, join } from "node:path";
|
|
11
12
|
import { fileURLToPath } from "node:url";
|
|
12
|
-
import { Dock } from "@vincemakes/kiso-tui";
|
|
13
|
+
import { AT_CAP, AT_SKIP, Dock } from "@vincemakes/kiso-tui";
|
|
13
14
|
/** finding #11: KISO_HOME is the ONE root — every default path derives from
|
|
14
15
|
* it (sessions, trust, extensions, mcp config, skills). The dedicated
|
|
15
16
|
* env vars (KISO_EXTENSIONS_DIR / KISO_MCP_CONFIG / KISO_SKILLS_DIR)
|
|
@@ -24,6 +25,62 @@ export function sessionsDir() {
|
|
|
24
25
|
export function extensionsDir() {
|
|
25
26
|
return process.env.KISO_EXTENSIONS_DIR ?? join(kisoHome(), "extensions");
|
|
26
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* KC3 §5 — the @ picker's file source. Computed PER OPEN: no index, no
|
|
30
|
+
* daemon, no watcher, nothing to invalidate and nothing to go stale.
|
|
31
|
+
* (The editor snapshots the result for the life of one open, so this
|
|
32
|
+
* runs once per `@`, not once per keystroke.)
|
|
33
|
+
*
|
|
34
|
+
* In a git repo, git IS the answer. `ls-files -c -o --exclude-standard`
|
|
35
|
+
* is the tracked files AND the untracked ones that are not ignored, in
|
|
36
|
+
* ONE process: the same set the user's own tooling calls "the project",
|
|
37
|
+
* with every .gitignore in the tree already honoured — and honoured by
|
|
38
|
+
* git rather than by a reimplementation of git's rules. stderr is
|
|
39
|
+
* discarded because "not a git repository" must never land in a live
|
|
40
|
+
* TUI frame.
|
|
41
|
+
*
|
|
42
|
+
* Outside a repo — or with no git on PATH — the bounded walk stands
|
|
43
|
+
* in: it prunes AT_SKIP before descending and stops at AT_CAP + 1
|
|
44
|
+
* entries, the extra entry being what lets the panel's counter SAY it
|
|
45
|
+
* truncated instead of showing the first two thousand files as though
|
|
46
|
+
* they were all of them.
|
|
47
|
+
*
|
|
48
|
+
* Paths are forward-slashed on both branches (git's own format), so
|
|
49
|
+
* the fuzzy filter sees one alphabet whichever branch ran.
|
|
50
|
+
*/
|
|
51
|
+
export function atFiles() {
|
|
52
|
+
let paths;
|
|
53
|
+
try {
|
|
54
|
+
paths = execFileSync("git", ["ls-files", "-c", "-o", "--exclude-standard"], { cwd: process.cwd(), encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], maxBuffer: 1 << 24 }).split("\n").filter((p) => p !== "");
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
paths = atWalk(process.cwd(), "", []);
|
|
58
|
+
}
|
|
59
|
+
return paths.slice(0, AT_CAP + 1).map((path) => ({ path }));
|
|
60
|
+
}
|
|
61
|
+
/** The fallback walk. `prefix` carries the repo-relative directory so
|
|
62
|
+
* the result needs no path arithmetic afterwards. An unreadable
|
|
63
|
+
* directory contributes nothing and ends nothing — the recursion's own
|
|
64
|
+
* try catches it at that level, so one locked subtree cannot stop a
|
|
65
|
+
* file picker from opening. */
|
|
66
|
+
function atWalk(dir, prefix, out) {
|
|
67
|
+
try {
|
|
68
|
+
for (const e of readdirSync(dir, { withFileTypes: true })) {
|
|
69
|
+
if (out.length > AT_CAP)
|
|
70
|
+
break;
|
|
71
|
+
if (AT_SKIP.has(e.name))
|
|
72
|
+
continue;
|
|
73
|
+
if (e.isDirectory())
|
|
74
|
+
atWalk(`${dir}/${e.name}`, `${prefix}${e.name}/`, out);
|
|
75
|
+
else if (e.isFile())
|
|
76
|
+
out.push(`${prefix}${e.name}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// unreadable — skipped
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
27
84
|
/** v2b: the bottom-anchored UI — docked only on a color TTY; pipes and
|
|
28
85
|
* NO_COLOR stay the v2a line mode byte-for-byte. Created at load, like
|
|
29
86
|
* the pre-split module-scope const. */
|
package/dist/trust-ui.d.ts
CHANGED
|
@@ -9,11 +9,6 @@ import { type PanelVerdict, type PanelView } from "@vincemakes/kiso-tui";
|
|
|
9
9
|
import { type ProjectArtifacts } from "@vincemakes/kiso-runtime";
|
|
10
10
|
import type { AgentSession } from "@vincemakes/kiso-runtime";
|
|
11
11
|
import { type LineInput } from "./state.js";
|
|
12
|
-
/** v2a: the interactive prompt — blue, the identity accent. readline owns
|
|
13
|
-
* the echo of what the user types; we own the prompt's color. (v2c: the
|
|
14
|
-
* readline prompt keeps "you> " — the brick ▌ is the dock's row only;
|
|
15
|
-
* pipe bytes must not change.) */
|
|
16
|
-
export declare function interactivePrompt(): string;
|
|
17
12
|
/**
|
|
18
13
|
* W21 — ask the human with the approval panel: the bounded block that
|
|
19
14
|
* replaces the running tool's live window while the approval is pending.
|
package/dist/trust-ui.js
CHANGED
|
@@ -9,19 +9,11 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, symlinkS
|
|
|
9
9
|
import { homedir, tmpdir } from "node:os";
|
|
10
10
|
import { join } from "node:path";
|
|
11
11
|
import { pathToFileURL } from "node:url";
|
|
12
|
-
import {
|
|
12
|
+
import { projectTrustRows, projectTrustView, projectUntrustedNote, uncertainView } from "@vincemakes/kiso-tui";
|
|
13
13
|
import { projectArtifacts, recordTrust, trustFor } from "@vincemakes/kiso-runtime";
|
|
14
14
|
import { bodyLog, currentAgentExtensions, dock, extensionsDir, kisoHome, mergedTempPaths } from "./state.js";
|
|
15
15
|
import { loadUserConfig, resolveProjectTrustPolicy } from "./config.js";
|
|
16
16
|
import { getMode } from "./mode.js";
|
|
17
|
-
/** v2a: the interactive prompt — blue, the identity accent. readline owns
|
|
18
|
-
* the echo of what the user types; we own the prompt's color. (v2c: the
|
|
19
|
-
* readline prompt keeps "you> " — the brick ▌ is the dock's row only;
|
|
20
|
-
* pipe bytes must not change.) */
|
|
21
|
-
export function interactivePrompt() {
|
|
22
|
-
const p = palette();
|
|
23
|
-
return `${p.bold}you> ${p.reset}`;
|
|
24
|
-
}
|
|
25
17
|
/**
|
|
26
18
|
* W21 — ask the human with the approval panel: the bounded block that
|
|
27
19
|
* replaces the running tool's live window while the approval is pending.
|
|
@@ -192,7 +184,7 @@ export async function resolveProjectTrust(input) {
|
|
|
192
184
|
// First discovery — list every artifact (file name + digest short
|
|
193
185
|
// prefix) and ask the human ONCE.
|
|
194
186
|
if (!process.stdin.isTTY) {
|
|
195
|
-
console.error(
|
|
187
|
+
console.error(projectUntrustedNote(artifacts.files.length, artifacts.root));
|
|
196
188
|
return null;
|
|
197
189
|
}
|
|
198
190
|
// v2c: the shared input (the editor on a TTY) reads the answer.
|
|
@@ -201,19 +193,9 @@ export async function resolveProjectTrust(input) {
|
|
|
201
193
|
// the bodyLog below records, verbatim — the listing still lands in
|
|
202
194
|
// the scrollback; the panel is a bounded block, the record is not).
|
|
203
195
|
bodyLog(`[project .kiso] ${artifacts.root}`);
|
|
204
|
-
for (const
|
|
205
|
-
bodyLog(
|
|
206
|
-
|
|
207
|
-
const verdict = await askPanel(input, {
|
|
208
|
-
flavor: "simple",
|
|
209
|
-
name: "project trust",
|
|
210
|
-
title: artifacts.root,
|
|
211
|
-
speaker: "kiso",
|
|
212
|
-
statusText: "▸ project trust",
|
|
213
|
-
args: { kind: "text", lines: artifacts.files.map((f) => `${f.path} (${f.digest.slice(0, 6)})`) },
|
|
214
|
-
ruleOverride: "trust this project's .kiso?",
|
|
215
|
-
fallbackQuestion: `trust this project's .kiso? (y/n) `,
|
|
216
|
-
});
|
|
196
|
+
for (const row of projectTrustRows(artifacts.files, " "))
|
|
197
|
+
bodyLog(row);
|
|
198
|
+
const verdict = await askPanel(input, projectTrustView(artifacts.root, artifacts.files));
|
|
217
199
|
// A cancel is a "no" HERE — refused is sticky, the project does not
|
|
218
200
|
// load (re-evaluate by deleting the trust line or changing a file).
|
|
219
201
|
// The non-TTY branch above returned WITHOUT a record so an interactive
|
|
@@ -317,16 +299,7 @@ function readdirSyncSafe(dir) {
|
|
|
317
299
|
* the body is the single stdout writer, never a stray console.log. */
|
|
318
300
|
export async function resolveUncertains(session, input, isCancelled) {
|
|
319
301
|
for (const uncertain of session.uncertainExecutions()) {
|
|
320
|
-
const verdict = await askPanel(input,
|
|
321
|
-
flavor: "simple",
|
|
322
|
-
name: "uncertain execution",
|
|
323
|
-
title: `${uncertain.name} (${uncertain.executionId})`,
|
|
324
|
-
speaker: "kiso",
|
|
325
|
-
statusText: "▸ uncertain execution",
|
|
326
|
-
args: { kind: "text", lines: [uncertain.executionId] },
|
|
327
|
-
ruleOverride: "did the interrupted execution apply? — 1 rerun · 3 abandon",
|
|
328
|
-
fallbackQuestion: `⚠ interrupted execution: ${escapeTerminal(uncertain.name)} (${uncertain.executionId}) — did it apply? (y)es / (n)o `,
|
|
329
|
-
});
|
|
302
|
+
const verdict = await askPanel(input, uncertainView(uncertain.name, uncertain.executionId));
|
|
330
303
|
if (isCancelled() || verdict.action === "cancel") {
|
|
331
304
|
// round 10: a cancellation NEVER records a verdict — the execution
|
|
332
305
|
// stays uncertain and durable; no rerun/abandoned is fabricated.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vincemakes/kiso-code",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.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,18 +18,18 @@
|
|
|
18
18
|
"test": "vitest run"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@vincemakes/kiso-core": "0.
|
|
22
|
-
"@vincemakes/kiso-evals": "0.
|
|
23
|
-
"@vincemakes/kiso-mcp-ext": "0.
|
|
24
|
-
"@vincemakes/kiso-provider-anthropic": "0.
|
|
25
|
-
"@vincemakes/kiso-provider-openai": "0.
|
|
26
|
-
"@vincemakes/kiso-runtime": "0.
|
|
27
|
-
"@vincemakes/kiso-skills-ext": "0.
|
|
28
|
-
"@vincemakes/kiso-subagent-ext": "0.
|
|
29
|
-
"@vincemakes/kiso-task-ext": "0.
|
|
30
|
-
"@vincemakes/kiso-tools-node": "0.
|
|
31
|
-
"@vincemakes/kiso-tui": "0.
|
|
32
|
-
"@vincemakes/kiso-tui-cells": "0.
|
|
21
|
+
"@vincemakes/kiso-core": "0.7.0",
|
|
22
|
+
"@vincemakes/kiso-evals": "0.7.0",
|
|
23
|
+
"@vincemakes/kiso-mcp-ext": "0.7.0",
|
|
24
|
+
"@vincemakes/kiso-provider-anthropic": "0.7.0",
|
|
25
|
+
"@vincemakes/kiso-provider-openai": "0.7.0",
|
|
26
|
+
"@vincemakes/kiso-runtime": "0.7.0",
|
|
27
|
+
"@vincemakes/kiso-skills-ext": "0.7.0",
|
|
28
|
+
"@vincemakes/kiso-subagent-ext": "0.7.0",
|
|
29
|
+
"@vincemakes/kiso-task-ext": "0.7.0",
|
|
30
|
+
"@vincemakes/kiso-tools-node": "0.7.0",
|
|
31
|
+
"@vincemakes/kiso-tui": "0.7.0",
|
|
32
|
+
"@vincemakes/kiso-tui-cells": "0.7.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/node": "^26.1.2",
|