@grackle-ai/web-components 0.118.0 → 0.119.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/{e5461b19665f030d269f07cf8797f2bcfeac1bf7.tar.log → 5029e8eb2a183283a13abb63c8b98671df398046.tar.log} +2 -2
- package/.rush/temp/{54cccf3e758698925ef11c80c60777421e1be435.untar.log → 5029e8eb2a183283a13abb63c8b98671df398046.untar.log} +2 -2
- package/.rush/temp/{54cccf3e758698925ef11c80c60777421e1be435.tar.log → 9e64c83035307e17fee515015bb370270d4cf3c8.tar.log} +14 -11
- package/.rush/temp/{e5461b19665f030d269f07cf8797f2bcfeac1bf7.untar.log → 9e64c83035307e17fee515015bb370270d4cf3c8.untar.log} +2 -2
- package/.rush/temp/chunked-rush-logs/web-components._phase_build.chunks.jsonl +8 -8
- package/.rush/temp/chunked-rush-logs/web-components._phase_test.chunks.jsonl +23 -22
- package/.rush/temp/operation/_phase_build/all.log +8 -8
- package/.rush/temp/operation/_phase_build/log-chunks.jsonl +8 -8
- package/.rush/temp/operation/_phase_build/state.json +1 -1
- package/.rush/temp/operation/_phase_test/all.log +23 -22
- package/.rush/temp/operation/_phase_test/log-chunks.jsonl +23 -22
- package/.rush/temp/operation/_phase_test/state.json +1 -1
- package/.rush/temp/shrinkwrap-deps.json +3 -3
- package/dist/index.css +1 -1
- package/dist/index.js +5801 -5768
- package/package.json +2 -2
- package/rush-logs/web-components._phase_build.cache.log +1 -1
- package/rush-logs/web-components._phase_build.log +8 -8
- package/rush-logs/web-components._phase_test.cache.log +1 -1
- package/rush-logs/web-components._phase_test.log +23 -22
- package/src/components/streams/StreamDetailPanel.stories.tsx +16 -1
- package/src/components/streams/StreamDetailPanel.tsx +10 -7
- package/src/components/streams/StreamTranscript.module.scss +47 -0
- package/src/components/streams/StreamTranscript.stories.tsx +42 -0
- package/src/components/streams/StreamTranscript.tsx +58 -0
- package/src/components/streams/index.ts +2 -0
- package/src/hooks/types.ts +20 -0
- package/src/index.ts +3 -3
- package/src/mocks/MockGrackleProvider.tsx +4 -0
- package/src/mocks/mockData.ts +1 -1
- package/src/mocks/mockStreamsData.ts +10 -1
- package/temp/build/lint/_eslint-5eVG3S6w.json +17 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@grackle-ai/web-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.119.0",
|
|
4
4
|
"description": "Presentational React component library for the Grackle web UI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"sideEffects": [
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"remark-gfm": "^4.0.0",
|
|
48
48
|
"lucide-react": "~0.474.0",
|
|
49
49
|
"react-router": "^7.0.0",
|
|
50
|
-
"@grackle-ai/common": "0.
|
|
50
|
+
"@grackle-ai/common": "0.119.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@rushstack/heft": "1.2.7",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
Build cache hit.
|
|
2
|
-
Cache key:
|
|
2
|
+
Cache key: 9e64c83035307e17fee515015bb370270d4cf3c8
|
|
3
3
|
Clearing cached folders: dist, storybook-static, mcp-app-runtime, .rush/temp/operation/_phase_build
|
|
4
4
|
Successfully restored output from the build cache.
|
|
@@ -7,20 +7,20 @@ 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
|
+
✓ 2714 modules transformed.
|
|
11
11
|
rendering chunks...
|
|
12
12
|
computing gzip size...
|
|
13
|
-
dist/index.css 155.
|
|
13
|
+
dist/index.css 155.86 kB │ gzip: 20.51 kB
|
|
14
14
|
dist/McpAppWidget-CSX2W2Vb.js 205.28 kB │ gzip: 47.19 kB
|
|
15
|
-
dist/index.js 1,
|
|
16
|
-
✓ built in 5.
|
|
15
|
+
dist/index.js 1,377.57 kB │ gzip: 353.56 kB
|
|
16
|
+
✓ built in 5.62s
|
|
17
17
|
vite v6.4.2 building for production...
|
|
18
18
|
transforming...
|
|
19
|
-
✓
|
|
19
|
+
✓ 2872 modules transformed.
|
|
20
20
|
rendering chunks...
|
|
21
21
|
computing gzip size...
|
|
22
22
|
mcp-app-runtime/runtime.js 1,243.84 kB │ gzip: 267.73 kB
|
|
23
|
-
✓ built in 4.
|
|
23
|
+
✓ built in 4.81s
|
|
24
24
|
[build:vite-build] Vite build completed.
|
|
25
|
-
---- build finished (
|
|
26
|
-
-------------------- Finished (
|
|
25
|
+
---- build finished (83.403s) ----
|
|
26
|
+
-------------------- Finished (83.407s) --------------------
|
|
@@ -5,31 +5,32 @@ 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/
|
|
9
|
-
✓ src/utils/
|
|
10
|
-
✓ src/utils/
|
|
11
|
-
✓ src/utils/
|
|
12
|
-
✓ src/utils/
|
|
13
|
-
✓ src/utils/
|
|
14
|
-
✓ src/utils/scrollUtils.test.ts (11 tests)
|
|
15
|
-
✓ src/components/tools/classifyTool.test.ts (6 tests)
|
|
16
|
-
✓ src/utils/assetUrl.test.ts (3 tests)
|
|
17
|
-
✓ src/components/tools/toolCardHelpers.test.ts (10 tests)
|
|
18
|
-
✓ src/components/display/extractText.test.tsx (8 tests)
|
|
19
|
-
✓ src/components/editable/useEditableField.test.tsx (17 tests)
|
|
20
|
-
✓ src/hooks/useEventSelection.test.ts (13 tests)
|
|
21
|
-
✓ src/components/
|
|
22
|
-
✓ src/
|
|
23
|
-
|
|
24
|
-
|
|
8
|
+
✓ src/utils/eventContent.test.ts (38 tests) 61ms
|
|
9
|
+
✓ src/utils/sessionEvents.test.ts (14 tests) 23ms
|
|
10
|
+
✓ src/utils/streamCoordination.test.ts (10 tests) 19ms
|
|
11
|
+
✓ src/utils/dashboard.test.ts (4 tests) 33ms
|
|
12
|
+
✓ src/utils/breadcrumbs.test.ts (15 tests) 59ms
|
|
13
|
+
✓ src/utils/route-config.test.ts (16 tests) 73ms
|
|
14
|
+
✓ src/utils/scrollUtils.test.ts (11 tests) 48ms
|
|
15
|
+
✓ src/components/tools/classifyTool.test.ts (6 tests) 17ms
|
|
16
|
+
✓ src/utils/assetUrl.test.ts (3 tests) 6ms
|
|
17
|
+
✓ src/components/tools/toolCardHelpers.test.ts (10 tests) 18ms
|
|
18
|
+
✓ src/components/display/extractText.test.tsx (8 tests) 11ms
|
|
19
|
+
✓ src/components/editable/useEditableField.test.tsx (17 tests) 202ms
|
|
20
|
+
✓ src/hooks/useEventSelection.test.ts (13 tests) 200ms
|
|
21
|
+
✓ src/components/notifications/UpdateBanner.test.tsx (4 tests) 123ms
|
|
22
|
+
✓ src/utils/grackleHostStyleVariables.test.ts (2 tests) 395ms
|
|
23
|
+
✓ grackleHostStyleVariables > always returns the MCP-standard fallback variables 375ms
|
|
24
|
+
✓ src/components/display/McpAppWidget.test.tsx (3 tests) 371ms
|
|
25
|
+
✓ McpAppWidget > mounts an iframe host for the widget 300ms
|
|
25
26
|
|
|
26
27
|
Test Files 16 passed (16)
|
|
27
28
|
Tests 174 passed (174)
|
|
28
|
-
Start at
|
|
29
|
-
Duration
|
|
29
|
+
Start at 18:20:37
|
|
30
|
+
Duration 16.15s (transform 2.75s, setup 0ms, collect 16.48s, tests 1.66s, environment 13.02s, prepare 5.17s)
|
|
30
31
|
|
|
31
32
|
[test:vitest] Vitest completed.
|
|
32
|
-
[test:storybook-test] Starting Storybook static server on port
|
|
33
|
+
[test:storybook-test] Starting Storybook static server on port 38031...
|
|
33
34
|
[test:storybook-test] Storybook server ready. Running interaction tests...
|
|
34
35
|
jest-haste-map: duplicate manual mock found: adapter-manager
|
|
35
36
|
The following files share their name; please delete one of them:
|
|
@@ -122,5 +123,5 @@ jest-haste-map: duplicate manual mock found: utils/network
|
|
|
122
123
|
* <rootDir>/packages/server/src/__mocks__/utils/network.ts
|
|
123
124
|
|
|
124
125
|
[test:storybook-test] Storybook interaction tests completed.
|
|
125
|
-
---- test finished (
|
|
126
|
-
-------------------- Finished (
|
|
126
|
+
---- test finished (110.698s) ----
|
|
127
|
+
-------------------- Finished (110.709s) --------------------
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
2
|
import { expect, fn } from "@storybook/test";
|
|
3
|
-
import type { StreamData } from "../../hooks/types.js";
|
|
3
|
+
import type { StreamData, StreamMessageData } from "../../hooks/types.js";
|
|
4
4
|
import { withMockGrackleRoute } from "../../test-utils/storybook-helpers.js";
|
|
5
5
|
import { StreamDetailPanel } from "./StreamDetailPanel.js";
|
|
6
6
|
|
|
@@ -125,6 +125,21 @@ export const AllPermissionModes: Story = {
|
|
|
125
125
|
},
|
|
126
126
|
};
|
|
127
127
|
|
|
128
|
+
const sampleMessages: StreamMessageData[] = [
|
|
129
|
+
{ streamId: "stream-abc123", seq: "01A", senderId: "session-aabbccdd-eeff-0011", content: "Proposing JWT with RS256.", timestamp: "2026-05-24T18:00:01.000Z" },
|
|
130
|
+
{ streamId: "stream-abc123", seq: "01B", senderId: "session-11223344-5566-7788", content: "Agreed; rotate refresh tokens on use.", timestamp: "2026-05-24T18:00:07.000Z" },
|
|
131
|
+
];
|
|
132
|
+
|
|
133
|
+
/** Stream with a populated conversation transcript. */
|
|
134
|
+
export const WithTranscript: Story = {
|
|
135
|
+
args: {
|
|
136
|
+
messages: sampleMessages,
|
|
137
|
+
},
|
|
138
|
+
play: async ({ canvas }) => {
|
|
139
|
+
await expect(canvas.getAllByTestId("stream-transcript-message")).toHaveLength(2);
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
|
|
128
143
|
/** Close button calls onClose. */
|
|
129
144
|
export const CloseButton: Story = {
|
|
130
145
|
play: async ({ canvas, args }) => {
|
|
@@ -6,21 +6,26 @@
|
|
|
6
6
|
*
|
|
7
7
|
* Read-only: participants link to their sessions; low-level wiring (fds, full
|
|
8
8
|
* GUIDs, permission/delivery mode) is tucked behind an "Advanced" disclosure.
|
|
9
|
-
*
|
|
9
|
+
* The Conversation section shows the durable room transcript (RFC #1264 Phase 2).
|
|
10
10
|
*
|
|
11
11
|
* @module
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { useEffect, type JSX } from "react";
|
|
15
|
-
import type { StreamData } from "../../hooks/types.js";
|
|
15
|
+
import type { StreamData, StreamMessageData } from "../../hooks/types.js";
|
|
16
16
|
import { useAppNavigate, sessionUrl } from "../../utils/navigation.js";
|
|
17
17
|
import { streamKind, type StreamKind } from "../../utils/streamCoordination.js";
|
|
18
|
+
import { StreamTranscript } from "./StreamTranscript.js";
|
|
18
19
|
import styles from "./StreamDetailPanel.module.scss";
|
|
19
20
|
|
|
20
21
|
/** Props for the StreamDetailPanel component. */
|
|
21
22
|
export interface StreamDetailPanelProps {
|
|
22
23
|
/** The stream to display details for. */
|
|
23
24
|
stream: StreamData;
|
|
25
|
+
/** The stream's transcript messages, oldest first (scrollback + live merged). */
|
|
26
|
+
messages?: StreamMessageData[];
|
|
27
|
+
/** Whether the transcript is currently loading. */
|
|
28
|
+
transcriptLoading?: boolean;
|
|
24
29
|
/** Called when the user requests to close the panel. */
|
|
25
30
|
onClose: () => void;
|
|
26
31
|
}
|
|
@@ -56,7 +61,7 @@ function DeliveryModeBadge({ mode }: { mode: string }): JSX.Element {
|
|
|
56
61
|
* Pull-out right drawer showing stream metadata: overview, participants, and an
|
|
57
62
|
* Advanced disclosure with low-level wiring. Conversation content is V2.
|
|
58
63
|
*/
|
|
59
|
-
export function StreamDetailPanel({ stream, onClose }: StreamDetailPanelProps): JSX.Element {
|
|
64
|
+
export function StreamDetailPanel({ stream, messages, transcriptLoading, onClose }: StreamDetailPanelProps): JSX.Element {
|
|
60
65
|
const navigate = useAppNavigate();
|
|
61
66
|
|
|
62
67
|
// Close on Escape key
|
|
@@ -119,12 +124,10 @@ export function StreamDetailPanel({ stream, onClose }: StreamDetailPanelProps):
|
|
|
119
124
|
)}
|
|
120
125
|
</div>
|
|
121
126
|
|
|
122
|
-
{/* Live conversation
|
|
127
|
+
{/* Live conversation transcript (RFC #1264 Phase 2) */}
|
|
123
128
|
<div className={styles.section}>
|
|
124
129
|
<div className={styles.sectionLabel}>Conversation</div>
|
|
125
|
-
<
|
|
126
|
-
Live conversation view — coming in V2.
|
|
127
|
-
</div>
|
|
130
|
+
<StreamTranscript messages={messages ?? []} loading={transcriptLoading ?? false} />
|
|
128
131
|
</div>
|
|
129
132
|
|
|
130
133
|
{/* Advanced wiring */}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
.transcript {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: 10px;
|
|
5
|
+
max-height: 320px;
|
|
6
|
+
overflow-y: auto;
|
|
7
|
+
padding: 4px 2px;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.message {
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
gap: 2px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.meta {
|
|
17
|
+
display: flex;
|
|
18
|
+
justify-content: space-between;
|
|
19
|
+
align-items: baseline;
|
|
20
|
+
gap: 8px;
|
|
21
|
+
font-size: 11px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.sender {
|
|
25
|
+
font-family: var(--font-mono, monospace);
|
|
26
|
+
color: var(--color-text-secondary, #8b949e);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.time {
|
|
30
|
+
color: var(--color-text-tertiary, #6e7681);
|
|
31
|
+
font-variant-numeric: tabular-nums;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.content {
|
|
35
|
+
white-space: pre-wrap;
|
|
36
|
+
word-break: break-word;
|
|
37
|
+
font-size: 13px;
|
|
38
|
+
line-height: 1.45;
|
|
39
|
+
color: var(--color-text-primary, #e6edf3);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.state {
|
|
43
|
+
padding: 16px 8px;
|
|
44
|
+
font-size: 13px;
|
|
45
|
+
font-style: italic;
|
|
46
|
+
color: var(--color-text-secondary, #8b949e);
|
|
47
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
2
|
+
import { expect } from "@storybook/test";
|
|
3
|
+
import type { StreamMessageData } from "../../hooks/types.js";
|
|
4
|
+
import { StreamTranscript } from "./StreamTranscript.js";
|
|
5
|
+
|
|
6
|
+
const messages: StreamMessageData[] = [
|
|
7
|
+
{ streamId: "s1", seq: "01A", senderId: "session-aabbccdd-eeff", content: "Proposing JWT with RS256.", timestamp: "2026-05-24T18:00:01.000Z" },
|
|
8
|
+
{ streamId: "s1", seq: "01B", senderId: "session-11223344-5566", content: "Agreed; rotate refresh tokens on use.", timestamp: "2026-05-24T18:00:07.000Z" },
|
|
9
|
+
{ streamId: "s1", seq: "01C", senderId: "session-aabbccdd-eeff", content: "Ship it.", timestamp: "2026-05-24T18:00:14.000Z" },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
const meta: Meta<typeof StreamTranscript> = {
|
|
13
|
+
title: "Grackle/Streams/StreamTranscript",
|
|
14
|
+
component: StreamTranscript,
|
|
15
|
+
args: { messages },
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
type Story = StoryObj<typeof StreamTranscript>;
|
|
20
|
+
|
|
21
|
+
/** Populated transcript renders one row per message. */
|
|
22
|
+
export const Populated: Story = {
|
|
23
|
+
play: async ({ canvas }) => {
|
|
24
|
+
await expect(canvas.getAllByTestId("stream-transcript-message")).toHaveLength(3);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** Empty transcript shows the empty state. */
|
|
29
|
+
export const Empty: Story = {
|
|
30
|
+
args: { messages: [] },
|
|
31
|
+
play: async ({ canvas }) => {
|
|
32
|
+
await expect(canvas.getByTestId("stream-transcript-empty")).toBeInTheDocument();
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/** Loading state while scrollback is being fetched. */
|
|
37
|
+
export const Loading: Story = {
|
|
38
|
+
args: { messages: [], loading: true },
|
|
39
|
+
play: async ({ canvas }) => {
|
|
40
|
+
await expect(canvas.getByTestId("stream-transcript-loading")).toBeInTheDocument();
|
|
41
|
+
},
|
|
42
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StreamTranscript — read-only transcript of an IPC stream room (RFC #1264 Phase 2).
|
|
3
|
+
*
|
|
4
|
+
* Pure presentational: renders an ordered (oldest-first) list of stream messages
|
|
5
|
+
* with sender + timestamp. Fed by the durable transcript (scrollback) merged with
|
|
6
|
+
* the live message feed; the owning page supplies the data and loading state.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { type JSX } from "react";
|
|
12
|
+
import type { StreamMessageData } from "../../hooks/types.js";
|
|
13
|
+
import styles from "./StreamTranscript.module.scss";
|
|
14
|
+
|
|
15
|
+
/** Props for the StreamTranscript component. */
|
|
16
|
+
export interface StreamTranscriptProps {
|
|
17
|
+
/** Messages to render, oldest first. */
|
|
18
|
+
messages: StreamMessageData[];
|
|
19
|
+
/** Whether the transcript is currently loading (scrollback fetch in flight). */
|
|
20
|
+
loading?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Format an ISO 8601 timestamp as a short local time. */
|
|
24
|
+
function formatTime(iso: string): string {
|
|
25
|
+
const date = new Date(iso);
|
|
26
|
+
return Number.isNaN(date.getTime()) ? iso : date.toLocaleTimeString();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Read-only, ordered transcript of an IPC stream room's messages. */
|
|
30
|
+
export function StreamTranscript({ messages, loading = false }: StreamTranscriptProps): JSX.Element {
|
|
31
|
+
if (loading) {
|
|
32
|
+
return (
|
|
33
|
+
<div className={styles.state} data-testid="stream-transcript-loading">
|
|
34
|
+
Loading transcript…
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
if (messages.length === 0) {
|
|
39
|
+
return (
|
|
40
|
+
<div className={styles.state} data-testid="stream-transcript-empty">
|
|
41
|
+
No messages yet.
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
return (
|
|
46
|
+
<div className={styles.transcript} data-testid="stream-transcript">
|
|
47
|
+
{messages.map((m) => (
|
|
48
|
+
<div key={m.seq} className={styles.message} data-testid="stream-transcript-message">
|
|
49
|
+
<div className={styles.meta}>
|
|
50
|
+
<span className={styles.sender} title={m.senderId}>{m.senderId.slice(0, 12)}</span>
|
|
51
|
+
<span className={styles.time}>{formatTime(m.timestamp)}</span>
|
|
52
|
+
</div>
|
|
53
|
+
<div className={styles.content}>{m.content}</div>
|
|
54
|
+
</div>
|
|
55
|
+
))}
|
|
56
|
+
</div>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -8,3 +8,5 @@ export { CoordinationList } from "./CoordinationList.js";
|
|
|
8
8
|
export type { CoordinationListProps } from "./CoordinationList.js";
|
|
9
9
|
export { StreamDetailPanel } from "./StreamDetailPanel.js";
|
|
10
10
|
export type { StreamDetailPanelProps } from "./StreamDetailPanel.js";
|
|
11
|
+
export { StreamTranscript } from "./StreamTranscript.js";
|
|
12
|
+
export type { StreamTranscriptProps } from "./StreamTranscript.js";
|
package/src/hooks/types.ts
CHANGED
|
@@ -604,6 +604,20 @@ export interface StreamData {
|
|
|
604
604
|
selfEcho: boolean;
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
+
/** A single message in an IPC stream room transcript (RFC #1264 Phase 2). */
|
|
608
|
+
export interface StreamMessageData {
|
|
609
|
+
/** The stream (room) this message belongs to. */
|
|
610
|
+
streamId: string;
|
|
611
|
+
/** ULID transcript sequence key (monotonic per stream, ascending = chronological). */
|
|
612
|
+
seq: string;
|
|
613
|
+
/** Session id of the sender. */
|
|
614
|
+
senderId: string;
|
|
615
|
+
/** Message content. */
|
|
616
|
+
content: string;
|
|
617
|
+
/** ISO 8601 timestamp. */
|
|
618
|
+
timestamp: string;
|
|
619
|
+
}
|
|
620
|
+
|
|
607
621
|
/** Values returned by the streams domain hook. */
|
|
608
622
|
export interface UseStreamsResult {
|
|
609
623
|
/** All known IPC streams. */
|
|
@@ -619,6 +633,12 @@ export interface UseStreamsResult {
|
|
|
619
633
|
* to surface internal IPC plumbing (lifecycle/pipe/stdin); defaults to false.
|
|
620
634
|
*/
|
|
621
635
|
loadStreams: (includeInternal?: boolean) => Promise<void>;
|
|
636
|
+
/** Transcript buffer keyed by stream id (scrollback + live, deduped by seq, ascending). */
|
|
637
|
+
liveMessages: Record<string, StreamMessageData[]>;
|
|
638
|
+
/** Fetch a stream's durable transcript (scrollback) and merge it into the buffer. */
|
|
639
|
+
loadTranscript: (streamId: string, beforeSeq?: string) => Promise<void>;
|
|
640
|
+
/** Append a live stream message to the per-stream buffer. */
|
|
641
|
+
handleStreamMessage: (message: StreamMessageData) => void;
|
|
622
642
|
/** Handle a domain event from the event bus. Returns `true` if handled. */
|
|
623
643
|
handleEvent: (event: GrackleEvent) => boolean;
|
|
624
644
|
/** Lifecycle hook for connect/disconnect/event routing. */
|
package/src/index.ts
CHANGED
|
@@ -87,8 +87,8 @@ export type { ScheduleManagerProps } from "./components/schedules/ScheduleManage
|
|
|
87
87
|
export { SettingsNav } from "./components/settings/SettingsNav.js";
|
|
88
88
|
|
|
89
89
|
// Streams (Coordination tab)
|
|
90
|
-
export { CoordinationList, StreamDetailPanel } from "./components/streams/index.js";
|
|
91
|
-
export type { CoordinationListProps, StreamDetailPanelProps } from "./components/streams/index.js";
|
|
90
|
+
export { CoordinationList, StreamDetailPanel, StreamTranscript } from "./components/streams/index.js";
|
|
91
|
+
export type { CoordinationListProps, StreamDetailPanelProps, StreamTranscriptProps } from "./components/streams/index.js";
|
|
92
92
|
|
|
93
93
|
// Tools
|
|
94
94
|
export { ToolCard } from "./components/tools/ToolCard.js";
|
|
@@ -135,7 +135,7 @@ export type {
|
|
|
135
135
|
UseTasksResult, UseTokensResult,
|
|
136
136
|
UseCredentialsResult, UseCodespacesResult, UseDockerContainersResult, UsePersonasResult,
|
|
137
137
|
UsePluginsResult, PluginData,
|
|
138
|
-
StreamData, StreamSubscriberData, UseStreamsResult,
|
|
138
|
+
StreamData, StreamSubscriberData, StreamMessageData, UseStreamsResult,
|
|
139
139
|
UseGitHubAccountsResult, GitHubAccountData,
|
|
140
140
|
DomainHook,
|
|
141
141
|
ConnectionStatus,
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
MOCK_ENVIRONMENTS,
|
|
45
45
|
MOCK_SESSIONS,
|
|
46
46
|
MOCK_STREAMS,
|
|
47
|
+
MOCK_STREAM_MESSAGES,
|
|
47
48
|
MOCK_EVENTS,
|
|
48
49
|
MOCK_WORKSPACES,
|
|
49
50
|
MOCK_TASKS,
|
|
@@ -1123,6 +1124,9 @@ export function MockGrackleProvider({ children }: MockGrackleProviderProps): JSX
|
|
|
1123
1124
|
streamsLoadedOnce: true,
|
|
1124
1125
|
streamsLoadError: false,
|
|
1125
1126
|
loadStreams: async (includeInternal = false) => { setStreams(filterMockStreams(includeInternal)); },
|
|
1127
|
+
liveMessages: MOCK_STREAM_MESSAGES,
|
|
1128
|
+
loadTranscript: async () => { /* mock transcripts are static */ },
|
|
1129
|
+
handleStreamMessage: () => { /* no-op in mock */ },
|
|
1126
1130
|
domainHook: NOOP_DOMAIN_HOOK,
|
|
1127
1131
|
},
|
|
1128
1132
|
|
package/src/mocks/mockData.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type {
|
|
|
16
16
|
PersonaData,
|
|
17
17
|
} from "../hooks/types.js";
|
|
18
18
|
export { MOCK_KNOWLEDGE_NODES, MOCK_KNOWLEDGE_LINKS, MOCK_KNOWLEDGE_DETAILS } from "./mockKnowledgeData.js";
|
|
19
|
-
export { MOCK_STREAMS } from "./mockStreamsData.js";
|
|
19
|
+
export { MOCK_STREAMS, MOCK_STREAM_MESSAGES } from "./mockStreamsData.js";
|
|
20
20
|
|
|
21
21
|
// ─── Environments ───────────────────────────────────
|
|
22
22
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type { StreamData } from "../hooks/types.js";
|
|
12
|
+
import type { StreamData, StreamMessageData } from "../hooks/types.js";
|
|
13
13
|
|
|
14
14
|
/** Sample IPC streams: a chatroom + channel attributed to tasks, an unattached
|
|
15
15
|
* stream, and internal plumbing streams. */
|
|
@@ -78,3 +78,12 @@ export const MOCK_STREAMS: StreamData[] = [
|
|
|
78
78
|
],
|
|
79
79
|
},
|
|
80
80
|
];
|
|
81
|
+
|
|
82
|
+
/** Sample transcript messages for the planning room, keyed by stream id (RFC #1264 Phase 2). */
|
|
83
|
+
export const MOCK_STREAM_MESSAGES: Record<string, StreamMessageData[]> = {
|
|
84
|
+
"stream-planning": [
|
|
85
|
+
{ streamId: "stream-planning", seq: "01J0000000000000000000MSG1", senderId: "sess-001", content: "Proposing JWT with RS256 + 15-min access tokens.", timestamp: "2026-05-24T18:00:01.000Z" },
|
|
86
|
+
{ streamId: "stream-planning", seq: "01J0000000000000000000MSG2", senderId: "sess-002", content: "Agreed. Refresh tokens rotate on use; store the jti denylist in Redis.", timestamp: "2026-05-24T18:00:07.000Z" },
|
|
87
|
+
{ streamId: "stream-planning", seq: "01J0000000000000000000MSG3", senderId: "sess-001", content: "Ship it. I'll wire the middleware; you take the refresh endpoint.", timestamp: "2026-05-24T18:00:14.000Z" },
|
|
88
|
+
],
|
|
89
|
+
};
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
],
|
|
8
8
|
[
|
|
9
9
|
"hooks/types.ts",
|
|
10
|
-
"
|
|
10
|
+
"6r0o+OaciGsZexJET91xeVksGXI=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
11
11
|
],
|
|
12
12
|
[
|
|
13
13
|
"components/chat/ChatInput.tsx",
|
|
@@ -405,13 +405,17 @@
|
|
|
405
405
|
"components/streams/CoordinationList.tsx",
|
|
406
406
|
"xDBNKE1Nr/O3BrdHcyQlPea6MtM=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
407
407
|
],
|
|
408
|
+
[
|
|
409
|
+
"components/streams/StreamTranscript.tsx",
|
|
410
|
+
"do8OXELxLObi1qnOSEyGglfwrY8=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
411
|
+
],
|
|
408
412
|
[
|
|
409
413
|
"components/streams/StreamDetailPanel.tsx",
|
|
410
|
-
"
|
|
414
|
+
"aeawtCjddBuXTyEKaxOyJvCZIAA=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
411
415
|
],
|
|
412
416
|
[
|
|
413
417
|
"components/streams/index.ts",
|
|
414
|
-
"
|
|
418
|
+
"0chJAM7tVb+DCTTPCPOs4k2KfD4=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
415
419
|
],
|
|
416
420
|
[
|
|
417
421
|
"utils/boardColumns.ts",
|
|
@@ -455,15 +459,15 @@
|
|
|
455
459
|
],
|
|
456
460
|
[
|
|
457
461
|
"mocks/mockStreamsData.ts",
|
|
458
|
-
"
|
|
462
|
+
"XXQoCU5/w8kXwVBl8S8i/5vMg1Q=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
459
463
|
],
|
|
460
464
|
[
|
|
461
465
|
"mocks/mockData.ts",
|
|
462
|
-
"
|
|
466
|
+
"LHqkwplEmqmBdfMiMvyPWZAaI+Y=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
463
467
|
],
|
|
464
468
|
[
|
|
465
469
|
"mocks/MockGrackleProvider.tsx",
|
|
466
|
-
"
|
|
470
|
+
"5Fo6VDfUkysHIFcc2CV/yWKhFw8=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
467
471
|
],
|
|
468
472
|
[
|
|
469
473
|
"test-utils/storybook-decorators.tsx",
|
|
@@ -475,7 +479,7 @@
|
|
|
475
479
|
],
|
|
476
480
|
[
|
|
477
481
|
"index.ts",
|
|
478
|
-
"
|
|
482
|
+
"0HAGVKwcQlcxpA1aUtgUrMWpu98=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
479
483
|
],
|
|
480
484
|
[
|
|
481
485
|
"components/index.ts",
|
|
@@ -707,7 +711,11 @@
|
|
|
707
711
|
],
|
|
708
712
|
[
|
|
709
713
|
"components/streams/StreamDetailPanel.stories.tsx",
|
|
710
|
-
"
|
|
714
|
+
"j2qugPMk7KA5jov7N6kNpUxenqw=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
715
|
+
],
|
|
716
|
+
[
|
|
717
|
+
"components/streams/StreamTranscript.stories.tsx",
|
|
718
|
+
"/AkYRGxhKte2p1+RLA17HPgJulU=_7W3TvvwZxl0TGST6/dyQa8DKDDc="
|
|
711
719
|
],
|
|
712
720
|
[
|
|
713
721
|
"components/tools/AgentToolCard.stories.tsx",
|
|
@@ -826,5 +834,5 @@
|
|
|
826
834
|
"tcFLEiIFvYYLO/1jT41tcJ4CIX4=_orHdc0vDZqoYfD6TIDl1Za3EAL4="
|
|
827
835
|
]
|
|
828
836
|
],
|
|
829
|
-
"filesHash": "
|
|
837
|
+
"filesHash": "u_c8NEn8Xzoz1UbJZkZoyg"
|
|
830
838
|
}
|