@bastani/atomic 0.8.28-alpha.1 → 0.8.28-alpha.2
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/CHANGELOG.md +53 -0
- package/README.md +120 -118
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +8 -0
- package/dist/builtin/workflows/builtin/open-claude-design.ts +150 -13
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/tui/chat-surface.ts +32 -33
- package/dist/builtin/workflows/src/tui/run-detail.ts +11 -4
- package/dist/builtin/workflows/src/tui/status-list.ts +32 -2
- package/dist/cli/args.d.ts +4 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +35 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/project-trust.d.ts +10 -0
- package/dist/cli/project-trust.d.ts.map +1 -0
- package/dist/cli/project-trust.js +36 -0
- package/dist/cli/project-trust.js.map +1 -0
- package/dist/cli/startup-ui.d.ts +7 -0
- package/dist/cli/startup-ui.d.ts.map +1 -0
- package/dist/cli/startup-ui.js +57 -0
- package/dist/cli/startup-ui.js.map +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +24 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +3 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +1 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +2 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +2 -2
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +5 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +58 -20
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +4 -3
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +3 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +9 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +18 -24
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +1 -1
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +1 -1
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/experimental.d.ts +2 -0
- package/dist/core/experimental.d.ts.map +1 -0
- package/dist/core/experimental.js +5 -0
- package/dist/core/experimental.js.map +1 -0
- package/dist/core/export-html/template.js +19 -6
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +6 -4
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +11 -4
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +53 -3
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +34 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +2 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +27 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +64 -7
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/output-guard.d.ts +1 -0
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js +52 -22
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts +1 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +20 -8
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/project-trust.d.ts +15 -0
- package/dist/core/project-trust.d.ts.map +1 -0
- package/dist/core/project-trust.js +58 -0
- package/dist/core/project-trust.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +5 -4
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +30 -29
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-attribution.d.ts +4 -0
- package/dist/core/provider-attribution.d.ts.map +1 -0
- package/dist/core/provider-attribution.js +73 -0
- package/dist/core/provider-attribution.js.map +1 -0
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +3 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +9 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +134 -11
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +12 -2
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +108 -18
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +12 -42
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +6 -7
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +99 -35
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +15 -2
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +69 -10
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +0 -3
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +2 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +7 -10
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/oversized-tool-result.d.ts +53 -0
- package/dist/core/tools/oversized-tool-result.d.ts.map +1 -0
- package/dist/core/tools/oversized-tool-result.js +206 -0
- package/dist/core/tools/oversized-tool-result.js.map +1 -0
- package/dist/core/tools/read.d.ts +12 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +99 -34
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +6 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +17 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +6 -0
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +2 -0
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/tool-limits.d.ts +25 -0
- package/dist/core/tools/tool-limits.d.ts.map +1 -0
- package/dist/core/tools/tool-limits.js +25 -0
- package/dist/core/tools/tool-limits.js.map +1 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +1 -1
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts +31 -0
- package/dist/core/trust-manager.d.ts.map +1 -0
- package/dist/core/trust-manager.js +196 -0
- package/dist/core/trust-manager.js.map +1 -0
- package/dist/index.d.ts +9 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +142 -30
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +3 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +325 -7
- package/dist/migrations.js.map +1 -1
- package/dist/modes/index.d.ts +1 -1
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +2 -2
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +6 -0
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +9 -16
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +20 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +22 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/trust-selector.js +85 -0
- package/dist/modes/interactive/components/trust-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +1 -1
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +9 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +130 -9
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +10 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +1 -0
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +3 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +50 -6
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +23 -4
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +1 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts +6 -2
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +104 -10
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/changelog.d.ts +1 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +72 -0
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/deprecation.d.ts +4 -0
- package/dist/utils/deprecation.d.ts.map +1 -0
- package/dist/utils/deprecation.js +13 -0
- package/dist/utils/deprecation.js.map +1 -0
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +54 -22
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/open-browser.d.ts +9 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +22 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/docs/containerization.md +111 -0
- package/docs/custom-provider.md +9 -9
- package/docs/development.md +1 -1
- package/docs/docs.json +2 -0
- package/docs/extensions.md +40 -4
- package/docs/index.md +2 -0
- package/docs/models.md +10 -10
- package/docs/packages.md +1 -1
- package/docs/prompt-templates.md +9 -2
- package/docs/providers.md +18 -5
- package/docs/quickstart.md +1 -0
- package/docs/rpc.md +3 -2
- package/docs/sdk.md +5 -0
- package/docs/security.md +56 -0
- package/docs/session-format.md +2 -2
- package/docs/sessions.md +8 -0
- package/docs/settings.md +21 -4
- package/docs/skills.md +1 -1
- package/docs/terminal-setup.md +44 -2
- package/docs/themes.md +1 -1
- package/docs/tmux.md +4 -2
- package/docs/tui.md +14 -5
- package/docs/usage.md +17 -3
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +8 -5
- package/examples/extensions/bash-spawn-hook.ts +1 -1
- package/examples/extensions/built-in-tool-renderer.ts +1 -1
- package/examples/extensions/claude-rules.ts +1 -1
- package/examples/extensions/commands.ts +1 -1
- package/examples/extensions/custom-header.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +3 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +4 -4
- package/examples/extensions/custom-provider-anthropic/package.json +6 -6
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +55 -4
- package/examples/extensions/custom-provider-gitlab-duo/package.json +3 -3
- package/examples/extensions/doom-overlay/README.md +1 -1
- package/examples/extensions/doom-overlay/index.ts +2 -2
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/gondolin/index.ts +523 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +1 -1
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/inline-bash.ts +2 -2
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/input-transform.ts +3 -3
- package/examples/extensions/interactive-shell.ts +2 -2
- package/examples/extensions/mac-system-theme.ts +2 -2
- package/examples/extensions/minimal-mode.ts +1 -1
- package/examples/extensions/modal-editor.ts +1 -1
- package/examples/extensions/model-status.ts +1 -1
- package/examples/extensions/overlay-qa-tests.ts +198 -179
- package/examples/extensions/overlay-test.ts +1 -1
- package/examples/extensions/pirate.ts +1 -1
- package/examples/extensions/preset.ts +14 -12
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/prompt-customizer.ts +1 -1
- package/examples/extensions/qna.ts +1 -1
- package/examples/extensions/question.ts +1 -1
- package/examples/extensions/questionnaire.ts +1 -1
- package/examples/extensions/rainbow-editor.ts +1 -1
- package/examples/extensions/sandbox/index.ts +16 -14
- package/examples/extensions/sandbox/package-lock.json +90 -90
- package/examples/extensions/sandbox/package.json +17 -17
- package/examples/extensions/snake.ts +1 -1
- package/examples/extensions/space-invaders.ts +1 -1
- package/examples/extensions/ssh.ts +2 -2
- package/examples/extensions/subagent/README.md +13 -13
- package/examples/extensions/subagent/agents.ts +4 -2
- package/examples/extensions/subagent/index.ts +6 -6
- package/examples/extensions/summarize.ts +1 -1
- package/examples/extensions/tic-tac-toe.ts +1 -1
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/todo.ts +1 -1
- package/examples/extensions/tool-override.ts +1 -1
- package/examples/extensions/tools.ts +6 -1
- package/examples/extensions/with-deps/package-lock.json +4 -4
- package/examples/extensions/with-deps/package.json +7 -7
- package/examples/extensions/working-indicator.ts +4 -4
- package/examples/extensions/working-message-test.ts +1 -1
- package/examples/sdk/01-minimal.ts +1 -1
- package/examples/sdk/03-custom-prompt.ts +1 -1
- package/examples/sdk/04-skills.ts +1 -1
- package/examples/sdk/06-extensions.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +1 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +2 -2
- package/examples/sdk/README.md +2 -2
- package/package.json +4 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay QA Tests - comprehensive overlay positioning and edge case tests
|
|
3
3
|
*
|
|
4
|
-
* Usage:
|
|
4
|
+
* Usage: atomic --extension ./examples/extensions/overlay-qa-tests.ts
|
|
5
5
|
*
|
|
6
6
|
* Commands:
|
|
7
7
|
* /overlay-animation - Real-time animation demo (~30 FPS, proves DOOM-like rendering works)
|
|
@@ -15,20 +15,20 @@
|
|
|
15
15
|
* /overlay-sidepanel - Responsive sidepanel (hides when terminal < 100 cols)
|
|
16
16
|
* /overlay-toggle - Toggle visibility demo (demonstrates OverlayHandle.setHidden)
|
|
17
17
|
* /overlay-passive - Non-capturing overlay demo (passive info panel alongside active overlay)
|
|
18
|
-
* /overlay-focus - Focus cycling and rendering order with
|
|
18
|
+
* /overlay-focus - Focus cycling, input routing, dismissal, and rendering order with overlays
|
|
19
19
|
* /overlay-streaming - Multiple input panels with simulated streaming (Tab to cycle focus)
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import type { ExtensionAPI, ExtensionCommandContext, Theme } from "@bastani/atomic";
|
|
23
23
|
import type { Component, OverlayAnchor, OverlayHandle, OverlayOptions, TUI } from "@earendil-works/pi-tui";
|
|
24
|
-
import { matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
24
|
+
import { Input, matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
25
25
|
import { spawn } from "child_process";
|
|
26
26
|
|
|
27
27
|
// Global handle for toggle demo (in real code, use a more elegant pattern)
|
|
28
28
|
let globalToggleHandle: OverlayHandle | null = null;
|
|
29
29
|
|
|
30
30
|
export default function (pi: ExtensionAPI) {
|
|
31
|
-
// Animation demo - proves overlays can handle real-time updates (like
|
|
31
|
+
// Animation demo - proves overlays can handle real-time updates (like Atomic doom would need)
|
|
32
32
|
pi.registerCommand("overlay-animation", {
|
|
33
33
|
description: "Test real-time animation in overlay (~30 FPS)",
|
|
34
34
|
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
@@ -272,9 +272,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
272
272
|
},
|
|
273
273
|
});
|
|
274
274
|
|
|
275
|
-
// Focus cycling demo - demonstrates focus(),
|
|
275
|
+
// Focus cycling demo - demonstrates focus(), input routing, per-panel dismissal, and rendering order
|
|
276
276
|
pi.registerCommand("overlay-focus", {
|
|
277
|
-
description: "Test focus cycling and rendering order with
|
|
277
|
+
description: "Test focus cycling, input routing, dismissal, and rendering order with overlays",
|
|
278
278
|
handler: async (_args: string, ctx: ExtensionCommandContext) => {
|
|
279
279
|
ctx.ui.setEditorText("");
|
|
280
280
|
await ctx.ui.custom<void>((tui, theme, _kb, done) => new FocusDemoController(tui, theme, done), {
|
|
@@ -303,7 +303,7 @@ function sleep(ms: number): Promise<void> {
|
|
|
303
303
|
|
|
304
304
|
// Base overlay component with common rendering
|
|
305
305
|
abstract class BaseOverlay {
|
|
306
|
-
|
|
306
|
+
protected theme: Theme;
|
|
307
307
|
|
|
308
308
|
constructor(theme: Theme) {
|
|
309
309
|
this.theme = theme;
|
|
@@ -334,14 +334,10 @@ abstract class BaseOverlay {
|
|
|
334
334
|
|
|
335
335
|
// Anchor position test
|
|
336
336
|
class AnchorTestComponent extends BaseOverlay {
|
|
337
|
-
|
|
338
|
-
|
|
337
|
+
private anchor: OverlayAnchor;
|
|
338
|
+
private done: (result: "next" | "confirm" | "cancel") => void;
|
|
339
339
|
|
|
340
|
-
constructor(
|
|
341
|
-
theme: Theme,
|
|
342
|
-
anchor: OverlayAnchor,
|
|
343
|
-
done: (result: "next" | "confirm" | "cancel") => void,
|
|
344
|
-
) {
|
|
340
|
+
constructor(theme: Theme, anchor: OverlayAnchor, done: (result: "next" | "confirm" | "cancel") => void) {
|
|
345
341
|
super(theme);
|
|
346
342
|
this.anchor = anchor;
|
|
347
343
|
this.done = done;
|
|
@@ -377,8 +373,8 @@ class AnchorTestComponent extends BaseOverlay {
|
|
|
377
373
|
|
|
378
374
|
// Margin/offset test
|
|
379
375
|
class MarginTestComponent extends BaseOverlay {
|
|
380
|
-
|
|
381
|
-
|
|
376
|
+
private config: { name: string; options: OverlayOptions };
|
|
377
|
+
private done: (result: "next" | "close") => void;
|
|
382
378
|
|
|
383
379
|
constructor(
|
|
384
380
|
theme: Theme,
|
|
@@ -417,16 +413,11 @@ class MarginTestComponent extends BaseOverlay {
|
|
|
417
413
|
|
|
418
414
|
// Stacked overlay test
|
|
419
415
|
class StackOverlayComponent extends BaseOverlay {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
416
|
+
private num: number;
|
|
417
|
+
private position: string;
|
|
418
|
+
private done: (result: string) => void;
|
|
423
419
|
|
|
424
|
-
constructor(
|
|
425
|
-
theme: Theme,
|
|
426
|
-
num: number,
|
|
427
|
-
position: string,
|
|
428
|
-
done: (result: string) => void,
|
|
429
|
-
) {
|
|
420
|
+
constructor(theme: Theme, num: number, position: string, done: (result: string) => void) {
|
|
430
421
|
super(theme);
|
|
431
422
|
this.num = num;
|
|
432
423
|
this.position = position;
|
|
@@ -467,21 +458,16 @@ class StackOverlayComponent extends BaseOverlay {
|
|
|
467
458
|
|
|
468
459
|
// Streaming overflow test - spawns real process with colored output (original crash scenario)
|
|
469
460
|
class StreamingOverflowComponent extends BaseOverlay {
|
|
461
|
+
private tui: TUI;
|
|
470
462
|
private lines: string[] = [];
|
|
471
463
|
private proc: ReturnType<typeof spawn> | null = null;
|
|
472
464
|
private scrollOffset = 0;
|
|
473
465
|
private maxVisibleLines = 15;
|
|
474
466
|
private finished = false;
|
|
475
467
|
private disposed = false;
|
|
468
|
+
private done: () => void;
|
|
476
469
|
|
|
477
|
-
|
|
478
|
-
declare private done: () => void;
|
|
479
|
-
|
|
480
|
-
constructor(
|
|
481
|
-
tui: TUI,
|
|
482
|
-
theme: Theme,
|
|
483
|
-
done: () => void,
|
|
484
|
-
) {
|
|
470
|
+
constructor(tui: TUI, theme: Theme, done: () => void) {
|
|
485
471
|
super(theme);
|
|
486
472
|
this.tui = tui;
|
|
487
473
|
this.done = done;
|
|
@@ -499,13 +485,13 @@ class StreamingOverflowComponent extends BaseOverlay {
|
|
|
499
485
|
echo ""
|
|
500
486
|
for i in $(seq 1 100); do
|
|
501
487
|
# Simulate long file paths with OSC 8 hyperlinks (clickable) - tests width overflow
|
|
502
|
-
DIR="/Users/
|
|
488
|
+
DIR="/Users/example/Documents/development/atomic/packages/coding-agent/src/modes/interactive"
|
|
503
489
|
FILE="\${DIR}/components/very-long-component-name-that-exceeds-width-\${i}.ts"
|
|
504
490
|
echo -e "\\033]8;;file://\${FILE}\\007▶ read: \${FILE}\\033]8;;\\007"
|
|
505
491
|
|
|
506
492
|
# Add some colored status messages with long text
|
|
507
493
|
if [ $((i % 5)) -eq 0 ]; then
|
|
508
|
-
echo -e " \\033[32m✓ Successfully processed \${i} files in /Users/
|
|
494
|
+
echo -e " \\033[32m✓ Successfully processed \${i} files in /Users/example/Documents/development/atomic\\033[0m"
|
|
509
495
|
fi
|
|
510
496
|
if [ $((i % 7)) -eq 0 ]; then
|
|
511
497
|
echo -e " \\033[33m⚠ Warning: potential issue detected at line \${i} in very-long-component-name-that-exceeds-width.ts\\033[0m"
|
|
@@ -605,12 +591,9 @@ class StreamingOverflowComponent extends BaseOverlay {
|
|
|
605
591
|
|
|
606
592
|
// Edge position test
|
|
607
593
|
class EdgeTestComponent extends BaseOverlay {
|
|
608
|
-
|
|
594
|
+
private done: () => void;
|
|
609
595
|
|
|
610
|
-
constructor(
|
|
611
|
-
theme: Theme,
|
|
612
|
-
done: () => void,
|
|
613
|
-
) {
|
|
596
|
+
constructor(theme: Theme, done: () => void) {
|
|
614
597
|
super(theme);
|
|
615
598
|
this.done = done;
|
|
616
599
|
}
|
|
@@ -643,8 +626,8 @@ class EdgeTestComponent extends BaseOverlay {
|
|
|
643
626
|
|
|
644
627
|
// Percentage positioning test
|
|
645
628
|
class PercentTestComponent extends BaseOverlay {
|
|
646
|
-
|
|
647
|
-
|
|
629
|
+
private config: { name: string; row: number; col: number };
|
|
630
|
+
private done: (result: "next" | "close") => void;
|
|
648
631
|
|
|
649
632
|
constructor(
|
|
650
633
|
theme: Theme,
|
|
@@ -683,12 +666,9 @@ class PercentTestComponent extends BaseOverlay {
|
|
|
683
666
|
|
|
684
667
|
// MaxHeight test - renders 20 lines, truncated to 10 by maxHeight
|
|
685
668
|
class MaxHeightTestComponent extends BaseOverlay {
|
|
686
|
-
|
|
669
|
+
private done: () => void;
|
|
687
670
|
|
|
688
|
-
constructor(
|
|
689
|
-
theme: Theme,
|
|
690
|
-
done: () => void,
|
|
691
|
-
) {
|
|
671
|
+
constructor(theme: Theme, done: () => void) {
|
|
692
672
|
super(theme);
|
|
693
673
|
this.done = done;
|
|
694
674
|
}
|
|
@@ -721,17 +701,12 @@ class MaxHeightTestComponent extends BaseOverlay {
|
|
|
721
701
|
|
|
722
702
|
// Responsive sidepanel - demonstrates percentage width and visibility callback
|
|
723
703
|
class SidepanelComponent extends BaseOverlay {
|
|
704
|
+
private tui: TUI;
|
|
724
705
|
private items = ["Dashboard", "Messages", "Settings", "Help", "About"];
|
|
725
706
|
private selectedIndex = 0;
|
|
707
|
+
private done: () => void;
|
|
726
708
|
|
|
727
|
-
|
|
728
|
-
declare private done: () => void;
|
|
729
|
-
|
|
730
|
-
constructor(
|
|
731
|
-
tui: TUI,
|
|
732
|
-
theme: Theme,
|
|
733
|
-
done: () => void,
|
|
734
|
-
) {
|
|
709
|
+
constructor(tui: TUI, theme: Theme, done: () => void) {
|
|
735
710
|
super(theme);
|
|
736
711
|
this.tui = tui;
|
|
737
712
|
this.done = done;
|
|
@@ -785,22 +760,17 @@ class SidepanelComponent extends BaseOverlay {
|
|
|
785
760
|
}
|
|
786
761
|
}
|
|
787
762
|
|
|
788
|
-
// Animation demo - proves overlays can handle real-time updates like
|
|
763
|
+
// Animation demo - proves overlays can handle real-time updates like Atomic doom
|
|
789
764
|
class AnimationDemoComponent extends BaseOverlay {
|
|
765
|
+
private tui: TUI;
|
|
790
766
|
private frame = 0;
|
|
791
767
|
private interval: ReturnType<typeof setInterval> | null = null;
|
|
792
768
|
private fps = 0;
|
|
793
769
|
private lastFpsUpdate = Date.now();
|
|
794
770
|
private framesSinceLastFps = 0;
|
|
771
|
+
private done: () => void;
|
|
795
772
|
|
|
796
|
-
|
|
797
|
-
declare private done: () => void;
|
|
798
|
-
|
|
799
|
-
constructor(
|
|
800
|
-
tui: TUI,
|
|
801
|
-
theme: Theme,
|
|
802
|
-
done: () => void,
|
|
803
|
-
) {
|
|
773
|
+
constructor(tui: TUI, theme: Theme, done: () => void) {
|
|
804
774
|
super(theme);
|
|
805
775
|
this.tui = tui;
|
|
806
776
|
this.done = done;
|
|
@@ -866,7 +836,7 @@ class AnimationDemoComponent extends BaseOverlay {
|
|
|
866
836
|
lines.push(border("│") + padLine(``) + border("│"));
|
|
867
837
|
lines.push(border("│") + padLine(th.fg("dim", " This proves overlays can handle")) + border("│"));
|
|
868
838
|
lines.push(border("│") + padLine(th.fg("dim", " real-time game-like rendering.")) + border("│"));
|
|
869
|
-
lines.push(border("│") + padLine(th.fg("dim", " (
|
|
839
|
+
lines.push(border("│") + padLine(th.fg("dim", " (Atomic doom uses same approach)")) + border("│"));
|
|
870
840
|
lines.push(border("│") + padLine(``) + border("│"));
|
|
871
841
|
lines.push(border("│") + padLine(th.fg("dim", " Press Esc to close")) + border("│"));
|
|
872
842
|
lines.push(border(`╰${"─".repeat(innerW)}╯`));
|
|
@@ -907,17 +877,12 @@ function hslToRgb(h: number, s: number, l: number): [number, number, number] {
|
|
|
907
877
|
|
|
908
878
|
// Toggle demo - demonstrates OverlayHandle.setHidden() via onHandle callback
|
|
909
879
|
class ToggleDemoComponent extends BaseOverlay {
|
|
880
|
+
private tui: TUI;
|
|
910
881
|
private toggleCount = 0;
|
|
911
882
|
private isToggling = false;
|
|
883
|
+
private done: () => void;
|
|
912
884
|
|
|
913
|
-
|
|
914
|
-
declare private done: () => void;
|
|
915
|
-
|
|
916
|
-
constructor(
|
|
917
|
-
tui: TUI,
|
|
918
|
-
theme: Theme,
|
|
919
|
-
done: () => void,
|
|
920
|
-
) {
|
|
885
|
+
constructor(tui: TUI, theme: Theme, done: () => void) {
|
|
921
886
|
super(theme);
|
|
922
887
|
this.tui = tui;
|
|
923
888
|
this.done = done;
|
|
@@ -975,21 +940,16 @@ class ToggleDemoComponent extends BaseOverlay {
|
|
|
975
940
|
|
|
976
941
|
class PassiveDemoController extends BaseOverlay {
|
|
977
942
|
focused = false;
|
|
943
|
+
private tui: TUI;
|
|
978
944
|
private typed = "";
|
|
979
945
|
private timerComponent: TimerPanel;
|
|
980
946
|
private timerHandle: OverlayHandle | null = null;
|
|
981
947
|
private interval: ReturnType<typeof setInterval> | null = null;
|
|
982
948
|
private inputCount = 0;
|
|
983
949
|
private lastInputDebug = "";
|
|
950
|
+
private done: () => void;
|
|
984
951
|
|
|
985
|
-
|
|
986
|
-
declare private done: () => void;
|
|
987
|
-
|
|
988
|
-
constructor(
|
|
989
|
-
tui: TUI,
|
|
990
|
-
theme: Theme,
|
|
991
|
-
done: () => void,
|
|
992
|
-
) {
|
|
952
|
+
constructor(tui: TUI, theme: Theme, done: () => void) {
|
|
993
953
|
super(theme);
|
|
994
954
|
this.tui = tui;
|
|
995
955
|
this.done = done;
|
|
@@ -1071,62 +1031,66 @@ class TimerPanel extends BaseOverlay {
|
|
|
1071
1031
|
|
|
1072
1032
|
// === Focus cycling demo ===
|
|
1073
1033
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
private focusIndex = -1;
|
|
1034
|
+
type FocusPanelColor = "error" | "success" | "accent";
|
|
1035
|
+
type FocusPanelConfig = { label: string; color: FocusPanelColor; options: OverlayOptions };
|
|
1036
|
+
type FocusPanelEntry = { panel: FocusPanel; handle: OverlayHandle };
|
|
1078
1037
|
|
|
1079
|
-
|
|
1080
|
-
|
|
1038
|
+
const FOCUS_PANEL_CONFIGS = [
|
|
1039
|
+
{ label: "Alpha", color: "error", options: { row: 2, col: 4, width: 34 } },
|
|
1040
|
+
{ label: "Beta", color: "success", options: { row: 5, col: 28, width: 34 } },
|
|
1041
|
+
{ label: "Gamma", color: "accent", options: { row: 8, col: 52, width: 34 } },
|
|
1042
|
+
] satisfies FocusPanelConfig[];
|
|
1081
1043
|
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1044
|
+
class FocusDemoController extends BaseOverlay {
|
|
1045
|
+
private readonly tui: TUI;
|
|
1046
|
+
private entries: FocusPanelEntry[] = [];
|
|
1047
|
+
private readonly done: () => void;
|
|
1048
|
+
private closed = false;
|
|
1049
|
+
|
|
1050
|
+
constructor(tui: TUI, theme: Theme, done: () => void) {
|
|
1087
1051
|
super(theme);
|
|
1088
1052
|
this.tui = tui;
|
|
1089
1053
|
this.done = done;
|
|
1090
|
-
const colors = ["error", "success", "accent"] as const;
|
|
1091
|
-
const labels = ["Alpha", "Beta", "Gamma"];
|
|
1092
1054
|
|
|
1093
|
-
for (
|
|
1094
|
-
const panel = new FocusPanel(
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
colors[i]!,
|
|
1098
|
-
() => this.cycleFocus(),
|
|
1099
|
-
() => this.close(),
|
|
1100
|
-
);
|
|
1101
|
-
const handle = this.tui.showOverlay(panel, {
|
|
1102
|
-
nonCapturing: true,
|
|
1103
|
-
row: 2,
|
|
1104
|
-
col: 5 + i * 6,
|
|
1105
|
-
width: 28,
|
|
1106
|
-
});
|
|
1107
|
-
panel.handle = handle;
|
|
1108
|
-
this.panels.push(panel);
|
|
1109
|
-
this.handles.push(handle);
|
|
1055
|
+
for (const config of FOCUS_PANEL_CONFIGS) {
|
|
1056
|
+
const panel = new FocusPanel({ theme, config, controller: this });
|
|
1057
|
+
const handle = this.tui.showOverlay(panel, { nonCapturing: true, ...config.options });
|
|
1058
|
+
this.entries.push({ panel, handle });
|
|
1110
1059
|
}
|
|
1060
|
+
|
|
1061
|
+
this.focusFirstOpenPanel();
|
|
1111
1062
|
}
|
|
1112
1063
|
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1064
|
+
focusNext(current: FocusPanel, direction: 1 | -1 = 1): void {
|
|
1065
|
+
const openEntries = this.openEntries();
|
|
1066
|
+
const currentOpenPosition = openEntries.findIndex((entry) => entry.panel === current);
|
|
1067
|
+
if (currentOpenPosition === -1) throw new Error(`Panel ${current.label} is not open`);
|
|
1068
|
+
const nextOpenPosition = (currentOpenPosition + direction + openEntries.length) % openEntries.length;
|
|
1069
|
+
this.focusEntryAt(openEntries, nextOpenPosition);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
dismiss(panel: FocusPanel): void {
|
|
1073
|
+
const openEntries = this.openEntries();
|
|
1074
|
+
const currentOpenPosition = openEntries.findIndex((candidate) => candidate.panel === panel);
|
|
1075
|
+
if (currentOpenPosition === -1) return;
|
|
1076
|
+
const entry = openEntries[currentOpenPosition];
|
|
1077
|
+
if (!entry) throw new Error(`Invalid focus panel index ${currentOpenPosition}`);
|
|
1078
|
+
const remainingEntries = openEntries.filter((candidate) => candidate.panel !== panel);
|
|
1079
|
+
|
|
1080
|
+
entry.panel.closed = true;
|
|
1081
|
+
entry.handle.hide();
|
|
1082
|
+
if (remainingEntries.length === 0) {
|
|
1083
|
+
this.close();
|
|
1084
|
+
return;
|
|
1122
1085
|
}
|
|
1123
|
-
|
|
1086
|
+
|
|
1087
|
+
this.focusEntryAt(remainingEntries, currentOpenPosition % remainingEntries.length);
|
|
1124
1088
|
}
|
|
1125
1089
|
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
this.
|
|
1129
|
-
this.
|
|
1090
|
+
close(): void {
|
|
1091
|
+
if (this.closed) return;
|
|
1092
|
+
this.closed = true;
|
|
1093
|
+
this.hidePanels();
|
|
1130
1094
|
this.done();
|
|
1131
1095
|
}
|
|
1132
1096
|
|
|
@@ -1134,87 +1098,148 @@ class FocusDemoController extends BaseOverlay {
|
|
|
1134
1098
|
if (matchesKey(data, "escape") || matchesKey(data, "ctrl+c")) {
|
|
1135
1099
|
this.close();
|
|
1136
1100
|
} else if (matchesKey(data, "tab")) {
|
|
1137
|
-
this.
|
|
1101
|
+
this.focusFirstOpenPanel();
|
|
1138
1102
|
}
|
|
1139
1103
|
}
|
|
1140
1104
|
|
|
1141
1105
|
render(width: number): string[] {
|
|
1142
1106
|
const th = this.theme;
|
|
1143
|
-
const focused = this.
|
|
1107
|
+
const focused = this.entries.find((entry) => entry.handle.isFocused())?.panel.label ?? "Controller";
|
|
1144
1108
|
return this.box(
|
|
1145
1109
|
[
|
|
1146
1110
|
"",
|
|
1147
1111
|
` Current focus: ${th.fg("accent", focused)}`,
|
|
1148
1112
|
"",
|
|
1149
1113
|
" Three overlapping panels above are",
|
|
1150
|
-
`
|
|
1151
|
-
"
|
|
1114
|
+
` ${th.fg("accent", "nonCapturing")} overlays controlled with`,
|
|
1115
|
+
" raw OverlayHandle.focus()/hide().",
|
|
1152
1116
|
"",
|
|
1153
|
-
"
|
|
1154
|
-
"
|
|
1117
|
+
" Type in the focused panel's input.",
|
|
1118
|
+
" Focused panel renders on top.",
|
|
1155
1119
|
"",
|
|
1156
|
-
th.fg("dim", " Tab = cycle
|
|
1120
|
+
th.fg("dim", " Tab/Shift+Tab = cycle panels"),
|
|
1121
|
+
th.fg("dim", " Esc/Ctrl+D = dismiss panel"),
|
|
1122
|
+
th.fg("dim", " Ctrl+C = close all"),
|
|
1157
1123
|
"",
|
|
1158
1124
|
],
|
|
1159
1125
|
width,
|
|
1160
|
-
"Focus Demo",
|
|
1126
|
+
"Focus + Input Demo",
|
|
1161
1127
|
);
|
|
1162
1128
|
}
|
|
1163
1129
|
|
|
1164
1130
|
override dispose(): void {
|
|
1165
|
-
|
|
1131
|
+
if (this.closed) return;
|
|
1132
|
+
this.closed = true;
|
|
1133
|
+
this.hidePanels();
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
private focusFirstOpenPanel(): void {
|
|
1137
|
+
const firstOpen = this.openEntries()[0];
|
|
1138
|
+
if (firstOpen) {
|
|
1139
|
+
firstOpen.handle.focus();
|
|
1140
|
+
this.tui.requestRender();
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
private focusEntryAt(entries: FocusPanelEntry[], index: number): void {
|
|
1145
|
+
const entry = entries[index];
|
|
1146
|
+
if (!entry) throw new Error(`Invalid focus panel index ${index}`);
|
|
1147
|
+
entry.handle.focus();
|
|
1148
|
+
this.tui.requestRender();
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
private hidePanels(): void {
|
|
1152
|
+
for (const entry of this.entries) {
|
|
1153
|
+
if (!entry.panel.closed) {
|
|
1154
|
+
entry.panel.closed = true;
|
|
1155
|
+
entry.handle.hide();
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
this.entries = [];
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
private openEntries(): FocusPanelEntry[] {
|
|
1162
|
+
return this.entries.filter((entry) => !entry.panel.closed);
|
|
1166
1163
|
}
|
|
1167
1164
|
}
|
|
1168
1165
|
|
|
1169
1166
|
class FocusPanel extends BaseOverlay {
|
|
1170
|
-
|
|
1167
|
+
focused = false;
|
|
1168
|
+
closed = false;
|
|
1171
1169
|
readonly label: string;
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
constructor(
|
|
1178
|
-
theme
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1170
|
+
private readonly color: FocusPanelColor;
|
|
1171
|
+
private readonly controller: FocusDemoController;
|
|
1172
|
+
private readonly input = new Input();
|
|
1173
|
+
private inputs: string[] = [];
|
|
1174
|
+
|
|
1175
|
+
constructor({
|
|
1176
|
+
theme,
|
|
1177
|
+
config,
|
|
1178
|
+
controller,
|
|
1179
|
+
}: {
|
|
1180
|
+
theme: Theme;
|
|
1181
|
+
config: FocusPanelConfig;
|
|
1182
|
+
controller: FocusDemoController;
|
|
1183
|
+
}) {
|
|
1184
1184
|
super(theme);
|
|
1185
|
-
this.
|
|
1186
|
-
this.
|
|
1187
|
-
this.
|
|
1188
|
-
this.label = label;
|
|
1185
|
+
this.label = config.label;
|
|
1186
|
+
this.color = config.color;
|
|
1187
|
+
this.controller = controller;
|
|
1189
1188
|
}
|
|
1190
1189
|
|
|
1191
1190
|
handleInput(data: string): void {
|
|
1192
1191
|
if (matchesKey(data, "tab")) {
|
|
1193
|
-
this.
|
|
1194
|
-
} else if (matchesKey(data, "
|
|
1195
|
-
this.
|
|
1192
|
+
this.controller.focusNext(this);
|
|
1193
|
+
} else if (matchesKey(data, "shift+tab")) {
|
|
1194
|
+
this.controller.focusNext(this, -1);
|
|
1195
|
+
} else if (matchesKey(data, "escape") || matchesKey(data, "ctrl+d")) {
|
|
1196
|
+
this.controller.dismiss(this);
|
|
1197
|
+
} else if (matchesKey(data, "ctrl+c")) {
|
|
1198
|
+
this.controller.close();
|
|
1199
|
+
} else if (matchesKey(data, "return")) {
|
|
1200
|
+
this.inputs.push("Enter");
|
|
1201
|
+
} else if (matchesKey(data, "up")) {
|
|
1202
|
+
this.inputs.push("↑");
|
|
1203
|
+
} else if (matchesKey(data, "down")) {
|
|
1204
|
+
this.inputs.push("↓");
|
|
1205
|
+
} else if (matchesKey(data, "left")) {
|
|
1206
|
+
this.input.handleInput(data);
|
|
1207
|
+
this.inputs.push("←");
|
|
1208
|
+
} else if (matchesKey(data, "right")) {
|
|
1209
|
+
this.input.handleInput(data);
|
|
1210
|
+
this.inputs.push("→");
|
|
1211
|
+
} else if (matchesKey(data, "backspace")) {
|
|
1212
|
+
this.input.handleInput(data);
|
|
1213
|
+
this.inputs.push("Backspace");
|
|
1214
|
+
} else {
|
|
1215
|
+
this.input.handleInput(data);
|
|
1216
|
+
this.inputs.push(JSON.stringify(data));
|
|
1196
1217
|
}
|
|
1197
1218
|
}
|
|
1198
1219
|
|
|
1199
1220
|
render(width: number): string[] {
|
|
1200
1221
|
const th = this.theme;
|
|
1201
|
-
const focused = this.handle?.isFocused() ?? false;
|
|
1202
1222
|
const innerW = Math.max(1, width - 2);
|
|
1203
|
-
const border = (c: string) => th.fg(this.color, c);
|
|
1223
|
+
const border = (c: string) => th.fg(this.focused ? this.color : "dim", c);
|
|
1204
1224
|
const padLine = (s: string) => truncateToWidth(s, innerW, "...", true);
|
|
1225
|
+
const recent = this.inputs.length === 0 ? "(none)" : this.inputs.slice(-6).join(" ");
|
|
1205
1226
|
const lines: string[] = [];
|
|
1206
1227
|
|
|
1228
|
+
this.input.focused = this.focused;
|
|
1229
|
+
const [inputLine = ""] = this.input.render(Math.max(1, innerW - 8));
|
|
1207
1230
|
lines.push(border(`╭${"─".repeat(innerW)}╮`));
|
|
1208
|
-
lines.push(
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
lines.push(border("│") + padLine(th.fg("dim", " (passive)")) + border("│"));
|
|
1216
|
-
}
|
|
1231
|
+
lines.push(
|
|
1232
|
+
border("│") +
|
|
1233
|
+
padLine(
|
|
1234
|
+
` ${th.fg(this.color, this.label)} ${this.focused ? th.fg("success", "FOCUSED") : th.fg("dim", "visible")}`,
|
|
1235
|
+
) +
|
|
1236
|
+
border("│"),
|
|
1237
|
+
);
|
|
1217
1238
|
lines.push(border("│") + padLine("") + border("│"));
|
|
1239
|
+
lines.push(border("│") + padLine(` Input: ${inputLine}`) + border("│"));
|
|
1240
|
+
lines.push(border("│") + padLine(` Keys: ${recent}`) + border("│"));
|
|
1241
|
+
lines.push(border("│") + padLine(th.fg("dim", " Tab/Shift+Tab focus")) + border("│"));
|
|
1242
|
+
lines.push(border("│") + padLine(th.fg("dim", " Esc/Ctrl+D dismiss")) + border("│"));
|
|
1218
1243
|
lines.push(border(`╰${"─".repeat(innerW)}╯`));
|
|
1219
1244
|
|
|
1220
1245
|
return lines;
|
|
@@ -1224,21 +1249,16 @@ class FocusPanel extends BaseOverlay {
|
|
|
1224
1249
|
// === Streaming input panel test (/overlay-streaming) ===
|
|
1225
1250
|
|
|
1226
1251
|
class StreamingInputController extends BaseOverlay {
|
|
1252
|
+
private tui: TUI;
|
|
1227
1253
|
private panels: StreamingInputPanel[] = [];
|
|
1228
1254
|
private handles: OverlayHandle[] = [];
|
|
1229
1255
|
private focusIndex = -1; // -1 = controller focused, 0-2 = panel focused
|
|
1230
1256
|
private streamLines: string[] = [];
|
|
1231
1257
|
private streamInterval: ReturnType<typeof setInterval> | null = null;
|
|
1232
1258
|
private lineCount = 0;
|
|
1259
|
+
private done: () => void;
|
|
1233
1260
|
|
|
1234
|
-
|
|
1235
|
-
declare private done: () => void;
|
|
1236
|
-
|
|
1237
|
-
constructor(
|
|
1238
|
-
tui: TUI,
|
|
1239
|
-
theme: Theme,
|
|
1240
|
-
done: () => void,
|
|
1241
|
-
) {
|
|
1261
|
+
constructor(tui: TUI, theme: Theme, done: () => void) {
|
|
1242
1262
|
super(theme);
|
|
1243
1263
|
this.tui = tui;
|
|
1244
1264
|
this.done = done;
|
|
@@ -1361,13 +1381,12 @@ class StreamingInputController extends BaseOverlay {
|
|
|
1361
1381
|
|
|
1362
1382
|
class StreamingInputPanel implements Component {
|
|
1363
1383
|
handle: OverlayHandle | null = null;
|
|
1384
|
+
private theme: Theme;
|
|
1364
1385
|
private typed = "";
|
|
1365
1386
|
readonly label: string;
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
declare private onTab: () => void;
|
|
1370
|
-
declare private onClose: () => void;
|
|
1387
|
+
private color: "error" | "success" | "accent";
|
|
1388
|
+
private onTab: () => void;
|
|
1389
|
+
private onClose: () => void;
|
|
1371
1390
|
|
|
1372
1391
|
constructor(
|
|
1373
1392
|
theme: Theme,
|
|
@@ -1377,10 +1396,10 @@ class StreamingInputPanel implements Component {
|
|
|
1377
1396
|
onClose: () => void,
|
|
1378
1397
|
) {
|
|
1379
1398
|
this.theme = theme;
|
|
1399
|
+
this.label = label;
|
|
1380
1400
|
this.color = color;
|
|
1381
1401
|
this.onTab = onTab;
|
|
1382
1402
|
this.onClose = onClose;
|
|
1383
|
-
this.label = label;
|
|
1384
1403
|
}
|
|
1385
1404
|
|
|
1386
1405
|
handleInput(data: string): void {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Overlay Test - validates overlay compositing with inline text inputs
|
|
3
3
|
*
|
|
4
|
-
* Usage:
|
|
4
|
+
* Usage: atomic --extension ./examples/extensions/overlay-test.ts
|
|
5
5
|
*
|
|
6
6
|
* Run /overlay-test to show a floating overlay with:
|
|
7
7
|
* - Inline text inputs within menu items
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* change agent behavior based on extension state.
|
|
6
6
|
*
|
|
7
7
|
* Usage:
|
|
8
|
-
* 1. Copy this file to ~/.
|
|
8
|
+
* 1. Copy this file to ~/.atomic/agent/extensions/ or your project's .atomic/extensions/ (legacy .pi/extensions/ also works)
|
|
9
9
|
* 2. Use /pirate to toggle pirate mode
|
|
10
10
|
* 3. When enabled, the agent will respond like a pirate
|
|
11
11
|
*/
|