@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 +21 -0
- package/README.md +9 -0
- package/dist/dock.d.ts +55 -0
- package/dist/dock.js +152 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +1086 -0
- package/dist/render.d.ts +105 -0
- package/dist/render.js +265 -0
- package/package.json +45 -0
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
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -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;
|