@grackle-ai/web-components 0.115.2 → 0.116.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/.rush/temp/chunked-rush-logs/web-components._phase_build.chunks.jsonl +6 -6
- package/.rush/temp/chunked-rush-logs/web-components._phase_test.chunks.jsonl +20 -21
- package/.rush/temp/{b32d9c7748f6c2c43df816a4bdd427ae0c7f1e32.tar.log → f238c174d295031bec7f186733732e0fd7e4b9a5.tar.log} +55 -60
- package/.rush/temp/{49e5384757b767ffca6c218faf139f6813911f4a.untar.log → f238c174d295031bec7f186733732e0fd7e4b9a5.untar.log} +2 -2
- package/.rush/temp/{49e5384757b767ffca6c218faf139f6813911f4a.tar.log → f5301e6a84109dcec06242d178df01e555a83456.tar.log} +2 -2
- package/.rush/temp/{b32d9c7748f6c2c43df816a4bdd427ae0c7f1e32.untar.log → f5301e6a84109dcec06242d178df01e555a83456.untar.log} +2 -2
- package/.rush/temp/operation/_phase_build/all.log +6 -6
- package/.rush/temp/operation/_phase_build/log-chunks.jsonl +6 -6
- package/.rush/temp/operation/_phase_build/state.json +1 -1
- package/.rush/temp/operation/_phase_test/all.log +20 -21
- package/.rush/temp/operation/_phase_test/log-chunks.jsonl +20 -21
- package/.rush/temp/operation/_phase_test/state.json +1 -1
- package/.rush/temp/shrinkwrap-deps.json +3 -3
- package/README.md +2 -2
- package/dist/index.css +1 -1
- package/dist/index.js +9055 -9498
- package/package.json +2 -2
- package/rush-logs/web-components._phase_build.cache.log +1 -1
- package/rush-logs/web-components._phase_build.log +6 -6
- package/rush-logs/web-components._phase_test.cache.log +1 -1
- package/rush-logs/web-components._phase_test.log +20 -21
- package/src/components/index.ts +0 -3
- package/src/components/knowledge/KnowledgeDetailPanel.tsx +1 -4
- package/src/components/layout/AppNav.stories.tsx +3 -6
- package/src/components/layout/AppNav.tsx +3 -7
- package/src/components/layout/BottomStatusBar.tsx +4 -6
- package/src/components/lists/index.ts +0 -1
- package/src/components/panels/KeyboardShortcutsPanel.tsx +0 -1
- package/src/components/panels/index.ts +0 -1
- package/src/components/personas/McpToolSelector.stories.tsx +12 -12
- package/src/components/tools/ToolCard.stories.tsx +0 -26
- package/src/components/tools/ToolCard.tsx +0 -3
- package/src/components/tools/ToolSearchCard.stories.tsx +8 -8
- package/src/components/tools/WorkpadCard.stories.tsx +5 -5
- package/src/components/tools/classifyTool.test.ts +0 -1
- package/src/components/tools/classifyTool.ts +2 -7
- package/src/context/GrackleContextTypes.ts +1 -3
- package/src/hooks/types.ts +1 -44
- package/src/index.ts +4 -8
- package/src/mocks/MockGrackleProvider.tsx +0 -75
- package/src/mocks/mockData.ts +8 -99
- package/src/test-utils/storybook-helpers.ts +0 -19
- package/src/utils/breadcrumbs.test.ts +0 -43
- package/src/utils/breadcrumbs.ts +1 -37
- package/src/utils/navigation.ts +1 -20
- package/src/utils/route-config.test.ts +0 -31
- package/temp/build/lint/_eslint-5eVG3S6w.json +30 -54
- package/src/components/lists/FindingsNav.module.scss +0 -126
- package/src/components/lists/FindingsNav.tsx +0 -146
- package/src/components/panels/FindingsPanel.module.scss +0 -94
- package/src/components/panels/FindingsPanel.stories.tsx +0 -109
- package/src/components/panels/FindingsPanel.tsx +0 -76
- package/src/components/tools/FindingCard.stories.tsx +0 -124
- package/src/components/tools/FindingCard.tsx +0 -178
- package/src/utils/findingCategory.ts +0 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grackle-ai/web-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.116.0",
|
|
4
4
|
"description": "Presentational React component library for the Grackle web UI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"sideEffects": [
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"remark-gfm": "^4.0.0",
|
|
47
47
|
"lucide-react": "~0.474.0",
|
|
48
48
|
"react-router": "^7.0.0",
|
|
49
|
-
"@grackle-ai/common": "0.
|
|
49
|
+
"@grackle-ai/common": "0.116.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@rushstack/heft": "1.2.7",
|
|
@@ -7,13 +7,13 @@ Invoking: heft run --only build -- --clean
|
|
|
7
7
|
[build:lint] Using ESLint version 9.39.4
|
|
8
8
|
vite v6.4.2 building for production...
|
|
9
9
|
transforming...
|
|
10
|
-
✓
|
|
10
|
+
✓ 2712 modules transformed.
|
|
11
11
|
rendering chunks...
|
|
12
12
|
computing gzip size...
|
|
13
|
-
dist/index.css
|
|
13
|
+
dist/index.css 155.14 kB │ gzip: 20.34 kB
|
|
14
14
|
dist/McpAppWidget-CSX2W2Vb.js 205.28 kB │ gzip: 47.19 kB
|
|
15
|
-
dist/index.js 1,
|
|
16
|
-
✓ built in
|
|
15
|
+
dist/index.js 1,374.93 kB │ gzip: 352.80 kB
|
|
16
|
+
✓ built in 5.75s
|
|
17
17
|
[build:vite-build] Vite build completed.
|
|
18
|
-
---- build finished (
|
|
19
|
-
-------------------- Finished (
|
|
18
|
+
---- build finished (50.985s) ----
|
|
19
|
+
-------------------- Finished (50.988s) --------------------
|
|
@@ -5,31 +5,30 @@ The provided list of phases does not contain all phase dependencies. You may nee
|
|
|
5
5
|
|
|
6
6
|
RUN v3.2.4 /home/runner/work/grackle/grackle/packages/web-components
|
|
7
7
|
|
|
8
|
-
✓ src/utils/sessionEvents.test.ts (14 tests)
|
|
9
|
-
✓ src/utils/eventContent.test.ts (38 tests)
|
|
10
|
-
✓ src/utils/dashboard.test.ts (4 tests)
|
|
11
|
-
✓ src/utils/
|
|
12
|
-
✓ src/utils/
|
|
13
|
-
✓ src/utils/breadcrumbs.test.ts (
|
|
8
|
+
✓ src/utils/sessionEvents.test.ts (14 tests) 46ms
|
|
9
|
+
✓ src/utils/eventContent.test.ts (38 tests) 129ms
|
|
10
|
+
✓ src/utils/dashboard.test.ts (4 tests) 9ms
|
|
11
|
+
✓ src/utils/streamCoordination.test.ts (10 tests) 20ms
|
|
12
|
+
✓ src/utils/route-config.test.ts (16 tests) 27ms
|
|
13
|
+
✓ src/utils/breadcrumbs.test.ts (15 tests) 15ms
|
|
14
14
|
✓ src/utils/scrollUtils.test.ts (11 tests) 21ms
|
|
15
|
-
✓ src/components/tools/classifyTool.test.ts (6 tests)
|
|
16
|
-
✓ src/utils/assetUrl.test.ts (3 tests) 17ms
|
|
15
|
+
✓ src/components/tools/classifyTool.test.ts (6 tests) 11ms
|
|
17
16
|
✓ src/components/tools/toolCardHelpers.test.ts (10 tests) 25ms
|
|
18
|
-
✓ src/
|
|
19
|
-
✓ src/components/
|
|
20
|
-
✓ src/hooks/useEventSelection.test.ts (13 tests)
|
|
21
|
-
✓ src/
|
|
22
|
-
|
|
23
|
-
✓ src/
|
|
24
|
-
✓ src/components/display/McpAppWidget.test.tsx (3 tests)
|
|
17
|
+
✓ src/utils/assetUrl.test.ts (3 tests) 14ms
|
|
18
|
+
✓ src/components/display/extractText.test.tsx (8 tests) 22ms
|
|
19
|
+
✓ src/hooks/useEventSelection.test.ts (13 tests) 180ms
|
|
20
|
+
✓ src/components/editable/useEditableField.test.tsx (17 tests) 159ms
|
|
21
|
+
✓ src/components/notifications/UpdateBanner.test.tsx (4 tests) 95ms
|
|
22
|
+
✓ src/utils/grackleHostStyleVariables.test.ts (2 tests) 195ms
|
|
23
|
+
✓ src/components/display/McpAppWidget.test.tsx (3 tests) 361ms
|
|
25
24
|
|
|
26
25
|
Test Files 16 passed (16)
|
|
27
|
-
Tests
|
|
28
|
-
Start at
|
|
29
|
-
Duration
|
|
26
|
+
Tests 174 passed (174)
|
|
27
|
+
Start at 23:49:50
|
|
28
|
+
Duration 15.38s (transform 2.97s, setup 0ms, collect 14.70s, tests 1.33s, environment 12.10s, prepare 5.21s)
|
|
30
29
|
|
|
31
30
|
[test:vitest] Vitest completed.
|
|
32
|
-
[test:storybook-test] Starting Storybook static server on port
|
|
31
|
+
[test:storybook-test] Starting Storybook static server on port 45217...
|
|
33
32
|
[test:storybook-test] Storybook server ready. Running interaction tests...
|
|
34
33
|
jest-haste-map: duplicate manual mock found: adapter-manager
|
|
35
34
|
The following files share their name; please delete one of them:
|
|
@@ -122,5 +121,5 @@ jest-haste-map: duplicate manual mock found: utils/network
|
|
|
122
121
|
* <rootDir>/packages/server/src/__mocks__/utils/network.ts
|
|
123
122
|
|
|
124
123
|
[test:storybook-test] Storybook interaction tests completed.
|
|
125
|
-
---- test finished (
|
|
126
|
-
-------------------- Finished (
|
|
124
|
+
---- test finished (74.932s) ----
|
|
125
|
+
-------------------- Finished (74.942s) --------------------
|
package/src/components/index.ts
CHANGED
|
@@ -6,9 +6,6 @@
|
|
|
6
6
|
// Layout components - application shell structure
|
|
7
7
|
export { StatusBar, Sidebar, BottomStatusBar } from "./layout/index.js";
|
|
8
8
|
|
|
9
|
-
// Panel components - main content areas
|
|
10
|
-
export { FindingsPanel } from "./panels/index.js";
|
|
11
|
-
|
|
12
9
|
// List components - sidebar navigation
|
|
13
10
|
export { EnvironmentNav } from "./lists/index.js";
|
|
14
11
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { useMemo, type JSX } from "react";
|
|
8
8
|
import type { GraphNode, NodeDetail } from "../../hooks/types.js";
|
|
9
|
-
import { taskUrl, sessionUrl
|
|
9
|
+
import { taskUrl, sessionUrl } from "../../utils/navigation.js";
|
|
10
10
|
import { useAppNavigate } from "../../utils/navigation.js";
|
|
11
11
|
import styles from "./KnowledgeDetailPanel.module.scss";
|
|
12
12
|
|
|
@@ -40,9 +40,6 @@ export function KnowledgeDetailPanel({
|
|
|
40
40
|
case "session":
|
|
41
41
|
navigate(sessionUrl(node.sourceId));
|
|
42
42
|
break;
|
|
43
|
-
case "finding":
|
|
44
|
-
navigate(findingUrl(node.sourceId));
|
|
45
|
-
break;
|
|
46
43
|
default:
|
|
47
44
|
break;
|
|
48
45
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
2
|
import { expect, userEvent } from "@storybook/test";
|
|
3
|
-
import { Brain, ClipboardList, Home, MessageSquare, Monitor,
|
|
3
|
+
import { Brain, ClipboardList, Home, MessageSquare, Monitor, Settings } from "lucide-react";
|
|
4
4
|
import { AppNav } from "./AppNav.js";
|
|
5
5
|
import { ICON_LG } from "../../utils/iconSize.js";
|
|
6
|
-
import { HOME_URL, CHAT_URL, ENVIRONMENTS_URL, SETTINGS_CREDENTIALS_URL, TASKS_URL,
|
|
6
|
+
import { HOME_URL, CHAT_URL, ENVIRONMENTS_URL, SETTINGS_CREDENTIALS_URL, TASKS_URL, KNOWLEDGE_URL } from "../../utils/navigation.js";
|
|
7
7
|
|
|
8
8
|
const meta: Meta<typeof AppNav> = {
|
|
9
9
|
title: "Grackle/Layout/AppNav",
|
|
@@ -25,7 +25,7 @@ export const AllTabsRendered: Story = {
|
|
|
25
25
|
},
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
/** Core-only tabs: orchestration (Tasks
|
|
28
|
+
/** Core-only tabs: orchestration (Tasks) and knowledge tabs are absent. */
|
|
29
29
|
export const CoreOnlyTabs: Story = {
|
|
30
30
|
args: {
|
|
31
31
|
tabs: [
|
|
@@ -55,13 +55,11 @@ export const AllTabsExplicit: Story = {
|
|
|
55
55
|
{ view: "tasks", label: "Tasks", icon: <ClipboardList size={ICON_LG} />, route: TASKS_URL, testId: "sidebar-tab-tasks" },
|
|
56
56
|
{ view: "environments", label: "Environments", icon: <Monitor size={ICON_LG} />, route: ENVIRONMENTS_URL, testId: "sidebar-tab-environments" },
|
|
57
57
|
{ view: "knowledge", label: "Knowledge", icon: <Brain size={ICON_LG} />, route: KNOWLEDGE_URL, testId: "sidebar-tab-knowledge" },
|
|
58
|
-
{ view: "findings", label: "Findings", icon: <Search size={ICON_LG} />, route: FINDINGS_URL, testId: "sidebar-tab-findings" },
|
|
59
58
|
{ view: "settings", label: "Settings", icon: <Settings size={ICON_LG} />, route: SETTINGS_CREDENTIALS_URL, testId: "sidebar-tab-settings" },
|
|
60
59
|
],
|
|
61
60
|
},
|
|
62
61
|
play: async ({ canvas }) => {
|
|
63
62
|
await expect(canvas.getByRole("tab", { name: /Tasks/ })).toBeInTheDocument();
|
|
64
|
-
await expect(canvas.getByRole("tab", { name: /Findings/ })).toBeInTheDocument();
|
|
65
63
|
await expect(canvas.getByRole("tab", { name: /Knowledge/ })).toBeInTheDocument();
|
|
66
64
|
},
|
|
67
65
|
};
|
|
@@ -82,7 +80,6 @@ export const SettingsPinnedRight: Story = {
|
|
|
82
80
|
{ view: "environments", label: "Environments", icon: <Monitor size={ICON_LG} />, route: ENVIRONMENTS_URL, testId: "sidebar-tab-environments" },
|
|
83
81
|
{ view: "settings", label: "Settings", icon: <Settings size={ICON_LG} />, route: SETTINGS_CREDENTIALS_URL, testId: "sidebar-tab-settings", align: "end" },
|
|
84
82
|
{ view: "tasks", label: "Tasks", icon: <ClipboardList size={ICON_LG} />, route: TASKS_URL, testId: "sidebar-tab-tasks" },
|
|
85
|
-
{ view: "findings", label: "Findings", icon: <Search size={ICON_LG} />, route: FINDINGS_URL, testId: "sidebar-tab-findings" },
|
|
86
83
|
{ view: "knowledge", label: "Knowledge", icon: <Brain size={ICON_LG} />, route: KNOWLEDGE_URL, testId: "sidebar-tab-knowledge" },
|
|
87
84
|
],
|
|
88
85
|
},
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useCallback, useMemo, useRef, type JSX, type KeyboardEvent, type ReactNode } from "react";
|
|
2
2
|
import { useLocation } from "react-router";
|
|
3
|
-
import { Brain, ClipboardList, Home, MessageSquare, Monitor, Network,
|
|
4
|
-
import { CHAT_URL, COORDINATION_URL, ENVIRONMENTS_URL,
|
|
3
|
+
import { Brain, ClipboardList, Home, MessageSquare, Monitor, Network, Settings } from "lucide-react";
|
|
4
|
+
import { CHAT_URL, COORDINATION_URL, ENVIRONMENTS_URL, HOME_URL, KNOWLEDGE_URL, SETTINGS_URL, SETTINGS_CREDENTIALS_URL, TASKS_URL, useAppNavigate } from "../../utils/navigation.js";
|
|
5
5
|
import { ICON_LG } from "../../utils/iconSize.js";
|
|
6
6
|
import { Tooltip } from "../display/Tooltip.js";
|
|
7
7
|
import styles from "./AppNav.module.scss";
|
|
8
8
|
|
|
9
9
|
/** Application view identifiers. */
|
|
10
|
-
export type AppView = "dashboard" | "chat" | "tasks" | "environments" | "knowledge" | "
|
|
10
|
+
export type AppView = "dashboard" | "chat" | "tasks" | "environments" | "knowledge" | "coordination" | "settings";
|
|
11
11
|
|
|
12
12
|
/** Tab definition for the application navigation bar. */
|
|
13
13
|
export interface AppTab {
|
|
@@ -37,7 +37,6 @@ export const TABS: AppTab[] = [
|
|
|
37
37
|
{ view: "tasks", label: "Tasks", icon: <ClipboardList size={ICON_LG} />, route: TASKS_URL, testId: "sidebar-tab-tasks", order: 1 },
|
|
38
38
|
{ view: "environments", label: "Environments", icon: <Monitor size={ICON_LG} />, route: ENVIRONMENTS_URL, testId: "sidebar-tab-environments", order: 2 },
|
|
39
39
|
{ view: "chat", label: "Root", icon: <MessageSquare size={ICON_LG} />, route: CHAT_URL, testId: "sidebar-tab-chat", order: 3 },
|
|
40
|
-
{ view: "findings", label: "Findings", icon: <Search size={ICON_LG} />, route: FINDINGS_URL, testId: "sidebar-tab-findings", order: 4 },
|
|
41
40
|
{ view: "knowledge", label: "Knowledge", icon: <Brain size={ICON_LG} />, route: KNOWLEDGE_URL, testId: "sidebar-tab-knowledge", order: 5 },
|
|
42
41
|
{ view: "coordination", label: "Coordination", icon: <Network size={ICON_LG} />, route: COORDINATION_URL, testId: "sidebar-tab-coordination", order: 6 },
|
|
43
42
|
{ view: "settings", label: "Settings", icon: <Settings size={ICON_LG} />, route: SETTINGS_CREDENTIALS_URL, testId: "sidebar-tab-settings", align: "end" },
|
|
@@ -60,9 +59,6 @@ export function getActiveView(pathname: string): AppView {
|
|
|
60
59
|
if (pathname.startsWith(KNOWLEDGE_URL)) {
|
|
61
60
|
return "knowledge";
|
|
62
61
|
}
|
|
63
|
-
if (pathname.startsWith(FINDINGS_URL)) {
|
|
64
|
-
return "findings";
|
|
65
|
-
}
|
|
66
62
|
if (pathname.startsWith(SETTINGS_URL)) {
|
|
67
63
|
return "settings";
|
|
68
64
|
}
|
|
@@ -30,11 +30,9 @@ export function BottomStatusBar({ sessions, tasks, environments }: BottomStatusB
|
|
|
30
30
|
const sessionMatch = useMatch("/sessions/:sessionId");
|
|
31
31
|
const taskMatch = useMatch("/tasks/:taskId");
|
|
32
32
|
const taskStreamMatch = useMatch("/tasks/:taskId/stream");
|
|
33
|
-
const taskFindingsMatch = useMatch("/tasks/:taskId/findings");
|
|
34
33
|
const taskEditMatch = useMatch("/tasks/:taskId/edit");
|
|
35
34
|
const wsTaskMatch = useMatch("/environments/:environmentId/workspaces/:workspaceId/tasks/:taskId");
|
|
36
35
|
const wsTaskStreamMatch = useMatch("/environments/:environmentId/workspaces/:workspaceId/tasks/:taskId/stream");
|
|
37
|
-
const wsTaskFindingsMatch = useMatch("/environments/:environmentId/workspaces/:workspaceId/tasks/:taskId/findings");
|
|
38
36
|
const wsTaskEditMatch = useMatch("/environments/:environmentId/workspaces/:workspaceId/tasks/:taskId/edit");
|
|
39
37
|
const newChatMatch = useMatch("/sessions/new");
|
|
40
38
|
const workspaceMatch = useMatch("/environments/:environmentId/workspaces/:workspaceId");
|
|
@@ -45,14 +43,14 @@ export function BottomStatusBar({ sessions, tasks, environments }: BottomStatusB
|
|
|
45
43
|
|
|
46
44
|
// Derive current page context
|
|
47
45
|
const sessionId = sessionMatch?.params.sessionId;
|
|
48
|
-
const taskId = taskMatch?.params.taskId ?? taskStreamMatch?.params.taskId
|
|
49
|
-
?? wsTaskMatch?.params.taskId ?? wsTaskStreamMatch?.params.taskId ??
|
|
50
|
-
const wsMatch = wsTaskMatch ?? wsTaskStreamMatch ??
|
|
46
|
+
const taskId = taskMatch?.params.taskId ?? taskStreamMatch?.params.taskId
|
|
47
|
+
?? wsTaskMatch?.params.taskId ?? wsTaskStreamMatch?.params.taskId ?? wsTaskEditMatch?.params.taskId;
|
|
48
|
+
const wsMatch = wsTaskMatch ?? wsTaskStreamMatch ?? wsTaskEditMatch;
|
|
51
49
|
const routeEnvironmentId = wsMatch?.params.environmentId ?? workspaceMatch?.params.environmentId;
|
|
52
50
|
const isEnvironments = location.pathname.startsWith("/environments") && !workspaceMatch && !wsMatch;
|
|
53
51
|
const isChat = !!chatMatch;
|
|
54
52
|
const isNewChat = !!newChatMatch;
|
|
55
|
-
const isWorkspace = !!workspaceMatch && !wsTaskMatch && !wsTaskStreamMatch && !
|
|
53
|
+
const isWorkspace = !!workspaceMatch && !wsTaskMatch && !wsTaskStreamMatch && !wsTaskEditMatch;
|
|
56
54
|
const isNewTask = !!newTaskMatch;
|
|
57
55
|
const isTaskEdit = !!taskEditMatch || !!wsTaskEditMatch;
|
|
58
56
|
const isEmpty = !!emptyMatch && !isNewChat && !isWorkspace && !isNewTask;
|
|
@@ -58,13 +58,13 @@ export const WithPresetWorker: Story = {
|
|
|
58
58
|
|
|
59
59
|
export const CustomSelection: Story = {
|
|
60
60
|
args: {
|
|
61
|
-
selectedTools: ["
|
|
61
|
+
selectedTools: ["task_show", "task_list", "workpad_read"],
|
|
62
62
|
},
|
|
63
63
|
play: async ({ canvasElement }) => {
|
|
64
64
|
const canvas = within(canvasElement);
|
|
65
65
|
// Verify selected tools are checked
|
|
66
|
-
const
|
|
67
|
-
await expect(
|
|
66
|
+
const taskShow = canvas.getByTestId("tool-task_show") as HTMLInputElement;
|
|
67
|
+
await expect(taskShow.checked).toBe(true);
|
|
68
68
|
const taskList = canvas.getByTestId("tool-task_list") as HTMLInputElement;
|
|
69
69
|
await expect(taskList.checked).toBe(true);
|
|
70
70
|
// Verify unselected tool is not checked
|
|
@@ -78,8 +78,8 @@ export const CustomSelection: Story = {
|
|
|
78
78
|
export const ToggleIndividualTool: Story = {
|
|
79
79
|
play: async ({ canvasElement, args }) => {
|
|
80
80
|
const canvas = within(canvasElement);
|
|
81
|
-
await userEvent.click(canvas.getByTestId("tool-
|
|
82
|
-
await expect(args.onChange).toHaveBeenCalledWith(["
|
|
81
|
+
await userEvent.click(canvas.getByTestId("tool-task_show"));
|
|
82
|
+
await expect(args.onChange).toHaveBeenCalledWith(["task_show"]);
|
|
83
83
|
},
|
|
84
84
|
};
|
|
85
85
|
|
|
@@ -87,11 +87,11 @@ export const SearchFilter: Story = {
|
|
|
87
87
|
play: async ({ canvasElement }) => {
|
|
88
88
|
const canvas = within(canvasElement);
|
|
89
89
|
const filterInput = canvas.getByTestId("mcp-tool-filter");
|
|
90
|
-
await userEvent.type(filterInput, "
|
|
91
|
-
//
|
|
92
|
-
await expect(canvas.getByTestId("tool-group-
|
|
93
|
-
await expect(canvas.getByTestId("tool-
|
|
94
|
-
await expect(canvas.getByTestId("tool-
|
|
90
|
+
await userEvent.type(filterInput, "workpad");
|
|
91
|
+
// workpad group should be visible with its tools
|
|
92
|
+
await expect(canvas.getByTestId("tool-group-workpad")).toBeInTheDocument();
|
|
93
|
+
await expect(canvas.getByTestId("tool-workpad_write")).toBeInTheDocument();
|
|
94
|
+
await expect(canvas.getByTestId("tool-workpad_read")).toBeInTheDocument();
|
|
95
95
|
// env group should be hidden (no match)
|
|
96
96
|
await expect(canvas.queryByTestId("tool-group-env")).not.toBeInTheDocument();
|
|
97
97
|
},
|
|
@@ -115,7 +115,7 @@ export const GroupSelectAll: Story = {
|
|
|
115
115
|
export const DisabledState: Story = {
|
|
116
116
|
args: {
|
|
117
117
|
disabled: true,
|
|
118
|
-
selectedTools: ["
|
|
118
|
+
selectedTools: ["task_show"],
|
|
119
119
|
},
|
|
120
120
|
play: async ({ canvasElement }) => {
|
|
121
121
|
const canvas = within(canvasElement);
|
|
@@ -124,6 +124,6 @@ export const DisabledState: Story = {
|
|
|
124
124
|
// Filter input should be disabled
|
|
125
125
|
await expect(canvas.getByTestId("mcp-tool-filter")).toBeDisabled();
|
|
126
126
|
// Tool checkboxes should be disabled
|
|
127
|
-
await expect(canvas.getByTestId("tool-
|
|
127
|
+
await expect(canvas.getByTestId("tool-task_show")).toBeDisabled();
|
|
128
128
|
},
|
|
129
129
|
};
|
|
@@ -49,32 +49,6 @@ export const GenericTool: Story = {
|
|
|
49
49
|
},
|
|
50
50
|
};
|
|
51
51
|
|
|
52
|
-
/** MCP finding tool (Claude Code format) routes to FindingCard. */
|
|
53
|
-
export const McpFinding: Story = {
|
|
54
|
-
name: "MCP finding_post (Claude Code)",
|
|
55
|
-
args: {
|
|
56
|
-
tool: "mcp__grackle__finding_post",
|
|
57
|
-
args: { title: "Test finding", category: "insight" },
|
|
58
|
-
result: JSON.stringify({ id: "f1", title: "Test finding", category: "insight", tags: [] }),
|
|
59
|
-
},
|
|
60
|
-
play: async ({ canvas }) => {
|
|
61
|
-
await expect(canvas.getByTestId("tool-card-finding")).toBeInTheDocument();
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
/** MCP finding tool (Copilot format) routes to FindingCard. */
|
|
66
|
-
export const McpFindingCopilot: Story = {
|
|
67
|
-
name: "MCP finding_post (Copilot)",
|
|
68
|
-
args: {
|
|
69
|
-
tool: "grackle-finding_post",
|
|
70
|
-
args: { title: "Copilot finding", category: "bug" },
|
|
71
|
-
result: JSON.stringify({ id: "f2", title: "Copilot finding", category: "bug", tags: [] }),
|
|
72
|
-
},
|
|
73
|
-
play: async ({ canvas }) => {
|
|
74
|
-
await expect(canvas.getByTestId("tool-card-finding")).toBeInTheDocument();
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
|
|
78
52
|
/** MCP task tool routes to TaskCard. */
|
|
79
53
|
export const McpTask: Story = {
|
|
80
54
|
name: "MCP task_list",
|
|
@@ -7,7 +7,6 @@ import { ShellCard } from "./ShellCard.js";
|
|
|
7
7
|
import { SearchCard } from "./SearchCard.js";
|
|
8
8
|
import { TodoCard } from "./TodoCard.js";
|
|
9
9
|
import { MetadataCard } from "./MetadataCard.js";
|
|
10
|
-
import { FindingCard } from "./FindingCard.js";
|
|
11
10
|
import { TaskCard } from "./TaskCard.js";
|
|
12
11
|
import { WorkpadCard } from "./WorkpadCard.js";
|
|
13
12
|
import { KnowledgeCard } from "./KnowledgeCard.js";
|
|
@@ -40,8 +39,6 @@ export function ToolCard(props: ToolCardProps): JSX.Element {
|
|
|
40
39
|
return <TodoCard {...props} />;
|
|
41
40
|
case "metadata":
|
|
42
41
|
return <MetadataCard {...props} />;
|
|
43
|
-
case "finding":
|
|
44
|
-
return <FindingCard {...props} />;
|
|
45
42
|
case "task":
|
|
46
43
|
return <TaskCard {...props} />;
|
|
47
44
|
case "workpad":
|
|
@@ -13,7 +13,7 @@ export const InProgress: Story = {
|
|
|
13
13
|
name: "ToolSearch - in progress",
|
|
14
14
|
args: {
|
|
15
15
|
tool: "ToolSearch",
|
|
16
|
-
args: { query: "select:
|
|
16
|
+
args: { query: "select:mcp__grackle__task_create,mcp__grackle__workpad_write", max_results: 3 },
|
|
17
17
|
},
|
|
18
18
|
play: async ({ canvas }) => {
|
|
19
19
|
await expect(canvas.getByTestId("tool-card-tool-search")).toBeInTheDocument();
|
|
@@ -25,15 +25,15 @@ export const WithResults: Story = {
|
|
|
25
25
|
name: "ToolSearch - with results",
|
|
26
26
|
args: {
|
|
27
27
|
tool: "ToolSearch",
|
|
28
|
-
args: { query: "select:
|
|
28
|
+
args: { query: "select:mcp__grackle__task_create", max_results: 3 },
|
|
29
29
|
result: [
|
|
30
|
-
"
|
|
31
|
-
"
|
|
30
|
+
"mcp__grackle__task_create:",
|
|
31
|
+
" Create a new task in the workspace.",
|
|
32
32
|
" Parameters:",
|
|
33
|
-
" title (string, required):
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
33
|
+
" title (string, required): Task title",
|
|
34
|
+
" description (string, optional): Task description",
|
|
35
|
+
" parentTaskId (string, optional): Parent task to nest under",
|
|
36
|
+
" canDecompose (boolean, optional): Allow the task to create subtasks",
|
|
37
37
|
"",
|
|
38
38
|
"mcp__grackle__workpad_write:",
|
|
39
39
|
" Write to the task workpad.",
|
|
@@ -37,10 +37,10 @@ export const WriteCompleted: Story = {
|
|
|
37
37
|
taskId: "74f5b716",
|
|
38
38
|
workpad: {
|
|
39
39
|
status: "completed",
|
|
40
|
-
summary: "Tested Grackle MCP tools:
|
|
40
|
+
summary: "Tested Grackle MCP tools: created a task, wrote to workpad, and searched knowledge.",
|
|
41
41
|
extra: {
|
|
42
|
-
tools_tested: ["
|
|
43
|
-
|
|
42
|
+
tools_tested: ["task_create", "workpad_write", "knowledge_search"],
|
|
43
|
+
search_topic: "qdrant catalog",
|
|
44
44
|
},
|
|
45
45
|
},
|
|
46
46
|
}),
|
|
@@ -79,10 +79,10 @@ export const CopilotFormat: Story = {
|
|
|
79
79
|
name: "workpad_write - Copilot tool name",
|
|
80
80
|
args: {
|
|
81
81
|
tool: "grackle-workpad_write",
|
|
82
|
-
args: { status: "in progress", summary: "
|
|
82
|
+
args: { status: "in progress", summary: "Wrote a progress note about Rush worktrees." },
|
|
83
83
|
result: JSON.stringify({
|
|
84
84
|
taskId: "e4366a55",
|
|
85
|
-
workpad: { status: "in progress", summary: "
|
|
85
|
+
workpad: { status: "in progress", summary: "Wrote a progress note about Rush worktrees." },
|
|
86
86
|
}),
|
|
87
87
|
},
|
|
88
88
|
play: async ({ canvas }) => {
|
|
@@ -33,7 +33,6 @@ describe("classifyTool", () => {
|
|
|
33
33
|
|
|
34
34
|
it("classifies Grackle MCP tools", () => {
|
|
35
35
|
expect(classifyTool("mcp__grackle__workpad_write")).toBe("workpad");
|
|
36
|
-
expect(classifyTool("mcp__grackle__finding_post")).toBe("finding");
|
|
37
36
|
expect(classifyTool("mcp__grackle__task_create")).toBe("task");
|
|
38
37
|
});
|
|
39
38
|
|
|
@@ -14,7 +14,6 @@ export type ToolCategory =
|
|
|
14
14
|
| "search"
|
|
15
15
|
| "todo"
|
|
16
16
|
| "metadata"
|
|
17
|
-
| "finding"
|
|
18
17
|
| "task"
|
|
19
18
|
| "workpad"
|
|
20
19
|
| "knowledge"
|
|
@@ -29,8 +28,8 @@ const KNOWN_MCP_SERVERS: Set<string> = new Set(["grackle"]);
|
|
|
29
28
|
/**
|
|
30
29
|
* Extracts the bare tool name from runtime-specific naming conventions.
|
|
31
30
|
*
|
|
32
|
-
* - Claude Code / Codex: `
|
|
33
|
-
* - Copilot: `grackle-
|
|
31
|
+
* - Claude Code / Codex: `mcp__grackle__task_create` -> `task_create`
|
|
32
|
+
* - Copilot: `grackle-task_create` -> `task_create`
|
|
34
33
|
* - Built-in: `Read` -> `read` (unchanged, lowered later)
|
|
35
34
|
*/
|
|
36
35
|
export function extractBareName(toolName: string): string {
|
|
@@ -84,10 +83,6 @@ const TOOL_MAP: Record<string, ToolCategory> = {
|
|
|
84
83
|
// Metadata — Copilot: report_intent
|
|
85
84
|
report_intent: "metadata",
|
|
86
85
|
|
|
87
|
-
// Finding — Grackle MCP
|
|
88
|
-
finding_post: "finding",
|
|
89
|
-
finding_list: "finding",
|
|
90
|
-
|
|
91
86
|
// Task — Grackle MCP
|
|
92
87
|
task_list: "task",
|
|
93
88
|
task_create: "task",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import type {
|
|
10
10
|
UsageStats, UseKnowledgeResult,
|
|
11
11
|
UseEnvironmentsResult, UseSessionsResult, UseWorkspacesResult,
|
|
12
|
-
UseTasksResult,
|
|
12
|
+
UseTasksResult, UseTokensResult,
|
|
13
13
|
UseCredentialsResult, UseCodespacesResult, UseDockerContainersResult, UsePersonasResult,
|
|
14
14
|
UsePluginsResult,
|
|
15
15
|
UseSchedulesResult,
|
|
@@ -30,8 +30,6 @@ export interface UseGrackleSocketResult {
|
|
|
30
30
|
workspaces: Omit<UseWorkspacesResult, "handleEvent" | "onDisconnect">;
|
|
31
31
|
/** Task state and actions. */
|
|
32
32
|
tasks: Omit<UseTasksResult, "handleEvent" | "onDisconnect" | "handleLegacyMessage">;
|
|
33
|
-
/** Finding state and actions. */
|
|
34
|
-
findings: Omit<UseFindingsResult, "handleEvent">;
|
|
35
33
|
/** Token state and actions. */
|
|
36
34
|
tokens: Omit<UseTokensResult, "handleEvent">;
|
|
37
35
|
/** Credential provider state and actions. */
|
package/src/hooks/types.ts
CHANGED
|
@@ -74,7 +74,7 @@ export interface SessionEvent {
|
|
|
74
74
|
raw?: string;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
/** A workspace that groups tasks
|
|
77
|
+
/** A workspace that groups tasks. */
|
|
78
78
|
export interface Workspace {
|
|
79
79
|
id: string;
|
|
80
80
|
name: string;
|
|
@@ -125,19 +125,6 @@ export interface TaskData {
|
|
|
125
125
|
costBudgetMillicents: number;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
/** A finding posted by an agent or user. */
|
|
129
|
-
export interface FindingData {
|
|
130
|
-
id: string;
|
|
131
|
-
workspaceId: string;
|
|
132
|
-
taskId: string;
|
|
133
|
-
sessionId: string;
|
|
134
|
-
category: string;
|
|
135
|
-
title: string;
|
|
136
|
-
content: string;
|
|
137
|
-
tags: string[];
|
|
138
|
-
createdAt: string;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
128
|
/** Metadata about a stored token. */
|
|
142
129
|
export interface TokenInfo {
|
|
143
130
|
name: string;
|
|
@@ -419,36 +406,6 @@ export interface UseTasksResult {
|
|
|
419
406
|
domainHook: DomainHook;
|
|
420
407
|
}
|
|
421
408
|
|
|
422
|
-
/** Values returned by the findings domain hook. */
|
|
423
|
-
export interface UseFindingsResult {
|
|
424
|
-
/** All loaded findings. */
|
|
425
|
-
findings: FindingData[];
|
|
426
|
-
/** The currently selected finding (loaded by ID). */
|
|
427
|
-
selectedFinding: FindingData | undefined;
|
|
428
|
-
/** Whether a single finding is being loaded. */
|
|
429
|
-
findingLoading: boolean;
|
|
430
|
-
/** Whether a findings list fetch is in-flight. */
|
|
431
|
-
findingsLoading: boolean;
|
|
432
|
-
/** Load findings for a given workspace. */
|
|
433
|
-
loadFindings: (workspaceId: string) => Promise<void>;
|
|
434
|
-
/** Load findings across all workspaces. */
|
|
435
|
-
loadAllFindings: () => Promise<void>;
|
|
436
|
-
/** Load a single finding by ID. */
|
|
437
|
-
loadFinding: (findingId: string) => Promise<void>;
|
|
438
|
-
/** Post a new finding to a workspace. */
|
|
439
|
-
postFinding: (
|
|
440
|
-
workspaceId: string,
|
|
441
|
-
title: string,
|
|
442
|
-
content: string,
|
|
443
|
-
category?: string,
|
|
444
|
-
tags?: string[],
|
|
445
|
-
) => Promise<void>;
|
|
446
|
-
/** Handle a domain event from the event bus. Returns `true` if handled. */
|
|
447
|
-
handleEvent: (event: GrackleEvent) => boolean;
|
|
448
|
-
/** Lifecycle hook for connect/disconnect/event routing. */
|
|
449
|
-
domainHook: DomainHook;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
409
|
/** Values returned by the tokens domain hook. */
|
|
453
410
|
export interface UseTokensResult {
|
|
454
411
|
/** All known tokens. */
|
package/src/index.ts
CHANGED
|
@@ -55,7 +55,7 @@ export { StatusBar, AppNav, Sidebar, BottomStatusBar, TABS } from "./components/
|
|
|
55
55
|
export type { AppTab } from "./components/layout/index.js";
|
|
56
56
|
|
|
57
57
|
// Lists
|
|
58
|
-
export { EnvironmentNav
|
|
58
|
+
export { EnvironmentNav } from "./components/lists/index.js";
|
|
59
59
|
export { TaskList } from "./components/lists/TaskList.js";
|
|
60
60
|
export { HighlightedText, buildTaskTree, groupTasksByStatus } from "./components/lists/listHelpers.js";
|
|
61
61
|
|
|
@@ -65,7 +65,7 @@ export type { CalloutVariant } from "./components/notifications/index.js";
|
|
|
65
65
|
export { UpdateBanner } from "./components/notifications/UpdateBanner.js";
|
|
66
66
|
|
|
67
67
|
// Panels
|
|
68
|
-
export {
|
|
68
|
+
export { TokensPanel, AppearancePanel, AboutPanel, TaskEditPanel, TaskActionButtons, TaskOverviewPanel, PluginsPanel, GitHubAccountsPanel } from "./components/panels/index.js";
|
|
69
69
|
export type { PluginsPanelProps, GitHubAccountsPanelProps } from "./components/panels/index.js";
|
|
70
70
|
export type { TaskActionButtonsProps } from "./components/panels/TaskActionButtons.js";
|
|
71
71
|
export type { TaskOverviewPanelProps } from "./components/panels/TaskOverviewPanel.js";
|
|
@@ -126,13 +126,13 @@ export type { UseGrackleSocketResult, GrackleContextType } from "./context/Grack
|
|
|
126
126
|
|
|
127
127
|
export type {
|
|
128
128
|
Environment, Session, UsageStats, SessionEvent,
|
|
129
|
-
Workspace, TaskData,
|
|
129
|
+
Workspace, TaskData, TokenInfo,
|
|
130
130
|
CredentialProviderConfig, Codespace, DockerContainer, PersonaData,
|
|
131
131
|
ScheduleData, ScheduleUpdate, UseSchedulesResult,
|
|
132
132
|
ProvisionStatus, GrackleEvent, WsMessage, SendFunction,
|
|
133
133
|
GraphNode, GraphLink, NodeDetail, UseKnowledgeResult,
|
|
134
134
|
UseEnvironmentsResult, UseSessionsResult, UseWorkspacesResult,
|
|
135
|
-
UseTasksResult,
|
|
135
|
+
UseTasksResult, UseTokensResult,
|
|
136
136
|
UseCredentialsResult, UseCodespacesResult, UseDockerContainersResult, UsePersonasResult,
|
|
137
137
|
UsePluginsResult, PluginData,
|
|
138
138
|
StreamData, StreamSubscriberData, UseStreamsResult,
|
|
@@ -164,7 +164,6 @@ export {
|
|
|
164
164
|
SCHEDULES_URL, NEW_SCHEDULE_URL, scheduleUrl,
|
|
165
165
|
SETTINGS_APPEARANCE_URL, SETTINGS_ABOUT_URL, SETTINGS_SHORTCUTS_URL,
|
|
166
166
|
PAIR_PATH, NEW_WORKSPACE_URL, KNOWLEDGE_URL, HOME_URL,
|
|
167
|
-
FINDINGS_URL, findingsUrl, findingUrl,
|
|
168
167
|
CHAT_URL, COORDINATION_URL, TASKS_URL,
|
|
169
168
|
} from "./utils/navigation.js";
|
|
170
169
|
|
|
@@ -177,8 +176,6 @@ export type { TaskStatusKey, VirtualStatus, DisplayStatus, TaskStatusStyle } fro
|
|
|
177
176
|
|
|
178
177
|
export { formatTokens, formatCost } from "./utils/format.js";
|
|
179
178
|
export { formatRelativeTime, formatCountdown } from "./utils/time.js";
|
|
180
|
-
export { CATEGORY_COLORS, getCategoryColor } from "./utils/findingCategory.js";
|
|
181
|
-
export type { CategoryColor } from "./utils/findingCategory.js";
|
|
182
179
|
|
|
183
180
|
export type { BreadcrumbSegment } from "./utils/breadcrumbs.js";
|
|
184
181
|
export {
|
|
@@ -186,7 +183,6 @@ export {
|
|
|
186
183
|
buildEnvironmentsBreadcrumbs, buildNewEnvironmentBreadcrumbs,
|
|
187
184
|
buildNewChatBreadcrumbs, buildSessionBreadcrumbs,
|
|
188
185
|
buildWorkspaceBreadcrumbs, buildTaskBreadcrumbs, buildNewTaskBreadcrumbs,
|
|
189
|
-
buildFindingsBreadcrumbs, buildFindingBreadcrumbs,
|
|
190
186
|
} from "./utils/breadcrumbs.js";
|
|
191
187
|
|
|
192
188
|
export { groupConsecutiveTextEvents, pairToolEvents } from "./utils/sessionEvents.js";
|