@mcp-b/react-components 0.55.0 → 0.56.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AgentToolRunsContext-GMe_hSnD.d.ts → AgentToolRunsContext-DT50htHj.d.ts} +4 -17
- package/dist/{EmployeeChrome-B605rpVz.d.ts → EmployeeChrome-B7Gt2Hpk.d.ts} +1 -1
- package/dist/{ThinkChatActivity-DENkintt.d.ts → ThinkChatActivity-B6dh3n0-.d.ts} +1 -1
- package/dist/components/agents-sdk/AgentChat.js +10 -14
- package/dist/components/agents-sdk/AgentToolRunsContext.d.ts +1 -1
- package/dist/components/agents-sdk/EmployeeApp.d.ts +1 -1
- package/dist/components/agents-sdk/EmployeeChrome.d.ts +1 -1
- package/dist/components/agents-sdk/EmployeeChrome.js +2 -2
- package/dist/components/agents-sdk/EmployeeSchedules.d.ts +1 -1
- package/dist/components/agents-sdk/EmployeeStartScreen.d.ts +1 -1
- package/dist/components/agents-sdk/ManagerOfficeScreens.d.ts +1 -1
- package/dist/components/agents-sdk/SubagentRunDetails.d.ts +1 -1
- package/dist/components/agents-sdk/SubagentRunIndicator.d.ts +1 -1
- package/dist/components/agents-sdk/SubagentRunList.d.ts +1 -1
- package/dist/components/agents-sdk/SubagentRunPanel.d.ts +3 -14
- package/dist/components/agents-sdk/SubagentRunPanel.js +11 -14
- package/dist/components/agents-sdk/SubagentRunSelector.d.ts +1 -1
- package/dist/components/agents-sdk/ThinkChat.d.ts +2 -9
- package/dist/components/agents-sdk/ThinkChat.js +3 -36
- package/dist/components/agents-sdk/ThinkChatActivity.d.ts +1 -1
- package/dist/components/agents-sdk/ThinkFullApp.d.ts +1 -1
- package/dist/components/agents-sdk/ThinkFullApp.js +1 -4
- package/dist/components/agents-sdk/ThinkThreadPicker.js +10 -7
- package/dist/components/nanites/AgentToolDetail.d.ts +1 -1
- package/dist/styles/agent-chat.css +30 -35
- package/dist/styles/app-icon.css +1 -2
- package/dist/styles/base.css +19 -10
- package/dist/styles/brand-loading.css +14 -0
- package/dist/styles/brand.test.ts +21 -0
- package/dist/styles/browser-replay.css +2 -2
- package/dist/styles/button.css +0 -2
- package/dist/styles/checkbox.css +1 -1
- package/dist/styles/composition-motion.css +13 -3
- package/dist/styles/github-motion-mark.css +2 -2
- package/dist/styles/responsive-sidebar-shell.css +11 -1
- package/dist/styles/search-field.css +1 -1
- package/dist/styles/tabs.css +1 -1
- package/dist/styles/think-routine.css +0 -2
- package/dist/styles/think-thread-picker.css +18 -5
- package/dist/styles/toggle-group.css +2 -2
- package/package.json +6 -6
- package/dist/SessionCompaction-CmTJFpzj.d.ts +0 -89
- package/dist/components/agents-sdk/SessionCompaction.d.ts +0 -2
- package/dist/components/agents-sdk/SessionCompaction.js +0 -140
package/dist/styles/app-icon.css
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
silhouette, so a transparent favicon casts its shape, not an invisible box. */
|
|
4
4
|
.avatar.app-icon {
|
|
5
5
|
--sigvelo-recipe-app-icon-size: var(--sigvelo-spacing-8);
|
|
6
|
-
--sigvelo-recipe-app-icon-radius:
|
|
6
|
+
--sigvelo-recipe-app-icon-radius: var(--sigvelo-radius-md);
|
|
7
7
|
|
|
8
8
|
position: relative;
|
|
9
9
|
display: inline-flex;
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
|
|
29
29
|
.app-icon[data-app-icon-size="sm"] {
|
|
30
30
|
--sigvelo-recipe-app-icon-size: var(--sigvelo-spacing-6);
|
|
31
|
-
--sigvelo-recipe-app-icon-radius: 37.5%;
|
|
32
31
|
}
|
|
33
32
|
|
|
34
33
|
.app-icon[data-app-icon-size="lg"] {
|
package/dist/styles/base.css
CHANGED
|
@@ -27,33 +27,32 @@
|
|
|
27
27
|
* `round` in the block below. audit:css-recipes fails if that list falls out of
|
|
28
28
|
* sync with the stylesheets.
|
|
29
29
|
*/
|
|
30
|
-
:where(*)
|
|
30
|
+
:where(*),
|
|
31
|
+
:where(*)::before,
|
|
32
|
+
:where(*)::after {
|
|
31
33
|
corner-shape: var(--sigvelo-corner-shape);
|
|
32
34
|
}
|
|
33
35
|
|
|
36
|
+
/* Pseudo-elements follow :where(), since they are invalid inside its selector list. */
|
|
34
37
|
/* sigvelo-pill-shapes:start */
|
|
35
38
|
:where(
|
|
36
39
|
.approval__key,
|
|
37
40
|
.avatar[data-shape="circle"],
|
|
38
41
|
.avatar-group__count,
|
|
39
42
|
.browser-run-panel__tab-glyph,
|
|
43
|
+
.browser-replay .replayer-mouse.touch-device,
|
|
40
44
|
.chain-of-thought__search-result,
|
|
41
45
|
.chain-of-thought__step-indicator,
|
|
42
46
|
.codex-model-selector__trigger,
|
|
43
|
-
.codex-model-selector__trigger::before,
|
|
44
47
|
.empty-state__icon,
|
|
45
48
|
.inline-citation__trigger,
|
|
46
49
|
.media-preview-card__play,
|
|
47
50
|
.manager-office__unread-dot,
|
|
48
|
-
.manager-office__employee-nav::-webkit-scrollbar-thumb,
|
|
49
|
-
:where([data-layout="chat"]) .manager-office__employee-link[aria-current="page"]::after,
|
|
50
|
-
.menu__radio-indicator::before,
|
|
51
51
|
.message-scroller__button,
|
|
52
52
|
.plan-summary__trigger,
|
|
53
53
|
.plan__step-indicator,
|
|
54
54
|
.prompt-input__button[data-responsive-label],
|
|
55
55
|
.prompt-input__context-trigger,
|
|
56
|
-
.prompt-input__dictation[data-listening] .prompt-input__dictation-icon::before,
|
|
57
56
|
.prompt-input__permissions-trigger,
|
|
58
57
|
.prompt-input__recording-button,
|
|
59
58
|
.prompt-input__stop,
|
|
@@ -62,24 +61,34 @@
|
|
|
62
61
|
.radio,
|
|
63
62
|
.radio__indicator,
|
|
64
63
|
.scroll-area__thumb,
|
|
64
|
+
.sigvelo-floating-prompt > *,
|
|
65
65
|
.slider__indicator,
|
|
66
66
|
.slider__thumb,
|
|
67
67
|
.slider__track,
|
|
68
68
|
.stepper__indicator,
|
|
69
69
|
.stepper__separator,
|
|
70
70
|
.stepper__trigger,
|
|
71
|
-
.subagent-run__milestone::before,
|
|
72
71
|
.switch,
|
|
73
72
|
.switch__thumb,
|
|
74
|
-
.task__item::before,
|
|
75
73
|
.test-results__test-status,
|
|
76
|
-
.think-full-app__resizer::before,
|
|
77
74
|
.think-routine__routine-status,
|
|
75
|
+
.think-thread-status-dot,
|
|
78
76
|
[data-slot="meter-indicator"],
|
|
79
77
|
[data-slot="meter-track"],
|
|
80
78
|
[data-slot="progress-indicator"],
|
|
81
79
|
[data-slot="progress-track"]
|
|
82
|
-
)
|
|
80
|
+
),
|
|
81
|
+
:where(.browser-replay .replayer-mouse)::after,
|
|
82
|
+
:where(.codex-model-selector__trigger)::before,
|
|
83
|
+
:where(.github-motion-mark)::before,
|
|
84
|
+
:where(.github-motion-mark)::after,
|
|
85
|
+
:where(.manager-office__employee-nav)::-webkit-scrollbar-thumb,
|
|
86
|
+
:where(:where([data-layout="chat"]) .manager-office__employee-link[aria-current="page"])::after,
|
|
87
|
+
:where(.menu__radio-indicator)::before,
|
|
88
|
+
:where(.prompt-input__dictation[data-listening] .prompt-input__dictation-icon)::before,
|
|
89
|
+
:where(.subagent-run__milestone)::before,
|
|
90
|
+
:where(.task__item)::before,
|
|
91
|
+
:where(.think-full-app__resizer)::before {
|
|
83
92
|
--sigvelo-corner-shape: round;
|
|
84
93
|
}
|
|
85
94
|
/* sigvelo-pill-shapes:end */
|
|
@@ -47,6 +47,20 @@
|
|
|
47
47
|
text-align: center;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
/* A brief pending mount should not flash a full-strength logo. Keep the
|
|
51
|
+
region and its announcement present; only the artwork and copy fade in. */
|
|
52
|
+
.brand-loading__mark,
|
|
53
|
+
.brand-loading__label {
|
|
54
|
+
transition: opacity var(--sigvelo-motion-duration-disclosure) var(--sigvelo-motion-ease-enter);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
@starting-style {
|
|
58
|
+
.brand-loading__mark,
|
|
59
|
+
.brand-loading__label {
|
|
60
|
+
opacity: 0;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
50
64
|
@media (prefers-reduced-motion: reduce), (forced-colors: active) {
|
|
51
65
|
.brand-loading__mark::after {
|
|
52
66
|
display: none;
|
|
@@ -156,3 +156,24 @@ test("OS-following mode uses the same Sigvelo palette", () => {
|
|
|
156
156
|
matchMedia("(prefers-color-scheme: dark)").matches ? "rgb(23, 23, 22)" : "rgb(247, 247, 244)",
|
|
157
157
|
);
|
|
158
158
|
});
|
|
159
|
+
|
|
160
|
+
test("shared Squircle corners preserve true circular pseudo-elements and button variant shape", () => {
|
|
161
|
+
root.removeAttribute("data-preset");
|
|
162
|
+
root.removeAttribute("data-style");
|
|
163
|
+
const primary = document.createElement("button");
|
|
164
|
+
primary.className = "button button--normal button--primary";
|
|
165
|
+
const destructive = document.createElement("button");
|
|
166
|
+
destructive.className = "button button--normal button--destructive";
|
|
167
|
+
const mark = document.createElement("span");
|
|
168
|
+
mark.className = "github-motion-mark";
|
|
169
|
+
document.body.append(primary, destructive, mark);
|
|
170
|
+
expect(getComputedStyle(destructive).borderRadius).toBe(getComputedStyle(primary).borderRadius);
|
|
171
|
+
if (CSS.supports("corner-shape", "superellipse(1.5)")) {
|
|
172
|
+
expect(getComputedStyle(primary).getPropertyValue("corner-shape")).toBe("superellipse(1.5)");
|
|
173
|
+
expect(getComputedStyle(primary, "::after").getPropertyValue("corner-shape")).toBe(
|
|
174
|
+
"superellipse(1.5)",
|
|
175
|
+
);
|
|
176
|
+
expect(getComputedStyle(mark, "::before").getPropertyValue("corner-shape")).toBe("round");
|
|
177
|
+
expect(getComputedStyle(mark, "::after").getPropertyValue("corner-shape")).toBe("round");
|
|
178
|
+
}
|
|
179
|
+
});
|
|
@@ -96,7 +96,7 @@
|
|
|
96
96
|
width: 20px;
|
|
97
97
|
height: 20px;
|
|
98
98
|
background: var(--sigvelo-color-focus);
|
|
99
|
-
border-radius:
|
|
99
|
+
border-radius: var(--sigvelo-radius-circle);
|
|
100
100
|
transform: translate(-50%, -50%);
|
|
101
101
|
opacity: 0.3;
|
|
102
102
|
}
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
border-color: transparent;
|
|
115
115
|
border-style: solid;
|
|
116
116
|
border-width: 4px;
|
|
117
|
-
border-radius:
|
|
117
|
+
border-radius: var(--sigvelo-radius-circle);
|
|
118
118
|
transition:
|
|
119
119
|
left 0s linear,
|
|
120
120
|
top 0s linear,
|
package/dist/styles/button.css
CHANGED
package/dist/styles/checkbox.css
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
flex-shrink: 0;
|
|
10
10
|
border: var(--sigvelo-border-style) var(--sigvelo-border-width)
|
|
11
11
|
var(--sigvelo-color-neutral-border-muted);
|
|
12
|
-
border-radius: calc(var(--sigvelo-radius-md) -
|
|
12
|
+
border-radius: calc(var(--sigvelo-radius-md) - var(--sigvelo-spacing-1));
|
|
13
13
|
background-color: var(--sigvelo-color-canvas);
|
|
14
14
|
outline: none;
|
|
15
15
|
cursor: pointer;
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
/*
|
|
53
|
+
/* Snapshot ownership stays with the caller: Router for routes, React for local Suspense demos. */
|
|
54
54
|
::view-transition {
|
|
55
55
|
pointer-events: none;
|
|
56
56
|
}
|
|
@@ -60,12 +60,22 @@
|
|
|
60
60
|
animation-timing-function: var(--sigvelo-motion-ease-change);
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
/* A single Router-owned crossfade. Streaming and refetches never start this type. */
|
|
64
|
+
:root:active-view-transition-type(sigvelo-navigation)::view-transition-group(root) {
|
|
65
|
+
animation-duration: var(--sigvelo-motion-duration-disclosure);
|
|
66
|
+
animation-timing-function: var(--sigvelo-motion-ease-change);
|
|
67
|
+
}
|
|
68
|
+
|
|
63
69
|
@media (prefers-reduced-motion: reduce) {
|
|
64
|
-
::view-transition-group(
|
|
70
|
+
::view-transition-group(*),
|
|
71
|
+
::view-transition-old(*),
|
|
72
|
+
::view-transition-new(*) {
|
|
65
73
|
animation: none !important;
|
|
66
74
|
}
|
|
67
75
|
}
|
|
68
76
|
|
|
69
|
-
:root[data-motion="reduce"]::view-transition-group(
|
|
77
|
+
:root[data-motion="reduce"]::view-transition-group(*),
|
|
78
|
+
:root[data-motion="reduce"]::view-transition-old(*),
|
|
79
|
+
:root[data-motion="reduce"]::view-transition-new(*) {
|
|
70
80
|
animation: none !important;
|
|
71
81
|
}
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
.github-motion-mark::before {
|
|
27
27
|
inset: -0.22em;
|
|
28
28
|
border: var(--sigvelo-border-style) var(--sigvelo-border-width) currentColor;
|
|
29
|
-
border-radius:
|
|
29
|
+
border-radius: var(--sigvelo-radius-circle);
|
|
30
30
|
opacity: 0.24;
|
|
31
31
|
transform-origin: 50% 50%;
|
|
32
32
|
animation: github-motion-mark-ring 2.6s ease-out infinite;
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
.github-motion-mark::after {
|
|
36
36
|
inline-size: 0.24em;
|
|
37
37
|
block-size: 0.24em;
|
|
38
|
-
border-radius:
|
|
38
|
+
border-radius: var(--sigvelo-radius-circle);
|
|
39
39
|
background: currentColor;
|
|
40
40
|
opacity: 0.55;
|
|
41
41
|
transform: translate(0.48em, -0.46em);
|
|
@@ -272,6 +272,16 @@
|
|
|
272
272
|
display: contents;
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
+
/* Rich title triggers need the space left by the actual controls, rather
|
|
276
|
+
than the plain title's 45vw cap, to keep activity counts and a readable name. */
|
|
277
|
+
.app-top-bar[data-compact-leading="trigger"] {
|
|
278
|
+
grid-template-columns: auto var(--sigvelo-layout-track-fill) auto;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
.app-top-bar[data-compact-leading="trigger"] .app-top-bar__title {
|
|
282
|
+
max-inline-size: 100%;
|
|
283
|
+
}
|
|
284
|
+
|
|
275
285
|
.responsive-sidebar-shell__title-trigger {
|
|
276
286
|
inline-size: auto;
|
|
277
287
|
max-inline-size: 100%;
|
|
@@ -290,7 +300,7 @@
|
|
|
290
300
|
box-shadow: var(--sigvelo-recipe-focus-shadow-inset);
|
|
291
301
|
}
|
|
292
302
|
|
|
293
|
-
.responsive-sidebar-shell__title-trigger span {
|
|
303
|
+
.responsive-sidebar-shell__title-trigger > span {
|
|
294
304
|
min-inline-size: 0;
|
|
295
305
|
overflow: hidden;
|
|
296
306
|
text-overflow: ellipsis;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
--sigvelo-recipe-control-font-size: var(--sigvelo-density-compact-control-font-size);
|
|
5
5
|
--sigvelo-recipe-control-line-height: var(--sigvelo-density-compact-control-line-height);
|
|
6
6
|
--sigvelo-recipe-control-icon-size: var(--sigvelo-density-compact-control-icon-size);
|
|
7
|
-
--sigvelo-recipe-control-radius: var(--sigvelo-radius-
|
|
7
|
+
--sigvelo-recipe-control-radius: var(--sigvelo-radius-xl);
|
|
8
8
|
--sigvelo-recipe-focus-shadow: var(--sigvelo-recipe-focus-shadow-inset);
|
|
9
9
|
--sigvelo-focus-offset: -2px;
|
|
10
10
|
}
|
package/dist/styles/tabs.css
CHANGED
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
.think-thread-status-indicators {
|
|
46
|
+
flex: 0 0 auto;
|
|
46
47
|
min-inline-size: 0;
|
|
47
48
|
display: inline-flex;
|
|
48
49
|
align-items: center;
|
|
@@ -66,6 +67,18 @@
|
|
|
66
67
|
block-size: var(--sigvelo-density-compact-control-icon-size);
|
|
67
68
|
}
|
|
68
69
|
|
|
70
|
+
.think-thread-status-dot {
|
|
71
|
+
flex: none;
|
|
72
|
+
inline-size: var(--sigvelo-spacing-1-5);
|
|
73
|
+
block-size: var(--sigvelo-spacing-1-5);
|
|
74
|
+
border-radius: var(--sigvelo-radius-full);
|
|
75
|
+
background: currentColor;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.think-thread-status-indicators__item .think-thread-status-dot {
|
|
79
|
+
margin-inline: var(--sigvelo-spacing-1);
|
|
80
|
+
}
|
|
81
|
+
|
|
69
82
|
.think-thread-status-indicators__item[data-status="running"] {
|
|
70
83
|
color: var(--sigvelo-color-primary-text);
|
|
71
84
|
}
|
|
@@ -260,11 +273,6 @@
|
|
|
260
273
|
color: var(--sigvelo-color-primary-text);
|
|
261
274
|
}
|
|
262
275
|
|
|
263
|
-
/* The six statuses this rule used to list were `isThreadBusy` written out a
|
|
264
|
-
second time, and those are exactly the ones that render SpinnerIcon, which
|
|
265
|
-
spins itself. A DotIcon never needed the rule and would have started turning
|
|
266
|
-
the moment the two lists disagreed. */
|
|
267
|
-
|
|
268
276
|
.think-thread-picker__thread[data-thread-status="error"] .think-thread-picker__thread-status {
|
|
269
277
|
color: var(--sigvelo-color-danger-text);
|
|
270
278
|
}
|
|
@@ -343,6 +351,11 @@
|
|
|
343
351
|
}
|
|
344
352
|
|
|
345
353
|
@media (forced-colors: active) {
|
|
354
|
+
.think-thread-status-dot {
|
|
355
|
+
forced-color-adjust: none;
|
|
356
|
+
background: CanvasText;
|
|
357
|
+
}
|
|
358
|
+
|
|
346
359
|
.think-thread-picker {
|
|
347
360
|
border-inline-end: var(--sigvelo-border-style) var(--sigvelo-border-width) canvastext;
|
|
348
361
|
background: canvas;
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
.toggle-group__item {
|
|
20
20
|
color: var(--sigvelo-color-text-muted);
|
|
21
21
|
border: none;
|
|
22
|
-
border-radius: calc(var(--sigvelo-radius-md) -
|
|
22
|
+
border-radius: calc(var(--sigvelo-radius-md) - var(--sigvelo-spacing-0-5));
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
.toggle-group__item:hover:not([data-disabled]) {
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
inset-block: var(--sigvelo-spacing-1);
|
|
66
66
|
inline-size: var(--toggle-group-thumb-size, 0);
|
|
67
67
|
translate: var(--toggle-group-thumb-start, 0) 0;
|
|
68
|
-
border-radius: calc(var(--sigvelo-radius-md) -
|
|
68
|
+
border-radius: calc(var(--sigvelo-radius-md) - var(--sigvelo-spacing-0-5));
|
|
69
69
|
background-color: var(--sigvelo-color-canvas);
|
|
70
70
|
box-shadow: var(--sigvelo-elevation-raised);
|
|
71
71
|
transition:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mcp-b/react-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.56.1",
|
|
4
4
|
"description": "MCP-B React components built on Base UI and shared design tokens, including Cloudflare Think chat primitives.",
|
|
5
5
|
"homepage": "https://design-system.sigvelo.com",
|
|
6
6
|
"bugs": {
|
|
@@ -54,13 +54,13 @@
|
|
|
54
54
|
"streamdown": "^2.5.0",
|
|
55
55
|
"unist-util-visit": "^5.1.0",
|
|
56
56
|
"yet-another-react-lightbox": "^3.32.2",
|
|
57
|
-
"@mcp-b/design-tokens": "0.
|
|
57
|
+
"@mcp-b/design-tokens": "0.56.1"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@ai-sdk/react": "^3.0.249",
|
|
61
|
-
"@cloudflare/codemode": "
|
|
62
|
-
"@cloudflare/shell": "
|
|
63
|
-
"@cloudflare/think": "
|
|
61
|
+
"@cloudflare/codemode": "https://github.com/WebMCP-org/do-runtime/releases/download/rook-sdk-155b267477ca/cloudflare-codemode-0.5.2.tgz",
|
|
62
|
+
"@cloudflare/shell": "https://github.com/WebMCP-org/do-runtime/releases/download/rook-sdk-155b267477ca/cloudflare-shell-0.4.3.tgz",
|
|
63
|
+
"@cloudflare/think": "https://github.com/WebMCP-org/do-runtime/releases/download/rook-sdk-155b267477ca/cloudflare-think-0.18.0.tgz",
|
|
64
64
|
"@cloudflare/workers-types": "^5.20260811.1",
|
|
65
65
|
"@storybook/addon-a11y": "^10.5.7",
|
|
66
66
|
"@storybook/addon-docs": "^10.5.7",
|
|
@@ -79,7 +79,7 @@
|
|
|
79
79
|
"@vitest/browser-playwright": "^4.1.10",
|
|
80
80
|
"@vitest/coverage-v8": "^4.1.10",
|
|
81
81
|
"@vitest/mocker": "^4.1.10",
|
|
82
|
-
"agents": "
|
|
82
|
+
"agents": "https://github.com/WebMCP-org/do-runtime/releases/download/rook-sdk-155b267477ca/agents-0.23.0.tgz",
|
|
83
83
|
"ai": "^6.0.247",
|
|
84
84
|
"cloudflare": "^7.0.0",
|
|
85
85
|
"oversight-lint": "0.7.1",
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import { ChatStatus, UIMessage } from "ai";
|
|
2
|
-
|
|
3
|
-
//#region src/components/agents-sdk/SessionCompaction.d.ts
|
|
4
|
-
type SessionStatusPhase = "idle" | "compacting";
|
|
5
|
-
interface SessionStatusFrame {
|
|
6
|
-
phase: SessionStatusPhase;
|
|
7
|
-
/** Present on the idle frame that follows a successful compaction. */
|
|
8
|
-
compacted: boolean;
|
|
9
|
-
/**
|
|
10
|
-
* Session's own estimate for the history this frame describes, or null when
|
|
11
|
-
* the frame omits it or carries a non-finite value. Not provider-reported
|
|
12
|
-
* usage — never render it as an exact token count, and never feed it to the
|
|
13
|
-
* `Context` ring, which reads `metadata.usage`.
|
|
14
|
-
*/
|
|
15
|
-
tokenEstimate: number | null;
|
|
16
|
-
/**
|
|
17
|
-
* The same estimate taken before the compaction this frame reports, from its
|
|
18
|
-
* `compacted` payload. Null on every other frame. Both numbers come from one
|
|
19
|
-
* estimator over one history, so their difference is a meaningful size even
|
|
20
|
-
* though neither is exact.
|
|
21
|
-
*/
|
|
22
|
-
tokensBefore: number | null;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Parse a raw websocket payload as a `cf_agent_session` status frame.
|
|
26
|
-
* Returns null for every other frame on the connection.
|
|
27
|
-
*/
|
|
28
|
-
declare function parseSessionStatusFrame(data: unknown): SessionStatusFrame | null;
|
|
29
|
-
/**
|
|
30
|
-
* Parse a raw websocket payload as a `cf_agent_session_error` frame,
|
|
31
|
-
* returning its error text. Null for every other frame on the connection.
|
|
32
|
-
*/
|
|
33
|
-
declare function parseSessionErrorFrame(data: unknown): string | null;
|
|
34
|
-
/** The message-frame surface of a `useAgent` connection. */
|
|
35
|
-
interface SessionFrameSource {
|
|
36
|
-
addEventListener(type: "message", listener: (event: MessageEvent) => void): void;
|
|
37
|
-
removeEventListener(type: "message", listener: (event: MessageEvent) => void): void;
|
|
38
|
-
}
|
|
39
|
-
interface UseSessionCompactionOptions<MessageT extends UIMessage> {
|
|
40
|
-
/** The conversation agent's `useAgent` connection. */
|
|
41
|
-
agent: SessionFrameSource;
|
|
42
|
-
/** The conversation's `useAgentChat` value (status + local view setter). */
|
|
43
|
-
chat: {
|
|
44
|
-
status: ChatStatus;
|
|
45
|
-
setMessages: (messages: MessageT[]) => void;
|
|
46
|
-
};
|
|
47
|
-
/** Server read used to reload the transcript after a compaction lands. */
|
|
48
|
-
getMessages: () => Promise<MessageT[]>;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* How much a landed compaction shortened the history, per Session's own
|
|
52
|
-
* estimator. A UI may show the difference as an approximate size; it must not
|
|
53
|
-
* present either number as exact usage.
|
|
54
|
-
*/
|
|
55
|
-
interface SessionCompactionSize {
|
|
56
|
-
tokensBefore: number;
|
|
57
|
-
tokensAfter: number;
|
|
58
|
-
}
|
|
59
|
-
interface UseSessionCompactionResult {
|
|
60
|
-
compacting: boolean;
|
|
61
|
-
/**
|
|
62
|
-
* Size of the compaction that landed most recently on this connection, or
|
|
63
|
-
* null when none has landed or the frames carried no usable estimates. A new
|
|
64
|
-
* object per compaction, so a consumer can dismiss one acknowledgement by
|
|
65
|
-
* identity and still show the next. Cleared when the next compaction starts.
|
|
66
|
-
*/
|
|
67
|
-
lastCompaction: SessionCompactionSize | null;
|
|
68
|
-
/**
|
|
69
|
-
* Set when the post-compaction transcript reload rejected — the local view
|
|
70
|
-
* is stale relative to the server until a retry succeeds. Surface it
|
|
71
|
-
* ("Transcript may be out of date"); the hook retries on the next status
|
|
72
|
-
* transition to `"ready"`.
|
|
73
|
-
*/
|
|
74
|
-
reloadError: unknown;
|
|
75
|
-
/**
|
|
76
|
-
* Error text from the last `cf_agent_session_error` frame — the only signal
|
|
77
|
-
* a user who ran /compact gets when the server-side compaction itself fails
|
|
78
|
-
* (the phase just flips back to idle with no `compacted` payload). Cleared
|
|
79
|
-
* when the next compaction starts.
|
|
80
|
-
*/
|
|
81
|
-
sessionError: string | null;
|
|
82
|
-
}
|
|
83
|
-
declare function useSessionCompaction<MessageT extends UIMessage>({
|
|
84
|
-
agent,
|
|
85
|
-
chat,
|
|
86
|
-
getMessages
|
|
87
|
-
}: UseSessionCompactionOptions<MessageT>): UseSessionCompactionResult;
|
|
88
|
-
//#endregion
|
|
89
|
-
export { UseSessionCompactionOptions as a, parseSessionStatusFrame as c, SessionStatusPhase as i, useSessionCompaction as l, SessionFrameSource as n, UseSessionCompactionResult as o, SessionStatusFrame as r, parseSessionErrorFrame as s, SessionCompactionSize as t };
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import { a as UseSessionCompactionOptions, c as parseSessionStatusFrame, i as SessionStatusPhase, l as useSessionCompaction, n as SessionFrameSource, o as UseSessionCompactionResult, r as SessionStatusFrame, s as parseSessionErrorFrame, t as SessionCompactionSize } from "../../SessionCompaction-CmTJFpzj.js";
|
|
2
|
-
export { SessionCompactionSize, SessionFrameSource, SessionStatusFrame, SessionStatusPhase, UseSessionCompactionOptions, UseSessionCompactionResult, parseSessionErrorFrame, parseSessionStatusFrame, useSessionCompaction };
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
//#region src/components/agents-sdk/SessionCompaction.ts
|
|
3
|
-
/**
|
|
4
|
-
* Client-side session-compaction plumbing for Think conversations.
|
|
5
|
-
*
|
|
6
|
-
* The Agents Session broadcasts `cf_agent_session` status frames to every
|
|
7
|
-
* connected client: `phase` flips to `"compacting"` while a compaction runs
|
|
8
|
-
* and back to `"idle"` when it settles, with a `compacted` payload on the
|
|
9
|
-
* idle frame when an overlay was actually written. Think refreshes only its
|
|
10
|
-
* server-side message cache after a compaction (`_syncMessages()` does not
|
|
11
|
-
* push to clients), so a connected transcript keeps showing the uncompacted
|
|
12
|
-
* history until its next `getMessages()`. `useSessionCompaction` closes that
|
|
13
|
-
* gap: it tracks the live phase for a "Compacting context…" affordance and
|
|
14
|
-
* reloads the transcript once a compaction lands — deferring the reload to
|
|
15
|
-
* the end of the turn when one is streaming, so a mid-turn proactive
|
|
16
|
-
* compaction never clobbers streamed state.
|
|
17
|
-
*
|
|
18
|
-
* Compose the command with `useAgentChatCompaction`: supply the app's
|
|
19
|
-
* compaction callable, then place its command and notice explicitly.
|
|
20
|
-
*
|
|
21
|
-
* This module is the "local adapter … documented runtime-only mirror" that
|
|
22
|
-
* docs/think-session-ui.md calls for: upstream exports no payload types or
|
|
23
|
-
* client hook for these frames. The doc records the complete frame shapes;
|
|
24
|
-
* this adapter consumes `phase`, the presence of `compacted`, the error string
|
|
25
|
-
* of `cf_agent_session_error`, and the two estimates that size a landed
|
|
26
|
-
* compaction (`tokenEstimate` and `compacted.tokensBefore`). Every field but
|
|
27
|
-
* `phase` degrades to null rather than throwing, so an upstream field change
|
|
28
|
-
* costs detail, never the UI. Per that doc, `tokenThreshold` is the
|
|
29
|
-
* auto-compaction threshold, not the model context window — it stays unread
|
|
30
|
-
* here, and neither estimate may drive the `Context` ring, which reads
|
|
31
|
-
* provider-reported `metadata.usage`.
|
|
32
|
-
*
|
|
33
|
-
* @see ../../docs/think-session-ui.md
|
|
34
|
-
* @see https://github.com/cloudflare/agents/blob/main/docs/agents/sessions.md#compaction
|
|
35
|
-
*/
|
|
36
|
-
/** Finite numbers only — an absent or malformed field degrades to null. */
|
|
37
|
-
function finiteNumber(value) {
|
|
38
|
-
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Parse a raw websocket payload as a `cf_agent_session` status frame.
|
|
42
|
-
* Returns null for every other frame on the connection.
|
|
43
|
-
*/
|
|
44
|
-
function parseSessionStatusFrame(data) {
|
|
45
|
-
if (typeof data !== "string") return null;
|
|
46
|
-
let message;
|
|
47
|
-
try {
|
|
48
|
-
message = JSON.parse(data);
|
|
49
|
-
} catch {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
if (typeof message !== "object" || message === null || !("type" in message) || message.type !== "cf_agent_session" || !("phase" in message) || message.phase !== "idle" && message.phase !== "compacting") return null;
|
|
53
|
-
const compacted = "compacted" in message && message.compacted != null ? message.compacted : null;
|
|
54
|
-
return {
|
|
55
|
-
phase: message.phase,
|
|
56
|
-
compacted: compacted !== null,
|
|
57
|
-
tokenEstimate: finiteNumber("tokenEstimate" in message ? message.tokenEstimate : void 0),
|
|
58
|
-
tokensBefore: typeof compacted === "object" && compacted !== null && "tokensBefore" in compacted ? finiteNumber(compacted.tokensBefore) : null
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Parse a raw websocket payload as a `cf_agent_session_error` frame,
|
|
63
|
-
* returning its error text. Null for every other frame on the connection.
|
|
64
|
-
*/
|
|
65
|
-
function parseSessionErrorFrame(data) {
|
|
66
|
-
if (typeof data !== "string") return null;
|
|
67
|
-
let message;
|
|
68
|
-
try {
|
|
69
|
-
message = JSON.parse(data);
|
|
70
|
-
} catch {
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
if (typeof message !== "object" || message === null || !("type" in message) || message.type !== "cf_agent_session_error" || !("error" in message) || typeof message.error !== "string") return null;
|
|
74
|
-
return message.error;
|
|
75
|
-
}
|
|
76
|
-
function useSessionCompaction({ agent, chat, getMessages }) {
|
|
77
|
-
const [compacting, setCompacting] = React.useState(false);
|
|
78
|
-
const [refreshPending, setRefreshPending] = React.useState(false);
|
|
79
|
-
const [reloadError, setReloadError] = React.useState(null);
|
|
80
|
-
const [sessionError, setSessionError] = React.useState(null);
|
|
81
|
-
const [lastCompaction, setLastCompaction] = React.useState(null);
|
|
82
|
-
React.useEffect(() => {
|
|
83
|
-
setCompacting(false);
|
|
84
|
-
setSessionError(null);
|
|
85
|
-
setRefreshPending(false);
|
|
86
|
-
setReloadError(null);
|
|
87
|
-
setLastCompaction(null);
|
|
88
|
-
const onMessage = (event) => {
|
|
89
|
-
const frame = parseSessionStatusFrame(event.data);
|
|
90
|
-
if (frame) {
|
|
91
|
-
setCompacting(frame.phase === "compacting");
|
|
92
|
-
if (frame.phase === "compacting") {
|
|
93
|
-
setSessionError(null);
|
|
94
|
-
setLastCompaction(null);
|
|
95
|
-
}
|
|
96
|
-
if (frame.compacted) {
|
|
97
|
-
setRefreshPending(true);
|
|
98
|
-
setLastCompaction(frame.tokensBefore !== null && frame.tokenEstimate !== null ? {
|
|
99
|
-
tokensAfter: frame.tokenEstimate,
|
|
100
|
-
tokensBefore: frame.tokensBefore
|
|
101
|
-
} : null);
|
|
102
|
-
}
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
const error = parseSessionErrorFrame(event.data);
|
|
106
|
-
if (error !== null) {
|
|
107
|
-
setCompacting(false);
|
|
108
|
-
setSessionError(error);
|
|
109
|
-
}
|
|
110
|
-
};
|
|
111
|
-
agent.addEventListener("message", onMessage);
|
|
112
|
-
return () => agent.removeEventListener("message", onMessage);
|
|
113
|
-
}, [agent]);
|
|
114
|
-
const { status, setMessages } = chat;
|
|
115
|
-
React.useEffect(() => {
|
|
116
|
-
if (!refreshPending || status !== "ready") return;
|
|
117
|
-
let stale = false;
|
|
118
|
-
getMessages().then((messages) => {
|
|
119
|
-
if (stale) return;
|
|
120
|
-
setRefreshPending(false);
|
|
121
|
-
setReloadError(null);
|
|
122
|
-
setMessages(messages);
|
|
123
|
-
}, (error) => {
|
|
124
|
-
if (stale) return;
|
|
125
|
-
console.error("Transcript reload after compaction failed", error);
|
|
126
|
-
setReloadError(error);
|
|
127
|
-
});
|
|
128
|
-
return () => {
|
|
129
|
-
stale = true;
|
|
130
|
-
};
|
|
131
|
-
}, [refreshPending, status]);
|
|
132
|
-
return {
|
|
133
|
-
compacting,
|
|
134
|
-
lastCompaction,
|
|
135
|
-
reloadError,
|
|
136
|
-
sessionError
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
//#endregion
|
|
140
|
-
export { parseSessionErrorFrame, parseSessionStatusFrame, useSessionCompaction };
|