@vincemakes/kiso-code 0.1.13

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kiso contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,9 @@
1
+ # @vincemakes/kiso-code
2
+
3
+ The coding-agent reference product: kiso chat / kiso resume / kiso
4
+ sessions. Install it or run directly with npx @vincemakes/kiso-code. Keyless faux
5
+ mode out of the box; ANTHROPIC_API_KEY or OPENAI_API_KEY + OPENAI_BASE_URL
6
+ switch to real providers.
7
+
8
+ Requires Node >= 22. See the repository README for the framework
9
+ overview.
package/dist/dock.d.ts ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * v2b — the bottom-anchored UI (TTY + color only). Borrows pi-tui's IDEA —
3
+ * a DECSTBM scroll region with a reserved bottom — without its
4
+ * implementation: zero dependencies, line-level ANSI, no differential
5
+ * renderer.
6
+ *
7
+ * Layout (H = terminal height): rows 1..H-3 = the scroll region (the body
8
+ * streams and scrolls here, never touching the bottom), row H-2 = the dim
9
+ * separator, row H-1 = the live status bar (or a takeover question), row
10
+ * H = the input line (blue you> + readline). Bottom redraws are wrapped in
11
+ * CSI 2026 (synchronized output) to avoid flicker — the pi trick.
12
+ *
13
+ * Pipes / NO_COLOR: the dock never activates; the v2a line mode stays
14
+ * byte-for-byte (the existing e2e assertions guard it).
15
+ */
16
+ export declare class Dock {
17
+ #private;
18
+ /** v2b: docked only on a color TTY — pipes and NO_COLOR stay v2a. */
19
+ get active(): boolean;
20
+ /** Bind the CURRENT input line's state — called when a readline takes
21
+ * over (the chat REPL, the trust question's short-lived rl, resume). */
22
+ bindInput(state: () => {
23
+ line: string;
24
+ cursor: number;
25
+ }, prompt: string): void;
26
+ /** Enter docked mode: DECSTBM the scroll region, draw the chrome. A
27
+ * TTY without a real window size (rows < 4) stays in the v2a line
28
+ * mode — the bottom three rows need room to exist. */
29
+ enter(): void;
30
+ /** Teardown — CSI r resets the scroll region, the cursor lands at the
31
+ * input line, the bottom rows are cleared: no broken terminal. Called
32
+ * from main's finally on EVERY exit path (kill -9 excepted — README:
33
+ * `reset` saves it). */
34
+ exit(): void;
35
+ /** SIGWINCH: recompute the region, redraw the chrome. */
36
+ onResize(): void;
37
+ /** Body output: position the cursor inside the scroll region at the
38
+ * body's tracked position, write, and hand the cursor back to the
39
+ * input line. The row/col tracking is approximate for width-wrapped
40
+ * and wide-char lines (documented) — the region clamp keeps the
41
+ * bottom rows safe regardless. */
42
+ writeBody(text: string): void;
43
+ /** The status bar's base text (usage, ctx, session, …). */
44
+ setStatus(text: string): void;
45
+ /** The live tail — the spinner glyph or "running <tool> Ns". */
46
+ setTail(tail: string): void;
47
+ /** Show a takeover question at the status position (answered at the
48
+ * input line by the caller's readline); clearQuestion() restores. */
49
+ showQuestion(question: string): void;
50
+ clearQuestion(): void;
51
+ /** The bottom three rows, wrapped in CSI 2026 (synchronized output —
52
+ * the pi trick against flicker). The cursor ends at the input line's
53
+ * edit position. */
54
+ redraw(): void;
55
+ }
package/dist/dock.js ADDED
@@ -0,0 +1,152 @@
1
+ /**
2
+ * v2b — the bottom-anchored UI (TTY + color only). Borrows pi-tui's IDEA —
3
+ * a DECSTBM scroll region with a reserved bottom — without its
4
+ * implementation: zero dependencies, line-level ANSI, no differential
5
+ * renderer.
6
+ *
7
+ * Layout (H = terminal height): rows 1..H-3 = the scroll region (the body
8
+ * streams and scrolls here, never touching the bottom), row H-2 = the dim
9
+ * separator, row H-1 = the live status bar (or a takeover question), row
10
+ * H = the input line (blue you> + readline). Bottom redraws are wrapped in
11
+ * CSI 2026 (synchronized output) to avoid flicker — the pi trick.
12
+ *
13
+ * Pipes / NO_COLOR: the dock never activates; the v2a line mode stays
14
+ * byte-for-byte (the existing e2e assertions guard it).
15
+ */
16
+ import { palette } from "./render.js";
17
+ export class Dock {
18
+ #active = false;
19
+ #height = 0;
20
+ #width = 0;
21
+ #status = "";
22
+ #tail = ""; // the live tail: the spinner glyph or "running <tool> Ns"
23
+ #question = null; // a takeover question shown at H-1
24
+ #inputState = () => ({ line: "", cursor: 0 });
25
+ #inputPrompt = "";
26
+ #bodyRow = 1; // the body's logical row inside the scroll region
27
+ #bodyCol = 1; // …and column (mid-line continuations survive cursor jumps)
28
+ #resizeHandler = null;
29
+ /** v2b: docked only on a color TTY — pipes and NO_COLOR stay v2a. */
30
+ get active() {
31
+ return this.#active;
32
+ }
33
+ /** Bind the CURRENT input line's state — called when a readline takes
34
+ * over (the chat REPL, the trust question's short-lived rl, resume). */
35
+ bindInput(state, prompt) {
36
+ this.#inputState = state;
37
+ this.#inputPrompt = prompt;
38
+ }
39
+ /** Enter docked mode: DECSTBM the scroll region, draw the chrome. A
40
+ * TTY without a real window size (rows < 4) stays in the v2a line
41
+ * mode — the bottom three rows need room to exist. */
42
+ enter() {
43
+ const rows = process.stdout.rows ?? 0;
44
+ if (process.stdout.isTTY !== true || palette().blue === "" || rows < 4)
45
+ return;
46
+ this.#active = true;
47
+ this.#height = rows;
48
+ this.#width = process.stdout.columns ?? 80;
49
+ this.#bodyRow = 1;
50
+ this.#bodyCol = 1;
51
+ process.stdout.write(`\x1b[1;${this.#height - 3}r`); // scroll region: top .. H-3
52
+ this.redraw();
53
+ this.#resizeHandler = () => this.onResize();
54
+ process.stdout.on("resize", this.#resizeHandler);
55
+ }
56
+ /** Teardown — CSI r resets the scroll region, the cursor lands at the
57
+ * input line, the bottom rows are cleared: no broken terminal. Called
58
+ * from main's finally on EVERY exit path (kill -9 excepted — README:
59
+ * `reset` saves it). */
60
+ exit() {
61
+ if (!this.#active)
62
+ return;
63
+ this.#active = false;
64
+ if (this.#resizeHandler !== null) {
65
+ process.stdout.off("resize", this.#resizeHandler);
66
+ this.#resizeHandler = null;
67
+ }
68
+ const H = this.#height;
69
+ process.stdout.write("\x1b[r"); // reset the scroll region
70
+ for (let row = H - 2; row <= H; row += 1) {
71
+ process.stdout.write(`\x1b[${row};1H\x1b[0K`); // clear the three rows
72
+ }
73
+ process.stdout.write(`\x1b[${H};1H`);
74
+ }
75
+ /** SIGWINCH: recompute the region, redraw the chrome. */
76
+ onResize() {
77
+ if (!this.#active)
78
+ return;
79
+ this.#height = process.stdout.rows ?? this.#height;
80
+ this.#width = process.stdout.columns ?? this.#width;
81
+ process.stdout.write(`\x1b[1;${this.#height - 3}r`);
82
+ this.redraw();
83
+ }
84
+ /** Body output: position the cursor inside the scroll region at the
85
+ * body's tracked position, write, and hand the cursor back to the
86
+ * input line. The row/col tracking is approximate for width-wrapped
87
+ * and wide-char lines (documented) — the region clamp keeps the
88
+ * bottom rows safe regardless. */
89
+ writeBody(text) {
90
+ if (!this.#active) {
91
+ process.stdout.write(text);
92
+ return;
93
+ }
94
+ const row = Math.min(this.#bodyRow, this.#height - 3);
95
+ const col = this.#bodyCol > this.#width ? this.#width : this.#bodyCol;
96
+ process.stdout.write(`\x1b[${row};${col}H`);
97
+ process.stdout.write(text);
98
+ for (const ch of text) {
99
+ if (ch === "\n") {
100
+ this.#bodyRow += 1;
101
+ this.#bodyCol = 1;
102
+ }
103
+ else {
104
+ this.#bodyCol += 1;
105
+ }
106
+ }
107
+ process.stdout.write(`\x1b[${this.#height};1H`); // back to the input line
108
+ }
109
+ /** The status bar's base text (usage, ctx, session, …). */
110
+ setStatus(text) {
111
+ this.#status = text;
112
+ this.redraw();
113
+ }
114
+ /** The live tail — the spinner glyph or "running <tool> Ns". */
115
+ setTail(tail) {
116
+ this.#tail = tail;
117
+ this.redraw();
118
+ }
119
+ /** Show a takeover question at the status position (answered at the
120
+ * input line by the caller's readline); clearQuestion() restores. */
121
+ showQuestion(question) {
122
+ this.#question = question;
123
+ this.redraw();
124
+ }
125
+ clearQuestion() {
126
+ this.#question = null;
127
+ this.redraw();
128
+ }
129
+ /** The bottom three rows, wrapped in CSI 2026 (synchronized output —
130
+ * the pi trick against flicker). The cursor ends at the input line's
131
+ * edit position. */
132
+ redraw() {
133
+ if (!this.#active)
134
+ return;
135
+ const p = palette();
136
+ const H = this.#height;
137
+ const W = this.#width;
138
+ const sep = `${p.dim}${"─".repeat(W)}${p.reset}`;
139
+ const status = `${this.#status}${this.#tail === "" ? "" : ` · ${this.#tail}`}`;
140
+ const statusLine = this.#question ?? status;
141
+ const inp = this.#inputState();
142
+ const promptWidth = this.#inputPrompt.replace(/\x1b\[[0-9;]*m/g, "").length;
143
+ const out = [];
144
+ out.push("\x1b[2026h"); // synchronized output ON
145
+ out.push(`\x1b[${H - 2};1H\x1b[0K${sep}`);
146
+ out.push(`\x1b[${H - 1};1H\x1b[0K${statusLine}`);
147
+ out.push(`\x1b[${H};1H\x1b[0K${this.#inputPrompt}${inp.line}`);
148
+ out.push(`\x1b[${H};${promptWidth + inp.cursor + 1}H`); // back to the edit position
149
+ out.push("\x1b[2026l"); // synchronized output OFF
150
+ process.stdout.write(out.join(""));
151
+ }
152
+ }
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * kiso — the coding-agent reference product.
4
+ *
5
+ * kiso chat [sessionId] start or continue an interactive session
6
+ * kiso resume <sessionId> continue a session in one-shot mode
7
+ * kiso sessions list durable sessions
8
+ *
9
+ * Provider selection (first match):
10
+ * ANTHROPIC_API_KEY → Anthropic (ANTHROPIC_MODEL, default claude-sonnet-5)
11
+ * OPENAI_API_KEY → OpenAI-compatible (OPENAI_MODEL, OPENAI_BASE_URL)
12
+ * neither → faux mode: scripted model, zero keys, full CLI
13
+ *
14
+ * Sessions live under $KISO_HOME/sessions (default ~/.kiso/sessions) as
15
+ * append-only JSONL. Write/edit/shell tools sit behind the approval policy:
16
+ * the run pauses, asks, and resumes — durably (ADR-0024).
17
+ */
18
+ import { type ProjectArtifacts } from "@vincemakes/kiso-runtime";
19
+ /**
20
+ * E3 — merge the project's mcp.json and skills into the env BEFORE the
21
+ * extension load. A server name in BOTH configs is a LOUD error (a silent
22
+ * override would be a supply-chain surprise); a skill name in both merges
23
+ * with project-wins and a stderr note. Exported for tests.
24
+ */
25
+ export declare function applyProjectMerges(artifacts: ProjectArtifacts): void;
26
+ /**
27
+ * A 区: read the FIRST present instruction file (AGENTS.md preferred) and
28
+ * return it as an injected section, or "" when none exists. Truncated at
29
+ * 8KB with an explicit note. Pure — read once per session, so the prompt
30
+ * is byte-stable for the session's lifetime.
31
+ */
32
+ export declare function readProjectInstructions(cwd: string): string;
33
+ /** A 区: the session's system prompt — the constant plus any project
34
+ * instructions found in the workspace. Deterministic per cwd. */
35
+ export declare function composeSystemPrompt(cwd: string): string;