@chances-ai/tui 24.2.0 → 24.3.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.
Files changed (52) hide show
  1. package/dist/app.d.ts +22 -1
  2. package/dist/app.d.ts.map +1 -1
  3. package/dist/app.js +107 -42
  4. package/dist/app.js.map +1 -1
  5. package/dist/editor/file-search.d.ts +18 -0
  6. package/dist/editor/file-search.d.ts.map +1 -0
  7. package/dist/editor/file-search.js +78 -0
  8. package/dist/editor/file-search.js.map +1 -0
  9. package/dist/editor/prompt-editor.d.ts +35 -0
  10. package/dist/editor/prompt-editor.d.ts.map +1 -0
  11. package/dist/editor/prompt-editor.js +153 -0
  12. package/dist/editor/prompt-editor.js.map +1 -0
  13. package/dist/editor/unified-autocomplete.d.ts +42 -0
  14. package/dist/editor/unified-autocomplete.d.ts.map +1 -0
  15. package/dist/editor/unified-autocomplete.js +141 -0
  16. package/dist/editor/unified-autocomplete.js.map +1 -0
  17. package/dist/index.d.ts +14 -1
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +3 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/ink-ext/keys.d.ts +4 -2
  22. package/dist/ink-ext/keys.d.ts.map +1 -1
  23. package/dist/ink-ext/keys.js +47 -5
  24. package/dist/ink-ext/keys.js.map +1 -1
  25. package/dist/ink-ext/types.d.ts +1 -1
  26. package/dist/ink-ext/types.d.ts.map +1 -1
  27. package/dist/ink-ext/types.js.map +1 -1
  28. package/dist/keybindings/defaults.d.ts +24 -0
  29. package/dist/keybindings/defaults.d.ts.map +1 -0
  30. package/dist/keybindings/defaults.js +21 -0
  31. package/dist/keybindings/defaults.js.map +1 -0
  32. package/dist/keybindings/index.d.ts +9 -0
  33. package/dist/keybindings/index.d.ts.map +1 -0
  34. package/dist/keybindings/index.js +9 -0
  35. package/dist/keybindings/index.js.map +1 -0
  36. package/dist/keybindings/merge.d.ts +25 -0
  37. package/dist/keybindings/merge.d.ts.map +1 -0
  38. package/dist/keybindings/merge.js +98 -0
  39. package/dist/keybindings/merge.js.map +1 -0
  40. package/dist/keybindings/schema.d.ts +17 -0
  41. package/dist/keybindings/schema.d.ts.map +1 -0
  42. package/dist/keybindings/schema.js +16 -0
  43. package/dist/keybindings/schema.js.map +1 -0
  44. package/dist/pager.d.ts +19 -0
  45. package/dist/pager.d.ts.map +1 -0
  46. package/dist/pager.js +83 -0
  47. package/dist/pager.js.map +1 -0
  48. package/dist/slash-typeahead.d.ts +8 -24
  49. package/dist/slash-typeahead.d.ts.map +1 -1
  50. package/dist/slash-typeahead.js +8 -67
  51. package/dist/slash-typeahead.js.map +1 -1
  52. package/package.json +7 -5
@@ -0,0 +1,24 @@
1
+ /**
2
+ * (7.4 / task 04) Platform / VT-mode default keybindings, layered FIRST (before
3
+ * the user's keybindings.json) — docs/7.4 §4.4, borrowing claude-code's
4
+ * platform-default *concept*.
5
+ */
6
+ import type { ContextName } from "../ink-ext/index.js";
7
+ export interface PlatformEnv {
8
+ /** `process.platform` (e.g. "win32", "darwin"). */
9
+ platform?: string;
10
+ /** Whether the terminal supports VT mode (so `shift+tab` arrives). */
11
+ vtMode?: boolean;
12
+ }
13
+ /**
14
+ * Per-context default overrides for the current platform. Today: the approval-
15
+ * mode cycle. `shift+tab` is the primary (bound in `DEFAULT_BINDINGS`), and
16
+ * `meta+m` is the cross-platform fallback claude-code uses where `shift+tab`
17
+ * can't be distinguished (Windows without VT mode) — bound here as a real
18
+ * action so it no longer needs the `app.tsx` text-sink special-case (R1-M2).
19
+ *
20
+ * (Image-paste key differences — `ctrl+v` non-Windows / `meta+v` Windows — are
21
+ * deferred to task 05/09 when image paste lands.)
22
+ */
23
+ export declare function platformDefaults(_env?: PlatformEnv): Partial<Record<ContextName, Record<string, string>>>;
24
+ //# sourceMappingURL=defaults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/keybindings/defaults.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,MAAM,WAAW,WAAW;IAC1B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAI7G"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * (7.4 / task 04) Platform / VT-mode default keybindings, layered FIRST (before
3
+ * the user's keybindings.json) — docs/7.4 §4.4, borrowing claude-code's
4
+ * platform-default *concept*.
5
+ */
6
+ /**
7
+ * Per-context default overrides for the current platform. Today: the approval-
8
+ * mode cycle. `shift+tab` is the primary (bound in `DEFAULT_BINDINGS`), and
9
+ * `meta+m` is the cross-platform fallback claude-code uses where `shift+tab`
10
+ * can't be distinguished (Windows without VT mode) — bound here as a real
11
+ * action so it no longer needs the `app.tsx` text-sink special-case (R1-M2).
12
+ *
13
+ * (Image-paste key differences — `ctrl+v` non-Windows / `meta+v` Windows — are
14
+ * deferred to task 05/09 when image paste lands.)
15
+ */
16
+ export function platformDefaults(_env = {}) {
17
+ return {
18
+ Chat: { "meta+m": "chat:cycleApprovalMode" },
19
+ };
20
+ }
21
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/keybindings/defaults.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAoB,EAAE;IACrD,OAAO;QACL,IAAI,EAAE,EAAE,QAAQ,EAAE,wBAAwB,EAAE;KAC7C,CAAC;AACJ,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * (7.4 / task 04) `keybindings.json` layer over ink-ext (decision `[12.4]`):
3
+ * a chances-own Zod schema + a pure merge that produces the ink-ext `BindingMap`
4
+ * + the editor keymap with fail-soft warnings. See docs/7.4 §4.
5
+ */
6
+ export { KeybindingsFileSchema, type KeybindingsFile } from "./schema.js";
7
+ export { platformDefaults, type PlatformEnv } from "./defaults.js";
8
+ export { mergeKeymaps, type MergedKeymaps } from "./merge.js";
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/keybindings/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,qBAAqB,EAAE,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * (7.4 / task 04) `keybindings.json` layer over ink-ext (decision `[12.4]`):
3
+ * a chances-own Zod schema + a pure merge that produces the ink-ext `BindingMap`
4
+ * + the editor keymap with fail-soft warnings. See docs/7.4 §4.
5
+ */
6
+ export { KeybindingsFileSchema } from "./schema.js";
7
+ export { platformDefaults } from "./defaults.js";
8
+ export { mergeKeymaps } from "./merge.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/keybindings/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,qBAAqB,EAAwB,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAoB,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,YAAY,EAAsB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * (7.4 / task 04) Merge `keybindings.json` over the defaults → an ink-ext
3
+ * `BindingMap` (for the input bus) + an editor keymap (for `EmacsEditor`), with
4
+ * fail-soft warnings (docs/7.4 §4.3). PURE — no fs/Ink; the caller reads the
5
+ * file and feeds the parsed object here.
6
+ *
7
+ * Rules: platform defaults layered first → user overrides on top; `null` unbinds
8
+ * a default; the reserved `ctrl+c` can't be rebound/unbound (warn + ignore);
9
+ * `"Editor"` context feeds the editor keymap (validated against the editor's
10
+ * action set), other contexts feed the ink-ext `BindingMap`; a bad schema or
11
+ * unknown context warns and is skipped (never throws).
12
+ */
13
+ import { type BindingMap } from "../ink-ext/index.js";
14
+ import { type EditorAction } from "@chances-ai/ui-core";
15
+ import { type PlatformEnv } from "./defaults.js";
16
+ export interface MergedKeymaps {
17
+ /** Merged ink-ext bindings (fed to `KeybindingProvider bindings=...`). */
18
+ bindings: BindingMap;
19
+ /** Merged editor keymap, token → editor action (fed to `EmacsEditor`). */
20
+ editorKeymap: Map<string, EditorAction["t"]>;
21
+ /** Non-fatal problems to surface (one `vm.pushError` line on startup). */
22
+ warnings: string[];
23
+ }
24
+ export declare function mergeKeymaps(user: unknown, env?: PlatformEnv): MergedKeymaps;
25
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../../src/keybindings/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAoB,KAAK,UAAU,EAAoB,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEtG,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAC;AAuBnE,MAAM,WAAW,aAAa;IAC5B,0EAA0E;IAC1E,QAAQ,EAAE,UAAU,CAAC;IACrB,0EAA0E;IAC1E,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7C,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAeD,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,GAAE,WAAgB,GAAG,aAAa,CAoDhF"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * (7.4 / task 04) Merge `keybindings.json` over the defaults → an ink-ext
3
+ * `BindingMap` (for the input bus) + an editor keymap (for `EmacsEditor`), with
4
+ * fail-soft warnings (docs/7.4 §4.3). PURE — no fs/Ink; the caller reads the
5
+ * file and feeds the parsed object here.
6
+ *
7
+ * Rules: platform defaults layered first → user overrides on top; `null` unbinds
8
+ * a default; the reserved `ctrl+c` can't be rebound/unbound (warn + ignore);
9
+ * `"Editor"` context feeds the editor keymap (validated against the editor's
10
+ * action set), other contexts feed the ink-ext `BindingMap`; a bad schema or
11
+ * unknown context warns and is skipped (never throws).
12
+ */
13
+ import { DEFAULT_BINDINGS } from "../ink-ext/index.js";
14
+ import { BINDABLE_EDITOR_ACTIONS, defaultEditorKeymap } from "@chances-ai/ui-core";
15
+ import { KeybindingsFileSchema } from "./schema.js";
16
+ import { platformDefaults } from "./defaults.js";
17
+ /** ink-ext contexts that may appear in keybindings.json. */
18
+ const INK_CONTEXTS = new Set([
19
+ "Global",
20
+ "Chat",
21
+ "Autocomplete",
22
+ "Select",
23
+ "Confirmation",
24
+ "Modal",
25
+ "Pager",
26
+ ]);
27
+ /** Tokens no user binding may touch (the non-stoppable force-exit). */
28
+ const RESERVED = new Set(["ctrl+c"]);
29
+ /** Known ink-ext actions (the canonical catalog = every action the defaults
30
+ * bind). A user binding to anything else is a typo → warn + skip (7.4 R2-S4),
31
+ * rather than silently writing a binding no handler will ever claim. */
32
+ const KNOWN_INK_ACTIONS = new Set(Object.values(DEFAULT_BINDINGS).flatMap((m) => Object.values(m ?? {})));
33
+ /** Deep-copy the shared `DEFAULT_BINDINGS` so merging never mutates the constant. */
34
+ function cloneBindings(src) {
35
+ const out = {};
36
+ for (const [ctx, map] of Object.entries(src)) {
37
+ if (map)
38
+ out[ctx] = { ...map };
39
+ }
40
+ return out;
41
+ }
42
+ function setBinding(bindings, ctx, token, action) {
43
+ (bindings[ctx] ??= {})[token] = action;
44
+ }
45
+ export function mergeKeymaps(user, env = {}) {
46
+ const warnings = [];
47
+ const bindings = cloneBindings(DEFAULT_BINDINGS);
48
+ const editorKeymap = new Map(defaultEditorKeymap());
49
+ // Platform defaults first (e.g. meta+m approval-cycle fallback).
50
+ for (const [ctx, map] of Object.entries(platformDefaults(env))) {
51
+ for (const [token, action] of Object.entries(map ?? {}))
52
+ setBinding(bindings, ctx, token, action);
53
+ }
54
+ const parsed = KeybindingsFileSchema.safeParse(user ?? {});
55
+ if (!parsed.success) {
56
+ warnings.push(`keybindings.json is invalid; using defaults (${parsed.error.issues[0]?.message ?? "schema error"})`);
57
+ return { bindings, editorKeymap, warnings };
58
+ }
59
+ for (const [context, map] of Object.entries(parsed.data)) {
60
+ for (const [token, action] of Object.entries(map)) {
61
+ if (RESERVED.has(token)) {
62
+ warnings.push(`'${token}' is reserved (force-exit) and cannot be rebound`);
63
+ continue;
64
+ }
65
+ if (context === "Editor") {
66
+ if (action === null) {
67
+ editorKeymap.delete(token);
68
+ }
69
+ else if (BINDABLE_EDITOR_ACTIONS.has(action)) {
70
+ editorKeymap.set(token, action);
71
+ }
72
+ else {
73
+ // Unknown OR a payload-required action (insert/setText/setCursor) — the
74
+ // latter would crash if dispatched without a payload (7.4 R2-M1).
75
+ warnings.push(`unknown or non-bindable editor action '${action}' for '${token}'`);
76
+ }
77
+ continue;
78
+ }
79
+ if (!INK_CONTEXTS.has(context)) {
80
+ warnings.push(`unknown keybinding context '${context}'`);
81
+ continue;
82
+ }
83
+ const ctx = context;
84
+ if (action === null) {
85
+ if (bindings[ctx])
86
+ delete bindings[ctx][token];
87
+ }
88
+ else if (!KNOWN_INK_ACTIONS.has(action)) {
89
+ warnings.push(`unknown action '${action}' for '${context}/${token}'`);
90
+ }
91
+ else {
92
+ setBinding(bindings, ctx, token, action);
93
+ }
94
+ }
95
+ }
96
+ return { bindings, editorKeymap, warnings };
97
+ }
98
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/keybindings/merge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,gBAAgB,EAAqC,MAAM,qBAAqB,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAqB,MAAM,qBAAqB,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAoB,MAAM,eAAe,CAAC;AAEnE,4DAA4D;AAC5D,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAc;IAC7D,QAAQ;IACR,MAAM;IACN,cAAc;IACd,QAAQ;IACR,cAAc;IACd,OAAO;IACP,OAAO;CACR,CAAC,CAAC;AAEH,uEAAuE;AACvE,MAAM,QAAQ,GAAwB,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAE1D;;yEAEyE;AACzE,MAAM,iBAAiB,GAAwB,IAAI,GAAG,CACpD,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CACvE,CAAC;AAWF,qFAAqF;AACrF,SAAS,aAAa,CAAC,GAAe;IACpC,MAAM,GAAG,GAAe,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7C,IAAI,GAAG;YAAE,GAAG,CAAC,GAAkB,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,UAAU,CAAC,QAAoB,EAAE,GAAgB,EAAE,KAAa,EAAE,MAAc;IACvF,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAa,EAAE,MAAmB,EAAE;IAC/D,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,aAAa,CAAC,gBAAgB,CAAC,CAAC;IACjD,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAEpD,iEAAiE;IACjE,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC/D,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC;YAAE,UAAU,CAAC,QAAQ,EAAE,GAAkB,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;IACnH,CAAC;IAED,MAAM,MAAM,GAAG,qBAAqB,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC3D,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,QAAQ,CAAC,IAAI,CACX,gDAAgD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,IAAI,cAAc,GAAG,CACrG,CAAC;QACF,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;IAC9C,CAAC;IAED,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACzD,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAClD,IAAI,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxB,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,kDAAkD,CAAC,CAAC;gBAC3E,SAAS;YACX,CAAC;YACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACzB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;oBACpB,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC7B,CAAC;qBAAM,IAAI,uBAAuB,CAAC,GAAG,CAAC,MAA2B,CAAC,EAAE,CAAC;oBACpE,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,MAA2B,CAAC,CAAC;gBACvD,CAAC;qBAAM,CAAC;oBACN,wEAAwE;oBACxE,kEAAkE;oBAClE,QAAQ,CAAC,IAAI,CAAC,0CAA0C,MAAM,UAAU,KAAK,GAAG,CAAC,CAAC;gBACpF,CAAC;gBACD,SAAS;YACX,CAAC;YACD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,QAAQ,CAAC,IAAI,CAAC,+BAA+B,OAAO,GAAG,CAAC,CAAC;gBACzD,SAAS;YACX,CAAC;YACD,MAAM,GAAG,GAAG,OAAsB,CAAC;YACnC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,IAAI,QAAQ,CAAC,GAAG,CAAC;oBAAE,OAAO,QAAQ,CAAC,GAAG,CAAE,CAAC,KAAK,CAAC,CAAC;YAClD,CAAC;iBAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC1C,QAAQ,CAAC,IAAI,CAAC,mBAAmB,MAAM,UAAU,OAAO,IAAI,KAAK,GAAG,CAAC,CAAC;YACxE,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * (7.4 / task 04) The `keybindings.json` schema (decision `[12.4]`).
3
+ *
4
+ * **chances' OWN simplified shape** — `{ [context]: { [keyToken]: action | null } }`
5
+ * — NOT claude-code's `{ bindings: [{ context, bindings }] }` block-array (R1-S4
6
+ * corrected the original doc's "borrow claude-code schema" framing; only its
7
+ * null-unbind / reserved-key / platform-default *concepts* are borrowed).
8
+ *
9
+ * `context` is an ink-ext `ContextName` (Chat/Autocomplete/Select/Confirmation/
10
+ * Modal/Global) OR the pseudo-context `"Editor"` (the in-editor Emacs keymap,
11
+ * docs/7.4 §4.2). `action` is an action string, or `null` to unbind a default.
12
+ */
13
+ import { z } from "zod";
14
+ /** `{ [context]: { [keyToken]: action | null } }`. */
15
+ export declare const KeybindingsFileSchema: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodString, z.ZodNull]>>>;
16
+ export type KeybindingsFile = z.infer<typeof KeybindingsFileSchema>;
17
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/keybindings/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,sDAAsD;AACtD,eAAO,MAAM,qBAAqB,0FAGjC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * (7.4 / task 04) The `keybindings.json` schema (decision `[12.4]`).
3
+ *
4
+ * **chances' OWN simplified shape** — `{ [context]: { [keyToken]: action | null } }`
5
+ * — NOT claude-code's `{ bindings: [{ context, bindings }] }` block-array (R1-S4
6
+ * corrected the original doc's "borrow claude-code schema" framing; only its
7
+ * null-unbind / reserved-key / platform-default *concepts* are borrowed).
8
+ *
9
+ * `context` is an ink-ext `ContextName` (Chat/Autocomplete/Select/Confirmation/
10
+ * Modal/Global) OR the pseudo-context `"Editor"` (the in-editor Emacs keymap,
11
+ * docs/7.4 §4.2). `action` is an action string, or `null` to unbind a default.
12
+ */
13
+ import { z } from "zod";
14
+ /** `{ [context]: { [keyToken]: action | null } }`. */
15
+ export const KeybindingsFileSchema = z.record(z.string(), z.record(z.string(), z.union([z.string(), z.null()])));
16
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/keybindings/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,sDAAsD;AACtD,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAC3C,CAAC,CAAC,MAAM,EAAE,EACV,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CACtD,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { type JSX } from "react";
2
+ import type { Line, LineKind } from "@chances-ai/ui-core";
3
+ export interface PagerRow {
4
+ kind: LineKind;
5
+ text: string;
6
+ }
7
+ /** Flatten transcript lines into one display row per physical line (`\n` split),
8
+ * indenting wrapped continuation lines so multi-line blocks stay readable. */
9
+ export declare function pagerRows(lines: Line[]): PagerRow[];
10
+ /** Clamp a scroll offset to `[0, max]` where `max` keeps the last page in view. */
11
+ export declare function clampOffset(offset: number, total: number, viewHeight: number): number;
12
+ export interface TranscriptPagerProps {
13
+ lines: Line[];
14
+ onClose: () => void;
15
+ }
16
+ /** The pager view. Mounted only while open; entering/leaving the alt screen is a
17
+ * mount/unmount side effect (TTY only, so tests + pipes are unaffected). */
18
+ export declare function TranscriptPager({ lines, onClose }: TranscriptPagerProps): JSX.Element;
19
+ //# sourceMappingURL=pager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pager.d.ts","sourceRoot":"","sources":["../src/pager.tsx"],"names":[],"mappings":"AASA,OAAO,EAAgC,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAC/D,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAM1D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;+EAC+E;AAC/E,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,QAAQ,EAAE,CAOnD;AAED,mFAAmF;AACnF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAGrF;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;6EAC6E;AAC7E,wBAAgB,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,oBAAoB,GAAG,GAAG,CAAC,OAAO,CA0DrF"}
package/dist/pager.js ADDED
@@ -0,0 +1,83 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * (7.4 §G4) Full-screen, keyboard-scrollable transcript pager on stock Ink.
4
+ * Opens over the alternate screen buffer (`?1049h`) so the whole conversation
5
+ * is browsable with the keyboard regardless of the terminal's own scrollback,
6
+ * and restores the main screen verbatim on close (`?1049l`). The scroll model is
7
+ * a pure, tested function; the component is a thin shell so the TTY-only escape
8
+ * writes stay out of the logic.
9
+ */
10
+ import { Box, Text, useStdout } from "ink";
11
+ import { useEffect, useMemo, useState } from "react";
12
+ import { useKeybinding, useKeybindingContext, useTextInput } from "./ink-ext/index.js";
13
+ import { useTheme } from "./theme-context.js";
14
+ const GLYPH = { user: "❯", assistant: "⏺", tool: "⎿", info: "·", error: "✗" };
15
+ /** Flatten transcript lines into one display row per physical line (`\n` split),
16
+ * indenting wrapped continuation lines so multi-line blocks stay readable. */
17
+ export function pagerRows(lines) {
18
+ const rows = [];
19
+ for (const l of lines) {
20
+ const segs = l.text.split("\n");
21
+ for (let i = 0; i < segs.length; i++)
22
+ rows.push({ kind: l.kind, text: i === 0 ? segs[i] : ` ${segs[i]}` });
23
+ }
24
+ return rows;
25
+ }
26
+ /** Clamp a scroll offset to `[0, max]` where `max` keeps the last page in view. */
27
+ export function clampOffset(offset, total, viewHeight) {
28
+ const max = Math.max(0, total - viewHeight);
29
+ return Math.min(Math.max(0, offset), max);
30
+ }
31
+ /** The pager view. Mounted only while open; entering/leaving the alt screen is a
32
+ * mount/unmount side effect (TTY only, so tests + pipes are unaffected). */
33
+ export function TranscriptPager({ lines, onClose }) {
34
+ const { stdout } = useStdout();
35
+ const { theme } = useTheme();
36
+ const rows = stdout?.rows ?? 24;
37
+ const viewHeight = Math.max(1, rows - 1); // reserve the bottom row for the status bar
38
+ const allRows = useMemo(() => pagerRows(lines), [lines]);
39
+ const total = allRows.length;
40
+ const maxOffset = Math.max(0, total - viewHeight);
41
+ const [offset, setOffset] = useState(maxOffset); // open at the bottom (newest)
42
+ const scrollBy = (delta) => setOffset((o) => clampOffset(o + delta, total, viewHeight));
43
+ useEffect(() => {
44
+ if (stdout?.isTTY)
45
+ stdout.write("\x1b[?1049h\x1b[H"); // enter alt screen + home
46
+ return () => {
47
+ if (stdout?.isTTY)
48
+ stdout.write("\x1b[?1049l"); // restore the main screen verbatim
49
+ };
50
+ }, [stdout]);
51
+ useKeybindingContext("Pager", true);
52
+ useKeybinding("pager:up", () => scrollBy(-1), { context: "Pager" });
53
+ useKeybinding("pager:down", () => scrollBy(1), { context: "Pager" });
54
+ useKeybinding("pager:pageUp", () => scrollBy(-viewHeight), { context: "Pager" });
55
+ useKeybinding("pager:pageDown", () => scrollBy(viewHeight), { context: "Pager" });
56
+ useKeybinding("pager:close", onClose, { context: "Pager" });
57
+ // vim-style keys flow through the modal context's text sink (mirrors how the
58
+ // Confirmation prompt handles y/n).
59
+ useTextInput("Pager", (char) => {
60
+ if (char === "q")
61
+ onClose();
62
+ else if (char === "j")
63
+ scrollBy(1);
64
+ else if (char === "k")
65
+ scrollBy(-1);
66
+ else if (char === "b")
67
+ scrollBy(-viewHeight);
68
+ else if (char === "d")
69
+ scrollBy(Math.floor(viewHeight / 2));
70
+ else if (char === "u")
71
+ scrollBy(-Math.floor(viewHeight / 2));
72
+ else if (char === "g")
73
+ setOffset(0);
74
+ else if (char === "G")
75
+ setOffset(maxOffset);
76
+ }, { active: true });
77
+ const safeOffset = clampOffset(offset, total, viewHeight);
78
+ const visible = allRows.slice(safeOffset, safeOffset + viewHeight);
79
+ const atBottom = safeOffset >= maxOffset;
80
+ const pos = total === 0 ? "empty" : atBottom ? "END" : `${safeOffset + viewHeight}/${total}`;
81
+ return (_jsxs(Box, { flexDirection: "column", children: [visible.map((r, i) => (_jsxs(Text, { wrap: "truncate-end", children: [_jsxs(Text, { color: r.kind === "error" ? theme.error : undefined, dimColor: r.kind !== "error", children: [GLYPH[r.kind], " "] }), r.text] }, safeOffset + i))), _jsx(Text, { inverse: true, children: ` ${pos} · ↑↓/jk scroll · space/b page · g/G top/bottom · q close ` })] }));
82
+ }
83
+ //# sourceMappingURL=pager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pager.js","sourceRoot":"","sources":["../src/pager.tsx"],"names":[],"mappings":"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"}
@@ -1,4 +1,9 @@
1
- import { type JSX } from "react";
1
+ /**
2
+ * (5.10 A3) Pure slash-command suggestion helper. The interactive typeahead
3
+ * component was superseded by `editor/unified-autocomplete.tsx` (7.4 W5 — one
4
+ * fuzzy menu for slash + @file + @agent + @mcp); this keeps the pure matcher +
5
+ * type the unified component, the host snapshot, and tests still consume.
6
+ */
2
7
  export interface SlashSuggestion {
3
8
  name: string;
4
9
  description: string;
@@ -7,28 +12,7 @@ export interface SlashSuggestion {
7
12
  }
8
13
  /** Pure helper for picking the suggestions to show for a partial input. The
9
14
  * typeahead is only meaningful before the first space (while typing the command
10
- * NAME); once args begin, the menu hides and Enter submits normally. */
15
+ * NAME); once args begin, the menu hides and Enter submits normally. Prefix
16
+ * match (the unified menu re-ranks with the native fuzzy ranker). */
11
17
  export declare function suggestSlashCommands(input: string, available: SlashSuggestion[]): SlashSuggestion[];
12
- /**
13
- * (5.10 A3) Stateful slash-command typeahead — replaces the old passive
14
- * ghost-text list. While visible it owns the **non-modal** `Autocomplete`
15
- * context (ink-ext A1), so the user keeps typing into chat to filter, but
16
- * `↑/↓` select, `Tab` completes the name, `Enter` executes the SELECTED command
17
- * (not the raw text), and `Esc` dismisses. The Enter interception is real
18
- * submit-gating: `Autocomplete.return → autocomplete:execute` resolves before
19
- * `Chat.chat:submit` on the bus, so the menu must be acted on or dismissed.
20
- *
21
- * Visible only while typing the command name (input starts with `/`, no space
22
- * yet, ≥1 match, not dismissed). Tab inserts a trailing space → the menu closes
23
- * and the user types args, which Enter then submits via the normal chat path.
24
- */
25
- export declare function SlashTypeahead({ input, available, busy, onComplete, onExecute, }: {
26
- input: string;
27
- available: SlashSuggestion[];
28
- busy: boolean;
29
- /** Tab: replace the draft with the completed `"/name "` (trailing space). */
30
- onComplete: (newInput: string) => void;
31
- /** Enter: run the selected command line `"/name"`. */
32
- onExecute: (line: string) => void;
33
- }): JSX.Element | null;
34
18
  //# sourceMappingURL=slash-typeahead.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"slash-typeahead.d.ts","sourceRoot":"","sources":["../src/slash-typeahead.tsx"],"names":[],"mappings":"AACA,OAAO,EAAuB,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAItD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;yEAEyE;AACzE,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,eAAe,EAAE,GAC3B,eAAe,EAAE,CAKnB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,SAAS,EACT,IAAI,EACJ,UAAU,EACV,SAAS,GACV,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,IAAI,EAAE,OAAO,CAAC;IACd,6EAA6E;IAC7E,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,sDAAsD;IACtD,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC,GAAG,GAAG,CAAC,OAAO,GAAG,IAAI,CAgErB"}
1
+ {"version":3,"file":"slash-typeahead.d.ts","sourceRoot":"","sources":["../src/slash-typeahead.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;sEAGsE;AACtE,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,eAAe,EAAE,GAAG,eAAe,EAAE,CAKnG"}
@@ -1,11 +1,13 @@
1
- import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Text } from "ink";
3
- import { useEffect, useState } from "react";
4
- import { useKeybinding, useKeybindingContext } from "./ink-ext/index.js";
5
- import { useTheme } from "./theme-context.js";
1
+ /**
2
+ * (5.10 A3) Pure slash-command suggestion helper. The interactive typeahead
3
+ * component was superseded by `editor/unified-autocomplete.tsx` (7.4 W5 — one
4
+ * fuzzy menu for slash + @file + @agent + @mcp); this keeps the pure matcher +
5
+ * type the unified component, the host snapshot, and tests still consume.
6
+ */
6
7
  /** Pure helper for picking the suggestions to show for a partial input. The
7
8
  * typeahead is only meaningful before the first space (while typing the command
8
- * NAME); once args begin, the menu hides and Enter submits normally. */
9
+ * NAME); once args begin, the menu hides and Enter submits normally. Prefix
10
+ * match (the unified menu re-ranks with the native fuzzy ranker). */
9
11
  export function suggestSlashCommands(input, available) {
10
12
  if (!input.startsWith("/"))
11
13
  return [];
@@ -14,65 +16,4 @@ export function suggestSlashCommands(input, available) {
14
16
  return available.slice(0, 5);
15
17
  return available.filter((c) => c.name.toLowerCase().startsWith(partial)).slice(0, 5);
16
18
  }
17
- /**
18
- * (5.10 A3) Stateful slash-command typeahead — replaces the old passive
19
- * ghost-text list. While visible it owns the **non-modal** `Autocomplete`
20
- * context (ink-ext A1), so the user keeps typing into chat to filter, but
21
- * `↑/↓` select, `Tab` completes the name, `Enter` executes the SELECTED command
22
- * (not the raw text), and `Esc` dismisses. The Enter interception is real
23
- * submit-gating: `Autocomplete.return → autocomplete:execute` resolves before
24
- * `Chat.chat:submit` on the bus, so the menu must be acted on or dismissed.
25
- *
26
- * Visible only while typing the command name (input starts with `/`, no space
27
- * yet, ≥1 match, not dismissed). Tab inserts a trailing space → the menu closes
28
- * and the user types args, which Enter then submits via the normal chat path.
29
- */
30
- export function SlashTypeahead({ input, available, busy, onComplete, onExecute, }) {
31
- const { theme } = useTheme();
32
- const [selectedIndex, setSelectedIndex] = useState(0);
33
- const [dismissed, setDismissed] = useState(false);
34
- const matches = suggestSlashCommands(input, available);
35
- const isCommandName = input.startsWith("/") && !input.includes(" ");
36
- const visible = isCommandName && matches.length > 0 && !dismissed;
37
- // Any edit to the draft re-opens the menu and resets the selection — the
38
- // filter changed, so a stale index/dismiss must not stick.
39
- useEffect(() => {
40
- setDismissed(false);
41
- setSelectedIndex(0);
42
- }, [input]);
43
- const safeIndex = Math.min(selectedIndex, Math.max(0, matches.length - 1));
44
- useKeybindingContext("Autocomplete", visible);
45
- useKeybinding("autocomplete:previous", () => setSelectedIndex(Math.max(0, safeIndex - 1)), {
46
- context: "Autocomplete",
47
- active: visible,
48
- });
49
- useKeybinding("autocomplete:next", () => setSelectedIndex(Math.min(matches.length - 1, safeIndex + 1)), {
50
- context: "Autocomplete",
51
- active: visible,
52
- });
53
- useKeybinding("autocomplete:accept", // Tab — complete the name, leave args to the user
54
- () => {
55
- const m = matches[safeIndex];
56
- if (m)
57
- onComplete(`/${m.name} `);
58
- }, { context: "Autocomplete", active: visible });
59
- useKeybinding("autocomplete:execute", // Enter — run the selected command
60
- () => {
61
- if (busy)
62
- return; // mirror chat:submit's streaming guard
63
- const m = matches[safeIndex];
64
- if (m)
65
- onExecute(`/${m.name}`);
66
- }, { context: "Autocomplete", active: visible });
67
- useKeybinding("autocomplete:dismiss", () => setDismissed(true), {
68
- context: "Autocomplete",
69
- active: visible,
70
- });
71
- if (!visible)
72
- return null;
73
- return (_jsx(Box, { flexDirection: "column", marginLeft: 2, children: matches.map((m, i) => {
74
- const selected = i === safeIndex;
75
- return (_jsxs(Text, { color: selected ? theme.permission : undefined, dimColor: !selected, children: [selected ? "❯ " : " ", "/", m.name, m.argumentHint ? _jsxs(Text, { dimColor: true, children: [" ", m.argumentHint] }) : null, _jsxs(Text, { dimColor: true, children: [" \u2014 ", m.description] })] }, m.name));
76
- }) }));
77
- }
78
19
  //# sourceMappingURL=slash-typeahead.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"slash-typeahead.js","sourceRoot":"","sources":["../src/slash-typeahead.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slash-typeahead.js","sourceRoot":"","sources":["../src/slash-typeahead.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH;;;sEAGsE;AACtE,MAAM,UAAU,oBAAoB,CAAC,KAAa,EAAE,SAA4B;IAC9E,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAC7C,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjD,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACvF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chances-ai/tui",
3
- "version": "24.2.0",
3
+ "version": "24.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -14,13 +14,15 @@
14
14
  "dist"
15
15
  ],
16
16
  "dependencies": {
17
- "@chances-ai/engine": "24.2.0",
18
- "@chances-ai/runtime": "24.2.0",
19
- "@chances-ai/ui-core": "24.2.0",
17
+ "@chances-ai/engine": "24.3.0",
18
+ "@chances-ai/native": "24.3.0",
19
+ "@chances-ai/runtime": "24.3.0",
20
+ "@chances-ai/ui-core": "24.3.0",
20
21
  "marked": "^18.0.0",
21
22
  "highlight.js": "^11.11.1",
22
23
  "diff": "^9.0.0",
23
- "string-width": "^8.2.1"
24
+ "string-width": "^8.2.1",
25
+ "zod": "^3.23.8"
24
26
  },
25
27
  "peerDependencies": {
26
28
  "ink": "^7.0.5",