@travisennis/acai 0.0.10 → 0.0.12
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/agent/index.d.ts.map +1 -1
- package/dist/agent/index.js +29 -27
- package/dist/cli/stdin.d.ts +2 -1
- package/dist/cli/stdin.d.ts.map +1 -1
- package/dist/commands/generate-rules/service.d.ts +3 -2
- package/dist/commands/generate-rules/service.d.ts.map +1 -1
- package/dist/commands/health/utils.d.ts +3 -2
- package/dist/commands/health/utils.d.ts.map +1 -1
- package/dist/commands/init-project/utils.d.ts +2 -1
- package/dist/commands/init-project/utils.d.ts.map +1 -1
- package/dist/commands/init-project/utils.js +0 -11
- package/dist/commands/manager.d.ts.map +1 -1
- package/dist/commands/manager.js +6 -1
- package/dist/commands/resources/index.d.ts.map +1 -1
- package/dist/commands/resources/index.js +4 -1
- package/dist/commands/review/utils.d.ts +6 -1
- package/dist/commands/review/utils.d.ts.map +1 -1
- package/dist/commands/session/index.d.ts.map +1 -1
- package/dist/commands/session/index.js +6 -0
- package/dist/commands/session/types.d.ts +1 -0
- package/dist/commands/session/types.d.ts.map +1 -1
- package/dist/commands/tools/index.d.ts +3 -0
- package/dist/commands/tools/index.d.ts.map +1 -0
- package/dist/commands/tools/index.js +190 -0
- package/dist/commands/tools/templates.d.ts +6 -0
- package/dist/commands/tools/templates.d.ts.map +1 -0
- package/dist/commands/tools/templates.js +97 -0
- package/dist/config/index.d.ts +5 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +41 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -3
- package/dist/models/anthropic-provider.d.ts +1 -1
- package/dist/models/deepseek-provider.d.ts +3 -3
- package/dist/models/deepseek-provider.js +17 -17
- package/dist/models/google-provider.d.ts +2 -4
- package/dist/models/google-provider.d.ts.map +1 -1
- package/dist/models/google-provider.js +2 -17
- package/dist/models/groq-provider.d.ts +2 -4
- package/dist/models/groq-provider.d.ts.map +1 -1
- package/dist/models/groq-provider.js +3 -21
- package/dist/models/opencode-go-provider.d.ts +35 -0
- package/dist/models/opencode-go-provider.d.ts.map +1 -0
- package/dist/models/opencode-go-provider.js +214 -0
- package/dist/models/opencode-zen-provider.d.ts +5 -5
- package/dist/models/opencode-zen-provider.d.ts.map +1 -1
- package/dist/models/opencode-zen-provider.js +41 -47
- package/dist/models/openrouter-provider.d.ts +5 -13
- package/dist/models/openrouter-provider.d.ts.map +1 -1
- package/dist/models/openrouter-provider.js +34 -138
- package/dist/models/providers.d.ts +3 -3
- package/dist/models/providers.d.ts.map +1 -1
- package/dist/models/providers.js +6 -0
- package/dist/models/xai-provider.d.ts +1 -2
- package/dist/models/xai-provider.d.ts.map +1 -1
- package/dist/models/xai-provider.js +0 -13
- package/dist/prompts/manager.d.ts.map +1 -1
- package/dist/prompts/manager.js +5 -1
- package/dist/prompts/mentions.d.ts.map +1 -1
- package/dist/prompts/mentions.js +35 -6
- package/dist/prompts/system-prompt.d.ts +1 -0
- package/dist/prompts/system-prompt.d.ts.map +1 -1
- package/dist/prompts/system-prompt.js +20 -5
- package/dist/repl/index.d.ts +1 -2
- package/dist/repl/index.d.ts.map +1 -1
- package/dist/repl/index.js +14 -53
- package/dist/sessions/manager.d.ts +3 -3
- package/dist/sessions/manager.d.ts.map +1 -1
- package/dist/sessions/manager.js +1 -1
- package/dist/skills/activated-tracker.d.ts +11 -0
- package/dist/skills/activated-tracker.d.ts.map +1 -0
- package/dist/skills/activated-tracker.js +16 -0
- package/dist/skills/index.d.ts +3 -2
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +7 -1
- package/dist/subagents/index.d.ts +2 -1
- package/dist/subagents/index.d.ts.map +1 -1
- package/dist/terminal/table/utils.d.ts +1 -1
- package/dist/terminal/table/utils.d.ts.map +1 -1
- package/dist/terminal/wrap-ansi.js +2 -2
- package/dist/tools/agent.js +1 -1
- package/dist/tools/apply-patch.d.ts +62 -0
- package/dist/tools/apply-patch.d.ts.map +1 -0
- package/dist/tools/apply-patch.js +377 -0
- package/dist/tools/bash.d.ts +4 -4
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +40 -8
- package/dist/tools/directory-tree.d.ts +4 -4
- package/dist/tools/directory-tree.d.ts.map +1 -1
- package/dist/tools/directory-tree.js +3 -1
- package/dist/tools/dynamic-tool-loader.d.ts +12 -3
- package/dist/tools/dynamic-tool-loader.d.ts.map +1 -1
- package/dist/tools/dynamic-tool-loader.js +299 -39
- package/dist/tools/edit-file.d.ts +2 -2
- package/dist/tools/edit-file.d.ts.map +1 -1
- package/dist/tools/edit-file.js +188 -79
- package/dist/tools/glob.d.ts +16 -16
- package/dist/tools/glob.d.ts.map +1 -1
- package/dist/tools/glob.js +30 -15
- package/dist/tools/grep.d.ts +14 -14
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +50 -29
- package/dist/tools/index.d.ts +57 -84
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +20 -5
- package/dist/tools/ls.d.ts +2 -2
- package/dist/tools/ls.d.ts.map +1 -1
- package/dist/tools/ls.js +2 -1
- package/dist/tools/read-file.d.ts +9 -11
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +21 -16
- package/dist/tools/save-file.d.ts +4 -4
- package/dist/tools/save-file.d.ts.map +1 -1
- package/dist/tools/save-file.js +26 -21
- package/dist/tools/skill.d.ts +2 -1
- package/dist/tools/skill.d.ts.map +1 -1
- package/dist/tools/skill.js +55 -12
- package/dist/tools/types.d.ts +8 -2
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/web-fetch.d.ts +6 -18
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +45 -9
- package/dist/tools/web-search.d.ts +4 -22
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +1 -1
- package/dist/tui/autocomplete/file-search-provider.js +1 -1
- package/dist/tui/autocomplete/utils.d.ts +2 -1
- package/dist/tui/autocomplete/utils.d.ts.map +1 -1
- package/dist/tui/autocomplete/utils.js +25 -23
- package/dist/tui/components/editor.d.ts +2 -1
- package/dist/tui/components/editor.d.ts.map +1 -1
- package/dist/tui/components/editor.js +1 -1
- package/dist/tui/components/footer.d.ts +0 -2
- package/dist/tui/components/footer.d.ts.map +1 -1
- package/dist/tui/components/footer.js +1 -17
- package/dist/tui/components/markdown.d.ts +2 -2
- package/dist/tui/components/markdown.d.ts.map +1 -1
- package/dist/tui/components/welcome.d.ts +2 -1
- package/dist/tui/components/welcome.d.ts.map +1 -1
- package/dist/tui/editor-launcher.d.ts +3 -2
- package/dist/tui/editor-launcher.d.ts.map +1 -1
- package/dist/tui/index.d.ts +0 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/tui.d.ts +1 -0
- package/dist/tui/tui.d.ts.map +1 -1
- package/dist/tui/tui.js +9 -0
- package/dist/tui/utils.d.ts +1 -5
- package/dist/tui/utils.d.ts.map +1 -1
- package/dist/tui/utils.js +271 -44
- package/dist/utils/binary-output.d.ts +32 -0
- package/dist/utils/binary-output.d.ts.map +1 -0
- package/dist/utils/binary-output.js +127 -0
- package/dist/utils/command-protection.d.ts.map +1 -1
- package/dist/utils/command-protection.js +92 -9
- package/dist/utils/parsing.d.ts +1 -1
- package/dist/utils/parsing.d.ts.map +1 -1
- package/package.json +28 -26
- package/dist/commands/add-directory/types.d.ts +0 -6
- package/dist/commands/add-directory/types.d.ts.map +0 -1
- package/dist/commands/add-directory/types.js +0 -1
- package/dist/commands/copy/types.d.ts +0 -3
- package/dist/commands/copy/types.d.ts.map +0 -1
- package/dist/commands/copy/types.js +0 -1
- package/dist/commands/review/types.d.ts +0 -12
- package/dist/commands/review/types.d.ts.map +0 -1
- package/dist/commands/review/types.js +0 -1
- package/dist/modes/manager.d.ts +0 -23
- package/dist/modes/manager.d.ts.map +0 -1
- package/dist/modes/manager.js +0 -77
- package/dist/modes/prompts.d.ts +0 -2
- package/dist/modes/prompts.d.ts.map +0 -1
- package/dist/modes/prompts.js +0 -143
- package/dist/tools/code-search.d.ts +0 -41
- package/dist/tools/code-search.d.ts.map +0 -1
- package/dist/tools/code-search.js +0 -195
- package/dist/utils/iterables.d.ts +0 -2
- package/dist/utils/iterables.d.ts.map +0 -1
- package/dist/utils/iterables.js +0 -6
|
@@ -5,7 +5,7 @@ type Color = "black" | "red" | "green" | "yellow" | "blue" | "magenta" | "cyan"
|
|
|
5
5
|
* Theme functions for markdown elements.
|
|
6
6
|
* Each function takes text and returns styled text with ANSI codes.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
interface MarkdownTheme {
|
|
9
9
|
heading: (text: string) => string;
|
|
10
10
|
paragraph: (text: string) => string;
|
|
11
11
|
link: (text: string) => string;
|
|
@@ -25,7 +25,7 @@ export interface MarkdownTheme {
|
|
|
25
25
|
/**
|
|
26
26
|
* Options for configuring Markdown component
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
interface MarkdownOptions {
|
|
29
29
|
/** Background color */
|
|
30
30
|
bgColor?: Color;
|
|
31
31
|
/** Custom background RGB color */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../source/tui/components/markdown.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mCAAmC,CAAC;AAM/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C,KAAK,KAAK,GACN,OAAO,GACP,KAAK,GACL,OAAO,GACP,QAAQ,GACR,MAAM,GACN,SAAS,GACT,MAAM,GACN,OAAO,GACP,MAAM,GACN,SAAS,GACT,OAAO,GACP,SAAS,GACT,UAAU,GACV,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,SAAS,GACT,QAAQ,CAAC;AAEb;;;GAGG;AACH,
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../../source/tui/components/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Component } from "../tui.ts";
|
|
2
|
-
|
|
2
|
+
interface WelcomeOptions {
|
|
3
3
|
type?: "default" | "simple";
|
|
4
4
|
}
|
|
5
5
|
export declare class Welcome implements Component {
|
|
@@ -10,4 +10,5 @@ export declare class Welcome implements Component {
|
|
|
10
10
|
private renderDefault;
|
|
11
11
|
private getLogo;
|
|
12
12
|
}
|
|
13
|
+
export {};
|
|
13
14
|
//# sourceMappingURL=welcome.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../../source/tui/components/welcome.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C,
|
|
1
|
+
{"version":3,"file":"welcome.d.ts","sourceRoot":"","sources":["../../../source/tui/components/welcome.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAG3C,UAAU,cAAc;IACtB,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;CAC7B;AAED,qBAAa,OAAQ,YAAW,SAAS;IACvC,OAAO,CAAC,OAAO,CAAiB;gBAEpB,OAAO,GAAE,cAAmB;IAIxC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAQ/B,OAAO,CAAC,YAAY;IA8BpB,OAAO,CAAC,aAAa;IA2BrB,OAAO,CAAC,OAAO;CAUhB"}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { Terminal } from "./terminal.ts";
|
|
2
|
-
|
|
2
|
+
interface EditorLaunchOptions {
|
|
3
3
|
initialContent?: string;
|
|
4
4
|
postfix?: string;
|
|
5
5
|
terminal: Terminal;
|
|
6
6
|
signal?: AbortSignal;
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
interface EditorLaunchResult {
|
|
9
9
|
content: string;
|
|
10
10
|
aborted: boolean;
|
|
11
11
|
}
|
|
12
12
|
export declare function launchEditor(options: EditorLaunchOptions): Promise<EditorLaunchResult>;
|
|
13
|
+
export {};
|
|
13
14
|
//# sourceMappingURL=editor-launcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"editor-launcher.d.ts","sourceRoot":"","sources":["../../source/tui/editor-launcher.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,
|
|
1
|
+
{"version":3,"file":"editor-launcher.d.ts","sourceRoot":"","sources":["../../source/tui/editor-launcher.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,UAAU,mBAAmB;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,UAAU,kBAAkB;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,CA0C7B"}
|
package/dist/tui/index.d.ts
CHANGED
|
@@ -14,7 +14,6 @@ export { Spacer } from "./components/spacer.ts";
|
|
|
14
14
|
export { TableComponent } from "./components/table.ts";
|
|
15
15
|
export { Text } from "./components/text.ts";
|
|
16
16
|
export { UserMessageComponent } from "./components/user-message.ts";
|
|
17
|
-
export type { EditorLaunchOptions, EditorLaunchResult, } from "./editor-launcher.ts";
|
|
18
17
|
export { launchEditor } from "./editor-launcher.ts";
|
|
19
18
|
export { ProcessTerminal, type ProcessTerminalOptions } from "./terminal.ts";
|
|
20
19
|
export { Container, TUI } from "./tui.ts";
|
package/dist/tui/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/tui/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,IAAI,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAEvG,YAAY,EACV,gBAAgB,EAChB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../source/tui/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,IAAI,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAEvG,YAAY,EACV,gBAAgB,EAChB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/tui/tui.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export declare class Container implements Component {
|
|
|
38
38
|
children: Component[];
|
|
39
39
|
addChild(component: Component): void;
|
|
40
40
|
removeChild(component: Component): void;
|
|
41
|
+
insertChildBefore(beforeComponent: Component, newComponent: Component): void;
|
|
41
42
|
clear(): void;
|
|
42
43
|
render(width: number): string[];
|
|
43
44
|
}
|
package/dist/tui/tui.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../source/tui/tui.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEhC;;OAEG;IACH,WAAW,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC;;;;OAIG;IACH,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAE9C;;;OAGG;IACH,mBAAmB,CAAC,IAAI,OAAO,CAAC;CACjC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,qBAAa,SAAU,YAAW,SAAS;IACzC,QAAQ,EAAE,SAAS,EAAE,CAAM;IAE3B,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAIpC,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAOvC,KAAK,IAAI,IAAI;IAIb,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAGhC;AAED;;;;;;;;;;GAUG;AAGH,qBAAa,GAAI,SAAQ,SAAS;IAChC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IAE1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,sEAAsE;IAC/D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;gBAEnB,QAAQ,EAAE,QAAQ;IAK9B;;;;OAIG;IACH,mBAAmB,IAAI,IAAI;IAI3B,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IAI3C;;;OAGG;IACH,WAAW,IAAI,QAAQ;IAIvB,KAAK,IAAI,IAAI;IAUb,IAAI,IAAI,IAAI;IAKZ,aAAa,IAAI,IAAI;IAarB,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,+BAA+B;IAIvC,OAAO,CAAC,WAAW;IAyFnB,OAAO,CAAC,gBAAgB;IAiCxB,cAAc,IAAI,IAAI;IAWtB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,uBAAuB;IAU/B,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,QAAQ;IAoFhB;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAK7B;;OAEG;IACH,SAAS,IAAI,IAAI;IAKjB;;OAEG;IACH,aAAa,IAAI,OAAO;CAGzB"}
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../source/tui/tui.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAEhC;;OAEG;IACH,WAAW,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAEjC;;;;OAIG;IACH,iBAAiB,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAE9C;;;OAGG;IACH,mBAAmB,CAAC,IAAI,OAAO,CAAC;CACjC;AAED,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;GAEG;AACH,qBAAa,SAAU,YAAW,SAAS;IACzC,QAAQ,EAAE,SAAS,EAAE,CAAM;IAE3B,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAIpC,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI;IAOvC,iBAAiB,CAAC,eAAe,EAAE,SAAS,EAAE,YAAY,EAAE,SAAS,GAAG,IAAI;IAS5E,KAAK,IAAI,IAAI;IAIb,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;CAGhC;AAED;;;;;;;;;;GAUG;AAGH,qBAAa,GAAI,SAAQ,SAAS;IAChC,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,gBAAgB,CAA0B;IAClD,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAsB;IACzC,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,gBAAgB,CAAM;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IAE1B,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,IAAI,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,sEAAsE;IAC/D,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;gBAEnB,QAAQ,EAAE,QAAQ;IAK9B;;;;OAIG;IACH,mBAAmB,IAAI,IAAI;IAI3B,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI;IAI3C;;;OAGG;IACH,WAAW,IAAI,QAAQ;IAIvB,KAAK,IAAI,IAAI;IAUb,IAAI,IAAI,IAAI;IAKZ,aAAa,IAAI,IAAI;IAarB,OAAO,CAAC,gBAAgB,CAAS;IAEjC,OAAO,CAAC,+BAA+B;IAIvC,OAAO,CAAC,WAAW;IAyFnB,OAAO,CAAC,gBAAgB;IAiCxB,cAAc,IAAI,IAAI;IAWtB,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,uBAAuB;IAU/B,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,QAAQ;IAoFhB;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAK7B;;OAEG;IACH,SAAS,IAAI,IAAI;IAKjB;;OAEG;IACH,aAAa,IAAI,OAAO;CAGzB"}
|
package/dist/tui/tui.js
CHANGED
|
@@ -20,6 +20,15 @@ export class Container {
|
|
|
20
20
|
this.children.splice(index, 1);
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
|
+
insertChildBefore(beforeComponent, newComponent) {
|
|
24
|
+
const index = this.children.indexOf(beforeComponent);
|
|
25
|
+
if (index !== -1) {
|
|
26
|
+
this.children.splice(index, 0, newComponent);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
this.children.push(newComponent);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
23
32
|
clear() {
|
|
24
33
|
this.children = [];
|
|
25
34
|
}
|
package/dist/tui/utils.d.ts
CHANGED
|
@@ -7,11 +7,7 @@
|
|
|
7
7
|
* - Tabs (replaced with 3 spaces for consistent width)
|
|
8
8
|
*/
|
|
9
9
|
export declare function visibleWidth(str: string): number;
|
|
10
|
-
|
|
11
|
-
* Truncate text to fit within a maximum visible width, preserving ANSI codes.
|
|
12
|
-
* Adds ellipsis if truncation occurs.
|
|
13
|
-
*/
|
|
14
|
-
export declare function truncateToWidth(text: string, maxWidth: number, ellipsis?: string): string;
|
|
10
|
+
export declare function truncateToWidth(text: string, maxWidth: number, ellipsis?: string, pad?: boolean): string;
|
|
15
11
|
/**
|
|
16
12
|
* Apply background color to a line, padding to full width.
|
|
17
13
|
*
|
package/dist/tui/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../source/tui/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../source/tui/utils.ts"],"names":[],"mappings":"AAgBA;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIhD;AAwOD,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,QAAQ,SAAQ,EAChB,GAAG,UAAQ,GACV,MAAM,CAuER;AAwHD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAC7B,MAAM,CASR"}
|
package/dist/tui/utils.js
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { getSegmenter } from "../terminal/segmenter.js";
|
|
2
2
|
import stringWidth from "../terminal/string-width.js";
|
|
3
|
+
/**
|
|
4
|
+
* Check if a string contains only printable ASCII characters (0x20-0x7e).
|
|
5
|
+
*/
|
|
6
|
+
function isPrintableAscii(str) {
|
|
7
|
+
for (let i = 0; i < str.length; i++) {
|
|
8
|
+
const code = str.charCodeAt(i);
|
|
9
|
+
if (code < 0x20 || code > 0x7e) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
3
15
|
/**
|
|
4
16
|
* Calculate the visible width of a string in terminal columns.
|
|
5
17
|
* This correctly handles:
|
|
@@ -13,6 +25,12 @@ export function visibleWidth(str) {
|
|
|
13
25
|
const normalized = str.replace(/\t/g, " ");
|
|
14
26
|
return stringWidth(normalized);
|
|
15
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Get the width of a single grapheme cluster.
|
|
30
|
+
*/
|
|
31
|
+
function graphemeWidth(grapheme) {
|
|
32
|
+
return stringWidth(grapheme);
|
|
33
|
+
}
|
|
16
34
|
/**
|
|
17
35
|
* Extract ANSI escape sequences from a string at the given position.
|
|
18
36
|
*/
|
|
@@ -32,64 +50,273 @@ function extractAnsiCode(str, pos) {
|
|
|
32
50
|
}
|
|
33
51
|
return null;
|
|
34
52
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
53
|
+
function createInitialState() {
|
|
54
|
+
return {
|
|
55
|
+
result: "",
|
|
56
|
+
pendingAnsi: "",
|
|
57
|
+
visibleSoFar: 0,
|
|
58
|
+
keptWidth: 0,
|
|
59
|
+
keepContiguousPrefix: true,
|
|
60
|
+
overflowed: false,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function processAnsiCode(state, text, pos) {
|
|
64
|
+
const ansi = extractAnsiCode(text, pos);
|
|
65
|
+
if (ansi) {
|
|
66
|
+
state.pendingAnsi += ansi.code;
|
|
67
|
+
return ansi.length;
|
|
68
|
+
}
|
|
69
|
+
return 0;
|
|
70
|
+
}
|
|
71
|
+
function processTab(state, targetWidth, maxWidth) {
|
|
72
|
+
if (state.keepContiguousPrefix && state.keptWidth + 3 <= targetWidth) {
|
|
73
|
+
if (state.pendingAnsi) {
|
|
74
|
+
state.result += state.pendingAnsi;
|
|
75
|
+
state.pendingAnsi = "";
|
|
76
|
+
}
|
|
77
|
+
state.result += "\t";
|
|
78
|
+
state.keptWidth += 3;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
state.keepContiguousPrefix = false;
|
|
82
|
+
state.pendingAnsi = "";
|
|
83
|
+
}
|
|
84
|
+
state.visibleSoFar += 3;
|
|
85
|
+
if (state.visibleSoFar > maxWidth) {
|
|
86
|
+
state.overflowed = true;
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
function processGraphemeSegment(state, segment, targetWidth, maxWidth) {
|
|
92
|
+
const width = graphemeWidth(segment);
|
|
93
|
+
if (state.keepContiguousPrefix && state.keptWidth + width <= targetWidth) {
|
|
94
|
+
if (state.pendingAnsi) {
|
|
95
|
+
state.result += state.pendingAnsi;
|
|
96
|
+
state.pendingAnsi = "";
|
|
97
|
+
}
|
|
98
|
+
state.result += segment;
|
|
99
|
+
state.keptWidth += width;
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
state.keepContiguousPrefix = false;
|
|
103
|
+
state.pendingAnsi = "";
|
|
104
|
+
}
|
|
105
|
+
state.visibleSoFar += width;
|
|
106
|
+
if (state.visibleSoFar > maxWidth) {
|
|
107
|
+
state.overflowed = true;
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
function truncateSimple(text, targetWidth, maxWidth) {
|
|
113
|
+
const state = createInitialState();
|
|
114
|
+
for (const { segment } of getSegmenter().segment(text)) {
|
|
115
|
+
if (processGraphemeSegment(state, segment, targetWidth, maxWidth)) {
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
result: state.result,
|
|
121
|
+
keptWidth: state.keptWidth,
|
|
122
|
+
overflowed: state.overflowed,
|
|
123
|
+
visibleSoFar: state.visibleSoFar,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
function truncateComplex(text, targetWidth, maxWidth) {
|
|
127
|
+
const state = createInitialState();
|
|
128
|
+
let i = 0;
|
|
129
|
+
while (i < text.length && !state.overflowed) {
|
|
130
|
+
const ansiSkip = processAnsiCode(state, text, i);
|
|
131
|
+
if (ansiSkip > 0) {
|
|
132
|
+
i += ansiSkip;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (text[i] === "\t") {
|
|
136
|
+
if (processTab(state, targetWidth, maxWidth)) {
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
i++;
|
|
140
|
+
continue;
|
|
141
|
+
}
|
|
142
|
+
// Find end of current text segment (until tab or ANSI)
|
|
143
|
+
let end = i;
|
|
144
|
+
while (end < text.length && text[end] !== "\t") {
|
|
145
|
+
const nextAnsi = extractAnsiCode(text, end);
|
|
146
|
+
if (nextAnsi) {
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
end++;
|
|
150
|
+
}
|
|
151
|
+
// Process graphemes in this segment
|
|
152
|
+
for (const { segment } of getSegmenter().segment(text.slice(i, end))) {
|
|
153
|
+
if (processGraphemeSegment(state, segment, targetWidth, maxWidth)) {
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
i = end;
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
result: state.result,
|
|
161
|
+
keptWidth: state.keptWidth,
|
|
162
|
+
overflowed: state.overflowed,
|
|
163
|
+
exhaustedInput: i >= text.length,
|
|
164
|
+
visibleSoFar: state.visibleSoFar,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function handleOversizedEllipsis(text, maxWidth, ellipsis, pad) {
|
|
168
|
+
const textWidth = visibleWidth(text);
|
|
169
|
+
if (textWidth <= maxWidth) {
|
|
170
|
+
return pad ? text + " ".repeat(maxWidth - textWidth) : text;
|
|
171
|
+
}
|
|
172
|
+
const clippedEllipsis = truncateFragmentToWidth(ellipsis, maxWidth);
|
|
173
|
+
if (clippedEllipsis.width === 0) {
|
|
174
|
+
return pad ? " ".repeat(maxWidth) : "";
|
|
175
|
+
}
|
|
176
|
+
return finalizeTruncatedResult("", 0, clippedEllipsis.text, clippedEllipsis.width, maxWidth, pad);
|
|
177
|
+
}
|
|
178
|
+
export function truncateToWidth(text, maxWidth, ellipsis = "...", pad = false) {
|
|
179
|
+
if (maxWidth <= 0) {
|
|
180
|
+
return "";
|
|
181
|
+
}
|
|
182
|
+
if (text.length === 0) {
|
|
183
|
+
return pad ? " ".repeat(maxWidth) : "";
|
|
43
184
|
}
|
|
44
185
|
const ellipsisWidth = visibleWidth(ellipsis);
|
|
186
|
+
// Handle case where ellipsis is wider than maxWidth
|
|
187
|
+
if (ellipsisWidth >= maxWidth) {
|
|
188
|
+
const result = handleOversizedEllipsis(text, maxWidth, ellipsis, pad);
|
|
189
|
+
if (result !== null) {
|
|
190
|
+
return result;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Fast path: pure ASCII printable
|
|
194
|
+
if (isPrintableAscii(text)) {
|
|
195
|
+
if (text.length <= maxWidth) {
|
|
196
|
+
return pad ? text + " ".repeat(maxWidth - text.length) : text;
|
|
197
|
+
}
|
|
198
|
+
const targetWidth = maxWidth - ellipsisWidth;
|
|
199
|
+
return finalizeTruncatedResult(text.slice(0, targetWidth), targetWidth, ellipsis, ellipsisWidth, maxWidth, pad);
|
|
200
|
+
}
|
|
45
201
|
const targetWidth = maxWidth - ellipsisWidth;
|
|
46
|
-
|
|
47
|
-
|
|
202
|
+
const hasAnsi = text.includes("\x1b");
|
|
203
|
+
const hasTabs = text.includes("\t");
|
|
204
|
+
let truncatedResult;
|
|
205
|
+
let exhaustedInput;
|
|
206
|
+
if (!hasAnsi && !hasTabs) {
|
|
207
|
+
truncatedResult = truncateSimple(text, targetWidth, maxWidth);
|
|
208
|
+
exhaustedInput = !truncatedResult.overflowed;
|
|
48
209
|
}
|
|
49
|
-
|
|
210
|
+
else {
|
|
211
|
+
const complexResult = truncateComplex(text, targetWidth, maxWidth);
|
|
212
|
+
truncatedResult = complexResult;
|
|
213
|
+
exhaustedInput = complexResult.exhaustedInput;
|
|
214
|
+
}
|
|
215
|
+
// Text fits completely
|
|
216
|
+
if (!truncatedResult.overflowed && exhaustedInput) {
|
|
217
|
+
return pad
|
|
218
|
+
? text + " ".repeat(Math.max(0, maxWidth - truncatedResult.visibleSoFar))
|
|
219
|
+
: text;
|
|
220
|
+
}
|
|
221
|
+
return finalizeTruncatedResult(truncatedResult.result, truncatedResult.keptWidth, ellipsis, ellipsisWidth, maxWidth, pad);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Truncate a single fragment to a maximum width.
|
|
225
|
+
*/
|
|
226
|
+
function truncateFragmentToWidth(text, maxWidth) {
|
|
227
|
+
if (maxWidth <= 0 || text.length === 0) {
|
|
228
|
+
return { text: "", width: 0 };
|
|
229
|
+
}
|
|
230
|
+
if (isPrintableAscii(text)) {
|
|
231
|
+
const clipped = text.slice(0, maxWidth);
|
|
232
|
+
return { text: clipped, width: clipped.length };
|
|
233
|
+
}
|
|
234
|
+
const hasAnsi = text.includes("\x1b");
|
|
235
|
+
const hasTabs = text.includes("\t");
|
|
236
|
+
if (!hasAnsi && !hasTabs) {
|
|
237
|
+
let result = "";
|
|
238
|
+
let width = 0;
|
|
239
|
+
for (const { segment } of getSegmenter().segment(text)) {
|
|
240
|
+
const w = graphemeWidth(segment);
|
|
241
|
+
if (width + w > maxWidth) {
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
result += segment;
|
|
245
|
+
width += w;
|
|
246
|
+
}
|
|
247
|
+
return { text: result, width };
|
|
248
|
+
}
|
|
249
|
+
let result = "";
|
|
250
|
+
let width = 0;
|
|
50
251
|
let i = 0;
|
|
51
|
-
|
|
252
|
+
let pendingAnsi = "";
|
|
52
253
|
while (i < text.length) {
|
|
53
|
-
const
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
i +=
|
|
254
|
+
const ansi = extractAnsiCode(text, i);
|
|
255
|
+
if (ansi) {
|
|
256
|
+
pendingAnsi += ansi.code;
|
|
257
|
+
i += ansi.length;
|
|
258
|
+
continue;
|
|
57
259
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
260
|
+
if (text[i] === "\t") {
|
|
261
|
+
if (width + 3 > maxWidth) {
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
if (pendingAnsi) {
|
|
265
|
+
result += pendingAnsi;
|
|
266
|
+
pendingAnsi = "";
|
|
267
|
+
}
|
|
268
|
+
result += "\t";
|
|
269
|
+
width += 3;
|
|
270
|
+
i++;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
let end = i;
|
|
274
|
+
while (end < text.length && text[end] !== "\t") {
|
|
275
|
+
const nextAnsi = extractAnsiCode(text, end);
|
|
276
|
+
if (nextAnsi) {
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
end++;
|
|
280
|
+
}
|
|
281
|
+
for (const { segment } of getSegmenter().segment(text.slice(i, end))) {
|
|
282
|
+
const w = graphemeWidth(segment);
|
|
283
|
+
if (width + w > maxWidth) {
|
|
284
|
+
return { text: result, width };
|
|
66
285
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
segments.push({ type: "grapheme", value: seg.segment });
|
|
286
|
+
if (pendingAnsi) {
|
|
287
|
+
result += pendingAnsi;
|
|
288
|
+
pendingAnsi = "";
|
|
71
289
|
}
|
|
72
|
-
|
|
290
|
+
result += segment;
|
|
291
|
+
width += w;
|
|
73
292
|
}
|
|
293
|
+
i = end;
|
|
74
294
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
295
|
+
return { text: result, width };
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Finalize a truncated result with proper ANSI reset codes.
|
|
299
|
+
* Only adds reset codes if the prefix contains ANSI sequences.
|
|
300
|
+
*/
|
|
301
|
+
function finalizeTruncatedResult(prefix, prefixWidth, ellipsis, ellipsisWidth, maxWidth, pad) {
|
|
302
|
+
const hasAnsi = prefix.includes("\x1b");
|
|
303
|
+
const visibleWidth = prefixWidth + ellipsisWidth;
|
|
304
|
+
let result;
|
|
305
|
+
if (hasAnsi) {
|
|
306
|
+
const reset = "\x1b[0m";
|
|
307
|
+
if (ellipsis.length > 0) {
|
|
308
|
+
result = `${prefix}${reset}${ellipsis}${reset}`;
|
|
82
309
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (currentWidth + graphemeWidth > targetWidth) {
|
|
86
|
-
break;
|
|
310
|
+
else {
|
|
311
|
+
result = `${prefix}${reset}`;
|
|
87
312
|
}
|
|
88
|
-
result += grapheme;
|
|
89
|
-
currentWidth += graphemeWidth;
|
|
90
313
|
}
|
|
91
|
-
|
|
92
|
-
|
|
314
|
+
else {
|
|
315
|
+
result = ellipsis.length > 0 ? `${prefix}${ellipsis}` : prefix;
|
|
316
|
+
}
|
|
317
|
+
return pad
|
|
318
|
+
? result + " ".repeat(Math.max(0, maxWidth - visibleWidth))
|
|
319
|
+
: result;
|
|
93
320
|
}
|
|
94
321
|
/**
|
|
95
322
|
* Apply background color to a line, padding to full width.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binary output handling for Bash tool
|
|
3
|
+
*
|
|
4
|
+
* Detects binary output from commands and saves it to temp files
|
|
5
|
+
* with helpful metadata for the user.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Check if output appears to be binary data
|
|
9
|
+
* Binary is detected by:
|
|
10
|
+
* - Null bytes (most reliable indicator)
|
|
11
|
+
* - High ratio of non-printable characters
|
|
12
|
+
*/
|
|
13
|
+
export declare function isBinaryOutput(output: string): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Result of saving binary output
|
|
16
|
+
*/
|
|
17
|
+
export interface BinarySaveResult {
|
|
18
|
+
success: boolean;
|
|
19
|
+
path?: string;
|
|
20
|
+
size?: number;
|
|
21
|
+
mimeType?: string;
|
|
22
|
+
error?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Save binary output to a temp file and detect its MIME type
|
|
26
|
+
*/
|
|
27
|
+
export declare function saveBinaryOutput(output: string): BinarySaveResult;
|
|
28
|
+
/**
|
|
29
|
+
* Format a user-friendly message for binary output
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatBinaryMessage(result: BinarySaveResult): string;
|
|
32
|
+
//# sourceMappingURL=binary-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary-output.d.ts","sourceRoot":"","sources":["../../source/utils/binary-output.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CA4BtD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,gBAAgB,CA4CjE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAqBpE"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Binary output handling for Bash tool
|
|
3
|
+
*
|
|
4
|
+
* Detects binary output from commands and saves it to temp files
|
|
5
|
+
* with helpful metadata for the user.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from "node:child_process";
|
|
8
|
+
import { randomBytes } from "node:crypto";
|
|
9
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { dirname } from "node:path";
|
|
11
|
+
/**
|
|
12
|
+
* Threshold for checking binary content (check first N bytes)
|
|
13
|
+
*/
|
|
14
|
+
const BINARY_CHECK_BYTES = 8192;
|
|
15
|
+
/**
|
|
16
|
+
* Check if output appears to be binary data
|
|
17
|
+
* Binary is detected by:
|
|
18
|
+
* - Null bytes (most reliable indicator)
|
|
19
|
+
* - High ratio of non-printable characters
|
|
20
|
+
*/
|
|
21
|
+
export function isBinaryOutput(output) {
|
|
22
|
+
if (output.length === 0) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// Check first N bytes for null bytes (strongest binary indicator)
|
|
26
|
+
const checkLength = Math.min(output.length, BINARY_CHECK_BYTES);
|
|
27
|
+
const sample = output.slice(0, checkLength);
|
|
28
|
+
// Null byte is definitive binary indicator
|
|
29
|
+
if (sample.includes("\0")) {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
// Count non-printable characters (excluding common whitespace)
|
|
33
|
+
let nonPrintable = 0;
|
|
34
|
+
for (let i = 0; i < sample.length; i++) {
|
|
35
|
+
const code = sample.charCodeAt(i);
|
|
36
|
+
// Allow printable ASCII (32-126), newlines (10), tabs (9), and carriage returns (13)
|
|
37
|
+
// Also allow extended ASCII/UTF-8 (127+)
|
|
38
|
+
if (code < 32 && code !== 9 && code !== 10 && code !== 13) {
|
|
39
|
+
nonPrintable++;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// If more than 30% non-printable in the sample, treat as binary
|
|
43
|
+
const ratio = nonPrintable / sample.length;
|
|
44
|
+
return ratio > 0.3;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Save binary output to a temp file and detect its MIME type
|
|
48
|
+
*/
|
|
49
|
+
export function saveBinaryOutput(output) {
|
|
50
|
+
try {
|
|
51
|
+
// Generate unique filename
|
|
52
|
+
const id = randomBytes(8).toString("hex");
|
|
53
|
+
const filePath = `/tmp/acai/bash_binary_${id}`;
|
|
54
|
+
// Ensure directory exists
|
|
55
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
56
|
+
// Convert string back to buffer for accurate binary writing
|
|
57
|
+
// Note: Some data loss may have occurred during UTF-8 decoding
|
|
58
|
+
const buffer = Buffer.from(output, "utf8");
|
|
59
|
+
writeFileSync(filePath, buffer);
|
|
60
|
+
const size = buffer.length;
|
|
61
|
+
// Detect MIME type using `file` command
|
|
62
|
+
let mimeType = "application/octet-stream";
|
|
63
|
+
try {
|
|
64
|
+
const fileOutput = execSync(`file --mime-type -b "${filePath}"`, {
|
|
65
|
+
encoding: "utf8",
|
|
66
|
+
timeout: 5000,
|
|
67
|
+
}).trim();
|
|
68
|
+
if (fileOutput && fileOutput !== "cannot open") {
|
|
69
|
+
mimeType = fileOutput;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// `file` command not available or failed, use default
|
|
74
|
+
}
|
|
75
|
+
return {
|
|
76
|
+
success: true,
|
|
77
|
+
path: filePath,
|
|
78
|
+
size,
|
|
79
|
+
mimeType,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error";
|
|
84
|
+
return {
|
|
85
|
+
success: false,
|
|
86
|
+
error: errorMessage,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Format a user-friendly message for binary output
|
|
92
|
+
*/
|
|
93
|
+
export function formatBinaryMessage(result) {
|
|
94
|
+
if (!result.success) {
|
|
95
|
+
return `⚠️ Binary output detected but could not be saved: ${result.error ?? "Unknown error"}`;
|
|
96
|
+
}
|
|
97
|
+
const sizeStr = formatBytes(result.size ?? 0);
|
|
98
|
+
const lines = [
|
|
99
|
+
"📦 Binary output detected",
|
|
100
|
+
"",
|
|
101
|
+
`**Size:** ${sizeStr}`,
|
|
102
|
+
`**Type:** ${result.mimeType}`,
|
|
103
|
+
`**Saved to:** \`${result.path}\``,
|
|
104
|
+
"",
|
|
105
|
+
"**To inspect this file, you can use:**",
|
|
106
|
+
" • `file <path>` - Detect file type",
|
|
107
|
+
" • `xxd <path>` - Hex dump",
|
|
108
|
+
" • `hexdump -C <path>` - Hex dump with ASCII",
|
|
109
|
+
" • `head -c 100 <path> | xxd` - Preview first 100 bytes",
|
|
110
|
+
];
|
|
111
|
+
return lines.join("\n");
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Format bytes as human-readable string
|
|
115
|
+
*/
|
|
116
|
+
function formatBytes(bytes) {
|
|
117
|
+
if (bytes === 0)
|
|
118
|
+
return "0 bytes";
|
|
119
|
+
const units = ["bytes", "KB", "MB", "GB"];
|
|
120
|
+
const unitIndex = Math.floor(Math.log(bytes) / Math.log(1024));
|
|
121
|
+
const size = bytes / 1024 ** unitIndex;
|
|
122
|
+
// Show decimal for KB and up, whole number for bytes
|
|
123
|
+
if (unitIndex === 0) {
|
|
124
|
+
return `${bytes} bytes`;
|
|
125
|
+
}
|
|
126
|
+
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
127
|
+
}
|