@chances-ai/tui 2.0.0 → 3.0.1

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.
@@ -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
- export declare function ChatApp({ vm, onSubmit, onSlash }: ChatAppProps): JSX.Element;
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;AA8B3D,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;CAC3C;AAED,wBAAgB,OAAO,CAAC,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,YAAY,GAAG,GAAG,CAAC,OAAO,CA4D5E"}
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
- export function ChatApp({ vm, onSubmit, onSlash }) {
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":"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"}
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>): ChatHandle;
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,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;;;;;GAKG;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,GACxC,UAAU,CAOZ"}
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;AAEhD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAQnC;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CACxB,EAAiB,EACjB,QAA2C,EAC3C,OAAyC;IAEzC,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAC,OAAO,IAAC,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAI,CAAC,CAAC;IACnF,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"}
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"}
@@ -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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"}
@@ -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;
@@ -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;IAE9B,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,MAAM,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;IAoC3B,sDAAsD;IACtD,iBAAiB,GAAI,KAAK,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,CAIzD;IAEL,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;CAS1C"}
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"}
@@ -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
- bus.on("turn:start", () => {
40
- this.busy = true;
41
- this.bump();
42
- });
43
- bus.on("turn:end", () => {
44
- this.busy = false;
45
- this.bump();
46
- });
47
- bus.on("assistant:delta", (e) => {
48
- if (!this.assistantOpen) {
49
- this.lines.push({ kind: "assistant", text: "" });
50
- this.assistantOpen = true;
51
- }
52
- this.lines[this.lines.length - 1].text += e.text;
53
- this.bump();
54
- });
55
- bus.on("assistant:message", () => {
56
- this.assistantOpen = false;
57
- this.bump();
58
- });
59
- bus.on("tool:call", (e) => {
60
- this.lines.push({ kind: "tool", text: `${e.name} ${JSON.stringify(e.args)}` });
61
- this.assistantOpen = false;
62
- this.bump();
63
- });
64
- bus.on("tool:result", (e) => {
65
- this.lines.push({ kind: "tool-result", ok: e.ok, text: clip(e.output) });
66
- this.bump();
67
- });
68
- bus.on("error", (e) => {
69
- this.lines.push({ kind: "error", text: `${e.code}: ${e.message}` });
70
- this.bump();
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) => {
@@ -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;IAE9B,SAAS,GAAG,CAAC,EAAc,EAAgB,EAAE;QAC3C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC,CAAC;IAEF,WAAW,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;IAEjC,IAAI;QACV,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,SAAS;YAAE,CAAC,EAAE,CAAC;IACtC,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,QAAQ,CAAC,IAAY;QACnB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,SAAS,CAAC,IAAY;QACpB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAED,MAAM,CAAC,GAAa;QAClB,GAAG,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YACxB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YACjB,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YACtB,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC;YAClB,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE;YAC9B,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACxB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;gBACjD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC;YAClD,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;YAC/B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE;YACxB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/E,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;YAC3B,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE;YAC1B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACzE,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;QACH,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;YACpB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACpE,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACL,CAAC;IAED,sDAAsD;IACtD,iBAAiB,GAAG,CAAC,GAAsB,EAAoB,EAAE,CAC/D,IAAI,OAAO,CAAU,CAAC,OAAO,EAAE,EAAE;QAC/B,IAAI,CAAC,OAAO,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;QAChC,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC,CAAC,CAAC;IAEL,iBAAiB,CAAC,OAAgB;QAChC,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,EAAE,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAChG,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;CACF;AAED,SAAS,IAAI,CAAC,CAAS,EAAE,CAAC,GAAG,GAAG;IAC9B,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,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,27 +1,30 @@
1
1
  {
2
2
  "name": "@chances-ai/tui",
3
- "version": "2.0.0",
3
+ "version": "3.0.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
7
7
  "exports": {
8
8
  ".": {
9
- "types": "./dist/index.d.ts",
10
- "import": "./dist/index.js"
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "dependencies": {
17
+ "@chances-ai/plugin-api": "3.0.1",
18
+ "@chances-ai/runtime": "3.0.1",
19
+ "@chances-ai/tools": "3.0.1"
20
+ },
21
+ "peerDependencies": {
22
+ "ink": "^5.0.1",
23
+ "react": "^18.3.1"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc -b",
27
+ "check": "tsc -b",
28
+ "test": "bun test"
11
29
  }
12
- },
13
- "files": ["dist"],
14
- "dependencies": {
15
- "@chances-ai/runtime": "2.0.0",
16
- "@chances-ai/tools": "2.0.0"
17
- },
18
- "peerDependencies": {
19
- "ink": "^5.0.1",
20
- "react": "^18.3.1"
21
- },
22
- "scripts": {
23
- "build": "tsc -b",
24
- "check": "tsc -b",
25
- "test": "bun test"
26
- }
27
30
  }