@kenkaiiii/ggcoder 4.3.219 → 4.3.221
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/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +53 -22
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session-compaction.test.js +0 -7
- package/dist/core/agent-session-compaction.test.js.map +1 -1
- package/dist/core/agent-session.d.ts +0 -23
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +4 -98
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/continue-replay-inventory.test.js +1 -1
- package/dist/core/continue-replay-inventory.test.js.map +1 -1
- package/dist/core/goal-controller.d.ts +2 -0
- package/dist/core/goal-controller.d.ts.map +1 -1
- package/dist/core/goal-controller.js +152 -8
- package/dist/core/goal-controller.js.map +1 -1
- package/dist/core/goal-controller.test.js +232 -3
- package/dist/core/goal-controller.test.js.map +1 -1
- package/dist/core/goal-overhead-harness.d.ts +33 -0
- package/dist/core/goal-overhead-harness.d.ts.map +1 -0
- package/dist/core/goal-overhead-harness.js +268 -0
- package/dist/core/goal-overhead-harness.js.map +1 -0
- package/dist/core/goal-store.d.ts +1 -0
- package/dist/core/goal-store.d.ts.map +1 -1
- package/dist/core/goal-store.js +43 -3
- package/dist/core/goal-store.js.map +1 -1
- package/dist/core/goal-store.test.js +13 -0
- package/dist/core/goal-store.test.js.map +1 -1
- package/dist/core/goal-worker.d.ts.map +1 -1
- package/dist/core/goal-worker.js +17 -11
- package/dist/core/goal-worker.js.map +1 -1
- package/dist/core/goal-worker.test.js +41 -8
- package/dist/core/goal-worker.test.js.map +1 -1
- package/dist/core/goal-worktree.d.ts +21 -0
- package/dist/core/goal-worktree.d.ts.map +1 -1
- package/dist/core/goal-worktree.js +71 -1
- package/dist/core/goal-worktree.js.map +1 -1
- package/dist/core/goal-worktree.test.js +127 -2
- package/dist/core/goal-worktree.test.js.map +1 -1
- package/dist/core/prompt-commands.js +2 -2
- package/dist/core/prompt-commands.test.js +1 -1
- package/dist/core/prompt-commands.test.js.map +1 -1
- package/dist/core/runtime-mode.d.ts +7 -0
- package/dist/core/runtime-mode.d.ts.map +1 -1
- package/dist/core/runtime-mode.js +6 -0
- package/dist/core/runtime-mode.js.map +1 -1
- package/dist/core/session-manager.d.ts +4 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +20 -0
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-restore-display.test.js +84 -0
- package/dist/core/session-restore-display.test.js.map +1 -1
- package/dist/core/slash-commands.d.ts +0 -2
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +0 -15
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/system-prompt.d.ts +1 -1
- package/dist/system-prompt.d.ts.map +1 -1
- package/dist/system-prompt.js +13 -1
- package/dist/system-prompt.js.map +1 -1
- package/dist/system-prompt.test.js +2 -2
- package/dist/system-prompt.test.js.map +1 -1
- package/dist/tools/bash.d.ts +2 -0
- package/dist/tools/bash.d.ts.map +1 -1
- package/dist/tools/bash.js +5 -2
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.d.ts.map +1 -1
- package/dist/tools/edit.js +16 -3
- package/dist/tools/edit.js.map +1 -1
- package/dist/tools/enter-plan.d.ts +8 -0
- package/dist/tools/enter-plan.d.ts.map +1 -0
- package/dist/tools/enter-plan.js +27 -0
- package/dist/tools/enter-plan.js.map +1 -0
- package/dist/tools/exit-plan.d.ts +8 -0
- package/dist/tools/exit-plan.d.ts.map +1 -0
- package/dist/tools/exit-plan.js +35 -0
- package/dist/tools/exit-plan.js.map +1 -0
- package/dist/tools/goals.d.ts +8 -5
- package/dist/tools/goals.d.ts.map +1 -1
- package/dist/tools/goals.js +124 -49
- package/dist/tools/goals.js.map +1 -1
- package/dist/tools/goals.test.js +356 -11
- package/dist/tools/goals.test.js.map +1 -1
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +15 -4
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/plan-mode.test.js +63 -24
- package/dist/tools/plan-mode.test.js.map +1 -1
- package/dist/tools/prompt-hints.d.ts.map +1 -1
- package/dist/tools/prompt-hints.js +4 -0
- package/dist/tools/prompt-hints.js.map +1 -1
- package/dist/tools/subagent.d.ts +3 -1
- package/dist/tools/subagent.d.ts.map +1 -1
- package/dist/tools/subagent.js +5 -2
- package/dist/tools/subagent.js.map +1 -1
- package/dist/tools/write.d.ts +2 -0
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +23 -3
- package/dist/tools/write.js.map +1 -1
- package/dist/ui/App.d.ts +13 -6
- package/dist/ui/App.d.ts.map +1 -1
- package/dist/ui/App.js +617 -926
- package/dist/ui/App.js.map +1 -1
- package/dist/ui/app-items.d.ts +8 -1
- package/dist/ui/app-items.d.ts.map +1 -1
- package/dist/ui/app-items.js +1 -1
- package/dist/ui/app-items.js.map +1 -1
- package/dist/ui/app-state-persistence.test.js +22 -22
- package/dist/ui/app-state-persistence.test.js.map +1 -1
- package/dist/ui/components/AssistantMessage.test.js +7 -7
- package/dist/ui/components/AssistantMessage.test.js.map +1 -1
- package/dist/ui/components/BackgroundTasksBar.d.ts.map +1 -1
- package/dist/ui/components/BackgroundTasksBar.js +6 -6
- package/dist/ui/components/BackgroundTasksBar.js.map +1 -1
- package/dist/ui/components/ChatFooterPane.d.ts +29 -0
- package/dist/ui/components/ChatFooterPane.d.ts.map +1 -0
- package/dist/ui/components/ChatFooterPane.js +16 -0
- package/dist/ui/components/ChatFooterPane.js.map +1 -0
- package/dist/ui/components/ChatInputStack.d.ts +34 -0
- package/dist/ui/components/ChatInputStack.d.ts.map +1 -0
- package/dist/ui/components/ChatInputStack.js +9 -0
- package/dist/ui/components/ChatInputStack.js.map +1 -0
- package/dist/ui/components/ChatLayout.d.ts +23 -0
- package/dist/ui/components/ChatLayout.d.ts.map +1 -0
- package/dist/ui/components/ChatLayout.js +16 -0
- package/dist/ui/components/ChatLayout.js.map +1 -0
- package/dist/ui/components/ChatLivePane.d.ts +18 -0
- package/dist/ui/components/ChatLivePane.d.ts.map +1 -0
- package/dist/ui/components/ChatLivePane.js +8 -0
- package/dist/ui/components/ChatLivePane.js.map +1 -0
- package/dist/ui/components/ChatScreen.d.ts +118 -0
- package/dist/ui/components/ChatScreen.d.ts.map +1 -0
- package/dist/ui/components/ChatScreen.js +14 -0
- package/dist/ui/components/ChatScreen.js.map +1 -0
- package/dist/ui/components/ChatStatusRow.d.ts +34 -0
- package/dist/ui/components/ChatStatusRow.d.ts.map +1 -0
- package/dist/ui/components/ChatStatusRow.js +11 -0
- package/dist/ui/components/ChatStatusRow.js.map +1 -0
- package/dist/ui/components/CompactionNotice.d.ts +4 -2
- package/dist/ui/components/CompactionNotice.d.ts.map +1 -1
- package/dist/ui/components/CompactionNotice.js +4 -4
- package/dist/ui/components/CompactionNotice.js.map +1 -1
- package/dist/ui/components/Footer.d.ts +6 -3
- package/dist/ui/components/Footer.d.ts.map +1 -1
- package/dist/ui/components/Footer.js +14 -4
- package/dist/ui/components/Footer.js.map +1 -1
- package/dist/ui/components/FooterStatusRow.d.ts +20 -0
- package/dist/ui/components/FooterStatusRow.d.ts.map +1 -0
- package/dist/ui/components/FooterStatusRow.js +10 -0
- package/dist/ui/components/FooterStatusRow.js.map +1 -0
- package/dist/ui/components/FullScreenOverlayRouter.d.ts +19 -0
- package/dist/ui/components/FullScreenOverlayRouter.d.ts.map +1 -0
- package/dist/ui/components/FullScreenOverlayRouter.js +18 -0
- package/dist/ui/components/FullScreenOverlayRouter.js.map +1 -0
- package/dist/ui/components/GoalOverlay.d.ts +2 -1
- package/dist/ui/components/GoalOverlay.d.ts.map +1 -1
- package/dist/ui/components/GoalOverlay.js +11 -6
- package/dist/ui/components/GoalOverlay.js.map +1 -1
- package/dist/ui/components/GoalStatusBar.d.ts +2 -0
- package/dist/ui/components/GoalStatusBar.d.ts.map +1 -1
- package/dist/ui/components/GoalStatusBar.js +27 -11
- package/dist/ui/components/GoalStatusBar.js.map +1 -1
- package/dist/ui/components/GoalStatusBar.test.d.ts +2 -0
- package/dist/ui/components/GoalStatusBar.test.d.ts.map +1 -0
- package/dist/ui/components/GoalStatusBar.test.js +17 -0
- package/dist/ui/components/GoalStatusBar.test.js.map +1 -0
- package/dist/ui/components/InputArea.d.ts.map +1 -1
- package/dist/ui/components/InputArea.js +6 -5
- package/dist/ui/components/InputArea.js.map +1 -1
- package/dist/ui/components/PlanOverlay.d.ts +7 -0
- package/dist/ui/components/PlanOverlay.d.ts.map +1 -1
- package/dist/ui/components/PlanOverlay.js +16 -2
- package/dist/ui/components/PlanOverlay.js.map +1 -1
- package/dist/ui/components/PlanOverlay.test.d.ts +2 -0
- package/dist/ui/components/PlanOverlay.test.d.ts.map +1 -0
- package/dist/ui/components/PlanOverlay.test.js +24 -0
- package/dist/ui/components/PlanOverlay.test.js.map +1 -0
- package/dist/ui/components/QueueIndicator.d.ts +9 -0
- package/dist/ui/components/QueueIndicator.d.ts.map +1 -0
- package/dist/ui/components/QueueIndicator.js +9 -0
- package/dist/ui/components/QueueIndicator.js.map +1 -0
- package/dist/ui/components/ServerToolExecution.d.ts +2 -0
- package/dist/ui/components/ServerToolExecution.d.ts.map +1 -1
- package/dist/ui/components/ServerToolExecution.js +3 -2
- package/dist/ui/components/ServerToolExecution.js.map +1 -1
- package/dist/ui/components/SessionSummary.d.ts +5 -0
- package/dist/ui/components/SessionSummary.d.ts.map +1 -0
- package/dist/ui/components/SessionSummary.js +32 -0
- package/dist/ui/components/SessionSummary.js.map +1 -0
- package/dist/ui/components/StreamingArea.js +1 -1
- package/dist/ui/components/StreamingArea.js.map +1 -1
- package/dist/ui/components/SubAgentPanel.d.ts +2 -1
- package/dist/ui/components/SubAgentPanel.d.ts.map +1 -1
- package/dist/ui/components/SubAgentPanel.js +2 -2
- package/dist/ui/components/SubAgentPanel.js.map +1 -1
- package/dist/ui/components/ToolExecution.d.ts +2 -0
- package/dist/ui/components/ToolExecution.d.ts.map +1 -1
- package/dist/ui/components/ToolExecution.js +13 -11
- package/dist/ui/components/ToolExecution.js.map +1 -1
- package/dist/ui/components/ToolGroupExecution.d.ts +2 -1
- package/dist/ui/components/ToolGroupExecution.d.ts.map +1 -1
- package/dist/ui/components/ToolGroupExecution.js +5 -3
- package/dist/ui/components/ToolGroupExecution.js.map +1 -1
- package/dist/ui/duration-format.d.ts +2 -0
- package/dist/ui/duration-format.d.ts.map +1 -0
- package/dist/ui/duration-format.js +9 -0
- package/dist/ui/duration-format.js.map +1 -0
- package/dist/ui/duration-summary.d.ts +2 -0
- package/dist/ui/duration-summary.d.ts.map +1 -0
- package/dist/ui/duration-summary.js +66 -0
- package/dist/ui/duration-summary.js.map +1 -0
- package/dist/ui/error-item.d.ts +8 -0
- package/dist/ui/error-item.d.ts.map +1 -0
- package/dist/ui/error-item.js +32 -0
- package/dist/ui/error-item.js.map +1 -0
- package/dist/ui/footer-status-layout.test.js +4 -3
- package/dist/ui/footer-status-layout.test.js.map +1 -1
- package/dist/ui/goal-events.d.ts +1 -0
- package/dist/ui/goal-events.d.ts.map +1 -1
- package/dist/ui/goal-events.js +2 -1
- package/dist/ui/goal-events.js.map +1 -1
- package/dist/ui/goal-events.test.js +16 -0
- package/dist/ui/goal-events.test.js.map +1 -1
- package/dist/ui/goal-lifecycle-orchestration.test.js +105 -18
- package/dist/ui/goal-lifecycle-orchestration.test.js.map +1 -1
- package/dist/ui/goal-progress.d.ts +1 -1
- package/dist/ui/goal-progress.d.ts.map +1 -1
- package/dist/ui/goal-progress.js +11 -13
- package/dist/ui/goal-progress.js.map +1 -1
- package/dist/ui/goal-run-helpers.d.ts +16 -0
- package/dist/ui/goal-run-helpers.d.ts.map +1 -0
- package/dist/ui/goal-run-helpers.js +61 -0
- package/dist/ui/goal-run-helpers.js.map +1 -0
- package/dist/ui/goal-status-bar.test.js +8 -6
- package/dist/ui/goal-status-bar.test.js.map +1 -1
- package/dist/ui/hooks/useChatLayoutMeasurements.d.ts +38 -0
- package/dist/ui/hooks/useChatLayoutMeasurements.d.ts.map +1 -0
- package/dist/ui/hooks/useChatLayoutMeasurements.js +71 -0
- package/dist/ui/hooks/useChatLayoutMeasurements.js.map +1 -0
- package/dist/ui/hooks/useGoalPickerController.d.ts +22 -0
- package/dist/ui/hooks/useGoalPickerController.d.ts.map +1 -0
- package/dist/ui/hooks/useGoalPickerController.js +35 -0
- package/dist/ui/hooks/useGoalPickerController.js.map +1 -0
- package/dist/ui/hooks/useTaskPickerController.d.ts +19 -0
- package/dist/ui/hooks/useTaskPickerController.d.ts.map +1 -0
- package/dist/ui/hooks/useTaskPickerController.js +41 -0
- package/dist/ui/hooks/useTaskPickerController.js.map +1 -0
- package/dist/ui/hooks/useTranscriptHistory.d.ts +34 -0
- package/dist/ui/hooks/useTranscriptHistory.d.ts.map +1 -0
- package/dist/ui/hooks/useTranscriptHistory.js +96 -0
- package/dist/ui/hooks/useTranscriptHistory.js.map +1 -0
- package/dist/ui/layout-decisions.d.ts +3 -12
- package/dist/ui/layout-decisions.d.ts.map +1 -1
- package/dist/ui/layout-decisions.js +7 -65
- package/dist/ui/layout-decisions.js.map +1 -1
- package/dist/ui/prompt-routing.d.ts.map +1 -1
- package/dist/ui/prompt-routing.js +36 -2
- package/dist/ui/prompt-routing.js.map +1 -1
- package/dist/ui/prompt-routing.test.d.ts +2 -0
- package/dist/ui/prompt-routing.test.d.ts.map +1 -0
- package/dist/ui/prompt-routing.test.js +48 -0
- package/dist/ui/prompt-routing.test.js.map +1 -0
- package/dist/ui/render.d.ts +11 -6
- package/dist/ui/render.d.ts.map +1 -1
- package/dist/ui/render.js +8 -2
- package/dist/ui/render.js.map +1 -1
- package/dist/ui/session-summary.d.ts +63 -0
- package/dist/ui/session-summary.d.ts.map +1 -0
- package/dist/ui/session-summary.js +81 -0
- package/dist/ui/session-summary.js.map +1 -0
- package/dist/ui/slash-command-images.test.js +3 -2
- package/dist/ui/slash-command-images.test.js.map +1 -1
- package/dist/ui/submit-prompt-command.d.ts +40 -0
- package/dist/ui/submit-prompt-command.d.ts.map +1 -0
- package/dist/ui/submit-prompt-command.js +92 -0
- package/dist/ui/submit-prompt-command.js.map +1 -0
- package/dist/ui/submit-slash-commands.d.ts +13 -0
- package/dist/ui/submit-slash-commands.d.ts.map +1 -0
- package/dist/ui/submit-slash-commands.js +36 -0
- package/dist/ui/submit-slash-commands.js.map +1 -0
- package/dist/ui/terminal-history-format.d.ts +1 -0
- package/dist/ui/terminal-history-format.d.ts.map +1 -1
- package/dist/ui/terminal-history-format.js +2 -1
- package/dist/ui/terminal-history-format.js.map +1 -1
- package/dist/ui/terminal-history-spacing.d.ts +1 -2
- package/dist/ui/terminal-history-spacing.d.ts.map +1 -1
- package/dist/ui/terminal-history-spacing.js +1 -28
- package/dist/ui/terminal-history-spacing.js.map +1 -1
- package/dist/ui/terminal-history-status-renderers.d.ts +2 -2
- package/dist/ui/terminal-history-status-renderers.d.ts.map +1 -1
- package/dist/ui/terminal-history-status-renderers.js +36 -17
- package/dist/ui/terminal-history-status-renderers.js.map +1 -1
- package/dist/ui/terminal-history.d.ts.map +1 -1
- package/dist/ui/terminal-history.js +93 -24
- package/dist/ui/terminal-history.js.map +1 -1
- package/dist/ui/terminal-history.test.js +2 -1
- package/dist/ui/terminal-history.test.js.map +1 -1
- package/dist/ui/tool-group-summary.d.ts +2 -2
- package/dist/ui/tool-group-summary.d.ts.map +1 -1
- package/dist/ui/tool-group-summary.js +18 -18
- package/dist/ui/tool-group-summary.js.map +1 -1
- package/dist/ui/transcript/GoalRows.d.ts +10 -0
- package/dist/ui/transcript/GoalRows.d.ts.map +1 -0
- package/dist/ui/transcript/GoalRows.js +35 -0
- package/dist/ui/transcript/GoalRows.js.map +1 -0
- package/dist/ui/transcript/MiscRows.d.ts +23 -0
- package/dist/ui/transcript/MiscRows.d.ts.map +1 -0
- package/dist/ui/transcript/MiscRows.js +41 -0
- package/dist/ui/transcript/MiscRows.js.map +1 -0
- package/dist/ui/transcript/StatusRow.d.ts +14 -0
- package/dist/ui/transcript/StatusRow.d.ts.map +1 -0
- package/dist/ui/transcript/StatusRow.js +14 -0
- package/dist/ui/transcript/StatusRow.js.map +1 -0
- package/dist/ui/transcript/ToolRows.d.ts +20 -0
- package/dist/ui/transcript/ToolRows.d.ts.map +1 -0
- package/dist/ui/transcript/ToolRows.js +25 -0
- package/dist/ui/transcript/ToolRows.js.map +1 -0
- package/dist/ui/transcript/TranscriptItemFrame.d.ts +8 -0
- package/dist/ui/transcript/TranscriptItemFrame.d.ts.map +1 -0
- package/dist/ui/transcript/TranscriptItemFrame.js +9 -0
- package/dist/ui/transcript/TranscriptItemFrame.js.map +1 -0
- package/dist/ui/transcript/TranscriptRenderer.d.ts +22 -0
- package/dist/ui/transcript/TranscriptRenderer.d.ts.map +1 -0
- package/dist/ui/transcript/TranscriptRenderer.js +87 -0
- package/dist/ui/transcript/TranscriptRenderer.js.map +1 -0
- package/dist/ui/transcript/presentation.d.ts +76 -0
- package/dist/ui/transcript/presentation.d.ts.map +1 -0
- package/dist/ui/transcript/presentation.js +109 -0
- package/dist/ui/transcript/presentation.js.map +1 -0
- package/dist/ui/transcript/spacing.d.ts +29 -0
- package/dist/ui/transcript/spacing.d.ts.map +1 -0
- package/dist/ui/transcript/spacing.js +91 -0
- package/dist/ui/transcript/spacing.js.map +1 -0
- package/dist/ui/transcript/spacing.test.d.ts +2 -0
- package/dist/ui/transcript/spacing.test.d.ts.map +1 -0
- package/dist/ui/transcript/spacing.test.js +21 -0
- package/dist/ui/transcript/spacing.test.js.map +1 -0
- package/dist/ui/transcript/tool-presentation.d.ts +12 -0
- package/dist/ui/transcript/tool-presentation.d.ts.map +1 -0
- package/dist/ui/transcript/tool-presentation.js +55 -0
- package/dist/ui/transcript/tool-presentation.js.map +1 -0
- package/dist/ui/tui-history-parity.test.js +42 -2
- package/dist/ui/tui-history-parity.test.js.map +1 -1
- package/dist/utils/plan-steps.d.ts.map +1 -1
- package/dist/utils/plan-steps.js +5 -1
- package/dist/utils/plan-steps.js.map +1 -1
- package/dist/utils/plan-steps.test.d.ts +2 -0
- package/dist/utils/plan-steps.test.d.ts.map +1 -0
- package/dist/utils/plan-steps.test.js +16 -0
- package/dist/utils/plan-steps.test.js.map +1 -0
- package/package.json +7 -7
- package/dist/core/repomap-budget.d.ts +0 -7
- package/dist/core/repomap-budget.d.ts.map +0 -1
- package/dist/core/repomap-budget.js +0 -10
- package/dist/core/repomap-budget.js.map +0 -1
- package/dist/core/repomap-budget.test.d.ts +0 -2
- package/dist/core/repomap-budget.test.d.ts.map +0 -1
- package/dist/core/repomap-budget.test.js +0 -26
- package/dist/core/repomap-budget.test.js.map +0 -1
- package/dist/core/repomap-context.d.ts +0 -11
- package/dist/core/repomap-context.d.ts.map +0 -1
- package/dist/core/repomap-context.js +0 -68
- package/dist/core/repomap-context.js.map +0 -1
- package/dist/core/repomap-context.test.d.ts +0 -2
- package/dist/core/repomap-context.test.d.ts.map +0 -1
- package/dist/core/repomap-context.test.js +0 -47
- package/dist/core/repomap-context.test.js.map +0 -1
- package/dist/core/repomap.d.ts +0 -74
- package/dist/core/repomap.d.ts.map +0 -1
- package/dist/core/repomap.js +0 -906
- package/dist/core/repomap.js.map +0 -1
- package/dist/core/repomap.test.d.ts +0 -2
- package/dist/core/repomap.test.d.ts.map +0 -1
- package/dist/core/repomap.test.js +0 -494
- package/dist/core/repomap.test.js.map +0 -1
package/dist/core/repomap.js
DELETED
|
@@ -1,906 +0,0 @@
|
|
|
1
|
-
import { execFile } from "node:child_process";
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { promisify } from "node:util";
|
|
5
|
-
import fg from "fast-glob";
|
|
6
|
-
import ignore from "ignore";
|
|
7
|
-
export const DEFAULT_REPO_MAP_MAX_CHARS = 5000;
|
|
8
|
-
export const FIRST_TURN_REPO_MAP_MAX_CHARS = 6500;
|
|
9
|
-
export const FOCUSED_REPO_MAP_MAX_CHARS = 3500;
|
|
10
|
-
const DEFAULT_MAX_FILES = 80;
|
|
11
|
-
const DEFAULT_MAX_SYMBOLS_PER_FILE = 8;
|
|
12
|
-
const DEFAULT_MAX_CHARS = DEFAULT_REPO_MAP_MAX_CHARS;
|
|
13
|
-
const MAX_FILE_SIZE_BYTES = 200_000;
|
|
14
|
-
const REPO_MAP_VERSION = 3;
|
|
15
|
-
const MAX_RENDERED_DIRECTORIES = 6;
|
|
16
|
-
const MAX_RENDERED_CHANGED_FILES = 10;
|
|
17
|
-
const MAX_RENDERED_READ_FILES = 8;
|
|
18
|
-
const MAX_SIGNATURE_FILES = 12;
|
|
19
|
-
const MAX_SIGNATURES_PER_FILE = 3;
|
|
20
|
-
const MAX_CROSS_PACKAGE_FILES = 4;
|
|
21
|
-
const MAX_FALLBACK_DIRTY_ROOTS = 1;
|
|
22
|
-
const GENERIC_FOCUS_TERMS = new Set([
|
|
23
|
-
"agent",
|
|
24
|
-
"app",
|
|
25
|
-
"cli",
|
|
26
|
-
"core",
|
|
27
|
-
"src",
|
|
28
|
-
"test",
|
|
29
|
-
"tests",
|
|
30
|
-
"tool",
|
|
31
|
-
"tools",
|
|
32
|
-
"ui",
|
|
33
|
-
]);
|
|
34
|
-
const execFileAsync = promisify(execFile);
|
|
35
|
-
export function createRepoMapCache() {
|
|
36
|
-
return { files: new Map() };
|
|
37
|
-
}
|
|
38
|
-
const IGNORE_PATTERNS = [
|
|
39
|
-
"**/.git/**",
|
|
40
|
-
"**/.gg/**",
|
|
41
|
-
"**/node_modules/**",
|
|
42
|
-
"**/dist/**",
|
|
43
|
-
"**/build/**",
|
|
44
|
-
"**/coverage/**",
|
|
45
|
-
"**/.next/**",
|
|
46
|
-
"**/.turbo/**",
|
|
47
|
-
"**/.cache/**",
|
|
48
|
-
"**/vendor/**",
|
|
49
|
-
"**/*.lock",
|
|
50
|
-
"pnpm-lock.yaml",
|
|
51
|
-
"package-lock.json",
|
|
52
|
-
"yarn.lock",
|
|
53
|
-
];
|
|
54
|
-
const BINARY_EXTENSIONS = new Set([
|
|
55
|
-
".png",
|
|
56
|
-
".jpg",
|
|
57
|
-
".jpeg",
|
|
58
|
-
".gif",
|
|
59
|
-
".webp",
|
|
60
|
-
".ico",
|
|
61
|
-
".pdf",
|
|
62
|
-
".zip",
|
|
63
|
-
".gz",
|
|
64
|
-
".tgz",
|
|
65
|
-
".wasm",
|
|
66
|
-
".woff",
|
|
67
|
-
".woff2",
|
|
68
|
-
".ttf",
|
|
69
|
-
".eot",
|
|
70
|
-
".mp3",
|
|
71
|
-
".mp4",
|
|
72
|
-
".mov",
|
|
73
|
-
]);
|
|
74
|
-
const LANGUAGE_BY_EXTENSION = new Map([
|
|
75
|
-
[".ts", "TypeScript"],
|
|
76
|
-
[".tsx", "TypeScript React"],
|
|
77
|
-
[".js", "JavaScript"],
|
|
78
|
-
[".jsx", "JavaScript React"],
|
|
79
|
-
[".mjs", "JavaScript"],
|
|
80
|
-
[".cjs", "JavaScript"],
|
|
81
|
-
[".json", "JSON"],
|
|
82
|
-
[".md", "Markdown"],
|
|
83
|
-
[".py", "Python"],
|
|
84
|
-
[".go", "Go"],
|
|
85
|
-
[".rs", "Rust"],
|
|
86
|
-
[".css", "CSS"],
|
|
87
|
-
]);
|
|
88
|
-
export async function buildRepoMap(options) {
|
|
89
|
-
const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
|
|
90
|
-
const maxSymbolsPerFile = options.maxSymbolsPerFile ?? DEFAULT_MAX_SYMBOLS_PER_FILE;
|
|
91
|
-
const maxChars = options.maxChars ?? DEFAULT_MAX_CHARS;
|
|
92
|
-
const explicitChangedFiles = normalizeRelativePaths(options.cwd, options.changedFiles ?? []);
|
|
93
|
-
const gitChangedFiles = normalizeRelativePaths(options.cwd, await listChangedFiles(options.cwd, options.listGitChangedFiles));
|
|
94
|
-
const readFiles = normalizeRelativePaths(options.cwd, options.readFiles ?? []);
|
|
95
|
-
const focusTerms = normalizeFocusTerms(options.focusTerms ?? []);
|
|
96
|
-
const createdAt = (options.now ?? new Date()).toISOString();
|
|
97
|
-
const cache = options.cache;
|
|
98
|
-
const readFile = options.readFile ?? ((absolutePath) => fs.readFile(absolutePath, "utf-8"));
|
|
99
|
-
const entries = await listCandidateFiles(options.cwd);
|
|
100
|
-
const entrySet = new Set(entries);
|
|
101
|
-
if (cache) {
|
|
102
|
-
for (const cachedPath of cache.files.keys()) {
|
|
103
|
-
if (!entrySet.has(cachedPath))
|
|
104
|
-
cache.files.delete(cachedPath);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
const files = [];
|
|
108
|
-
for (const entry of entries) {
|
|
109
|
-
const absolute = path.join(options.cwd, entry);
|
|
110
|
-
const stat = await fs.stat(absolute).catch(() => null);
|
|
111
|
-
if (!stat?.isFile() || stat.size > MAX_FILE_SIZE_BYTES) {
|
|
112
|
-
cache?.files.delete(entry);
|
|
113
|
-
continue;
|
|
114
|
-
}
|
|
115
|
-
const cached = cache?.files.get(entry);
|
|
116
|
-
if (cached &&
|
|
117
|
-
cached.maxSymbolsPerFile === maxSymbolsPerFile &&
|
|
118
|
-
cached.file.mtimeMs === stat.mtimeMs &&
|
|
119
|
-
cached.file.size === stat.size) {
|
|
120
|
-
files.push(cached.file);
|
|
121
|
-
continue;
|
|
122
|
-
}
|
|
123
|
-
const language = detectLanguage(entry);
|
|
124
|
-
const shouldRead = isTextExtension(entry);
|
|
125
|
-
const content = shouldRead ? await readFile(absolute).catch(() => "") : "";
|
|
126
|
-
const extracted = extractFileFacts(entry, content, maxSymbolsPerFile);
|
|
127
|
-
const file = {
|
|
128
|
-
path: entry,
|
|
129
|
-
language,
|
|
130
|
-
exports: extracted.exports,
|
|
131
|
-
symbols: extracted.symbols,
|
|
132
|
-
imports: extracted.imports,
|
|
133
|
-
signatures: extracted.signatures,
|
|
134
|
-
mtimeMs: stat.mtimeMs,
|
|
135
|
-
size: stat.size,
|
|
136
|
-
};
|
|
137
|
-
files.push(file);
|
|
138
|
-
cache?.files.set(entry, { file, maxSymbolsPerFile });
|
|
139
|
-
}
|
|
140
|
-
const preferredDirtyRoots = inferPreferredDirtyRoots({
|
|
141
|
-
files,
|
|
142
|
-
explicitChangedFiles,
|
|
143
|
-
gitChangedFiles,
|
|
144
|
-
readFiles,
|
|
145
|
-
focusTerms,
|
|
146
|
-
});
|
|
147
|
-
const filteredGitChangedFiles = filterGitChangedFiles(gitChangedFiles, preferredDirtyRoots);
|
|
148
|
-
const changedFiles = unique([...explicitChangedFiles, ...filteredGitChangedFiles]);
|
|
149
|
-
const otherDirtyRoots = summarizeOtherDirtyRoots(gitChangedFiles, changedFiles);
|
|
150
|
-
const context = { changedFiles, readFiles, focusTerms };
|
|
151
|
-
const ranked = selectRepoMapFiles(files, { ...context, maxFiles });
|
|
152
|
-
const activeRoots = inferActivePackageRoots(files, context);
|
|
153
|
-
const directories = summarizeDirectories(files, ranked, activeRoots);
|
|
154
|
-
const snapshot = createSnapshot(ranked, directories, files.length, changedFiles, readFiles, [...activeRoots].sort((a, b) => a.localeCompare(b)), otherDirtyRoots, createdAt, maxChars);
|
|
155
|
-
const markdown = renderRepoMap(snapshot, maxChars);
|
|
156
|
-
const renderedStats = { ...snapshot.stats, renderedChars: markdown.length };
|
|
157
|
-
const renderedSnapshot = {
|
|
158
|
-
...snapshot,
|
|
159
|
-
stats: renderedStats,
|
|
160
|
-
truncated: snapshot.truncated || renderedStats.truncated,
|
|
161
|
-
};
|
|
162
|
-
return { snapshot: renderedSnapshot, markdown };
|
|
163
|
-
}
|
|
164
|
-
export function extractFileFacts(filePath, content, maxSymbolsPerFile = DEFAULT_MAX_SYMBOLS_PER_FILE) {
|
|
165
|
-
if (!isCodeLike(filePath) || content.length === 0) {
|
|
166
|
-
return { exports: [], symbols: [], imports: [], signatures: [] };
|
|
167
|
-
}
|
|
168
|
-
const imports = unique([
|
|
169
|
-
...matchAll(content, /import\s+(?:type\s+)?(?:[^"'\n]+?\s+from\s+)?["']([^"']+)["']/g),
|
|
170
|
-
...matchAll(content, /export\s+[^"'\n]+?\s+from\s+["']([^"']+)["']/g),
|
|
171
|
-
...matchAll(content, /require\(["']([^"']+)["']\)/g),
|
|
172
|
-
]).slice(0, maxSymbolsPerFile);
|
|
173
|
-
const exportedDeclarations = matchNamedDeclarations(content, /export\s+(?:async\s+)?(?:function|class|interface|type|const|let|var)\s+([A-Za-z_$][\w$]*)/g);
|
|
174
|
-
const namedExports = matchExportLists(content);
|
|
175
|
-
const symbols = unique([
|
|
176
|
-
...exportedDeclarations,
|
|
177
|
-
...matchNamedDeclarations(content, /(?:^|\n)\s*(?:async\s+)?function\s+([A-Za-z_$][\w$]*)/g),
|
|
178
|
-
...matchNamedDeclarations(content, /(?:^|\n)\s*class\s+([A-Za-z_$][\w$]*)/g),
|
|
179
|
-
...matchNamedDeclarations(content, /(?:^|\n)\s*interface\s+([A-Za-z_$][\w$]*)/g),
|
|
180
|
-
...matchNamedDeclarations(content, /(?:^|\n)\s*type\s+([A-Za-z_$][\w$]*)/g),
|
|
181
|
-
...matchNamedDeclarations(content, /(?:^|\n)\s*const\s+([A-Za-z_$][\w$]*)\s*=/g),
|
|
182
|
-
]).slice(0, maxSymbolsPerFile);
|
|
183
|
-
return {
|
|
184
|
-
exports: unique([...exportedDeclarations, ...namedExports]).slice(0, maxSymbolsPerFile),
|
|
185
|
-
symbols,
|
|
186
|
-
imports,
|
|
187
|
-
signatures: extractSignatures(content, maxSymbolsPerFile),
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
export function rankRepoMapFiles(files, context) {
|
|
191
|
-
return rankRepoMapFilesWithGraph(files, context, buildDependencyGraph(files));
|
|
192
|
-
}
|
|
193
|
-
function selectRepoMapFiles(files, context) {
|
|
194
|
-
const graph = buildDependencyGraph(files);
|
|
195
|
-
const ranked = rankRepoMapFilesWithGraph(files, context, graph);
|
|
196
|
-
const activeRoots = inferActivePackageRoots(files, context);
|
|
197
|
-
if (activeRoots.size === 0)
|
|
198
|
-
return ranked.slice(0, context.maxFiles);
|
|
199
|
-
const contextualPaths = new Set([...context.changedFiles, ...context.readFiles]);
|
|
200
|
-
const readPaths = new Set(context.readFiles);
|
|
201
|
-
const hasActiveDirtyContext = context.changedFiles.some((filePath) => {
|
|
202
|
-
const root = packageRoot(filePath);
|
|
203
|
-
return root && activeRoots.has(root);
|
|
204
|
-
});
|
|
205
|
-
const active = [];
|
|
206
|
-
const explicitCrossPackage = [];
|
|
207
|
-
const supportCrossPackage = [];
|
|
208
|
-
for (const file of ranked) {
|
|
209
|
-
const root = packageRoot(file.path);
|
|
210
|
-
if (!root || activeRoots.has(root)) {
|
|
211
|
-
active.push(file);
|
|
212
|
-
continue;
|
|
213
|
-
}
|
|
214
|
-
if (!hasActiveDirtyContext && isExplicitlyRelevantCrossPackage(file, context.focusTerms)) {
|
|
215
|
-
explicitCrossPackage.push(file);
|
|
216
|
-
continue;
|
|
217
|
-
}
|
|
218
|
-
if (isConnectedToActivePackage(file.path, activeRoots, graph)) {
|
|
219
|
-
supportCrossPackage.push(file);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
const anchors = active.filter((file) => contextualPaths.has(file.path) &&
|
|
223
|
-
(readPaths.has(file.path) || !isColdStartSupportFile(file.path)));
|
|
224
|
-
const supportAnchors = active.filter((file) => contextualPaths.has(file.path) && isColdStartSupportFile(file.path));
|
|
225
|
-
const relatedActive = active.filter((file) => !contextualPaths.has(file.path) && isRelatedToContext(file.path, contextualPaths, graph));
|
|
226
|
-
const fallbackActive = active.filter((file) => !contextualPaths.has(file.path) && !isRelatedToContext(file.path, contextualPaths, graph));
|
|
227
|
-
return uniqueFiles([
|
|
228
|
-
...anchors,
|
|
229
|
-
...relatedActive,
|
|
230
|
-
...supportAnchors,
|
|
231
|
-
...explicitCrossPackage.slice(0, MAX_CROSS_PACKAGE_FILES),
|
|
232
|
-
...supportCrossPackage.slice(0, MAX_CROSS_PACKAGE_FILES),
|
|
233
|
-
...fallbackActive,
|
|
234
|
-
]).slice(0, context.maxFiles);
|
|
235
|
-
}
|
|
236
|
-
function rankRepoMapFilesWithGraph(files, context, graph) {
|
|
237
|
-
const changed = new Set(context.changedFiles);
|
|
238
|
-
const read = new Set(context.readFiles ?? []);
|
|
239
|
-
const isColdStart = read.size === 0;
|
|
240
|
-
const activeRoots = inferActivePackageRoots(files, {
|
|
241
|
-
changedFiles: context.changedFiles,
|
|
242
|
-
readFiles: context.readFiles ?? [],
|
|
243
|
-
focusTerms: context.focusTerms,
|
|
244
|
-
});
|
|
245
|
-
return [...files].sort((a, b) => {
|
|
246
|
-
const scoreDelta = scoreFile(b, changed, read, activeRoots, graph, context.focusTerms, isColdStart) -
|
|
247
|
-
scoreFile(a, changed, read, activeRoots, graph, context.focusTerms, isColdStart);
|
|
248
|
-
if (scoreDelta !== 0)
|
|
249
|
-
return scoreDelta;
|
|
250
|
-
if (b.mtimeMs !== a.mtimeMs)
|
|
251
|
-
return b.mtimeMs - a.mtimeMs;
|
|
252
|
-
return a.path.localeCompare(b.path);
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
export function renderRepoMap(snapshot, maxChars = DEFAULT_MAX_CHARS) {
|
|
256
|
-
const lines = [
|
|
257
|
-
"<!-- gg-repomap -->",
|
|
258
|
-
"## Repo Map",
|
|
259
|
-
"Navigation-only map. Read files before editing; entries may be stale.",
|
|
260
|
-
"Format: path [lang size] ex=exports sym=locals deps=local imports sig=top signatures.",
|
|
261
|
-
];
|
|
262
|
-
const activeRoots = renderedActiveRoots(snapshot);
|
|
263
|
-
const changedFiles = filterPathsToActiveRoots(snapshot.changedFiles, activeRoots);
|
|
264
|
-
const hiddenChangedFiles = snapshot.changedFiles.filter((filePath) => !changedFiles.includes(filePath));
|
|
265
|
-
const otherDirtyRoots = mergeDirtyRoots(snapshot.otherDirtyRoots ?? [], summarizeDirtyRoots(hiddenChangedFiles));
|
|
266
|
-
const directories = filterDirectoriesToActiveRoots(snapshot.directories, activeRoots);
|
|
267
|
-
if (changedFiles.length > 0) {
|
|
268
|
-
lines.push(`Changed: ${formatPathList(changedFiles, MAX_RENDERED_CHANGED_FILES)}`);
|
|
269
|
-
}
|
|
270
|
-
if (otherDirtyRoots.length > 0) {
|
|
271
|
-
lines.push(`Other dirty packages: ${formatDirtyRootList(otherDirtyRoots, MAX_RENDERED_CHANGED_FILES)}`);
|
|
272
|
-
}
|
|
273
|
-
if (snapshot.readFiles.length > 0) {
|
|
274
|
-
lines.push(`Already read: ${formatPathList(snapshot.readFiles, MAX_RENDERED_READ_FILES)}`);
|
|
275
|
-
}
|
|
276
|
-
if (directories.length > 0) {
|
|
277
|
-
lines.push(`Dirs: ${directories.map((directory) => `${directory.path}/(${directory.files})`).join(" ")}`);
|
|
278
|
-
}
|
|
279
|
-
for (const [index, file] of snapshot.files.entries()) {
|
|
280
|
-
const parts = [`${file.path} [${file.language} ${formatBytes(file.size)}]`];
|
|
281
|
-
const localImports = file.imports.filter(isLocalImport);
|
|
282
|
-
const nonExportedSymbols = file.symbols.filter((symbol) => !file.exports.includes(symbol));
|
|
283
|
-
if (file.exports.length > 0)
|
|
284
|
-
parts.push(`ex=${file.exports.join(",")}`);
|
|
285
|
-
if (nonExportedSymbols.length > 0)
|
|
286
|
-
parts.push(`sym=${nonExportedSymbols.join(",")}`);
|
|
287
|
-
if (localImports.length > 0)
|
|
288
|
-
parts.push(`deps=${localImports.join(",")}`);
|
|
289
|
-
if (index < MAX_SIGNATURE_FILES && file.signatures.length > 0) {
|
|
290
|
-
parts.push(`sig=${file.signatures.slice(0, MAX_SIGNATURES_PER_FILE).join(" | ")}`);
|
|
291
|
-
}
|
|
292
|
-
lines.push(`- ${parts.join(" ")}`);
|
|
293
|
-
}
|
|
294
|
-
return fitLinesToBudget(lines, maxChars);
|
|
295
|
-
}
|
|
296
|
-
function createSnapshot(files, directories, indexedFiles, changedFiles, readFiles, activeRoots, otherDirtyRoots, createdAt, maxChars) {
|
|
297
|
-
const totalSymbols = files.reduce((sum, file) => sum + file.symbols.length + file.exports.length, 0);
|
|
298
|
-
const initial = {
|
|
299
|
-
version: REPO_MAP_VERSION,
|
|
300
|
-
createdAt,
|
|
301
|
-
files,
|
|
302
|
-
directories,
|
|
303
|
-
changedFiles,
|
|
304
|
-
readFiles,
|
|
305
|
-
activeRoots,
|
|
306
|
-
otherDirtyRoots,
|
|
307
|
-
stats: {
|
|
308
|
-
indexedFiles,
|
|
309
|
-
shownFiles: files.length,
|
|
310
|
-
totalSymbols,
|
|
311
|
-
renderedChars: 0,
|
|
312
|
-
truncated: files.length < indexedFiles,
|
|
313
|
-
},
|
|
314
|
-
truncated: files.length < indexedFiles,
|
|
315
|
-
};
|
|
316
|
-
const markdown = renderRepoMap(initial, maxChars);
|
|
317
|
-
const truncated = initial.truncated || markdown.includes("truncated to repo map budget");
|
|
318
|
-
return {
|
|
319
|
-
...initial,
|
|
320
|
-
stats: { ...initial.stats, renderedChars: markdown.length, truncated },
|
|
321
|
-
truncated,
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
async function listChangedFiles(cwd, override) {
|
|
325
|
-
if (override)
|
|
326
|
-
return [...(await override(cwd))];
|
|
327
|
-
try {
|
|
328
|
-
const { stdout } = await execFileAsync("git", ["status", "--porcelain=v1", "-uall"], {
|
|
329
|
-
cwd,
|
|
330
|
-
timeout: 2_000,
|
|
331
|
-
maxBuffer: 512_000,
|
|
332
|
-
});
|
|
333
|
-
return parseGitStatus(stdout);
|
|
334
|
-
}
|
|
335
|
-
catch {
|
|
336
|
-
return [];
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
function parseGitStatus(output) {
|
|
340
|
-
const files = [];
|
|
341
|
-
for (const line of output.split("\n")) {
|
|
342
|
-
if (line.length < 4)
|
|
343
|
-
continue;
|
|
344
|
-
const status = line.slice(0, 2);
|
|
345
|
-
if (status === "!!")
|
|
346
|
-
continue;
|
|
347
|
-
const rawPath = line.slice(3).trim();
|
|
348
|
-
if (!rawPath)
|
|
349
|
-
continue;
|
|
350
|
-
const renamedPath = rawPath.includes(" -> ") ? rawPath.split(" -> ").at(-1) : rawPath;
|
|
351
|
-
if (renamedPath)
|
|
352
|
-
files.push(unquoteGitPath(renamedPath));
|
|
353
|
-
}
|
|
354
|
-
return unique(files);
|
|
355
|
-
}
|
|
356
|
-
function unquoteGitPath(filePath) {
|
|
357
|
-
if (!filePath.startsWith('"') || !filePath.endsWith('"'))
|
|
358
|
-
return filePath;
|
|
359
|
-
try {
|
|
360
|
-
return JSON.parse(filePath);
|
|
361
|
-
}
|
|
362
|
-
catch {
|
|
363
|
-
return filePath.slice(1, -1);
|
|
364
|
-
}
|
|
365
|
-
}
|
|
366
|
-
async function listCandidateFiles(cwd) {
|
|
367
|
-
if (isUnboundedRepoMapRoot(cwd))
|
|
368
|
-
return [];
|
|
369
|
-
const ignorePatterns = await loadGitignore(cwd);
|
|
370
|
-
const ig = ignore().add(ignorePatterns);
|
|
371
|
-
const entries = await fg("**/*", {
|
|
372
|
-
cwd,
|
|
373
|
-
dot: false,
|
|
374
|
-
onlyFiles: true,
|
|
375
|
-
ignore: IGNORE_PATTERNS,
|
|
376
|
-
suppressErrors: true,
|
|
377
|
-
followSymbolicLinks: false,
|
|
378
|
-
});
|
|
379
|
-
return entries
|
|
380
|
-
.filter((entry) => !BINARY_EXTENSIONS.has(path.extname(entry).toLowerCase()))
|
|
381
|
-
.filter((entry) => !ig.ignores(entry))
|
|
382
|
-
.sort((a, b) => a.localeCompare(b));
|
|
383
|
-
}
|
|
384
|
-
function isUnboundedRepoMapRoot(cwd) {
|
|
385
|
-
const resolvedCwd = path.resolve(cwd);
|
|
386
|
-
const home = process.env.HOME;
|
|
387
|
-
return (resolvedCwd === path.parse(resolvedCwd).root || (!!home && resolvedCwd === path.resolve(home)));
|
|
388
|
-
}
|
|
389
|
-
async function loadGitignore(cwd) {
|
|
390
|
-
const content = await fs.readFile(path.join(cwd, ".gitignore"), "utf-8").catch(() => "");
|
|
391
|
-
return content
|
|
392
|
-
.split("\n")
|
|
393
|
-
.map((line) => line.trim())
|
|
394
|
-
.filter((line) => line.length > 0 && !line.startsWith("#"));
|
|
395
|
-
}
|
|
396
|
-
function detectLanguage(filePath) {
|
|
397
|
-
return LANGUAGE_BY_EXTENSION.get(path.extname(filePath).toLowerCase()) ?? "Text";
|
|
398
|
-
}
|
|
399
|
-
function isTextExtension(filePath) {
|
|
400
|
-
return !BINARY_EXTENSIONS.has(path.extname(filePath).toLowerCase());
|
|
401
|
-
}
|
|
402
|
-
function isCodeLike(filePath) {
|
|
403
|
-
return [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"].includes(path.extname(filePath).toLowerCase());
|
|
404
|
-
}
|
|
405
|
-
function matchAll(content, regexp) {
|
|
406
|
-
return [...content.matchAll(regexp)].map((match) => match[1]).filter(isPresent);
|
|
407
|
-
}
|
|
408
|
-
function matchNamedDeclarations(content, regexp) {
|
|
409
|
-
return matchAll(content, regexp);
|
|
410
|
-
}
|
|
411
|
-
function matchExportLists(content) {
|
|
412
|
-
const names = [];
|
|
413
|
-
for (const match of content.matchAll(/export\s*\{([^}]+)\}/g)) {
|
|
414
|
-
const list = match[1];
|
|
415
|
-
if (!list)
|
|
416
|
-
continue;
|
|
417
|
-
for (const raw of list.split(",")) {
|
|
418
|
-
const name = raw
|
|
419
|
-
.trim()
|
|
420
|
-
.split(/\s+as\s+/)[0]
|
|
421
|
-
?.trim();
|
|
422
|
-
if (name)
|
|
423
|
-
names.push(name);
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
return names;
|
|
427
|
-
}
|
|
428
|
-
function extractSignatures(content, maxSignatures) {
|
|
429
|
-
const code = stripTemplateLiterals(content);
|
|
430
|
-
const signatures = [];
|
|
431
|
-
const patterns = [
|
|
432
|
-
/(?:export\s+)?(?:async\s+)?function\s+[A-Za-z_$][\w$]*\s*\([^)]*\)(?:\s*:\s*[^\n{]+)?/g,
|
|
433
|
-
/(?:export\s+)?(?:class|interface|type)\s+[A-Za-z_$][\w$]*(?:\s*[^=\n{]*)?(?:\s*=\s*[^\n;]+)?/g,
|
|
434
|
-
/(?:export\s+)?const\s+[A-Za-z_$][\w$]*\s*=\s*(?:async\s*)?\([^)]*\)\s*=>/g,
|
|
435
|
-
];
|
|
436
|
-
for (const pattern of patterns) {
|
|
437
|
-
for (const match of code.matchAll(pattern)) {
|
|
438
|
-
const signature = match[0]?.replace(/\s+/g, " ").trim();
|
|
439
|
-
if (signature)
|
|
440
|
-
signatures.push(signature);
|
|
441
|
-
if (signatures.length >= maxSignatures)
|
|
442
|
-
return unique(signatures);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
return unique(signatures).slice(0, maxSignatures);
|
|
446
|
-
}
|
|
447
|
-
function stripTemplateLiterals(content) {
|
|
448
|
-
return content.replace(/`(?:\\.|[^`\\])*`/gs, "``");
|
|
449
|
-
}
|
|
450
|
-
function unique(values) {
|
|
451
|
-
return [...new Set(values.filter((value) => value.length > 0))];
|
|
452
|
-
}
|
|
453
|
-
function isPresent(value) {
|
|
454
|
-
return typeof value === "string" && value.length > 0;
|
|
455
|
-
}
|
|
456
|
-
function scoreFile(file, changedFiles, readFiles, activeRoots, graph, focusTerms, isColdStart) {
|
|
457
|
-
let score = 0;
|
|
458
|
-
const isChanged = changedFiles.has(file.path);
|
|
459
|
-
const isRead = readFiles.has(file.path);
|
|
460
|
-
if (isChanged)
|
|
461
|
-
score += 1200;
|
|
462
|
-
if (isChanged && isRead)
|
|
463
|
-
score += 700;
|
|
464
|
-
if (isChanged && isRead && isCodeLike(file.path))
|
|
465
|
-
score += 300;
|
|
466
|
-
if (isRead && !isChanged)
|
|
467
|
-
score -= 450;
|
|
468
|
-
score += scorePackageRoot(file.path, activeRoots, focusTerms);
|
|
469
|
-
if (isReadNeighbor(file.path, readFiles, graph))
|
|
470
|
-
score += 260;
|
|
471
|
-
if (isChangedNeighbor(file.path, changedFiles, graph))
|
|
472
|
-
score += 420;
|
|
473
|
-
if (sharesNeighborhood(file.path, changedFiles))
|
|
474
|
-
score += 180;
|
|
475
|
-
if (sharesNeighborhood(file.path, readFiles))
|
|
476
|
-
score += 120;
|
|
477
|
-
score += Math.min(300, (graph.inbound.get(file.path)?.size ?? 0) * 45);
|
|
478
|
-
score += Math.min(180, (graph.outbound.get(file.path)?.size ?? 0) * 25);
|
|
479
|
-
if (isEntrypoint(file.path))
|
|
480
|
-
score += 150;
|
|
481
|
-
if (file.path.startsWith("src/") || file.path.includes("/src/"))
|
|
482
|
-
score += 80;
|
|
483
|
-
score += Math.min(120, (file.exports.length + file.symbols.length) * 10);
|
|
484
|
-
if (isColdStart && isChanged)
|
|
485
|
-
score += scoreColdStartSpecificity(file, focusTerms);
|
|
486
|
-
score -=
|
|
487
|
-
isTestFile(file.path) && !focusTerms.includes("test") && !focusTerms.includes("tests") ? 80 : 0;
|
|
488
|
-
score -= file.size > 100_000 ? 50 : 0;
|
|
489
|
-
const searchable = `${file.path} ${file.exports.join(" ")} ${file.symbols.join(" ")} ${file.signatures.join(" ")}`.toLowerCase();
|
|
490
|
-
for (const term of focusTerms) {
|
|
491
|
-
if (searchable.includes(term))
|
|
492
|
-
score += 220;
|
|
493
|
-
if (file.path.toLowerCase().includes(term))
|
|
494
|
-
score += 80;
|
|
495
|
-
}
|
|
496
|
-
return score;
|
|
497
|
-
}
|
|
498
|
-
function scoreColdStartSpecificity(file, focusTerms) {
|
|
499
|
-
let score = 0;
|
|
500
|
-
const pathTokens = tokenizePath(file.path);
|
|
501
|
-
const filename = path.posix.basename(file.path).toLowerCase();
|
|
502
|
-
for (const term of focusTerms) {
|
|
503
|
-
if (pathTokens.includes(term))
|
|
504
|
-
score += 260;
|
|
505
|
-
}
|
|
506
|
-
if (pathTokens.includes("repomap"))
|
|
507
|
-
score += 320;
|
|
508
|
-
if (filename === "repomap.ts")
|
|
509
|
-
score += 260;
|
|
510
|
-
if (pathTokens.includes("test") || pathTokens.includes("spec"))
|
|
511
|
-
score += 140;
|
|
512
|
-
if (file.path.includes("/core/"))
|
|
513
|
-
score += 120;
|
|
514
|
-
if (file.path.includes("/scripts/"))
|
|
515
|
-
score -= 520;
|
|
516
|
-
if (filename === "app.tsx" || filename === "app.ts" || filename === "cli.ts")
|
|
517
|
-
score -= 220;
|
|
518
|
-
score -= Math.min(420, Math.floor(file.size / 20_000) * 90);
|
|
519
|
-
return score;
|
|
520
|
-
}
|
|
521
|
-
function tokenizePath(filePath) {
|
|
522
|
-
return unique(filePath
|
|
523
|
-
.toLowerCase()
|
|
524
|
-
.split(/[^a-z0-9]+/)
|
|
525
|
-
.filter((part) => part.length >= 3));
|
|
526
|
-
}
|
|
527
|
-
function buildDependencyGraph(files) {
|
|
528
|
-
const paths = new Set(files.map((file) => file.path));
|
|
529
|
-
const outbound = new Map();
|
|
530
|
-
const inbound = new Map();
|
|
531
|
-
for (const file of files) {
|
|
532
|
-
const dependencies = new Set();
|
|
533
|
-
for (const importPath of file.imports) {
|
|
534
|
-
const resolved = resolveLocalImport(file.path, importPath, paths);
|
|
535
|
-
if (resolved)
|
|
536
|
-
dependencies.add(resolved);
|
|
537
|
-
}
|
|
538
|
-
outbound.set(file.path, dependencies);
|
|
539
|
-
for (const dependency of dependencies) {
|
|
540
|
-
const importers = inbound.get(dependency) ?? new Set();
|
|
541
|
-
importers.add(file.path);
|
|
542
|
-
inbound.set(dependency, importers);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
return { outbound, inbound };
|
|
546
|
-
}
|
|
547
|
-
function filterGitChangedFiles(gitChangedFiles, preferredRoots) {
|
|
548
|
-
if (gitChangedFiles.length === 0)
|
|
549
|
-
return [];
|
|
550
|
-
if (preferredRoots.size === 0)
|
|
551
|
-
return [...gitChangedFiles];
|
|
552
|
-
return gitChangedFiles.filter((filePath) => {
|
|
553
|
-
const root = packageRoot(filePath);
|
|
554
|
-
return !root || preferredRoots.has(root);
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
function inferPreferredDirtyRoots(context) {
|
|
558
|
-
const explicitRoots = collectPackageRoots(context.explicitChangedFiles);
|
|
559
|
-
if (explicitRoots.size > 0)
|
|
560
|
-
return explicitRoots;
|
|
561
|
-
const readRoots = collectPackageRoots(context.readFiles);
|
|
562
|
-
if (readRoots.size > 0)
|
|
563
|
-
return readRoots;
|
|
564
|
-
const focusedRoots = inferFocusedPackageRoots(context.files, context.focusTerms);
|
|
565
|
-
if (focusedRoots.size > 0)
|
|
566
|
-
return focusedRoots;
|
|
567
|
-
const focusMatchedDirtyRoots = inferFocusMatchedDirtyRoots(context.files, context.gitChangedFiles, context.focusTerms);
|
|
568
|
-
if (focusMatchedDirtyRoots.size > 0)
|
|
569
|
-
return focusMatchedDirtyRoots;
|
|
570
|
-
return inferRecentlyChangedDirtyRoots(context.gitChangedFiles, context.files);
|
|
571
|
-
}
|
|
572
|
-
function inferActivePackageRoots(files, context) {
|
|
573
|
-
const readRoots = collectPackageRoots(context.readFiles);
|
|
574
|
-
if (readRoots.size > 0)
|
|
575
|
-
return readRoots;
|
|
576
|
-
const focusedRoots = inferFocusedPackageRoots(files, context.focusTerms);
|
|
577
|
-
if (focusedRoots.size > 0)
|
|
578
|
-
return focusedRoots;
|
|
579
|
-
const focusMatchedDirtyRoots = inferFocusMatchedDirtyRoots(files, context.changedFiles, context.focusTerms);
|
|
580
|
-
if (focusMatchedDirtyRoots.size > 0)
|
|
581
|
-
return focusMatchedDirtyRoots;
|
|
582
|
-
return collectPackageRoots(context.changedFiles);
|
|
583
|
-
}
|
|
584
|
-
function inferFocusedPackageRoots(files, focusTerms) {
|
|
585
|
-
const roots = new Set();
|
|
586
|
-
const knownRoots = new Set(files.map((file) => packageRoot(file.path)).filter(isPresent));
|
|
587
|
-
for (const term of focusTerms) {
|
|
588
|
-
for (const root of knownRoots) {
|
|
589
|
-
if (isPackageExplicitlyMentioned(root, [term]))
|
|
590
|
-
roots.add(root);
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
return roots;
|
|
594
|
-
}
|
|
595
|
-
function inferFocusMatchedDirtyRoots(files, dirtyFiles, focusTerms) {
|
|
596
|
-
if (dirtyFiles.length === 0 || focusTerms.length === 0)
|
|
597
|
-
return new Set();
|
|
598
|
-
const dirty = new Set(dirtyFiles);
|
|
599
|
-
const roots = new Set();
|
|
600
|
-
for (const file of files) {
|
|
601
|
-
if (!dirty.has(file.path) || !matchesFocus(file, focusTerms))
|
|
602
|
-
continue;
|
|
603
|
-
const root = packageRoot(file.path);
|
|
604
|
-
if (root)
|
|
605
|
-
roots.add(root);
|
|
606
|
-
}
|
|
607
|
-
return roots;
|
|
608
|
-
}
|
|
609
|
-
function matchesFocus(file, focusTerms) {
|
|
610
|
-
const meaningfulTerms = focusTerms.filter((term) => !GENERIC_FOCUS_TERMS.has(term));
|
|
611
|
-
const searchable = [
|
|
612
|
-
...tokenizePath(file.path),
|
|
613
|
-
...file.exports.map((value) => value.toLowerCase()),
|
|
614
|
-
...file.symbols.map((value) => value.toLowerCase()),
|
|
615
|
-
];
|
|
616
|
-
const searchableSet = new Set(searchable);
|
|
617
|
-
return meaningfulTerms.some((term) => searchableSet.has(term) || searchable.some((value) => value.includes(term)));
|
|
618
|
-
}
|
|
619
|
-
function collectPackageRoots(filePaths) {
|
|
620
|
-
const roots = new Set();
|
|
621
|
-
for (const filePath of filePaths) {
|
|
622
|
-
const root = packageRoot(filePath);
|
|
623
|
-
if (root)
|
|
624
|
-
roots.add(root);
|
|
625
|
-
}
|
|
626
|
-
return roots;
|
|
627
|
-
}
|
|
628
|
-
function inferRecentlyChangedDirtyRoots(gitChangedFiles, files) {
|
|
629
|
-
const dirtyRoots = collectPackageRoots(gitChangedFiles);
|
|
630
|
-
if (dirtyRoots.size <= MAX_FALLBACK_DIRTY_ROOTS)
|
|
631
|
-
return dirtyRoots;
|
|
632
|
-
const recentByRoot = new Map();
|
|
633
|
-
for (const file of files) {
|
|
634
|
-
const root = packageRoot(file.path);
|
|
635
|
-
if (!root || !dirtyRoots.has(root))
|
|
636
|
-
continue;
|
|
637
|
-
recentByRoot.set(root, Math.max(recentByRoot.get(root) ?? 0, file.mtimeMs));
|
|
638
|
-
}
|
|
639
|
-
return new Set([...dirtyRoots]
|
|
640
|
-
.sort((a, b) => (recentByRoot.get(b) ?? 0) - (recentByRoot.get(a) ?? 0) || a.localeCompare(b))
|
|
641
|
-
.slice(0, MAX_FALLBACK_DIRTY_ROOTS));
|
|
642
|
-
}
|
|
643
|
-
function scorePackageRoot(filePath, activeRoots, focusTerms) {
|
|
644
|
-
if (activeRoots.size === 0)
|
|
645
|
-
return 0;
|
|
646
|
-
const root = packageRoot(filePath);
|
|
647
|
-
if (!root)
|
|
648
|
-
return 0;
|
|
649
|
-
if (activeRoots.has(root))
|
|
650
|
-
return 900;
|
|
651
|
-
if (isPackageExplicitlyMentioned(root, focusTerms))
|
|
652
|
-
return 500;
|
|
653
|
-
return -900;
|
|
654
|
-
}
|
|
655
|
-
function isExplicitlyRelevantCrossPackage(file, focusTerms) {
|
|
656
|
-
const root = packageRoot(file.path);
|
|
657
|
-
if (!root)
|
|
658
|
-
return true;
|
|
659
|
-
return isPackageExplicitlyMentioned(root, focusTerms);
|
|
660
|
-
}
|
|
661
|
-
function isRelatedToContext(filePath, contextualPaths, graph) {
|
|
662
|
-
if (contextualPaths.size === 0)
|
|
663
|
-
return false;
|
|
664
|
-
for (const contextualPath of contextualPaths) {
|
|
665
|
-
if (contextualPath === filePath)
|
|
666
|
-
return true;
|
|
667
|
-
if (topDirectory(contextualPath) === topDirectory(filePath))
|
|
668
|
-
return true;
|
|
669
|
-
if (graph.outbound.get(contextualPath)?.has(filePath))
|
|
670
|
-
return true;
|
|
671
|
-
if (graph.inbound.get(contextualPath)?.has(filePath))
|
|
672
|
-
return true;
|
|
673
|
-
}
|
|
674
|
-
return false;
|
|
675
|
-
}
|
|
676
|
-
function isConnectedToActivePackage(filePath, activeRoots, graph) {
|
|
677
|
-
const outbound = graph.outbound.get(filePath) ?? new Set();
|
|
678
|
-
const inbound = graph.inbound.get(filePath) ?? new Set();
|
|
679
|
-
for (const related of [...outbound, ...inbound]) {
|
|
680
|
-
const relatedRoot = packageRoot(related);
|
|
681
|
-
if (relatedRoot && activeRoots.has(relatedRoot))
|
|
682
|
-
return true;
|
|
683
|
-
}
|
|
684
|
-
return false;
|
|
685
|
-
}
|
|
686
|
-
function isPackageExplicitlyMentioned(root, focusTerms) {
|
|
687
|
-
const packageName = path.posix.basename(root).toLowerCase();
|
|
688
|
-
const shortName = packageName.replace(/^gg-/, "");
|
|
689
|
-
return (focusTerms.includes(packageName) ||
|
|
690
|
-
(!GENERIC_FOCUS_TERMS.has(shortName) && focusTerms.includes(shortName)));
|
|
691
|
-
}
|
|
692
|
-
function packageRoot(filePath) {
|
|
693
|
-
const parts = filePath.split("/");
|
|
694
|
-
if (parts[0] === "packages" && parts.length >= 2)
|
|
695
|
-
return parts.slice(0, 2).join("/");
|
|
696
|
-
return undefined;
|
|
697
|
-
}
|
|
698
|
-
function uniqueFiles(files) {
|
|
699
|
-
const seen = new Set();
|
|
700
|
-
const result = [];
|
|
701
|
-
for (const file of files) {
|
|
702
|
-
if (seen.has(file.path))
|
|
703
|
-
continue;
|
|
704
|
-
seen.add(file.path);
|
|
705
|
-
result.push(file);
|
|
706
|
-
}
|
|
707
|
-
return result;
|
|
708
|
-
}
|
|
709
|
-
function summarizeOtherDirtyRoots(gitChangedFiles, visibleChangedFiles) {
|
|
710
|
-
const visibleRoots = new Set(visibleChangedFiles.map((filePath) => packageRoot(filePath)).filter(isPresent));
|
|
711
|
-
const hiddenFiles = gitChangedFiles.filter((filePath) => {
|
|
712
|
-
const root = packageRoot(filePath);
|
|
713
|
-
return root && !visibleRoots.has(root);
|
|
714
|
-
});
|
|
715
|
-
return summarizeDirtyRoots(hiddenFiles);
|
|
716
|
-
}
|
|
717
|
-
function summarizeDirectories(allFiles, rankedFiles, activeRoots) {
|
|
718
|
-
const shown = new Set(rankedFiles.map((file) => topDirectory(file.path)));
|
|
719
|
-
const counts = new Map();
|
|
720
|
-
for (const file of allFiles) {
|
|
721
|
-
const directory = topDirectory(file.path);
|
|
722
|
-
const root = packageRoot(file.path);
|
|
723
|
-
if (!directory || shown.has(directory))
|
|
724
|
-
continue;
|
|
725
|
-
if (root && activeRoots.size > 0 && !activeRoots.has(root))
|
|
726
|
-
continue;
|
|
727
|
-
counts.set(directory, (counts.get(directory) ?? 0) + 1);
|
|
728
|
-
}
|
|
729
|
-
return [...counts.entries()]
|
|
730
|
-
.map(([directoryPath, files]) => ({ path: directoryPath, files }))
|
|
731
|
-
.sort((a, b) => b.files - a.files || a.path.localeCompare(b.path))
|
|
732
|
-
.slice(0, MAX_RENDERED_DIRECTORIES);
|
|
733
|
-
}
|
|
734
|
-
function resolveLocalImport(sourcePath, importPath, paths) {
|
|
735
|
-
if (!isLocalImport(importPath))
|
|
736
|
-
return undefined;
|
|
737
|
-
const sourceDir = path.posix.dirname(sourcePath);
|
|
738
|
-
const base = path.posix.normalize(path.posix.join(sourceDir, importPath));
|
|
739
|
-
const candidates = [
|
|
740
|
-
base,
|
|
741
|
-
`${base}.ts`,
|
|
742
|
-
`${base}.tsx`,
|
|
743
|
-
`${base}.js`,
|
|
744
|
-
`${base}.jsx`,
|
|
745
|
-
`${base}.mjs`,
|
|
746
|
-
`${base}.cjs`,
|
|
747
|
-
`${base}.json`,
|
|
748
|
-
path.posix.join(base, "index.ts"),
|
|
749
|
-
path.posix.join(base, "index.tsx"),
|
|
750
|
-
path.posix.join(base, "index.js"),
|
|
751
|
-
path.posix.join(base, "index.jsx"),
|
|
752
|
-
];
|
|
753
|
-
return candidates.find((candidate) => paths.has(candidate));
|
|
754
|
-
}
|
|
755
|
-
function isReadNeighbor(filePath, readFiles, graph) {
|
|
756
|
-
for (const readFile of readFiles) {
|
|
757
|
-
if (graph.outbound.get(readFile)?.has(filePath) || graph.inbound.get(readFile)?.has(filePath)) {
|
|
758
|
-
return true;
|
|
759
|
-
}
|
|
760
|
-
}
|
|
761
|
-
return false;
|
|
762
|
-
}
|
|
763
|
-
function isChangedNeighbor(filePath, changedFiles, graph) {
|
|
764
|
-
for (const changedFile of changedFiles) {
|
|
765
|
-
if (graph.outbound.get(changedFile)?.has(filePath) ||
|
|
766
|
-
graph.inbound.get(changedFile)?.has(filePath)) {
|
|
767
|
-
return true;
|
|
768
|
-
}
|
|
769
|
-
}
|
|
770
|
-
return false;
|
|
771
|
-
}
|
|
772
|
-
function sharesNeighborhood(filePath, relatedFiles) {
|
|
773
|
-
const directory = contextDirectory(filePath);
|
|
774
|
-
if (!directory)
|
|
775
|
-
return false;
|
|
776
|
-
for (const relatedFile of relatedFiles) {
|
|
777
|
-
if (relatedFile !== filePath && contextDirectory(relatedFile) === directory)
|
|
778
|
-
return true;
|
|
779
|
-
}
|
|
780
|
-
return false;
|
|
781
|
-
}
|
|
782
|
-
function contextDirectory(filePath) {
|
|
783
|
-
const directory = path.posix.dirname(filePath);
|
|
784
|
-
return directory === "." ? "" : directory;
|
|
785
|
-
}
|
|
786
|
-
function topDirectory(filePath) {
|
|
787
|
-
const parts = filePath.split("/");
|
|
788
|
-
if (parts.length <= 1)
|
|
789
|
-
return "";
|
|
790
|
-
if (parts[0] === "packages" && parts.length >= 4)
|
|
791
|
-
return parts.slice(0, 3).join("/");
|
|
792
|
-
if (parts[0] === "packages" && parts.length >= 2)
|
|
793
|
-
return parts.slice(0, 2).join("/");
|
|
794
|
-
return parts[0] ?? "";
|
|
795
|
-
}
|
|
796
|
-
function isColdStartSupportFile(filePath) {
|
|
797
|
-
return filePath.includes("/scripts/");
|
|
798
|
-
}
|
|
799
|
-
function isEntrypoint(filePath) {
|
|
800
|
-
const base = path.basename(filePath).toLowerCase();
|
|
801
|
-
return ["package.json", "index.ts", "index.tsx", "index.js", "cli.ts", "main.ts"].includes(base);
|
|
802
|
-
}
|
|
803
|
-
function isTestFile(filePath) {
|
|
804
|
-
return /(?:^|\/|\.)(test|spec)\.[jt]sx?$/.test(filePath) || filePath.includes("__tests__");
|
|
805
|
-
}
|
|
806
|
-
function isLocalImport(importPath) {
|
|
807
|
-
return importPath.startsWith(".") || importPath.startsWith("/");
|
|
808
|
-
}
|
|
809
|
-
function normalizeFocusTerms(terms) {
|
|
810
|
-
return unique(terms
|
|
811
|
-
.flatMap((term) => term.toLowerCase().split(/[^a-z0-9_$-]+/))
|
|
812
|
-
.filter((term) => term.length >= 3));
|
|
813
|
-
}
|
|
814
|
-
function normalizeRelativePaths(cwd, files) {
|
|
815
|
-
return unique(files.map((file) => {
|
|
816
|
-
const absolute = path.isAbsolute(file) ? file : path.join(cwd, file);
|
|
817
|
-
return path.relative(cwd, absolute).split(path.sep).join("/");
|
|
818
|
-
})).sort((a, b) => a.localeCompare(b));
|
|
819
|
-
}
|
|
820
|
-
function fitLinesToBudget(lines, maxChars) {
|
|
821
|
-
const suffix = "… truncated to repo map budget.";
|
|
822
|
-
const kept = [];
|
|
823
|
-
let used = 0;
|
|
824
|
-
for (const line of lines) {
|
|
825
|
-
const nextUsed = used + (kept.length > 0 ? 1 : 0) + line.length;
|
|
826
|
-
if (nextUsed > maxChars)
|
|
827
|
-
break;
|
|
828
|
-
kept.push(line);
|
|
829
|
-
used = nextUsed;
|
|
830
|
-
}
|
|
831
|
-
if (kept.length === lines.length)
|
|
832
|
-
return kept.join("\n");
|
|
833
|
-
while (kept.length > 0 && kept.join("\n").length + 1 + suffix.length > maxChars) {
|
|
834
|
-
kept.pop();
|
|
835
|
-
}
|
|
836
|
-
if (kept.length === 0)
|
|
837
|
-
return suffix.slice(0, maxChars);
|
|
838
|
-
return `${kept.join("\n")}\n${suffix}`;
|
|
839
|
-
}
|
|
840
|
-
function formatPathList(paths, maxItems) {
|
|
841
|
-
const visible = paths.slice(0, maxItems);
|
|
842
|
-
const hidden = paths.length - visible.length;
|
|
843
|
-
return hidden > 0 ? `${visible.join(",")},+${hidden} more` : visible.join(",");
|
|
844
|
-
}
|
|
845
|
-
function formatDirtyRootList(roots, maxItems) {
|
|
846
|
-
const visible = roots.slice(0, maxItems);
|
|
847
|
-
const hidden = roots.length - visible.length;
|
|
848
|
-
const formatted = visible
|
|
849
|
-
.map((root) => `${path.posix.basename(root.path)}(${root.files})`)
|
|
850
|
-
.join(",");
|
|
851
|
-
return hidden > 0 ? `${formatted},+${hidden} more` : formatted;
|
|
852
|
-
}
|
|
853
|
-
function renderedActiveRoots(snapshot) {
|
|
854
|
-
const roots = new Set(snapshot.activeRoots ?? []);
|
|
855
|
-
if (roots.size > 0)
|
|
856
|
-
return roots;
|
|
857
|
-
for (const readFile of snapshot.readFiles) {
|
|
858
|
-
const root = packageRoot(readFile);
|
|
859
|
-
if (root)
|
|
860
|
-
roots.add(root);
|
|
861
|
-
}
|
|
862
|
-
return roots;
|
|
863
|
-
}
|
|
864
|
-
function filterPathsToActiveRoots(paths, activeRoots) {
|
|
865
|
-
if (activeRoots.size === 0)
|
|
866
|
-
return [...paths];
|
|
867
|
-
return paths.filter((filePath) => {
|
|
868
|
-
const root = packageRoot(filePath);
|
|
869
|
-
return !root || activeRoots.has(root);
|
|
870
|
-
});
|
|
871
|
-
}
|
|
872
|
-
function filterDirectoriesToActiveRoots(directories, activeRoots) {
|
|
873
|
-
if (activeRoots.size === 0)
|
|
874
|
-
return [...directories];
|
|
875
|
-
return directories.filter((directory) => {
|
|
876
|
-
const root = packageRoot(directory.path);
|
|
877
|
-
return !root || activeRoots.has(root);
|
|
878
|
-
});
|
|
879
|
-
}
|
|
880
|
-
function summarizeDirtyRoots(files) {
|
|
881
|
-
const counts = new Map();
|
|
882
|
-
for (const filePath of files) {
|
|
883
|
-
const root = packageRoot(filePath);
|
|
884
|
-
if (!root)
|
|
885
|
-
continue;
|
|
886
|
-
counts.set(root, (counts.get(root) ?? 0) + 1);
|
|
887
|
-
}
|
|
888
|
-
return [...counts.entries()]
|
|
889
|
-
.map(([root, files]) => ({ path: root, files }))
|
|
890
|
-
.sort((a, b) => b.files - a.files || a.path.localeCompare(b.path));
|
|
891
|
-
}
|
|
892
|
-
function mergeDirtyRoots(primary, secondary) {
|
|
893
|
-
const counts = new Map();
|
|
894
|
-
for (const root of [...primary, ...secondary]) {
|
|
895
|
-
counts.set(root.path, Math.max(counts.get(root.path) ?? 0, root.files));
|
|
896
|
-
}
|
|
897
|
-
return [...counts.entries()]
|
|
898
|
-
.map(([root, files]) => ({ path: root, files }))
|
|
899
|
-
.sort((a, b) => b.files - a.files || a.path.localeCompare(b.path));
|
|
900
|
-
}
|
|
901
|
-
function formatBytes(size) {
|
|
902
|
-
if (size < 1024)
|
|
903
|
-
return `${size}B`;
|
|
904
|
-
return `${Math.round(size / 1024)}KB`;
|
|
905
|
-
}
|
|
906
|
-
//# sourceMappingURL=repomap.js.map
|