@opengeni/react 3.8.0-canary.1 → 4.0.1-canary.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/README.md +10 -24
- package/dist/artifacts.js +7 -7
- package/dist/{browser-viewer-SS46LUAC.js → browser-viewer-NTD6UIPR.js} +3 -3
- package/dist/{chunk-VEPNNDNG.js → chunk-24M4YBCL.js} +4 -4
- package/dist/{chunk-ELIYWBZR.js → chunk-BV5A4OTE.js} +4 -4
- package/dist/{chunk-7W6PVVTK.js → chunk-CQG7YUJB.js} +2582 -1037
- package/dist/chunk-CQG7YUJB.js.map +1 -0
- package/dist/{chunk-BXJOQFCD.js → chunk-HUMIRRYI.js} +84 -221
- package/dist/chunk-HUMIRRYI.js.map +1 -0
- package/dist/{chunk-7BWFU6H4.js → chunk-Z7WBDB4E.js} +395 -287
- package/dist/chunk-Z7WBDB4E.js.map +1 -0
- package/dist/components/human-input-form.d.ts +3 -1
- package/dist/components/human-input-surface.d.ts +3 -2
- package/dist/components/markdown-table-layout.d.ts +9 -0
- package/dist/components/session-conversation.d.ts +2 -0
- package/dist/composer.js +2 -3
- package/dist/{computer-viewer-FWEZISW4.js → computer-viewer-7TEZC6Y2.js} +3 -3
- package/dist/hooks/use-codex-accounts.d.ts +11 -1
- package/dist/hooks/use-session-events.d.ts +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +44 -34
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +3 -3
- package/dist/markdown-table-layout-3Z3AWBY7.js +71 -0
- package/dist/markdown-table-layout-3Z3AWBY7.js.map +1 -0
- package/dist/older-history.d.ts +3 -2
- package/dist/{platform-activity-row-BJHUHXAT.js → platform-activity-row-27LKAWZD.js} +2 -2
- package/dist/platform-activity-row-27LKAWZD.js.map +1 -0
- package/dist/realtime.js +3 -3
- package/dist/session-ui.js +6 -9
- package/dist/session.js +1 -1
- package/dist/timeline/types.d.ts +3 -0
- package/package.json +2 -6
- package/src/components/human-input-form.tsx +185 -53
- package/src/components/human-input-surface.tsx +3 -0
- package/src/components/markdown-table-layout.ts +85 -0
- package/src/components/markdown.tsx +20 -2
- package/src/components/message-timeline.tsx +47 -7
- package/src/components/session-commands-panel.tsx +7 -1
- package/src/components/session-conversation.tsx +4 -1
- package/src/hooks/use-codex-accounts.ts +32 -5
- package/src/hooks/use-session-events.ts +16 -277
- package/src/index.ts +0 -1
- package/src/older-history.ts +22 -4
- package/src/timeline/platform-activity-row.tsx +4 -1
- package/src/timeline/projection.ts +99 -9
- package/src/timeline/types.ts +3 -0
- package/dist/chat.d.ts +0 -37
- package/dist/chat.js +0 -315
- package/dist/chat.js.map +0 -1
- package/dist/chunk-7BWFU6H4.js.map +0 -1
- package/dist/chunk-7W6PVVTK.js.map +0 -1
- package/dist/chunk-BXJOQFCD.js.map +0 -1
- package/dist/chunk-HQV2I5HV.js +0 -124
- package/dist/chunk-HQV2I5HV.js.map +0 -1
- package/dist/chunk-YAIPFO5D.js +0 -1416
- package/dist/chunk-YAIPFO5D.js.map +0 -1
- package/dist/platform-activity-row-BJHUHXAT.js.map +0 -1
- package/src/chat.tsx +0 -393
- /package/dist/{browser-viewer-SS46LUAC.js.map → browser-viewer-NTD6UIPR.js.map} +0 -0
- /package/dist/{chunk-VEPNNDNG.js.map → chunk-24M4YBCL.js.map} +0 -0
- /package/dist/{chunk-ELIYWBZR.js.map → chunk-BV5A4OTE.js.map} +0 -0
- /package/dist/{computer-viewer-FWEZISW4.js.map → computer-viewer-7TEZC6Y2.js.map} +0 -0
package/dist/interaction.js
CHANGED
|
@@ -7,19 +7,20 @@ import {
|
|
|
7
7
|
useBrowserSession,
|
|
8
8
|
useBrowserSessions,
|
|
9
9
|
useSiteAuthConnections
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-24M4YBCL.js";
|
|
11
11
|
import {
|
|
12
12
|
ComputerViewer,
|
|
13
13
|
useComputerFrameStream,
|
|
14
14
|
useComputerSession,
|
|
15
15
|
useComputerSessions
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-BV5A4OTE.js";
|
|
17
17
|
import {
|
|
18
18
|
useInteractionInterventions,
|
|
19
19
|
useInteractionInvalidation
|
|
20
20
|
} from "./chunk-H5YGYNXS.js";
|
|
21
21
|
import "./chunk-4MDLEHXL.js";
|
|
22
22
|
import "./chunk-5YK2ZDIG.js";
|
|
23
|
+
import "./chunk-JVYQRRC4.js";
|
|
23
24
|
import "./chunk-PLYRL5ER.js";
|
|
24
25
|
import "./chunk-KZ73RL76.js";
|
|
25
26
|
import {
|
|
@@ -28,7 +29,6 @@ import {
|
|
|
28
29
|
useEmbeddedInteraction,
|
|
29
30
|
useEmbeddedInterventions
|
|
30
31
|
} from "./chunk-NEXLLTP4.js";
|
|
31
|
-
import "./chunk-JVYQRRC4.js";
|
|
32
32
|
import "./chunk-22KP6LR5.js";
|
|
33
33
|
|
|
34
34
|
// src/hooks/use-network-routes.ts
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// src/components/markdown-table-layout.ts
|
|
2
|
+
function markdownTableWidth({
|
|
3
|
+
columnLeft,
|
|
4
|
+
columnWidth,
|
|
5
|
+
contentLeft,
|
|
6
|
+
contentRight,
|
|
7
|
+
preferredWidth
|
|
8
|
+
}) {
|
|
9
|
+
const center = columnLeft + columnWidth / 2;
|
|
10
|
+
const available = 2 * Math.min(center - contentLeft, contentRight - center);
|
|
11
|
+
return Math.max(columnWidth, Math.min(preferredWidth, available));
|
|
12
|
+
}
|
|
13
|
+
function observeMarkdownTableLayout(wrapper, table) {
|
|
14
|
+
const body = wrapper.parentElement;
|
|
15
|
+
const scroller = body?.closest("[data-og-wide-table-message]")?.closest("[data-og-timeline-scroller]");
|
|
16
|
+
if (!body?.classList.contains("og-markdown-body") || !scroller) return;
|
|
17
|
+
let width = null;
|
|
18
|
+
const reset = () => {
|
|
19
|
+
width = null;
|
|
20
|
+
wrapper.style.width = "";
|
|
21
|
+
wrapper.style.maxWidth = "";
|
|
22
|
+
wrapper.style.marginInline = "";
|
|
23
|
+
};
|
|
24
|
+
const measure = () => {
|
|
25
|
+
for (let ancestor = body; ancestor && ancestor !== scroller; ancestor = ancestor.parentElement) {
|
|
26
|
+
if (getComputedStyle(ancestor).overflowX !== "visible") {
|
|
27
|
+
reset();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const column = body.getBoundingClientRect();
|
|
32
|
+
const panel = scroller.getBoundingClientRect();
|
|
33
|
+
const panelStyle = getComputedStyle(scroller);
|
|
34
|
+
const left = panel.left + scroller.clientLeft + parseFloat(panelStyle.paddingLeft);
|
|
35
|
+
const right = panel.left + scroller.clientLeft + scroller.clientWidth - parseFloat(panelStyle.paddingRight);
|
|
36
|
+
const previousWidth = table.style.width;
|
|
37
|
+
let preferred;
|
|
38
|
+
try {
|
|
39
|
+
table.style.width = "max-content";
|
|
40
|
+
preferred = table.getBoundingClientRect().width;
|
|
41
|
+
} finally {
|
|
42
|
+
table.style.width = previousWidth;
|
|
43
|
+
}
|
|
44
|
+
const next = markdownTableWidth({
|
|
45
|
+
columnLeft: column.left,
|
|
46
|
+
columnWidth: column.width,
|
|
47
|
+
contentLeft: left,
|
|
48
|
+
contentRight: right,
|
|
49
|
+
preferredWidth: preferred
|
|
50
|
+
});
|
|
51
|
+
if (width !== null && Math.abs(width - next) < 0.5) return;
|
|
52
|
+
width = next;
|
|
53
|
+
wrapper.style.width = `${width}px`;
|
|
54
|
+
wrapper.style.maxWidth = "none";
|
|
55
|
+
wrapper.style.marginInline = `calc((100% - ${width}px) / 2)`;
|
|
56
|
+
};
|
|
57
|
+
measure();
|
|
58
|
+
const observer = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(measure);
|
|
59
|
+
observer?.observe(scroller);
|
|
60
|
+
observer?.observe(body);
|
|
61
|
+
observer?.observe(table);
|
|
62
|
+
return () => {
|
|
63
|
+
observer?.disconnect();
|
|
64
|
+
reset();
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
export {
|
|
68
|
+
markdownTableWidth,
|
|
69
|
+
observeMarkdownTableLayout
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=markdown-table-layout-3Z3AWBY7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/markdown-table-layout.ts"],"sourcesContent":["export function markdownTableWidth({\n columnLeft,\n columnWidth,\n contentLeft,\n contentRight,\n preferredWidth,\n}: {\n columnLeft: number;\n columnWidth: number;\n contentLeft: number;\n contentRight: number;\n preferredWidth: number;\n}): number {\n const center = columnLeft + columnWidth / 2;\n const available = 2 * Math.min(center - contentLeft, contentRight - center);\n return Math.max(columnWidth, Math.min(preferredWidth, available));\n}\n\n/** Loaded only for assistant tables. Keep prose and nested scroll owners intact. */\nexport function observeMarkdownTableLayout(wrapper: HTMLDivElement, table: HTMLTableElement) {\n const body = wrapper.parentElement;\n const scroller = body\n ?.closest(\"[data-og-wide-table-message]\")\n ?.closest<HTMLElement>(\"[data-og-timeline-scroller]\");\n if (!body?.classList.contains(\"og-markdown-body\") || !scroller) return;\n\n let width: number | null = null;\n const reset = () => {\n width = null;\n wrapper.style.width = \"\";\n wrapper.style.maxWidth = \"\";\n wrapper.style.marginInline = \"\";\n };\n const measure = () => {\n // Intermediate clipped/scrollable surfaces own their own content bounds.\n for (\n let ancestor: HTMLElement | null = body;\n ancestor && ancestor !== scroller;\n ancestor = ancestor.parentElement\n ) {\n if (getComputedStyle(ancestor).overflowX !== \"visible\") {\n reset();\n return;\n }\n }\n const column = body.getBoundingClientRect();\n const panel = scroller.getBoundingClientRect();\n const panelStyle = getComputedStyle(scroller);\n const left = panel.left + scroller.clientLeft + parseFloat(panelStyle.paddingLeft);\n const right =\n panel.left + scroller.clientLeft + scroller.clientWidth - parseFloat(panelStyle.paddingRight);\n\n // Measure the original table, preserving its wrapping and TSV copy DOM.\n const previousWidth = table.style.width;\n let preferred: number;\n try {\n table.style.width = \"max-content\";\n preferred = table.getBoundingClientRect().width;\n } finally {\n table.style.width = previousWidth;\n }\n const next = markdownTableWidth({\n columnLeft: column.left,\n columnWidth: column.width,\n contentLeft: left,\n contentRight: right,\n preferredWidth: preferred,\n });\n if (width !== null && Math.abs(width - next) < 0.5) return;\n width = next;\n wrapper.style.width = `${width}px`;\n wrapper.style.maxWidth = \"none\";\n wrapper.style.marginInline = `calc((100% - ${width}px) / 2)`;\n };\n\n measure();\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(measure);\n observer?.observe(scroller);\n observer?.observe(body);\n observer?.observe(table);\n return () => {\n observer?.disconnect();\n reset();\n };\n}\n"],"mappings":";AAAO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAMW;AACT,QAAM,SAAS,aAAa,cAAc;AAC1C,QAAM,YAAY,IAAI,KAAK,IAAI,SAAS,aAAa,eAAe,MAAM;AAC1E,SAAO,KAAK,IAAI,aAAa,KAAK,IAAI,gBAAgB,SAAS,CAAC;AAClE;AAGO,SAAS,2BAA2B,SAAyB,OAAyB;AAC3F,QAAM,OAAO,QAAQ;AACrB,QAAM,WAAW,MACb,QAAQ,8BAA8B,GACtC,QAAqB,6BAA6B;AACtD,MAAI,CAAC,MAAM,UAAU,SAAS,kBAAkB,KAAK,CAAC,SAAU;AAEhE,MAAI,QAAuB;AAC3B,QAAM,QAAQ,MAAM;AAClB,YAAQ;AACR,YAAQ,MAAM,QAAQ;AACtB,YAAQ,MAAM,WAAW;AACzB,YAAQ,MAAM,eAAe;AAAA,EAC/B;AACA,QAAM,UAAU,MAAM;AAEpB,aACM,WAA+B,MACnC,YAAY,aAAa,UACzB,WAAW,SAAS,eACpB;AACA,UAAI,iBAAiB,QAAQ,EAAE,cAAc,WAAW;AACtD,cAAM;AACN;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAAS,KAAK,sBAAsB;AAC1C,UAAM,QAAQ,SAAS,sBAAsB;AAC7C,UAAM,aAAa,iBAAiB,QAAQ;AAC5C,UAAM,OAAO,MAAM,OAAO,SAAS,aAAa,WAAW,WAAW,WAAW;AACjF,UAAM,QACJ,MAAM,OAAO,SAAS,aAAa,SAAS,cAAc,WAAW,WAAW,YAAY;AAG9F,UAAM,gBAAgB,MAAM,MAAM;AAClC,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,QAAQ;AACpB,kBAAY,MAAM,sBAAsB,EAAE;AAAA,IAC5C,UAAE;AACA,YAAM,MAAM,QAAQ;AAAA,IACtB;AACA,UAAM,OAAO,mBAAmB;AAAA,MAC9B,YAAY,OAAO;AAAA,MACnB,aAAa,OAAO;AAAA,MACpB,aAAa;AAAA,MACb,cAAc;AAAA,MACd,gBAAgB;AAAA,IAClB,CAAC;AACD,QAAI,UAAU,QAAQ,KAAK,IAAI,QAAQ,IAAI,IAAI,IAAK;AACpD,YAAQ;AACR,YAAQ,MAAM,QAAQ,GAAG,KAAK;AAC9B,YAAQ,MAAM,WAAW;AACzB,YAAQ,MAAM,eAAe,gBAAgB,KAAK;AAAA,EACpD;AAEA,UAAQ;AACR,QAAM,WAAW,OAAO,mBAAmB,cAAc,SAAY,IAAI,eAAe,OAAO;AAC/F,YAAU,QAAQ,QAAQ;AAC1B,YAAU,QAAQ,IAAI;AACtB,YAAU,QAAQ,KAAK;AACvB,SAAO,MAAM;AACX,cAAU,WAAW;AACrB,UAAM;AAAA,EACR;AACF;","names":[]}
|
package/dist/older-history.d.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export type OlderHistoryLoadReceipt = Promise<boolean> & {
|
|
10
10
|
readonly committed: boolean;
|
|
11
|
+
readonly tailPreserved?: boolean;
|
|
11
12
|
};
|
|
12
13
|
/**
|
|
13
14
|
* Source-compatible public callback accepted by MessageTimeline.
|
|
@@ -20,10 +21,10 @@ export type OlderHistoryLoadReceipt = Promise<boolean> & {
|
|
|
20
21
|
export type OlderHistoryLoader = () => unknown;
|
|
21
22
|
type OlderHistoryReceiptCapture = (receipt: OlderHistoryLoadReceipt) => void;
|
|
22
23
|
/** Bind a receipt before a synchronous forwarding stack can publish state. */
|
|
23
|
-
export declare function invokeOlderHistoryLoaderWithReceiptCapture(load: OlderHistoryLoader, capture: OlderHistoryReceiptCapture): unknown;
|
|
24
|
+
export declare function invokeOlderHistoryLoaderWithReceiptCapture(load: OlderHistoryLoader, capture: OlderHistoryReceiptCapture, preserveTail?: boolean): unknown;
|
|
24
25
|
/**
|
|
25
26
|
* Build an await-compatible older-history receipt for custom timeline hosts.
|
|
26
27
|
* Call `markCommitted` immediately before publishing an accepted older window.
|
|
27
28
|
*/
|
|
28
|
-
export declare function createOlderHistoryLoadReceipt(load: (markCommitted: () => void) => boolean | Promise<boolean>): OlderHistoryLoadReceipt;
|
|
29
|
+
export declare function createOlderHistoryLoadReceipt(load: (markCommitted: () => void, preserveTail: boolean, markTailPreserved: () => void) => boolean | Promise<boolean>): OlderHistoryLoadReceipt;
|
|
29
30
|
export {};
|
|
@@ -47,7 +47,7 @@ function PlatformActivityRow({
|
|
|
47
47
|
return j(ActivityDisclosure, {
|
|
48
48
|
icon: j(BotIcon, { className: "size-3.5" }),
|
|
49
49
|
iconTone: failed ? "failed" : running ? "running" : "muted",
|
|
50
|
-
title: startupPhaseTitle(item.phase, item.status, item.outcome),
|
|
50
|
+
title: item.blockedReason === "rotation_in_progress" ? "Waiting for sandbox rotation" : startupPhaseTitle(item.phase, item.status, item.outcome),
|
|
51
51
|
preview: item.phase === "model_preparation" ? "Includes overlapping sandbox, rig, repository, and runtime setup shown below." : void 0,
|
|
52
52
|
running,
|
|
53
53
|
failed,
|
|
@@ -166,4 +166,4 @@ function startupDuration(durationMs) {
|
|
|
166
166
|
export {
|
|
167
167
|
PlatformActivityRow as default
|
|
168
168
|
};
|
|
169
|
-
//# sourceMappingURL=platform-activity-row-
|
|
169
|
+
//# sourceMappingURL=platform-activity-row-27LKAWZD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/timeline/platform-activity-row.tsx"],"sourcesContent":["import type { ReasoningItem, SandboxItem, StartupPhaseItem } from \"./types\";\n\ntype RowJsx = typeof import(\"react/jsx-runtime\").jsx;\ntype RowJsxs = typeof import(\"react/jsx-runtime\").jsxs;\n\nexport default function PlatformActivityRow({\n item,\n d: ActivityDisclosure,\n p: PayloadBlock,\n t: displayName,\n b: BotIcon,\n m: Markdown,\n r: truncate,\n j,\n s,\n}: {\n item: ReasoningItem | SandboxItem | StartupPhaseItem;\n d: typeof import(\"./shared\").ActivityDisclosure;\n p: typeof import(\"./shared\").PayloadBlock;\n t: (name: string) => string;\n b: typeof import(\"lucide-react\").BotIcon;\n m: typeof import(\"../components/markdown\").Markdown;\n r: typeof import(\"../lib/format\").truncate;\n j: RowJsx;\n s: RowJsxs;\n}) {\n if (item.kind === \"reasoning\") {\n return j(ActivityDisclosure, {\n icon: brainIcon(j, s),\n iconTone: \"muted\",\n title: item.streaming\n ? \"Thinking\"\n : j(\"span\", {\n className: \"font-normal italic text-og-fg-subtle\",\n children: \"Thought\",\n }),\n running: item.streaming,\n preview: truncate(item.text, 110),\n children: j(\"div\", {\n className: \"text-og-base leading-6 text-og-fg-muted [&_strong]:text-og-fg-muted\",\n children: j(Markdown, { streaming: item.streaming, children: item.text }),\n }),\n });\n }\n if (item.kind === \"sandbox\") {\n return s(ActivityDisclosure, {\n icon: terminalIcon(j, s),\n iconTone:\n item.status === \"failed\" ? \"failed\" : item.status === \"running\" ? \"running\" : \"muted\",\n title: sandboxRowTitle(item, displayName),\n running: item.status === \"running\",\n failed: item.status === \"failed\",\n cancelled: item.status === \"cancelled\",\n preview: item.command ?? undefined,\n children: [\n item.command ? j(PayloadBlock, { label: \"Command\", value: item.command }, \"command\") : null,\n item.output ? j(PayloadBlock, { label: \"Output\", value: item.output }, \"output\") : null,\n ],\n });\n }\n\n const failed = item.status === \"failed\";\n const running = item.status === \"running\";\n const duration = startupDuration(item.durationMs);\n return j(ActivityDisclosure, {\n icon: j(BotIcon, { className: \"size-3.5\" }),\n iconTone: failed ? \"failed\" : running ? \"running\" : \"muted\",\n title:\n item.blockedReason === \"rotation_in_progress\"\n ? \"Waiting for sandbox rotation\"\n : startupPhaseTitle(item.phase, item.status, item.outcome),\n preview:\n item.phase === \"model_preparation\"\n ? \"Includes overlapping sandbox, rig, repository, and runtime setup shown below.\"\n : undefined,\n running,\n failed,\n cancelled: item.status === \"cancelled\",\n chip: duration ? { tone: failed ? \"bad\" : \"muted\", text: duration } : undefined,\n expandable: false,\n });\n}\n\nfunction brainIcon(j: RowJsx, s: RowJsxs) {\n return lucideIcon(j, s, \"brain\", [\n j(\"path\", { d: \"M 12 18V5\" }, \"spine\"),\n j(\"path\", { d: \"M15 13a4.17 4.17 0 0 1-3-4 4.17 4.17 0 0 1-3 4\" }, \"center\"),\n j(\"path\", { d: \"M17.598 6.5A3 3 0 1 0 12 5a3 3 0 1 0-5.598 1.5\" }, \"top\"),\n j(\"path\", { d: \"M17.997 5.125a4 4 0 0 1 2.526 5.77\" }, \"upper-right\"),\n j(\"path\", { d: \"M18 18a4 4 0 0 0 2-7.464\" }, \"right\"),\n j(\"path\", { d: \"M19.967 17.483A4 4 0 1 1 12 18a4 4 0 1 1-7.967-.517\" }, \"base\"),\n j(\"path\", { d: \"M6 18a4 4 0 0 1-2-7.464\" }, \"left\"),\n j(\"path\", { d: \"M6.003 5.125a4 4 0 0 0-2.526 5.77\" }, \"upper-left\"),\n ]);\n}\n\nfunction terminalIcon(j: RowJsx, s: RowJsxs) {\n return lucideIcon(j, s, \"square-terminal\", [\n j(\"path\", { d: \"m7 11 2-2-2-2\" }, \"prompt\"),\n j(\"path\", { d: \"M11 13h4\" }, \"cursor\"),\n j(\"rect\", { width: 18, height: 18, x: 3, y: 3, rx: 2, ry: 2 }, \"frame\"),\n ]);\n}\n\nfunction lucideIcon(j: RowJsx, s: RowJsxs, name: string, children: ReturnType<RowJsx>[]) {\n return s(\"svg\", {\n \"aria-hidden\": \"true\",\n className: `lucide lucide-${name} size-3.5`,\n fill: \"none\",\n height: 24,\n stroke: \"currentColor\",\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeWidth: 2,\n viewBox: \"0 0 24 24\",\n width: 24,\n children,\n });\n}\n\nfunction sandboxRowTitle(item: SandboxItem, displayName: (name: string) => string): string {\n if (item.name === \"sandbox.provision\") {\n return startupPhaseTitle(\n \"sandbox\",\n item.status === \"cancelled\" ? \"complete\" : item.status,\n item.origin ?? null,\n );\n }\n return displayName(item.name);\n}\n\nfunction startupPhaseTitle(\n phase: StartupPhaseItem[\"phase\"],\n status: StartupPhaseItem[\"status\"],\n outcome: StartupPhaseItem[\"outcome\"],\n): string {\n if (status === \"complete\" && phase === \"sandbox\" && outcome && outcome !== \"skipped\") {\n return `Sandbox ${outcome === \"resumed\" ? \"reattached\" : outcome}`;\n }\n if (status === \"complete\" && phase === \"rig\" && outcome === \"skipped\") {\n return \"Rig already ready\";\n }\n const statusIndex =\n status === \"running\" ? 0 : status === \"failed\" ? 1 : status === \"cancelled\" ? 2 : 3;\n return STARTUP_PHASE_TITLES[phase][statusIndex];\n}\n\nconst STARTUP_PHASE_TITLES: Record<\n StartupPhaseItem[\"phase\"],\n readonly [string, string, string, string]\n> = {\n queue: [\n \"Waiting for a worker\",\n \"Worker startup failed\",\n \"Worker wait interrupted\",\n \"Worker started\",\n ],\n sandbox: [\n \"Starting sandbox\",\n \"Sandbox didn’t start\",\n \"Sandbox startup interrupted\",\n \"Sandbox ready\",\n ],\n rig: [\"Setting up rig\", \"Rig setup failed\", \"Rig setup interrupted\", \"Rig ready\"],\n repository: [\n \"Preparing repository\",\n \"Repository preparation failed\",\n \"Repository preparation interrupted\",\n \"Repository ready\",\n ],\n files: [\n \"Preparing files\",\n \"File preparation failed\",\n \"File preparation interrupted\",\n \"Files ready\",\n ],\n tools: [\n \"Connecting tools\",\n \"Tool connection failed\",\n \"Tool connection interrupted\",\n \"Tools ready\",\n ],\n model_preparation: [\n \"Preparing runtime and model request\",\n \"Runtime/model preparation failed\",\n \"Runtime/model preparation interrupted\",\n \"Model request dispatched\",\n ],\n provider_first_byte: [\n \"Waiting for model\",\n \"Model didn’t respond\",\n \"Model wait interrupted\",\n \"Model started responding\",\n ],\n};\n\nfunction startupDuration(durationMs: number | null): string | null {\n if (durationMs === null || !Number.isFinite(durationMs) || durationMs < 0) return null;\n if (durationMs < 1_000) return `${Math.round(durationMs)}ms`;\n if (durationMs < 60_000) return `${(durationMs / 1_000).toFixed(1)}s`;\n const minutes = Math.floor(durationMs / 60_000);\n const seconds = Math.round((durationMs % 60_000) / 1_000);\n return `${minutes}m ${String(seconds).padStart(2, \"0\")}s`;\n}\n"],"mappings":"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","names":[]}
|
package/dist/realtime.js
CHANGED
|
@@ -4,13 +4,13 @@ import {
|
|
|
4
4
|
PickerBackHeader,
|
|
5
5
|
PickerNavRow
|
|
6
6
|
} from "./chunk-R4KRSFGA.js";
|
|
7
|
-
import {
|
|
8
|
-
useEmbeddedRealtimeSession
|
|
9
|
-
} from "./chunk-NEXLLTP4.js";
|
|
10
7
|
import {
|
|
11
8
|
usePortalTokenSource,
|
|
12
9
|
usePortalTokenStyle
|
|
13
10
|
} from "./chunk-VZTQ73XT.js";
|
|
11
|
+
import {
|
|
12
|
+
useEmbeddedRealtimeSession
|
|
13
|
+
} from "./chunk-NEXLLTP4.js";
|
|
14
14
|
import "./chunk-VRBL3F5E.js";
|
|
15
15
|
import {
|
|
16
16
|
cn
|
package/dist/session-ui.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BUILT_IN_TURN_SUMMARY_FACET_IDS,
|
|
3
|
+
HumanInputForm,
|
|
3
4
|
HumanInputSurface,
|
|
4
5
|
MessageTimeline,
|
|
5
6
|
QueueSurface,
|
|
@@ -12,27 +13,23 @@ import {
|
|
|
12
13
|
sessionChromeGoalPillLabel,
|
|
13
14
|
sessionChromeGoalPillState,
|
|
14
15
|
userMessageLikelyNeedsDisclosure
|
|
15
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-CQG7YUJB.js";
|
|
16
17
|
import "./chunk-YBM6CQRU.js";
|
|
17
18
|
import "./chunk-5M6VTFJ5.js";
|
|
18
19
|
import "./chunk-ZYRGEKWS.js";
|
|
19
20
|
import "./chunk-NOSYBS2D.js";
|
|
20
21
|
import "./chunk-PAJU5KKL.js";
|
|
21
|
-
import "./chunk-
|
|
22
|
+
import "./chunk-JVYQRRC4.js";
|
|
23
|
+
import "./chunk-Z7WBDB4E.js";
|
|
22
24
|
import "./chunk-R4KRSFGA.js";
|
|
25
|
+
import "./chunk-VZTQ73XT.js";
|
|
23
26
|
import {
|
|
24
27
|
createOlderHistoryLoadReceipt
|
|
25
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-HUMIRRYI.js";
|
|
26
29
|
import "./chunk-6J56T3MG.js";
|
|
27
30
|
import "./chunk-PLYRL5ER.js";
|
|
28
31
|
import "./chunk-KZ73RL76.js";
|
|
29
32
|
import "./chunk-NEXLLTP4.js";
|
|
30
|
-
import {
|
|
31
|
-
HumanInputForm
|
|
32
|
-
} from "./chunk-YAIPFO5D.js";
|
|
33
|
-
import "./chunk-JVYQRRC4.js";
|
|
34
|
-
import "./chunk-HQV2I5HV.js";
|
|
35
|
-
import "./chunk-VZTQ73XT.js";
|
|
36
33
|
import "./chunk-VRBL3F5E.js";
|
|
37
34
|
import "./chunk-22KP6LR5.js";
|
|
38
35
|
export {
|
package/dist/session.js
CHANGED
package/dist/timeline/types.d.ts
CHANGED
|
@@ -173,6 +173,7 @@ export type StartupPhaseItem = {
|
|
|
173
173
|
durationMs: number | null;
|
|
174
174
|
/** Sandbox origin and rig marker outcomes refine the settled label only. */
|
|
175
175
|
outcome: "created" | "restored" | "resumed" | "skipped" | null;
|
|
176
|
+
blockedReason?: "rotation_in_progress" | undefined;
|
|
176
177
|
occurredAt: string;
|
|
177
178
|
};
|
|
178
179
|
/**
|
|
@@ -352,6 +353,8 @@ export type AuthNeededItem = {
|
|
|
352
353
|
export type TurnOutcome = "complete" | "failed" | "cancelled";
|
|
353
354
|
export type TurnEndItem = {
|
|
354
355
|
kind: "turn-end";
|
|
356
|
+
/** Keep an existing answer visible when a recorded input wait ends without final output. */
|
|
357
|
+
preserveWaitResponse?: true;
|
|
355
358
|
id: string;
|
|
356
359
|
turnId: string | null;
|
|
357
360
|
outcome: TurnOutcome;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1-canary.1",
|
|
4
4
|
"description": "React hooks and styled components for OpenGeni: live session streaming, chat composer, message timeline, session status, and fleet views — token-themed (CSS variables), dark-first, built on Tailwind v4 + Radix + Motion.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -78,10 +78,6 @@
|
|
|
78
78
|
"types": "./dist/clipboard.d.ts",
|
|
79
79
|
"import": "./dist/clipboard.js"
|
|
80
80
|
},
|
|
81
|
-
"./chat": {
|
|
82
|
-
"types": "./dist/chat.tsx",
|
|
83
|
-
"import": "./dist/chat.tsx"
|
|
84
|
-
},
|
|
85
81
|
"./styles.css": {
|
|
86
82
|
"types": "./styles/index.d.ts",
|
|
87
83
|
"style": "./styles/index.css",
|
|
@@ -124,7 +120,7 @@
|
|
|
124
120
|
"@dnd-kit/utilities": "3.2.2",
|
|
125
121
|
"@fontsource-variable/noto-sans-arabic": "5.2.10",
|
|
126
122
|
"@fontsource-variable/noto-sans-jp": "5.2.10",
|
|
127
|
-
"@opengeni/sdk": "^
|
|
123
|
+
"@opengeni/sdk": "^4.0.1-canary.1",
|
|
128
124
|
"clsx": "^2.1.1",
|
|
129
125
|
"dequal": "2.0.3",
|
|
130
126
|
"lucide-react": "^1.8.0",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
HumanInputAnswer,
|
|
3
3
|
HumanInputQuestion,
|
|
4
|
+
SkillRecord,
|
|
4
5
|
SessionHumanInputRequest,
|
|
5
6
|
SubmitHumanInputResponseRequest,
|
|
6
7
|
} from "@opengeni/sdk";
|
|
@@ -64,6 +65,10 @@ export const defaultHumanInputFormMessages: HumanInputFormMessages = {
|
|
|
64
65
|
};
|
|
65
66
|
|
|
66
67
|
export type HumanInputFormProps = {
|
|
68
|
+
/** Scoped immutable revision reader. Saving a Skill fails closed without its full preview. */
|
|
69
|
+
loadSkillReview?:
|
|
70
|
+
| ((reference: NonNullable<HumanInputQuestion["skillReview"]>) => Promise<SkillRecord>)
|
|
71
|
+
| undefined;
|
|
67
72
|
request: Pick<SessionHumanInputRequest, "id" | "questions" | "allowSkip" | "expiresAt">;
|
|
68
73
|
onSubmit: (response: SubmitHumanInputResponseRequest) => void | Promise<void>;
|
|
69
74
|
submitting?: boolean | undefined;
|
|
@@ -98,6 +103,7 @@ export function HumanInputForm(props: HumanInputFormProps) {
|
|
|
98
103
|
function HumanInputRequestForm({
|
|
99
104
|
request,
|
|
100
105
|
onSubmit,
|
|
106
|
+
loadSkillReview,
|
|
101
107
|
submitting = false,
|
|
102
108
|
error,
|
|
103
109
|
title,
|
|
@@ -142,6 +148,116 @@ function HumanInputRequestForm({
|
|
|
142
148
|
const submissionInFlight = useRef(false);
|
|
143
149
|
const submissionGeneration = useRef(0);
|
|
144
150
|
const busy = submitting || submittingInternally;
|
|
151
|
+
const reviewIdentity = JSON.stringify(
|
|
152
|
+
request.questions
|
|
153
|
+
.filter((question) => question.skillReview)
|
|
154
|
+
.map((question) => ({
|
|
155
|
+
id: question.id,
|
|
156
|
+
reference: {
|
|
157
|
+
sourceOperationId: question.skillReview!.sourceOperationId,
|
|
158
|
+
skillId: question.skillReview!.skillId,
|
|
159
|
+
revisionId: question.skillReview!.revisionId,
|
|
160
|
+
expectedRevisionId: question.skillReview!.expectedRevisionId,
|
|
161
|
+
expectedScopeVersion: question.skillReview!.expectedScopeVersion,
|
|
162
|
+
},
|
|
163
|
+
})),
|
|
164
|
+
);
|
|
165
|
+
const [reviewReload, setReviewReload] = useState(0);
|
|
166
|
+
const [reviews, setReviews] = useState<{
|
|
167
|
+
loader: typeof loadSkillReview;
|
|
168
|
+
identity: string;
|
|
169
|
+
records: Record<string, SkillRecord>;
|
|
170
|
+
error: string | null;
|
|
171
|
+
} | null>(null);
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
let current = true;
|
|
174
|
+
const questions = JSON.parse(reviewIdentity) as Array<{
|
|
175
|
+
id: string;
|
|
176
|
+
reference: NonNullable<HumanInputQuestion["skillReview"]>;
|
|
177
|
+
}>;
|
|
178
|
+
if (!questions.length) return;
|
|
179
|
+
setReviews(null);
|
|
180
|
+
void Promise.all(
|
|
181
|
+
questions.map(async (question) => {
|
|
182
|
+
if (!loadSkillReview)
|
|
183
|
+
throw new Error(
|
|
184
|
+
"This client cannot preview Skill files. Open this request in OpenGeni to review it.",
|
|
185
|
+
);
|
|
186
|
+
const reference = question.reference;
|
|
187
|
+
const record = await loadSkillReview(reference);
|
|
188
|
+
if (
|
|
189
|
+
record.id !== reference.skillId ||
|
|
190
|
+
record.revisionId !== reference.revisionId ||
|
|
191
|
+
!record.files.some((file) => file.path === "SKILL.md")
|
|
192
|
+
) {
|
|
193
|
+
throw new Error("The requested Skill revision could not be verified.");
|
|
194
|
+
}
|
|
195
|
+
return [question.id, record] as const;
|
|
196
|
+
}),
|
|
197
|
+
)
|
|
198
|
+
.then((records) => {
|
|
199
|
+
if (current)
|
|
200
|
+
setReviews({
|
|
201
|
+
loader: loadSkillReview,
|
|
202
|
+
identity: reviewIdentity,
|
|
203
|
+
records: Object.fromEntries(records),
|
|
204
|
+
error: null,
|
|
205
|
+
});
|
|
206
|
+
})
|
|
207
|
+
.catch((cause) => {
|
|
208
|
+
if (current)
|
|
209
|
+
setReviews({
|
|
210
|
+
loader: loadSkillReview,
|
|
211
|
+
identity: reviewIdentity,
|
|
212
|
+
records: {},
|
|
213
|
+
error: cause instanceof Error ? cause.message : "Could not load the Skill files.",
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
return () => {
|
|
217
|
+
current = false;
|
|
218
|
+
};
|
|
219
|
+
}, [loadSkillReview, reviewIdentity, reviewReload]);
|
|
220
|
+
const visibleReviews =
|
|
221
|
+
reviews?.loader === loadSkillReview && reviews?.identity === reviewIdentity ? reviews : null;
|
|
222
|
+
const preview = (question: HumanInputQuestion) => {
|
|
223
|
+
if (!question.skillReview) return null;
|
|
224
|
+
const record = visibleReviews?.records[question.id];
|
|
225
|
+
return (
|
|
226
|
+
<div className="mb-3 min-w-0 space-y-2" data-skill-review="">
|
|
227
|
+
{record ? (
|
|
228
|
+
<>
|
|
229
|
+
<p className="text-og-sm">
|
|
230
|
+
{record.title ?? "Skill"} · {record.scope} · {record.files.length} files
|
|
231
|
+
</p>
|
|
232
|
+
<p className="text-og-xs text-og-fg-muted">
|
|
233
|
+
Saving activates these exact files. No additional review is required.
|
|
234
|
+
</p>
|
|
235
|
+
{record.files.map((file) => (
|
|
236
|
+
<details key={file.path} open={file.path === "SKILL.md"}>
|
|
237
|
+
<summary className="cursor-pointer break-all text-og-sm">{file.path}</summary>
|
|
238
|
+
<pre className="max-h-64 overflow-auto whitespace-pre-wrap break-words rounded-og-md bg-og-surface-1 p-2 text-og-xs">
|
|
239
|
+
{file.content}
|
|
240
|
+
</pre>
|
|
241
|
+
</details>
|
|
242
|
+
))}
|
|
243
|
+
</>
|
|
244
|
+
) : visibleReviews?.error ? (
|
|
245
|
+
<>
|
|
246
|
+
<p role="alert" className="text-og-sm">
|
|
247
|
+
{visibleReviews.error}
|
|
248
|
+
</p>
|
|
249
|
+
<button type="button" onClick={() => setReviewReload((value) => value + 1)}>
|
|
250
|
+
Retry preview
|
|
251
|
+
</button>
|
|
252
|
+
</>
|
|
253
|
+
) : (
|
|
254
|
+
<p role="status" className="text-og-sm">
|
|
255
|
+
Loading the exact Skill files…
|
|
256
|
+
</p>
|
|
257
|
+
)}
|
|
258
|
+
</div>
|
|
259
|
+
);
|
|
260
|
+
};
|
|
145
261
|
|
|
146
262
|
useEffect(() => {
|
|
147
263
|
if (collapsed) {
|
|
@@ -232,6 +348,18 @@ function HumanInputRequestForm({
|
|
|
232
348
|
}
|
|
233
349
|
return;
|
|
234
350
|
}
|
|
351
|
+
const unreviewedSave = request.questions.find(
|
|
352
|
+
(question) =>
|
|
353
|
+
question.skillReview &&
|
|
354
|
+
!visibleReviews?.records[question.id] &&
|
|
355
|
+
result.answers.some(
|
|
356
|
+
(answer) => answer.questionId === question.id && answer.values.includes("save"),
|
|
357
|
+
),
|
|
358
|
+
);
|
|
359
|
+
if (unreviewedSave) {
|
|
360
|
+
setValidationErrors({ [unreviewedSave.id]: "Load the exact Skill files before saving." });
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
235
363
|
await submitResponse({ outcome: "answered", answers: result.answers });
|
|
236
364
|
};
|
|
237
365
|
|
|
@@ -365,6 +493,7 @@ function HumanInputRequestForm({
|
|
|
365
493
|
// Title already carries the question; only render the control + help extras.
|
|
366
494
|
return (
|
|
367
495
|
<div key={question.id} data-human-input-question={question.id}>
|
|
496
|
+
{preview(question)}
|
|
368
497
|
<QuestionControls
|
|
369
498
|
question={question}
|
|
370
499
|
questionNumber={null}
|
|
@@ -389,6 +518,7 @@ function HumanInputRequestForm({
|
|
|
389
518
|
data-human-input-question={question.id}
|
|
390
519
|
className="flex flex-col gap-1.5"
|
|
391
520
|
>
|
|
521
|
+
{preview(question)}
|
|
392
522
|
<QuestionControls
|
|
393
523
|
question={question}
|
|
394
524
|
questionNumber={index + 1}
|
|
@@ -643,62 +773,64 @@ function QuestionControls({
|
|
|
643
773
|
</label>
|
|
644
774
|
);
|
|
645
775
|
})}
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
id={otherChoiceId}
|
|
656
|
-
type={question.kind === "single_select" ? "radio" : "checkbox"}
|
|
657
|
-
name={question.kind === "single_select" ? fieldId : undefined}
|
|
658
|
-
aria-labelledby={otherLabelId}
|
|
659
|
-
checked={draft.otherSelected}
|
|
660
|
-
autoFocus={autoFocus && firstOption && question.options.length === 0}
|
|
661
|
-
onChange={(event) =>
|
|
662
|
-
onUpdate((current) => ({
|
|
663
|
-
...current,
|
|
664
|
-
otherSelected: event.target.checked,
|
|
665
|
-
...(question.kind === "single_select" && event.target.checked
|
|
666
|
-
? { values: [] }
|
|
667
|
-
: {}),
|
|
668
|
-
}))
|
|
669
|
-
}
|
|
670
|
-
className="mt-2 accent-og-accent"
|
|
671
|
-
/>
|
|
672
|
-
<span className="min-w-0 flex-1">
|
|
673
|
-
<label
|
|
674
|
-
id={otherLabelId}
|
|
675
|
-
htmlFor={otherChoiceId}
|
|
676
|
-
className="block text-og-sm font-medium"
|
|
677
|
-
>
|
|
678
|
-
{messages.other}
|
|
679
|
-
</label>
|
|
680
|
-
<label htmlFor={otherTextId} className="sr-only">
|
|
681
|
-
{messages.other} answer for {visibleLabel}
|
|
682
|
-
</label>
|
|
776
|
+
{!question.skillReview ? (
|
|
777
|
+
<div
|
|
778
|
+
className={cn(
|
|
779
|
+
"flex items-start gap-2.5 rounded-og-md px-2.5 py-2 transition-colors",
|
|
780
|
+
draft.otherSelected
|
|
781
|
+
? "bg-og-status-waiting/12 text-og-fg"
|
|
782
|
+
: "text-og-fg hover:bg-og-surface-1/80",
|
|
783
|
+
)}
|
|
784
|
+
>
|
|
683
785
|
<input
|
|
684
|
-
id={
|
|
685
|
-
type="
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
onChange={(event) => {
|
|
692
|
-
const other = event.target.value;
|
|
786
|
+
id={otherChoiceId}
|
|
787
|
+
type={question.kind === "single_select" ? "radio" : "checkbox"}
|
|
788
|
+
name={question.kind === "single_select" ? fieldId : undefined}
|
|
789
|
+
aria-labelledby={otherLabelId}
|
|
790
|
+
checked={draft.otherSelected}
|
|
791
|
+
autoFocus={autoFocus && firstOption && question.options.length === 0}
|
|
792
|
+
onChange={(event) =>
|
|
693
793
|
onUpdate((current) => ({
|
|
694
|
-
...
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
794
|
+
...current,
|
|
795
|
+
otherSelected: event.target.checked,
|
|
796
|
+
...(question.kind === "single_select" && event.target.checked
|
|
797
|
+
? { values: [] }
|
|
798
|
+
: {}),
|
|
799
|
+
}))
|
|
800
|
+
}
|
|
801
|
+
className="mt-2 accent-og-accent"
|
|
699
802
|
/>
|
|
700
|
-
|
|
701
|
-
|
|
803
|
+
<span className="min-w-0 flex-1">
|
|
804
|
+
<label
|
|
805
|
+
id={otherLabelId}
|
|
806
|
+
htmlFor={otherChoiceId}
|
|
807
|
+
className="block text-og-sm font-medium"
|
|
808
|
+
>
|
|
809
|
+
{messages.other}
|
|
810
|
+
</label>
|
|
811
|
+
<label htmlFor={otherTextId} className="sr-only">
|
|
812
|
+
{messages.other} answer for {visibleLabel}
|
|
813
|
+
</label>
|
|
814
|
+
<input
|
|
815
|
+
id={otherTextId}
|
|
816
|
+
type="text"
|
|
817
|
+
value={draft.other}
|
|
818
|
+
disabled={busy}
|
|
819
|
+
placeholder="Type a value…"
|
|
820
|
+
onClick={() => onUpdate(selectOtherDraft)}
|
|
821
|
+
onFocus={() => onUpdate(selectOtherDraft)}
|
|
822
|
+
onChange={(event) => {
|
|
823
|
+
const other = event.target.value;
|
|
824
|
+
onUpdate((current) => ({
|
|
825
|
+
...selectOtherDraft(current),
|
|
826
|
+
other,
|
|
827
|
+
}));
|
|
828
|
+
}}
|
|
829
|
+
className="mt-1.5 w-full rounded-og-sm border border-og-border bg-og-surface-1 px-2 py-1.5 text-og-sm text-og-fg outline-hidden focus:border-og-accent disabled:opacity-50"
|
|
830
|
+
/>
|
|
831
|
+
</span>
|
|
832
|
+
</div>
|
|
833
|
+
) : null}
|
|
702
834
|
</div>
|
|
703
835
|
)}
|
|
704
836
|
{error ? (
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from "./human-input-form";
|
|
10
10
|
|
|
11
11
|
export type HumanInputSurfaceProps = {
|
|
12
|
+
loadSkillReview?: HumanInputFormProps["loadSkillReview"];
|
|
12
13
|
requests: SessionHumanInputRequest[];
|
|
13
14
|
onSubmit: (requestId: string, response: SubmitHumanInputResponseRequest) => void | Promise<void>;
|
|
14
15
|
respondingRequestId?: string | null | undefined;
|
|
@@ -28,6 +29,7 @@ export type HumanInputSurfaceProps = {
|
|
|
28
29
|
export function HumanInputSurface({
|
|
29
30
|
requests,
|
|
30
31
|
onSubmit,
|
|
32
|
+
loadSkillReview,
|
|
31
33
|
respondingRequestId = null,
|
|
32
34
|
error,
|
|
33
35
|
messages,
|
|
@@ -68,6 +70,7 @@ export function HumanInputSurface({
|
|
|
68
70
|
|
|
69
71
|
const formProps: HumanInputFormProps = {
|
|
70
72
|
request: active,
|
|
73
|
+
loadSkillReview,
|
|
71
74
|
submitting: respondingRequestId !== null,
|
|
72
75
|
error: error ?? null,
|
|
73
76
|
progressLabel,
|