chivgent 0.17.0 → 0.18.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/README.md +19 -2
- package/README.zh-CN.md +15 -1
- package/dist/cli.js +18 -3
- package/dist/cli.js.map +1 -1
- package/dist/remote/framing.d.ts +3 -1
- package/dist/remote/framing.d.ts.map +1 -1
- package/dist/remote/framing.js +23 -9
- package/dist/remote/framing.js.map +1 -1
- package/dist/repl.d.ts +1 -0
- package/dist/repl.d.ts.map +1 -1
- package/dist/repl.js +89 -65
- package/dist/repl.js.map +1 -1
- package/dist/shell/output.d.ts.map +1 -1
- package/dist/shell/output.js +3 -14
- package/dist/shell/output.js.map +1 -1
- package/dist/shell/truncate.d.ts +2 -0
- package/dist/shell/truncate.d.ts.map +1 -1
- package/dist/shell/truncate.js +17 -6
- package/dist/shell/truncate.js.map +1 -1
- package/dist/tui/input.d.ts +24 -0
- package/dist/tui/input.d.ts.map +1 -0
- package/dist/tui/input.js +45 -0
- package/dist/tui/input.js.map +1 -0
- package/dist/tui/live.d.ts +3 -0
- package/dist/tui/live.d.ts.map +1 -1
- package/dist/tui/live.js +38 -4
- package/dist/tui/live.js.map +1 -1
- package/dist/tui/paint.d.ts +3 -1
- package/dist/tui/paint.d.ts.map +1 -1
- package/dist/tui/paint.js +17 -7
- package/dist/tui/paint.js.map +1 -1
- package/dist/tui/text.d.ts +7 -0
- package/dist/tui/text.d.ts.map +1 -0
- package/dist/tui/text.js +31 -0
- package/dist/tui/text.js.map +1 -0
- package/dist/tui/view.d.ts +1 -0
- package/dist/tui/view.d.ts.map +1 -1
- package/dist/tui/view.js +6 -11
- package/dist/tui/view.js.map +1 -1
- package/dist/tui/welcome.d.ts +12 -0
- package/dist/tui/welcome.d.ts.map +1 -0
- package/dist/tui/welcome.js +28 -0
- package/dist/tui/welcome.js.map +1 -0
- package/package.json +4 -2
package/dist/shell/truncate.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export interface TruncationResult {
|
|
|
17
17
|
readonly maxLines: number;
|
|
18
18
|
readonly maxBytes: number;
|
|
19
19
|
}
|
|
20
|
+
/** Keeps whole characters, never splitting a multi-byte sequence. */
|
|
21
|
+
export declare function takeLastBytes(value: string, maxBytes: number): string;
|
|
20
22
|
export declare function countLines(content: string): number;
|
|
21
23
|
/**
|
|
22
24
|
* Keeps the end of the content.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../src/shell/truncate.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AACvC,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAE3C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../src/shell/truncate.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,iBAAiB,OAAQ,CAAC;AACvC,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAE3C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAAC;IAC/C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,gFAAgF;IAChF,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAoBD,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAwBrE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,iBAAsB,GAC9B,gBAAgB,CAsElB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQhD"}
|
package/dist/shell/truncate.js
CHANGED
|
@@ -17,19 +17,30 @@ function splitLines(content) {
|
|
|
17
17
|
return lines;
|
|
18
18
|
}
|
|
19
19
|
/** Keeps whole characters, never splitting a multi-byte sequence. */
|
|
20
|
-
function takeLastBytes(value, maxBytes) {
|
|
21
|
-
const characters = [...value];
|
|
20
|
+
export function takeLastBytes(value, maxBytes) {
|
|
22
21
|
let bytes = 0;
|
|
23
|
-
let index =
|
|
22
|
+
let index = value.length;
|
|
23
|
+
// Walk UTF-16 backwards without allocating an array for the entire input.
|
|
24
|
+
// A surrogate pair is one four-byte UTF-8 character; an unpaired surrogate
|
|
25
|
+
// is encoded as the three-byte replacement character, just like Buffer.
|
|
24
26
|
while (index > 0) {
|
|
25
|
-
const
|
|
27
|
+
const code = value.charCodeAt(index - 1);
|
|
28
|
+
let units = 1;
|
|
29
|
+
let size = code <= 0x7f ? 1 : code <= 0x7ff ? 2 : 3;
|
|
30
|
+
if (code >= 0xdc00 && code <= 0xdfff && index > 1) {
|
|
31
|
+
const previous = value.charCodeAt(index - 2);
|
|
32
|
+
if (previous >= 0xd800 && previous <= 0xdbff) {
|
|
33
|
+
units = 2;
|
|
34
|
+
size = 4;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
26
37
|
if (bytes + size > maxBytes) {
|
|
27
38
|
break;
|
|
28
39
|
}
|
|
29
40
|
bytes += size;
|
|
30
|
-
index -=
|
|
41
|
+
index -= units;
|
|
31
42
|
}
|
|
32
|
-
return
|
|
43
|
+
return value.slice(index);
|
|
33
44
|
}
|
|
34
45
|
export function countLines(content) {
|
|
35
46
|
return splitLines(content).length;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../src/shell/truncate.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,0CAA0C;AAE1C,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAC;AACvC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,CAAC;AAqB3C,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAC1C,CAAC;AAED,4EAA4E;AAC5E,SAAS,UAAU,CAAC,OAAe;IACjC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CACzD,KAAK,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAC9C,CAAC;IACF,IAAI,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QACxB,KAAK,CAAC,GAAG,EAAE,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,qEAAqE;AACrE,
|
|
1
|
+
{"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../src/shell/truncate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { PassThrough } from "node:stream";
|
|
2
|
+
type TerminalInput = NodeJS.ReadableStream & {
|
|
3
|
+
isTTY?: boolean;
|
|
4
|
+
setRawMode?: (enabled: boolean) => unknown;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Readline keeps its normal editing and history. During a run, only Ctrl+C
|
|
8
|
+
* reaches it: typing must neither echo into the live region nor queue prompts.
|
|
9
|
+
* The source stays in raw mode so cancellation still arrives immediately.
|
|
10
|
+
*/
|
|
11
|
+
export declare class TuiInput extends PassThrough {
|
|
12
|
+
private readonly source;
|
|
13
|
+
readonly isTTY: boolean;
|
|
14
|
+
private busy;
|
|
15
|
+
constructor(source: TerminalInput);
|
|
16
|
+
setRawMode(enabled: boolean): this;
|
|
17
|
+
setBusy(busy: boolean): void;
|
|
18
|
+
dispose(): void;
|
|
19
|
+
private readonly receive;
|
|
20
|
+
private readonly ended;
|
|
21
|
+
private readonly failed;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/tui/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,KAAK,aAAa,GAAG,MAAM,CAAC,cAAc,GAAG;IAC3C,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC;CAC5C,CAAC;AAEF;;;;GAIG;AACH,qBAAa,QAAS,SAAQ,WAAW;IAI3B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAHnC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,IAAI,CAAS;IAErB,YAA6B,MAAM,EAAE,aAAa,EAMjD;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAGjC;IAED,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAE3B;IAED,OAAO,IAAI,IAAI,CAOd;IAED,OAAO,CAAC,QAAQ,CAAC,OAAO,CAMtB;IAEF,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA+B;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoD;CAC5E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { PassThrough } from "node:stream";
|
|
2
|
+
/**
|
|
3
|
+
* Readline keeps its normal editing and history. During a run, only Ctrl+C
|
|
4
|
+
* reaches it: typing must neither echo into the live region nor queue prompts.
|
|
5
|
+
* The source stays in raw mode so cancellation still arrives immediately.
|
|
6
|
+
*/
|
|
7
|
+
export class TuiInput extends PassThrough {
|
|
8
|
+
source;
|
|
9
|
+
isTTY;
|
|
10
|
+
busy = false;
|
|
11
|
+
constructor(source) {
|
|
12
|
+
super();
|
|
13
|
+
this.source = source;
|
|
14
|
+
this.isTTY = source.isTTY === true;
|
|
15
|
+
source.on("data", this.receive);
|
|
16
|
+
source.on("end", this.ended);
|
|
17
|
+
source.on("error", this.failed);
|
|
18
|
+
}
|
|
19
|
+
setRawMode(enabled) {
|
|
20
|
+
this.source.setRawMode?.(enabled);
|
|
21
|
+
return this;
|
|
22
|
+
}
|
|
23
|
+
setBusy(busy) {
|
|
24
|
+
this.busy = busy;
|
|
25
|
+
}
|
|
26
|
+
dispose() {
|
|
27
|
+
this.source.off("data", this.receive);
|
|
28
|
+
this.source.off("end", this.ended);
|
|
29
|
+
this.source.off("error", this.failed);
|
|
30
|
+
this.setRawMode(false);
|
|
31
|
+
this.source.pause();
|
|
32
|
+
this.destroy();
|
|
33
|
+
}
|
|
34
|
+
receive = (chunk) => {
|
|
35
|
+
if (!this.busy) {
|
|
36
|
+
this.write(chunk);
|
|
37
|
+
}
|
|
38
|
+
else if (chunk.includes("\u0003")) {
|
|
39
|
+
this.write("\u0003");
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
ended = () => { this.end(); };
|
|
43
|
+
failed = (error) => { this.destroy(error); };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/tui/input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAO1C;;;;GAIG;AACH,MAAM,OAAO,QAAS,SAAQ,WAAW;IAIV,MAAM;IAH1B,KAAK,CAAU;IAChB,IAAI,GAAG,KAAK,CAAC;IAErB,YAA6B,MAAqB;QAChD,KAAK,EAAE,CAAC;sBADmB,MAAM;QAEjC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC;QACnC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IAED,UAAU,CAAC,OAAgB;QACzB,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,OAAO,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CAAC,IAAa;QACnB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,OAAO;QACL,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAEgB,OAAO,GAAG,CAAC,KAAsB,EAAQ,EAAE;QAC1D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IAEe,KAAK,GAAG,GAAS,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,GAAG,CAAC,KAAY,EAAQ,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;CAC5E"}
|
package/dist/tui/live.d.ts
CHANGED
|
@@ -4,6 +4,9 @@ export interface LiveRegionOptions {
|
|
|
4
4
|
readonly stream: OutputStream;
|
|
5
5
|
/** Re-read on every paint: a resize changes it under us. */
|
|
6
6
|
readonly width: () => number;
|
|
7
|
+
readonly height?: () => number;
|
|
8
|
+
/** Final answers can be redirected independently of terminal chrome. */
|
|
9
|
+
readonly answerStream?: OutputStream;
|
|
7
10
|
readonly now?: () => number;
|
|
8
11
|
readonly tickMs?: number;
|
|
9
12
|
}
|
package/dist/tui/live.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/tui/live.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/tui/live.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAc,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AASjD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,EAAE,MAAM,MAAM,CAAC;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IAC/B,wEAAwE;IACxE,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,EAAE,kBAAkB,CAAC;IACtC,iEAAiE;IACjE,IAAI,IAAI,IAAI,CAAC;IACb,0DAA0D;IAC1D,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,iBAAiB,GAAG,UAAU,CA+FvE;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAGlE"}
|
package/dist/tui/live.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { formatTokens } from "../providers/usage.js";
|
|
2
|
+
import { terminalText, fitLine } from "./text.js";
|
|
1
3
|
import { Painter } from "./paint.js";
|
|
2
4
|
import { EMPTY_STATE, reduce } from "./state.js";
|
|
3
5
|
import { transcriptLines, view } from "./view.js";
|
|
@@ -17,7 +19,12 @@ export function createLiveRegion(options) {
|
|
|
17
19
|
let state = EMPTY_STATE;
|
|
18
20
|
let timer;
|
|
19
21
|
const paint = () => {
|
|
20
|
-
painter.render(view(state, {
|
|
22
|
+
painter.render(view(state, {
|
|
23
|
+
// Leave one cell spare to avoid a terminal's pending autowrap state.
|
|
24
|
+
width: Math.max(1, options.width() - 1),
|
|
25
|
+
height: Math.max(1, (options.height?.() ?? 24) - 2),
|
|
26
|
+
now: clock(),
|
|
27
|
+
}));
|
|
21
28
|
};
|
|
22
29
|
const startClock = () => {
|
|
23
30
|
if (timer !== undefined) {
|
|
@@ -41,11 +48,18 @@ export function createLiveRegion(options) {
|
|
|
41
48
|
// region is erased first so the transcript lands where it was, then
|
|
42
49
|
// the region is drawn again below it.
|
|
43
50
|
painter.clear();
|
|
44
|
-
const lines = transcriptLines(event
|
|
51
|
+
const lines = transcriptLines(options.answerStream === undefined ? event : {
|
|
52
|
+
...event,
|
|
53
|
+
message: { ...event.message, content: "" },
|
|
54
|
+
});
|
|
45
55
|
if (lines.length > 0) {
|
|
46
|
-
options.stream.write(`${lines.join("\n")}\n`);
|
|
56
|
+
options.stream.write(`${terminalText(lines.join("\n"))}\n`);
|
|
57
|
+
}
|
|
58
|
+
if (options.answerStream !== undefined && event.message.content.trim().length > 0) {
|
|
59
|
+
options.answerStream.write(`${event.message.content}\n`);
|
|
47
60
|
}
|
|
48
61
|
}
|
|
62
|
+
const previous = state;
|
|
49
63
|
state = reduce(state, event, clock());
|
|
50
64
|
if (event.type === "agent_start") {
|
|
51
65
|
startClock();
|
|
@@ -53,6 +67,24 @@ export function createLiveRegion(options) {
|
|
|
53
67
|
if (event.type === "agent_end") {
|
|
54
68
|
stopClock();
|
|
55
69
|
painter.clear();
|
|
70
|
+
// Cancellation can end a streamed turn before turn_end arrives.
|
|
71
|
+
if (previous.run?.text) {
|
|
72
|
+
(options.answerStream ?? options.stream).write(`${terminalText(previous.run.text)}\n`);
|
|
73
|
+
}
|
|
74
|
+
const label = event.status === "completed" ? "Completed"
|
|
75
|
+
: event.status === "aborted" ? "Stopped"
|
|
76
|
+
: event.status === "max_turns" ? "Turn limit reached" : "Failed";
|
|
77
|
+
const parts = [label, `${event.turnCount} turn(s)`];
|
|
78
|
+
if (previous.run !== undefined) {
|
|
79
|
+
parts.push(`${Math.max(0, Math.round((clock() - previous.run.startedAt) / 1000))}s`);
|
|
80
|
+
}
|
|
81
|
+
if (event.usage !== undefined) {
|
|
82
|
+
parts.push(`${formatTokens(event.usage.usage.totalTokens)} tokens${event.usage.complete ? "" : "+"}`);
|
|
83
|
+
}
|
|
84
|
+
options.stream.write(`${fitLine(parts.join(" · "), options.width() - 1)}\n`);
|
|
85
|
+
if (event.error !== undefined) {
|
|
86
|
+
options.stream.write(`${terminalText(event.error)}\n`);
|
|
87
|
+
}
|
|
56
88
|
return;
|
|
57
89
|
}
|
|
58
90
|
paint();
|
|
@@ -63,7 +95,9 @@ export function createLiveRegion(options) {
|
|
|
63
95
|
state = EMPTY_STATE;
|
|
64
96
|
},
|
|
65
97
|
resized: () => {
|
|
66
|
-
|
|
98
|
+
if (state.run === undefined)
|
|
99
|
+
return;
|
|
100
|
+
painter.invalidate(options.width());
|
|
67
101
|
paint();
|
|
68
102
|
},
|
|
69
103
|
};
|
package/dist/tui/live.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/tui/live.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/tui/live.ts"],"names":[],"mappings":"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"}
|
package/dist/tui/paint.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ export declare class Painter {
|
|
|
19
19
|
* without the painter knowing anything about it.
|
|
20
20
|
*/
|
|
21
21
|
private previous;
|
|
22
|
+
private invalidated;
|
|
23
|
+
private previousRows;
|
|
22
24
|
constructor(options: PainterOptions);
|
|
23
25
|
/**
|
|
24
26
|
* Discards the diff baseline.
|
|
@@ -28,7 +30,7 @@ export declare class Painter {
|
|
|
28
30
|
* lines that are no longer there. This is the one moment a full repaint is
|
|
29
31
|
* the correct answer rather than a lazy one.
|
|
30
32
|
*/
|
|
31
|
-
invalidate(): void;
|
|
33
|
+
invalidate(columns?: number): void;
|
|
32
34
|
render(lines: readonly string[]): void;
|
|
33
35
|
/** Erases the region entirely, leaving the cursor where it began. */
|
|
34
36
|
clear(): void;
|
package/dist/tui/paint.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/tui/paint.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paint.d.ts","sourceRoot":"","sources":["../../src/tui/paint.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAMjD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,qBAAa,OAAO;IAUN,OAAO,CAAC,QAAQ,CAAC,OAAO;IATpC;;;;OAIG;IACH,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAK;IAEzB,YAA6B,OAAO,EAAE,cAAc,EAAI;IAExD;;;;;;;OAOG;IACH,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAQjC;IAED,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CA4BrC;IAED,qEAAqE;IACrE,KAAK,IAAI,IAAI,CAcZ;CACF"}
|
package/dist/tui/paint.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { displayWidth } from "./text.js";
|
|
1
2
|
const CURSOR_UP = "\u001B[A";
|
|
2
3
|
const CLEAR_LINE = "\u001B[2K";
|
|
3
4
|
const CARRIAGE_RETURN = "\r";
|
|
@@ -18,6 +19,8 @@ export class Painter {
|
|
|
18
19
|
* without the painter knowing anything about it.
|
|
19
20
|
*/
|
|
20
21
|
previous = [];
|
|
22
|
+
invalidated = false;
|
|
23
|
+
previousRows = 0;
|
|
21
24
|
constructor(options) {
|
|
22
25
|
this.options = options;
|
|
23
26
|
}
|
|
@@ -29,17 +32,20 @@ export class Painter {
|
|
|
29
32
|
* lines that are no longer there. This is the one moment a full repaint is
|
|
30
33
|
* the correct answer rather than a lazy one.
|
|
31
34
|
*/
|
|
32
|
-
invalidate() {
|
|
33
|
-
this.
|
|
35
|
+
invalidate(columns) {
|
|
36
|
+
this.invalidated = true;
|
|
37
|
+
if (columns !== undefined && columns > 0) {
|
|
38
|
+
this.previousRows = this.previous.reduce((rows, line) => rows + Math.max(1, Math.ceil(displayWidth(line) / columns)), 0);
|
|
39
|
+
}
|
|
34
40
|
}
|
|
35
41
|
render(lines) {
|
|
36
|
-
if (sameLines(this.previous, lines)) {
|
|
42
|
+
if (!this.invalidated && sameLines(this.previous, lines)) {
|
|
37
43
|
return;
|
|
38
44
|
}
|
|
39
45
|
// Back to the top of the region, then forward a line at a time, so the
|
|
40
46
|
// cursor ends where it began and the caller's prompt line is undisturbed.
|
|
41
|
-
let out = CURSOR_UP.repeat(this.
|
|
42
|
-
const height = Math.max(this.
|
|
47
|
+
let out = CURSOR_UP.repeat(this.previousRows) + CARRIAGE_RETURN;
|
|
48
|
+
const height = Math.max(this.previousRows, lines.length);
|
|
43
49
|
for (let index = 0; index < height; index += 1) {
|
|
44
50
|
const next = lines[index];
|
|
45
51
|
if (next === undefined) {
|
|
@@ -47,7 +53,7 @@ export class Painter {
|
|
|
47
53
|
out += `${CLEAR_LINE}\n`;
|
|
48
54
|
continue;
|
|
49
55
|
}
|
|
50
|
-
out += this.previous[index] === next ? "\n" : `${CLEAR_LINE}${next}\n`;
|
|
56
|
+
out += !this.invalidated && this.previous[index] === next ? "\n" : `${CLEAR_LINE}${next}\n`;
|
|
51
57
|
}
|
|
52
58
|
// A shrunken region left the cursor below its new last line.
|
|
53
59
|
if (height > lines.length) {
|
|
@@ -55,10 +61,12 @@ export class Painter {
|
|
|
55
61
|
}
|
|
56
62
|
this.options.stream.write(out);
|
|
57
63
|
this.previous = [...lines];
|
|
64
|
+
this.previousRows = lines.length;
|
|
65
|
+
this.invalidated = false;
|
|
58
66
|
}
|
|
59
67
|
/** Erases the region entirely, leaving the cursor where it began. */
|
|
60
68
|
clear() {
|
|
61
|
-
const height = this.
|
|
69
|
+
const height = this.previousRows;
|
|
62
70
|
if (height === 0) {
|
|
63
71
|
return;
|
|
64
72
|
}
|
|
@@ -67,6 +75,8 @@ export class Painter {
|
|
|
67
75
|
`${CLEAR_LINE}\n`.repeat(height) +
|
|
68
76
|
CURSOR_UP.repeat(height));
|
|
69
77
|
this.previous = [];
|
|
78
|
+
this.previousRows = 0;
|
|
79
|
+
this.invalidated = false;
|
|
70
80
|
}
|
|
71
81
|
}
|
|
72
82
|
function sameLines(left, right) {
|
package/dist/tui/paint.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paint.js","sourceRoot":"","sources":["../../src/tui/paint.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paint.js","sourceRoot":"","sources":["../../src/tui/paint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import stringWidth from "string-width";
|
|
2
|
+
/** Terminal content may contain cursor controls; only our painter owns those. */
|
|
3
|
+
export declare function terminalText(text: string): string;
|
|
4
|
+
export { stringWidth as displayWidth };
|
|
5
|
+
/** Fit terminal cells, preserving whole graphemes (including joined emoji). */
|
|
6
|
+
export declare function fitLine(text: string, columns: number): string;
|
|
7
|
+
//# sourceMappingURL=text.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/tui/text.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,MAAM,cAAc,CAAC;AAIvC,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD;AAED,OAAO,EAAE,WAAW,IAAI,YAAY,EAAE,CAAC;AAEvC,+EAA+E;AAC/E,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAc7D"}
|
package/dist/tui/text.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { stripVTControlCharacters } from "node:util";
|
|
2
|
+
import stringWidth from "string-width";
|
|
3
|
+
const graphemes = new Intl.Segmenter(undefined, { granularity: "grapheme" });
|
|
4
|
+
/** Terminal content may contain cursor controls; only our painter owns those. */
|
|
5
|
+
export function terminalText(text) {
|
|
6
|
+
return stripVTControlCharacters(text)
|
|
7
|
+
.replace(/\r\n/g, "\n")
|
|
8
|
+
.replace(/\t/g, " ")
|
|
9
|
+
.replace(/[\u0000-\u0009\u000b-\u001f\u007f-\u009f]/g, "");
|
|
10
|
+
}
|
|
11
|
+
export { stringWidth as displayWidth };
|
|
12
|
+
/** Fit terminal cells, preserving whole graphemes (including joined emoji). */
|
|
13
|
+
export function fitLine(text, columns) {
|
|
14
|
+
const width = Math.max(0, Math.floor(columns));
|
|
15
|
+
const clean = terminalText(text).replace(/\n/g, " ");
|
|
16
|
+
if (width === 0)
|
|
17
|
+
return "";
|
|
18
|
+
if (stringWidth(clean) <= width)
|
|
19
|
+
return clean;
|
|
20
|
+
let result = "";
|
|
21
|
+
let used = 0;
|
|
22
|
+
for (const { segment } of graphemes.segment(clean)) {
|
|
23
|
+
const size = stringWidth(segment);
|
|
24
|
+
if (used + size > width - 1)
|
|
25
|
+
break;
|
|
26
|
+
result += segment;
|
|
27
|
+
used += size;
|
|
28
|
+
}
|
|
29
|
+
return `${result}…`;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/tui/text.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,WAAW,MAAM,cAAc,CAAC;AAEvC,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,WAAW,EAAE,UAAU,EAAE,CAAC,CAAC;AAE7E,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,wBAAwB,CAAC,IAAI,CAAC;SAClC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC;SACtB,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC;SACpB,OAAO,CAAC,4CAA4C,EAAE,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,OAAO,EAAE,WAAW,IAAI,YAAY,EAAE,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,UAAU,OAAO,CAAC,IAAY,EAAE,OAAe;IACnD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACrD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAC3B,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IAC9C,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG,CAAC;YAAE,MAAM;QACnC,MAAM,IAAI,OAAO,CAAC;QAClB,IAAI,IAAI,IAAI,CAAC;IACf,CAAC;IACD,OAAO,GAAG,MAAM,GAAG,CAAC;AACtB,CAAC"}
|
package/dist/tui/view.d.ts
CHANGED
package/dist/tui/view.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/tui/view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"view.d.ts","sourceRoot":"","sources":["../../src/tui/view.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,OAAO,KAAK,EAAe,SAAS,EAAE,MAAM,YAAY,CAAC;AAQzD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAmBD;;;;;;GAMG;AACH,wBAAgB,IAAI,CAClB,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,WAAW,GACnB,SAAS,MAAM,EAAE,CAqCnB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,SAAS,MAAM,EAAE,CActE"}
|
package/dist/tui/view.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { formatTokens } from "../providers/usage.js";
|
|
2
2
|
import { callTarget } from "../tools/target.js";
|
|
3
|
+
import { fitLine } from "./text.js";
|
|
3
4
|
/** Tools listed individually before the rest are summarised as a count. */
|
|
4
5
|
const MAX_LISTED_TOOLS = 3;
|
|
5
6
|
/** Lines of the answer kept visible while it streams. */
|
|
6
7
|
const MAX_TEXT_LINES = 3;
|
|
7
|
-
const MINIMUM_WIDTH = 20;
|
|
8
8
|
function elapsed(from, now) {
|
|
9
9
|
const seconds = Math.max(0, Math.round((now - from) / 1000));
|
|
10
10
|
if (seconds < 60) {
|
|
@@ -12,11 +12,6 @@ function elapsed(from, now) {
|
|
|
12
12
|
}
|
|
13
13
|
return `${Math.floor(seconds / 60)}m${String(seconds % 60).padStart(2, "0")}s`;
|
|
14
14
|
}
|
|
15
|
-
/** Cuts to the width, marking the cut so a truncated line never reads as whole. */
|
|
16
|
-
function fit(line, width) {
|
|
17
|
-
const usable = Math.max(MINIMUM_WIDTH, width);
|
|
18
|
-
return line.length <= usable ? line : `${line.slice(0, usable - 1)}…`;
|
|
19
|
-
}
|
|
20
15
|
function describeTool(tool, now) {
|
|
21
16
|
const head = tool.target === undefined ? tool.name : `${tool.name} ${tool.target}`;
|
|
22
17
|
// The newest line of a tool's output says more than its first, and a running
|
|
@@ -41,15 +36,15 @@ export function view(state, options) {
|
|
|
41
36
|
const tail = run.text.split("\n").slice(-MAX_TEXT_LINES);
|
|
42
37
|
for (const line of tail) {
|
|
43
38
|
if (line.length > 0) {
|
|
44
|
-
lines.push(
|
|
39
|
+
lines.push(fitLine(line, options.width));
|
|
45
40
|
}
|
|
46
41
|
}
|
|
47
42
|
for (const tool of run.running.slice(0, MAX_LISTED_TOOLS)) {
|
|
48
|
-
lines.push(
|
|
43
|
+
lines.push(fitLine(describeTool(tool, options.now), options.width));
|
|
49
44
|
}
|
|
50
45
|
const hidden = run.running.length - MAX_LISTED_TOOLS;
|
|
51
46
|
if (hidden > 0) {
|
|
52
|
-
lines.push(` and ${hidden} more
|
|
47
|
+
lines.push(fitLine(` and ${hidden} more`, options.width));
|
|
53
48
|
}
|
|
54
49
|
const status = [
|
|
55
50
|
run.status === "thinking" ? "thinking" : "running tools",
|
|
@@ -60,8 +55,8 @@ export function view(state, options) {
|
|
|
60
55
|
status.push(`${formatTokens(run.usage.usage.totalTokens)} tokens${run.usage.complete ? "" : "+"}`);
|
|
61
56
|
}
|
|
62
57
|
status.push("ctrl+c to stop");
|
|
63
|
-
lines.push(
|
|
64
|
-
return lines;
|
|
58
|
+
lines.push(fitLine(status.join(" · "), options.width));
|
|
59
|
+
return lines.slice(-Math.max(1, options.height ?? lines.length));
|
|
65
60
|
}
|
|
66
61
|
/**
|
|
67
62
|
* What a finished turn leaves behind in the terminal's own scrollback.
|
package/dist/tui/view.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/tui/view.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"view.js","sourceRoot":"","sources":["../../src/tui/view.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface WelcomeOptions {
|
|
2
|
+
readonly version: string;
|
|
3
|
+
readonly provider: string;
|
|
4
|
+
readonly model: string;
|
|
5
|
+
readonly cwd: string;
|
|
6
|
+
readonly sessionId: string;
|
|
7
|
+
readonly resumed: boolean;
|
|
8
|
+
readonly signedOut: boolean;
|
|
9
|
+
readonly width: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function welcome(options: WelcomeOptions): string;
|
|
12
|
+
//# sourceMappingURL=welcome.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../src/tui/welcome.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAyBvD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { displayWidth, fitLine } from "./text.js";
|
|
2
|
+
export function welcome(options) {
|
|
3
|
+
const width = Math.max(1, Math.min(88, options.width - 1));
|
|
4
|
+
const content = [
|
|
5
|
+
`chivgent ${options.version} · coding assistant`,
|
|
6
|
+
`${options.provider} / ${options.model}`,
|
|
7
|
+
`Workspace ${options.cwd}`,
|
|
8
|
+
`${options.resumed ? "Resumed" : "Session"} ${options.sessionId}`,
|
|
9
|
+
"",
|
|
10
|
+
options.signedOut ? "Run /login to add your API key." : "Ready. Describe what you want to build.",
|
|
11
|
+
"Tab commands · ↑ history · Ctrl+C stop · Ctrl+D exit",
|
|
12
|
+
];
|
|
13
|
+
if (width < 12) {
|
|
14
|
+
return `${content.map((line) => fitLine(line, width)).join("\n")}\n`;
|
|
15
|
+
}
|
|
16
|
+
const inner = width - 4;
|
|
17
|
+
const lines = content.map((line) => {
|
|
18
|
+
const fitted = fitLine(line, inner);
|
|
19
|
+
return `│ ${fitted}${" ".repeat(inner - displayWidth(fitted))} │`;
|
|
20
|
+
});
|
|
21
|
+
return [
|
|
22
|
+
`╭${"─".repeat(width - 2)}╮`,
|
|
23
|
+
...lines,
|
|
24
|
+
`╰${"─".repeat(width - 2)}╯`,
|
|
25
|
+
"",
|
|
26
|
+
].join("\n");
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=welcome.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"welcome.js","sourceRoot":"","sources":["../../src/tui/welcome.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAalD,MAAM,UAAU,OAAO,CAAC,OAAuB;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG;QACd,YAAY,OAAO,CAAC,OAAO,uBAAuB;QAClD,GAAG,OAAO,CAAC,QAAQ,MAAM,OAAO,CAAC,KAAK,EAAE;QACxC,cAAc,OAAO,CAAC,GAAG,EAAE;QAC3B,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,OAAO,OAAO,CAAC,SAAS,EAAE;QACpE,EAAE;QACF,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,yCAAyC;QACjG,sDAAsD;KACvD,CAAC;IACF,IAAI,KAAK,GAAG,EAAE,EAAE,CAAC;QACf,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACvE,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,CAAC;IACxB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACjC,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACpC,OAAO,KAAK,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;IACpE,CAAC,CAAC,CAAC;IACH,OAAO;QACL,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG;QAC5B,GAAG,KAAK;QACR,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG;QAC5B,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "chivgent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "A minimal coding agent CLI built to learn agent harness architecture.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"check": "tsc -p tsconfig.json --noEmit",
|
|
40
40
|
"test": "vitest run",
|
|
41
41
|
"test:watch": "vitest",
|
|
42
|
+
"demo:tui": "npm run build && node scripts/tui-demo.mjs",
|
|
42
43
|
"release:check": "npm run check && npm test && npm run build && npm pack --dry-run",
|
|
43
44
|
"prepublishOnly": "npm run check && npm test",
|
|
44
45
|
"prepack": "npm run build",
|
|
@@ -46,7 +47,8 @@
|
|
|
46
47
|
},
|
|
47
48
|
"dependencies": {
|
|
48
49
|
"ignore": "7.0.6",
|
|
49
|
-
"openai": "7.5.0"
|
|
50
|
+
"openai": "7.5.0",
|
|
51
|
+
"string-width": "7.2.0"
|
|
50
52
|
},
|
|
51
53
|
"devDependencies": {
|
|
52
54
|
"@types/node": "26.2.0",
|