@butlerw/vellum 0.1.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/LICENSE +21 -0
- package/README.md +411 -0
- package/__fixtures__/responses/code-generation.json +42 -0
- package/__fixtures__/responses/error-response.json +20 -0
- package/__fixtures__/responses/hello-world.json +32 -0
- package/dist/auth-6MCXESOH.js +26 -0
- package/dist/chunk-SECXJGWA.js +597 -0
- package/dist/index.js +34023 -0
- package/package.json +67 -0
- package/src/__tests__/commands.e2e.test.ts +728 -0
- package/src/__tests__/credentials.test.ts +713 -0
- package/src/__tests__/mode-e2e.test.ts +391 -0
- package/src/__tests__/tui-integration.test.tsx +1271 -0
- package/src/agents/__tests__/task-persistence.test.ts +235 -0
- package/src/agents/commands/delegate.ts +240 -0
- package/src/agents/commands/index.ts +10 -0
- package/src/agents/commands/resume.ts +335 -0
- package/src/agents/index.ts +29 -0
- package/src/agents/task-persistence.ts +272 -0
- package/src/agents/task-resumption.ts +242 -0
- package/src/app.tsx +4737 -0
- package/src/commands/__tests__/.gitkeep +1 -0
- package/src/commands/__tests__/agents.test.ts +606 -0
- package/src/commands/__tests__/auth.test.ts +626 -0
- package/src/commands/__tests__/autocomplete.test.ts +683 -0
- package/src/commands/__tests__/batch.test.ts +287 -0
- package/src/commands/__tests__/chain-pipe-parser.test.ts +654 -0
- package/src/commands/__tests__/completion.test.ts +238 -0
- package/src/commands/__tests__/core.test.ts +363 -0
- package/src/commands/__tests__/executor.test.ts +496 -0
- package/src/commands/__tests__/exit-codes.test.ts +220 -0
- package/src/commands/__tests__/init.test.ts +243 -0
- package/src/commands/__tests__/language.test.ts +353 -0
- package/src/commands/__tests__/mode-cli.test.ts +667 -0
- package/src/commands/__tests__/model.test.ts +277 -0
- package/src/commands/__tests__/parser.test.ts +493 -0
- package/src/commands/__tests__/performance.bench.ts +380 -0
- package/src/commands/__tests__/registry.test.ts +534 -0
- package/src/commands/__tests__/resume.test.ts +449 -0
- package/src/commands/__tests__/security.test.ts +845 -0
- package/src/commands/__tests__/stream-json.test.ts +372 -0
- package/src/commands/__tests__/user-commands.test.ts +597 -0
- package/src/commands/adapters.ts +267 -0
- package/src/commands/agent.ts +395 -0
- package/src/commands/agents/generate.ts +506 -0
- package/src/commands/agents/index.ts +272 -0
- package/src/commands/agents/show.ts +271 -0
- package/src/commands/agents/validate.ts +387 -0
- package/src/commands/auth.ts +883 -0
- package/src/commands/autocomplete.ts +480 -0
- package/src/commands/batch/command.ts +388 -0
- package/src/commands/batch/executor.ts +361 -0
- package/src/commands/batch/index.ts +12 -0
- package/src/commands/commit.ts +235 -0
- package/src/commands/completion/index.ts +371 -0
- package/src/commands/condense.ts +191 -0
- package/src/commands/config.ts +344 -0
- package/src/commands/context-provider.ts +173 -0
- package/src/commands/copy.ts +329 -0
- package/src/commands/core/clear.ts +38 -0
- package/src/commands/core/exit.ts +43 -0
- package/src/commands/core/help.ts +354 -0
- package/src/commands/core/index.ts +15 -0
- package/src/commands/cost.ts +179 -0
- package/src/commands/credentials.tsx +618 -0
- package/src/commands/custom-agents/__tests__/custom-agents.test.ts +709 -0
- package/src/commands/custom-agents/create.ts +377 -0
- package/src/commands/custom-agents/export.ts +135 -0
- package/src/commands/custom-agents/import.ts +199 -0
- package/src/commands/custom-agents/index.ts +372 -0
- package/src/commands/custom-agents/info.ts +318 -0
- package/src/commands/custom-agents/list.ts +267 -0
- package/src/commands/custom-agents/validate.ts +388 -0
- package/src/commands/diff-mode.ts +241 -0
- package/src/commands/env.ts +53 -0
- package/src/commands/executor.ts +579 -0
- package/src/commands/exit-codes.ts +202 -0
- package/src/commands/index.ts +701 -0
- package/src/commands/init/index.ts +15 -0
- package/src/commands/init/prompts.ts +366 -0
- package/src/commands/init/templates/commands-readme.md +80 -0
- package/src/commands/init/templates/example-command.md +79 -0
- package/src/commands/init/templates/example-skill.md +168 -0
- package/src/commands/init/templates/example-workflow.md +101 -0
- package/src/commands/init/templates/prompts-readme.md +52 -0
- package/src/commands/init/templates/rules-readme.md +63 -0
- package/src/commands/init/templates/skills-readme.md +83 -0
- package/src/commands/init/templates/workflows-readme.md +94 -0
- package/src/commands/init.ts +391 -0
- package/src/commands/install.ts +90 -0
- package/src/commands/language.ts +191 -0
- package/src/commands/loaders/.gitkeep +1 -0
- package/src/commands/lsp.ts +199 -0
- package/src/commands/markdown-commands.ts +253 -0
- package/src/commands/mcp.ts +588 -0
- package/src/commands/memory/export.ts +341 -0
- package/src/commands/memory/index.ts +148 -0
- package/src/commands/memory/list.ts +261 -0
- package/src/commands/memory/search.ts +346 -0
- package/src/commands/memory/utils.ts +15 -0
- package/src/commands/metrics.ts +75 -0
- package/src/commands/migrate/index.ts +16 -0
- package/src/commands/migrate/prompts.ts +477 -0
- package/src/commands/mode.ts +331 -0
- package/src/commands/model.ts +298 -0
- package/src/commands/onboard.ts +205 -0
- package/src/commands/open.ts +169 -0
- package/src/commands/output/stream-json.ts +373 -0
- package/src/commands/parser/chain-parser.ts +370 -0
- package/src/commands/parser/index.ts +29 -0
- package/src/commands/parser/pipe-parser.ts +480 -0
- package/src/commands/parser.ts +588 -0
- package/src/commands/persistence.ts +355 -0
- package/src/commands/progress.ts +18 -0
- package/src/commands/prompt/index.ts +17 -0
- package/src/commands/prompt/validate.ts +621 -0
- package/src/commands/prompt-priority.ts +401 -0
- package/src/commands/registry.ts +374 -0
- package/src/commands/sandbox/index.ts +131 -0
- package/src/commands/security/index.ts +21 -0
- package/src/commands/security/input-sanitizer.ts +168 -0
- package/src/commands/security/permission-checker.ts +456 -0
- package/src/commands/security/sensitive-data.ts +350 -0
- package/src/commands/session/delete.ts +38 -0
- package/src/commands/session/export.ts +39 -0
- package/src/commands/session/index.ts +26 -0
- package/src/commands/session/list.ts +26 -0
- package/src/commands/session/resume.ts +562 -0
- package/src/commands/session/search.ts +434 -0
- package/src/commands/session/show.ts +26 -0
- package/src/commands/settings.ts +368 -0
- package/src/commands/setup.ts +23 -0
- package/src/commands/shell/index.ts +16 -0
- package/src/commands/shell/setup.ts +422 -0
- package/src/commands/shell-init.ts +50 -0
- package/src/commands/shell-integration/index.ts +194 -0
- package/src/commands/skill.ts +1220 -0
- package/src/commands/spec.ts +558 -0
- package/src/commands/status.ts +246 -0
- package/src/commands/theme.ts +211 -0
- package/src/commands/think.ts +551 -0
- package/src/commands/trust.ts +211 -0
- package/src/commands/tutorial.ts +522 -0
- package/src/commands/types.ts +512 -0
- package/src/commands/update.ts +274 -0
- package/src/commands/usage.ts +213 -0
- package/src/commands/user-commands.ts +630 -0
- package/src/commands/utils.ts +142 -0
- package/src/commands/vim.ts +152 -0
- package/src/commands/workflow.ts +257 -0
- package/src/components/header.tsx +25 -0
- package/src/components/input.tsx +25 -0
- package/src/components/message-list.tsx +32 -0
- package/src/components/status-bar.tsx +23 -0
- package/src/index.tsx +614 -0
- package/src/onboarding/__tests__/tutorial.test.ts +740 -0
- package/src/onboarding/index.ts +69 -0
- package/src/onboarding/tips/index.ts +9 -0
- package/src/onboarding/tips/tip-engine.ts +459 -0
- package/src/onboarding/tutorial/index.ts +88 -0
- package/src/onboarding/tutorial/lessons/basics.ts +151 -0
- package/src/onboarding/tutorial/lessons/index.ts +151 -0
- package/src/onboarding/tutorial/lessons/modes.ts +230 -0
- package/src/onboarding/tutorial/lessons/tools.ts +172 -0
- package/src/onboarding/tutorial/progress-tracker.ts +350 -0
- package/src/onboarding/tutorial/storage.ts +249 -0
- package/src/onboarding/tutorial/tutorial-system.ts +462 -0
- package/src/onboarding/tutorial/types.ts +310 -0
- package/src/orchestrator-singleton.ts +129 -0
- package/src/shutdown.ts +33 -0
- package/src/test/e2e/assertions.ts +267 -0
- package/src/test/e2e/fixtures.ts +204 -0
- package/src/test/e2e/harness.ts +575 -0
- package/src/test/e2e/index.ts +57 -0
- package/src/test/e2e/types.ts +228 -0
- package/src/test/fixtures/__tests__/fake-response-loader.test.ts +314 -0
- package/src/test/fixtures/fake-response-loader.ts +314 -0
- package/src/test/fixtures/index.ts +20 -0
- package/src/tui/__tests__/mcp-panel.test.tsx +82 -0
- package/src/tui/__tests__/mcp-wiring.test.tsx +78 -0
- package/src/tui/__tests__/mode-components.test.tsx +395 -0
- package/src/tui/__tests__/permission-ask-flow.test.tsx +138 -0
- package/src/tui/__tests__/sidebar-panel-data.test.tsx +148 -0
- package/src/tui/__tests__/tools-panel-hotkeys.test.tsx +41 -0
- package/src/tui/adapters/agent-adapter.ts +1008 -0
- package/src/tui/adapters/index.ts +48 -0
- package/src/tui/adapters/message-adapter.ts +315 -0
- package/src/tui/adapters/persistence-bridge.ts +331 -0
- package/src/tui/adapters/session-adapter.ts +419 -0
- package/src/tui/buffered-stdout.ts +223 -0
- package/src/tui/components/AgentProgress.tsx +424 -0
- package/src/tui/components/Banner/AsciiArt.ts +160 -0
- package/src/tui/components/Banner/Banner.tsx +355 -0
- package/src/tui/components/Banner/ShimmerContext.tsx +131 -0
- package/src/tui/components/Banner/ShimmerText.tsx +193 -0
- package/src/tui/components/Banner/TypeWriterGradient.tsx +321 -0
- package/src/tui/components/Banner/index.ts +61 -0
- package/src/tui/components/Banner/useShimmer.ts +241 -0
- package/src/tui/components/ChatView.tsx +11 -0
- package/src/tui/components/Checkpoint/CheckpointDiffView.tsx +371 -0
- package/src/tui/components/Checkpoint/SnapshotCheckpointPanel.tsx +440 -0
- package/src/tui/components/Checkpoint/index.ts +19 -0
- package/src/tui/components/CostDisplay.tsx +226 -0
- package/src/tui/components/InitErrorBanner.tsx +122 -0
- package/src/tui/components/Input/Autocomplete.tsx +603 -0
- package/src/tui/components/Input/EnhancedCommandInput.tsx +471 -0
- package/src/tui/components/Input/HighlightedText.tsx +236 -0
- package/src/tui/components/Input/MentionAutocomplete.tsx +375 -0
- package/src/tui/components/Input/TextInput.tsx +1002 -0
- package/src/tui/components/Input/__tests__/Autocomplete.test.tsx +374 -0
- package/src/tui/components/Input/__tests__/TextInput.test.tsx +241 -0
- package/src/tui/components/Input/__tests__/highlight.test.ts +219 -0
- package/src/tui/components/Input/__tests__/slash-command-utils.test.ts +104 -0
- package/src/tui/components/Input/highlight.ts +362 -0
- package/src/tui/components/Input/index.ts +36 -0
- package/src/tui/components/Input/slash-command-utils.ts +135 -0
- package/src/tui/components/Layout.tsx +432 -0
- package/src/tui/components/McpPanel.tsx +137 -0
- package/src/tui/components/MemoryPanel.tsx +448 -0
- package/src/tui/components/Messages/CodeBlock.tsx +527 -0
- package/src/tui/components/Messages/DiffView.tsx +679 -0
- package/src/tui/components/Messages/ImageReference.tsx +89 -0
- package/src/tui/components/Messages/MarkdownBlock.tsx +228 -0
- package/src/tui/components/Messages/MarkdownRenderer.tsx +498 -0
- package/src/tui/components/Messages/MessageBubble.tsx +270 -0
- package/src/tui/components/Messages/MessageList.tsx +1719 -0
- package/src/tui/components/Messages/StreamingText.tsx +216 -0
- package/src/tui/components/Messages/ThinkingBlock.tsx +408 -0
- package/src/tui/components/Messages/ToolResultPreview.tsx +243 -0
- package/src/tui/components/Messages/__tests__/CodeBlock.test.tsx +296 -0
- package/src/tui/components/Messages/__tests__/DiffView.test.tsx +239 -0
- package/src/tui/components/Messages/__tests__/MarkdownRenderer.test.tsx +303 -0
- package/src/tui/components/Messages/__tests__/MessageBubble.test.tsx +268 -0
- package/src/tui/components/Messages/__tests__/MessageList.test.tsx +324 -0
- package/src/tui/components/Messages/__tests__/StreamingText.test.tsx +215 -0
- package/src/tui/components/Messages/index.ts +25 -0
- package/src/tui/components/ModeIndicator.tsx +177 -0
- package/src/tui/components/ModeSelector.tsx +216 -0
- package/src/tui/components/ModelSelector.tsx +339 -0
- package/src/tui/components/OnboardingWizard.tsx +670 -0
- package/src/tui/components/PhaseProgressIndicator.tsx +270 -0
- package/src/tui/components/RateLimitIndicator.tsx +82 -0
- package/src/tui/components/ScreenReaderLayout.tsx +295 -0
- package/src/tui/components/SettingsPanel.tsx +643 -0
- package/src/tui/components/Sidebar/SystemStatusPanel.tsx +284 -0
- package/src/tui/components/Sidebar/index.ts +9 -0
- package/src/tui/components/Status/ModelStatusBar.tsx +270 -0
- package/src/tui/components/Status/index.ts +12 -0
- package/src/tui/components/StatusBar/AgentModeIndicator.tsx +257 -0
- package/src/tui/components/StatusBar/ContextProgress.tsx +167 -0
- package/src/tui/components/StatusBar/FileChangesIndicator.tsx +62 -0
- package/src/tui/components/StatusBar/GitIndicator.tsx +89 -0
- package/src/tui/components/StatusBar/HeaderBar.tsx +126 -0
- package/src/tui/components/StatusBar/ModelIndicator.tsx +157 -0
- package/src/tui/components/StatusBar/PersistenceStatusIndicator.tsx +210 -0
- package/src/tui/components/StatusBar/ResilienceIndicator.tsx +106 -0
- package/src/tui/components/StatusBar/SandboxIndicator.tsx +167 -0
- package/src/tui/components/StatusBar/StatusBar.tsx +368 -0
- package/src/tui/components/StatusBar/ThinkingModeIndicator.tsx +170 -0
- package/src/tui/components/StatusBar/TokenBreakdown.tsx +246 -0
- package/src/tui/components/StatusBar/TokenCounter.tsx +135 -0
- package/src/tui/components/StatusBar/TrustModeIndicator.tsx +130 -0
- package/src/tui/components/StatusBar/WorkspaceIndicator.tsx +86 -0
- package/src/tui/components/StatusBar/__tests__/AgentModeIndicator.test.tsx +193 -0
- package/src/tui/components/StatusBar/__tests__/StatusBar.test.tsx +729 -0
- package/src/tui/components/StatusBar/index.ts +60 -0
- package/src/tui/components/TipBanner.tsx +115 -0
- package/src/tui/components/TodoItem.tsx +208 -0
- package/src/tui/components/TodoPanel.tsx +455 -0
- package/src/tui/components/Tools/ApprovalQueue.tsx +407 -0
- package/src/tui/components/Tools/OptionSelector.tsx +160 -0
- package/src/tui/components/Tools/PermissionDialog.tsx +286 -0
- package/src/tui/components/Tools/ToolParams.tsx +483 -0
- package/src/tui/components/Tools/ToolsPanel.tsx +178 -0
- package/src/tui/components/Tools/__tests__/PermissionDialog.test.tsx +510 -0
- package/src/tui/components/Tools/__tests__/ToolParams.test.tsx +432 -0
- package/src/tui/components/Tools/index.ts +21 -0
- package/src/tui/components/TrustPrompt.tsx +279 -0
- package/src/tui/components/UpdateBanner.tsx +166 -0
- package/src/tui/components/VimModeIndicator.tsx +112 -0
- package/src/tui/components/backtrack/BacktrackControls.tsx +402 -0
- package/src/tui/components/backtrack/index.ts +13 -0
- package/src/tui/components/common/AutoApprovalStatus.tsx +251 -0
- package/src/tui/components/common/CostWarning.tsx +294 -0
- package/src/tui/components/common/DynamicShortcutHints.tsx +209 -0
- package/src/tui/components/common/EnhancedLoadingIndicator.tsx +305 -0
- package/src/tui/components/common/ErrorBoundary.tsx +140 -0
- package/src/tui/components/common/GradientText.tsx +224 -0
- package/src/tui/components/common/HotkeyHelpModal.tsx +193 -0
- package/src/tui/components/common/HotkeyHints.tsx +70 -0
- package/src/tui/components/common/MaxSizedBox.tsx +354 -0
- package/src/tui/components/common/NewMessagesBadge.tsx +65 -0
- package/src/tui/components/common/ProtectedFileLegend.tsx +89 -0
- package/src/tui/components/common/ScrollIndicator.tsx +160 -0
- package/src/tui/components/common/Spinner.tsx +342 -0
- package/src/tui/components/common/StreamingIndicator.tsx +316 -0
- package/src/tui/components/common/VirtualizedList/VirtualizedList.tsx +428 -0
- package/src/tui/components/common/VirtualizedList/hooks/index.ts +19 -0
- package/src/tui/components/common/VirtualizedList/hooks/useBatchedScroll.ts +64 -0
- package/src/tui/components/common/VirtualizedList/hooks/useScrollAnchor.ts +290 -0
- package/src/tui/components/common/VirtualizedList/hooks/useVirtualization.ts +340 -0
- package/src/tui/components/common/VirtualizedList/index.ts +30 -0
- package/src/tui/components/common/VirtualizedList/types.ts +107 -0
- package/src/tui/components/common/__tests__/NewMessagesBadge.test.tsx +74 -0
- package/src/tui/components/common/__tests__/ScrollIndicator.test.tsx +193 -0
- package/src/tui/components/common/index.ts +110 -0
- package/src/tui/components/index.ts +79 -0
- package/src/tui/components/session/CheckpointPanel.tsx +323 -0
- package/src/tui/components/session/RollbackDialog.tsx +169 -0
- package/src/tui/components/session/SessionItem.tsx +136 -0
- package/src/tui/components/session/SessionListPanel.tsx +252 -0
- package/src/tui/components/session/SessionPicker.tsx +449 -0
- package/src/tui/components/session/SessionPreview.tsx +240 -0
- package/src/tui/components/session/__tests__/session.test.tsx +408 -0
- package/src/tui/components/session/index.ts +28 -0
- package/src/tui/components/session/types.ts +116 -0
- package/src/tui/components/theme/__tests__/tokens.test.ts +471 -0
- package/src/tui/components/theme/index.ts +227 -0
- package/src/tui/components/theme/tokens.ts +484 -0
- package/src/tui/config/defaults.ts +134 -0
- package/src/tui/config/index.ts +17 -0
- package/src/tui/context/AnimationContext.tsx +284 -0
- package/src/tui/context/AppContext.tsx +349 -0
- package/src/tui/context/BracketedPasteContext.tsx +372 -0
- package/src/tui/context/LspContext.tsx +192 -0
- package/src/tui/context/McpContext.tsx +325 -0
- package/src/tui/context/MessagesContext.tsx +870 -0
- package/src/tui/context/OverflowContext.tsx +213 -0
- package/src/tui/context/RateLimitContext.tsx +108 -0
- package/src/tui/context/ResilienceContext.tsx +275 -0
- package/src/tui/context/RootProvider.tsx +136 -0
- package/src/tui/context/ScrollContext.tsx +331 -0
- package/src/tui/context/ToolsContext.tsx +702 -0
- package/src/tui/context/__tests__/BracketedPasteContext.test.tsx +416 -0
- package/src/tui/context/index.ts +140 -0
- package/src/tui/enterprise-integration.ts +282 -0
- package/src/tui/hooks/__tests__/useBacktrack.test.tsx +138 -0
- package/src/tui/hooks/__tests__/useBracketedPaste.test.tsx +222 -0
- package/src/tui/hooks/__tests__/useCopyMode.test.tsx +336 -0
- package/src/tui/hooks/__tests__/useHotkeys.ctrl-input.test.tsx +96 -0
- package/src/tui/hooks/__tests__/useHotkeys.test.tsx +454 -0
- package/src/tui/hooks/__tests__/useInputHistory.test.tsx +660 -0
- package/src/tui/hooks/__tests__/useLineBuffer.test.ts +295 -0
- package/src/tui/hooks/__tests__/useModeController.test.ts +137 -0
- package/src/tui/hooks/__tests__/useModeShortcuts.test.tsx +142 -0
- package/src/tui/hooks/__tests__/useScrollController.test.ts +464 -0
- package/src/tui/hooks/__tests__/useVim.test.tsx +531 -0
- package/src/tui/hooks/index.ts +252 -0
- package/src/tui/hooks/useAgentLoop.ts +712 -0
- package/src/tui/hooks/useAlternateBuffer.ts +398 -0
- package/src/tui/hooks/useAnimatedScrollbar.ts +241 -0
- package/src/tui/hooks/useBacktrack.ts +443 -0
- package/src/tui/hooks/useBracketedPaste.ts +104 -0
- package/src/tui/hooks/useCollapsible.ts +240 -0
- package/src/tui/hooks/useCopyMode.ts +382 -0
- package/src/tui/hooks/useCostSummary.ts +75 -0
- package/src/tui/hooks/useDesktopNotification.ts +414 -0
- package/src/tui/hooks/useDiffMode.ts +44 -0
- package/src/tui/hooks/useFileChangeStats.ts +110 -0
- package/src/tui/hooks/useFileSuggestions.ts +284 -0
- package/src/tui/hooks/useFlickerDetector.ts +250 -0
- package/src/tui/hooks/useGitStatus.ts +200 -0
- package/src/tui/hooks/useHotkeys.ts +579 -0
- package/src/tui/hooks/useImagePaste.ts +114 -0
- package/src/tui/hooks/useInputHighlight.ts +145 -0
- package/src/tui/hooks/useInputHistory.ts +246 -0
- package/src/tui/hooks/useKeyboardScroll.ts +209 -0
- package/src/tui/hooks/useLineBuffer.ts +356 -0
- package/src/tui/hooks/useMentionAutocomplete.ts +235 -0
- package/src/tui/hooks/useModeController.ts +167 -0
- package/src/tui/hooks/useModeShortcuts.ts +196 -0
- package/src/tui/hooks/usePermissionHandler.ts +146 -0
- package/src/tui/hooks/usePersistence.ts +480 -0
- package/src/tui/hooks/usePersistenceShortcuts.ts +225 -0
- package/src/tui/hooks/usePlaceholderRotation.ts +143 -0
- package/src/tui/hooks/useProviderStatus.ts +270 -0
- package/src/tui/hooks/useRateLimitStatus.ts +90 -0
- package/src/tui/hooks/useScreenReader.ts +315 -0
- package/src/tui/hooks/useScrollController.ts +450 -0
- package/src/tui/hooks/useScrollEventBatcher.ts +185 -0
- package/src/tui/hooks/useSidebarPanelData.ts +115 -0
- package/src/tui/hooks/useSmoothScroll.ts +202 -0
- package/src/tui/hooks/useSnapshots.ts +300 -0
- package/src/tui/hooks/useStateAndRef.ts +50 -0
- package/src/tui/hooks/useTerminalSize.ts +206 -0
- package/src/tui/hooks/useToolApprovalController.ts +91 -0
- package/src/tui/hooks/useVim.ts +334 -0
- package/src/tui/hooks/useWorkspace.ts +56 -0
- package/src/tui/i18n/__tests__/init.test.ts +278 -0
- package/src/tui/i18n/__tests__/language-config.test.ts +199 -0
- package/src/tui/i18n/__tests__/locale-detection.test.ts +250 -0
- package/src/tui/i18n/__tests__/settings-integration.test.ts +262 -0
- package/src/tui/i18n/index.ts +72 -0
- package/src/tui/i18n/init.ts +131 -0
- package/src/tui/i18n/language-config.ts +106 -0
- package/src/tui/i18n/locale-detection.ts +173 -0
- package/src/tui/i18n/settings-integration.ts +557 -0
- package/src/tui/i18n/tui-namespace.ts +538 -0
- package/src/tui/i18n/types.ts +312 -0
- package/src/tui/index.ts +43 -0
- package/src/tui/lsp-integration.ts +409 -0
- package/src/tui/metrics-integration.ts +366 -0
- package/src/tui/plugins.ts +383 -0
- package/src/tui/resilience.ts +342 -0
- package/src/tui/sandbox-integration.ts +317 -0
- package/src/tui/services/clipboard.ts +348 -0
- package/src/tui/services/fuzzy-search.ts +441 -0
- package/src/tui/services/index.ts +72 -0
- package/src/tui/services/markdown-renderer.ts +565 -0
- package/src/tui/services/open-external.ts +247 -0
- package/src/tui/services/syntax-highlighter.ts +483 -0
- package/src/tui/slash-commands.ts +12 -0
- package/src/tui/theme/index.ts +15 -0
- package/src/tui/theme/provider.tsx +206 -0
- package/src/tui/tip-integration.ts +300 -0
- package/src/tui/types/__tests__/ink-extended.test.ts +121 -0
- package/src/tui/types/ink-extended.ts +87 -0
- package/src/tui/utils/__tests__/bracketedPaste.test.ts +231 -0
- package/src/tui/utils/__tests__/heightEstimator.test.ts +157 -0
- package/src/tui/utils/__tests__/text-width.test.ts +158 -0
- package/src/tui/utils/__tests__/textSanitizer.test.ts +266 -0
- package/src/tui/utils/__tests__/ui-sizing.test.ts +169 -0
- package/src/tui/utils/bracketedPaste.ts +107 -0
- package/src/tui/utils/cursor-manager.ts +131 -0
- package/src/tui/utils/detectTerminal.ts +596 -0
- package/src/tui/utils/findLastSafeSplitPoint.ts +92 -0
- package/src/tui/utils/heightEstimator.ts +198 -0
- package/src/tui/utils/index.ts +91 -0
- package/src/tui/utils/isNarrowWidth.ts +52 -0
- package/src/tui/utils/stdoutGuard.ts +90 -0
- package/src/tui/utils/synchronized-update.ts +70 -0
- package/src/tui/utils/text-width.ts +225 -0
- package/src/tui/utils/textSanitizer.ts +225 -0
- package/src/tui/utils/textUtils.ts +114 -0
- package/src/tui/utils/ui-sizing.ts +192 -0
- package/src/tui-blessed/app.ts +160 -0
- package/src/tui-blessed/index.ts +2 -0
- package/src/tui-blessed/neo-blessed.d.ts +6 -0
- package/src/tui-blessed/test.ts +21 -0
- package/src/tui-blessed/types.ts +14 -0
- package/src/utils/icons.ts +130 -0
- package/src/utils/index.ts +33 -0
- package/src/utils/resume-hint.ts +86 -0
- package/src/version.ts +1 -0
- package/tsconfig.json +8 -0
- package/vitest.config.ts +35 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agents Generate Command
|
|
3
|
+
*
|
|
4
|
+
* Generates AGENTS.md based on project analysis (package.json, tsconfig.json, etc.)
|
|
5
|
+
* Uses template-based generation without LLM calls.
|
|
6
|
+
*
|
|
7
|
+
* @module cli/commands/agents/generate
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as fs from "node:fs/promises";
|
|
11
|
+
import * as path from "node:path";
|
|
12
|
+
import chalk from "chalk";
|
|
13
|
+
|
|
14
|
+
import type { CommandContext, CommandResult } from "../types.js";
|
|
15
|
+
import { error, success } from "../types.js";
|
|
16
|
+
import type { AgentsGenerateOptions } from "./index.js";
|
|
17
|
+
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// Types
|
|
20
|
+
// =============================================================================
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Detected project information
|
|
24
|
+
*/
|
|
25
|
+
interface DetectedProjectInfo {
|
|
26
|
+
/** Project name from package.json */
|
|
27
|
+
name: string;
|
|
28
|
+
/** Description from package.json */
|
|
29
|
+
description?: string;
|
|
30
|
+
/** Detected programming language */
|
|
31
|
+
language: string;
|
|
32
|
+
/** Detected framework */
|
|
33
|
+
framework?: string;
|
|
34
|
+
/** Package manager (npm, pnpm, yarn) */
|
|
35
|
+
packageManager?: string;
|
|
36
|
+
/** Build tool (vite, webpack, etc.) */
|
|
37
|
+
buildTool?: string;
|
|
38
|
+
/** Test framework */
|
|
39
|
+
testFramework?: string;
|
|
40
|
+
/** Detected patterns/conventions */
|
|
41
|
+
patterns: string[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Detection result with confidence
|
|
46
|
+
*/
|
|
47
|
+
interface DetectionResult {
|
|
48
|
+
/** Detected project info */
|
|
49
|
+
info: DetectedProjectInfo;
|
|
50
|
+
/** Files that were analyzed */
|
|
51
|
+
analyzedFiles: string[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// =============================================================================
|
|
55
|
+
// Project Detection
|
|
56
|
+
// =============================================================================
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Read and parse package.json
|
|
60
|
+
*/
|
|
61
|
+
async function readPackageJson(cwd: string): Promise<Record<string, unknown> | null> {
|
|
62
|
+
try {
|
|
63
|
+
const content = await fs.readFile(path.join(cwd, "package.json"), "utf-8");
|
|
64
|
+
return JSON.parse(content) as Record<string, unknown>;
|
|
65
|
+
} catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Read and parse tsconfig.json
|
|
72
|
+
*/
|
|
73
|
+
async function readTsConfig(cwd: string): Promise<Record<string, unknown> | null> {
|
|
74
|
+
try {
|
|
75
|
+
const content = await fs.readFile(path.join(cwd, "tsconfig.json"), "utf-8");
|
|
76
|
+
// Remove comments (tsconfig allows them)
|
|
77
|
+
const cleaned = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, "");
|
|
78
|
+
return JSON.parse(cleaned) as Record<string, unknown>;
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Check if a file exists
|
|
86
|
+
*/
|
|
87
|
+
async function fileExists(filePath: string): Promise<boolean> {
|
|
88
|
+
try {
|
|
89
|
+
await fs.access(filePath);
|
|
90
|
+
return true;
|
|
91
|
+
} catch {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Detect framework from dependencies
|
|
98
|
+
*/
|
|
99
|
+
function detectFramework(
|
|
100
|
+
deps: Record<string, string>,
|
|
101
|
+
devDeps: Record<string, string>
|
|
102
|
+
): string | undefined {
|
|
103
|
+
const allDeps = { ...deps, ...devDeps };
|
|
104
|
+
|
|
105
|
+
// React-based
|
|
106
|
+
if (allDeps.next) return "Next.js";
|
|
107
|
+
if (allDeps.react) return "React";
|
|
108
|
+
if (allDeps.vue) return "Vue";
|
|
109
|
+
if (allDeps.svelte) return "Svelte";
|
|
110
|
+
if (allDeps["@angular/core"]) return "Angular";
|
|
111
|
+
|
|
112
|
+
// Node.js
|
|
113
|
+
if (allDeps.express) return "Express";
|
|
114
|
+
if (allDeps.fastify) return "Fastify";
|
|
115
|
+
if (allDeps.koa) return "Koa";
|
|
116
|
+
if (allDeps.hono) return "Hono";
|
|
117
|
+
if (allDeps.nestjs || allDeps["@nestjs/core"]) return "NestJS";
|
|
118
|
+
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Detect package manager
|
|
124
|
+
*/
|
|
125
|
+
async function detectPackageManager(cwd: string): Promise<string> {
|
|
126
|
+
if (await fileExists(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
127
|
+
if (await fileExists(path.join(cwd, "yarn.lock"))) return "yarn";
|
|
128
|
+
if (await fileExists(path.join(cwd, "bun.lockb"))) return "bun";
|
|
129
|
+
return "npm";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Detect build tool
|
|
134
|
+
*/
|
|
135
|
+
function detectBuildTool(
|
|
136
|
+
deps: Record<string, string>,
|
|
137
|
+
devDeps: Record<string, string>
|
|
138
|
+
): string | undefined {
|
|
139
|
+
const allDeps = { ...deps, ...devDeps };
|
|
140
|
+
|
|
141
|
+
if (allDeps.vite) return "Vite";
|
|
142
|
+
if (allDeps.webpack) return "Webpack";
|
|
143
|
+
if (allDeps.esbuild) return "esbuild";
|
|
144
|
+
if (allDeps.rollup) return "Rollup";
|
|
145
|
+
if (allDeps.parcel) return "Parcel";
|
|
146
|
+
if (allDeps.turbo || allDeps.turbopack) return "Turbopack";
|
|
147
|
+
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Detect test framework
|
|
153
|
+
*/
|
|
154
|
+
function detectTestFramework(
|
|
155
|
+
deps: Record<string, string>,
|
|
156
|
+
devDeps: Record<string, string>
|
|
157
|
+
): string | undefined {
|
|
158
|
+
const allDeps = { ...deps, ...devDeps };
|
|
159
|
+
|
|
160
|
+
if (allDeps.vitest) return "Vitest";
|
|
161
|
+
if (allDeps.jest) return "Jest";
|
|
162
|
+
if (allDeps.mocha) return "Mocha";
|
|
163
|
+
if (allDeps["@playwright/test"]) return "Playwright";
|
|
164
|
+
if (allDeps.cypress) return "Cypress";
|
|
165
|
+
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Detect language from project files
|
|
171
|
+
*/
|
|
172
|
+
async function detectLanguage(cwd: string, pkg: Record<string, unknown> | null): Promise<string> {
|
|
173
|
+
// Check for TypeScript
|
|
174
|
+
if (await fileExists(path.join(cwd, "tsconfig.json"))) return "TypeScript";
|
|
175
|
+
|
|
176
|
+
// Check package.json
|
|
177
|
+
if (pkg) {
|
|
178
|
+
const devDeps = (pkg.devDependencies as Record<string, string>) ?? {};
|
|
179
|
+
if (devDeps.typescript) return "TypeScript";
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Check for other languages
|
|
183
|
+
if (await fileExists(path.join(cwd, "pyproject.toml"))) return "Python";
|
|
184
|
+
if (await fileExists(path.join(cwd, "Cargo.toml"))) return "Rust";
|
|
185
|
+
if (await fileExists(path.join(cwd, "go.mod"))) return "Go";
|
|
186
|
+
if (await fileExists(path.join(cwd, "pom.xml"))) return "Java";
|
|
187
|
+
if (await fileExists(path.join(cwd, "build.gradle"))) return "Java";
|
|
188
|
+
|
|
189
|
+
// Default to JavaScript if package.json exists
|
|
190
|
+
if (pkg) return "JavaScript";
|
|
191
|
+
|
|
192
|
+
return "Unknown";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Detect project patterns/conventions
|
|
197
|
+
*/
|
|
198
|
+
async function detectPatterns(cwd: string): Promise<string[]> {
|
|
199
|
+
const patterns: string[] = [];
|
|
200
|
+
|
|
201
|
+
// Check for monorepo
|
|
202
|
+
if (
|
|
203
|
+
(await fileExists(path.join(cwd, "pnpm-workspace.yaml"))) ||
|
|
204
|
+
(await fileExists(path.join(cwd, "lerna.json")))
|
|
205
|
+
) {
|
|
206
|
+
patterns.push("Monorepo");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Check for common configs
|
|
210
|
+
if (
|
|
211
|
+
(await fileExists(path.join(cwd, ".eslintrc.json"))) ||
|
|
212
|
+
(await fileExists(path.join(cwd, "eslint.config.js")))
|
|
213
|
+
) {
|
|
214
|
+
patterns.push("ESLint");
|
|
215
|
+
}
|
|
216
|
+
if (
|
|
217
|
+
(await fileExists(path.join(cwd, ".prettierrc"))) ||
|
|
218
|
+
(await fileExists(path.join(cwd, "prettier.config.js")))
|
|
219
|
+
) {
|
|
220
|
+
patterns.push("Prettier");
|
|
221
|
+
}
|
|
222
|
+
if (await fileExists(path.join(cwd, "biome.json"))) {
|
|
223
|
+
patterns.push("Biome");
|
|
224
|
+
}
|
|
225
|
+
if (await fileExists(path.join(cwd, ".github/workflows"))) {
|
|
226
|
+
patterns.push("GitHub Actions");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return patterns;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Analyze project and detect information
|
|
234
|
+
*/
|
|
235
|
+
async function analyzeProject(cwd: string): Promise<DetectionResult> {
|
|
236
|
+
const analyzedFiles: string[] = [];
|
|
237
|
+
|
|
238
|
+
// Read package.json
|
|
239
|
+
const pkg = await readPackageJson(cwd);
|
|
240
|
+
if (pkg) analyzedFiles.push("package.json");
|
|
241
|
+
|
|
242
|
+
// Read tsconfig.json
|
|
243
|
+
const tsconfig = await readTsConfig(cwd);
|
|
244
|
+
if (tsconfig) analyzedFiles.push("tsconfig.json");
|
|
245
|
+
|
|
246
|
+
// Extract info from package.json
|
|
247
|
+
const deps = (pkg?.dependencies as Record<string, string>) ?? {};
|
|
248
|
+
const devDeps = (pkg?.devDependencies as Record<string, string>) ?? {};
|
|
249
|
+
|
|
250
|
+
// Detect various aspects
|
|
251
|
+
const language = await detectLanguage(cwd, pkg);
|
|
252
|
+
const framework = detectFramework(deps, devDeps);
|
|
253
|
+
const packageManager = await detectPackageManager(cwd);
|
|
254
|
+
const buildTool = detectBuildTool(deps, devDeps);
|
|
255
|
+
const testFramework = detectTestFramework(deps, devDeps);
|
|
256
|
+
const patterns = await detectPatterns(cwd);
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
info: {
|
|
260
|
+
name: (pkg?.name as string) ?? path.basename(cwd),
|
|
261
|
+
description: pkg?.description as string | undefined,
|
|
262
|
+
language,
|
|
263
|
+
framework,
|
|
264
|
+
packageManager,
|
|
265
|
+
buildTool,
|
|
266
|
+
testFramework,
|
|
267
|
+
patterns,
|
|
268
|
+
},
|
|
269
|
+
analyzedFiles,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// =============================================================================
|
|
274
|
+
// Template Generation
|
|
275
|
+
// =============================================================================
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Generate AGENTS.md content from detected info
|
|
279
|
+
*/
|
|
280
|
+
function generateAgentsMd(info: DetectedProjectInfo): string {
|
|
281
|
+
const lines: string[] = [];
|
|
282
|
+
|
|
283
|
+
// Frontmatter
|
|
284
|
+
lines.push("---");
|
|
285
|
+
lines.push(`name: "${info.name}"`);
|
|
286
|
+
lines.push('version: "1.0.0"');
|
|
287
|
+
if (info.description) {
|
|
288
|
+
lines.push(`description: "${info.description.replace(/"/g, '\\"')}"`);
|
|
289
|
+
}
|
|
290
|
+
lines.push("priority: 100");
|
|
291
|
+
lines.push("merge:");
|
|
292
|
+
lines.push(" strategy: extend");
|
|
293
|
+
lines.push(" arrays: append");
|
|
294
|
+
lines.push("---");
|
|
295
|
+
lines.push("");
|
|
296
|
+
|
|
297
|
+
// Instructions header
|
|
298
|
+
lines.push("# Instructions");
|
|
299
|
+
lines.push("");
|
|
300
|
+
lines.push(`You are an AI coding assistant for ${info.name}.`);
|
|
301
|
+
lines.push("");
|
|
302
|
+
|
|
303
|
+
// Tech stack
|
|
304
|
+
lines.push("## Tech Stack");
|
|
305
|
+
lines.push("");
|
|
306
|
+
lines.push(`- ${info.language}`);
|
|
307
|
+
if (info.framework) {
|
|
308
|
+
lines.push(`- ${info.framework}`);
|
|
309
|
+
}
|
|
310
|
+
if (info.buildTool) {
|
|
311
|
+
lines.push(`- ${info.buildTool}`);
|
|
312
|
+
}
|
|
313
|
+
if (info.testFramework) {
|
|
314
|
+
lines.push(`- ${info.testFramework}`);
|
|
315
|
+
}
|
|
316
|
+
if (info.packageManager && info.packageManager !== "npm") {
|
|
317
|
+
lines.push(`- Package Manager: ${info.packageManager}`);
|
|
318
|
+
}
|
|
319
|
+
lines.push("");
|
|
320
|
+
|
|
321
|
+
// Patterns
|
|
322
|
+
if (info.patterns.length > 0) {
|
|
323
|
+
lines.push("## Project Patterns");
|
|
324
|
+
lines.push("");
|
|
325
|
+
for (const pattern of info.patterns) {
|
|
326
|
+
lines.push(`- ${pattern}`);
|
|
327
|
+
}
|
|
328
|
+
lines.push("");
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Coding standards
|
|
332
|
+
lines.push("## Coding Standards");
|
|
333
|
+
lines.push("");
|
|
334
|
+
lines.push("- Follow existing project conventions");
|
|
335
|
+
lines.push("- Write clean, readable, well-documented code");
|
|
336
|
+
lines.push("- Use meaningful variable and function names");
|
|
337
|
+
lines.push("- Add appropriate comments for complex logic");
|
|
338
|
+
|
|
339
|
+
// Language-specific standards
|
|
340
|
+
if (info.language === "TypeScript") {
|
|
341
|
+
lines.push("- Use proper TypeScript types, avoid `any`");
|
|
342
|
+
lines.push("- Prefer `const` over `let`, avoid `var`");
|
|
343
|
+
}
|
|
344
|
+
if (info.testFramework) {
|
|
345
|
+
lines.push(`- Write tests using ${info.testFramework}`);
|
|
346
|
+
}
|
|
347
|
+
lines.push("");
|
|
348
|
+
|
|
349
|
+
// Allowed tools
|
|
350
|
+
lines.push("## Allowed Tools");
|
|
351
|
+
lines.push("");
|
|
352
|
+
lines.push("allowed-tools:");
|
|
353
|
+
lines.push(' - "@readonly"');
|
|
354
|
+
lines.push(' - "@edit"');
|
|
355
|
+
|
|
356
|
+
// Safe shell commands based on package manager
|
|
357
|
+
if (info.packageManager) {
|
|
358
|
+
lines.push(` - "Bash(${info.packageManager} run *)"`);
|
|
359
|
+
lines.push(` - "Bash(${info.packageManager} test *)"`);
|
|
360
|
+
}
|
|
361
|
+
lines.push(' - "!Bash"');
|
|
362
|
+
lines.push("");
|
|
363
|
+
|
|
364
|
+
return lines.join("\n");
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Format detection summary for display
|
|
369
|
+
*/
|
|
370
|
+
function formatDetectionSummary(result: DetectionResult): string {
|
|
371
|
+
const { info, analyzedFiles } = result;
|
|
372
|
+
const lines: string[] = [];
|
|
373
|
+
|
|
374
|
+
lines.push(chalk.bold("📊 Project Analysis"));
|
|
375
|
+
lines.push(chalk.gray("━".repeat(40)));
|
|
376
|
+
lines.push("");
|
|
377
|
+
lines.push(`${chalk.gray("Name:")} ${info.name}`);
|
|
378
|
+
lines.push(`${chalk.gray("Language:")} ${chalk.cyan(info.language)}`);
|
|
379
|
+
|
|
380
|
+
if (info.framework) {
|
|
381
|
+
lines.push(`${chalk.gray("Framework:")} ${chalk.cyan(info.framework)}`);
|
|
382
|
+
}
|
|
383
|
+
if (info.packageManager) {
|
|
384
|
+
lines.push(`${chalk.gray("Package Manager:")} ${info.packageManager}`);
|
|
385
|
+
}
|
|
386
|
+
if (info.buildTool) {
|
|
387
|
+
lines.push(`${chalk.gray("Build Tool:")} ${info.buildTool}`);
|
|
388
|
+
}
|
|
389
|
+
if (info.testFramework) {
|
|
390
|
+
lines.push(`${chalk.gray("Test Framework:")} ${info.testFramework}`);
|
|
391
|
+
}
|
|
392
|
+
if (info.patterns.length > 0) {
|
|
393
|
+
lines.push(`${chalk.gray("Patterns:")} ${info.patterns.join(", ")}`);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
lines.push("");
|
|
397
|
+
lines.push(chalk.gray(`Analyzed: ${analyzedFiles.join(", ")}`));
|
|
398
|
+
|
|
399
|
+
return lines.join("\n");
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// =============================================================================
|
|
403
|
+
// Command Handler
|
|
404
|
+
// =============================================================================
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Execute agents generate command
|
|
408
|
+
*
|
|
409
|
+
* @param options - Command options
|
|
410
|
+
* @returns Command result
|
|
411
|
+
*/
|
|
412
|
+
export async function handleAgentsGenerate(options: AgentsGenerateOptions): Promise<CommandResult> {
|
|
413
|
+
const cwd = process.cwd();
|
|
414
|
+
const outputPath = options.output ? path.resolve(options.output) : path.join(cwd, "AGENTS.md");
|
|
415
|
+
|
|
416
|
+
try {
|
|
417
|
+
// Analyze project
|
|
418
|
+
const result = await analyzeProject(cwd);
|
|
419
|
+
|
|
420
|
+
// Generate content
|
|
421
|
+
const content = generateAgentsMd(result.info);
|
|
422
|
+
|
|
423
|
+
// Dry run - just show what would be generated
|
|
424
|
+
if (options.dryRun) {
|
|
425
|
+
const summary = formatDetectionSummary(result);
|
|
426
|
+
const preview = [
|
|
427
|
+
summary,
|
|
428
|
+
"",
|
|
429
|
+
chalk.bold("📄 Generated AGENTS.md Preview:"),
|
|
430
|
+
chalk.gray("━".repeat(40)),
|
|
431
|
+
"",
|
|
432
|
+
chalk.gray(content),
|
|
433
|
+
"",
|
|
434
|
+
chalk.yellow(`Would write to: ${outputPath}`),
|
|
435
|
+
].join("\n");
|
|
436
|
+
|
|
437
|
+
return success(preview);
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Check if file exists (unless --merge is specified)
|
|
441
|
+
if (!options.merge) {
|
|
442
|
+
try {
|
|
443
|
+
await fs.access(outputPath);
|
|
444
|
+
return error(
|
|
445
|
+
"OPERATION_NOT_ALLOWED",
|
|
446
|
+
`${outputPath} already exists. Use --merge to combine with existing file, or delete it first.`
|
|
447
|
+
);
|
|
448
|
+
} catch {
|
|
449
|
+
// File doesn't exist, good to proceed
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Handle merge with existing file
|
|
454
|
+
if (options.merge) {
|
|
455
|
+
try {
|
|
456
|
+
const existing = await fs.readFile(outputPath, "utf-8");
|
|
457
|
+
// For basic merge, append generated content as a comment
|
|
458
|
+
const merged = [
|
|
459
|
+
existing,
|
|
460
|
+
"",
|
|
461
|
+
"<!-- Generated additions from `vellum agents generate` -->",
|
|
462
|
+
"",
|
|
463
|
+
content,
|
|
464
|
+
].join("\n");
|
|
465
|
+
await fs.writeFile(outputPath, merged, "utf-8");
|
|
466
|
+
} catch {
|
|
467
|
+
// No existing file, just write new content
|
|
468
|
+
await fs.writeFile(outputPath, content, "utf-8");
|
|
469
|
+
}
|
|
470
|
+
} else {
|
|
471
|
+
// Write new file
|
|
472
|
+
await fs.writeFile(outputPath, content, "utf-8");
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Format success message
|
|
476
|
+
const summary = formatDetectionSummary(result);
|
|
477
|
+
const successMsg = [
|
|
478
|
+
summary,
|
|
479
|
+
"",
|
|
480
|
+
chalk.green(`✅ Created ${outputPath}`),
|
|
481
|
+
"",
|
|
482
|
+
chalk.gray("Next steps:"),
|
|
483
|
+
chalk.gray(" • Review and customize the generated AGENTS.md"),
|
|
484
|
+
chalk.gray(` • Run ${chalk.cyan("/agents validate")} to check syntax`),
|
|
485
|
+
chalk.gray(` • Run ${chalk.cyan("/agents show")} to view merged config`),
|
|
486
|
+
].join("\n");
|
|
487
|
+
|
|
488
|
+
return success(successMsg, { filePath: outputPath });
|
|
489
|
+
} catch (err) {
|
|
490
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
491
|
+
return error("INTERNAL_ERROR", `Failed to generate AGENTS.md: ${message}`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Execute handler for command context
|
|
497
|
+
*/
|
|
498
|
+
export async function executeGenerate(ctx: CommandContext): Promise<CommandResult> {
|
|
499
|
+
const options: AgentsGenerateOptions = {
|
|
500
|
+
output: ctx.parsedArgs.named.output as string | undefined,
|
|
501
|
+
merge: ctx.parsedArgs.named.merge as boolean | undefined,
|
|
502
|
+
dryRun: ctx.parsedArgs.named["dry-run"] as boolean | undefined,
|
|
503
|
+
};
|
|
504
|
+
|
|
505
|
+
return handleAgentsGenerate(options);
|
|
506
|
+
}
|