orbital-command 0.1.4 → 0.3.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/bin/orbital.js +676 -53
- package/dist/assets/PrimitivesConfig-CrmQXYh4.js +32 -0
- package/dist/assets/QualityGates-BbasOsF3.js +21 -0
- package/dist/assets/SessionTimeline-CGeJsVvy.js +1 -0
- package/dist/assets/Settings-oiM496mc.js +12 -0
- package/dist/assets/SourceControl-B1fP2nJL.js +41 -0
- package/dist/assets/WorkflowVisualizer-CWLYf-f0.js +74 -0
- package/dist/assets/arrow-down-CPy85_J6.js +6 -0
- package/dist/assets/charts-DbDg0Psc.js +68 -0
- package/dist/assets/circle-x-Cwz6ZQDV.js +6 -0
- package/dist/assets/file-text-C46Xr65c.js +6 -0
- package/dist/assets/formatDistanceToNow-BMqsSP44.js +1 -0
- package/dist/assets/globe-Cn2yNZUD.js +6 -0
- package/dist/assets/index-Aj4sV8Al.css +1 -0
- package/dist/assets/index-Bc9dK3MW.js +354 -0
- package/dist/assets/key-OPaNTWJ5.js +6 -0
- package/dist/assets/minus-GMsbpKym.js +6 -0
- package/dist/assets/shield-DwAFkDYI.js +6 -0
- package/dist/assets/ui-BmsSg9jU.js +53 -0
- package/dist/assets/useWorkflowEditor-BJkTX_NR.js +16 -0
- package/dist/assets/{vendor-Dzv9lrRc.js → vendor-Bqt8AJn2.js} +1 -1
- package/dist/assets/zap-DfbUoOty.js +11 -0
- package/dist/favicon.svg +1 -0
- package/dist/index.html +6 -5
- package/dist/server/server/__tests__/data-routes.test.js +124 -0
- package/dist/server/server/__tests__/helpers/db.js +17 -0
- package/dist/server/server/__tests__/helpers/mock-emitter.js +8 -0
- package/dist/server/server/__tests__/scope-routes.test.js +137 -0
- package/dist/server/server/__tests__/sprint-routes.test.js +102 -0
- package/dist/server/server/__tests__/workflow-routes.test.js +107 -0
- package/dist/server/server/config-migrator.js +138 -0
- package/dist/server/server/config.js +17 -2
- package/dist/server/server/database.js +27 -12
- package/dist/server/server/global-config.js +143 -0
- package/dist/server/server/index.js +882 -252
- package/dist/server/server/init.js +579 -194
- package/dist/server/server/launch.js +29 -0
- package/dist/server/server/manifest-types.js +8 -0
- package/dist/server/server/manifest.js +454 -0
- package/dist/server/server/migrate-legacy.js +229 -0
- package/dist/server/server/parsers/event-parser.test.js +117 -0
- package/dist/server/server/parsers/scope-parser.js +74 -28
- package/dist/server/server/parsers/scope-parser.test.js +230 -0
- package/dist/server/server/project-context.js +255 -0
- package/dist/server/server/project-emitter.js +41 -0
- package/dist/server/server/project-manager.js +297 -0
- package/dist/server/server/routes/config-routes.js +1 -3
- package/dist/server/server/routes/data-routes.js +22 -110
- package/dist/server/server/routes/dispatch-routes.js +15 -9
- package/dist/server/server/routes/git-routes.js +74 -0
- package/dist/server/server/routes/manifest-routes.js +319 -0
- package/dist/server/server/routes/scope-routes.js +37 -23
- package/dist/server/server/routes/sync-routes.js +134 -0
- package/dist/server/server/routes/version-routes.js +1 -15
- package/dist/server/server/routes/workflow-routes.js +9 -3
- package/dist/server/server/schema.js +2 -0
- package/dist/server/server/services/batch-orchestrator.js +26 -16
- package/dist/server/server/services/claude-session-service.js +17 -14
- package/dist/server/server/services/deploy-service.test.js +119 -0
- package/dist/server/server/services/event-service.js +64 -1
- package/dist/server/server/services/event-service.test.js +191 -0
- package/dist/server/server/services/gate-service.test.js +105 -0
- package/dist/server/server/services/git-service.js +108 -4
- package/dist/server/server/services/github-service.js +110 -2
- package/dist/server/server/services/readiness-service.test.js +190 -0
- package/dist/server/server/services/scope-cache.js +5 -1
- package/dist/server/server/services/scope-cache.test.js +142 -0
- package/dist/server/server/services/scope-service.js +217 -126
- package/dist/server/server/services/scope-service.test.js +137 -0
- package/dist/server/server/services/sprint-orchestrator.js +7 -6
- package/dist/server/server/services/sprint-service.js +21 -1
- package/dist/server/server/services/sprint-service.test.js +238 -0
- package/dist/server/server/services/sync-service.js +434 -0
- package/dist/server/server/services/sync-types.js +2 -0
- package/dist/server/server/services/telemetry-service.js +143 -0
- package/dist/server/server/services/workflow-service.js +26 -5
- package/dist/server/server/services/workflow-service.test.js +159 -0
- package/dist/server/server/settings-sync.js +284 -0
- package/dist/server/server/update-planner.js +279 -0
- package/dist/server/server/utils/cc-hooks-parser.js +3 -0
- package/dist/server/server/utils/cc-hooks-parser.test.js +86 -0
- package/dist/server/server/utils/dispatch-utils.js +77 -20
- package/dist/server/server/utils/dispatch-utils.test.js +182 -0
- package/dist/server/server/utils/logger.js +37 -3
- package/dist/server/server/utils/package-info.js +30 -0
- package/dist/server/server/utils/route-helpers.js +10 -0
- package/dist/server/server/utils/terminal-launcher.js +79 -25
- package/dist/server/server/utils/worktree-manager.js +13 -4
- package/dist/server/server/validator.js +230 -0
- package/dist/server/server/watchers/global-watcher.js +63 -0
- package/dist/server/server/watchers/scope-watcher.js +27 -12
- package/dist/server/server/wizard/config-editor.js +237 -0
- package/dist/server/server/wizard/detect.js +96 -0
- package/dist/server/server/wizard/doctor.js +115 -0
- package/dist/server/server/wizard/index.js +155 -0
- package/dist/server/server/wizard/phases/confirm.js +39 -0
- package/dist/server/server/wizard/phases/project-setup.js +90 -0
- package/dist/server/server/wizard/phases/setup-wizard.js +66 -0
- package/dist/server/server/wizard/phases/welcome.js +35 -0
- package/dist/server/server/wizard/phases/workflow-setup.js +22 -0
- package/dist/server/server/wizard/types.js +29 -0
- package/dist/server/server/wizard/ui.js +74 -0
- package/dist/server/shared/__fixtures__/workflow-configs.js +75 -0
- package/dist/server/shared/default-workflow.json +65 -0
- package/dist/server/shared/onboarding-tour.test.js +81 -0
- package/dist/server/shared/project-colors.js +24 -0
- package/dist/server/shared/workflow-config.test.js +84 -0
- package/dist/server/shared/workflow-engine.test.js +302 -0
- package/dist/server/shared/workflow-normalizer.js +101 -0
- package/dist/server/shared/workflow-normalizer.test.js +100 -0
- package/dist/server/src/components/onboarding/tour-steps.js +84 -0
- package/package.json +20 -15
- package/schemas/orbital.config.schema.json +16 -1
- package/scripts/postinstall.js +55 -7
- package/server/__tests__/data-routes.test.ts +149 -0
- package/server/__tests__/helpers/db.ts +19 -0
- package/server/__tests__/helpers/mock-emitter.ts +10 -0
- package/server/__tests__/scope-routes.test.ts +157 -0
- package/server/__tests__/sprint-routes.test.ts +118 -0
- package/server/__tests__/workflow-routes.test.ts +120 -0
- package/server/config-migrator.ts +163 -0
- package/server/config.ts +26 -2
- package/server/database.ts +35 -18
- package/server/global-config.ts +200 -0
- package/server/index.ts +975 -287
- package/server/init.ts +625 -182
- package/server/launch.ts +32 -0
- package/server/manifest-types.ts +145 -0
- package/server/manifest.ts +494 -0
- package/server/migrate-legacy.ts +290 -0
- package/server/parsers/event-parser.test.ts +135 -0
- package/server/parsers/scope-parser.test.ts +270 -0
- package/server/parsers/scope-parser.ts +79 -31
- package/server/project-context.ts +309 -0
- package/server/project-emitter.ts +50 -0
- package/server/project-manager.ts +369 -0
- package/server/routes/config-routes.ts +3 -5
- package/server/routes/data-routes.ts +28 -141
- package/server/routes/dispatch-routes.ts +19 -11
- package/server/routes/git-routes.ts +77 -0
- package/server/routes/manifest-routes.ts +388 -0
- package/server/routes/scope-routes.ts +29 -25
- package/server/routes/sync-routes.ts +175 -0
- package/server/routes/version-routes.ts +1 -16
- package/server/routes/workflow-routes.ts +9 -3
- package/server/schema.ts +2 -0
- package/server/services/batch-orchestrator.ts +24 -16
- package/server/services/claude-session-service.ts +16 -14
- package/server/services/deploy-service.test.ts +145 -0
- package/server/services/deploy-service.ts +2 -2
- package/server/services/event-service.test.ts +242 -0
- package/server/services/event-service.ts +92 -3
- package/server/services/gate-service.test.ts +131 -0
- package/server/services/gate-service.ts +2 -2
- package/server/services/git-service.ts +137 -4
- package/server/services/github-service.ts +120 -2
- package/server/services/readiness-service.test.ts +217 -0
- package/server/services/scope-cache.test.ts +167 -0
- package/server/services/scope-cache.ts +4 -1
- package/server/services/scope-service.test.ts +169 -0
- package/server/services/scope-service.ts +220 -126
- package/server/services/sprint-orchestrator.ts +7 -7
- package/server/services/sprint-service.test.ts +271 -0
- package/server/services/sprint-service.ts +27 -3
- package/server/services/sync-service.ts +482 -0
- package/server/services/sync-types.ts +77 -0
- package/server/services/telemetry-service.ts +195 -0
- package/server/services/workflow-service.test.ts +190 -0
- package/server/services/workflow-service.ts +29 -9
- package/server/settings-sync.ts +359 -0
- package/server/update-planner.ts +346 -0
- package/server/utils/cc-hooks-parser.test.ts +96 -0
- package/server/utils/cc-hooks-parser.ts +4 -0
- package/server/utils/dispatch-utils.test.ts +245 -0
- package/server/utils/dispatch-utils.ts +97 -27
- package/server/utils/logger.ts +40 -3
- package/server/utils/package-info.ts +32 -0
- package/server/utils/route-helpers.ts +12 -0
- package/server/utils/terminal-launcher.ts +85 -25
- package/server/utils/worktree-manager.ts +9 -4
- package/server/validator.ts +270 -0
- package/server/watchers/global-watcher.ts +77 -0
- package/server/watchers/scope-watcher.ts +21 -9
- package/server/wizard/config-editor.ts +248 -0
- package/server/wizard/detect.ts +104 -0
- package/server/wizard/doctor.ts +114 -0
- package/server/wizard/index.ts +187 -0
- package/server/wizard/phases/confirm.ts +45 -0
- package/server/wizard/phases/project-setup.ts +106 -0
- package/server/wizard/phases/setup-wizard.ts +78 -0
- package/server/wizard/phases/welcome.ts +43 -0
- package/server/wizard/phases/workflow-setup.ts +28 -0
- package/server/wizard/types.ts +56 -0
- package/server/wizard/ui.ts +93 -0
- package/shared/__fixtures__/workflow-configs.ts +80 -0
- package/shared/default-workflow.json +65 -0
- package/shared/onboarding-tour.test.ts +94 -0
- package/shared/project-colors.ts +24 -0
- package/shared/workflow-config.test.ts +111 -0
- package/shared/workflow-config.ts +7 -0
- package/shared/workflow-engine.test.ts +388 -0
- package/shared/workflow-normalizer.test.ts +119 -0
- package/shared/workflow-normalizer.ts +118 -0
- package/templates/hooks/end-session.sh +3 -1
- package/templates/hooks/orbital-emit.sh +2 -2
- package/templates/hooks/orbital-report-deploy.sh +4 -4
- package/templates/hooks/orbital-report-gates.sh +4 -4
- package/templates/hooks/orbital-scope-update.sh +1 -1
- package/templates/hooks/scope-create-cleanup.sh +2 -2
- package/templates/hooks/scope-create-gate.sh +0 -1
- package/templates/hooks/scope-helpers.sh +18 -0
- package/templates/hooks/scope-prepare.sh +66 -11
- package/templates/migrations/renames.json +1 -0
- package/templates/orbital.config.json +7 -2
- package/templates/settings-hooks.json +1 -1
- package/templates/skills/git-commit/SKILL.md +9 -4
- package/templates/skills/git-dev/SKILL.md +8 -3
- package/templates/skills/git-main/SKILL.md +8 -2
- package/templates/skills/git-production/SKILL.md +6 -2
- package/templates/skills/git-staging/SKILL.md +8 -3
- package/templates/skills/scope-create/SKILL.md +17 -3
- package/templates/skills/scope-fix-review/SKILL.md +6 -3
- package/templates/skills/scope-implement/SKILL.md +4 -1
- package/templates/skills/scope-post-review/SKILL.md +63 -5
- package/templates/skills/scope-pre-review/SKILL.md +5 -2
- package/templates/skills/scope-verify/SKILL.md +5 -3
- package/templates/skills/test-code-review/SKILL.md +41 -33
- package/templates/skills/test-scaffold/SKILL.md +222 -0
- package/dist/assets/WorkflowVisualizer-BZ21PIIF.js +0 -84
- package/dist/assets/charts-D__PA1zp.js +0 -72
- package/dist/assets/index-D1G6i0nS.css +0 -1
- package/dist/assets/index-DpItvKpf.js +0 -419
- package/dist/assets/ui-BvF022GT.js +0 -53
- package/index.html +0 -15
- package/postcss.config.js +0 -6
- package/src/App.tsx +0 -33
- package/src/components/AgentBadge.tsx +0 -40
- package/src/components/BatchPreflightModal.tsx +0 -115
- package/src/components/CardDisplayToggle.tsx +0 -74
- package/src/components/ColumnHeaderActions.tsx +0 -55
- package/src/components/ColumnMenu.tsx +0 -99
- package/src/components/DeployHistory.tsx +0 -141
- package/src/components/DispatchModal.tsx +0 -164
- package/src/components/DispatchPopover.tsx +0 -139
- package/src/components/DragOverlay.tsx +0 -25
- package/src/components/DriftSidebar.tsx +0 -140
- package/src/components/EnvironmentStrip.tsx +0 -88
- package/src/components/ErrorBoundary.tsx +0 -62
- package/src/components/FilterChip.tsx +0 -105
- package/src/components/GateIndicator.tsx +0 -33
- package/src/components/IdeaDetailModal.tsx +0 -190
- package/src/components/IdeaFormDialog.tsx +0 -113
- package/src/components/KanbanColumn.tsx +0 -201
- package/src/components/MarkdownRenderer.tsx +0 -114
- package/src/components/NeonGrid.tsx +0 -128
- package/src/components/PromotionQueue.tsx +0 -89
- package/src/components/ScopeCard.tsx +0 -234
- package/src/components/ScopeDetailModal.tsx +0 -255
- package/src/components/ScopeFilterBar.tsx +0 -152
- package/src/components/SearchInput.tsx +0 -102
- package/src/components/SessionPanel.tsx +0 -335
- package/src/components/SprintContainer.tsx +0 -303
- package/src/components/SprintDependencyDialog.tsx +0 -78
- package/src/components/SprintPreflightModal.tsx +0 -138
- package/src/components/StatusBar.tsx +0 -168
- package/src/components/SwimCell.tsx +0 -67
- package/src/components/SwimLaneRow.tsx +0 -94
- package/src/components/SwimlaneBoardView.tsx +0 -108
- package/src/components/VersionBadge.tsx +0 -139
- package/src/components/ViewModeSelector.tsx +0 -114
- package/src/components/config/AgentChip.tsx +0 -53
- package/src/components/config/AgentCreateDialog.tsx +0 -321
- package/src/components/config/AgentEditor.tsx +0 -175
- package/src/components/config/DirectoryTree.tsx +0 -582
- package/src/components/config/FileEditor.tsx +0 -550
- package/src/components/config/HookChip.tsx +0 -50
- package/src/components/config/StageCard.tsx +0 -198
- package/src/components/config/TransitionZone.tsx +0 -173
- package/src/components/config/UnifiedWorkflowPipeline.tsx +0 -216
- package/src/components/config/WorkflowPipeline.tsx +0 -161
- package/src/components/source-control/BranchList.tsx +0 -93
- package/src/components/source-control/BranchPanel.tsx +0 -105
- package/src/components/source-control/CommitLog.tsx +0 -100
- package/src/components/source-control/CommitRow.tsx +0 -47
- package/src/components/source-control/GitHubPanel.tsx +0 -110
- package/src/components/source-control/GitHubSetupGuide.tsx +0 -52
- package/src/components/source-control/GitOverviewBar.tsx +0 -101
- package/src/components/source-control/PullRequestList.tsx +0 -69
- package/src/components/source-control/WorktreeList.tsx +0 -80
- package/src/components/ui/badge.tsx +0 -41
- package/src/components/ui/button.tsx +0 -55
- package/src/components/ui/card.tsx +0 -78
- package/src/components/ui/dialog.tsx +0 -94
- package/src/components/ui/popover.tsx +0 -33
- package/src/components/ui/scroll-area.tsx +0 -54
- package/src/components/ui/separator.tsx +0 -28
- package/src/components/ui/tabs.tsx +0 -52
- package/src/components/ui/toggle-switch.tsx +0 -35
- package/src/components/ui/tooltip.tsx +0 -27
- package/src/components/workflow/AddEdgeDialog.tsx +0 -217
- package/src/components/workflow/AddListDialog.tsx +0 -201
- package/src/components/workflow/ChecklistEditor.tsx +0 -239
- package/src/components/workflow/CommandPrefixManager.tsx +0 -118
- package/src/components/workflow/ConfigSettingsPanel.tsx +0 -189
- package/src/components/workflow/DirectionSelector.tsx +0 -133
- package/src/components/workflow/DispatchConfigPanel.tsx +0 -180
- package/src/components/workflow/EdgeDetailPanel.tsx +0 -236
- package/src/components/workflow/EdgePropertyEditor.tsx +0 -251
- package/src/components/workflow/EditToolbar.tsx +0 -138
- package/src/components/workflow/HookDetailPanel.tsx +0 -250
- package/src/components/workflow/HookExecutionLog.tsx +0 -24
- package/src/components/workflow/HookSourceModal.tsx +0 -129
- package/src/components/workflow/HooksDashboard.tsx +0 -363
- package/src/components/workflow/ListPropertyEditor.tsx +0 -251
- package/src/components/workflow/MigrationPreviewDialog.tsx +0 -237
- package/src/components/workflow/MovementRulesPanel.tsx +0 -188
- package/src/components/workflow/NodeDetailPanel.tsx +0 -245
- package/src/components/workflow/PresetSelector.tsx +0 -414
- package/src/components/workflow/SkillCommandBuilder.tsx +0 -174
- package/src/components/workflow/WorkflowEdgeComponent.tsx +0 -145
- package/src/components/workflow/WorkflowNode.tsx +0 -147
- package/src/components/workflow/graphLayout.ts +0 -186
- package/src/components/workflow/mergeHooks.ts +0 -85
- package/src/components/workflow/useEditHistory.ts +0 -88
- package/src/components/workflow/useWorkflowEditor.ts +0 -262
- package/src/components/workflow/validateConfig.ts +0 -70
- package/src/hooks/useActiveDispatches.ts +0 -198
- package/src/hooks/useBoardSettings.ts +0 -170
- package/src/hooks/useCardDisplay.ts +0 -57
- package/src/hooks/useCcHooks.ts +0 -24
- package/src/hooks/useConfigTree.ts +0 -51
- package/src/hooks/useEnforcementRules.ts +0 -46
- package/src/hooks/useEvents.ts +0 -59
- package/src/hooks/useFileEditor.ts +0 -165
- package/src/hooks/useGates.ts +0 -57
- package/src/hooks/useIdeaActions.ts +0 -53
- package/src/hooks/useKanbanDnd.ts +0 -410
- package/src/hooks/useOrbitalConfig.ts +0 -54
- package/src/hooks/usePipeline.ts +0 -47
- package/src/hooks/usePipelineData.ts +0 -338
- package/src/hooks/useReconnect.ts +0 -25
- package/src/hooks/useScopeFilters.ts +0 -125
- package/src/hooks/useScopeSessions.ts +0 -44
- package/src/hooks/useScopes.ts +0 -67
- package/src/hooks/useSearch.ts +0 -67
- package/src/hooks/useSettings.tsx +0 -187
- package/src/hooks/useSocket.ts +0 -25
- package/src/hooks/useSourceControl.ts +0 -105
- package/src/hooks/useSprintPreflight.ts +0 -55
- package/src/hooks/useSprints.ts +0 -154
- package/src/hooks/useStatusBarHighlight.ts +0 -18
- package/src/hooks/useSwimlaneBoardSettings.ts +0 -104
- package/src/hooks/useTheme.ts +0 -9
- package/src/hooks/useTransitionReadiness.ts +0 -53
- package/src/hooks/useVersion.ts +0 -155
- package/src/hooks/useViolations.ts +0 -65
- package/src/hooks/useWorkflow.tsx +0 -125
- package/src/hooks/useZoomModifier.ts +0 -19
- package/src/index.css +0 -797
- package/src/layouts/DashboardLayout.tsx +0 -113
- package/src/lib/collisionDetection.ts +0 -20
- package/src/lib/scope-fields.ts +0 -61
- package/src/lib/swimlane.ts +0 -146
- package/src/lib/utils.ts +0 -15
- package/src/main.tsx +0 -19
- package/src/socket.ts +0 -11
- package/src/types/index.ts +0 -497
- package/src/views/AgentFeed.tsx +0 -339
- package/src/views/DeployPipeline.tsx +0 -59
- package/src/views/EnforcementView.tsx +0 -378
- package/src/views/PrimitivesConfig.tsx +0 -500
- package/src/views/QualityGates.tsx +0 -1012
- package/src/views/ScopeBoard.tsx +0 -454
- package/src/views/SessionTimeline.tsx +0 -516
- package/src/views/Settings.tsx +0 -183
- package/src/views/SourceControl.tsx +0 -95
- package/src/views/WorkflowVisualizer.tsx +0 -382
- package/tailwind.config.js +0 -161
- package/tsconfig.json +0 -25
- package/vite.config.ts +0 -49
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Plus, GitBranch, Undo2, Redo2, Save, XCircle, Eye,
|
|
3
|
-
CheckCircle2, AlertTriangle, Settings,
|
|
4
|
-
} from 'lucide-react';
|
|
5
|
-
import type { ConfigValidationResult } from './validateConfig';
|
|
6
|
-
|
|
7
|
-
// ─── Types ──────────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
interface EditToolbarProps {
|
|
10
|
-
canUndo: boolean;
|
|
11
|
-
canRedo: boolean;
|
|
12
|
-
changeCount: number;
|
|
13
|
-
validation: ConfigValidationResult;
|
|
14
|
-
saving: boolean;
|
|
15
|
-
onAddList: () => void;
|
|
16
|
-
onAddEdge: () => void;
|
|
17
|
-
onConfigSettings: () => void;
|
|
18
|
-
onUndo: () => void;
|
|
19
|
-
onRedo: () => void;
|
|
20
|
-
onSave: () => void;
|
|
21
|
-
onDiscard: () => void;
|
|
22
|
-
onPreview: () => void;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// ─── Component ──────────────────────────────────────────
|
|
26
|
-
|
|
27
|
-
export function EditToolbar({
|
|
28
|
-
canUndo,
|
|
29
|
-
canRedo,
|
|
30
|
-
changeCount,
|
|
31
|
-
validation,
|
|
32
|
-
saving,
|
|
33
|
-
onAddList,
|
|
34
|
-
onAddEdge,
|
|
35
|
-
onConfigSettings,
|
|
36
|
-
onUndo,
|
|
37
|
-
onRedo,
|
|
38
|
-
onSave,
|
|
39
|
-
onDiscard,
|
|
40
|
-
onPreview,
|
|
41
|
-
}: EditToolbarProps) {
|
|
42
|
-
return (
|
|
43
|
-
<div className="flex items-center gap-2 rounded-lg border border-cyan-500/30 bg-zinc-900/95 px-3 py-2 shadow-lg backdrop-blur">
|
|
44
|
-
{/* Add buttons */}
|
|
45
|
-
<ToolButton icon={Plus} label="List" onClick={onAddList} color="blue" />
|
|
46
|
-
<ToolButton icon={GitBranch} label="Edge" onClick={onAddEdge} color="blue" />
|
|
47
|
-
<ToolButton icon={Settings} label="Config" onClick={onConfigSettings} />
|
|
48
|
-
|
|
49
|
-
<Divider />
|
|
50
|
-
|
|
51
|
-
{/* Undo/Redo */}
|
|
52
|
-
<ToolButton icon={Undo2} onClick={onUndo} disabled={!canUndo} />
|
|
53
|
-
<ToolButton icon={Redo2} onClick={onRedo} disabled={!canRedo} />
|
|
54
|
-
|
|
55
|
-
{/* Dirty indicator */}
|
|
56
|
-
{changeCount > 0 && (
|
|
57
|
-
<span className="rounded-full bg-amber-500/20 px-2 py-0.5 text-[9px] font-semibold text-amber-400">
|
|
58
|
-
{changeCount} change{changeCount !== 1 ? 's' : ''}
|
|
59
|
-
</span>
|
|
60
|
-
)}
|
|
61
|
-
|
|
62
|
-
<Divider />
|
|
63
|
-
|
|
64
|
-
{/* Validation status */}
|
|
65
|
-
{validation.valid ? (
|
|
66
|
-
<span className="flex items-center gap-1 text-[10px] text-emerald-400">
|
|
67
|
-
<CheckCircle2 className="h-3.5 w-3.5" />
|
|
68
|
-
Valid
|
|
69
|
-
</span>
|
|
70
|
-
) : (
|
|
71
|
-
<span className="group relative flex items-center gap-1 text-[10px] text-red-400">
|
|
72
|
-
<AlertTriangle className="h-3.5 w-3.5" />
|
|
73
|
-
{validation.errors.length} error{validation.errors.length !== 1 ? 's' : ''}
|
|
74
|
-
{/* Tooltip with error list */}
|
|
75
|
-
<div className="absolute bottom-full left-0 z-50 mb-2 hidden w-64 rounded border border-red-500/30 bg-zinc-900 p-2 shadow-xl group-hover:block">
|
|
76
|
-
{validation.errors.map((e) => (
|
|
77
|
-
<p key={e} className="text-[10px] text-red-400">{e}</p>
|
|
78
|
-
))}
|
|
79
|
-
</div>
|
|
80
|
-
</span>
|
|
81
|
-
)}
|
|
82
|
-
|
|
83
|
-
<Divider />
|
|
84
|
-
|
|
85
|
-
{/* Preview / Save / Discard */}
|
|
86
|
-
<ToolButton icon={Eye} label="Preview" onClick={onPreview} />
|
|
87
|
-
<button
|
|
88
|
-
onClick={onSave}
|
|
89
|
-
disabled={!validation.valid || changeCount === 0 || saving}
|
|
90
|
-
className="flex items-center gap-1.5 rounded bg-emerald-600 px-3 py-1.5 text-[11px] font-medium text-white transition-colors hover:bg-emerald-500 disabled:opacity-40"
|
|
91
|
-
>
|
|
92
|
-
<Save className="h-3 w-3" />
|
|
93
|
-
{saving ? 'Saving...' : 'Save'}
|
|
94
|
-
</button>
|
|
95
|
-
<button
|
|
96
|
-
onClick={onDiscard}
|
|
97
|
-
className="flex items-center gap-1.5 rounded bg-red-600/80 px-3 py-1.5 text-[11px] font-medium text-white transition-colors hover:bg-red-500"
|
|
98
|
-
>
|
|
99
|
-
<XCircle className="h-3 w-3" />
|
|
100
|
-
Discard
|
|
101
|
-
</button>
|
|
102
|
-
</div>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// ─── Sub-components ─────────────────────────────────────
|
|
107
|
-
|
|
108
|
-
interface ToolButtonProps {
|
|
109
|
-
icon: React.ComponentType<{ className?: string }>;
|
|
110
|
-
label?: string;
|
|
111
|
-
onClick: () => void;
|
|
112
|
-
disabled?: boolean;
|
|
113
|
-
color?: 'blue' | 'default';
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function ToolButton({ icon: Icon, label, onClick, disabled, color }: ToolButtonProps) {
|
|
117
|
-
const isBlue = color === 'blue';
|
|
118
|
-
return (
|
|
119
|
-
<button
|
|
120
|
-
onClick={onClick}
|
|
121
|
-
disabled={disabled}
|
|
122
|
-
className="flex items-center gap-1 rounded px-2 py-1.5 text-[10px] font-medium transition-colors disabled:opacity-30"
|
|
123
|
-
style={{
|
|
124
|
-
color: isBlue ? '#3b82f6' : '#a1a1aa',
|
|
125
|
-
backgroundColor: 'transparent',
|
|
126
|
-
}}
|
|
127
|
-
onMouseEnter={(e) => { e.currentTarget.style.backgroundColor = isBlue ? '#3b82f615' : '#27272a'; }}
|
|
128
|
-
onMouseLeave={(e) => { e.currentTarget.style.backgroundColor = 'transparent'; }}
|
|
129
|
-
>
|
|
130
|
-
<Icon className="h-3.5 w-3.5" />
|
|
131
|
-
{label}
|
|
132
|
-
</button>
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function Divider() {
|
|
137
|
-
return <div className="h-4 w-px bg-zinc-800" />;
|
|
138
|
-
}
|
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
X, ArrowRight, Shield, Terminal, Radio, Globe, Bot,
|
|
4
|
-
ShieldCheck, AlertTriangle, Cog, Eye, FileCode2, ExternalLink,
|
|
5
|
-
} from 'lucide-react';
|
|
6
|
-
import type {
|
|
7
|
-
WorkflowEdge, HookCategory, HookEnforcement, UnifiedHook, CcTrigger,
|
|
8
|
-
} from '../../../shared/workflow-config';
|
|
9
|
-
import { getHookEnforcement } from '../../../shared/workflow-config';
|
|
10
|
-
|
|
11
|
-
// ─── Types ──────────────────────────────────────────
|
|
12
|
-
|
|
13
|
-
interface HookDetailPanelProps {
|
|
14
|
-
hook: UnifiedHook | null;
|
|
15
|
-
edges: WorkflowEdge[];
|
|
16
|
-
onClose: () => void;
|
|
17
|
-
onViewSource: (hook: UnifiedHook) => void;
|
|
18
|
-
onNavigateToEdge?: (from: string, to: string) => void;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// ─── Constants ──────────────────────────────────────────
|
|
22
|
-
|
|
23
|
-
const CATEGORY_CONFIG: Record<HookCategory, { icon: typeof Shield; color: string; label: string }> = {
|
|
24
|
-
guard: { icon: ShieldCheck, color: '#ef4444', label: 'Guard' },
|
|
25
|
-
gate: { icon: AlertTriangle, color: '#f59e0b', label: 'Gate' },
|
|
26
|
-
lifecycle: { icon: Cog, color: '#3b82f6', label: 'Lifecycle' },
|
|
27
|
-
observer: { icon: Eye, color: '#6b7280', label: 'Observer' },
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const ENFORCEMENT_CONFIG: Record<HookEnforcement, { color: string; description: string }> = {
|
|
31
|
-
blocker: { color: '#ef4444', description: 'Blocks transition on failure' },
|
|
32
|
-
advisor: { color: '#f59e0b', description: 'Warns but allows transition' },
|
|
33
|
-
operator: { color: '#3b82f6', description: 'Side-effects during lifecycle' },
|
|
34
|
-
silent: { color: '#6b7280', description: 'Observes without affecting outcome' },
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const TIMING_COLORS: Record<string, string> = { before: '#eab308', after: '#3b82f6' };
|
|
38
|
-
const TYPE_ICONS: Record<string, typeof Terminal> = { shell: Terminal, event: Radio, webhook: Globe };
|
|
39
|
-
const TYPE_COLORS: Record<string, string> = { shell: '#22c55e', event: '#a855f7', webhook: '#f97316' };
|
|
40
|
-
const DIRECTION_COLORS: Record<string, string> = { forward: '#22c55e', backward: '#f59e0b', shortcut: '#6366f1' };
|
|
41
|
-
|
|
42
|
-
const SOURCE_CONFIG: Record<string, { label: string; color: string }> = {
|
|
43
|
-
workflow: { label: 'Workflow', color: '#f97316' },
|
|
44
|
-
'claude-code': { label: 'Claude Code', color: '#10b981' },
|
|
45
|
-
both: { label: 'Both', color: '#8b5cf6' },
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
const CC_EVENT_COLORS: Record<string, string> = {
|
|
49
|
-
SessionStart: '#22c55e',
|
|
50
|
-
SessionEnd: '#ef4444',
|
|
51
|
-
PreToolUse: '#eab308',
|
|
52
|
-
PostToolUse: '#3b82f6',
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
// ─── Component ──────────────────────────────────────────
|
|
56
|
-
|
|
57
|
-
export function HookDetailPanel({ hook, edges, onClose, onViewSource, onNavigateToEdge }: HookDetailPanelProps) {
|
|
58
|
-
const attachedEdges = useMemo(() => {
|
|
59
|
-
if (!hook?.workflow) return [];
|
|
60
|
-
return edges.filter((e) => (e.hooks ?? []).includes(hook.id));
|
|
61
|
-
}, [hook, edges]);
|
|
62
|
-
|
|
63
|
-
if (!hook) return null;
|
|
64
|
-
|
|
65
|
-
const hasWorkflow = !!hook.workflow;
|
|
66
|
-
const hasCc = !!hook.ccTriggers?.length;
|
|
67
|
-
const srcConfig = SOURCE_CONFIG[hook.source];
|
|
68
|
-
const catConfig = hasWorkflow ? CATEGORY_CONFIG[hook.workflow!.category] : null;
|
|
69
|
-
const CatIcon = catConfig?.icon ?? Bot;
|
|
70
|
-
const catColor = catConfig?.color ?? '#10b981';
|
|
71
|
-
const enforcement = hasWorkflow
|
|
72
|
-
? getHookEnforcement({ category: hook.workflow!.category } as Parameters<typeof getHookEnforcement>[0])
|
|
73
|
-
: null;
|
|
74
|
-
const enforcementConfig = enforcement ? ENFORCEMENT_CONFIG[enforcement] : null;
|
|
75
|
-
const TypeIcon = hasWorkflow ? (TYPE_ICONS[hook.workflow!.type] ?? Terminal) : Bot;
|
|
76
|
-
|
|
77
|
-
return (
|
|
78
|
-
<div className="flex h-full w-96 shrink-0 flex-col rounded-lg border border-zinc-800 bg-zinc-900/95 backdrop-blur">
|
|
79
|
-
{/* Header */}
|
|
80
|
-
<div className="flex items-center justify-between border-b border-zinc-800 px-4 py-3">
|
|
81
|
-
<div className="flex items-center gap-2 min-w-0">
|
|
82
|
-
<CatIcon className="h-4 w-4 shrink-0" style={{ color: catColor }} />
|
|
83
|
-
<span className="text-sm font-medium text-zinc-200 truncate">{hook.label}</span>
|
|
84
|
-
</div>
|
|
85
|
-
<button onClick={onClose} className="rounded p-1 text-zinc-500 hover:bg-zinc-800 hover:text-zinc-300">
|
|
86
|
-
<X className="h-4 w-4" />
|
|
87
|
-
</button>
|
|
88
|
-
</div>
|
|
89
|
-
|
|
90
|
-
{/* Content */}
|
|
91
|
-
<div className="flex-1 space-y-4 overflow-y-auto p-4 text-xs">
|
|
92
|
-
{/* Source badge */}
|
|
93
|
-
<div className="flex flex-wrap items-center gap-2">
|
|
94
|
-
<span
|
|
95
|
-
className="rounded px-2 py-0.5 text-[10px] font-bold uppercase"
|
|
96
|
-
style={{ backgroundColor: `${srcConfig.color}20`, color: srcConfig.color }}
|
|
97
|
-
>
|
|
98
|
-
{srcConfig.label}
|
|
99
|
-
</span>
|
|
100
|
-
{hasWorkflow && enforcement && enforcementConfig && (
|
|
101
|
-
<span
|
|
102
|
-
className="rounded px-2 py-0.5 text-[10px] font-bold uppercase"
|
|
103
|
-
style={{ backgroundColor: `${enforcementConfig.color}20`, color: enforcementConfig.color }}
|
|
104
|
-
>
|
|
105
|
-
{enforcement}
|
|
106
|
-
</span>
|
|
107
|
-
)}
|
|
108
|
-
{hasWorkflow && hook.workflow!.blocking && (
|
|
109
|
-
<span className="flex items-center gap-1 rounded bg-red-500/15 px-2 py-0.5 text-[10px] font-semibold uppercase text-red-400">
|
|
110
|
-
<Shield className="h-2.5 w-2.5" />
|
|
111
|
-
Blocking
|
|
112
|
-
</span>
|
|
113
|
-
)}
|
|
114
|
-
</div>
|
|
115
|
-
|
|
116
|
-
{/* Workflow Properties */}
|
|
117
|
-
{hasWorkflow && (
|
|
118
|
-
<Section title="Workflow Properties">
|
|
119
|
-
<PropRow label="Timing" value={hook.workflow!.timing} color={TIMING_COLORS[hook.workflow!.timing]} />
|
|
120
|
-
<PropRow label="Type" value={hook.workflow!.type} color={TYPE_COLORS[hook.workflow!.type]} />
|
|
121
|
-
<PropRow label="Category" value={hook.workflow!.category} color={catColor} />
|
|
122
|
-
<PropRow label="Blocking" value={hook.workflow!.blocking ? 'Yes' : 'No'} color={hook.workflow!.blocking ? '#ef4444' : '#6b7280'} />
|
|
123
|
-
</Section>
|
|
124
|
-
)}
|
|
125
|
-
|
|
126
|
-
{/* Enforcement derivation */}
|
|
127
|
-
{hasWorkflow && enforcement && enforcementConfig && (
|
|
128
|
-
<Section title="Enforcement">
|
|
129
|
-
<p className="text-zinc-500">{enforcementConfig.description}</p>
|
|
130
|
-
<p className="mt-1 text-[10px] text-zinc-600">
|
|
131
|
-
{hook.workflow!.category} <span className="text-zinc-700">→</span>{' '}
|
|
132
|
-
<span style={{ color: enforcementConfig.color }}>{enforcement}</span>
|
|
133
|
-
</p>
|
|
134
|
-
</Section>
|
|
135
|
-
)}
|
|
136
|
-
|
|
137
|
-
{/* Description */}
|
|
138
|
-
{hasWorkflow && hook.workflow!.description && (
|
|
139
|
-
<Section title="Description">
|
|
140
|
-
<p className="text-zinc-400 leading-relaxed">{hook.workflow!.description}</p>
|
|
141
|
-
</Section>
|
|
142
|
-
)}
|
|
143
|
-
|
|
144
|
-
{/* Script Path */}
|
|
145
|
-
<Section title="Script Path">
|
|
146
|
-
<div className="flex items-center gap-2 rounded border border-zinc-800 bg-zinc-950 px-3 py-2 font-mono text-[11px] text-emerald-400">
|
|
147
|
-
<TypeIcon className="h-3.5 w-3.5 shrink-0 text-zinc-600" />
|
|
148
|
-
<span className="truncate">{hook.scriptPath}</span>
|
|
149
|
-
</div>
|
|
150
|
-
</Section>
|
|
151
|
-
|
|
152
|
-
{/* CC Triggers */}
|
|
153
|
-
{hasCc && (
|
|
154
|
-
<Section title={`Claude Code Triggers (${hook.ccTriggers!.length})`}>
|
|
155
|
-
<CCTriggerList triggers={hook.ccTriggers!} />
|
|
156
|
-
</Section>
|
|
157
|
-
)}
|
|
158
|
-
|
|
159
|
-
{/* Attached Edges */}
|
|
160
|
-
{hasWorkflow && (
|
|
161
|
-
<Section title={`Attached Edges (${attachedEdges.length})`}>
|
|
162
|
-
{attachedEdges.length === 0 ? (
|
|
163
|
-
<span className="text-zinc-600">No edges reference this hook</span>
|
|
164
|
-
) : (
|
|
165
|
-
<div className="space-y-1.5">
|
|
166
|
-
{attachedEdges.map((e) => {
|
|
167
|
-
const color = DIRECTION_COLORS[e.direction] ?? '#22c55e';
|
|
168
|
-
return (
|
|
169
|
-
<button
|
|
170
|
-
key={`${e.from}:${e.to}`}
|
|
171
|
-
onClick={() => onNavigateToEdge?.(e.from, e.to)}
|
|
172
|
-
className="flex w-full items-center gap-2 rounded border border-zinc-800/50 bg-zinc-950/30 px-2 py-1.5 text-left transition-colors hover:border-zinc-700 hover:bg-zinc-900/50"
|
|
173
|
-
>
|
|
174
|
-
<span className="rounded px-1 py-0.5 text-[9px] uppercase" style={{ backgroundColor: `${color}20`, color }}>
|
|
175
|
-
{e.direction}
|
|
176
|
-
</span>
|
|
177
|
-
<span className="text-zinc-300">{e.from}</span>
|
|
178
|
-
<ArrowRight className="h-2.5 w-2.5 text-zinc-600" />
|
|
179
|
-
<span className="text-zinc-300">{e.to}</span>
|
|
180
|
-
<ExternalLink className="ml-auto h-3 w-3 text-zinc-600" />
|
|
181
|
-
</button>
|
|
182
|
-
);
|
|
183
|
-
})}
|
|
184
|
-
</div>
|
|
185
|
-
)}
|
|
186
|
-
</Section>
|
|
187
|
-
)}
|
|
188
|
-
</div>
|
|
189
|
-
|
|
190
|
-
{/* Footer — View Source */}
|
|
191
|
-
<div className="border-t border-zinc-800 p-3">
|
|
192
|
-
<button
|
|
193
|
-
onClick={() => onViewSource(hook)}
|
|
194
|
-
className="flex w-full items-center justify-center gap-2 rounded border border-zinc-700 bg-zinc-800/50 px-3 py-2 text-xs text-zinc-300 transition-colors hover:border-zinc-600 hover:bg-zinc-800"
|
|
195
|
-
>
|
|
196
|
-
<FileCode2 className="h-3.5 w-3.5" />
|
|
197
|
-
View Source Code
|
|
198
|
-
</button>
|
|
199
|
-
</div>
|
|
200
|
-
</div>
|
|
201
|
-
);
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// ─── Sub-components ─────────────────────────────────────
|
|
205
|
-
|
|
206
|
-
function CCTriggerList({ triggers }: { triggers: CcTrigger[] }) {
|
|
207
|
-
return (
|
|
208
|
-
<div className="space-y-1.5">
|
|
209
|
-
{triggers.map((t, i) => {
|
|
210
|
-
const evColor = CC_EVENT_COLORS[t.event] ?? '#10b981';
|
|
211
|
-
return (
|
|
212
|
-
<div key={i} className="flex items-center gap-2 rounded border border-zinc-800/50 bg-zinc-950/30 px-2 py-1.5">
|
|
213
|
-
<span
|
|
214
|
-
className="rounded px-1.5 py-0.5 text-[9px] font-semibold uppercase"
|
|
215
|
-
style={{ backgroundColor: `${evColor}20`, color: evColor }}
|
|
216
|
-
>
|
|
217
|
-
{t.event}
|
|
218
|
-
</span>
|
|
219
|
-
{t.matcher && (
|
|
220
|
-
<span className="rounded bg-zinc-800 px-1.5 py-0.5 font-mono text-[9px] text-zinc-400">
|
|
221
|
-
{t.matcher}
|
|
222
|
-
</span>
|
|
223
|
-
)}
|
|
224
|
-
{t.statusMessage && (
|
|
225
|
-
<span className="ml-auto truncate text-[10px] text-zinc-600">{t.statusMessage}</span>
|
|
226
|
-
)}
|
|
227
|
-
</div>
|
|
228
|
-
);
|
|
229
|
-
})}
|
|
230
|
-
</div>
|
|
231
|
-
);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
function Section({ title, children }: { title: string; children: React.ReactNode }) {
|
|
235
|
-
return (
|
|
236
|
-
<div>
|
|
237
|
-
<h4 className="mb-2 text-[10px] font-semibold uppercase tracking-wider text-zinc-500">{title}</h4>
|
|
238
|
-
{children}
|
|
239
|
-
</div>
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
function PropRow({ label, value, color }: { label: string; value: string; color?: string }) {
|
|
244
|
-
return (
|
|
245
|
-
<div className="flex items-center justify-between py-0.5">
|
|
246
|
-
<span className="text-zinc-500">{label}</span>
|
|
247
|
-
<span className="text-zinc-300" style={color ? { color } : undefined}>{value}</span>
|
|
248
|
-
</div>
|
|
249
|
-
);
|
|
250
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { Zap, Clock } from 'lucide-react';
|
|
2
|
-
|
|
3
|
-
// ─── Component ──────────────────────────────────────────
|
|
4
|
-
// Placeholder for hook execution history.
|
|
5
|
-
// The CC events system does not yet track hook executions,
|
|
6
|
-
// so this component shows a "no data" state.
|
|
7
|
-
// When hook execution tracking is added (scope 079+),
|
|
8
|
-
// this will subscribe to Socket.io events and display live data.
|
|
9
|
-
|
|
10
|
-
export function HookExecutionLog() {
|
|
11
|
-
return (
|
|
12
|
-
<div className="flex flex-col items-center gap-3 rounded-lg border border-zinc-800 bg-zinc-950/50 p-8 text-center">
|
|
13
|
-
<div className="flex items-center gap-2 text-zinc-600">
|
|
14
|
-
<Zap className="h-4 w-4" />
|
|
15
|
-
<Clock className="h-4 w-4" />
|
|
16
|
-
</div>
|
|
17
|
-
<span className="text-xs font-medium text-zinc-500">No hook execution data available</span>
|
|
18
|
-
<p className="max-w-xs text-[10px] text-zinc-600">
|
|
19
|
-
Hook execution tracking will be added when the Hook & Event Foundation (scope 079) is implemented.
|
|
20
|
-
This panel will show real-time hook firing events with timestamps, results, and durations.
|
|
21
|
-
</p>
|
|
22
|
-
</div>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
|
-
import { FileCode2, Loader2 } from 'lucide-react';
|
|
3
|
-
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from '@/components/ui/dialog';
|
|
4
|
-
import { ScrollArea } from '@/components/ui/scroll-area';
|
|
5
|
-
import type { UnifiedHook } from '../../../shared/workflow-config';
|
|
6
|
-
|
|
7
|
-
// ─── Types ──────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
interface HookSourceModalProps {
|
|
10
|
-
hook: UnifiedHook | null;
|
|
11
|
-
open: boolean;
|
|
12
|
-
onClose: () => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
interface HookSource {
|
|
16
|
-
filePath: string;
|
|
17
|
-
content: string;
|
|
18
|
-
lineCount: number;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// ─── Component ──────────────────────────────────────────
|
|
22
|
-
|
|
23
|
-
export function HookSourceModal({ hook, open, onClose }: HookSourceModalProps) {
|
|
24
|
-
const [source, setSource] = useState<HookSource | null>(null);
|
|
25
|
-
const [loading, setLoading] = useState(false);
|
|
26
|
-
const [error, setError] = useState<string | null>(null);
|
|
27
|
-
|
|
28
|
-
useEffect(() => {
|
|
29
|
-
if (!hook || !open) { setSource(null); setError(null); return; }
|
|
30
|
-
let cancelled = false;
|
|
31
|
-
setLoading(true);
|
|
32
|
-
setError(null);
|
|
33
|
-
|
|
34
|
-
fetch(`/api/orbital/workflow/hooks/source?path=${encodeURIComponent(hook.scriptPath)}`)
|
|
35
|
-
.then(async (res) => {
|
|
36
|
-
if (cancelled) return;
|
|
37
|
-
if (!res.ok) {
|
|
38
|
-
const body = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
|
|
39
|
-
setError(body.error ?? `Failed to load source (HTTP ${res.status})`);
|
|
40
|
-
setSource(null);
|
|
41
|
-
} else {
|
|
42
|
-
const json = await res.json() as { data: HookSource };
|
|
43
|
-
setSource(json.data);
|
|
44
|
-
}
|
|
45
|
-
})
|
|
46
|
-
.catch((err) => { if (!cancelled) setError(err instanceof Error ? err.message : 'Network error'); })
|
|
47
|
-
.finally(() => { if (!cancelled) setLoading(false); });
|
|
48
|
-
|
|
49
|
-
return () => { cancelled = true; };
|
|
50
|
-
}, [hook?.id, hook?.scriptPath, open]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
51
|
-
|
|
52
|
-
if (!hook) return null;
|
|
53
|
-
|
|
54
|
-
return (
|
|
55
|
-
<Dialog open={open} onOpenChange={(isOpen) => { if (!isOpen) onClose(); }}>
|
|
56
|
-
<DialogContent className="max-w-[min(56rem,calc(100vw_-_2rem))] h-[80vh] flex flex-col p-0 gap-0 overflow-hidden">
|
|
57
|
-
<DialogHeader className="px-4 pt-3 pb-2">
|
|
58
|
-
<div className="flex items-center gap-2 pr-8">
|
|
59
|
-
<FileCode2 className="h-4 w-4 shrink-0 text-zinc-500" />
|
|
60
|
-
<DialogTitle className="text-sm font-medium text-foreground leading-tight truncate">
|
|
61
|
-
{hook.label}
|
|
62
|
-
</DialogTitle>
|
|
63
|
-
</div>
|
|
64
|
-
<DialogDescription className="mt-1 font-mono text-[11px] text-zinc-500 truncate">
|
|
65
|
-
{hook.scriptPath}
|
|
66
|
-
</DialogDescription>
|
|
67
|
-
</DialogHeader>
|
|
68
|
-
|
|
69
|
-
<div className="flex-1 min-h-0 border-t border-zinc-800 bg-[#0a0a12]">
|
|
70
|
-
<ScrollArea className="h-full">
|
|
71
|
-
<div className="px-2 py-3">
|
|
72
|
-
{loading && (
|
|
73
|
-
<div className="flex items-center gap-2 px-4 py-8 text-xs text-zinc-500">
|
|
74
|
-
<Loader2 className="h-4 w-4 animate-spin" />
|
|
75
|
-
Loading source...
|
|
76
|
-
</div>
|
|
77
|
-
)}
|
|
78
|
-
{error && (
|
|
79
|
-
<div className="px-4 py-8 text-xs text-red-400">
|
|
80
|
-
<FileCode2 className="mb-2 h-5 w-5 text-zinc-600" />
|
|
81
|
-
{error}
|
|
82
|
-
</div>
|
|
83
|
-
)}
|
|
84
|
-
{source && <SourceViewer content={source.content} filePath={source.filePath} />}
|
|
85
|
-
{!loading && !error && !source && (
|
|
86
|
-
<div className="px-4 py-8 text-xs text-zinc-600 italic">No source available</div>
|
|
87
|
-
)}
|
|
88
|
-
</div>
|
|
89
|
-
</ScrollArea>
|
|
90
|
-
</div>
|
|
91
|
-
|
|
92
|
-
{source && (
|
|
93
|
-
<div className="border-t border-zinc-800 px-4 py-2 text-[10px] text-zinc-600">
|
|
94
|
-
{source.lineCount} lines
|
|
95
|
-
</div>
|
|
96
|
-
)}
|
|
97
|
-
</DialogContent>
|
|
98
|
-
</Dialog>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// ─── Sub-components ─────────────────────────────────────
|
|
103
|
-
|
|
104
|
-
function SourceViewer({ content, filePath }: { content: string; filePath: string }) {
|
|
105
|
-
const lines = content.split('\n');
|
|
106
|
-
const gutterWidth = String(lines.length).length;
|
|
107
|
-
|
|
108
|
-
return (
|
|
109
|
-
<div>
|
|
110
|
-
<div className="mb-2 flex items-center gap-2 rounded border border-zinc-800/50 bg-zinc-900/50 px-3 py-1.5 font-mono text-[10px] text-zinc-500">
|
|
111
|
-
<FileCode2 className="h-3 w-3 shrink-0" />
|
|
112
|
-
{filePath}
|
|
113
|
-
</div>
|
|
114
|
-
<pre className="font-mono text-[12px] leading-[1.6]">
|
|
115
|
-
{lines.map((line, i) => (
|
|
116
|
-
<div key={i} className="flex hover:bg-white/[0.02]">
|
|
117
|
-
<span
|
|
118
|
-
className="select-none text-right text-zinc-700 pr-3 shrink-0"
|
|
119
|
-
style={{ width: `${gutterWidth + 2}ch` }}
|
|
120
|
-
>
|
|
121
|
-
{i + 1}
|
|
122
|
-
</span>
|
|
123
|
-
<span className="text-zinc-300 whitespace-pre overflow-x-auto">{line || ' '}</span>
|
|
124
|
-
</div>
|
|
125
|
-
))}
|
|
126
|
-
</pre>
|
|
127
|
-
</div>
|
|
128
|
-
);
|
|
129
|
-
}
|