groove-dev 0.27.143 → 0.27.145
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/CLAUDE.md +0 -7
- package/node_modules/@groove-dev/cli/package.json +1 -1
- package/node_modules/@groove-dev/daemon/package.json +1 -1
- package/node_modules/@groove-dev/daemon/src/api.js +1086 -6532
- package/node_modules/@groove-dev/daemon/src/conversations.js +18 -48
- package/node_modules/@groove-dev/daemon/src/gateways/manager.js +35 -1
- package/node_modules/@groove-dev/daemon/src/index.js +3 -0
- package/node_modules/@groove-dev/daemon/src/journalist.js +23 -13
- package/node_modules/@groove-dev/daemon/src/mlx-server.js +365 -0
- package/node_modules/@groove-dev/daemon/src/model-lab.js +308 -12
- package/node_modules/@groove-dev/daemon/src/pm.js +1 -1
- package/node_modules/@groove-dev/daemon/src/process.js +2 -2
- package/node_modules/@groove-dev/daemon/src/providers/local.js +36 -8
- package/node_modules/@groove-dev/daemon/src/registry.js +21 -5
- package/node_modules/@groove-dev/daemon/src/routes/agents.js +812 -0
- package/node_modules/@groove-dev/daemon/src/routes/coordination.js +318 -0
- package/node_modules/@groove-dev/daemon/src/routes/files.js +751 -0
- package/node_modules/@groove-dev/daemon/src/routes/integrations.js +485 -0
- package/node_modules/@groove-dev/daemon/src/routes/network.js +1784 -0
- package/node_modules/@groove-dev/daemon/src/routes/providers.js +755 -0
- package/node_modules/@groove-dev/daemon/src/routes/schedules.js +110 -0
- package/node_modules/@groove-dev/daemon/src/routes/teams.js +650 -0
- package/node_modules/@groove-dev/daemon/src/scheduler.js +456 -24
- package/node_modules/@groove-dev/daemon/src/teams.js +1 -1
- package/node_modules/@groove-dev/daemon/src/validate.js +38 -1
- package/node_modules/@groove-dev/daemon/templates/mlx-setup.json +12 -0
- package/node_modules/@groove-dev/daemon/templates/tgi-setup.json +1 -1
- package/node_modules/@groove-dev/daemon/templates/vllm-setup.json +1 -1
- package/node_modules/@groove-dev/daemon/test/introducer.test.js +3 -3
- package/node_modules/@groove-dev/daemon/test/journalist.test.js +7 -10
- package/node_modules/@groove-dev/daemon/test/registry.test.js +38 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-Bxc0gU06.js +1006 -0
- package/node_modules/@groove-dev/gui/dist/assets/index-C0pztKBn.css +1 -0
- package/node_modules/@groove-dev/gui/dist/index.html +2 -2
- package/node_modules/@groove-dev/gui/package.json +1 -1
- package/node_modules/@groove-dev/gui/src/{app.jsx → App.jsx} +0 -2
- package/node_modules/@groove-dev/gui/src/app.css +35 -0
- package/node_modules/@groove-dev/gui/src/components/agents/agent-config.jsx +1 -128
- package/node_modules/@groove-dev/gui/src/components/agents/agent-feed.jsx +210 -112
- package/node_modules/@groove-dev/gui/src/components/agents/agent-node.jsx +8 -13
- package/node_modules/@groove-dev/gui/src/components/agents/agent-panel.jsx +2 -70
- package/node_modules/@groove-dev/gui/src/components/agents/code-review.jsx +159 -122
- package/node_modules/@groove-dev/gui/src/components/agents/diff-viewer.jsx +23 -23
- package/node_modules/@groove-dev/gui/src/components/agents/journalist-panel.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/components/agents/spawn-wizard.jsx +2 -135
- package/node_modules/@groove-dev/gui/src/components/automations/automation-card.jsx +274 -0
- package/node_modules/@groove-dev/gui/src/components/automations/automation-wizard.jsx +1136 -0
- package/node_modules/@groove-dev/gui/src/components/chat/chat-header.jsx +2 -0
- package/node_modules/@groove-dev/gui/src/components/chat/chat-input.jsx +68 -66
- package/node_modules/@groove-dev/gui/src/components/chat/chat-view.jsx +4 -8
- package/node_modules/@groove-dev/gui/src/components/dashboard/activity-feed.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/components/dashboard/cache-ring.jsx +5 -5
- package/node_modules/@groove-dev/gui/src/components/dashboard/context-gauges.jsx +6 -8
- package/node_modules/@groove-dev/gui/src/components/dashboard/fleet-panel.jsx +8 -14
- package/node_modules/@groove-dev/gui/src/components/dashboard/intel-panel.jsx +238 -656
- package/node_modules/@groove-dev/gui/src/components/dashboard/kpi-card.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/components/dashboard/routing-chart.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/components/dashboard/team-burn-panel.jsx +1 -1
- package/node_modules/@groove-dev/gui/src/components/dashboard/token-chart.jsx +4 -4
- package/node_modules/@groove-dev/gui/src/components/lab/chat-playground.jsx +39 -31
- package/node_modules/@groove-dev/gui/src/components/lab/lab-assistant.jsx +316 -82
- package/node_modules/@groove-dev/gui/src/components/lab/metrics-panel.jsx +187 -32
- package/node_modules/@groove-dev/gui/src/components/lab/parameter-panel.jsx +200 -18
- package/node_modules/@groove-dev/gui/src/components/lab/preset-manager.jsx +17 -14
- package/node_modules/@groove-dev/gui/src/components/lab/runtime-config.jsx +335 -152
- package/node_modules/@groove-dev/gui/src/components/lab/system-prompt-editor.jsx +10 -8
- package/node_modules/@groove-dev/gui/src/components/layout/activity-bar.jsx +2 -4
- package/node_modules/@groove-dev/gui/src/components/layout/terminal-panel.jsx +4 -2
- package/node_modules/@groove-dev/gui/src/components/layout/welcome-splash.jsx +137 -108
- package/node_modules/@groove-dev/gui/src/components/network/network-health.jsx +2 -2
- package/node_modules/@groove-dev/gui/src/components/network/performance-dashboard.jsx +4 -4
- package/node_modules/@groove-dev/gui/src/components/settings/ssh-wizard.jsx +81 -99
- package/node_modules/@groove-dev/gui/src/components/ui/sheet.jsx +5 -2
- package/node_modules/@groove-dev/gui/src/components/ui/slider.jsx +8 -8
- package/node_modules/@groove-dev/gui/src/lib/cron.js +64 -0
- package/node_modules/@groove-dev/gui/src/lib/status.js +25 -24
- package/node_modules/@groove-dev/gui/src/lib/theme-hex.js +1 -0
- package/node_modules/@groove-dev/gui/src/stores/groove.js +51 -3144
- package/node_modules/@groove-dev/gui/src/stores/helpers.js +10 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/agents-slice.js +459 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/automations-slice.js +96 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/chat-slice.js +226 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/editor-slice.js +285 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/marketplace-slice.js +461 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/network-slice.js +361 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/preview-slice.js +109 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/providers-slice.js +897 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/teams-slice.js +413 -0
- package/node_modules/@groove-dev/gui/src/stores/slices/ui-slice.js +98 -0
- package/node_modules/@groove-dev/gui/src/views/agents.jsx +5 -5
- package/node_modules/@groove-dev/gui/src/views/dashboard.jsx +12 -13
- package/node_modules/@groove-dev/gui/src/views/marketplace.jsx +191 -3
- package/node_modules/@groove-dev/gui/src/views/model-lab.jsx +54 -12
- package/node_modules/@groove-dev/gui/src/views/models.jsx +419 -496
- package/node_modules/@groove-dev/gui/src/views/network.jsx +3 -3
- package/node_modules/@groove-dev/gui/src/views/settings.jsx +81 -94
- package/node_modules/@groove-dev/gui/src/views/teams.jsx +40 -483
- package/node_modules/axios/CHANGELOG.md +260 -0
- package/node_modules/axios/README.md +595 -223
- package/node_modules/axios/dist/axios.js +1460 -1090
- package/node_modules/axios/dist/axios.js.map +1 -1
- package/node_modules/axios/dist/axios.min.js +3 -3
- package/node_modules/axios/dist/axios.min.js.map +1 -1
- package/node_modules/axios/dist/browser/axios.cjs +1560 -1132
- package/node_modules/axios/dist/browser/axios.cjs.map +1 -1
- package/node_modules/axios/dist/esm/axios.js +1557 -1128
- package/node_modules/axios/dist/esm/axios.js.map +1 -1
- package/node_modules/axios/dist/esm/axios.min.js +2 -2
- package/node_modules/axios/dist/esm/axios.min.js.map +1 -1
- package/node_modules/axios/dist/node/axios.cjs +1594 -1057
- package/node_modules/axios/dist/node/axios.cjs.map +1 -1
- package/node_modules/axios/index.d.cts +40 -41
- package/node_modules/axios/index.d.ts +151 -227
- package/node_modules/axios/index.js +2 -0
- package/node_modules/axios/lib/adapters/adapters.js +4 -2
- package/node_modules/axios/lib/adapters/fetch.js +147 -16
- package/node_modules/axios/lib/adapters/http.js +306 -58
- package/node_modules/axios/lib/adapters/xhr.js +6 -2
- package/node_modules/axios/lib/core/Axios.js +7 -3
- package/node_modules/axios/lib/core/AxiosError.js +120 -34
- package/node_modules/axios/lib/core/AxiosHeaders.js +27 -25
- package/node_modules/axios/lib/core/buildFullPath.js +1 -1
- package/node_modules/axios/lib/core/dispatchRequest.js +19 -7
- package/node_modules/axios/lib/core/mergeConfig.js +21 -4
- package/node_modules/axios/lib/core/settle.js +7 -11
- package/node_modules/axios/lib/defaults/index.js +14 -9
- package/node_modules/axios/lib/env/data.js +1 -1
- package/node_modules/axios/lib/helpers/AxiosURLSearchParams.js +1 -2
- package/node_modules/axios/lib/helpers/buildURL.js +1 -1
- package/node_modules/axios/lib/helpers/cookies.js +14 -2
- package/node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js +28 -1
- package/node_modules/axios/lib/helpers/formDataToJSON.js +3 -1
- package/node_modules/axios/lib/helpers/formDataToStream.js +3 -2
- package/node_modules/axios/lib/helpers/parseProtocol.js +1 -1
- package/node_modules/axios/lib/helpers/progressEventReducer.js +5 -5
- package/node_modules/axios/lib/helpers/resolveConfig.js +54 -18
- package/node_modules/axios/lib/helpers/shouldBypassProxy.js +74 -2
- package/node_modules/axios/lib/helpers/toFormData.js +10 -2
- package/node_modules/axios/lib/helpers/validator.js +3 -1
- package/node_modules/axios/lib/utils.js +33 -21
- package/node_modules/axios/package.json +17 -24
- package/node_modules/follow-redirects/README.md +7 -5
- package/node_modules/follow-redirects/index.js +24 -1
- package/node_modules/follow-redirects/package.json +1 -1
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/daemon/package.json +1 -1
- package/packages/daemon/src/api.js +1086 -6532
- package/packages/daemon/src/conversations.js +18 -48
- package/packages/daemon/src/gateways/manager.js +35 -1
- package/packages/daemon/src/index.js +3 -0
- package/packages/daemon/src/journalist.js +23 -13
- package/packages/daemon/src/mlx-server.js +365 -0
- package/packages/daemon/src/model-lab.js +308 -12
- package/packages/daemon/src/pm.js +1 -1
- package/packages/daemon/src/process.js +2 -2
- package/packages/daemon/src/providers/local.js +36 -8
- package/packages/daemon/src/registry.js +21 -5
- package/packages/daemon/src/routes/agents.js +812 -0
- package/packages/daemon/src/routes/coordination.js +318 -0
- package/packages/daemon/src/routes/files.js +751 -0
- package/packages/daemon/src/routes/integrations.js +485 -0
- package/packages/daemon/src/routes/network.js +1784 -0
- package/packages/daemon/src/routes/providers.js +755 -0
- package/packages/daemon/src/routes/schedules.js +110 -0
- package/packages/daemon/src/routes/teams.js +650 -0
- package/packages/daemon/src/scheduler.js +456 -24
- package/packages/daemon/src/teams.js +1 -1
- package/packages/daemon/src/validate.js +38 -1
- package/packages/daemon/templates/mlx-setup.json +12 -0
- package/packages/daemon/templates/tgi-setup.json +1 -1
- package/packages/daemon/templates/vllm-setup.json +1 -1
- package/packages/gui/dist/assets/index-Bxc0gU06.js +1006 -0
- package/packages/gui/dist/assets/index-C0pztKBn.css +1 -0
- package/packages/gui/dist/index.html +2 -2
- package/packages/gui/package.json +1 -1
- package/packages/gui/src/{app.jsx → App.jsx} +0 -2
- package/packages/gui/src/app.css +35 -0
- package/packages/gui/src/components/agents/agent-config.jsx +1 -128
- package/packages/gui/src/components/agents/agent-feed.jsx +210 -112
- package/packages/gui/src/components/agents/agent-node.jsx +8 -13
- package/packages/gui/src/components/agents/agent-panel.jsx +2 -70
- package/packages/gui/src/components/agents/code-review.jsx +159 -122
- package/packages/gui/src/components/agents/diff-viewer.jsx +23 -23
- package/packages/gui/src/components/agents/journalist-panel.jsx +1 -1
- package/packages/gui/src/components/agents/spawn-wizard.jsx +2 -135
- package/packages/gui/src/components/automations/automation-card.jsx +274 -0
- package/packages/gui/src/components/automations/automation-wizard.jsx +1136 -0
- package/packages/gui/src/components/chat/chat-header.jsx +2 -0
- package/packages/gui/src/components/chat/chat-input.jsx +68 -66
- package/packages/gui/src/components/chat/chat-view.jsx +4 -8
- package/packages/gui/src/components/dashboard/activity-feed.jsx +3 -3
- package/packages/gui/src/components/dashboard/cache-ring.jsx +5 -5
- package/packages/gui/src/components/dashboard/context-gauges.jsx +6 -8
- package/packages/gui/src/components/dashboard/fleet-panel.jsx +8 -14
- package/packages/gui/src/components/dashboard/intel-panel.jsx +238 -656
- package/packages/gui/src/components/dashboard/kpi-card.jsx +3 -3
- package/packages/gui/src/components/dashboard/routing-chart.jsx +3 -3
- package/packages/gui/src/components/dashboard/team-burn-panel.jsx +1 -1
- package/packages/gui/src/components/dashboard/token-chart.jsx +4 -4
- package/packages/gui/src/components/lab/chat-playground.jsx +39 -31
- package/packages/gui/src/components/lab/lab-assistant.jsx +316 -82
- package/packages/gui/src/components/lab/metrics-panel.jsx +187 -32
- package/packages/gui/src/components/lab/parameter-panel.jsx +200 -18
- package/packages/gui/src/components/lab/preset-manager.jsx +17 -14
- package/packages/gui/src/components/lab/runtime-config.jsx +335 -152
- package/packages/gui/src/components/lab/system-prompt-editor.jsx +10 -8
- package/packages/gui/src/components/layout/activity-bar.jsx +2 -4
- package/packages/gui/src/components/layout/terminal-panel.jsx +4 -2
- package/packages/gui/src/components/layout/welcome-splash.jsx +137 -108
- package/packages/gui/src/components/network/network-health.jsx +2 -2
- package/packages/gui/src/components/network/performance-dashboard.jsx +4 -4
- package/packages/gui/src/components/settings/ssh-wizard.jsx +81 -99
- package/packages/gui/src/components/ui/sheet.jsx +5 -2
- package/packages/gui/src/components/ui/slider.jsx +8 -8
- package/packages/gui/src/lib/cron.js +64 -0
- package/packages/gui/src/lib/status.js +25 -24
- package/packages/gui/src/lib/theme-hex.js +1 -0
- package/packages/gui/src/stores/groove.js +51 -3144
- package/packages/gui/src/stores/helpers.js +10 -0
- package/packages/gui/src/stores/slices/agents-slice.js +459 -0
- package/packages/gui/src/stores/slices/automations-slice.js +96 -0
- package/packages/gui/src/stores/slices/chat-slice.js +226 -0
- package/packages/gui/src/stores/slices/editor-slice.js +285 -0
- package/packages/gui/src/stores/slices/marketplace-slice.js +461 -0
- package/packages/gui/src/stores/slices/network-slice.js +361 -0
- package/packages/gui/src/stores/slices/preview-slice.js +109 -0
- package/packages/gui/src/stores/slices/providers-slice.js +897 -0
- package/packages/gui/src/stores/slices/teams-slice.js +413 -0
- package/packages/gui/src/stores/slices/ui-slice.js +98 -0
- package/packages/gui/src/views/agents.jsx +5 -5
- package/packages/gui/src/views/dashboard.jsx +12 -13
- package/packages/gui/src/views/marketplace.jsx +191 -3
- package/packages/gui/src/views/model-lab.jsx +54 -12
- package/packages/gui/src/views/models.jsx +419 -496
- package/packages/gui/src/views/network.jsx +3 -3
- package/packages/gui/src/views/settings.jsx +81 -94
- package/packages/gui/src/views/teams.jsx +40 -483
- package/SECURITY_SWEEP.md +0 -228
- package/TRAINING_DATA_v4.md +0 -6
- package/node_modules/@groove-dev/gui/dist/assets/index-CCVvAoQn.css +0 -1
- package/node_modules/@groove-dev/gui/dist/assets/index-DGIv_TRm.js +0 -984
- package/node_modules/@groove-dev/gui/src/components/agents/agent-chat.jsx +0 -379
- package/node_modules/@groove-dev/gui/src/views/preview.jsx +0 -6
- package/node_modules/@groove-dev/gui/src/views/subscription-panel.jsx +0 -327
- package/packages/gui/dist/assets/index-CCVvAoQn.css +0 -1
- package/packages/gui/dist/assets/index-DGIv_TRm.js +0 -984
- package/packages/gui/src/components/agents/agent-chat.jsx +0 -379
- package/packages/gui/src/views/preview.jsx +0 -6
- package/packages/gui/src/views/subscription-panel.jsx +0 -327
- package/test.py +0 -571
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// FSL-1.1-Apache-2.0 — see LICENSE
|
|
2
|
-
import { useState, useEffect } from 'react';
|
|
2
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
3
3
|
import { useGrooveStore } from '../../stores/groove';
|
|
4
4
|
import { cn } from '../../lib/cn';
|
|
5
5
|
import { ScrollArea } from '../ui/scroll-area';
|
|
@@ -7,144 +7,161 @@ import { Button } from '../ui/button';
|
|
|
7
7
|
import { DiffViewer } from './diff-viewer';
|
|
8
8
|
import { api } from '../../lib/api';
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
ChevronLeft, ChevronRight, Send, FilePlus, FileMinus, FileEdit,
|
|
11
|
+
RotateCcw, MessageSquare, Eye,
|
|
12
12
|
} from 'lucide-react';
|
|
13
13
|
|
|
14
|
+
function statusIcon(status) {
|
|
15
|
+
if (status === 'added') return <FilePlus size={12} className="text-success" />;
|
|
16
|
+
if (status === 'deleted') return <FileMinus size={12} className="text-danger" />;
|
|
17
|
+
return <FileEdit size={12} className="text-warning" />;
|
|
18
|
+
}
|
|
19
|
+
|
|
14
20
|
export function CodeReview({ agentId: agentIdProp, onBack }) {
|
|
15
|
-
const storeAgentId = useGrooveStore((s) => s.
|
|
21
|
+
const storeAgentId = useGrooveStore((s) => s.workspaceAgentId);
|
|
16
22
|
const agentId = agentIdProp || storeAgentId;
|
|
23
|
+
const agents = useGrooveStore((s) => s.agents);
|
|
17
24
|
const instructAgent = useGrooveStore((s) => s.instructAgent);
|
|
18
|
-
const
|
|
19
|
-
|
|
25
|
+
const setEditorViewMode = useGrooveStore((s) => s.setEditorViewMode);
|
|
26
|
+
|
|
27
|
+
const agent = agents.find((a) => a.id === agentId);
|
|
28
|
+
const agentRunning = agent?.status === 'running' || agent?.status === 'starting';
|
|
20
29
|
|
|
21
30
|
const [files, setFiles] = useState([]);
|
|
22
31
|
const [loading, setLoading] = useState(true);
|
|
23
|
-
const [
|
|
32
|
+
const [expandedFile, setExpandedFile] = useState(null);
|
|
33
|
+
const [fileContents, setFileContents] = useState({});
|
|
34
|
+
const [reverting, setReverting] = useState({});
|
|
24
35
|
const [comments, setComments] = useState({});
|
|
25
|
-
const [statuses, setStatuses] = useState({});
|
|
26
36
|
const [commentingPath, setCommentingPath] = useState(null);
|
|
27
37
|
const [commentText, setCommentText] = useState('');
|
|
28
38
|
|
|
29
|
-
|
|
30
|
-
loadChanges();
|
|
31
|
-
}, []);
|
|
32
|
-
|
|
33
|
-
async function loadChanges() {
|
|
39
|
+
const loadChanges = useCallback(async () => {
|
|
34
40
|
setLoading(true);
|
|
35
41
|
try {
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
additions: f.additions || 0,
|
|
41
|
-
deletions: f.deletions || 0,
|
|
42
|
-
}));
|
|
43
|
-
setFiles(changed);
|
|
42
|
+
const url = agentId ? `/files/git-diff?agentId=${encodeURIComponent(agentId)}` : '/files/git-diff';
|
|
43
|
+
const data = await api.get(url);
|
|
44
|
+
const diffs = (data.diffs || []).filter((d) => !d.path.endsWith('/'));
|
|
45
|
+
setFiles(diffs);
|
|
44
46
|
} catch {
|
|
45
47
|
setFiles([]);
|
|
46
48
|
}
|
|
47
49
|
setLoading(false);
|
|
48
|
-
}
|
|
50
|
+
}, [agentId]);
|
|
51
|
+
|
|
52
|
+
useEffect(() => { loadChanges(); }, [loadChanges]);
|
|
49
53
|
|
|
50
|
-
function
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
async function loadFileContent(filePath) {
|
|
55
|
+
if (fileContents[filePath]) return;
|
|
56
|
+
try {
|
|
57
|
+
const [origRes, currRes] = await Promise.all([
|
|
58
|
+
api.get(`/files/git-show?path=${encodeURIComponent(filePath)}`),
|
|
59
|
+
api.get(`/files/read?path=${encodeURIComponent(filePath)}`).catch(() => null),
|
|
60
|
+
]);
|
|
61
|
+
setFileContents((prev) => ({
|
|
62
|
+
...prev,
|
|
63
|
+
[filePath]: {
|
|
64
|
+
original: origRes.content ?? '',
|
|
65
|
+
modified: currRes?.content ?? '',
|
|
66
|
+
},
|
|
67
|
+
}));
|
|
68
|
+
} catch {
|
|
69
|
+
setFileContents((prev) => ({
|
|
70
|
+
...prev,
|
|
71
|
+
[filePath]: { original: '', modified: '', error: true },
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
54
74
|
}
|
|
55
75
|
|
|
56
|
-
function
|
|
57
|
-
if (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
76
|
+
function toggleExpand(filePath) {
|
|
77
|
+
if (expandedFile === filePath) {
|
|
78
|
+
setExpandedFile(null);
|
|
79
|
+
} else {
|
|
80
|
+
setExpandedFile(filePath);
|
|
81
|
+
loadFileContent(filePath);
|
|
82
|
+
}
|
|
61
83
|
}
|
|
62
84
|
|
|
63
|
-
function
|
|
64
|
-
|
|
85
|
+
async function revertFile(filePath) {
|
|
86
|
+
setReverting((prev) => ({ ...prev, [filePath]: true }));
|
|
87
|
+
try {
|
|
88
|
+
await api.post('/files/revert', { path: filePath });
|
|
89
|
+
setFiles((prev) => prev.filter((f) => f.path !== filePath));
|
|
90
|
+
setFileContents((prev) => { const next = { ...prev }; delete next[filePath]; return next; });
|
|
91
|
+
if (expandedFile === filePath) setExpandedFile(null);
|
|
92
|
+
} catch (err) {
|
|
93
|
+
useGrooveStore.getState().addToast('error', 'Failed to revert', err.message);
|
|
94
|
+
}
|
|
95
|
+
setReverting((prev) => ({ ...prev, [filePath]: false }));
|
|
65
96
|
}
|
|
66
97
|
|
|
67
|
-
function
|
|
68
|
-
|
|
98
|
+
async function revertAll() {
|
|
99
|
+
for (const file of files) {
|
|
100
|
+
await revertFile(file.path);
|
|
101
|
+
}
|
|
69
102
|
}
|
|
70
103
|
|
|
71
|
-
function
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
104
|
+
function handleComment(path) {
|
|
105
|
+
if (!commentText.trim()) return;
|
|
106
|
+
setComments((prev) => ({ ...prev, [path]: commentText.trim() }));
|
|
107
|
+
setCommentText('');
|
|
108
|
+
setCommentingPath(null);
|
|
75
109
|
}
|
|
76
110
|
|
|
77
|
-
async function
|
|
111
|
+
async function handleSendFeedback() {
|
|
78
112
|
if (!agentId) return;
|
|
79
|
-
const
|
|
80
|
-
.filter((f) => comments[f.path]
|
|
81
|
-
.map((f) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
await instructAgent(agentId, `Code review feedback:\n${reviewComments.join('\n')}`);
|
|
87
|
-
}
|
|
88
|
-
if (onBack) onBack(); else setViewMode('code');
|
|
113
|
+
const feedbackLines = files
|
|
114
|
+
.filter((f) => comments[f.path])
|
|
115
|
+
.map((f) => `${f.path}: ${comments[f.path]}`);
|
|
116
|
+
if (feedbackLines.length === 0) return;
|
|
117
|
+
await instructAgent(agentId, `Code review feedback:\n${feedbackLines.join('\n')}`);
|
|
118
|
+
setComments({});
|
|
119
|
+
if (onBack) onBack(); else setEditorViewMode('code');
|
|
89
120
|
}
|
|
90
121
|
|
|
91
|
-
const
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
if (selectedFile) {
|
|
95
|
-
return (
|
|
96
|
-
<div className="flex flex-col h-full">
|
|
97
|
-
<div className="flex items-center gap-2 px-4 py-2 bg-surface-1 border-b border-border flex-shrink-0">
|
|
98
|
-
<button
|
|
99
|
-
onClick={() => setSelectedFile(null)}
|
|
100
|
-
className="p-1 rounded hover:bg-surface-4 text-text-3 hover:text-text-1 cursor-pointer"
|
|
101
|
-
>
|
|
102
|
-
<ChevronLeft size={14} />
|
|
103
|
-
</button>
|
|
104
|
-
<span className="text-xs font-mono text-text-1 truncate">{selectedFile}</span>
|
|
105
|
-
</div>
|
|
106
|
-
<div className="flex-1 min-h-0">
|
|
107
|
-
<DiffViewer filePath={selectedFile} />
|
|
108
|
-
</div>
|
|
109
|
-
</div>
|
|
110
|
-
);
|
|
111
|
-
}
|
|
122
|
+
const totalAdds = files.reduce((s, f) => s + (f.additions || 0), 0);
|
|
123
|
+
const totalDels = files.reduce((s, f) => s + (f.deletions || 0), 0);
|
|
124
|
+
const hasComments = Object.keys(comments).length > 0;
|
|
112
125
|
|
|
113
126
|
return (
|
|
114
127
|
<div className="flex flex-col h-full">
|
|
128
|
+
{/* Header */}
|
|
115
129
|
<div className="flex items-center gap-3 px-4 py-3 bg-surface-1 border-b border-border flex-shrink-0">
|
|
116
|
-
<button onClick={() => onBack ? onBack() :
|
|
130
|
+
<button onClick={() => onBack ? onBack() : setEditorViewMode('code')} className="p-1 rounded hover:bg-surface-4 text-text-3 hover:text-text-1 cursor-pointer" title="Back">
|
|
117
131
|
<ChevronLeft size={16} />
|
|
118
132
|
</button>
|
|
119
133
|
<span className="text-sm font-semibold text-text-0 font-sans flex-1">Review Changes</span>
|
|
120
134
|
<span className="text-xs text-text-3 font-sans">
|
|
121
|
-
{files.length} file{files.length !== 1 ? 's' : ''}
|
|
135
|
+
{files.length} file{files.length !== 1 ? 's' : ''}
|
|
122
136
|
</span>
|
|
123
|
-
{
|
|
124
|
-
{
|
|
137
|
+
{totalAdds > 0 && <span className="text-xs text-success font-sans">+{totalAdds}</span>}
|
|
138
|
+
{totalDels > 0 && <span className="text-xs text-danger font-sans">-{totalDels}</span>}
|
|
125
139
|
</div>
|
|
126
140
|
|
|
141
|
+
{/* File list */}
|
|
127
142
|
<ScrollArea className="flex-1">
|
|
128
143
|
<div className="p-2 space-y-1">
|
|
129
144
|
{loading && (
|
|
130
145
|
<div className="flex items-center justify-center py-12 text-text-4 text-xs font-sans">
|
|
131
|
-
Loading
|
|
146
|
+
Loading changes...
|
|
132
147
|
</div>
|
|
133
148
|
)}
|
|
134
149
|
{!loading && files.length === 0 && (
|
|
135
150
|
<div className="flex items-center justify-center py-12 text-text-4 text-xs font-sans">
|
|
136
|
-
No
|
|
151
|
+
No changes found
|
|
137
152
|
</div>
|
|
138
153
|
)}
|
|
139
154
|
{files.map((file) => (
|
|
140
|
-
<div key={file.path} className="rounded-md border border-border-subtle bg-surface-2">
|
|
155
|
+
<div key={file.path} className="rounded-md border border-border-subtle bg-surface-2 overflow-hidden">
|
|
156
|
+
{/* File row */}
|
|
141
157
|
<div className="flex items-center gap-2 px-3 py-2">
|
|
142
158
|
{statusIcon(file.status)}
|
|
143
159
|
<button
|
|
144
|
-
onClick={() =>
|
|
145
|
-
className="flex-1 min-w-0 text-xs font-mono text-text-1 hover:text-accent
|
|
160
|
+
onClick={() => toggleExpand(file.path)}
|
|
161
|
+
className="flex-1 min-w-0 flex items-center gap-1 text-xs font-mono text-text-1 hover:text-accent text-left cursor-pointer"
|
|
146
162
|
>
|
|
147
|
-
{file.path}
|
|
163
|
+
<ChevronRight size={10} className={cn('text-text-4 transition-transform flex-shrink-0', expandedFile === file.path && 'rotate-90')} />
|
|
164
|
+
<span className="truncate">{file.path}</span>
|
|
148
165
|
</button>
|
|
149
166
|
<div className="flex items-center gap-2 flex-shrink-0 text-2xs font-sans">
|
|
150
167
|
{file.additions > 0 && <span className="text-success">+{file.additions}</span>}
|
|
@@ -152,43 +169,43 @@ export function CodeReview({ agentId: agentIdProp, onBack }) {
|
|
|
152
169
|
</div>
|
|
153
170
|
<div className="flex items-center gap-1 flex-shrink-0">
|
|
154
171
|
<button
|
|
155
|
-
onClick={() =>
|
|
156
|
-
className=
|
|
157
|
-
|
|
158
|
-
statuses[file.path] === 'approved'
|
|
159
|
-
? 'bg-success/15 text-success'
|
|
160
|
-
: 'text-text-4 hover:text-success hover:bg-success/10',
|
|
161
|
-
)}
|
|
162
|
-
title="Approve"
|
|
172
|
+
onClick={() => toggleExpand(file.path)}
|
|
173
|
+
className="p-1 rounded text-text-4 hover:text-accent hover:bg-accent/10 cursor-pointer transition-colors"
|
|
174
|
+
title="View diff"
|
|
163
175
|
>
|
|
164
|
-
<
|
|
176
|
+
<Eye size={13} />
|
|
165
177
|
</button>
|
|
178
|
+
{agentRunning && (
|
|
179
|
+
<button
|
|
180
|
+
onClick={() => setCommentingPath(commentingPath === file.path ? null : file.path)}
|
|
181
|
+
className={cn(
|
|
182
|
+
'p-1 rounded cursor-pointer transition-colors',
|
|
183
|
+
comments[file.path]
|
|
184
|
+
? 'bg-accent/15 text-accent'
|
|
185
|
+
: 'text-text-4 hover:text-accent hover:bg-accent/10',
|
|
186
|
+
)}
|
|
187
|
+
title="Comment"
|
|
188
|
+
>
|
|
189
|
+
<MessageSquare size={13} />
|
|
190
|
+
</button>
|
|
191
|
+
)}
|
|
166
192
|
<button
|
|
167
|
-
onClick={() =>
|
|
193
|
+
onClick={() => revertFile(file.path)}
|
|
194
|
+
disabled={reverting[file.path]}
|
|
168
195
|
className={cn(
|
|
169
196
|
'p-1 rounded cursor-pointer transition-colors',
|
|
170
|
-
|
|
171
|
-
? '
|
|
197
|
+
reverting[file.path]
|
|
198
|
+
? 'text-text-4 opacity-50'
|
|
172
199
|
: 'text-text-4 hover:text-danger hover:bg-danger/10',
|
|
173
200
|
)}
|
|
174
|
-
title="
|
|
175
|
-
>
|
|
176
|
-
<X size={14} />
|
|
177
|
-
</button>
|
|
178
|
-
<button
|
|
179
|
-
onClick={() => setCommentingPath(commentingPath === file.path ? null : file.path)}
|
|
180
|
-
className={cn(
|
|
181
|
-
'p-1 rounded cursor-pointer transition-colors',
|
|
182
|
-
comments[file.path]
|
|
183
|
-
? 'bg-accent/15 text-accent'
|
|
184
|
-
: 'text-text-4 hover:text-accent hover:bg-accent/10',
|
|
185
|
-
)}
|
|
186
|
-
title="Comment"
|
|
201
|
+
title="Revert file"
|
|
187
202
|
>
|
|
188
|
-
<
|
|
203
|
+
<RotateCcw size={13} />
|
|
189
204
|
</button>
|
|
190
205
|
</div>
|
|
191
206
|
</div>
|
|
207
|
+
|
|
208
|
+
{/* Comment input */}
|
|
192
209
|
{comments[file.path] && commentingPath !== file.path && (
|
|
193
210
|
<div className="px-3 pb-2 text-2xs text-text-2 font-sans italic">
|
|
194
211
|
{comments[file.path]}
|
|
@@ -204,31 +221,51 @@ export function CodeReview({ agentId: agentIdProp, onBack }) {
|
|
|
204
221
|
className="flex-1 h-7 px-2 text-xs bg-surface-0 border border-border-subtle rounded text-text-0 font-sans focus:outline-none focus:border-accent"
|
|
205
222
|
autoFocus
|
|
206
223
|
/>
|
|
207
|
-
<button
|
|
208
|
-
onClick={() => handleComment(file.path)}
|
|
209
|
-
className="p-1 text-accent hover:text-accent/80 cursor-pointer"
|
|
210
|
-
>
|
|
224
|
+
<button onClick={() => handleComment(file.path)} className="p-1 text-accent hover:text-accent/80 cursor-pointer">
|
|
211
225
|
<Send size={12} />
|
|
212
226
|
</button>
|
|
213
227
|
</div>
|
|
214
228
|
)}
|
|
229
|
+
|
|
230
|
+
{/* Inline diff */}
|
|
231
|
+
{expandedFile === file.path && (
|
|
232
|
+
<div className="border-t border-border-subtle max-h-[400px] overflow-auto">
|
|
233
|
+
{fileContents[file.path] ? (
|
|
234
|
+
fileContents[file.path].error ? (
|
|
235
|
+
<div className="p-4 text-xs text-text-4 font-sans text-center">Could not load file contents</div>
|
|
236
|
+
) : (
|
|
237
|
+
<DiffViewer
|
|
238
|
+
filePath={file.path}
|
|
239
|
+
originalContent={fileContents[file.path].original}
|
|
240
|
+
modifiedContent={fileContents[file.path].modified}
|
|
241
|
+
/>
|
|
242
|
+
)
|
|
243
|
+
) : (
|
|
244
|
+
<div className="p-4 text-xs text-text-4 font-sans text-center">Loading diff...</div>
|
|
245
|
+
)}
|
|
246
|
+
</div>
|
|
247
|
+
)}
|
|
215
248
|
</div>
|
|
216
249
|
))}
|
|
217
250
|
</div>
|
|
218
251
|
</ScrollArea>
|
|
219
252
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
<Button variant="ghost" size="sm" onClick={handleRequestChanges} className="gap-1.5 text-warning">
|
|
227
|
-
<XCircle size={13} />
|
|
228
|
-
Send Review to Agent
|
|
253
|
+
{/* Footer actions */}
|
|
254
|
+
{files.length > 0 && (
|
|
255
|
+
<div className="flex items-center gap-2 px-4 py-3 border-t border-border bg-surface-1 flex-shrink-0">
|
|
256
|
+
<Button variant="ghost" size="sm" onClick={revertAll} className="gap-1.5 text-danger">
|
|
257
|
+
<RotateCcw size={13} />
|
|
258
|
+
Revert All
|
|
229
259
|
</Button>
|
|
230
|
-
|
|
231
|
-
|
|
260
|
+
<div className="flex-1" />
|
|
261
|
+
{agentRunning && hasComments && (
|
|
262
|
+
<Button variant="ghost" size="sm" onClick={handleSendFeedback} className="gap-1.5 text-accent">
|
|
263
|
+
<Send size={13} />
|
|
264
|
+
Send Feedback
|
|
265
|
+
</Button>
|
|
266
|
+
)}
|
|
267
|
+
</div>
|
|
268
|
+
)}
|
|
232
269
|
</div>
|
|
233
270
|
);
|
|
234
271
|
}
|
|
@@ -6,7 +6,7 @@ import { ScrollArea } from '../ui/scroll-area';
|
|
|
6
6
|
import { api } from '../../lib/api';
|
|
7
7
|
import { Columns2, AlignJustify } from 'lucide-react';
|
|
8
8
|
|
|
9
|
-
function computeDiff(original, modified) {
|
|
9
|
+
export function computeDiff(original, modified) {
|
|
10
10
|
const origLines = (original || '').split('\n');
|
|
11
11
|
const modLines = (modified || '').split('\n');
|
|
12
12
|
const result = [];
|
|
@@ -71,14 +71,14 @@ function buildSideBySide(diffLines) {
|
|
|
71
71
|
|
|
72
72
|
function UnifiedView({ diffLines }) {
|
|
73
73
|
return (
|
|
74
|
-
<div className="font-mono text-xs leading-5">
|
|
74
|
+
<div className="font-mono text-xs leading-5 overflow-x-auto">
|
|
75
75
|
{diffLines.map((line, i) => (
|
|
76
76
|
<div
|
|
77
77
|
key={i}
|
|
78
78
|
className={cn(
|
|
79
79
|
'flex',
|
|
80
|
-
line.type === 'add' && 'bg-success/
|
|
81
|
-
line.type === 'del' && 'bg-danger/
|
|
80
|
+
line.type === 'add' && 'bg-success/15',
|
|
81
|
+
line.type === 'del' && 'bg-danger/15',
|
|
82
82
|
)}
|
|
83
83
|
>
|
|
84
84
|
<span className={cn(
|
|
@@ -100,8 +100,8 @@ function UnifiedView({ diffLines }) {
|
|
|
100
100
|
{line.type === 'add' ? '+' : line.type === 'del' ? '-' : ' '}
|
|
101
101
|
</span>
|
|
102
102
|
<span className={cn(
|
|
103
|
-
'
|
|
104
|
-
line.type === 'add' ? 'text-success
|
|
103
|
+
'whitespace-pre px-2 flex-1',
|
|
104
|
+
line.type === 'add' ? 'text-success' : line.type === 'del' ? 'text-danger' : 'text-text-1',
|
|
105
105
|
)}>
|
|
106
106
|
{line.text}
|
|
107
107
|
</span>
|
|
@@ -113,14 +113,14 @@ function UnifiedView({ diffLines }) {
|
|
|
113
113
|
|
|
114
114
|
function SideBySideView({ pairs }) {
|
|
115
115
|
return (
|
|
116
|
-
<div className="font-mono text-xs leading-5">
|
|
116
|
+
<div className="font-mono text-xs leading-5 overflow-x-auto">
|
|
117
117
|
{pairs.map((pair, i) => (
|
|
118
118
|
<div key={i} className="flex">
|
|
119
119
|
{/* Left (original) */}
|
|
120
120
|
<div className={cn(
|
|
121
121
|
'flex flex-1 min-w-0 border-r border-border-subtle',
|
|
122
|
-
pair.left.type === 'del' && 'bg-danger/
|
|
123
|
-
pair.left.type === 'mod' && 'bg-warning/
|
|
122
|
+
pair.left.type === 'del' && 'bg-danger/15',
|
|
123
|
+
pair.left.type === 'mod' && 'bg-warning/10',
|
|
124
124
|
pair.left.type === 'empty' && 'bg-surface-2/50',
|
|
125
125
|
)}>
|
|
126
126
|
<span className={cn(
|
|
@@ -130,9 +130,9 @@ function SideBySideView({ pairs }) {
|
|
|
130
130
|
{pair.left.num}
|
|
131
131
|
</span>
|
|
132
132
|
<span className={cn(
|
|
133
|
-
'
|
|
134
|
-
pair.left.type === 'del' ? 'text-danger
|
|
135
|
-
pair.left.type === 'mod' ? 'text-warning
|
|
133
|
+
'whitespace-pre px-1',
|
|
134
|
+
pair.left.type === 'del' ? 'text-danger' :
|
|
135
|
+
pair.left.type === 'mod' ? 'text-warning' :
|
|
136
136
|
pair.left.type === 'empty' ? '' : 'text-text-1',
|
|
137
137
|
)}>
|
|
138
138
|
{pair.left.text}
|
|
@@ -141,8 +141,8 @@ function SideBySideView({ pairs }) {
|
|
|
141
141
|
{/* Right (modified) */}
|
|
142
142
|
<div className={cn(
|
|
143
143
|
'flex flex-1 min-w-0',
|
|
144
|
-
pair.right.type === 'add' && 'bg-success/
|
|
145
|
-
pair.right.type === 'mod' && 'bg-success/
|
|
144
|
+
pair.right.type === 'add' && 'bg-success/15',
|
|
145
|
+
pair.right.type === 'mod' && 'bg-success/10',
|
|
146
146
|
pair.right.type === 'empty' && 'bg-surface-2/50',
|
|
147
147
|
)}>
|
|
148
148
|
<span className={cn(
|
|
@@ -152,9 +152,9 @@ function SideBySideView({ pairs }) {
|
|
|
152
152
|
{pair.right.num}
|
|
153
153
|
</span>
|
|
154
154
|
<span className={cn(
|
|
155
|
-
'
|
|
156
|
-
pair.right.type === 'add' ? 'text-success
|
|
157
|
-
pair.right.type === 'mod' ? 'text-success
|
|
155
|
+
'whitespace-pre px-1',
|
|
156
|
+
pair.right.type === 'add' ? 'text-success' :
|
|
157
|
+
pair.right.type === 'mod' ? 'text-success' :
|
|
158
158
|
pair.right.type === 'empty' ? '' : 'text-text-1',
|
|
159
159
|
)}>
|
|
160
160
|
{pair.right.text}
|
|
@@ -166,7 +166,7 @@ function SideBySideView({ pairs }) {
|
|
|
166
166
|
);
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
export function DiffViewer({ filePath, gitDiffData }) {
|
|
169
|
+
export function DiffViewer({ filePath, gitDiffData, originalContent, modifiedContent }) {
|
|
170
170
|
const file = useGrooveStore((s) => s.editorFiles[filePath]);
|
|
171
171
|
const snapshot = useGrooveStore((s) => s.workspaceSnapshots[filePath]);
|
|
172
172
|
const [viewMode, setViewMode] = useState('side-by-side');
|
|
@@ -175,15 +175,15 @@ export function DiffViewer({ filePath, gitDiffData }) {
|
|
|
175
175
|
useEffect(() => {
|
|
176
176
|
if (gitDiffData?.original !== undefined) {
|
|
177
177
|
setGitOriginal(gitDiffData.original);
|
|
178
|
-
} else if (!snapshot && !file?.originalContent) {
|
|
178
|
+
} else if (originalContent === undefined && !snapshot && !file?.originalContent) {
|
|
179
179
|
api.get(`/files/git-diff?path=${encodeURIComponent(filePath)}`).then((data) => {
|
|
180
180
|
if (data?.original !== undefined) setGitOriginal(data.original);
|
|
181
181
|
}).catch(() => {});
|
|
182
182
|
}
|
|
183
|
-
}, [filePath, gitDiffData, snapshot, file?.originalContent]);
|
|
183
|
+
}, [filePath, gitDiffData, snapshot, file?.originalContent, originalContent]);
|
|
184
184
|
|
|
185
|
-
const original = gitOriginal ?? snapshot ?? file?.originalContent ?? '';
|
|
186
|
-
const modified = file?.content
|
|
185
|
+
const original = originalContent ?? gitOriginal ?? snapshot ?? file?.originalContent ?? '';
|
|
186
|
+
const modified = modifiedContent ?? file?.content ?? '';
|
|
187
187
|
|
|
188
188
|
const diffLines = useMemo(() => computeDiff(original, modified), [original, modified]);
|
|
189
189
|
const sidePairs = useMemo(() => buildSideBySide(diffLines), [diffLines]);
|
|
@@ -197,7 +197,7 @@ export function DiffViewer({ filePath, gitDiffData }) {
|
|
|
197
197
|
return { adds, dels };
|
|
198
198
|
}, [diffLines]);
|
|
199
199
|
|
|
200
|
-
if (!
|
|
200
|
+
if (!original && !modified) {
|
|
201
201
|
return (
|
|
202
202
|
<div className="flex items-center justify-center h-full text-text-4 text-xs font-sans">
|
|
203
203
|
No file loaded
|
|
@@ -47,7 +47,7 @@ export function JournalistPanel() {
|
|
|
47
47
|
return (
|
|
48
48
|
<div className="flex flex-col h-full">
|
|
49
49
|
{/* Header */}
|
|
50
|
-
<div className="
|
|
50
|
+
<div className="pl-5 pr-10 py-4 border-b border-border-subtle flex items-center gap-2">
|
|
51
51
|
<Newspaper size={16} className="text-accent" />
|
|
52
52
|
<h3 className="text-sm font-semibold text-text-0 font-sans flex-1">Journalist</h3>
|
|
53
53
|
<Button
|