@alumbwe/anvil 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -0
- package/bin/anvil +2 -0
- package/bin/tree-sitter.wasm +0 -0
- package/package.json +67 -0
- package/src/__tests__/README.md +256 -0
- package/src/__tests__/bash-mode.test.ts +442 -0
- package/src/__tests__/cli-args.test.ts +181 -0
- package/src/__tests__/cli-harness.test.ts +52 -0
- package/src/__tests__/e2e/first-time-login.test.ts +173 -0
- package/src/__tests__/e2e/logout-relogin-flow.test.ts +110 -0
- package/src/__tests__/e2e/returning-user-auth.test.ts +113 -0
- package/src/__tests__/e2e-cli.test.ts +183 -0
- package/src/__tests__/helpers/launcher-disconnect-fixture.cjs +176 -0
- package/src/__tests__/helpers/mock-api-client.ts +64 -0
- package/src/__tests__/helpers/renderer-cleanup-fixture.tsx +89 -0
- package/src/__tests__/helpers/terminal-watchdog-fixture.ts +75 -0
- package/src/__tests__/home-directory-detection.test.ts +213 -0
- package/src/__tests__/integration/api-integration.test.ts +288 -0
- package/src/__tests__/integration/credentials-storage.test.ts +486 -0
- package/src/__tests__/integration/local-agents.test.ts +1187 -0
- package/src/__tests__/integration/login-flow-instrumentation.test.ts +134 -0
- package/src/__tests__/integration/login-polling-working.test.ts +285 -0
- package/src/__tests__/integration/queue-editing.test.tsx +261 -0
- package/src/__tests__/integration/usage-refresh-on-completion.test.ts +168 -0
- package/src/__tests__/integration-tmux.test.ts +188 -0
- package/src/__tests__/launcher-avx2-fallback.test.ts +630 -0
- package/src/__tests__/launcher-disconnect.test.ts +104 -0
- package/src/__tests__/mocks/hover-toggle-controller.ts +71 -0
- package/src/__tests__/open-tui-native-bundle.test.ts +378 -0
- package/src/__tests__/path-completion.test.ts +243 -0
- package/src/__tests__/project-files-chat-id.test.ts +34 -0
- package/src/__tests__/release/proxy-http-get.test.ts +667 -0
- package/src/__tests__/release/wrapper-safety.test.ts +412 -0
- package/src/__tests__/renderer-cleanup.test.ts +174 -0
- package/src/__tests__/rerender-perf.integration.test.ts +283 -0
- package/src/__tests__/terminal-reset-sequences.test.ts +36 -0
- package/src/__tests__/terminal-watchdog.test.ts +388 -0
- package/src/__tests__/test-utils.ts +271 -0
- package/src/__tests__/tmux-poc.ts +150 -0
- package/src/__tests__/unit/agent-mode-toggle.test.ts +137 -0
- package/src/__tests__/unit/copy-button.test.ts +157 -0
- package/src/__tests__/unit/create-run-config.test.ts +66 -0
- package/src/__tests__/unit/publish-confirmation.test.ts +70 -0
- package/src/__tests__/unit/segmented-control.test.ts +152 -0
- package/src/__tests__/utils/env.test.ts +169 -0
- package/src/__tests__/utils/project-picker.test.ts +39 -0
- package/src/agents/bundled-agents.generated.d.ts +14 -0
- package/src/agents/bundled-agents.generated.ts +3692 -0
- package/src/app.tsx +399 -0
- package/src/chat.tsx +1698 -0
- package/src/cli-args.ts +134 -0
- package/src/commands/__tests__/bash-command.test.ts +445 -0
- package/src/commands/__tests__/command-args.test.ts +349 -0
- package/src/commands/__tests__/copy-conversation-clipboard.test.ts +108 -0
- package/src/commands/__tests__/copy-conversation.test.ts +226 -0
- package/src/commands/__tests__/diagnostics-command.test.ts +35 -0
- package/src/commands/__tests__/freebuff-command-aliases.test.ts +56 -0
- package/src/commands/__tests__/image.test.ts +99 -0
- package/src/commands/__tests__/init.test.ts +456 -0
- package/src/commands/__tests__/new-command-rotates-chat.test.ts +91 -0
- package/src/commands/__tests__/process-diagnostics.test.ts +54 -0
- package/src/commands/__tests__/prompt-builders.test.ts +28 -0
- package/src/commands/__tests__/router-input.test.ts +298 -0
- package/src/commands/ads.ts +44 -0
- package/src/commands/command-registry.ts +726 -0
- package/src/commands/copy-conversation.ts +392 -0
- package/src/commands/help.ts +13 -0
- package/src/commands/image.ts +20 -0
- package/src/commands/init.ts +121 -0
- package/src/commands/process-diagnostics.ts +120 -0
- package/src/commands/prompt-builders.ts +100 -0
- package/src/commands/publish.ts +203 -0
- package/src/commands/router-utils.ts +80 -0
- package/src/commands/router.ts +487 -0
- package/src/commands/usage.ts +26 -0
- package/src/components/__tests__/ad-banner.test.tsx +83 -0
- package/src/components/__tests__/chat-input-bar.test.tsx +130 -0
- package/src/components/__tests__/freebuff-landing-heading-row.test.tsx +91 -0
- package/src/components/__tests__/freebuff-model-selector.test.tsx +519 -0
- package/src/components/__tests__/freebuff-offer-invariants.test.ts +54 -0
- package/src/components/__tests__/freebuff-takeover-prompt.test.tsx +212 -0
- package/src/components/__tests__/grid-layout.integration.test.tsx +304 -0
- package/src/components/__tests__/grid-layout.test.tsx +1051 -0
- package/src/components/__tests__/message-block.completion.test.tsx +104 -0
- package/src/components/__tests__/message-block.streaming.test.tsx +78 -0
- package/src/components/__tests__/message-with-agents.test.tsx +579 -0
- package/src/components/__tests__/multiline-input.test.tsx +1132 -0
- package/src/components/__tests__/queue-panel.test.tsx +398 -0
- package/src/components/__tests__/selectable-list.test.ts +232 -0
- package/src/components/__tests__/status-bar.test.tsx +44 -0
- package/src/components/__tests__/status-indicator.test.tsx +204 -0
- package/src/components/__tests__/terminal-thinking-orb.test.tsx +111 -0
- package/src/components/__tests__/user-error-banner.test.tsx +102 -0
- package/src/components/ad-banner.tsx +323 -0
- package/src/components/agent-checklist.tsx +350 -0
- package/src/components/agent-mode-toggle.tsx +241 -0
- package/src/components/anvil-mark.tsx +52 -0
- package/src/components/ask-user/__tests__/multiple-choice-form.test.ts +432 -0
- package/src/components/ask-user/__tests__/validation.test.ts +213 -0
- package/src/components/ask-user/components/accordion-question.tsx +153 -0
- package/src/components/ask-user/components/custom-answer-input.tsx +66 -0
- package/src/components/ask-user/components/options-list.tsx +133 -0
- package/src/components/ask-user/components/question-header.tsx +80 -0
- package/src/components/ask-user/components/question-option.tsx +89 -0
- package/src/components/ask-user/constants.ts +38 -0
- package/src/components/ask-user/index.tsx +631 -0
- package/src/components/ask-user/utils/validation.ts +85 -0
- package/src/components/attachment-card.tsx +65 -0
- package/src/components/blocks/agent-block-grid.tsx +58 -0
- package/src/components/blocks/agent-branch-item.tsx +311 -0
- package/src/components/blocks/agent-branch-wrapper.tsx +493 -0
- package/src/components/blocks/agent-list-branch.tsx +77 -0
- package/src/components/blocks/ask-user-branch.tsx +81 -0
- package/src/components/blocks/block-helpers.ts +11 -0
- package/src/components/blocks/blocks-renderer.tsx +289 -0
- package/src/components/blocks/content-with-markdown.tsx +33 -0
- package/src/components/blocks/image-block.tsx +128 -0
- package/src/components/blocks/implementor-row.tsx +429 -0
- package/src/components/blocks/single-block.tsx +201 -0
- package/src/components/blocks/thinking-block.tsx +67 -0
- package/src/components/blocks/tool-block-group.tsx +57 -0
- package/src/components/blocks/tool-branch.tsx +206 -0
- package/src/components/blocks/user-content-copy.tsx +157 -0
- package/src/components/bottom-banner.tsx +136 -0
- package/src/components/build-mode-buttons.tsx +110 -0
- package/src/components/button.tsx +66 -0
- package/src/components/chat-header.tsx +77 -0
- package/src/components/chat-history-screen.tsx +413 -0
- package/src/components/chat-input-bar.tsx +523 -0
- package/src/components/clickable-title-box.tsx +66 -0
- package/src/components/clickable.tsx +119 -0
- package/src/components/collapse-button.tsx +34 -0
- package/src/components/copy-button.tsx +203 -0
- package/src/components/elapsed-timer.tsx +55 -0
- package/src/components/error-boundary.tsx +55 -0
- package/src/components/feedback-container.tsx +181 -0
- package/src/components/feedback-icon-button.tsx +89 -0
- package/src/components/feedback-input-mode.tsx +344 -0
- package/src/components/file-attachment-card.tsx +98 -0
- package/src/components/freebuff-active-session-summary.tsx +63 -0
- package/src/components/freebuff-landing-screen.tsx +865 -0
- package/src/components/freebuff-model-selector.tsx +1087 -0
- package/src/components/freebuff-referral-banner.tsx +604 -0
- package/src/components/freebuff-superseded-screen.tsx +62 -0
- package/src/components/grid-layout.tsx +80 -0
- package/src/components/help-banner.tsx +127 -0
- package/src/components/highlighted-text.tsx +52 -0
- package/src/components/image-card.tsx +167 -0
- package/src/components/image-thumbnail.tsx +114 -0
- package/src/components/input-cursor.tsx +77 -0
- package/src/components/input-mode-banner.tsx +57 -0
- package/src/components/load-previous-button.tsx +48 -0
- package/src/components/login-modal.tsx +475 -0
- package/src/components/message-block.tsx +346 -0
- package/src/components/message-footer.tsx +258 -0
- package/src/components/message-with-agents.tsx +506 -0
- package/src/components/mode-divider.tsx +43 -0
- package/src/components/multiline-input.tsx +1241 -0
- package/src/components/out-of-credits-banner.tsx +160 -0
- package/src/components/pending-attachments-banner.tsx +116 -0
- package/src/components/pending-bash-message.tsx +59 -0
- package/src/components/progress-bar.tsx +81 -0
- package/src/components/project-picker-screen.tsx +485 -0
- package/src/components/publish-confirmation.tsx +493 -0
- package/src/components/publish-container.tsx +687 -0
- package/src/components/queue-panel.tsx +310 -0
- package/src/components/raised-pill.tsx +95 -0
- package/src/components/renderers/plan-box.tsx +59 -0
- package/src/components/review-screen.tsx +112 -0
- package/src/components/scroll-to-bottom-button.tsx +34 -0
- package/src/components/segmented-control.tsx +187 -0
- package/src/components/selectable-list.tsx +248 -0
- package/src/components/selected-chips.tsx +80 -0
- package/src/components/separator.tsx +40 -0
- package/src/components/session-ended-banner.tsx +226 -0
- package/src/components/shimmer-text.tsx +248 -0
- package/src/components/status-bar.tsx +313 -0
- package/src/components/subscription-limit-banner.tsx +206 -0
- package/src/components/suggested-prompts.tsx +184 -0
- package/src/components/suggestion-menu.tsx +215 -0
- package/src/components/terminal-command-display.tsx +151 -0
- package/src/components/terminal-link.tsx +97 -0
- package/src/components/terminal-thinking-orb.tsx +95 -0
- package/src/components/text-attachment-card.tsx +77 -0
- package/src/components/thinking.tsx +109 -0
- package/src/components/tools/__tests__/apply-patch.test.tsx +84 -0
- package/src/components/tools/__tests__/code-search.test.tsx +45 -0
- package/src/components/tools/__tests__/gravity-index.test.ts +76 -0
- package/src/components/tools/__tests__/render-ui.test.tsx +92 -0
- package/src/components/tools/__tests__/run-terminal-command.test.ts +233 -0
- package/src/components/tools/apply-patch.tsx +95 -0
- package/src/components/tools/code-search.tsx +45 -0
- package/src/components/tools/composio.tsx +152 -0
- package/src/components/tools/diff-viewer.tsx +76 -0
- package/src/components/tools/glob.tsx +61 -0
- package/src/components/tools/gravity-index.tsx +77 -0
- package/src/components/tools/list-directory.tsx +61 -0
- package/src/components/tools/read-docs.tsx +37 -0
- package/src/components/tools/read-files.tsx +91 -0
- package/src/components/tools/read-subtree.tsx +44 -0
- package/src/components/tools/read-url.tsx +33 -0
- package/src/components/tools/registry.ts +126 -0
- package/src/components/tools/render-ui.tsx +122 -0
- package/src/components/tools/run-terminal-command.tsx +79 -0
- package/src/components/tools/skill.tsx +29 -0
- package/src/components/tools/str-replace.tsx +77 -0
- package/src/components/tools/suggest-followups.tsx +369 -0
- package/src/components/tools/task-completed.tsx +16 -0
- package/src/components/tools/tool-call-item.tsx +273 -0
- package/src/components/tools/types.ts +55 -0
- package/src/components/tools/web-search.tsx +33 -0
- package/src/components/tools/write-file.tsx +16 -0
- package/src/components/tools/write-todos.tsx +95 -0
- package/src/components/top-banner.tsx +178 -0
- package/src/components/usage-banner.tsx +244 -0
- package/src/components/user-error-banner.tsx +56 -0
- package/src/components/validation-error-popover.tsx +192 -0
- package/src/contexts/__tests__/chat-runtime-context.test.tsx +149 -0
- package/src/contexts/chat-runtime-context.tsx +240 -0
- package/src/data/slash-commands.test.ts +24 -0
- package/src/data/slash-commands.ts +249 -0
- package/src/entry.ts +12 -0
- package/src/hooks/__tests__/holds-live-freebuff-slot.test.ts +49 -0
- package/src/hooks/__tests__/session-fetch-signal.test.ts +63 -0
- package/src/hooks/__tests__/use-activity-query.test.ts +1000 -0
- package/src/hooks/__tests__/use-ask-user-bridge.test.ts +176 -0
- package/src/hooks/__tests__/use-auth-query.test.ts +21 -0
- package/src/hooks/__tests__/use-chat-input-remount.test.tsx +66 -0
- package/src/hooks/__tests__/use-clipboard.test.tsx +73 -0
- package/src/hooks/__tests__/use-connection-status.test.ts +112 -0
- package/src/hooks/__tests__/use-directory-browser.test.ts +203 -0
- package/src/hooks/__tests__/use-gravity-ad.test.ts +73 -0
- package/src/hooks/__tests__/use-grid-layout.test.ts +349 -0
- package/src/hooks/__tests__/use-input-history.test.ts +699 -0
- package/src/hooks/__tests__/use-message-queue-editing.test.tsx +209 -0
- package/src/hooks/__tests__/use-message-queue.test.tsx +71 -0
- package/src/hooks/__tests__/use-path-tab-completion.test.ts +315 -0
- package/src/hooks/__tests__/use-queue-controls.test.ts +68 -0
- package/src/hooks/__tests__/use-queue-ui.test.tsx +83 -0
- package/src/hooks/__tests__/use-searchable-list.test.ts +359 -0
- package/src/hooks/__tests__/use-send-message-timer.test.ts +146 -0
- package/src/hooks/__tests__/use-suggestion-engine-mention.test.ts +361 -0
- package/src/hooks/__tests__/use-suggestion-engine.test.ts +485 -0
- package/src/hooks/__tests__/use-terminal-focus.test.ts +66 -0
- package/src/hooks/__tests__/use-terminal-layout.test.ts +675 -0
- package/src/hooks/__tests__/use-timeout.test.ts +330 -0
- package/src/hooks/__tests__/use-usage-query.test.ts +502 -0
- package/src/hooks/__tests__/use-user-details-query.test.ts +195 -0
- package/src/hooks/helpers/__tests__/send-message.test.ts +1918 -0
- package/src/hooks/helpers/send-message.ts +654 -0
- package/src/hooks/stream-state.ts +83 -0
- package/src/hooks/use-activity-query.ts +668 -0
- package/src/hooks/use-agent-validation.ts +74 -0
- package/src/hooks/use-ask-user-bridge.ts +92 -0
- package/src/hooks/use-auth-query.ts +253 -0
- package/src/hooks/use-auth-state.ts +152 -0
- package/src/hooks/use-chat-input.ts +105 -0
- package/src/hooks/use-chat-keyboard.ts +321 -0
- package/src/hooks/use-chat-messages.ts +254 -0
- package/src/hooks/use-chat-state.ts +165 -0
- package/src/hooks/use-chat-streaming.ts +180 -0
- package/src/hooks/use-chat-ui.ts +131 -0
- package/src/hooks/use-clipboard.ts +151 -0
- package/src/hooks/use-connection-status.ts +142 -0
- package/src/hooks/use-directory-browser.ts +88 -0
- package/src/hooks/use-elapsed-time.ts +116 -0
- package/src/hooks/use-event.ts +34 -0
- package/src/hooks/use-exit-handler.ts +66 -0
- package/src/hooks/use-fetch-login-url.ts +65 -0
- package/src/hooks/use-fingerprint.ts +61 -0
- package/src/hooks/use-freebuff-ctrl-c-exit.ts +23 -0
- package/src/hooks/use-freebuff-session-progress.ts +34 -0
- package/src/hooks/use-freebuff-session.ts +806 -0
- package/src/hooks/use-freebuff-streak-query.ts +61 -0
- package/src/hooks/use-gravity-ad.ts +656 -0
- package/src/hooks/use-grid-layout.ts +73 -0
- package/src/hooks/use-input-history.ts +173 -0
- package/src/hooks/use-login-keyboard-handlers.ts +75 -0
- package/src/hooks/use-login-polling.ts +114 -0
- package/src/hooks/use-logo.tsx +161 -0
- package/src/hooks/use-message-queue.ts +387 -0
- package/src/hooks/use-now.ts +20 -0
- package/src/hooks/use-path-tab-completion.ts +88 -0
- package/src/hooks/use-publish-mutation.ts +60 -0
- package/src/hooks/use-queue-controls.ts +68 -0
- package/src/hooks/use-queue-ui.ts +74 -0
- package/src/hooks/use-scroll-management.ts +184 -0
- package/src/hooks/use-searchable-list.ts +98 -0
- package/src/hooks/use-send-message.ts +773 -0
- package/src/hooks/use-sheen-animation.tsx +88 -0
- package/src/hooks/use-subscription-query.ts +71 -0
- package/src/hooks/use-suggestion-engine.ts +783 -0
- package/src/hooks/use-terminal-breakpoints.ts +77 -0
- package/src/hooks/use-terminal-dimensions.ts +46 -0
- package/src/hooks/use-terminal-focus.ts +29 -0
- package/src/hooks/use-terminal-layout.ts +189 -0
- package/src/hooks/use-theme.tsx +140 -0
- package/src/hooks/use-timeout.ts +85 -0
- package/src/hooks/use-update-preference.ts +66 -0
- package/src/hooks/use-usage-monitor.ts +55 -0
- package/src/hooks/use-usage-query.ts +124 -0
- package/src/hooks/use-user-details-query.ts +93 -0
- package/src/hooks/use-why-did-you-update.ts +177 -0
- package/src/index.tsx +441 -0
- package/src/init/__tests__/init-direnv.test.ts +526 -0
- package/src/init/init-app.ts +34 -0
- package/src/init/init-direnv.ts +133 -0
- package/src/login/constants.ts +60 -0
- package/src/login/login-flow.ts +204 -0
- package/src/login/plain-login.ts +108 -0
- package/src/login/utils.ts +183 -0
- package/src/native/ripgrep.ts +80 -0
- package/src/polyfills/bun-strip-ansi.ts +12 -0
- package/src/pre-init/tree-sitter-wasm.ts +96 -0
- package/src/project-files.ts +102 -0
- package/src/smoke/terminal-command-broker.ts +439 -0
- package/src/state/__tests__/chat-store-focus.test.ts +22 -0
- package/src/state/__tests__/feedback-store.test.ts +257 -0
- package/src/state/chat-history-store.ts +30 -0
- package/src/state/chat-store.ts +544 -0
- package/src/state/feedback-store.ts +160 -0
- package/src/state/freebuff-model-store.ts +42 -0
- package/src/state/freebuff-session-store.ts +53 -0
- package/src/state/login-store.ts +150 -0
- package/src/state/message-block-store.ts +149 -0
- package/src/state/publish-store.ts +146 -0
- package/src/state/queue-panel-store.ts +26 -0
- package/src/state/review-store.ts +24 -0
- package/src/testing/env.ts +46 -0
- package/src/types/chat-state.ts +15 -0
- package/src/types/chat.ts +241 -0
- package/src/types/contracts/send-message.ts +12 -0
- package/src/types/env.ts +98 -0
- package/src/types/freebuff-session.ts +17 -0
- package/src/types/function-params.ts +28 -0
- package/src/types/react19-compat.d.ts +19 -0
- package/src/types/store.ts +111 -0
- package/src/types/theme-system.ts +144 -0
- package/src/types/utils.ts +3 -0
- package/src/utils/__tests__/active-run.test.ts +140 -0
- package/src/utils/__tests__/activity-tracker.test.ts +440 -0
- package/src/utils/__tests__/agent-display.test.ts +139 -0
- package/src/utils/__tests__/analytics-client.test.ts +262 -0
- package/src/utils/__tests__/anonymous-id.test.ts +74 -0
- package/src/utils/__tests__/anvil-api.test.ts +578 -0
- package/src/utils/__tests__/arrays.test.ts +264 -0
- package/src/utils/__tests__/bash-context-processor.test.ts +38 -0
- package/src/utils/__tests__/block-processor.test.ts +810 -0
- package/src/utils/__tests__/chat-history.test.ts +203 -0
- package/src/utils/__tests__/chat-input-key-intercept.test.ts +40 -0
- package/src/utils/__tests__/chat-meta.test.ts +130 -0
- package/src/utils/__tests__/clipboard-linux.test.ts +359 -0
- package/src/utils/__tests__/clipboard.test.ts +910 -0
- package/src/utils/__tests__/code-search-summary.test.ts +84 -0
- package/src/utils/__tests__/collapse-helpers.test.ts +1109 -0
- package/src/utils/__tests__/error-handling.test.ts +658 -0
- package/src/utils/__tests__/exit-cleanly.test.ts +110 -0
- package/src/utils/__tests__/feedback-helpers.test.ts +444 -0
- package/src/utils/__tests__/feedback-submission.test.ts +26 -0
- package/src/utils/__tests__/fetch-usage.test.ts +355 -0
- package/src/utils/__tests__/fingerprint.test.ts +144 -0
- package/src/utils/__tests__/fixtures/terminal-command-broker-child.ts +7 -0
- package/src/utils/__tests__/fixtures/terminal-command-broker-entry.ts +3 -0
- package/src/utils/__tests__/fixtures/terminal-command-broker-owner.ts +33 -0
- package/src/utils/__tests__/format-elapsed-time.test.ts +103 -0
- package/src/utils/__tests__/format-timeout.test.ts +87 -0
- package/src/utils/__tests__/freebuff-instance-owner.test.ts +69 -0
- package/src/utils/__tests__/freebuff-model-navigation.test.ts +102 -0
- package/src/utils/__tests__/freebuff-premium-reset.test.ts +79 -0
- package/src/utils/__tests__/freebuff-referral-cache.test.ts +116 -0
- package/src/utils/__tests__/freebuff-session-api.test.ts +215 -0
- package/src/utils/__tests__/freebuff-session-display.test.ts +23 -0
- package/src/utils/__tests__/freebuff-streak-line.test.ts +217 -0
- package/src/utils/__tests__/image-dimensions.test.ts +249 -0
- package/src/utils/__tests__/image-processor.test.ts +209 -0
- package/src/utils/__tests__/implementor-helpers.test.ts +1458 -0
- package/src/utils/__tests__/keyboard-actions.test.ts +660 -0
- package/src/utils/__tests__/layout-helpers.test.ts +36 -0
- package/src/utils/__tests__/lazy-response-ads.test.ts +167 -0
- package/src/utils/__tests__/log-shipper.test.ts +53 -0
- package/src/utils/__tests__/markdown-renderer.test.tsx +421 -0
- package/src/utils/__tests__/message-block-helpers.test.ts +1263 -0
- package/src/utils/__tests__/message-updater.test.ts +645 -0
- package/src/utils/__tests__/osc-timeout-scenarios.test.ts +172 -0
- package/src/utils/__tests__/pending-attachments.test.ts +277 -0
- package/src/utils/__tests__/polling-backoff.test.ts +51 -0
- package/src/utils/__tests__/queue-panel-actions.test.ts +148 -0
- package/src/utils/__tests__/run-state-storage.test.ts +919 -0
- package/src/utils/__tests__/safe-json.test.ts +77 -0
- package/src/utils/__tests__/sdk-event-handlers.test.ts +685 -0
- package/src/utils/__tests__/send-message-helpers.test.ts +1898 -0
- package/src/utils/__tests__/send-message-timer.test.ts +64 -0
- package/src/utils/__tests__/settings.test.ts +99 -0
- package/src/utils/__tests__/strings.test.ts +192 -0
- package/src/utils/__tests__/terminal-color-detection.test.ts +425 -0
- package/src/utils/__tests__/terminal-command-broker.test.ts +528 -0
- package/src/utils/__tests__/terminal-enter-detection.test.ts +77 -0
- package/src/utils/__tests__/terminal-io.test.ts +137 -0
- package/src/utils/__tests__/terminal-protocol-controller.test.ts +119 -0
- package/src/utils/__tests__/text-layout.test.ts +82 -0
- package/src/utils/__tests__/theme-platform-detection.test.ts +125 -0
- package/src/utils/__tests__/think-tag-parser.test.ts +159 -0
- package/src/utils/__tests__/trace-writer.test.ts +223 -0
- package/src/utils/__tests__/trim-chat-logs.test.ts +78 -0
- package/src/utils/__tests__/usage-banner-state.test.ts +298 -0
- package/src/utils/__tests__/validation-error-formatting.test.ts +126 -0
- package/src/utils/__tests__/windows-terminal-health.test.ts +101 -0
- package/src/utils/__tests__/write-file-atomic.test.ts +127 -0
- package/src/utils/active-run.ts +131 -0
- package/src/utils/activity-tracker.ts +66 -0
- package/src/utils/agent-display.ts +87 -0
- package/src/utils/agent-helpers.ts +27 -0
- package/src/utils/agent-id-utils.ts +14 -0
- package/src/utils/ai-message-id.ts +12 -0
- package/src/utils/analytics.ts +361 -0
- package/src/utils/anonymous-id.ts +87 -0
- package/src/utils/anvil-api.ts +612 -0
- package/src/utils/anvil-client.ts +217 -0
- package/src/utils/arrays.ts +117 -0
- package/src/utils/auth.ts +258 -0
- package/src/utils/bash-context-processor.ts +47 -0
- package/src/utils/bash-messages.ts +108 -0
- package/src/utils/block-margins.ts +35 -0
- package/src/utils/block-operations.ts +523 -0
- package/src/utils/block-processor.ts +213 -0
- package/src/utils/chat-history.ts +253 -0
- package/src/utils/chat-input-key-intercept.ts +52 -0
- package/src/utils/chat-meta.ts +90 -0
- package/src/utils/chat-scroll-accel.ts +151 -0
- package/src/utils/clipboard-image.ts +588 -0
- package/src/utils/clipboard.ts +397 -0
- package/src/utils/code-search-summary.ts +70 -0
- package/src/utils/collapse-helpers.ts +256 -0
- package/src/utils/config-dir.ts +24 -0
- package/src/utils/constants.ts +190 -0
- package/src/utils/create-event-handler-state.ts +73 -0
- package/src/utils/create-run-config.ts +121 -0
- package/src/utils/detect-shell.ts +116 -0
- package/src/utils/directory-browser.ts +72 -0
- package/src/utils/engagement.ts +55 -0
- package/src/utils/env.ts +92 -0
- package/src/utils/error-handling.ts +255 -0
- package/src/utils/error-messages.ts +62 -0
- package/src/utils/exit-cleanly.ts +86 -0
- package/src/utils/feedback-helpers.ts +103 -0
- package/src/utils/feedback-submission.ts +22 -0
- package/src/utils/fetch-usage.ts +76 -0
- package/src/utils/fingerprint.ts +245 -0
- package/src/utils/format-elapsed-time.ts +33 -0
- package/src/utils/format-session-units.ts +6 -0
- package/src/utils/format-timeout.ts +28 -0
- package/src/utils/format-validation-errors-for-message.ts +84 -0
- package/src/utils/freebuff-agent-selection.ts +33 -0
- package/src/utils/freebuff-instance-owner.ts +66 -0
- package/src/utils/freebuff-model-navigation.ts +50 -0
- package/src/utils/freebuff-premium-reset.ts +55 -0
- package/src/utils/freebuff-referral-cache.ts +51 -0
- package/src/utils/freebuff-session-api.ts +243 -0
- package/src/utils/freebuff-session-display.ts +21 -0
- package/src/utils/freebuff-streak-line.ts +93 -0
- package/src/utils/git.ts +17 -0
- package/src/utils/helpers.ts +47 -0
- package/src/utils/image-display.ts +67 -0
- package/src/utils/image-handler.ts +325 -0
- package/src/utils/image-processor.ts +133 -0
- package/src/utils/image-thumbnail.ts +78 -0
- package/src/utils/implementor-helpers.ts +787 -0
- package/src/utils/input-modes.ts +174 -0
- package/src/utils/keyboard-actions.ts +392 -0
- package/src/utils/keypad-keys.ts +47 -0
- package/src/utils/layout-helpers.ts +33 -0
- package/src/utils/lazy-response-ads.ts +1 -0
- package/src/utils/local-agent-registry.ts +474 -0
- package/src/utils/log-shipper.ts +126 -0
- package/src/utils/logger.ts +327 -0
- package/src/utils/markdown-renderer.tsx +1090 -0
- package/src/utils/math.ts +3 -0
- package/src/utils/message-block-helpers.ts +684 -0
- package/src/utils/message-history.ts +143 -0
- package/src/utils/message-tree-utils.ts +67 -0
- package/src/utils/message-updater.ts +279 -0
- package/src/utils/open-file.ts +146 -0
- package/src/utils/open-url.ts +63 -0
- package/src/utils/path-completion.ts +111 -0
- package/src/utils/path-helpers.ts +38 -0
- package/src/utils/pending-attachments.ts +360 -0
- package/src/utils/polling-backoff.ts +59 -0
- package/src/utils/project-picker.ts +12 -0
- package/src/utils/queue-panel-actions.ts +70 -0
- package/src/utils/recent-projects.ts +156 -0
- package/src/utils/renderer-cleanup.ts +233 -0
- package/src/utils/response-ad-positions.ts +1 -0
- package/src/utils/run-state-storage.ts +603 -0
- package/src/utils/safe-json.ts +153 -0
- package/src/utils/sdk-event-handlers.ts +571 -0
- package/src/utils/send-message-helpers.ts +210 -0
- package/src/utils/send-message-timer.ts +110 -0
- package/src/utils/settings.ts +226 -0
- package/src/utils/skill-registry.ts +94 -0
- package/src/utils/spawn-agent-matcher.ts +55 -0
- package/src/utils/status-indicator-state.ts +107 -0
- package/src/utils/stream-chunk-processor.ts +57 -0
- package/src/utils/strings.ts +271 -0
- package/src/utils/subscription.ts +31 -0
- package/src/utils/syntax-highlighter.tsx +19 -0
- package/src/utils/terminal-color-detection.ts +474 -0
- package/src/utils/terminal-command-broker.ts +467 -0
- package/src/utils/terminal-enter-detection.ts +63 -0
- package/src/utils/terminal-images.ts +229 -0
- package/src/utils/terminal-io.ts +85 -0
- package/src/utils/terminal-protocol-controller.ts +173 -0
- package/src/utils/terminal-reset-sequences.ts +33 -0
- package/src/utils/terminal-title.ts +84 -0
- package/src/utils/terminal-watchdog.ts +366 -0
- package/src/utils/text-layout.ts +149 -0
- package/src/utils/theme-config.ts +141 -0
- package/src/utils/theme-system.ts +1206 -0
- package/src/utils/think-tag-parser.ts +95 -0
- package/src/utils/time-format.ts +21 -0
- package/src/utils/trace-writer.ts +162 -0
- package/src/utils/ui-constants.ts +69 -0
- package/src/utils/update-checker.ts +110 -0
- package/src/utils/usage-banner-state.ts +146 -0
- package/src/utils/validation-error-formatting.ts +86 -0
- package/src/utils/validation-error-helpers.ts +19 -0
- package/src/utils/windows-terminal-health.ts +124 -0
- package/src/utils/word-wrap-utils.ts +53 -0
- package/src/utils/write-file-atomic.ts +54 -0
- package/src/utils/yield-to-event-loop.ts +9 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized prompt builders for /plan and /review commands.
|
|
3
|
+
* This ensures consistent behavior regardless of entry path. Both run on the
|
|
4
|
+
* user's currently selected model.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// Base prompts - both always gather context first.
|
|
8
|
+
const PLAN_BASE_PROMPT =
|
|
9
|
+
'Gather all the relevant context and then think carefully about how to implement the following:'
|
|
10
|
+
const REVIEW_BASE_PROMPT =
|
|
11
|
+
'Please gather all relevant context and then carefully review:'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Build a plan prompt from user input.
|
|
15
|
+
* @param input - The user's plan request (e.g., "add OAuth login")
|
|
16
|
+
* @returns The full prompt to send to the agent
|
|
17
|
+
*/
|
|
18
|
+
export function buildPlanPrompt(input: string): string {
|
|
19
|
+
const trimmedInput = input.trim()
|
|
20
|
+
if (!trimmedInput) {
|
|
21
|
+
return PLAN_BASE_PROMPT
|
|
22
|
+
}
|
|
23
|
+
return `${PLAN_BASE_PROMPT}\n\n${trimmedInput}`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Base prompt for interview command - asks clarifying questions before acting
|
|
27
|
+
export const INTERVIEW_BASE_PROMPT = 'Interview me to better understand my request and then create a spec file. First, gather any relevant context (read files, do research, etc.). Then, use several rounds of the ask_user tool to ask non-obvious clarifying questions — things you cannot easily infer from the codebase or my initial message. Ask about edge cases, preferences, constraints, and design decisions. All questions should be directed through the ask_user tool -- not written out as text. Keep coming up with new questions that get at unique aspects of the request. Aim for at least **3 rounds** with multiple questions each round. When satisfied, write a [INSERT_REQUEST_SHORT_NAME]-spec.md file with all the information you have gathered about the request. Aim for as much detail as possible. You should NOT make any code changes yet. Stop after creating the spec file. End by using the suggest_followups tool with ways to flesh out the spec file. Here is my request:'
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Build an interview prompt from user input.
|
|
31
|
+
* @param input - The user's request to be interviewed about
|
|
32
|
+
* @returns The full prompt to send to the agent
|
|
33
|
+
*/
|
|
34
|
+
export function buildInterviewPrompt(input: string): string {
|
|
35
|
+
const trimmedInput = input.trim()
|
|
36
|
+
if (!trimmedInput) {
|
|
37
|
+
return INTERVIEW_BASE_PROMPT
|
|
38
|
+
}
|
|
39
|
+
return `${INTERVIEW_BASE_PROMPT}\n\n${trimmedInput}`
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Review scope presets for the review screen.
|
|
44
|
+
*/
|
|
45
|
+
type ReviewScope = 'conversation' | 'uncommitted' | 'branch' | 'custom'
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the default text for a review scope preset.
|
|
49
|
+
*/
|
|
50
|
+
function getReviewScopeText(scope: ReviewScope): string {
|
|
51
|
+
switch (scope) {
|
|
52
|
+
case 'conversation':
|
|
53
|
+
return 'all changes made in this conversation'
|
|
54
|
+
case 'uncommitted':
|
|
55
|
+
return 'uncommitted changes'
|
|
56
|
+
case 'branch':
|
|
57
|
+
return 'this branch compared to main'
|
|
58
|
+
case 'custom':
|
|
59
|
+
return ''
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Build a review prompt from scope or custom input.
|
|
65
|
+
* @param scope - The selected review scope (conversation, uncommitted, branch, or custom)
|
|
66
|
+
* @param customInput - Optional custom review focus (when scope is 'custom')
|
|
67
|
+
* @returns The full prompt to send to the agent
|
|
68
|
+
*/
|
|
69
|
+
export function buildReviewPrompt(
|
|
70
|
+
scope: ReviewScope,
|
|
71
|
+
customInput?: string,
|
|
72
|
+
): string {
|
|
73
|
+
const scopeText = getReviewScopeText(scope)
|
|
74
|
+
|
|
75
|
+
// For custom input, append the user's specific focus
|
|
76
|
+
if (scope === 'custom' && customInput?.trim()) {
|
|
77
|
+
return `${REVIEW_BASE_PROMPT} ${customInput.trim()}`
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// For preset scopes, use the scope text
|
|
81
|
+
if (scopeText) {
|
|
82
|
+
return `${REVIEW_BASE_PROMPT} ${scopeText}`
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Fallback for custom with no input
|
|
86
|
+
return REVIEW_BASE_PROMPT
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Build a review prompt from direct argument (e.g., /review foo).
|
|
91
|
+
* This is used when the user provides review text directly after the command.
|
|
92
|
+
* @param input - The user's review request
|
|
93
|
+
* @returns The full prompt to send to the agent
|
|
94
|
+
*/
|
|
95
|
+
export function buildReviewPromptFromArgs(input: string): string {
|
|
96
|
+
const trimmedInput = input.trim()
|
|
97
|
+
// Use the same format as preset scopes for consistency
|
|
98
|
+
return `${REVIEW_BASE_PROMPT} ${trimmedInput}`
|
|
99
|
+
}
|
|
100
|
+
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { WEBSITE_URL } from '@anvil/sdk'
|
|
2
|
+
|
|
3
|
+
import { getUserCredentials } from '../utils/auth'
|
|
4
|
+
import { getApiClient, setApiClientAuthToken } from '../utils/anvil-api'
|
|
5
|
+
import { loadAgentDefinitions, getLoadedAgentsData } from '../utils/local-agent-registry'
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
PublishAgentsErrorResponse,
|
|
9
|
+
PublishAgentsResponse,
|
|
10
|
+
} from '@anvil/common/types/api/agents/publish'
|
|
11
|
+
|
|
12
|
+
export interface PublishResult {
|
|
13
|
+
success: boolean
|
|
14
|
+
publisherId?: string
|
|
15
|
+
agents?: Array<{
|
|
16
|
+
id: string
|
|
17
|
+
version: string
|
|
18
|
+
displayName: string
|
|
19
|
+
}>
|
|
20
|
+
error?: string
|
|
21
|
+
details?: string
|
|
22
|
+
hint?: string
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Publish agent templates to the backend
|
|
27
|
+
*/
|
|
28
|
+
async function publishAgentTemplates(
|
|
29
|
+
data: Record<string, any>[],
|
|
30
|
+
authToken: string,
|
|
31
|
+
allLocalAgentIds: string[],
|
|
32
|
+
): Promise<PublishAgentsResponse & { statusCode?: number }> {
|
|
33
|
+
setApiClientAuthToken(authToken)
|
|
34
|
+
const apiClient = getApiClient()
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const response = await apiClient.publish(data, allLocalAgentIds)
|
|
38
|
+
|
|
39
|
+
if (!response.ok) {
|
|
40
|
+
// Try to use the full error data if available (includes details, hint, etc.)
|
|
41
|
+
const errorData = response.errorData as
|
|
42
|
+
| Partial<PublishAgentsErrorResponse>
|
|
43
|
+
| undefined
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
error: errorData?.error ?? response.error ?? 'Unknown error',
|
|
47
|
+
details: errorData?.details,
|
|
48
|
+
hint: errorData?.hint,
|
|
49
|
+
availablePublishers: errorData?.availablePublishers,
|
|
50
|
+
validationErrors: errorData?.validationErrors,
|
|
51
|
+
statusCode: response.status,
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Guard against empty/undefined response data
|
|
56
|
+
if (!response.data) {
|
|
57
|
+
return {
|
|
58
|
+
success: false,
|
|
59
|
+
error: 'Failed to parse server response - empty response body',
|
|
60
|
+
statusCode: response.status,
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
...response.data,
|
|
66
|
+
statusCode: response.status,
|
|
67
|
+
}
|
|
68
|
+
} catch (err: any) {
|
|
69
|
+
if (err instanceof TypeError && err.message.includes('fetch')) {
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
error: `Network error: Unable to connect to ${WEBSITE_URL}. Please check your internet connection and try again.`,
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const body = err?.responseBody || err?.body || err
|
|
77
|
+
const error = body?.error || body?.message || 'Failed to publish'
|
|
78
|
+
const details = body?.details
|
|
79
|
+
const hint = body?.hint
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
success: false,
|
|
83
|
+
error,
|
|
84
|
+
details,
|
|
85
|
+
hint,
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Handle the publish command to upload agent templates to the backend
|
|
92
|
+
* @param agentIds The ids or display names of the agents to publish
|
|
93
|
+
* @returns PublishResult with success/error information
|
|
94
|
+
*/
|
|
95
|
+
export async function handlePublish(agentIds: string[]): Promise<PublishResult> {
|
|
96
|
+
const user = getUserCredentials()
|
|
97
|
+
|
|
98
|
+
if (!user) {
|
|
99
|
+
return {
|
|
100
|
+
success: false,
|
|
101
|
+
error: 'Not logged in',
|
|
102
|
+
hint: 'Please log in first using "login" command or web UI.',
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const availableAgents = getLoadedAgentsData()?.agents || []
|
|
107
|
+
|
|
108
|
+
if (agentIds?.length === 0) {
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: 'No agents specified',
|
|
112
|
+
hint: 'Usage: publish <agent-id> [agent-id2] ...',
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
const loadedDefinitions = loadAgentDefinitions()
|
|
118
|
+
|
|
119
|
+
if (loadedDefinitions.length === 0) {
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
error: 'No valid agent templates found in .agents directory.',
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const matchingTemplates: Record<string, any> = {}
|
|
127
|
+
|
|
128
|
+
for (const agentId of agentIds) {
|
|
129
|
+
// Find the specific agent
|
|
130
|
+
const matchingTemplate = loadedDefinitions.find(
|
|
131
|
+
(template) =>
|
|
132
|
+
template.id === agentId ||
|
|
133
|
+
(template as { displayName?: string }).displayName === agentId,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
if (!matchingTemplate) {
|
|
137
|
+
const availableList = availableAgents
|
|
138
|
+
.map((agent) =>
|
|
139
|
+
agent.displayName && agent.displayName !== agent.id
|
|
140
|
+
? `${agent.displayName} (${agent.id})`
|
|
141
|
+
: agent.displayName || agent.id,
|
|
142
|
+
)
|
|
143
|
+
.join(', ')
|
|
144
|
+
return {
|
|
145
|
+
success: false,
|
|
146
|
+
error: `Agent "${agentId}" not found`,
|
|
147
|
+
details: `Available agents: ${availableList}`,
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Process the template for publishing
|
|
152
|
+
const processedTemplate = { ...matchingTemplate }
|
|
153
|
+
|
|
154
|
+
// Convert handleSteps function to string if present
|
|
155
|
+
if (typeof (matchingTemplate as any).handleSteps === 'function') {
|
|
156
|
+
;(processedTemplate as any).handleSteps = (
|
|
157
|
+
matchingTemplate as any
|
|
158
|
+
).handleSteps.toString()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
matchingTemplates[matchingTemplate.id] = processedTemplate
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Get all local agent IDs so the server knows which agents exist locally
|
|
165
|
+
// (even if not being published) for validation purposes
|
|
166
|
+
const allLocalAgentIds = loadedDefinitions.map((template) => template.id)
|
|
167
|
+
|
|
168
|
+
const result = await publishAgentTemplates(
|
|
169
|
+
Object.values(matchingTemplates),
|
|
170
|
+
user.authToken!,
|
|
171
|
+
allLocalAgentIds,
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
if (result.success) {
|
|
175
|
+
return {
|
|
176
|
+
success: true,
|
|
177
|
+
publisherId: result.publisherId,
|
|
178
|
+
agents: result.agents ?? [],
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Build error result
|
|
183
|
+
let hint = result.hint
|
|
184
|
+
if (result.error?.includes('Publisher field required')) {
|
|
185
|
+
hint = 'Add a "publisher" field to your agent templates.'
|
|
186
|
+
} else if (result.error?.includes('Publisher not found or not accessible')) {
|
|
187
|
+
hint = `Check that the publisher ID is correct and you have access to it. Visit ${WEBSITE_URL}/publishers to manage publishers.`
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
success: false,
|
|
192
|
+
error: result.error,
|
|
193
|
+
details: result.details,
|
|
194
|
+
hint,
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
return {
|
|
198
|
+
success: false,
|
|
199
|
+
error: 'Publish failed',
|
|
200
|
+
details: error instanceof Error ? error.message : String(error),
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { SLASHLESS_COMMAND_IDS } from '../data/slash-commands'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if the input is a slash command (starts with '/').
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* isSlashCommand('/help') // => true
|
|
8
|
+
* isSlashCommand('help') // => false
|
|
9
|
+
*/
|
|
10
|
+
export function isSlashCommand(input: string): boolean {
|
|
11
|
+
return input.trim().startsWith('/')
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Parse the command name from user input.
|
|
16
|
+
* ONLY works for slash commands (input starting with '/').
|
|
17
|
+
* Returns empty string if the input is not a slash command.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* parseCommand('/help') // => 'help'
|
|
21
|
+
* parseCommand('/LOGOUT') // => 'logout'
|
|
22
|
+
* parseCommand('/usage stats') // => 'usage'
|
|
23
|
+
* parseCommand('help') // => '' (not a slash command)
|
|
24
|
+
* parseCommand('logout') // => '' (not a slash command)
|
|
25
|
+
*/
|
|
26
|
+
export function parseCommand(input: string): string {
|
|
27
|
+
const trimmed = input.trim()
|
|
28
|
+
if (!trimmed.startsWith('/')) {
|
|
29
|
+
return ''
|
|
30
|
+
}
|
|
31
|
+
const normalized = trimmed.slice(1)
|
|
32
|
+
const firstWord = normalized.split(/\s+/)[0] || ''
|
|
33
|
+
return firstWord.toLowerCase()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Result of parsing a command-like input.
|
|
38
|
+
*/
|
|
39
|
+
export type ParsedCommandInput = {
|
|
40
|
+
command: string
|
|
41
|
+
args: string
|
|
42
|
+
implicitCommand: boolean
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Parse a command from user input.
|
|
47
|
+
* Supports:
|
|
48
|
+
* - Standard slash commands: "/command args"
|
|
49
|
+
* - Slashless exact commands: "init" (only if configured)
|
|
50
|
+
*
|
|
51
|
+
* Returns null when the input should be treated as a normal message.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* parseCommandInput('/help') // => { command: 'help', args: '', implicitCommand: false }
|
|
55
|
+
* parseCommandInput('/usage stats') // => { command: 'usage', args: 'stats', implicitCommand: false }
|
|
56
|
+
* parseCommandInput('init') // => { command: 'init', args: '', implicitCommand: true }
|
|
57
|
+
* parseCommandInput('init something') // => null
|
|
58
|
+
*/
|
|
59
|
+
export function parseCommandInput(input: string): ParsedCommandInput | null {
|
|
60
|
+
const trimmed = input.trim()
|
|
61
|
+
if (!trimmed) return null
|
|
62
|
+
|
|
63
|
+
if (trimmed.startsWith('/')) {
|
|
64
|
+
const command = parseCommand(trimmed)
|
|
65
|
+
if (!command) return null
|
|
66
|
+
const args = trimmed.slice(1 + command.length).trim()
|
|
67
|
+
return { command, args, implicitCommand: false }
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (/\s/.test(trimmed)) {
|
|
71
|
+
return null
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const normalized = trimmed.toLowerCase()
|
|
75
|
+
if (!SLASHLESS_COMMAND_IDS.has(normalized)) {
|
|
76
|
+
return null
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return { command: normalized, args: '', implicitCommand: true }
|
|
80
|
+
}
|