@chengchenccc/oh-my-agent 0.1.1-rc.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 +79 -0
- package/dist/cli/args.d.ts +24 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +120 -0
- package/dist/cli/initial-input.d.ts +32 -0
- package/dist/cli/initial-input.d.ts.map +1 -0
- package/dist/cli/initial-input.js +131 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +3 -0
- package/dist/core/__fixtures__/echo-model.d.ts +6 -0
- package/dist/core/__fixtures__/echo-model.d.ts.map +1 -0
- package/dist/core/__fixtures__/echo-model.js +10 -0
- package/dist/core/__fixtures__/mcp-echo-server.d.ts +2 -0
- package/dist/core/__fixtures__/mcp-echo-server.d.ts.map +1 -0
- package/dist/core/__fixtures__/mcp-echo-server.js +54 -0
- package/dist/core/agent-runtime.d.ts +21 -0
- package/dist/core/agent-runtime.d.ts.map +1 -0
- package/dist/core/agent-runtime.js +14 -0
- package/dist/core/memory/autonomous-memory.d.ts +21 -0
- package/dist/core/memory/autonomous-memory.d.ts.map +1 -0
- package/dist/core/memory/autonomous-memory.js +202 -0
- package/dist/core/persistence/in-memory-session-store.d.ts +3 -0
- package/dist/core/persistence/in-memory-session-store.d.ts.map +1 -0
- package/dist/core/persistence/in-memory-session-store.js +109 -0
- package/dist/core/persistence/session-store.contract.d.ts +5 -0
- package/dist/core/persistence/session-store.contract.d.ts.map +1 -0
- package/dist/core/persistence/session-store.contract.js +183 -0
- package/dist/core/persistence/session-store.d.ts +33 -0
- package/dist/core/persistence/session-store.d.ts.map +1 -0
- package/dist/core/persistence/session-store.js +22 -0
- package/dist/core/persistence/session-tree.d.ts +49 -0
- package/dist/core/persistence/session-tree.d.ts.map +1 -0
- package/dist/core/persistence/session-tree.js +1 -0
- package/dist/core/plugins/plugin-code.d.ts +13 -0
- package/dist/core/plugins/plugin-code.d.ts.map +1 -0
- package/dist/core/plugins/plugin-code.js +62 -0
- package/dist/core/plugins/plugin-marketplace.d.ts +72 -0
- package/dist/core/plugins/plugin-marketplace.d.ts.map +1 -0
- package/dist/core/plugins/plugin-marketplace.js +340 -0
- package/dist/core/plugins/plugin-resolve.d.ts +32 -0
- package/dist/core/plugins/plugin-resolve.d.ts.map +1 -0
- package/dist/core/plugins/plugin-resolve.js +101 -0
- package/dist/core/plugins/plugin-trust.d.ts +24 -0
- package/dist/core/plugins/plugin-trust.d.ts.map +1 -0
- package/dist/core/plugins/plugin-trust.js +89 -0
- package/dist/core/runtime/agent-event.d.ts +98 -0
- package/dist/core/runtime/agent-event.d.ts.map +1 -0
- package/dist/core/runtime/agent-event.js +1 -0
- package/dist/core/runtime/agent-loop.d.ts +142 -0
- package/dist/core/runtime/agent-loop.d.ts.map +1 -0
- package/dist/core/runtime/agent-loop.js +1008 -0
- package/dist/core/runtime/approval.d.ts +23 -0
- package/dist/core/runtime/approval.d.ts.map +1 -0
- package/dist/core/runtime/approval.js +25 -0
- package/dist/core/runtime/compaction.d.ts +22 -0
- package/dist/core/runtime/compaction.d.ts.map +1 -0
- package/dist/core/runtime/compaction.js +90 -0
- package/dist/core/runtime/context-estimate.d.ts +42 -0
- package/dist/core/runtime/context-estimate.d.ts.map +1 -0
- package/dist/core/runtime/context-estimate.js +34 -0
- package/dist/core/runtime/create-runtime.d.ts +81 -0
- package/dist/core/runtime/create-runtime.d.ts.map +1 -0
- package/dist/core/runtime/create-runtime.js +250 -0
- package/dist/core/runtime/fake-provider.d.ts +3 -0
- package/dist/core/runtime/fake-provider.d.ts.map +1 -0
- package/dist/core/runtime/fake-provider.js +87 -0
- package/dist/core/runtime/logger.d.ts +13 -0
- package/dist/core/runtime/logger.d.ts.map +1 -0
- package/dist/core/runtime/logger.js +38 -0
- package/dist/core/runtime/loop-input.d.ts +39 -0
- package/dist/core/runtime/loop-input.d.ts.map +1 -0
- package/dist/core/runtime/loop-input.js +38 -0
- package/dist/core/runtime/message-cache.d.ts +16 -0
- package/dist/core/runtime/message-cache.d.ts.map +1 -0
- package/dist/core/runtime/message-cache.js +23 -0
- package/dist/core/runtime/model-catalog.d.ts +10 -0
- package/dist/core/runtime/model-catalog.d.ts.map +1 -0
- package/dist/core/runtime/model-catalog.js +14 -0
- package/dist/core/runtime/plugin-runtime.d.ts +41 -0
- package/dist/core/runtime/plugin-runtime.d.ts.map +1 -0
- package/dist/core/runtime/plugin-runtime.js +1 -0
- package/dist/core/runtime/plugin.d.ts +86 -0
- package/dist/core/runtime/plugin.d.ts.map +1 -0
- package/dist/core/runtime/plugin.js +23 -0
- package/dist/core/runtime/process-tree.d.ts +12 -0
- package/dist/core/runtime/process-tree.d.ts.map +1 -0
- package/dist/core/runtime/process-tree.js +40 -0
- package/dist/core/runtime/prompt.d.ts +23 -0
- package/dist/core/runtime/prompt.d.ts.map +1 -0
- package/dist/core/runtime/prompt.js +29 -0
- package/dist/core/runtime/prompts.d.ts +16 -0
- package/dist/core/runtime/prompts.d.ts.map +1 -0
- package/dist/core/runtime/prompts.js +36 -0
- package/dist/core/runtime/retry.d.ts +20 -0
- package/dist/core/runtime/retry.d.ts.map +1 -0
- package/dist/core/runtime/retry.js +60 -0
- package/dist/core/runtime/run-runtime.d.ts +93 -0
- package/dist/core/runtime/run-runtime.d.ts.map +1 -0
- package/dist/core/runtime/run-runtime.js +664 -0
- package/dist/core/runtime/runtime-catalog.d.ts +12 -0
- package/dist/core/runtime/runtime-catalog.d.ts.map +1 -0
- package/dist/core/runtime/runtime-catalog.js +89 -0
- package/dist/core/runtime/stream-rules.d.ts +9 -0
- package/dist/core/runtime/stream-rules.d.ts.map +1 -0
- package/dist/core/runtime/stream-rules.js +44 -0
- package/dist/core/runtime/title.d.ts +7 -0
- package/dist/core/runtime/title.d.ts.map +1 -0
- package/dist/core/runtime/title.js +114 -0
- package/dist/core/runtime/todo.d.ts +16 -0
- package/dist/core/runtime/todo.d.ts.map +1 -0
- package/dist/core/runtime/todo.js +40 -0
- package/dist/core/runtime/tool-filter.d.ts +12 -0
- package/dist/core/runtime/tool-filter.d.ts.map +1 -0
- package/dist/core/runtime/tool-filter.js +23 -0
- package/dist/core/runtime/tool-pruning.d.ts +29 -0
- package/dist/core/runtime/tool-pruning.d.ts.map +1 -0
- package/dist/core/runtime/tool-pruning.js +105 -0
- package/dist/core/session/input-history.d.ts +8 -0
- package/dist/core/session/input-history.d.ts.map +1 -0
- package/dist/core/session/input-history.js +41 -0
- package/dist/core/session/session-file.d.ts +84 -0
- package/dist/core/session/session-file.d.ts.map +1 -0
- package/dist/core/session/session-file.js +392 -0
- package/dist/core/session/session-loop.d.ts +33 -0
- package/dist/core/session/session-loop.d.ts.map +1 -0
- package/dist/core/session/session-loop.js +30 -0
- package/dist/core/settings/project-settings.d.ts +46 -0
- package/dist/core/settings/project-settings.d.ts.map +1 -0
- package/dist/core/settings/project-settings.js +85 -0
- package/dist/core/settings/workspace-context.d.ts +10 -0
- package/dist/core/settings/workspace-context.d.ts.map +1 -0
- package/dist/core/settings/workspace-context.js +48 -0
- package/dist/core/tools/agent-fs-like.d.ts +15 -0
- package/dist/core/tools/agent-fs-like.d.ts.map +1 -0
- package/dist/core/tools/agent-fs-like.js +4 -0
- package/dist/core/tools/ask-question.d.ts +5 -0
- package/dist/core/tools/ask-question.d.ts.map +1 -0
- package/dist/core/tools/ask-question.js +51 -0
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -0
- package/dist/core/tools/bash.js +109 -0
- package/dist/core/tools/eval.d.ts +10 -0
- package/dist/core/tools/eval.d.ts.map +1 -0
- package/dist/core/tools/eval.js +83 -0
- package/dist/core/tools/file-tools.d.ts +18 -0
- package/dist/core/tools/file-tools.d.ts.map +1 -0
- package/dist/core/tools/file-tools.js +249 -0
- package/dist/core/tools/glob.d.ts +5 -0
- package/dist/core/tools/glob.d.ts.map +1 -0
- package/dist/core/tools/glob.js +54 -0
- package/dist/core/tools/grep.d.ts +5 -0
- package/dist/core/tools/grep.d.ts.map +1 -0
- package/dist/core/tools/grep.js +61 -0
- package/dist/core/tools/index.d.ts +14 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +14 -0
- package/dist/core/tools/ls-tree.d.ts +10 -0
- package/dist/core/tools/ls-tree.d.ts.map +1 -0
- package/dist/core/tools/ls-tree.js +177 -0
- package/dist/core/tools/mcp-mount.d.ts +63 -0
- package/dist/core/tools/mcp-mount.d.ts.map +1 -0
- package/dist/core/tools/mcp-mount.js +287 -0
- package/dist/core/tools/read-image.d.ts +6 -0
- package/dist/core/tools/read-image.d.ts.map +1 -0
- package/dist/core/tools/read-image.js +98 -0
- package/dist/core/tools/skill.d.ts +11 -0
- package/dist/core/tools/skill.d.ts.map +1 -0
- package/dist/core/tools/skill.js +65 -0
- package/dist/core/tools/skills.d.ts +10 -0
- package/dist/core/tools/skills.d.ts.map +1 -0
- package/dist/core/tools/skills.js +116 -0
- package/dist/core/tools/todo-store.d.ts +8 -0
- package/dist/core/tools/todo-store.d.ts.map +1 -0
- package/dist/core/tools/todo-store.js +100 -0
- package/dist/core/tools/todo.d.ts +8 -0
- package/dist/core/tools/todo.d.ts.map +1 -0
- package/dist/core/tools/todo.js +91 -0
- package/dist/core/tools/url-guard.d.ts +12 -0
- package/dist/core/tools/url-guard.d.ts.map +1 -0
- package/dist/core/tools/url-guard.js +58 -0
- package/dist/core/tools/web-ports-std.d.ts +6 -0
- package/dist/core/tools/web-ports-std.d.ts.map +1 -0
- package/dist/core/tools/web-ports-std.js +145 -0
- package/dist/core/tools/web-ports.d.ts +56 -0
- package/dist/core/tools/web-ports.d.ts.map +1 -0
- package/dist/core/tools/web-ports.js +62 -0
- package/dist/core/tools/workspace-sandbox.d.ts +20 -0
- package/dist/core/tools/workspace-sandbox.d.ts.map +1 -0
- package/dist/core/tools/workspace-sandbox.js +84 -0
- package/dist/core/workflow/subagent-registry.d.ts +40 -0
- package/dist/core/workflow/subagent-registry.d.ts.map +1 -0
- package/dist/core/workflow/subagent-registry.js +118 -0
- package/dist/core/workflow/workflow-evaluator.d.ts +23 -0
- package/dist/core/workflow/workflow-evaluator.d.ts.map +1 -0
- package/dist/core/workflow/workflow-evaluator.js +21 -0
- package/dist/core/workflow/workflow-executor.d.ts +108 -0
- package/dist/core/workflow/workflow-executor.d.ts.map +1 -0
- package/dist/core/workflow/workflow-executor.js +549 -0
- package/dist/core/workflow/workflow-tools.d.ts +50 -0
- package/dist/core/workflow/workflow-tools.d.ts.map +1 -0
- package/dist/core/workflow/workflow-tools.js +217 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/main.d.ts +9 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +97 -0
- package/dist/modes/json-mode.d.ts +5 -0
- package/dist/modes/json-mode.d.ts.map +1 -0
- package/dist/modes/json-mode.js +46 -0
- package/dist/modes/print-mode.d.ts +20 -0
- package/dist/modes/print-mode.d.ts.map +1 -0
- package/dist/modes/print-mode.js +82 -0
- package/dist/modes/rpc/jsonl.d.ts +23 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -0
- package/dist/modes/rpc/jsonl.js +88 -0
- package/dist/modes/rpc/rpc-mode.d.ts +18 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-mode.js +326 -0
- package/dist/modes/tui/settings-overlay.d.ts +23 -0
- package/dist/modes/tui/settings-overlay.d.ts.map +1 -0
- package/dist/modes/tui/settings-overlay.js +136 -0
- package/dist/modes/tui/tui-commands-session.d.ts +3 -0
- package/dist/modes/tui/tui-commands-session.d.ts.map +1 -0
- package/dist/modes/tui/tui-commands-session.js +191 -0
- package/dist/modes/tui/tui-commands.d.ts +52 -0
- package/dist/modes/tui/tui-commands.d.ts.map +1 -0
- package/dist/modes/tui/tui-commands.js +373 -0
- package/dist/modes/tui/tui-components.d.ts +81 -0
- package/dist/modes/tui/tui-components.d.ts.map +1 -0
- package/dist/modes/tui/tui-components.js +248 -0
- package/dist/modes/tui/tui-format.d.ts +65 -0
- package/dist/modes/tui/tui-format.d.ts.map +1 -0
- package/dist/modes/tui/tui-format.js +246 -0
- package/dist/modes/tui/tui-frame-provider.d.ts +16 -0
- package/dist/modes/tui/tui-frame-provider.d.ts.map +1 -0
- package/dist/modes/tui/tui-frame-provider.js +31 -0
- package/dist/modes/tui/tui-interactive.d.ts +16 -0
- package/dist/modes/tui/tui-interactive.d.ts.map +1 -0
- package/dist/modes/tui/tui-interactive.js +123 -0
- package/dist/modes/tui/tui-io.d.ts +12 -0
- package/dist/modes/tui/tui-io.d.ts.map +1 -0
- package/dist/modes/tui/tui-io.js +620 -0
- package/dist/modes/tui/tui-mode.d.ts +120 -0
- package/dist/modes/tui/tui-mode.d.ts.map +1 -0
- package/dist/modes/tui/tui-mode.js +391 -0
- package/dist/modes/tui/tui-render.d.ts +54 -0
- package/dist/modes/tui/tui-render.d.ts.map +1 -0
- package/dist/modes/tui/tui-render.js +399 -0
- package/dist/modes/tui/tui-slash.d.ts +12 -0
- package/dist/modes/tui/tui-slash.d.ts.map +1 -0
- package/dist/modes/tui/tui-slash.js +64 -0
- package/dist/modes/tui/tui-tool-render.d.ts +6 -0
- package/dist/modes/tui/tui-tool-render.d.ts.map +1 -0
- package/dist/modes/tui/tui-tool-render.js +79 -0
- package/dist/modes/tui/tui-transcript-reconciler.d.ts +25 -0
- package/dist/modes/tui/tui-transcript-reconciler.d.ts.map +1 -0
- package/dist/modes/tui/tui-transcript-reconciler.js +97 -0
- package/dist/modes/tui/view-state.d.ts +67 -0
- package/dist/modes/tui/view-state.d.ts.map +1 -0
- package/dist/modes/tui/view-state.js +353 -0
- package/dist/prompts/agents/subagent.md +26 -0
- package/dist/prompts/system/base.md +20 -0
- package/dist/prompts/system/memory.md +23 -0
- package/dist/prompts/system/safety.md +12 -0
- package/dist/protocol/index.d.ts +5 -0
- package/dist/protocol/index.d.ts.map +1 -0
- package/dist/protocol/index.js +2 -0
- package/dist/protocol/mapping.d.ts +25 -0
- package/dist/protocol/mapping.d.ts.map +1 -0
- package/dist/protocol/mapping.js +115 -0
- package/dist/protocol/transport.d.ts +1396 -0
- package/dist/protocol/transport.d.ts.map +1 -0
- package/dist/protocol/transport.js +170 -0
- package/package.json +49 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Container, type FramePlan, type NativeScrollbackCommittedRows, type NativeScrollbackLiveRegion, type NativeScrollbackReplay, type RenderStablePrefix, SelectList, type SelectListTheme, type TerminalFrameProvider, type Text } from "@chengchenccc/tui";
|
|
2
|
+
export declare class PickerOverlay extends Container {
|
|
3
|
+
private readonly list;
|
|
4
|
+
constructor(title: Text, list: SelectList);
|
|
5
|
+
handleInput(data: string): void;
|
|
6
|
+
render(width: number): string[];
|
|
7
|
+
}
|
|
8
|
+
/** Overlay for ctrl+r history search (pi's HistorySearchComponent, lazy
|
|
9
|
+
* form): a query input plus a SelectList rebuilt per keystroke. Navigation
|
|
10
|
+
* keys go to the list; everything else edits the query. */
|
|
11
|
+
export declare class HistorySearchOverlay extends Container {
|
|
12
|
+
private readonly listSlot;
|
|
13
|
+
private readonly query;
|
|
14
|
+
private list;
|
|
15
|
+
private readonly entries;
|
|
16
|
+
private readonly theme;
|
|
17
|
+
private readonly selectCb;
|
|
18
|
+
private readonly cancelCb;
|
|
19
|
+
constructor(title: Text, entries: readonly string[], theme: SelectListTheme, onSelect: (value: string) => void, onCancel: () => void);
|
|
20
|
+
private buildList;
|
|
21
|
+
handleInput(data: string): void;
|
|
22
|
+
render(width: number): string[];
|
|
23
|
+
}
|
|
24
|
+
export declare class OmaTranscriptContainer extends Container implements NativeScrollbackCommittedRows, NativeScrollbackLiveRegion, NativeScrollbackReplay, RenderStablePrefix, TerminalFrameProvider {
|
|
25
|
+
/** Rows already written to native scrollback (acknowledged frontier). */
|
|
26
|
+
private committedRows;
|
|
27
|
+
/** Desired commit boundary set by the render shell each frame. */
|
|
28
|
+
private targetCommittedRows;
|
|
29
|
+
private lastLines;
|
|
30
|
+
private lastWidth;
|
|
31
|
+
private nextBatchId;
|
|
32
|
+
private offeredBatch;
|
|
33
|
+
private deferCommit;
|
|
34
|
+
/** While a run is live, mermaid/code rows may still re-layout on a later
|
|
35
|
+
* chunk; don't advance the scrollback frontier until the run settles
|
|
36
|
+
* (omp defers native-scrollback settling wholesale for live blocks). */
|
|
37
|
+
setDeferCommit(defer: boolean): void;
|
|
38
|
+
/** Records the desired commit boundary; `peekFinalizedBatch` turns it into
|
|
39
|
+
* an incremental history packet only when it is behind the frontier. */
|
|
40
|
+
setNativeScrollbackCommittedRows(rows: number): void;
|
|
41
|
+
getNativeScrollbackLiveRegionStart(): number | undefined;
|
|
42
|
+
getRenderStablePrefixRows(): number;
|
|
43
|
+
prepareNativeScrollbackReplay(): void;
|
|
44
|
+
clear(): void;
|
|
45
|
+
/** Total rows currently in the live (not-yet-committed) tail. */
|
|
46
|
+
liveRowCount(width: number): number;
|
|
47
|
+
/** Render only the live tail, keeping the most recent `maxRows`. */
|
|
48
|
+
renderViewport(width: number, maxRows: number): string[];
|
|
49
|
+
/** Populate the cached full-render baseline on first paint or a width change. */
|
|
50
|
+
private ensureFullRender;
|
|
51
|
+
/** Offer the next uncommitted prefix as one history batch (omp peek).
|
|
52
|
+
* Returns only the *new* rows (from the frontier), never the cumulative
|
|
53
|
+
* prefix, so the terminal appends each packet exactly once. */
|
|
54
|
+
peekFinalizedBatch(width: number): {
|
|
55
|
+
id: number;
|
|
56
|
+
end: number;
|
|
57
|
+
} | undefined;
|
|
58
|
+
/** Acknowledges the offered batch, advancing the frontier (omp ack). */
|
|
59
|
+
acknowledgeFinalizedBatch(id: number): void;
|
|
60
|
+
/** Render the currently-offered history packet rows (no full re-render). */
|
|
61
|
+
renderOfferedHistory(width: number): {
|
|
62
|
+
id: number;
|
|
63
|
+
rows: string[];
|
|
64
|
+
} | undefined;
|
|
65
|
+
/** Render the children in `[start, end)` as rows (used for history packets). */
|
|
66
|
+
renderRange(start: number, end: number, width: number): string[];
|
|
67
|
+
/** Frame provider viewport = full render; history = uncommitted frontier
|
|
68
|
+
* rows to append to native scrollback. */
|
|
69
|
+
renderFrame(opts: {
|
|
70
|
+
columns: number;
|
|
71
|
+
rows: number;
|
|
72
|
+
}): FramePlan;
|
|
73
|
+
/** Replay the committed prefix after a resize/replay (force full re-compose). */
|
|
74
|
+
beginReplay(): void;
|
|
75
|
+
/** Graceful shutdown flush: offer + ack the committed prefix, then reset. */
|
|
76
|
+
beginHistoryFlush(): void;
|
|
77
|
+
render(width: number): string[];
|
|
78
|
+
}
|
|
79
|
+
/** Production TuiIo over the real terminal. The optional terminal override
|
|
80
|
+
* is the test seam: e2e tests inject a VirtualTerminal (xterm headless). */
|
|
81
|
+
//# sourceMappingURL=tui-components.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-components.d.ts","sourceRoot":"","sources":["../../../src/modes/tui/tui-components.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { Container, Input, matchesKey, SelectList, } from "@chengchenccc/tui";
|
|
2
|
+
import { overlayLines } from "./tui-format.js";
|
|
3
|
+
export class PickerOverlay extends Container {
|
|
4
|
+
list;
|
|
5
|
+
constructor(title, list) {
|
|
6
|
+
super();
|
|
7
|
+
this.list = list;
|
|
8
|
+
this.addChild(title);
|
|
9
|
+
this.addChild(list);
|
|
10
|
+
}
|
|
11
|
+
handleInput(data) {
|
|
12
|
+
this.list.handleInput(data);
|
|
13
|
+
}
|
|
14
|
+
render(width) {
|
|
15
|
+
return overlayLines(super.render(Math.max(1, width - 2)), width);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Overlay for ctrl+r history search (pi's HistorySearchComponent, lazy
|
|
19
|
+
* form): a query input plus a SelectList rebuilt per keystroke. Navigation
|
|
20
|
+
* keys go to the list; everything else edits the query. */
|
|
21
|
+
export class HistorySearchOverlay extends Container {
|
|
22
|
+
listSlot = new Container();
|
|
23
|
+
query;
|
|
24
|
+
list;
|
|
25
|
+
entries;
|
|
26
|
+
theme;
|
|
27
|
+
selectCb;
|
|
28
|
+
cancelCb;
|
|
29
|
+
constructor(title, entries, theme, onSelect, onCancel) {
|
|
30
|
+
super();
|
|
31
|
+
this.entries = entries;
|
|
32
|
+
this.theme = theme;
|
|
33
|
+
this.selectCb = onSelect;
|
|
34
|
+
this.cancelCb = onCancel;
|
|
35
|
+
this.query = new Input();
|
|
36
|
+
this.list = this.buildList();
|
|
37
|
+
this.addChild(title);
|
|
38
|
+
this.addChild(this.query);
|
|
39
|
+
this.addChild(this.listSlot);
|
|
40
|
+
this.listSlot.addChild(this.list);
|
|
41
|
+
}
|
|
42
|
+
buildList() {
|
|
43
|
+
const needle = this.query.getValue().trim().toLowerCase();
|
|
44
|
+
const matches = this.entries.filter((e) => e.toLowerCase().includes(needle)).slice(0, 100);
|
|
45
|
+
const items = matches.map((value) => ({
|
|
46
|
+
value,
|
|
47
|
+
label: value.length > 48 ? `${value.slice(0, 48)}...` : value,
|
|
48
|
+
}));
|
|
49
|
+
const list = new SelectList(items, 10, this.theme);
|
|
50
|
+
list.onSelect = (item) => this.selectCb(item.value);
|
|
51
|
+
list.onCancel = () => this.cancelCb();
|
|
52
|
+
return list;
|
|
53
|
+
}
|
|
54
|
+
handleInput(data) {
|
|
55
|
+
const navigates = matchesKey(data, "up") ||
|
|
56
|
+
matchesKey(data, "down") ||
|
|
57
|
+
matchesKey(data, "pageUp") ||
|
|
58
|
+
matchesKey(data, "pageDown") ||
|
|
59
|
+
matchesKey(data, "enter");
|
|
60
|
+
if (navigates) {
|
|
61
|
+
this.list.handleInput(data);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
if (matchesKey(data, "escape")) {
|
|
65
|
+
this.list.onCancel?.();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.query.handleInput(data);
|
|
69
|
+
this.listSlot.clear();
|
|
70
|
+
this.list = this.buildList();
|
|
71
|
+
this.listSlot.addChild(this.list);
|
|
72
|
+
}
|
|
73
|
+
render(width) {
|
|
74
|
+
return overlayLines(super.render(Math.max(1, width - 2)), width);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
export class OmaTranscriptContainer extends Container {
|
|
78
|
+
/** Rows already written to native scrollback (acknowledged frontier). */
|
|
79
|
+
committedRows = 0;
|
|
80
|
+
/** Desired commit boundary set by the render shell each frame. */
|
|
81
|
+
targetCommittedRows = 0;
|
|
82
|
+
lastLines = [];
|
|
83
|
+
lastWidth = -1;
|
|
84
|
+
nextBatchId = 1;
|
|
85
|
+
offeredBatch;
|
|
86
|
+
deferCommit = false;
|
|
87
|
+
/** While a run is live, mermaid/code rows may still re-layout on a later
|
|
88
|
+
* chunk; don't advance the scrollback frontier until the run settles
|
|
89
|
+
* (omp defers native-scrollback settling wholesale for live blocks). */
|
|
90
|
+
setDeferCommit(defer) {
|
|
91
|
+
this.deferCommit = defer;
|
|
92
|
+
}
|
|
93
|
+
/** Records the desired commit boundary; `peekFinalizedBatch` turns it into
|
|
94
|
+
* an incremental history packet only when it is behind the frontier. */
|
|
95
|
+
setNativeScrollbackCommittedRows(rows) {
|
|
96
|
+
if (this.deferCommit)
|
|
97
|
+
return;
|
|
98
|
+
this.targetCommittedRows = Number.isFinite(rows) ? Math.max(0, Math.trunc(rows)) : 0;
|
|
99
|
+
if (this.targetCommittedRows < this.committedRows)
|
|
100
|
+
this.targetCommittedRows = this.committedRows;
|
|
101
|
+
}
|
|
102
|
+
getNativeScrollbackLiveRegionStart() {
|
|
103
|
+
return this.committedRows;
|
|
104
|
+
}
|
|
105
|
+
getRenderStablePrefixRows() {
|
|
106
|
+
return this.committedRows;
|
|
107
|
+
}
|
|
108
|
+
prepareNativeScrollbackReplay() {
|
|
109
|
+
this.lastLines = [];
|
|
110
|
+
this.lastWidth = -1;
|
|
111
|
+
}
|
|
112
|
+
clear() {
|
|
113
|
+
super.clear();
|
|
114
|
+
this.lastLines = [];
|
|
115
|
+
this.lastWidth = -1;
|
|
116
|
+
this.committedRows = 0;
|
|
117
|
+
this.targetCommittedRows = 0;
|
|
118
|
+
this.offeredBatch = undefined;
|
|
119
|
+
}
|
|
120
|
+
/** Total rows currently in the live (not-yet-committed) tail. */
|
|
121
|
+
liveRowCount(width) {
|
|
122
|
+
this.ensureFullRender(width);
|
|
123
|
+
let rows = 0;
|
|
124
|
+
for (let i = Math.min(this.committedRows, this.children.length); i < this.children.length; i++) {
|
|
125
|
+
rows += this.children[i].render(width).length;
|
|
126
|
+
}
|
|
127
|
+
return rows;
|
|
128
|
+
}
|
|
129
|
+
/** Render only the live tail, keeping the most recent `maxRows`. */
|
|
130
|
+
renderViewport(width, maxRows) {
|
|
131
|
+
this.ensureFullRender(width);
|
|
132
|
+
const live = [];
|
|
133
|
+
for (let i = Math.min(this.committedRows, this.children.length); i < this.children.length; i++) {
|
|
134
|
+
const childLines = this.children[i].render(width);
|
|
135
|
+
for (const line of childLines)
|
|
136
|
+
live.push(line);
|
|
137
|
+
}
|
|
138
|
+
if (live.length > maxRows)
|
|
139
|
+
return live.slice(live.length - maxRows);
|
|
140
|
+
return live;
|
|
141
|
+
}
|
|
142
|
+
/** Populate the cached full-render baseline on first paint or a width change. */
|
|
143
|
+
ensureFullRender(width) {
|
|
144
|
+
if (this.lastWidth !== width || this.lastLines.length === 0) {
|
|
145
|
+
this.lastLines = super.render(width);
|
|
146
|
+
this.lastWidth = width;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/** Offer the next uncommitted prefix as one history batch (omp peek).
|
|
150
|
+
* Returns only the *new* rows (from the frontier), never the cumulative
|
|
151
|
+
* prefix, so the terminal appends each packet exactly once. */
|
|
152
|
+
peekFinalizedBatch(width) {
|
|
153
|
+
if (this.deferCommit)
|
|
154
|
+
return undefined;
|
|
155
|
+
if (this.offeredBatch !== undefined)
|
|
156
|
+
return this.offeredBatch;
|
|
157
|
+
if (this.targetCommittedRows <= this.committedRows || this.lastWidth !== width)
|
|
158
|
+
return undefined;
|
|
159
|
+
const end = this.targetCommittedRows;
|
|
160
|
+
const batch = { id: this.nextBatchId++, end };
|
|
161
|
+
this.offeredBatch = batch;
|
|
162
|
+
return batch;
|
|
163
|
+
}
|
|
164
|
+
/** Acknowledges the offered batch, advancing the frontier (omp ack). */
|
|
165
|
+
acknowledgeFinalizedBatch(id) {
|
|
166
|
+
if (this.offeredBatch === undefined || this.offeredBatch.id !== id)
|
|
167
|
+
return;
|
|
168
|
+
this.committedRows = Math.max(this.committedRows, this.offeredBatch.end);
|
|
169
|
+
this.offeredBatch = undefined;
|
|
170
|
+
}
|
|
171
|
+
/** Render the currently-offered history packet rows (no full re-render). */
|
|
172
|
+
renderOfferedHistory(width) {
|
|
173
|
+
const batch = this.peekFinalizedBatch(width);
|
|
174
|
+
if (!batch)
|
|
175
|
+
return undefined;
|
|
176
|
+
return { id: batch.id, rows: this.renderRange(this.committedRows, batch.end, width) };
|
|
177
|
+
}
|
|
178
|
+
/** Render the children in `[start, end)` as rows (used for history packets). */
|
|
179
|
+
renderRange(start, end, width) {
|
|
180
|
+
const out = [];
|
|
181
|
+
for (let i = start; i < Math.min(end, this.children.length); i++) {
|
|
182
|
+
const childLines = this.children[i].render(width);
|
|
183
|
+
for (const line of childLines)
|
|
184
|
+
out.push(line);
|
|
185
|
+
}
|
|
186
|
+
return out;
|
|
187
|
+
}
|
|
188
|
+
/** Frame provider viewport = full render; history = uncommitted frontier
|
|
189
|
+
* rows to append to native scrollback. */
|
|
190
|
+
renderFrame(opts) {
|
|
191
|
+
const viewport = this.render(opts.columns);
|
|
192
|
+
const batch = this.peekFinalizedBatch(opts.columns);
|
|
193
|
+
return {
|
|
194
|
+
viewport,
|
|
195
|
+
history: batch
|
|
196
|
+
? { id: batch.id, rows: this.renderRange(this.committedRows, batch.end, opts.columns) }
|
|
197
|
+
: undefined,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/** Replay the committed prefix after a resize/replay (force full re-compose). */
|
|
201
|
+
beginReplay() {
|
|
202
|
+
this.offeredBatch = undefined;
|
|
203
|
+
this.committedRows = 0;
|
|
204
|
+
this.targetCommittedRows = 0;
|
|
205
|
+
this.lastLines = [];
|
|
206
|
+
this.lastWidth = -1;
|
|
207
|
+
}
|
|
208
|
+
/** Graceful shutdown flush: offer + ack the committed prefix, then reset. */
|
|
209
|
+
beginHistoryFlush() {
|
|
210
|
+
const batch = this.peekFinalizedBatch(this.lastWidth);
|
|
211
|
+
if (batch)
|
|
212
|
+
this.acknowledgeFinalizedBatch(batch.id);
|
|
213
|
+
this.beginReplay();
|
|
214
|
+
}
|
|
215
|
+
render(width) {
|
|
216
|
+
// Steady-state frames reuse the committed prefix (rows already in native
|
|
217
|
+
// scrollback) and only compose children at/after the seam, making each
|
|
218
|
+
// frame O(live tail) instead of O(history). A width change forces a full
|
|
219
|
+
// re-layout of the prefix too.
|
|
220
|
+
if (this.lastWidth !== width || this.children.length === 0) {
|
|
221
|
+
const all = super.render(width);
|
|
222
|
+
this.lastLines = all;
|
|
223
|
+
this.lastWidth = width;
|
|
224
|
+
return all;
|
|
225
|
+
}
|
|
226
|
+
const start = Math.min(this.committedRows, this.children.length);
|
|
227
|
+
// Cheap committed-prefix audit: the last committed row must still match
|
|
228
|
+
// its cached bytes, otherwise the prefix drifted and we re-layout fully.
|
|
229
|
+
if (start > 0) {
|
|
230
|
+
const audit = this.children[start - 1]?.render(width)?.[0] ?? "";
|
|
231
|
+
if (audit !== this.lastLines[start - 1]) {
|
|
232
|
+
const all = super.render(width);
|
|
233
|
+
this.lastLines = all;
|
|
234
|
+
this.lastWidth = width;
|
|
235
|
+
return all;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const prefix = this.lastLines.slice(0, Math.max(0, start));
|
|
239
|
+
const tail = [];
|
|
240
|
+
for (let i = start; i < this.children.length; i++) {
|
|
241
|
+
tail.push(...this.children[i].render(width));
|
|
242
|
+
}
|
|
243
|
+
this.lastLines = [...prefix, ...tail];
|
|
244
|
+
return this.lastLines;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
/** Production TuiIo over the real terminal. The optional terminal override
|
|
248
|
+
* is the test seam: e2e tests inject a VirtualTerminal (xterm headless). */
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { DefaultTextStyle, EditorTheme, MarkdownTheme } from "@chengchenccc/tui";
|
|
2
|
+
export declare const MAX_TOOL_ARGS = 200;
|
|
3
|
+
export declare const MAX_TOOL_DETAIL = 8000;
|
|
4
|
+
export declare const MAX_DIFF_LINES = 6;
|
|
5
|
+
/** Compact single-line JSON, truncated with an ellipsis marker. */
|
|
6
|
+
export declare function compactJson(value: unknown, max: number): string;
|
|
7
|
+
/** Multi-line pretty JSON, truncated at MAX_TOOL_DETAIL with an ellipsis. */
|
|
8
|
+
export declare function prettyJson(value: unknown): string;
|
|
9
|
+
/** Collapsed tool-result summary: prefer result.content as a human
|
|
10
|
+
* sentence, keeping the exit marker; fall back to compact JSON only
|
|
11
|
+
* when content is not a string. */
|
|
12
|
+
export declare function summarizeResult(result: Readonly<Record<string, unknown>>): string;
|
|
13
|
+
/** Pi-style collapsed arg summaries: a human sentence per common tool
|
|
14
|
+
* (bash's `$ cmd`, read's `path:a-b`), falling back to compact JSON. */
|
|
15
|
+
export declare const TOOL_ARG_SUMMARIES: Record<string, (input: Record<string, unknown>) => string>;
|
|
16
|
+
export declare function summarizeToolArgs(toolName: string, input: Readonly<Record<string, unknown>>): string;
|
|
17
|
+
export declare const EDITOR_THEME: EditorTheme;
|
|
18
|
+
/** Compact relative age for the session picker's label column. */
|
|
19
|
+
export declare function relativeTime(modifiedAt: number): string;
|
|
20
|
+
/** Markdown theme for assistant output: plain readable text with ANSI
|
|
21
|
+
* emphasis — bold/italic/links/code styled, headings bold, no colors
|
|
22
|
+
* beyond dim (pi renders through its theme; oma keeps it monochrome+dim
|
|
23
|
+
* so the cyan user bubble stays the only saturated element). */
|
|
24
|
+
export declare const MARKDOWN_THEME: MarkdownTheme;
|
|
25
|
+
/** User bubble: markdown text on a deep-blue background tint with cyan
|
|
26
|
+
* text (pi's UserMessageComponent look). */
|
|
27
|
+
export declare const USER_TEXT_STYLE: DefaultTextStyle;
|
|
28
|
+
/** Compact token count for the header: 12k / 200k. */
|
|
29
|
+
export declare function formatTokens(n: number): string;
|
|
30
|
+
/** Compact model meta line (pi's ModelBrowser columns): display name,
|
|
31
|
+
* context window, $in/out per-million cost (free when both legs are zero),
|
|
32
|
+
* current-model mark, and an over-context warning when the session's
|
|
33
|
+
* estimated tokens exceed the model's window. */
|
|
34
|
+
export declare function formatModelMeta(model: {
|
|
35
|
+
displayName: string;
|
|
36
|
+
contextWindow: number;
|
|
37
|
+
cost?: {
|
|
38
|
+
input: number;
|
|
39
|
+
output: number;
|
|
40
|
+
};
|
|
41
|
+
}, opts?: {
|
|
42
|
+
current?: boolean;
|
|
43
|
+
contextTokens?: number;
|
|
44
|
+
}): string;
|
|
45
|
+
export declare const OVERLAY_BG: (s: string) => string;
|
|
46
|
+
/** Pad + frame overlay lines so they cover the underlying transcript
|
|
47
|
+
* (a plain Container's unshaped whitespace lets the base text bleed
|
|
48
|
+
* through). */
|
|
49
|
+
export declare function overlayLines(lines: readonly string[], width: number): string[];
|
|
50
|
+
/** Overlay root for the session picker: renders title + list and routes
|
|
51
|
+
* key input to the list (a plain Container has no handleInput). */
|
|
52
|
+
/** Clean a session title for the header line: strip markdown heading
|
|
53
|
+
* markers/whitespace, collapse whitespace, cap at 32 chars. */
|
|
54
|
+
export declare function cleanHeaderTitle(title: string): string;
|
|
55
|
+
/** Compact git branch + dirty count for the idle status line. */
|
|
56
|
+
export declare function gitStatus(workspaceRoot: string): string;
|
|
57
|
+
/** Shorten the workspace path for display (~/... when under HOME). */
|
|
58
|
+
export declare function formatWorkspace(root: string): string;
|
|
59
|
+
/** Branch cyan, dirty count ember (omp gitClean/gitDirty colors). */
|
|
60
|
+
export declare function renderGitSegment(git: string): string;
|
|
61
|
+
/** Threshold color for context percent (omp contextPct). */
|
|
62
|
+
export declare function contextColor(ctx: string): string;
|
|
63
|
+
/** One-time welcome easter eggs, rotated per session (omp welcome tip). */
|
|
64
|
+
export declare const WELCOME_TIPS: readonly string[];
|
|
65
|
+
//# sourceMappingURL=tui-format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-format.d.ts","sourceRoot":"","sources":["../../../src/modes/tui/tui-format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGtF,eAAO,MAAM,aAAa,MAAM,CAAC;AACjC,eAAO,MAAM,eAAe,OAAQ,CAAC;AACrC,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,mEAAmE;AACnE,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG/D;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGjD;AAED;;oCAEoC;AACpC,wBAAgB,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAoCjF;AAED;yEACyE;AACzE,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAsBzF,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACvC,MAAM,CAOR;AACD,eAAO,MAAM,YAAY,EAAE,WAS1B,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CASvD;AAED;;;iEAGiE;AACjE,eAAO,MAAM,cAAc,EAAE,aAe5B,CAAC;AAEF;6CAC6C;AAC7C,eAAO,MAAM,eAAe,EAAE,gBAG7B,CAAC;AAEF,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAG9C;AAED;;;kDAGkD;AAClD,wBAAgB,eAAe,CAC7B,KAAK,EAAE;IACL,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C,EACD,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAO,GACvD,MAAM,CAUR;AAED,eAAO,MAAM,UAAU,GAAI,GAAG,MAAM,KAAG,MAAyC,CAAC;AAEjF;;gBAEgB;AAChB,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAM9E;AAED;oEACoE;AACpE;gEACgE;AAChE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQtD;AAED,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAoBvD;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED,qEAAqE;AACrE,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,4DAA4D;AAC5D,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAMhD;AAED,2EAA2E;AAC3E,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAMzC,CAAC"}
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import { applyBackgroundToLine, truncateToWidth } from "@chengchenccc/tui";
|
|
2
|
+
export const MAX_TOOL_ARGS = 200;
|
|
3
|
+
export const MAX_TOOL_DETAIL = 8_000;
|
|
4
|
+
export const MAX_DIFF_LINES = 6;
|
|
5
|
+
/** Compact single-line JSON, truncated with an ellipsis marker. */
|
|
6
|
+
export function compactJson(value, max) {
|
|
7
|
+
const json = JSON.stringify(value) ?? String(value);
|
|
8
|
+
return json.length > max ? `${json.slice(0, max)}…` : json;
|
|
9
|
+
}
|
|
10
|
+
/** Multi-line pretty JSON, truncated at MAX_TOOL_DETAIL with an ellipsis. */
|
|
11
|
+
export function prettyJson(value) {
|
|
12
|
+
const json = JSON.stringify(value, null, 2) ?? String(value);
|
|
13
|
+
return json.length > MAX_TOOL_DETAIL ? `${json.slice(0, MAX_TOOL_DETAIL)}…` : json;
|
|
14
|
+
}
|
|
15
|
+
/** Collapsed tool-result summary: prefer result.content as a human
|
|
16
|
+
* sentence, keeping the exit marker; fall back to compact JSON only
|
|
17
|
+
* when content is not a string. */
|
|
18
|
+
export function summarizeResult(result) {
|
|
19
|
+
const content = result.content;
|
|
20
|
+
if (typeof content === "string") {
|
|
21
|
+
const lines = content
|
|
22
|
+
.split("\n")
|
|
23
|
+
.map((s) => s.trim())
|
|
24
|
+
.filter(Boolean);
|
|
25
|
+
const isError = result.isError === true || result.error !== undefined;
|
|
26
|
+
// Success: strip the `[exit: 0]` notice (omp's stripExitCodeNotice) so
|
|
27
|
+
// the line stays human; error keeps a red exit marker (renderTool colors it).
|
|
28
|
+
const contentLines = isError ? lines : lines.filter((l) => !/^\[exit: \d+\]$/.test(l));
|
|
29
|
+
if (contentLines.length > 0) {
|
|
30
|
+
const first = contentLines[0];
|
|
31
|
+
const exit = isError ? lines.find((l) => /^\[exit: \d+\]$/.test(l)) : undefined;
|
|
32
|
+
const summary = exit && exit !== first ? `${first} · ${exit}` : first;
|
|
33
|
+
const remaining = contentLines.filter((l) => l !== first && l !== exit).length;
|
|
34
|
+
const suffix = remaining > 0 ? ` (+${remaining} line${remaining === 1 ? "" : "s"}, ctrl+o)` : "";
|
|
35
|
+
const base = summary.length > MAX_TOOL_ARGS ? `${summary.slice(0, MAX_TOOL_ARGS)}…` : summary;
|
|
36
|
+
return `${base}${suffix}`;
|
|
37
|
+
}
|
|
38
|
+
return "";
|
|
39
|
+
}
|
|
40
|
+
const json = JSON.stringify(result) ?? "";
|
|
41
|
+
if (json.length <= MAX_TOOL_ARGS)
|
|
42
|
+
return json;
|
|
43
|
+
let firstLine = json;
|
|
44
|
+
for (const value of Object.values(result)) {
|
|
45
|
+
if (typeof value === "string" && value.trim()) {
|
|
46
|
+
firstLine = value.trim().split("\n", 1)[0] ?? value;
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (firstLine.length > MAX_TOOL_ARGS) {
|
|
51
|
+
firstLine = `${firstLine.slice(0, MAX_TOOL_ARGS)}…`;
|
|
52
|
+
}
|
|
53
|
+
return `${firstLine} (+${json.length - firstLine.length} chars, ctrl+o)`;
|
|
54
|
+
}
|
|
55
|
+
/** Pi-style collapsed arg summaries: a human sentence per common tool
|
|
56
|
+
* (bash's `$ cmd`, read's `path:a-b`), falling back to compact JSON. */
|
|
57
|
+
export const TOOL_ARG_SUMMARIES = {
|
|
58
|
+
bash: (i) => {
|
|
59
|
+
const command = typeof i.command === "string" ? i.command : "";
|
|
60
|
+
const timeout = typeof i.timeout === "number" ? ` (timeout ${Math.round(i.timeout / 1000)}s)` : "";
|
|
61
|
+
return `$ ${command}${timeout}`;
|
|
62
|
+
},
|
|
63
|
+
read: (i) => {
|
|
64
|
+
const path = typeof i.path === "string" ? i.path : "";
|
|
65
|
+
if (typeof i.offset === "number" && typeof i.limit === "number") {
|
|
66
|
+
return `${path}:${i.offset}-${i.offset + i.limit - 1}`;
|
|
67
|
+
}
|
|
68
|
+
return path;
|
|
69
|
+
},
|
|
70
|
+
write: (i) => (typeof i.path === "string" ? i.path : ""),
|
|
71
|
+
edit: (i) => (typeof i.path === "string" ? i.path : ""),
|
|
72
|
+
grep: (i) => {
|
|
73
|
+
const pattern = typeof i.pattern === "string" ? i.pattern : "";
|
|
74
|
+
const path = typeof i.path === "string" ? ` ${i.path}` : "";
|
|
75
|
+
return `${pattern}${path}`;
|
|
76
|
+
},
|
|
77
|
+
glob: (i) => (typeof i.pattern === "string" ? i.pattern : ""),
|
|
78
|
+
};
|
|
79
|
+
export function summarizeToolArgs(toolName, input) {
|
|
80
|
+
const summarize = TOOL_ARG_SUMMARIES[toolName];
|
|
81
|
+
if (summarize) {
|
|
82
|
+
const summary = summarize(input);
|
|
83
|
+
if (summary.trim())
|
|
84
|
+
return summary;
|
|
85
|
+
}
|
|
86
|
+
return compactJson(input, MAX_TOOL_ARGS);
|
|
87
|
+
}
|
|
88
|
+
export const EDITOR_THEME = {
|
|
89
|
+
borderColor: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
90
|
+
selectList: {
|
|
91
|
+
selectedPrefix: (s) => `\u001b[36m${s}\u001b[0m`,
|
|
92
|
+
selectedText: (s) => `\u001b[1m${s}\u001b[0m`,
|
|
93
|
+
description: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
94
|
+
scrollInfo: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
95
|
+
noMatch: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
/** Compact relative age for the session picker's label column. */
|
|
99
|
+
export function relativeTime(modifiedAt) {
|
|
100
|
+
const minutes = Math.floor((Date.now() - modifiedAt) / 60_000);
|
|
101
|
+
if (minutes < 1)
|
|
102
|
+
return "now";
|
|
103
|
+
if (minutes < 60)
|
|
104
|
+
return `${minutes}m`;
|
|
105
|
+
const hours = Math.floor(minutes / 60);
|
|
106
|
+
if (hours < 24)
|
|
107
|
+
return `${hours}h`;
|
|
108
|
+
const days = Math.floor(hours / 24);
|
|
109
|
+
if (days < 30)
|
|
110
|
+
return `${days}d`;
|
|
111
|
+
return `${Math.floor(days / 30)}mo`;
|
|
112
|
+
}
|
|
113
|
+
/** Markdown theme for assistant output: plain readable text with ANSI
|
|
114
|
+
* emphasis — bold/italic/links/code styled, headings bold, no colors
|
|
115
|
+
* beyond dim (pi renders through its theme; oma keeps it monochrome+dim
|
|
116
|
+
* so the cyan user bubble stays the only saturated element). */
|
|
117
|
+
export const MARKDOWN_THEME = {
|
|
118
|
+
heading: (s) => `\u001b[1m${s}\u001b[0m`,
|
|
119
|
+
link: (s) => `\u001b[4m${s}\u001b[0m`,
|
|
120
|
+
linkUrl: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
121
|
+
code: (s) => `\u001b[36m${s}\u001b[0m`,
|
|
122
|
+
codeBlock: (s) => `\u001b[36m${s}\u001b[0m`,
|
|
123
|
+
codeBlockBorder: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
124
|
+
quote: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
125
|
+
quoteBorder: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
126
|
+
hr: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
127
|
+
listBullet: (s) => `\u001b[2m${s}\u001b[0m`,
|
|
128
|
+
bold: (s) => `\u001b[1m${s}\u001b[0m`,
|
|
129
|
+
italic: (s) => `\u001b[3m${s}\u001b[0m`,
|
|
130
|
+
strikethrough: (s) => `\u001b[9m${s}\u001b[0m`,
|
|
131
|
+
underline: (s) => `\u001b[4m${s}\u001b[0m`,
|
|
132
|
+
};
|
|
133
|
+
/** User bubble: markdown text on a deep-blue background tint with cyan
|
|
134
|
+
* text (pi's UserMessageComponent look). */
|
|
135
|
+
export const USER_TEXT_STYLE = {
|
|
136
|
+
color: (s) => `\u001b[36m${s}\u001b[0m`,
|
|
137
|
+
bgColor: (s) => `\u001b[48;5;234m${s}\u001b[0m`,
|
|
138
|
+
};
|
|
139
|
+
/** Compact token count for the header: 12k / 200k. */
|
|
140
|
+
export function formatTokens(n) {
|
|
141
|
+
if (n >= 1000)
|
|
142
|
+
return `${Math.round(n / 1000)}k`;
|
|
143
|
+
return `${n}`;
|
|
144
|
+
}
|
|
145
|
+
/** Compact model meta line (pi's ModelBrowser columns): display name,
|
|
146
|
+
* context window, $in/out per-million cost (free when both legs are zero),
|
|
147
|
+
* current-model mark, and an over-context warning when the session's
|
|
148
|
+
* estimated tokens exceed the model's window. */
|
|
149
|
+
export function formatModelMeta(model, opts = {}) {
|
|
150
|
+
const input = model.cost?.input ?? 0;
|
|
151
|
+
const output = model.cost?.output ?? 0;
|
|
152
|
+
const cost = input <= 0 && output <= 0 ? "free" : `$${input}/${output}`;
|
|
153
|
+
const parts = [model.displayName, `ctx ${formatTokens(model.contextWindow)}`, cost];
|
|
154
|
+
if (opts.current)
|
|
155
|
+
parts.push("current");
|
|
156
|
+
if (opts.contextTokens !== undefined && model.contextWindow < opts.contextTokens) {
|
|
157
|
+
parts.push("over current context!");
|
|
158
|
+
}
|
|
159
|
+
return parts.join(" · ");
|
|
160
|
+
}
|
|
161
|
+
export const OVERLAY_BG = (s) => `\u001b[48;5;235m${s}\u001b[0m`;
|
|
162
|
+
/** Pad + frame overlay lines so they cover the underlying transcript
|
|
163
|
+
* (a plain Container's unshaped whitespace lets the base text bleed
|
|
164
|
+
* through). */
|
|
165
|
+
export function overlayLines(lines, width) {
|
|
166
|
+
const innerWidth = Math.max(1, width - 2);
|
|
167
|
+
return lines.map((line) => {
|
|
168
|
+
const content = truncateToWidth(line, innerWidth, "", true);
|
|
169
|
+
return `\u001b[36m\u2502\u001b[0m${applyBackgroundToLine(content, innerWidth, OVERLAY_BG)}\u001b[36m\u2502\u001b[0m`;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/** Overlay root for the session picker: renders title + list and routes
|
|
173
|
+
* key input to the list (a plain Container has no handleInput). */
|
|
174
|
+
/** Clean a session title for the header line: strip markdown heading
|
|
175
|
+
* markers/whitespace, collapse whitespace, cap at 32 chars. */
|
|
176
|
+
export function cleanHeaderTitle(title) {
|
|
177
|
+
const cleaned = title
|
|
178
|
+
.replace(/^[#>*\s]+/, "")
|
|
179
|
+
.replace(/\s+/g, " ")
|
|
180
|
+
.trim();
|
|
181
|
+
if (!cleaned)
|
|
182
|
+
return "";
|
|
183
|
+
const truncated = cleaned.length > 32 ? `${cleaned.slice(0, 32)}…` : cleaned;
|
|
184
|
+
return ` — ${truncated}`;
|
|
185
|
+
}
|
|
186
|
+
/** Compact git branch + dirty count for the idle status line. */
|
|
187
|
+
export function gitStatus(workspaceRoot) {
|
|
188
|
+
try {
|
|
189
|
+
const branchResult = Bun.spawnSync([
|
|
190
|
+
"git",
|
|
191
|
+
"-C",
|
|
192
|
+
workspaceRoot,
|
|
193
|
+
"rev-parse",
|
|
194
|
+
"--abbrev-ref",
|
|
195
|
+
"HEAD",
|
|
196
|
+
]);
|
|
197
|
+
if (branchResult.exitCode !== 0)
|
|
198
|
+
return "";
|
|
199
|
+
const branch = branchResult.stdout.toString().trim();
|
|
200
|
+
if (!branch)
|
|
201
|
+
return "";
|
|
202
|
+
const porcelain = Bun.spawnSync(["git", "-C", workspaceRoot, "status", "--porcelain"]);
|
|
203
|
+
if (porcelain.exitCode !== 0)
|
|
204
|
+
return branch;
|
|
205
|
+
const changes = porcelain.stdout.toString().split("\n").filter(Boolean).length;
|
|
206
|
+
return changes > 0 ? `${branch}+${changes}` : branch;
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
return "";
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
/** Shorten the workspace path for display (~/... when under HOME). */
|
|
213
|
+
export function formatWorkspace(root) {
|
|
214
|
+
const home = process.env.HOME;
|
|
215
|
+
if (home && (root === home || root.startsWith(`${home}/`))) {
|
|
216
|
+
return root === home ? "~" : `~${root.slice(home.length)}`;
|
|
217
|
+
}
|
|
218
|
+
return root;
|
|
219
|
+
}
|
|
220
|
+
/** Branch cyan, dirty count ember (omp gitClean/gitDirty colors). */
|
|
221
|
+
export function renderGitSegment(git) {
|
|
222
|
+
if (!git)
|
|
223
|
+
return "";
|
|
224
|
+
const plus = git.indexOf("+");
|
|
225
|
+
if (plus === -1)
|
|
226
|
+
return `\u001b[38;5;42m${git}\u001b[0m`;
|
|
227
|
+
return `\u001b[38;5;39m${git.slice(0, plus)}\u001b[0m\u001b[38;5;172m${git.slice(plus)}\u001b[0m`;
|
|
228
|
+
}
|
|
229
|
+
/** Threshold color for context percent (omp contextPct). */
|
|
230
|
+
export function contextColor(ctx) {
|
|
231
|
+
const m = ctx.match(/(\d+)%/);
|
|
232
|
+
const pct = m ? Number(m[1]) : 0;
|
|
233
|
+
if (pct >= 90)
|
|
234
|
+
return "\u001b[38;5;196m";
|
|
235
|
+
if (pct >= 70)
|
|
236
|
+
return "\u001b[38;5;172m";
|
|
237
|
+
return "\u001b[2m";
|
|
238
|
+
}
|
|
239
|
+
/** One-time welcome easter eggs, rotated per session (omp welcome tip). */
|
|
240
|
+
export const WELCOME_TIPS = [
|
|
241
|
+
"Tip: press ctrl+t to expand thinking, ctrl+o for tool detail",
|
|
242
|
+
"Tip: /mcp test <name> checks a configured MCP server",
|
|
243
|
+
"Tip: /resume lists saved sessions; /session shows the current id",
|
|
244
|
+
"Tip: /workflow runs a script with subagents",
|
|
245
|
+
"Tip: /exit twice quits; /help lists all commands",
|
|
246
|
+
];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Container, Editor, TerminalFrameProvider } from "@chengchenccc/tui";
|
|
2
|
+
import type { OmaTranscriptContainer } from "./tui-components.js";
|
|
3
|
+
import type { TuiRenderShell } from "./tui-render.js";
|
|
4
|
+
export interface OmaFrameProviderOptions {
|
|
5
|
+
headerContainer: Container;
|
|
6
|
+
transcript: OmaTranscriptContainer;
|
|
7
|
+
statusContainer: Container;
|
|
8
|
+
editor: Editor;
|
|
9
|
+
shell: TuiRenderShell;
|
|
10
|
+
}
|
|
11
|
+
/** Composes the bounded mutable viewport (header + live transcript tail +
|
|
12
|
+
* status/editor) and offers incremental transcript history for native
|
|
13
|
+
* scrollback. Header is rendered as live chrome; when the transcript fills
|
|
14
|
+
* the available rows, settled prefix commits via `history`. */
|
|
15
|
+
export declare function createOmaFrameProvider({ headerContainer, transcript, statusContainer, editor, shell, }: OmaFrameProviderOptions): TerminalFrameProvider;
|
|
16
|
+
//# sourceMappingURL=tui-frame-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui-frame-provider.d.ts","sourceRoot":"","sources":["../../../src/modes/tui/tui-frame-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAClF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,MAAM,WAAW,uBAAuB;IACtC,eAAe,EAAE,SAAS,CAAC;IAC3B,UAAU,EAAE,sBAAsB,CAAC;IACnC,eAAe,EAAE,SAAS,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,cAAc,CAAC;CACvB;AAED;;;gEAGgE;AAChE,wBAAgB,sBAAsB,CAAC,EACrC,eAAe,EACf,UAAU,EACV,eAAe,EACf,MAAM,EACN,KAAK,GACN,EAAE,uBAAuB,GAAG,qBAAqB,CA0BjD"}
|