@chances-ai/tui 1.0.0 → 3.0.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/api-key-prompt.d.ts +23 -0
- package/dist/api-key-prompt.d.ts.map +1 -0
- package/dist/api-key-prompt.js +41 -0
- package/dist/api-key-prompt.js.map +1 -0
- package/dist/app.d.ts +18 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +31 -3
- package/dist/app.js.map +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -3
- package/dist/index.js.map +1 -1
- package/dist/modal.d.ts +32 -0
- package/dist/modal.d.ts.map +1 -0
- package/dist/modal.js +63 -0
- package/dist/modal.js.map +1 -0
- package/dist/model-picker.d.ts +53 -0
- package/dist/model-picker.d.ts.map +1 -0
- package/dist/model-picker.js +70 -0
- package/dist/model-picker.js.map +1 -0
- package/dist/session-picker.d.ts +30 -0
- package/dist/session-picker.d.ts.map +1 -0
- package/dist/session-picker.js +45 -0
- package/dist/session-picker.js.map +1 -0
- package/dist/view-model.d.ts +7 -0
- package/dist/view-model.d.ts.map +1 -1
- package/dist/view-model.js +50 -33
- package/dist/view-model.js.map +1 -1
- package/package.json +4 -3
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { PickerKey } from "./model-picker.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pure reducer for the ApiKeyPrompt — Enter on empty input cancels (returns
|
|
4
|
+
* null), Enter on non-empty submits, Esc always cancels, Backspace removes
|
|
5
|
+
* the last character, printable chars append.
|
|
6
|
+
*/
|
|
7
|
+
export declare function reduceApiKeyPrompt(value: string, char: string, key: PickerKey): {
|
|
8
|
+
value: string;
|
|
9
|
+
resolved?: string | null;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Single-line masked input for credentials. Characters are stored verbatim
|
|
13
|
+
* but rendered as `•`. Enter submits, Esc cancels, empty-Enter cancels.
|
|
14
|
+
*
|
|
15
|
+
* No clipboard-paste detection, no key validation against the provider —
|
|
16
|
+
* that's a `/provider add` UX concern and would require a network call we
|
|
17
|
+
* don't want to make from the TUI layer.
|
|
18
|
+
*/
|
|
19
|
+
export declare function ApiKeyPrompt({ provider, onSubmit, }: {
|
|
20
|
+
provider: string;
|
|
21
|
+
onSubmit: (key: string | null) => void;
|
|
22
|
+
}): JSX.Element;
|
|
23
|
+
//# sourceMappingURL=api-key-prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key-prompt.d.ts","sourceRoot":"","sources":["../src/api-key-prompt.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,SAAS,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAM7C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAC3B,QAAQ,EACR,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CACxC,GAAG,GAAG,CAAC,OAAO,CAwBd"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useInput } from "ink";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
/**
|
|
5
|
+
* Pure reducer for the ApiKeyPrompt — Enter on empty input cancels (returns
|
|
6
|
+
* null), Enter on non-empty submits, Esc always cancels, Backspace removes
|
|
7
|
+
* the last character, printable chars append.
|
|
8
|
+
*/
|
|
9
|
+
export function reduceApiKeyPrompt(value, char, key) {
|
|
10
|
+
if (key.escape)
|
|
11
|
+
return { value, resolved: null };
|
|
12
|
+
if (key.return)
|
|
13
|
+
return { value, resolved: value.length > 0 ? value : null };
|
|
14
|
+
if (key.backspace || key.delete)
|
|
15
|
+
return { value: value.slice(0, -1) };
|
|
16
|
+
if (char && !key.ctrl && !key.meta)
|
|
17
|
+
return { value: value + char };
|
|
18
|
+
return { value };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Single-line masked input for credentials. Characters are stored verbatim
|
|
22
|
+
* but rendered as `•`. Enter submits, Esc cancels, empty-Enter cancels.
|
|
23
|
+
*
|
|
24
|
+
* No clipboard-paste detection, no key validation against the provider —
|
|
25
|
+
* that's a `/provider add` UX concern and would require a network call we
|
|
26
|
+
* don't want to make from the TUI layer.
|
|
27
|
+
*/
|
|
28
|
+
export function ApiKeyPrompt({ provider, onSubmit, }) {
|
|
29
|
+
const [value, setValue] = useState("");
|
|
30
|
+
useInput((char, key) => {
|
|
31
|
+
const { value: next, resolved } = reduceApiKeyPrompt(value, char, key);
|
|
32
|
+
if (resolved !== undefined) {
|
|
33
|
+
onSubmit(resolved);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (next !== value)
|
|
37
|
+
setValue(next);
|
|
38
|
+
});
|
|
39
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 1, children: [_jsxs(Text, { color: "yellow", children: ["API key for ", provider, " \u00B7 Enter \u00B7 Esc to cancel"] }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { children: "\u203A " }), _jsx(Text, { color: "green", children: "•".repeat(value.length) })] }), _jsx(Text, { dimColor: true, children: "(input is masked; the key is written to ~/.config/chances/auth.json with 0600 perms)" })] }));
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=api-key-prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key-prompt.js","sourceRoot":"","sources":["../src/api-key-prompt.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGjC;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,KAAa,EACb,IAAY,EACZ,GAAc;IAEd,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IACjD,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5E,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACtE,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI;QAAE,OAAO,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,EAAE,CAAC;IACnE,OAAO,EAAE,KAAK,EAAE,CAAC;AACnB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,QAAQ,EACR,QAAQ,GAIT;IACC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEvC,QAAQ,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACrB,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,EAAE,GAAgB,CAAC,CAAC;QACpF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,OAAO;QACT,CAAC;QACD,IAAI,IAAI,KAAK,KAAK;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,WAAW,EAAC,OAAO,EAAC,WAAW,EAAC,QAAQ,EAAC,QAAQ,EAAE,CAAC,aAC9E,MAAC,IAAI,IAAC,KAAK,EAAC,QAAQ,6BAAc,QAAQ,0CAAgC,EAC1E,MAAC,GAAG,IAAC,SAAS,EAAE,CAAC,aACf,KAAC,IAAI,0BAAU,EACf,KAAC,IAAI,IAAC,KAAK,EAAC,OAAO,YAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAQ,IACjD,EACN,KAAC,IAAI,IAAC,QAAQ,2GAEP,IACH,CACP,CAAC;AACJ,CAAC"}
|
package/dist/app.d.ts
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
import type { ChatViewModel } from "./view-model.js";
|
|
2
|
+
import type { ModalController } from "./modal.js";
|
|
3
|
+
export interface SlashSuggestion {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
}
|
|
2
7
|
export interface ChatAppProps {
|
|
3
8
|
vm: ChatViewModel;
|
|
4
9
|
onSubmit: (prompt: string) => Promise<void>;
|
|
5
10
|
/** Called when the user enters a `/command` (other than `/exit`/`/quit`). */
|
|
6
11
|
onSlash?: (line: string) => Promise<void>;
|
|
12
|
+
/** When provided, ChatApp wires its render slot into the controller so
|
|
13
|
+
* slash commands can `await controller.open(render)` to pop modals
|
|
14
|
+
* (pickers, prompts). When absent, ChatApp behaves as before. */
|
|
15
|
+
modal?: ModalController;
|
|
16
|
+
/** Snapshot of the slash commands the host can dispatch. Used for inline
|
|
17
|
+
* ghost-text autocomplete when the user types `/`. Optional — when absent
|
|
18
|
+
* no autocomplete is shown (chat works exactly as before). The host should
|
|
19
|
+
* pass a fresh array on each render if the registry can change. */
|
|
20
|
+
availableSlashCommands?: SlashSuggestion[];
|
|
7
21
|
}
|
|
8
|
-
|
|
22
|
+
/** Pure helper for picking the suggestions to show for a partial input.
|
|
23
|
+
* Exported separately so tests don't have to drive ChatApp through Ink. */
|
|
24
|
+
export declare function suggestSlashCommands(input: string, available: SlashSuggestion[]): SlashSuggestion[];
|
|
25
|
+
export declare function ChatApp({ vm, onSubmit, onSlash, modal, availableSlashCommands }: ChatAppProps): JSX.Element;
|
|
9
26
|
//# sourceMappingURL=app.d.ts.map
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAQ,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAQ,MAAM,iBAAiB,CAAC;AAC3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AA8BlD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,aAAa,CAAC;IAClB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,6EAA6E;IAC7E,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C;;qEAEiE;IACjE,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB;;;uEAGmE;IACnE,sBAAsB,CAAC,EAAE,eAAe,EAAE,CAAC;CAC5C;AAED;2EAC2E;AAC3E,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,eAAe,EAAE,GAC3B,eAAe,EAAE,CAOnB;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,sBAAsB,EAAE,EAAE,YAAY,GAAG,GAAG,CAAC,OAAO,CA0E3G"}
|
package/dist/app.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text, useApp, useInput } from "ink";
|
|
3
|
-
import { useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { useEffect, useState, useSyncExternalStore } from "react";
|
|
4
4
|
const COLOR = {
|
|
5
5
|
user: "cyan",
|
|
6
6
|
assistant: "white",
|
|
@@ -21,11 +21,33 @@ function LineView({ line }) {
|
|
|
21
21
|
const color = line.kind === "tool-result" && line.ok === false ? "red" : COLOR[line.kind];
|
|
22
22
|
return (_jsxs(Text, { color: color, children: [PREFIX[line.kind], line.text] }));
|
|
23
23
|
}
|
|
24
|
-
|
|
24
|
+
/** Pure helper for picking the suggestions to show for a partial input.
|
|
25
|
+
* Exported separately so tests don't have to drive ChatApp through Ink. */
|
|
26
|
+
export function suggestSlashCommands(input, available) {
|
|
27
|
+
if (!input.startsWith("/"))
|
|
28
|
+
return [];
|
|
29
|
+
const partial = input.slice(1).toLowerCase();
|
|
30
|
+
if (partial === "")
|
|
31
|
+
return available.slice(0, 5);
|
|
32
|
+
return available
|
|
33
|
+
.filter((c) => c.name.toLowerCase().startsWith(partial))
|
|
34
|
+
.slice(0, 5);
|
|
35
|
+
}
|
|
36
|
+
export function ChatApp({ vm, onSubmit, onSlash, modal, availableSlashCommands }) {
|
|
25
37
|
useSyncExternalStore(vm.subscribe, vm.getSnapshot, vm.getSnapshot);
|
|
26
38
|
const [input, setInput] = useState("");
|
|
39
|
+
const [modalNode, setModalNode] = useState(null);
|
|
27
40
|
const { exit } = useApp();
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!modal)
|
|
43
|
+
return;
|
|
44
|
+
return modal.attach((node) => setModalNode(node));
|
|
45
|
+
}, [modal]);
|
|
28
46
|
useInput((char, key) => {
|
|
47
|
+
// When a modal is up, its own useInput owns the keystrokes — chat input
|
|
48
|
+
// must be inert so typing in the picker doesn't double-fire here.
|
|
49
|
+
if (modalNode)
|
|
50
|
+
return;
|
|
29
51
|
if (vm.pending) {
|
|
30
52
|
if (char === "y")
|
|
31
53
|
vm.resolvePermission(true);
|
|
@@ -65,6 +87,12 @@ export function ChatApp({ vm, onSubmit, onSlash }) {
|
|
|
65
87
|
if (char && !key.ctrl && !key.meta)
|
|
66
88
|
setInput((s) => s + char);
|
|
67
89
|
});
|
|
68
|
-
return (_jsxs(Box, { flexDirection: "column", children: [vm.lines.map((line, i) => (_jsx(LineView, { line: line }, i))), vm.pending ? (_jsxs(Box, { marginTop: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1, flexDirection: "column", children: [_jsxs(Text, { color: "yellow", children: ["Approve ", vm.pending.req.name, "?"] }), _jsx(Text, { children: vm.pending.req.summary }), _jsx(Text, { dimColor: true, children: "[y] approve \u00B7 [n] deny" })] })) : (_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: vm.busy ? "…thinking " : "› " }), _jsx(Text, { children: input })] }))] }));
|
|
90
|
+
return (_jsxs(Box, { flexDirection: "column", children: [vm.lines.map((line, i) => (_jsx(LineView, { line: line }, i))), modalNode ? _jsx(Box, { marginTop: 1, children: modalNode }) : null, !modalNode && vm.pending ? (_jsxs(Box, { marginTop: 1, borderStyle: "round", borderColor: "yellow", paddingX: 1, flexDirection: "column", children: [_jsxs(Text, { color: "yellow", children: ["Approve ", vm.pending.req.name, "?"] }), _jsx(Text, { children: vm.pending.req.summary }), _jsx(Text, { dimColor: true, children: "[y] approve \u00B7 [n] deny" })] })) : null, !modalNode && !vm.pending ? (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Box, { marginTop: 1, children: [_jsx(Text, { color: "cyan", children: vm.busy ? "…thinking " : "› " }), _jsx(Text, { children: input })] }), _jsx(SlashAutocomplete, { input: input, available: availableSlashCommands ?? [] })] })) : null] }));
|
|
91
|
+
}
|
|
92
|
+
function SlashAutocomplete({ input, available, }) {
|
|
93
|
+
const matches = suggestSlashCommands(input, available);
|
|
94
|
+
if (matches.length === 0)
|
|
95
|
+
return null;
|
|
96
|
+
return (_jsx(Box, { flexDirection: "column", marginLeft: 2, children: matches.map((m) => (_jsxs(Text, { dimColor: true, children: ["/", m.name, " \u2014 ", m.description] }, m.name))) }));
|
|
69
97
|
}
|
|
70
98
|
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.tsx"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { ChatViewModel } from "./view-model.js";
|
|
2
|
+
import type { ModalController } from "./modal.js";
|
|
2
3
|
export { ChatViewModel } from "./view-model.js";
|
|
3
4
|
export type { Line, LineKind } from "./view-model.js";
|
|
4
|
-
export { ChatApp } from "./app.js";
|
|
5
|
+
export { ChatApp, suggestSlashCommands, type SlashSuggestion } from "./app.js";
|
|
6
|
+
export { ModalController, type OpenModal } from "./modal.js";
|
|
7
|
+
export { ModelPicker, type PickableModel } from "./model-picker.js";
|
|
8
|
+
export { SessionPicker, type PickableSession } from "./session-picker.js";
|
|
9
|
+
export { ApiKeyPrompt } from "./api-key-prompt.js";
|
|
5
10
|
export interface ChatHandle {
|
|
6
11
|
vm: ChatViewModel;
|
|
7
12
|
waitUntilExit: () => Promise<void>;
|
|
@@ -12,6 +17,8 @@ export interface ChatHandle {
|
|
|
12
17
|
* `vm.requestPermission` into the PermissionGate before the engine is built.
|
|
13
18
|
* `onSlash` is invoked for any `/command` other than `/exit`/`/quit` — the
|
|
14
19
|
* caller decides how to dispatch (typically via `PluginHost.dispatchSlash`).
|
|
20
|
+
* `modal` is the controller slash commands use to open pickers; pass the
|
|
21
|
+
* same instance to `dispatchSlash(name, args, { openModal: modal.open })`.
|
|
15
22
|
*/
|
|
16
|
-
export declare function renderChat(vm: ChatViewModel, onSubmit: (prompt: string) => Promise<void>, onSlash?: (line: string) => Promise<void
|
|
23
|
+
export declare function renderChat(vm: ChatViewModel, onSubmit: (prompt: string) => Promise<void>, onSlash?: (line: string) => Promise<void>, modal?: ModalController, availableSlashCommands?: import("./app.js").SlashSuggestion[]): ChatHandle;
|
|
17
24
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAE,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,aAAa,CAAC;IAClB,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,UAAU,CACxB,EAAE,EAAE,aAAa,EACjB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EAC3C,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EACzC,KAAK,CAAC,EAAE,eAAe,EACvB,sBAAsB,CAAC,EAAE,OAAO,UAAU,EAAE,eAAe,EAAE,GAC5D,UAAU,CAeZ"}
|
package/dist/index.js
CHANGED
|
@@ -3,15 +3,21 @@ import { render } from "ink";
|
|
|
3
3
|
import { ChatApp } from "./app.js";
|
|
4
4
|
import { ChatViewModel } from "./view-model.js";
|
|
5
5
|
export { ChatViewModel } from "./view-model.js";
|
|
6
|
-
export { ChatApp } from "./app.js";
|
|
6
|
+
export { ChatApp, suggestSlashCommands } from "./app.js";
|
|
7
|
+
export { ModalController } from "./modal.js";
|
|
8
|
+
export { ModelPicker } from "./model-picker.js";
|
|
9
|
+
export { SessionPicker } from "./session-picker.js";
|
|
10
|
+
export { ApiKeyPrompt } from "./api-key-prompt.js";
|
|
7
11
|
/**
|
|
8
12
|
* Mounts the interactive chat. The caller owns the view-model so it can wire
|
|
9
13
|
* `vm.requestPermission` into the PermissionGate before the engine is built.
|
|
10
14
|
* `onSlash` is invoked for any `/command` other than `/exit`/`/quit` — the
|
|
11
15
|
* caller decides how to dispatch (typically via `PluginHost.dispatchSlash`).
|
|
16
|
+
* `modal` is the controller slash commands use to open pickers; pass the
|
|
17
|
+
* same instance to `dispatchSlash(name, args, { openModal: modal.open })`.
|
|
12
18
|
*/
|
|
13
|
-
export function renderChat(vm, onSubmit, onSlash) {
|
|
14
|
-
const instance = render(_jsx(ChatApp, { vm: vm, onSubmit: onSubmit, onSlash: onSlash }));
|
|
19
|
+
export function renderChat(vm, onSubmit, onSlash, modal, availableSlashCommands) {
|
|
20
|
+
const instance = render(_jsx(ChatApp, { vm: vm, onSubmit: onSubmit, onSlash: onSlash, modal: modal, availableSlashCommands: availableSlashCommands }));
|
|
15
21
|
return {
|
|
16
22
|
vm,
|
|
17
23
|
waitUntilExit: () => instance.waitUntilExit(),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,oBAAoB,EAAwB,MAAM,UAAU,CAAC;AAC/E,OAAO,EAAE,eAAe,EAAkB,MAAM,YAAY,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAsB,MAAM,mBAAmB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAwB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAQnD;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CACxB,EAAiB,EACjB,QAA2C,EAC3C,OAAyC,EACzC,KAAuB,EACvB,sBAA6D;IAE7D,MAAM,QAAQ,GAAG,MAAM,CACrB,KAAC,OAAO,IACN,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,KAAK,EACZ,sBAAsB,EAAE,sBAAsB,GAC9C,CACH,CAAC;IACF,OAAO;QACL,EAAE;QACF,aAAa,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,aAAa,EAAE;QAC7C,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE;KAClC,CAAC;AACJ,CAAC"}
|
package/dist/modal.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { OpenModal } from "@chances-ai/plugin-api";
|
|
3
|
+
/**
|
|
4
|
+
* Bridges async slash-command code (outside React) with React state inside
|
|
5
|
+
* ChatApp. A slash command awaits `controller.open(render)`; the controller
|
|
6
|
+
* triggers a re-render via a setter registered by ChatApp, the rendered
|
|
7
|
+
* modal calls `resolve(value)`, and the promise settles.
|
|
8
|
+
*
|
|
9
|
+
* Single-modal-at-a-time policy: opening a second modal while one is active
|
|
10
|
+
* cancels the first by resolving it to `null` (the "user dismissed" signal).
|
|
11
|
+
* Stacked overlays would require z-ordering that the simple chat input loop
|
|
12
|
+
* can't unwind cleanly — defer to 3.x.later if it ever matters.
|
|
13
|
+
*
|
|
14
|
+
* The shape of `open` deliberately matches `OpenModal` from
|
|
15
|
+
* `@chances-ai/plugin-api`, so this controller can be passed verbatim to
|
|
16
|
+
* `PluginHost.dispatchSlash(name, args, { openModal: controller.open })`.
|
|
17
|
+
*/
|
|
18
|
+
export declare class ModalController {
|
|
19
|
+
private setNode;
|
|
20
|
+
private active;
|
|
21
|
+
/**
|
|
22
|
+
* Called by ChatApp's mount effect with its `setState` setter. Returns a
|
|
23
|
+
* teardown that the effect uses to disconnect on unmount.
|
|
24
|
+
*/
|
|
25
|
+
attach(setter: (node: ReactNode) => void): () => void;
|
|
26
|
+
open: <T>(render: (resolve: (value: T | null) => void) => unknown) => Promise<T | null>;
|
|
27
|
+
/** True when a modal is currently displayed. Used by ChatApp.useInput to
|
|
28
|
+
* suppress chat input handling while the modal owns the keystrokes. */
|
|
29
|
+
isActive(): boolean;
|
|
30
|
+
}
|
|
31
|
+
export type { OpenModal };
|
|
32
|
+
//# sourceMappingURL=modal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../src/modal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;;;;;;;;;;;;GAcG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,OAAO,CAA4C;IAC3D,OAAO,CAAC,MAAM,CAAqD;IAEnE;;;OAGG;IACH,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,GAAG,MAAM,IAAI;IAcrD,IAAI,GAAI,CAAC,EAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,KAAK,IAAI,KAAK,OAAO,KAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAmBrF;IAEF;2EACuE;IACvE,QAAQ,IAAI,OAAO;CAGpB;AAED,YAAY,EAAE,SAAS,EAAE,CAAC"}
|
package/dist/modal.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridges async slash-command code (outside React) with React state inside
|
|
3
|
+
* ChatApp. A slash command awaits `controller.open(render)`; the controller
|
|
4
|
+
* triggers a re-render via a setter registered by ChatApp, the rendered
|
|
5
|
+
* modal calls `resolve(value)`, and the promise settles.
|
|
6
|
+
*
|
|
7
|
+
* Single-modal-at-a-time policy: opening a second modal while one is active
|
|
8
|
+
* cancels the first by resolving it to `null` (the "user dismissed" signal).
|
|
9
|
+
* Stacked overlays would require z-ordering that the simple chat input loop
|
|
10
|
+
* can't unwind cleanly — defer to 3.x.later if it ever matters.
|
|
11
|
+
*
|
|
12
|
+
* The shape of `open` deliberately matches `OpenModal` from
|
|
13
|
+
* `@chances-ai/plugin-api`, so this controller can be passed verbatim to
|
|
14
|
+
* `PluginHost.dispatchSlash(name, args, { openModal: controller.open })`.
|
|
15
|
+
*/
|
|
16
|
+
export class ModalController {
|
|
17
|
+
setNode = null;
|
|
18
|
+
active = null;
|
|
19
|
+
/**
|
|
20
|
+
* Called by ChatApp's mount effect with its `setState` setter. Returns a
|
|
21
|
+
* teardown that the effect uses to disconnect on unmount.
|
|
22
|
+
*/
|
|
23
|
+
attach(setter) {
|
|
24
|
+
this.setNode = setter;
|
|
25
|
+
return () => {
|
|
26
|
+
if (this.setNode === setter)
|
|
27
|
+
this.setNode = null;
|
|
28
|
+
// If the host unmounts mid-modal (e.g. ChatApp tears down for a
|
|
29
|
+
// /resume respawn), cancel the open promise so awaiters resolve to
|
|
30
|
+
// `null` instead of leaking.
|
|
31
|
+
if (this.active) {
|
|
32
|
+
this.active.resolveActive(null);
|
|
33
|
+
this.active = null;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
open = (render) => {
|
|
38
|
+
return new Promise((promiseResolve) => {
|
|
39
|
+
// Cancel any prior modal first so the screen never shows two overlays.
|
|
40
|
+
if (this.active)
|
|
41
|
+
this.active.resolveActive(null);
|
|
42
|
+
const resolveWith = (value) => {
|
|
43
|
+
// Only clear `active` if THIS modal is still the current one — a
|
|
44
|
+
// race where two opens overlap should not clobber the second's
|
|
45
|
+
// entry just because the first's resolve fires.
|
|
46
|
+
if (this.active?.resolveActive === resolveWith) {
|
|
47
|
+
this.active = null;
|
|
48
|
+
}
|
|
49
|
+
this.setNode?.(null);
|
|
50
|
+
promiseResolve(value);
|
|
51
|
+
};
|
|
52
|
+
this.active = { resolveActive: resolveWith };
|
|
53
|
+
const node = render(resolveWith);
|
|
54
|
+
this.setNode?.(node);
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
/** True when a modal is currently displayed. Used by ChatApp.useInput to
|
|
58
|
+
* suppress chat input handling while the modal owns the keystrokes. */
|
|
59
|
+
isActive() {
|
|
60
|
+
return this.active !== null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=modal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modal.js","sourceRoot":"","sources":["../src/modal.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,eAAe;IAClB,OAAO,GAAuC,IAAI,CAAC;IACnD,MAAM,GAAgD,IAAI,CAAC;IAEnE;;;OAGG;IACH,MAAM,CAAC,MAAiC;QACtC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,OAAO,GAAG,EAAE;YACV,IAAI,IAAI,CAAC,OAAO,KAAK,MAAM;gBAAE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACjD,gEAAgE;YAChE,mEAAmE;YACnE,6BAA6B;YAC7B,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;gBAChB,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;gBAChC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACrB,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,CAAK,MAAuD,EAAqB,EAAE;QACxF,OAAO,IAAI,OAAO,CAAW,CAAC,cAAc,EAAE,EAAE;YAC9C,uEAAuE;YACvE,IAAI,IAAI,CAAC,MAAM;gBAAE,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAEjD,MAAM,WAAW,GAAG,CAAC,KAAe,EAAQ,EAAE;gBAC5C,iEAAiE;gBACjE,+DAA+D;gBAC/D,gDAAgD;gBAChD,IAAI,IAAI,CAAC,MAAM,EAAE,aAAa,KAAM,WAAiC,EAAE,CAAC;oBACtE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;gBACrB,CAAC;gBACD,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;gBACrB,cAAc,CAAC,KAAK,CAAC,CAAC;YACxB,CAAC,CAAC;YACF,IAAI,CAAC,MAAM,GAAG,EAAE,aAAa,EAAE,WAAgC,EAAE,CAAC;YAClE,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAc,CAAC;YAC9C,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF;2EACuE;IACvE,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC;IAC9B,CAAC;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export interface PickableModel {
|
|
2
|
+
/** Display id, e.g. "claude-opus-4-7". */
|
|
3
|
+
id: string;
|
|
4
|
+
/** Provider id, e.g. "anthropic". Shown as a dim prefix. */
|
|
5
|
+
provider: string;
|
|
6
|
+
/** True for the currently-active model, rendered with a marker. */
|
|
7
|
+
current?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export interface ModelPickerState {
|
|
10
|
+
filter: string;
|
|
11
|
+
cursor: number;
|
|
12
|
+
}
|
|
13
|
+
/** Subset of Ink's Key shape that the reducer cares about. Defined locally so
|
|
14
|
+
* the reducer has no dependency on Ink at all — unit tests can drive it as
|
|
15
|
+
* plain data without needing a TTY. */
|
|
16
|
+
export interface PickerKey {
|
|
17
|
+
return?: boolean;
|
|
18
|
+
escape?: boolean;
|
|
19
|
+
upArrow?: boolean;
|
|
20
|
+
downArrow?: boolean;
|
|
21
|
+
backspace?: boolean;
|
|
22
|
+
delete?: boolean;
|
|
23
|
+
ctrl?: boolean;
|
|
24
|
+
meta?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** Subset of the active match list the reducer needs — kept as a generic
|
|
27
|
+
* function over PickableModel for ergonomics. */
|
|
28
|
+
export declare function filterModels(models: PickableModel[], filter: string): PickableModel[];
|
|
29
|
+
/**
|
|
30
|
+
* Pure reducer for the ModelPicker. Returns the next state plus an optional
|
|
31
|
+
* `resolved` value: a `PickableModel` when the user picked, `null` when they
|
|
32
|
+
* cancelled (Esc or Enter on empty matches), `undefined` when the keystroke
|
|
33
|
+
* was a navigation/filter edit and the picker should stay open.
|
|
34
|
+
*
|
|
35
|
+
* The component just plumbs Ink's useInput into this function — extracted so
|
|
36
|
+
* the keystroke logic is testable without ink-testing-library's stdin
|
|
37
|
+
* limitations.
|
|
38
|
+
*/
|
|
39
|
+
export declare function reduceModelPicker(state: ModelPickerState, char: string, key: PickerKey, models: PickableModel[]): {
|
|
40
|
+
state: ModelPickerState;
|
|
41
|
+
resolved?: PickableModel | null;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Fuzzy-filter model picker modeled on oh-my-pi's `model-selector.ts`. Arrow
|
|
45
|
+
* keys move the cursor, Enter selects, Esc cancels (resolves null). All
|
|
46
|
+
* keystroke logic lives in {@link reduceModelPicker} so it's testable as a
|
|
47
|
+
* pure function — this component is just glue to Ink's useInput.
|
|
48
|
+
*/
|
|
49
|
+
export declare function ModelPicker({ models, onChoose, }: {
|
|
50
|
+
models: PickableModel[];
|
|
51
|
+
onChoose: (model: PickableModel | null) => void;
|
|
52
|
+
}): JSX.Element;
|
|
53
|
+
//# sourceMappingURL=model-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-picker.d.ts","sourceRoot":"","sources":["../src/model-picker.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,0CAA0C;IAC1C,EAAE,EAAE,MAAM,CAAC;IACX,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;uCAEuC;AACvC,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;iDACiD;AACjD,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,EAAE,CAIrF;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,gBAAgB,EACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,aAAa,EAAE,GACtB;IAAE,KAAK,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;CAAE,CAsB9D;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,QAAQ,GACT,EAAE;IACD,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,KAAK,IAAI,CAAC;CACjD,GAAG,GAAG,CAAC,OAAO,CA4Cd"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useInput } from "ink";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
/** Subset of the active match list the reducer needs — kept as a generic
|
|
5
|
+
* function over PickableModel for ergonomics. */
|
|
6
|
+
export function filterModels(models, filter) {
|
|
7
|
+
const lower = filter.toLowerCase();
|
|
8
|
+
if (!lower)
|
|
9
|
+
return models;
|
|
10
|
+
return models.filter((m) => `${m.provider}/${m.id}`.toLowerCase().includes(lower));
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Pure reducer for the ModelPicker. Returns the next state plus an optional
|
|
14
|
+
* `resolved` value: a `PickableModel` when the user picked, `null` when they
|
|
15
|
+
* cancelled (Esc or Enter on empty matches), `undefined` when the keystroke
|
|
16
|
+
* was a navigation/filter edit and the picker should stay open.
|
|
17
|
+
*
|
|
18
|
+
* The component just plumbs Ink's useInput into this function — extracted so
|
|
19
|
+
* the keystroke logic is testable without ink-testing-library's stdin
|
|
20
|
+
* limitations.
|
|
21
|
+
*/
|
|
22
|
+
export function reduceModelPicker(state, char, key, models) {
|
|
23
|
+
const matches = filterModels(models, state.filter);
|
|
24
|
+
const safeCursor = Math.min(state.cursor, Math.max(0, matches.length - 1));
|
|
25
|
+
if (key.escape)
|
|
26
|
+
return { state, resolved: null };
|
|
27
|
+
if (key.return) {
|
|
28
|
+
const choice = matches[safeCursor];
|
|
29
|
+
return { state, resolved: choice ?? null };
|
|
30
|
+
}
|
|
31
|
+
if (key.upArrow) {
|
|
32
|
+
return { state: { ...state, cursor: Math.max(0, safeCursor - 1) } };
|
|
33
|
+
}
|
|
34
|
+
if (key.downArrow) {
|
|
35
|
+
return { state: { ...state, cursor: Math.min(matches.length - 1, safeCursor + 1) } };
|
|
36
|
+
}
|
|
37
|
+
if (key.backspace || key.delete) {
|
|
38
|
+
return { state: { filter: state.filter.slice(0, -1), cursor: 0 } };
|
|
39
|
+
}
|
|
40
|
+
if (char && !key.ctrl && !key.meta) {
|
|
41
|
+
return { state: { filter: state.filter + char, cursor: 0 } };
|
|
42
|
+
}
|
|
43
|
+
return { state };
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fuzzy-filter model picker modeled on oh-my-pi's `model-selector.ts`. Arrow
|
|
47
|
+
* keys move the cursor, Enter selects, Esc cancels (resolves null). All
|
|
48
|
+
* keystroke logic lives in {@link reduceModelPicker} so it's testable as a
|
|
49
|
+
* pure function — this component is just glue to Ink's useInput.
|
|
50
|
+
*/
|
|
51
|
+
export function ModelPicker({ models, onChoose, }) {
|
|
52
|
+
const [state, setState] = useState({ filter: "", cursor: 0 });
|
|
53
|
+
useInput((char, key) => {
|
|
54
|
+
const { state: next, resolved } = reduceModelPicker(state, char, key, models);
|
|
55
|
+
if (resolved !== undefined) {
|
|
56
|
+
onChoose(resolved);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (next !== state)
|
|
60
|
+
setState(next);
|
|
61
|
+
});
|
|
62
|
+
const matches = filterModels(models, state.filter);
|
|
63
|
+
const safeCursor = Math.min(state.cursor, Math.max(0, matches.length - 1));
|
|
64
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [_jsx(Text, { color: "cyan", children: "Pick a model \u00B7 type to filter \u00B7 \u2191\u2193 \u00B7 Enter \u00B7 Esc" }), _jsxs(Box, { marginTop: 1, children: [_jsx(Text, { children: "filter: " }), _jsx(Text, { color: "yellow", children: state.filter || "(any)" })] }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [matches.length === 0 ? (_jsx(Text, { dimColor: true, children: "no models match" })) : (matches.slice(0, 10).map((m, i) => {
|
|
65
|
+
const selected = i === safeCursor;
|
|
66
|
+
const marker = m.current ? "●" : " ";
|
|
67
|
+
return (_jsxs(Text, { color: selected ? "cyan" : undefined, children: [selected ? "▸ " : " ", marker, " ", _jsxs(Text, { dimColor: true, children: [m.provider, "/"] }), m.id] }, `${m.provider}/${m.id}`));
|
|
68
|
+
})), matches.length > 10 ? (_jsxs(Text, { dimColor: true, children: ["\u2026 ", matches.length - 10, " more (type to narrow)"] })) : null] })] }));
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=model-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-picker.js","sourceRoot":"","sources":["../src/model-picker.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { PickerKey } from "./model-picker.js";
|
|
2
|
+
export interface PickableSession {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
/** ISO timestamp; displayed truncated to date for compactness. */
|
|
6
|
+
updatedAt: string;
|
|
7
|
+
/** Optional preview snippet from the first user turn — helps the user
|
|
8
|
+
* recognize a session when titles are all "session" / "test". */
|
|
9
|
+
preview?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Pure reducer for the SessionPicker. Same convention as the model picker —
|
|
13
|
+
* returns `resolved: PickableSession | null` when the user picked or
|
|
14
|
+
* cancelled; `undefined` when the keystroke was navigation.
|
|
15
|
+
*/
|
|
16
|
+
export declare function reduceSessionPicker(cursor: number, key: PickerKey, sessions: PickableSession[]): {
|
|
17
|
+
cursor: number;
|
|
18
|
+
resolved?: PickableSession | null;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Vertical list of recent sessions with arrow-key cursor + Enter to resume.
|
|
22
|
+
* Modeled on oh-my-pi's `session-selector.ts`; simplified — no fuzzy filter
|
|
23
|
+
* yet (defer until lists exceed ~20 entries in practice). All keystroke
|
|
24
|
+
* logic in {@link reduceSessionPicker} for testability.
|
|
25
|
+
*/
|
|
26
|
+
export declare function SessionPicker({ sessions, onChoose, }: {
|
|
27
|
+
sessions: PickableSession[];
|
|
28
|
+
onChoose: (session: PickableSession | null) => void;
|
|
29
|
+
}): JSX.Element;
|
|
30
|
+
//# sourceMappingURL=session-picker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-picker.d.ts","sourceRoot":"","sources":["../src/session-picker.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,kEAAkE;IAClE,SAAS,EAAE,MAAM,CAAC;IAClB;qEACiE;IACjE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,SAAS,EACd,QAAQ,EAAE,eAAe,EAAE,GAC1B;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,eAAe,GAAG,IAAI,CAAA;CAAE,CAOvD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,QAAQ,EAAE,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;CACrD,GAAG,GAAG,CAAC,OAAO,CAuCd"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text, useInput } from "ink";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
/**
|
|
5
|
+
* Pure reducer for the SessionPicker. Same convention as the model picker —
|
|
6
|
+
* returns `resolved: PickableSession | null` when the user picked or
|
|
7
|
+
* cancelled; `undefined` when the keystroke was navigation.
|
|
8
|
+
*/
|
|
9
|
+
export function reduceSessionPicker(cursor, key, sessions) {
|
|
10
|
+
const safe = Math.min(cursor, Math.max(0, sessions.length - 1));
|
|
11
|
+
if (key.escape)
|
|
12
|
+
return { cursor: safe, resolved: null };
|
|
13
|
+
if (key.return)
|
|
14
|
+
return { cursor: safe, resolved: sessions[safe] ?? null };
|
|
15
|
+
if (key.upArrow)
|
|
16
|
+
return { cursor: Math.max(0, safe - 1) };
|
|
17
|
+
if (key.downArrow)
|
|
18
|
+
return { cursor: Math.min(sessions.length - 1, safe + 1) };
|
|
19
|
+
return { cursor: safe };
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Vertical list of recent sessions with arrow-key cursor + Enter to resume.
|
|
23
|
+
* Modeled on oh-my-pi's `session-selector.ts`; simplified — no fuzzy filter
|
|
24
|
+
* yet (defer until lists exceed ~20 entries in practice). All keystroke
|
|
25
|
+
* logic in {@link reduceSessionPicker} for testability.
|
|
26
|
+
*/
|
|
27
|
+
export function SessionPicker({ sessions, onChoose, }) {
|
|
28
|
+
const [cursor, setCursor] = useState(0);
|
|
29
|
+
const safeCursor = Math.min(cursor, Math.max(0, sessions.length - 1));
|
|
30
|
+
useInput((_char, key) => {
|
|
31
|
+
const { cursor: next, resolved } = reduceSessionPicker(cursor, key, sessions);
|
|
32
|
+
if (resolved !== undefined) {
|
|
33
|
+
onChoose(resolved);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (next !== cursor)
|
|
37
|
+
setCursor(next);
|
|
38
|
+
});
|
|
39
|
+
return (_jsxs(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: [_jsx(Text, { color: "cyan", children: "Resume a session \u00B7 \u2191\u2193 \u00B7 Enter \u00B7 Esc" }), _jsx(Box, { flexDirection: "column", marginTop: 1, children: sessions.length === 0 ? (_jsx(Text, { dimColor: true, children: "no saved sessions in this workspace" })) : (sessions.slice(0, 10).map((s, i) => {
|
|
40
|
+
const selected = i === safeCursor;
|
|
41
|
+
const date = s.updatedAt.slice(0, 10);
|
|
42
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsxs(Text, { color: selected ? "cyan" : undefined, children: [selected ? "▸ " : " ", _jsx(Text, { dimColor: true, children: date }), " ", s.title] }), s.preview ? (_jsxs(Text, { dimColor: true, children: [" ", s.preview.slice(0, 60)] })) : null] }, s.id));
|
|
43
|
+
})) })] }));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=session-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-picker.js","sourceRoot":"","sources":["../src/session-picker.tsx"],"names":[],"mappings":"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"}
|
package/dist/view-model.d.ts
CHANGED
|
@@ -22,13 +22,20 @@ export declare class ChatViewModel {
|
|
|
22
22
|
private version;
|
|
23
23
|
private readonly listeners;
|
|
24
24
|
private assistantOpen;
|
|
25
|
+
private busUnsubscribers;
|
|
25
26
|
subscribe: (fn: () => void) => (() => void);
|
|
26
27
|
getSnapshot: () => number;
|
|
27
28
|
private bump;
|
|
28
29
|
pushUser(text: string): void;
|
|
29
30
|
pushInfo(text: string): void;
|
|
30
31
|
pushError(text: string): void;
|
|
32
|
+
/** Empties the rendered scrollback — used by `/clear` so the user sees a
|
|
33
|
+
* fresh view alongside the session.clearTurns() that drops the conversation
|
|
34
|
+
* history. The view-model and the underlying session are intentionally
|
|
35
|
+
* separate operations; the slash command sequences both. */
|
|
36
|
+
clearLines(): void;
|
|
31
37
|
attach(bus: EventBus): void;
|
|
38
|
+
detach(): void;
|
|
32
39
|
/** Returned to the PermissionGate as its resolver. */
|
|
33
40
|
requestPermission: (req: PermissionRequest) => Promise<boolean>;
|
|
34
41
|
resolvePermission(approve: boolean): void;
|
package/dist/view-model.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-model.d.ts","sourceRoot":"","sources":["../src/view-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AACxF,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,UAAU,OAAO;IACf,GAAG,EAAE,iBAAiB,CAAC;IACvB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC;AAED;;;;GAIG;AACH,qBAAa,aAAa;IACxB,KAAK,EAAE,IAAI,EAAE,CAAM;IACnB,IAAI,UAAS;IACb,OAAO,EAAE,OAAO,GAAG,IAAI,CAAQ;IAE/B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IACnD,OAAO,CAAC,aAAa,CAAS;
|
|
1
|
+
{"version":3,"file":"view-model.d.ts","sourceRoot":"","sources":["../src/view-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AACxF,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;CACd;AAED,UAAU,OAAO;IACf,GAAG,EAAE,iBAAiB,CAAC;IACvB,OAAO,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACrC;AAED;;;;GAIG;AACH,qBAAa,aAAa;IACxB,KAAK,EAAE,IAAI,EAAE,CAAM;IACnB,IAAI,UAAS;IACb,OAAO,EAAE,OAAO,GAAG,IAAI,CAAQ;IAE/B,OAAO,CAAC,OAAO,CAAK;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAyB;IACnD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,gBAAgB,CAAyB;IAEjD,SAAS,GAAI,IAAI,MAAM,IAAI,KAAG,CAAC,MAAM,IAAI,CAAC,CAGxC;IAEF,WAAW,QAAO,MAAM,CAAiB;IAEzC,OAAO,CAAC,IAAI;IAKZ,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM5B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM5B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM7B;;;gEAG4D;IAC5D,UAAU,IAAI,IAAI;IAMlB,MAAM,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;IAuC3B,MAAM,IAAI,IAAI;IAId,sDAAsD;IACtD,iBAAiB,GAAI,KAAK,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,CAIzD;IAEL,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAS1C"}
|
package/dist/view-model.js
CHANGED
|
@@ -10,6 +10,7 @@ export class ChatViewModel {
|
|
|
10
10
|
version = 0;
|
|
11
11
|
listeners = new Set();
|
|
12
12
|
assistantOpen = false;
|
|
13
|
+
busUnsubscribers = [];
|
|
13
14
|
subscribe = (fn) => {
|
|
14
15
|
this.listeners.add(fn);
|
|
15
16
|
return () => this.listeners.delete(fn);
|
|
@@ -35,40 +36,56 @@ export class ChatViewModel {
|
|
|
35
36
|
this.assistantOpen = false;
|
|
36
37
|
this.bump();
|
|
37
38
|
}
|
|
39
|
+
/** Empties the rendered scrollback — used by `/clear` so the user sees a
|
|
40
|
+
* fresh view alongside the session.clearTurns() that drops the conversation
|
|
41
|
+
* history. The view-model and the underlying session are intentionally
|
|
42
|
+
* separate operations; the slash command sequences both. */
|
|
43
|
+
clearLines() {
|
|
44
|
+
this.lines = [];
|
|
45
|
+
this.assistantOpen = false;
|
|
46
|
+
this.bump();
|
|
47
|
+
}
|
|
38
48
|
attach(bus) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.assistantOpen
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
49
|
+
this.detach();
|
|
50
|
+
this.busUnsubscribers = [
|
|
51
|
+
bus.on("turn:start", () => {
|
|
52
|
+
this.busy = true;
|
|
53
|
+
this.bump();
|
|
54
|
+
}),
|
|
55
|
+
bus.on("turn:end", () => {
|
|
56
|
+
this.busy = false;
|
|
57
|
+
this.bump();
|
|
58
|
+
}),
|
|
59
|
+
bus.on("assistant:delta", (e) => {
|
|
60
|
+
if (!this.assistantOpen) {
|
|
61
|
+
this.lines.push({ kind: "assistant", text: "" });
|
|
62
|
+
this.assistantOpen = true;
|
|
63
|
+
}
|
|
64
|
+
this.lines[this.lines.length - 1].text += e.text;
|
|
65
|
+
this.bump();
|
|
66
|
+
}),
|
|
67
|
+
bus.on("assistant:message", () => {
|
|
68
|
+
this.assistantOpen = false;
|
|
69
|
+
this.bump();
|
|
70
|
+
}),
|
|
71
|
+
bus.on("tool:call", (e) => {
|
|
72
|
+
this.lines.push({ kind: "tool", text: `${e.name} ${JSON.stringify(e.args)}` });
|
|
73
|
+
this.assistantOpen = false;
|
|
74
|
+
this.bump();
|
|
75
|
+
}),
|
|
76
|
+
bus.on("tool:result", (e) => {
|
|
77
|
+
this.lines.push({ kind: "tool-result", ok: e.ok, text: clip(e.output) });
|
|
78
|
+
this.bump();
|
|
79
|
+
}),
|
|
80
|
+
bus.on("error", (e) => {
|
|
81
|
+
this.lines.push({ kind: "error", text: `${e.code}: ${e.message}` });
|
|
82
|
+
this.bump();
|
|
83
|
+
}),
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
detach() {
|
|
87
|
+
for (const unsubscribe of this.busUnsubscribers.splice(0))
|
|
88
|
+
unsubscribe();
|
|
72
89
|
}
|
|
73
90
|
/** Returned to the PermissionGate as its resolver. */
|
|
74
91
|
requestPermission = (req) => new Promise((resolve) => {
|
package/dist/view-model.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"view-model.js","sourceRoot":"","sources":["../src/view-model.ts"],"names":[],"mappings":"AAeA;;;;GAIG;AACH,MAAM,OAAO,aAAa;IACxB,KAAK,GAAW,EAAE,CAAC;IACnB,IAAI,GAAG,KAAK,CAAC;IACb,OAAO,GAAmB,IAAI,CAAC;IAEvB,OAAO,GAAG,CAAC,CAAC;IACH,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IAC3C,aAAa,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"view-model.js","sourceRoot":"","sources":["../src/view-model.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chances-ai/tui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -12,8 +12,9 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": ["dist"],
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@chances-ai/
|
|
16
|
-
"@chances-ai/
|
|
15
|
+
"@chances-ai/plugin-api": "3.0.0",
|
|
16
|
+
"@chances-ai/runtime": "3.0.0",
|
|
17
|
+
"@chances-ai/tools": "3.0.0"
|
|
17
18
|
},
|
|
18
19
|
"peerDependencies": {
|
|
19
20
|
"ink": "^5.0.1",
|