@pentoshi/clai 3.7.9 → 3.8.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.
- package/README.md +7 -4
- package/dist/commands/update.js +11 -3
- package/dist/commands/update.js.map +1 -1
- package/dist/prompts/embedded.js +2 -2
- package/dist/prompts/embedded.js.map +1 -1
- package/dist/prompts/index.js +3 -2
- package/dist/prompts/index.js.map +1 -1
- package/dist/prompts/system.agent.md +3 -3
- package/dist/prompts/system.ask.md +1 -1
- package/dist/repl/slash-commands.js +4 -0
- package/dist/repl/slash-commands.js.map +1 -1
- package/dist/tools/definitions.js +48 -5
- package/dist/tools/definitions.js.map +1 -1
- package/dist/tools/fs.d.ts +18 -3
- package/dist/tools/fs.js +471 -40
- package/dist/tools/fs.js.map +1 -1
- package/dist/tools/registry.js +10 -1
- package/dist/tools/registry.js.map +1 -1
- package/dist/tui-v2/actions/format-shortcuts.d.ts +12 -0
- package/dist/tui-v2/actions/format-shortcuts.js +257 -0
- package/dist/tui-v2/actions/format-shortcuts.js.map +1 -0
- package/dist/tui-v2/actions/keymap.js +7 -4
- package/dist/tui-v2/actions/keymap.js.map +1 -1
- package/dist/tui-v2/app/App.js +77 -21
- package/dist/tui-v2/app/App.js.map +1 -1
- package/dist/tui-v2/app/command-handlers.js +2 -1
- package/dist/tui-v2/app/command-handlers.js.map +1 -1
- package/dist/tui-v2/app/commands/config-commands.d.ts +1 -0
- package/dist/tui-v2/app/commands/config-commands.js +6 -5
- package/dist/tui-v2/app/commands/config-commands.js.map +1 -1
- package/dist/tui-v2/app/commands/picker-commands.js +3 -1
- package/dist/tui-v2/app/commands/picker-commands.js.map +1 -1
- package/dist/tui-v2/app/commands/session-commands.js +19 -2
- package/dist/tui-v2/app/commands/session-commands.js.map +1 -1
- package/dist/tui-v2/app/plan-lifecycle.js +1 -1
- package/dist/tui-v2/app/plan-lifecycle.js.map +1 -1
- package/dist/tui-v2/components/overlay/overlay-host.js +1 -1
- package/dist/tui-v2/components/overlay/overlay-host.js.map +1 -1
- package/dist/tui-v2/components/pager/pager-line.d.ts +31 -0
- package/dist/tui-v2/components/pager/pager-line.js +184 -0
- package/dist/tui-v2/components/pager/pager-line.js.map +1 -0
- package/dist/tui-v2/components/pager/pager.d.ts +7 -2
- package/dist/tui-v2/components/pager/pager.js +66 -187
- package/dist/tui-v2/components/pager/pager.js.map +1 -1
- package/dist/tui-v2/components/status/status-line.d.ts +22 -8
- package/dist/tui-v2/components/status/status-line.js +115 -57
- package/dist/tui-v2/components/status/status-line.js.map +1 -1
- package/dist/tui-v2/components/toast/toast-host.d.ts +5 -2
- package/dist/tui-v2/components/toast/toast-host.js +63 -28
- package/dist/tui-v2/components/toast/toast-host.js.map +1 -1
- package/dist/tui-v2/components/transcript/search-bar.d.ts +9 -5
- package/dist/tui-v2/components/transcript/search-bar.js +49 -3
- package/dist/tui-v2/components/transcript/search-bar.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-row.d.ts +9 -0
- package/dist/tui-v2/components/transcript/transcript-row.js +24 -7
- package/dist/tui-v2/components/transcript/transcript-row.js.map +1 -1
- package/dist/tui-v2/components/transcript/transcript-view.js +121 -13
- package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
- package/dist/tui-v2/components/transcript/use-native-selection-copy.js +7 -4
- package/dist/tui-v2/components/transcript/use-native-selection-copy.js.map +1 -1
- package/dist/tui-v2/composer/composer-action-port.d.ts +12 -0
- package/dist/tui-v2/composer/composer-action-port.js +20 -0
- package/dist/tui-v2/composer/composer-action-port.js.map +1 -0
- package/dist/tui-v2/composer/composer-editor.js +34 -2
- package/dist/tui-v2/composer/composer-editor.js.map +1 -1
- package/dist/tui-v2/composer/textarea-keybindings.d.ts +5 -3
- package/dist/tui-v2/composer/textarea-keybindings.js +29 -2
- package/dist/tui-v2/composer/textarea-keybindings.js.map +1 -1
- package/dist/tui-v2/controllers/overlay-controller.d.ts +6 -1
- package/dist/tui-v2/controllers/overlay-controller.js +2 -1
- package/dist/tui-v2/controllers/overlay-controller.js.map +1 -1
- package/dist/tui-v2/controllers/toast-controller.d.ts +17 -5
- package/dist/tui-v2/controllers/toast-controller.js +33 -7
- package/dist/tui-v2/controllers/toast-controller.js.map +1 -1
- package/dist/tui-v2/notify.d.ts +21 -0
- package/dist/tui-v2/notify.js +27 -0
- package/dist/tui-v2/notify.js.map +1 -0
- package/dist/tui-v2/rendering/format-help.d.ts +16 -0
- package/dist/tui-v2/rendering/format-help.js +95 -0
- package/dist/tui-v2/rendering/format-help.js.map +1 -0
- package/dist/tui-v2/rendering/pager-markdown.d.ts +40 -0
- package/dist/tui-v2/rendering/pager-markdown.js +82 -0
- package/dist/tui-v2/rendering/pager-markdown.js.map +1 -0
- package/dist/tui-v2/rendering/plan-view.d.ts +1 -2
- package/dist/tui-v2/rendering/plan-view.js +39 -55
- package/dist/tui-v2/rendering/plan-view.js.map +1 -1
- package/dist/version.generated.d.ts +6 -0
- package/dist/version.generated.js +7 -0
- package/dist/version.generated.js.map +1 -0
- package/package.json +5 -1
|
@@ -6,17 +6,19 @@
|
|
|
6
6
|
* undo semantics (INPUT-004/005) — this module only overrides the small set
|
|
7
7
|
* of chords where the library default is backwards for a submit-on-Enter
|
|
8
8
|
* composer (its default binds bare Enter to "newline" and Alt+Enter to
|
|
9
|
-
* "submit")
|
|
10
|
-
*
|
|
9
|
+
* "submit"), plus macOS line-delete chords that conflict with chat scroll.
|
|
10
|
+
* Everything else passes through untouched. The shape here mirrors
|
|
11
|
+
* `@opentui/core`'s `KeyBinding<TextareaAction>` structurally without
|
|
11
12
|
* importing it, keeping this module renderer-independent; the renderer glue
|
|
12
13
|
* casts it at the one place it is consumed.
|
|
13
14
|
*/
|
|
15
|
+
export type TextareaActionName = "submit" | "newline" | "delete-to-line-start" | "delete-to-line-end" | "delete-line";
|
|
14
16
|
export interface TextareaKeyBindingLike {
|
|
15
17
|
readonly name: string;
|
|
16
18
|
readonly ctrl?: boolean;
|
|
17
19
|
readonly shift?: boolean;
|
|
18
20
|
readonly meta?: boolean;
|
|
19
21
|
readonly super?: boolean;
|
|
20
|
-
readonly action:
|
|
22
|
+
readonly action: TextareaActionName;
|
|
21
23
|
}
|
|
22
24
|
export declare function buildComposerTextareaOverrides(): TextareaKeyBindingLike[];
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
* undo semantics (INPUT-004/005) — this module only overrides the small set
|
|
7
7
|
* of chords where the library default is backwards for a submit-on-Enter
|
|
8
8
|
* composer (its default binds bare Enter to "newline" and Alt+Enter to
|
|
9
|
-
* "submit")
|
|
10
|
-
*
|
|
9
|
+
* "submit"), plus macOS line-delete chords that conflict with chat scroll.
|
|
10
|
+
* Everything else passes through untouched. The shape here mirrors
|
|
11
|
+
* `@opentui/core`'s `KeyBinding<TextareaAction>` structurally without
|
|
11
12
|
* importing it, keeping this module renderer-independent; the renderer glue
|
|
12
13
|
* casts it at the one place it is consumed.
|
|
13
14
|
*/
|
|
@@ -22,6 +23,32 @@ export function buildComposerTextareaOverrides() {
|
|
|
22
23
|
overrides.push({ name, meta: true, action: "newline" });
|
|
23
24
|
overrides.push({ name, ctrl: true, action: "newline" });
|
|
24
25
|
}
|
|
26
|
+
// Line kill: readline Ctrl+U and macOS Cmd+Backspace/Delete.
|
|
27
|
+
// OpenTUI defaults map meta+backspace → delete-word-backward; override to
|
|
28
|
+
// delete-to-line-start so Cmd+Backspace matches macOS text fields. Explicit
|
|
29
|
+
// ctrl+u keeps delete-to-line-start even if library defaults change.
|
|
30
|
+
// (Chat jump-to-top is NOT bound globally on ctrl+u — see keymap.ts.)
|
|
31
|
+
overrides.push({ name: "u", ctrl: true, action: "delete-to-line-start" });
|
|
32
|
+
overrides.push({
|
|
33
|
+
name: "backspace",
|
|
34
|
+
meta: true,
|
|
35
|
+
action: "delete-to-line-start",
|
|
36
|
+
});
|
|
37
|
+
overrides.push({
|
|
38
|
+
name: "backspace",
|
|
39
|
+
super: true,
|
|
40
|
+
action: "delete-to-line-start",
|
|
41
|
+
});
|
|
42
|
+
overrides.push({
|
|
43
|
+
name: "delete",
|
|
44
|
+
meta: true,
|
|
45
|
+
action: "delete-to-line-end",
|
|
46
|
+
});
|
|
47
|
+
overrides.push({
|
|
48
|
+
name: "delete",
|
|
49
|
+
super: true,
|
|
50
|
+
action: "delete-to-line-end",
|
|
51
|
+
});
|
|
25
52
|
return overrides;
|
|
26
53
|
}
|
|
27
54
|
//# sourceMappingURL=textarea-keybindings.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"textarea-keybindings.js","sourceRoot":"","sources":["../../../src/tui-v2/composer/textarea-keybindings.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"textarea-keybindings.js","sourceRoot":"","sources":["../../../src/tui-v2/composer/textarea-keybindings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAkBH,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAU,CAAC;AAEnD,MAAM,UAAU,8BAA8B;IAC5C,MAAM,SAAS,GAA6B,EAAE,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,uEAAuE;QACvE,8DAA8D;QAC9D,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3C,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACzD,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QACxD,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,6DAA6D;IAC7D,0EAA0E;IAC1E,4EAA4E;IAC5E,qEAAqE;IACrE,sEAAsE;IACtE,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC,CAAC;IAC1E,SAAS,CAAC,IAAI,CAAC;QACb,IAAI,EAAE,WAAW;QACjB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,sBAAsB;KAC/B,CAAC,CAAC;IACH,SAAS,CAAC,IAAI,CAAC;QACb,IAAI,EAAE,WAAW;QACjB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,sBAAsB;KAC/B,CAAC,CAAC;IACH,SAAS,CAAC,IAAI,CAAC;QACb,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,oBAAoB;KAC7B,CAAC,CAAC;IACH,SAAS,CAAC,IAAI,CAAC;QACb,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,oBAAoB;KAC7B,CAAC,CAAC;IAEH,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -70,6 +70,11 @@ export type OverlayState = {
|
|
|
70
70
|
readonly source?: ArtifactPagerSource | undefined;
|
|
71
71
|
/** Path for syntax highlighting in file-diff modals. */
|
|
72
72
|
readonly highlightPath?: string | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Markdown rendering: force for help/shortcuts/plan, auto for mixed
|
|
75
|
+
* bodies, plain to disable. Default auto.
|
|
76
|
+
*/
|
|
77
|
+
readonly markdown?: "auto" | "force" | "plain" | undefined;
|
|
73
78
|
} | {
|
|
74
79
|
readonly kind: "jobs";
|
|
75
80
|
};
|
|
@@ -91,7 +96,7 @@ export declare class OverlayController {
|
|
|
91
96
|
* plan detail without resolving the confirm (F-021); closing the pager
|
|
92
97
|
* restores the suspended confirm. Any other open overlay is still rejected.
|
|
93
98
|
*/
|
|
94
|
-
openPager(title: string, body: string, source?: ArtifactPagerSource, highlightPath?: string): boolean;
|
|
99
|
+
openPager(title: string, body: string, source?: ArtifactPagerSource, highlightPath?: string, markdown?: "auto" | "force" | "plain"): boolean;
|
|
95
100
|
openJobs(): boolean;
|
|
96
101
|
openPromptActions(request: PromptActionsRequest): boolean;
|
|
97
102
|
/** Resolves `false` if a blocking overlay was already open rather than hanging. */
|
|
@@ -36,13 +36,14 @@ export class OverlayController {
|
|
|
36
36
|
* plan detail without resolving the confirm (F-021); closing the pager
|
|
37
37
|
* restores the suspended confirm. Any other open overlay is still rejected.
|
|
38
38
|
*/
|
|
39
|
-
openPager(title, body, source, highlightPath) {
|
|
39
|
+
openPager(title, body, source, highlightPath, markdown) {
|
|
40
40
|
const pager = {
|
|
41
41
|
kind: "pager",
|
|
42
42
|
title,
|
|
43
43
|
body,
|
|
44
44
|
...(source ? { source } : {}),
|
|
45
45
|
...(highlightPath ? { highlightPath } : {}),
|
|
46
|
+
...(markdown ? { markdown } : {}),
|
|
46
47
|
};
|
|
47
48
|
// Allow pager over any confirm (plan "p" or delete "v") without resolving it.
|
|
48
49
|
const opened = this.state.kind === "confirm" && !this.suspended
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overlay-controller.js","sourceRoot":"","sources":["../../../src/tui-v2/controllers/overlay-controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"overlay-controller.js","sourceRoot":"","sources":["../../../src/tui-v2/controllers/overlay-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ephemeral
|
|
2
|
+
* Ephemeral toast queue (UI chrome, not transcript history).
|
|
3
3
|
*
|
|
4
|
-
* Toasts auto-dismiss after a short TTL
|
|
5
|
-
*
|
|
4
|
+
* Toasts auto-dismiss after a short TTL. Same-key shows replace the previous
|
|
5
|
+
* toast so rapid toggles (thinking / output / scroll) do not stack noise.
|
|
6
|
+
* The host owns layout; this controller only owns data + timers.
|
|
6
7
|
*/
|
|
7
8
|
export type ToastLevel = "info" | "success" | "warn" | "error";
|
|
8
9
|
export interface ToastItem {
|
|
@@ -11,14 +12,21 @@ export interface ToastItem {
|
|
|
11
12
|
readonly level: ToastLevel;
|
|
12
13
|
readonly createdAt: number;
|
|
13
14
|
readonly durationMs: number;
|
|
15
|
+
/** Optional replace key — new shows with the same key dismiss the old one. */
|
|
16
|
+
readonly key?: string | undefined;
|
|
14
17
|
}
|
|
15
18
|
export interface ShowToastOptions {
|
|
16
19
|
readonly level?: ToastLevel | undefined;
|
|
17
|
-
/** Visible lifetime
|
|
20
|
+
/** Visible lifetime; default 1800ms. */
|
|
18
21
|
readonly durationMs?: number | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Replace any existing toast with this key (e.g. "thinking", "scroll").
|
|
24
|
+
* Prevents spam when the user hammers a toggle.
|
|
25
|
+
*/
|
|
26
|
+
readonly key?: string | undefined;
|
|
19
27
|
}
|
|
20
28
|
export type ToastListener = () => void;
|
|
21
|
-
export declare const DEFAULT_TOAST_DURATION_MS =
|
|
29
|
+
export declare const DEFAULT_TOAST_DURATION_MS = 1800;
|
|
22
30
|
export declare class ToastController {
|
|
23
31
|
private items;
|
|
24
32
|
private readonly timers;
|
|
@@ -28,6 +36,10 @@ export declare class ToastController {
|
|
|
28
36
|
getToasts(): readonly ToastItem[];
|
|
29
37
|
subscribe(listener: ToastListener): () => void;
|
|
30
38
|
show(message: string, options?: ShowToastOptions): string;
|
|
39
|
+
info(message: string, options?: Omit<ShowToastOptions, "level">): string;
|
|
40
|
+
success(message: string, options?: Omit<ShowToastOptions, "level">): string;
|
|
41
|
+
warn(message: string, options?: Omit<ShowToastOptions, "level">): string;
|
|
42
|
+
error(message: string, options?: Omit<ShowToastOptions, "level">): string;
|
|
31
43
|
dismiss(id: string): void;
|
|
32
44
|
clear(): void;
|
|
33
45
|
dispose(): void;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Ephemeral
|
|
2
|
+
* Ephemeral toast queue (UI chrome, not transcript history).
|
|
3
3
|
*
|
|
4
|
-
* Toasts auto-dismiss after a short TTL
|
|
5
|
-
*
|
|
4
|
+
* Toasts auto-dismiss after a short TTL. Same-key shows replace the previous
|
|
5
|
+
* toast so rapid toggles (thinking / output / scroll) do not stack noise.
|
|
6
|
+
* The host owns layout; this controller only owns data + timers.
|
|
6
7
|
*/
|
|
7
|
-
export const DEFAULT_TOAST_DURATION_MS =
|
|
8
|
-
const MAX_VISIBLE_TOASTS =
|
|
8
|
+
export const DEFAULT_TOAST_DURATION_MS = 1800;
|
|
9
|
+
const MAX_VISIBLE_TOASTS = 3;
|
|
10
|
+
const MAX_MESSAGE_CHARS = 72;
|
|
9
11
|
export class ToastController {
|
|
10
12
|
items = [];
|
|
11
13
|
timers = new Map();
|
|
@@ -25,6 +27,16 @@ export class ToastController {
|
|
|
25
27
|
const text = message.replace(/\s+/g, " ").trim();
|
|
26
28
|
if (!text)
|
|
27
29
|
return "";
|
|
30
|
+
const key = typeof options.key === "string" && options.key.trim()
|
|
31
|
+
? options.key.trim()
|
|
32
|
+
: undefined;
|
|
33
|
+
// Replace prior toast with the same key (toggle spam).
|
|
34
|
+
if (key) {
|
|
35
|
+
for (const existing of this.items) {
|
|
36
|
+
if (existing.key === key)
|
|
37
|
+
this.dismiss(existing.id);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
28
40
|
const id = `toast-${++this.seq}`;
|
|
29
41
|
const durationMs = typeof options.durationMs === "number" &&
|
|
30
42
|
Number.isFinite(options.durationMs) &&
|
|
@@ -33,13 +45,15 @@ export class ToastController {
|
|
|
33
45
|
: DEFAULT_TOAST_DURATION_MS;
|
|
34
46
|
const item = {
|
|
35
47
|
id,
|
|
36
|
-
message: text.length >
|
|
48
|
+
message: text.length > MAX_MESSAGE_CHARS
|
|
49
|
+
? `${text.slice(0, MAX_MESSAGE_CHARS - 1)}…`
|
|
50
|
+
: text,
|
|
37
51
|
level: options.level ?? "info",
|
|
38
52
|
createdAt: Date.now(),
|
|
39
53
|
durationMs,
|
|
54
|
+
...(key ? { key } : {}),
|
|
40
55
|
};
|
|
41
56
|
this.items = [...this.items, item].slice(-MAX_VISIBLE_TOASTS);
|
|
42
|
-
// Drop timers for items that fell off the cap.
|
|
43
57
|
for (const [timerId, timer] of this.timers) {
|
|
44
58
|
if (!this.items.some((t) => t.id === timerId)) {
|
|
45
59
|
clearTimeout(timer);
|
|
@@ -52,6 +66,18 @@ export class ToastController {
|
|
|
52
66
|
this.emit();
|
|
53
67
|
return id;
|
|
54
68
|
}
|
|
69
|
+
info(message, options = {}) {
|
|
70
|
+
return this.show(message, { ...options, level: "info" });
|
|
71
|
+
}
|
|
72
|
+
success(message, options = {}) {
|
|
73
|
+
return this.show(message, { ...options, level: "success" });
|
|
74
|
+
}
|
|
75
|
+
warn(message, options = {}) {
|
|
76
|
+
return this.show(message, { ...options, level: "warn" });
|
|
77
|
+
}
|
|
78
|
+
error(message, options = {}) {
|
|
79
|
+
return this.show(message, { ...options, level: "error" });
|
|
80
|
+
}
|
|
55
81
|
dismiss(id) {
|
|
56
82
|
const timer = this.timers.get(id);
|
|
57
83
|
if (timer) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toast-controller.js","sourceRoot":"","sources":["../../../src/tui-v2/controllers/toast-controller.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"toast-controller.js","sourceRoot":"","sources":["../../../src/tui-v2/controllers/toast-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ephemeral UI notifications via the toast stack.
|
|
3
|
+
*
|
|
4
|
+
* Prefer this over session.notice for chrome feedback (toggles, jumps, clear)
|
|
5
|
+
* so the transcript is not filled with UI chatter. Use session.notice for
|
|
6
|
+
* durable session/mode/config facts that should stay in chat history.
|
|
7
|
+
*/
|
|
8
|
+
import type { ToastController, ToastLevel } from "./controllers/toast-controller.js";
|
|
9
|
+
export interface NotifyTarget {
|
|
10
|
+
readonly toast: ToastController;
|
|
11
|
+
}
|
|
12
|
+
export interface NotifyOptions {
|
|
13
|
+
readonly level?: ToastLevel | undefined;
|
|
14
|
+
readonly durationMs?: number | undefined;
|
|
15
|
+
readonly key?: string | undefined;
|
|
16
|
+
}
|
|
17
|
+
/** Show a short toast. Empty messages are no-ops. */
|
|
18
|
+
export declare function notify(services: NotifyTarget, message: string, options?: NotifyOptions): void;
|
|
19
|
+
export declare function notifySuccess(services: NotifyTarget, message: string, options?: Omit<NotifyOptions, "level">): void;
|
|
20
|
+
export declare function notifyWarn(services: NotifyTarget, message: string, options?: Omit<NotifyOptions, "level">): void;
|
|
21
|
+
export declare function notifyError(services: NotifyTarget, message: string, options?: Omit<NotifyOptions, "level">): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ephemeral UI notifications via the toast stack.
|
|
3
|
+
*
|
|
4
|
+
* Prefer this over session.notice for chrome feedback (toggles, jumps, clear)
|
|
5
|
+
* so the transcript is not filled with UI chatter. Use session.notice for
|
|
6
|
+
* durable session/mode/config facts that should stay in chat history.
|
|
7
|
+
*/
|
|
8
|
+
/** Show a short toast. Empty messages are no-ops. */
|
|
9
|
+
export function notify(services, message, options = {}) {
|
|
10
|
+
services.toast.show(message, {
|
|
11
|
+
level: options.level ?? "info",
|
|
12
|
+
...(options.durationMs !== undefined
|
|
13
|
+
? { durationMs: options.durationMs }
|
|
14
|
+
: {}),
|
|
15
|
+
...(options.key !== undefined ? { key: options.key } : {}),
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export function notifySuccess(services, message, options = {}) {
|
|
19
|
+
notify(services, message, { ...options, level: "success" });
|
|
20
|
+
}
|
|
21
|
+
export function notifyWarn(services, message, options = {}) {
|
|
22
|
+
notify(services, message, { ...options, level: "warn" });
|
|
23
|
+
}
|
|
24
|
+
export function notifyError(services, message, options = {}) {
|
|
25
|
+
notify(services, message, { ...options, level: "error" });
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=notify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/tui-v2/notify.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAcH,qDAAqD;AACrD,MAAM,UAAU,MAAM,CACpB,QAAsB,EACtB,OAAe,EACf,UAAyB,EAAE;IAE3B,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE;QAC3B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,MAAM;QAC9B,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS;YAClC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE;YACpC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,OAAO,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3D,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,QAAsB,EACtB,OAAe,EACf,UAAwC,EAAE;IAE1C,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,QAAsB,EACtB,OAAe,EACf,UAAwC,EAAE;IAE1C,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,QAAsB,EACtB,OAAe,EACf,UAAwC,EAAE;IAE1C,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown body for `/help` and Ctrl+G command reference.
|
|
3
|
+
*
|
|
4
|
+
* Uses bullet lists (not tables): usage strings often contain `|` and `<>`
|
|
5
|
+
* which break markdown table cell parsing in our renderer (even when escaped).
|
|
6
|
+
*/
|
|
7
|
+
import type { CommandHelpEntry } from "../../app/commands/registry.js";
|
|
8
|
+
/**
|
|
9
|
+
* Format one command as a markdown list item.
|
|
10
|
+
* Command + usage stay in a single backtick span so `|` / `<>` are literal.
|
|
11
|
+
*/
|
|
12
|
+
export declare function formatHelpEntry(entry: CommandHelpEntry): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format the slash-command catalog as a clean markdown reference.
|
|
15
|
+
*/
|
|
16
|
+
export declare function formatCommandHelpMarkdown(entries: readonly CommandHelpEntry[]): string;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown body for `/help` and Ctrl+G command reference.
|
|
3
|
+
*
|
|
4
|
+
* Uses bullet lists (not tables): usage strings often contain `|` and `<>`
|
|
5
|
+
* which break markdown table cell parsing in our renderer (even when escaped).
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Group slash commands into readable sections by prefix / role.
|
|
9
|
+
*/
|
|
10
|
+
function sectionFor(command) {
|
|
11
|
+
const name = command.replace(/^\//, "").toLowerCase();
|
|
12
|
+
if (["ask", "agent", "plan", "implement", "discard"].includes(name)) {
|
|
13
|
+
return "Mode & plan";
|
|
14
|
+
}
|
|
15
|
+
if (["model", "provider", "use", "search", "search-provider", "variants", "reasoning"].includes(name)) {
|
|
16
|
+
return "Model & providers";
|
|
17
|
+
}
|
|
18
|
+
if (["set", "unset", "keys", "info"].includes(name)) {
|
|
19
|
+
return "Credentials";
|
|
20
|
+
}
|
|
21
|
+
if (["permissions", "allow", "disallow", "freeonly", "fallback", "mouse", "scope", "privacy"].includes(name)) {
|
|
22
|
+
return "Permissions & safety";
|
|
23
|
+
}
|
|
24
|
+
if (["history", "clear", "new", "clean", "save", "reset", "compact", "context", "think", "thinking", "output", "cwd"].includes(name)) {
|
|
25
|
+
return "Session";
|
|
26
|
+
}
|
|
27
|
+
if (["jobs", "update", "help", "shortcuts", "exit", "quit"].includes(name)) {
|
|
28
|
+
return "App";
|
|
29
|
+
}
|
|
30
|
+
return "Other";
|
|
31
|
+
}
|
|
32
|
+
const SECTION_ORDER = [
|
|
33
|
+
"Mode & plan",
|
|
34
|
+
"Model & providers",
|
|
35
|
+
"Credentials",
|
|
36
|
+
"Permissions & safety",
|
|
37
|
+
"Session",
|
|
38
|
+
"App",
|
|
39
|
+
"Other",
|
|
40
|
+
];
|
|
41
|
+
/** Collapse whitespace so a command never splits mid-token in the pager. */
|
|
42
|
+
function oneLine(text) {
|
|
43
|
+
return text.replace(/\s+/g, " ").trim();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Format one command as a markdown list item.
|
|
47
|
+
* Command + usage stay in a single backtick span so `|` / `<>` are literal.
|
|
48
|
+
*/
|
|
49
|
+
export function formatHelpEntry(entry) {
|
|
50
|
+
const usage = entry.usage ? ` ${oneLine(entry.usage)}` : "";
|
|
51
|
+
const cmd = oneLine(`${entry.command}${usage}`);
|
|
52
|
+
let desc = oneLine(entry.description);
|
|
53
|
+
if (entry.aliases.length > 0) {
|
|
54
|
+
const aliasList = entry.aliases.map((a) => `\`${oneLine(a)}\``).join(", ");
|
|
55
|
+
desc += ` · aliases: ${aliasList}`;
|
|
56
|
+
}
|
|
57
|
+
// Em dash between command and description — no table pipes.
|
|
58
|
+
return `- \`${cmd}\` — ${desc}`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Format the slash-command catalog as a clean markdown reference.
|
|
62
|
+
*/
|
|
63
|
+
export function formatCommandHelpMarkdown(entries) {
|
|
64
|
+
const bySection = new Map();
|
|
65
|
+
for (const e of entries) {
|
|
66
|
+
const sec = sectionFor(e.command);
|
|
67
|
+
const list = bySection.get(sec) ?? [];
|
|
68
|
+
list.push(e);
|
|
69
|
+
bySection.set(sec, list);
|
|
70
|
+
}
|
|
71
|
+
const out = [
|
|
72
|
+
"# Commands",
|
|
73
|
+
"",
|
|
74
|
+
"Type a command in the composer, or open the completion menu with `/`.",
|
|
75
|
+
"Also: **Ctrl+G** opens this help · **`/shortcuts`** lists keyboard chords.",
|
|
76
|
+
"",
|
|
77
|
+
];
|
|
78
|
+
for (const sec of SECTION_ORDER) {
|
|
79
|
+
const list = bySection.get(sec);
|
|
80
|
+
if (!list || list.length === 0)
|
|
81
|
+
continue;
|
|
82
|
+
out.push(`## ${sec}`);
|
|
83
|
+
out.push("");
|
|
84
|
+
const sorted = [...list].sort((a, b) => a.command.localeCompare(b.command));
|
|
85
|
+
for (const e of sorted) {
|
|
86
|
+
out.push(formatHelpEntry(e));
|
|
87
|
+
}
|
|
88
|
+
out.push("");
|
|
89
|
+
}
|
|
90
|
+
out.push("---");
|
|
91
|
+
out.push("");
|
|
92
|
+
out.push("Tip: `q` / `Esc` closes · `↑↓` scroll · `^r` search this page.");
|
|
93
|
+
return out.join("\n");
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=format-help.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format-help.js","sourceRoot":"","sources":["../../../src/tui-v2/rendering/format-help.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe markdown preparation for the full-screen pager.
|
|
3
|
+
*
|
|
4
|
+
* - Markdown docs (help, shortcuts, plan) force-render with classic parity.
|
|
5
|
+
* - Tool / log / plain bodies use a conservative heuristic so normal output
|
|
6
|
+
* is not mangled by italic underscores or stray asterisks.
|
|
7
|
+
* - Any render failure falls back to plain lines (never throws into the UI).
|
|
8
|
+
*/
|
|
9
|
+
import { renderMarkdownLines } from "./render-markdown-lines.js";
|
|
10
|
+
export type PagerMarkdownMode = "auto" | "force" | "plain";
|
|
11
|
+
/** Opaque styled line from renderMarkdownLines (avoids @opentui import here). */
|
|
12
|
+
export type PagerStyledLine = ReturnType<typeof renderMarkdownLines>[number];
|
|
13
|
+
export interface PagerDisplayLine {
|
|
14
|
+
/** Plain text used for search, line counts, and export fallbacks. */
|
|
15
|
+
readonly plain: string;
|
|
16
|
+
/**
|
|
17
|
+
* Pre-styled line when markdown rendered successfully.
|
|
18
|
+
* Undefined → paint as plain `plain` with baseLineFg heuristics.
|
|
19
|
+
*/
|
|
20
|
+
readonly styled?: PagerStyledLine | undefined;
|
|
21
|
+
}
|
|
22
|
+
export interface PreparePagerDisplayOptions {
|
|
23
|
+
readonly body: string;
|
|
24
|
+
readonly width: number;
|
|
25
|
+
readonly mode?: PagerMarkdownMode | undefined;
|
|
26
|
+
/** Default body foreground when markdown renders (theme.foreground). */
|
|
27
|
+
readonly defaultFg?: string | undefined;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Conservative detector: only claim "markdown" when structure is clear.
|
|
31
|
+
* Avoids mangling paths_with_underscores and shell output with * globs.
|
|
32
|
+
*/
|
|
33
|
+
export declare function looksLikeMarkdown(text: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Prepare body lines for the pager. Never throws.
|
|
36
|
+
*/
|
|
37
|
+
export declare function preparePagerDisplay(options: PreparePagerDisplayOptions): {
|
|
38
|
+
readonly mode: "markdown" | "plain";
|
|
39
|
+
readonly lines: readonly PagerDisplayLine[];
|
|
40
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe markdown preparation for the full-screen pager.
|
|
3
|
+
*
|
|
4
|
+
* - Markdown docs (help, shortcuts, plan) force-render with classic parity.
|
|
5
|
+
* - Tool / log / plain bodies use a conservative heuristic so normal output
|
|
6
|
+
* is not mangled by italic underscores or stray asterisks.
|
|
7
|
+
* - Any render failure falls back to plain lines (never throws into the UI).
|
|
8
|
+
*/
|
|
9
|
+
import { renderMarkdownLines } from "./render-markdown-lines.js";
|
|
10
|
+
import { sanitizeDisplayText } from "./sanitize-display.js";
|
|
11
|
+
/**
|
|
12
|
+
* Conservative detector: only claim "markdown" when structure is clear.
|
|
13
|
+
* Avoids mangling paths_with_underscores and shell output with * globs.
|
|
14
|
+
*/
|
|
15
|
+
export function looksLikeMarkdown(text) {
|
|
16
|
+
if (!text || text.length < 8)
|
|
17
|
+
return false;
|
|
18
|
+
let score = 0;
|
|
19
|
+
if (/^#{1,6}\s+\S/m.test(text))
|
|
20
|
+
score += 2;
|
|
21
|
+
if (/^```[\w-]*\s*$/m.test(text))
|
|
22
|
+
score += 2;
|
|
23
|
+
if (/^\|.+\|/m.test(text) && /^\|?[\s:|-]{3,}/m.test(text))
|
|
24
|
+
score += 2;
|
|
25
|
+
if (/^>\s+\S/m.test(text))
|
|
26
|
+
score += 1;
|
|
27
|
+
// Multiple bold spans or list items separated by blank lines
|
|
28
|
+
const bold = text.match(/\*\*[^*\n]{1,80}\*\*/g);
|
|
29
|
+
if (bold && bold.length >= 2)
|
|
30
|
+
score += 1;
|
|
31
|
+
if (/^[-*]\s+\S.+\n\n/m.test(text) || /^\d+\.\s+\S.+\n\n/m.test(text)) {
|
|
32
|
+
score += 1;
|
|
33
|
+
}
|
|
34
|
+
// Explicit horizontal rules common in our docs
|
|
35
|
+
if (/^---+\s*$/m.test(text) || /^\*\*\*+\s*$/m.test(text))
|
|
36
|
+
score += 1;
|
|
37
|
+
return score >= 2;
|
|
38
|
+
}
|
|
39
|
+
function plainLines(body) {
|
|
40
|
+
const raw = body.replace(/\n+$/, "");
|
|
41
|
+
if (!raw)
|
|
42
|
+
return [{ plain: " " }];
|
|
43
|
+
return raw.split("\n").map((line) => ({ plain: line.length === 0 ? " " : line }));
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Prepare body lines for the pager. Never throws.
|
|
47
|
+
*/
|
|
48
|
+
export function preparePagerDisplay(options) {
|
|
49
|
+
const mode = options.mode ?? "auto";
|
|
50
|
+
const body = options.body ?? "";
|
|
51
|
+
const width = Math.max(24, options.width);
|
|
52
|
+
if (mode === "plain") {
|
|
53
|
+
return { mode: "plain", lines: plainLines(body) };
|
|
54
|
+
}
|
|
55
|
+
const wantMarkdown = mode === "force" || (mode === "auto" && looksLikeMarkdown(body));
|
|
56
|
+
if (!wantMarkdown) {
|
|
57
|
+
return { mode: "plain", lines: plainLines(body) };
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const styled = renderMarkdownLines(body, {
|
|
61
|
+
width,
|
|
62
|
+
defaultFg: options.defaultFg,
|
|
63
|
+
stripOuterIndent: true,
|
|
64
|
+
});
|
|
65
|
+
if (styled.length === 0) {
|
|
66
|
+
return { mode: "plain", lines: plainLines(body) };
|
|
67
|
+
}
|
|
68
|
+
const lines = styled.map((st) => {
|
|
69
|
+
// Join styled chunks for search/highlight. Sanitize so no CSI leaks into
|
|
70
|
+
// the plain path (would blank the terminal when painting as raw text).
|
|
71
|
+
const joined = st.chunks.map((c) => c.text).join("");
|
|
72
|
+
const plain = sanitizeDisplayText(joined) || " ";
|
|
73
|
+
return { plain, styled: st };
|
|
74
|
+
});
|
|
75
|
+
return { mode: "markdown", lines };
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Never let a markdown bug blank the pager.
|
|
79
|
+
return { mode: "plain", lines: plainLines(body) };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=pager-markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pager-markdown.js","sourceRoot":"","sources":["../../../src/tui-v2/rendering/pager-markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -47,7 +47,6 @@ export declare function wrapPlanText(text: string, width: number): string[];
|
|
|
47
47
|
export declare function cleanTaskTitle(task: PlanTask): string;
|
|
48
48
|
/**
|
|
49
49
|
* Full plan body for the OpenTUI pager (Ctrl+P / /plan).
|
|
50
|
-
*
|
|
51
|
-
* Tasks are card-like blocks with clear rules between them.
|
|
50
|
+
* Markdown so the pager renders headings, tables, and lists cleanly.
|
|
52
51
|
*/
|
|
53
52
|
export declare function formatPlanPagerDocument(plan: SessionPlan): string;
|