@opengeni/react 7.6.1 → 7.7.0-canary.37090756480001
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 +19 -2
- package/dist/{browser-viewer-5X47I6T2.js → browser-viewer-63TXMINB.js} +6 -5
- package/dist/{chunk-UINDK6C3.js → chunk-2QUSQVF2.js} +3 -3
- package/dist/{chunk-CHPKSLPN.js → chunk-6ZSWSH4I.js} +3 -1
- package/dist/chunk-6ZSWSH4I.js.map +1 -0
- package/dist/{chunk-KGENSZKS.js → chunk-AAG4R3QN.js} +4 -3
- package/dist/chunk-AAG4R3QN.js.map +1 -0
- package/dist/{chunk-Z3DISEQN.js → chunk-CWWKTNKK.js} +35 -18
- package/dist/chunk-CWWKTNKK.js.map +1 -0
- package/dist/{chunk-5EXGU7UF.js → chunk-DOJWJQ3F.js} +3 -3
- package/dist/{chunk-WZ55DVGK.js → chunk-ELCE5SXV.js} +8 -4
- package/dist/chunk-ELCE5SXV.js.map +1 -0
- package/dist/{chunk-YSMMDOOE.js → chunk-GISEVGS6.js} +10 -2
- package/dist/chunk-GISEVGS6.js.map +1 -0
- package/dist/{chunk-YRYF2GLG.js → chunk-HNFCAQ5R.js} +39 -31
- package/dist/chunk-HNFCAQ5R.js.map +1 -0
- package/dist/{chunk-BI57CQUV.js → chunk-I7IWRQLN.js} +2 -2
- package/dist/{chunk-XA6R7DJQ.js → chunk-IQUCRAT7.js} +3 -3
- package/dist/{chunk-DV2DBNPQ.js → chunk-Q5QBEZIQ.js} +48 -29
- package/dist/chunk-Q5QBEZIQ.js.map +1 -0
- package/dist/{chunk-FGBCYQOT.js → chunk-RDKBXMWX.js} +120 -74
- package/dist/chunk-RDKBXMWX.js.map +1 -0
- package/dist/{chunk-45GE35O7.js → chunk-TKB4SB44.js} +10 -2
- package/dist/chunk-TKB4SB44.js.map +1 -0
- package/dist/{chunk-YCGBREUV.js → chunk-TOAH2BKA.js} +6 -2
- package/dist/{chunk-YCGBREUV.js.map → chunk-TOAH2BKA.js.map} +1 -1
- package/dist/chunk-UGLEYEMP.js +33 -0
- package/dist/chunk-UGLEYEMP.js.map +1 -0
- package/dist/{chunk-UJRYEWZI.js → chunk-UTRTG6LH.js} +48 -8
- package/dist/chunk-UTRTG6LH.js.map +1 -0
- package/dist/{chunk-VGIKFIO2.js → chunk-XOAMRDDK.js} +6 -3
- package/dist/chunk-XOAMRDDK.js.map +1 -0
- package/dist/{chunk-6NEZPF53.js → chunk-YN7I3STW.js} +153 -32
- package/dist/chunk-YN7I3STW.js.map +1 -0
- package/dist/{chunk-KZ73RL76.js → chunk-YQEAA6LT.js} +7 -3
- package/dist/chunk-YQEAA6LT.js.map +1 -0
- package/dist/{chunk-LZ3KHA55.js → chunk-ZYALTAEQ.js} +329 -339
- package/dist/chunk-ZYALTAEQ.js.map +1 -0
- package/dist/client.d.ts +4 -1
- package/dist/commands/types.d.ts +2 -0
- package/dist/components/approval-surface.d.ts +15 -0
- package/dist/composer.js +8 -7
- package/dist/{computer-viewer-7GF35SNY.js → computer-viewer-X2MBRZY4.js} +5 -4
- package/dist/connect.js +3 -3
- package/dist/hooks/use-browser-session.d.ts +4 -0
- package/dist/hooks/use-composer.d.ts +2 -0
- package/dist/hooks/use-computer-session.d.ts +2 -0
- package/dist/hooks/use-file-attachments.d.ts +2 -0
- package/dist/hooks/use-session-events.d.ts +1 -1
- package/dist/hooks/use-workspace-sessions.d.ts +15 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.js +28 -21
- package/dist/index.js.map +1 -1
- package/dist/interaction.d.ts +1 -1
- package/dist/interaction.js +6 -5
- package/dist/interaction.js.map +1 -1
- package/dist/{latest-question-3BJGKQQ6.js → latest-question-CNEZ5KAN.js} +3 -3
- package/dist/lib/error-message.d.ts +7 -0
- package/dist/lib/format.d.ts +27 -3
- package/dist/lib/interaction-errors.d.ts +3 -0
- package/dist/machines.js +5 -4
- package/dist/{model-policy-picker-menu-PUTA5JOB.js → model-policy-picker-menu-JSA64TNN.js} +4 -4
- package/dist/model-policy.js +1 -1
- package/dist/provider.d.ts +5 -1
- package/dist/{queue-surface-implementation-2CAQAIHM.js → queue-surface-implementation-HENWYFWA.js} +3 -2
- package/dist/{queue-surface-implementation-2CAQAIHM.js.map → queue-surface-implementation-HENWYFWA.js.map} +1 -1
- package/dist/realtime.js +2 -2
- package/dist/{sandbox-files-AEJTWGT4.js → sandbox-files-BBC47SLD.js} +4 -3
- package/dist/session-ui.d.ts +1 -1
- package/dist/session-ui.js +13 -12
- package/dist/session-ui.js.map +1 -1
- package/dist/session.js +7 -6
- package/dist/usage.js +2 -1
- package/dist/usage.js.map +1 -1
- package/package.json +3 -3
- package/src/client.ts +5 -1
- package/src/commands/registry.ts +18 -15
- package/src/commands/types.ts +2 -0
- package/src/components/approval-surface.tsx +166 -42
- package/src/components/browser-viewer.tsx +38 -9
- package/src/components/composer.tsx +9 -2
- package/src/components/computer-viewer.tsx +160 -30
- package/src/components/generated-video-player.tsx +4 -2
- package/src/components/human-input-form.tsx +18 -5
- package/src/components/message-timeline.tsx +120 -168
- package/src/components/open-geni-chat.tsx +11 -4
- package/src/components/queue-surface-state.tsx +3 -1
- package/src/components/session-chrome.tsx +5 -2
- package/src/components/session-commands-panel.tsx +3 -1
- package/src/components/session-conversation.tsx +4 -2
- package/src/components/session-list.tsx +7 -5
- package/src/components/session-mcp-capability-card.tsx +11 -1
- package/src/hooks/internal.ts +3 -2
- package/src/hooks/use-browser-session.ts +115 -79
- package/src/hooks/use-composer.ts +70 -31
- package/src/hooks/use-computer-session.ts +57 -6
- package/src/hooks/use-file-attachments.ts +16 -3
- package/src/hooks/use-goal.ts +2 -1
- package/src/hooks/use-session-capabilities.ts +3 -2
- package/src/hooks/use-session-events.ts +15 -8
- package/src/hooks/use-slash-commands.ts +6 -11
- package/src/hooks/use-turn-queue.ts +2 -1
- package/src/hooks/use-workspace-sessions.ts +40 -7
- package/src/index.ts +7 -2
- package/src/interaction.ts +1 -0
- package/src/lib/error-message.ts +37 -0
- package/src/lib/format.ts +73 -9
- package/src/lib/interaction-errors.ts +15 -0
- package/src/model-policy.ts +5 -0
- package/src/provider.tsx +12 -4
- package/src/session-ui.ts +1 -1
- package/src/timeline/projection.ts +12 -1
- package/styles/compiled.css +14 -30
- package/dist/chunk-45GE35O7.js.map +0 -1
- package/dist/chunk-6NEZPF53.js.map +0 -1
- package/dist/chunk-CHPKSLPN.js.map +0 -1
- package/dist/chunk-DV2DBNPQ.js.map +0 -1
- package/dist/chunk-FGBCYQOT.js.map +0 -1
- package/dist/chunk-KGENSZKS.js.map +0 -1
- package/dist/chunk-KZ73RL76.js.map +0 -1
- package/dist/chunk-LZ3KHA55.js.map +0 -1
- package/dist/chunk-UJRYEWZI.js.map +0 -1
- package/dist/chunk-VGIKFIO2.js.map +0 -1
- package/dist/chunk-WZ55DVGK.js.map +0 -1
- package/dist/chunk-YRYF2GLG.js.map +0 -1
- package/dist/chunk-YSMMDOOE.js.map +0 -1
- package/dist/chunk-Z3DISEQN.js.map +0 -1
- package/dist/components/timeline-pill-geometry.d.ts +0 -8
- package/dist/components/timeline-pill-placement.d.ts +0 -24
- package/dist/timeline-pill-geometry-Z23V243M.js +0 -110
- package/dist/timeline-pill-geometry-Z23V243M.js.map +0 -1
- package/src/components/timeline-pill-geometry.ts +0 -169
- package/src/components/timeline-pill-placement.ts +0 -99
- /package/dist/{browser-viewer-5X47I6T2.js.map → browser-viewer-63TXMINB.js.map} +0 -0
- /package/dist/{chunk-UINDK6C3.js.map → chunk-2QUSQVF2.js.map} +0 -0
- /package/dist/{chunk-5EXGU7UF.js.map → chunk-DOJWJQ3F.js.map} +0 -0
- /package/dist/{chunk-BI57CQUV.js.map → chunk-I7IWRQLN.js.map} +0 -0
- /package/dist/{chunk-XA6R7DJQ.js.map → chunk-IQUCRAT7.js.map} +0 -0
- /package/dist/{computer-viewer-7GF35SNY.js.map → computer-viewer-X2MBRZY4.js.map} +0 -0
- /package/dist/{latest-question-3BJGKQQ6.js.map → latest-question-CNEZ5KAN.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-PUTA5JOB.js.map → model-policy-picker-menu-JSA64TNN.js.map} +0 -0
- /package/dist/{sandbox-files-AEJTWGT4.js.map → sandbox-files-BBC47SLD.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
PickerNavRow,
|
|
4
4
|
defaultModelPolicyPickerMessages,
|
|
5
5
|
effectiveRows
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2QUSQVF2.js";
|
|
7
7
|
import {
|
|
8
8
|
MENU_CHECK_CLASS,
|
|
9
9
|
MENU_LABEL_CLASS,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
labelReasoningEffort,
|
|
19
19
|
payerSummaryForModel,
|
|
20
20
|
runnableLatencyModesForModel
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-6ZSWSH4I.js";
|
|
22
22
|
import {
|
|
23
23
|
cn
|
|
24
24
|
} from "./chunk-22KP6LR5.js";
|
|
@@ -305,4 +305,4 @@ export {
|
|
|
305
305
|
ModelPolicyPickerMenu,
|
|
306
306
|
ModelPolicyPickerPopover
|
|
307
307
|
};
|
|
308
|
-
//# sourceMappingURL=chunk-
|
|
308
|
+
//# sourceMappingURL=chunk-DOJWJQ3F.js.map
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
usePageLiveActivity
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YQEAA6LT.js";
|
|
4
|
+
import {
|
|
5
|
+
ErrorMessageContext
|
|
6
|
+
} from "./chunk-UGLEYEMP.js";
|
|
4
7
|
import {
|
|
5
8
|
OpenGeniContext
|
|
6
9
|
} from "./chunk-NEXLLTP4.js";
|
|
@@ -19,6 +22,7 @@ function OpenGeniProvider({
|
|
|
19
22
|
onWorkspaceControlEvent,
|
|
20
23
|
onWorkspaceInteractionEvent,
|
|
21
24
|
reloadOnApiContractChange = false,
|
|
25
|
+
formatError,
|
|
22
26
|
children
|
|
23
27
|
}) {
|
|
24
28
|
const [workspaceControlEvent, setWorkspaceControlEvent] = useState(
|
|
@@ -292,10 +296,10 @@ function OpenGeniProvider({
|
|
|
292
296
|
reconcileSession
|
|
293
297
|
]
|
|
294
298
|
);
|
|
295
|
-
return /* @__PURE__ */ jsxs(OpenGeniContext.Provider, { value, children: [
|
|
299
|
+
return /* @__PURE__ */ jsx(ErrorMessageContext.Provider, { value: formatError, children: /* @__PURE__ */ jsxs(OpenGeniContext.Provider, { value, children: [
|
|
296
300
|
children,
|
|
297
301
|
contractMismatch ? /* @__PURE__ */ jsx(ApiContractMismatchScreen, { mismatch: contractMismatch }) : null
|
|
298
|
-
] });
|
|
302
|
+
] }) });
|
|
299
303
|
}
|
|
300
304
|
function withTimeout(promise, timeoutMs, label) {
|
|
301
305
|
let timer;
|
|
@@ -352,4 +356,4 @@ function reloadForContractMismatchOnce(mismatch) {
|
|
|
352
356
|
export {
|
|
353
357
|
OpenGeniProvider
|
|
354
358
|
};
|
|
355
|
-
//# sourceMappingURL=chunk-
|
|
359
|
+
//# sourceMappingURL=chunk-ELCE5SXV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx"],"sourcesContent":["import {\n OpenGeniApiContractMismatchError,\n OPENGENI_API_CONTRACT_REVISION,\n type StreamConnectionState,\n type WorkspaceControlEvent,\n type WorkspaceInteractionRevisionEvent,\n} from \"@opengeni/sdk\";\nimport { useCallback, useEffect, useMemo, useRef, useState, type ReactNode } from \"react\";\nimport type { SessionClientLike } from \"./client\";\nimport { usePageLiveActivity } from \"./hooks/internal\";\nimport { OpenGeniContext } from \"./session-context\";\nimport { ErrorMessageContext, type ErrorMessageFormatter } from \"./lib/error-message\";\n\nexport type { ErrorMessageFormatter } from \"./lib/error-message\";\n\nexport { useOpenGeni, useOpenGeniClient } from \"./session-context\";\nexport type { ClientOverride, OpenGeniContextValue } from \"./session-context\";\nconst CONTRACT_RELOAD_STORAGE_PREFIX = \"opengeni.reloadForApiContract:\";\n\nexport type OpenGeniProviderProps = {\n client: SessionClientLike;\n workspaceId: string;\n onWorkspaceControlEvent?: ((event: WorkspaceControlEvent) => void) | undefined;\n onWorkspaceInteractionEvent?: ((event: WorkspaceInteractionRevisionEvent) => void) | undefined;\n /**\n * Stale-tab protection for the stock OpenGeni web app: when the server's API\n * contract revision differs from this bundle's, cover the page and reload it\n * once. Off by default, because an embedded product's page must never be\n * blocked or reloaded when OpenGeni deploys; there a mismatch is ignored and\n * the SDK's tolerant-reader compatibility applies.\n */\n reloadOnApiContractChange?: boolean | undefined;\n /** Host-owned error copy. Receives the original diagnostic error and neutral default copy. */\n formatError?: ErrorMessageFormatter | undefined;\n children?: ReactNode;\n};\n\n/**\n * Supplies the OpenGeni client + workspace to all hooks below it. Hooks also\n * accept `{ client, workspaceId }` overrides per call for multi-workspace UIs.\n */\nexport function OpenGeniProvider({\n client,\n workspaceId,\n onWorkspaceControlEvent,\n onWorkspaceInteractionEvent,\n reloadOnApiContractChange = false,\n formatError,\n children,\n}: OpenGeniProviderProps) {\n const [workspaceControlEvent, setWorkspaceControlEvent] = useState<WorkspaceControlEvent | null>(\n null,\n );\n const [workspaceControlConnectionState, setWorkspaceControlConnectionState] = useState<\n StreamConnectionState | \"idle\" | \"error\"\n >(\"idle\");\n const [workspaceInteractionEvent, setWorkspaceInteractionEvent] =\n useState<WorkspaceInteractionRevisionEvent | null>(null);\n const [workspaceInteractionConnectionState, setWorkspaceInteractionConnectionState] = useState<\n StreamConnectionState | \"idle\" | \"error\"\n >(\"idle\");\n const [contractMismatch, setContractMismatch] = useState<OpenGeniApiContractMismatchError | null>(\n null,\n );\n const callbackRef = useRef(onWorkspaceControlEvent);\n const interactionCallbackRef = useRef(onWorkspaceInteractionEvent);\n const reconcilersRef = useRef(new Map<string, Map<string, () => Promise<void>>>());\n const reconcileInFlightRef = useRef(new Map<string, Promise<void>>());\n const workspaceControlSequencesRef = useRef(new Map<string, number>());\n const workspaceInteractionSequencesRef = useRef(new Map<string, number>());\n const pageLive = usePageLiveActivity();\n const supportsWorkspaceLiveStream =\n \"streamWorkspaceLiveEvents\" in client && typeof client.streamWorkspaceLiveEvents === \"function\";\n callbackRef.current = onWorkspaceControlEvent;\n interactionCallbackRef.current = onWorkspaceInteractionEvent;\n\n const strictContract = reloadOnApiContractChange;\n const verifyApiContract = useCallback(async (): Promise<void> => {\n try {\n const config = await client.getClientConfig();\n if (strictContract && config.apiContractRevision !== OPENGENI_API_CONTRACT_REVISION) {\n throw new OpenGeniApiContractMismatchError(\n OPENGENI_API_CONTRACT_REVISION,\n String(config.apiContractRevision || \"(missing)\"),\n );\n }\n } catch (error) {\n if (error instanceof OpenGeniApiContractMismatchError) {\n // Embedded hosts: a revision difference is not a reason to block or reload the page.\n if (!strictContract) return;\n setContractMismatch(error);\n reloadForContractMismatchOnce(error);\n }\n throw error;\n }\n }, [client, strictContract]);\n\n const registerSessionReconciler = useMemo(\n () =>\n (sessionId: string, key: string, reconcile: () => Promise<void>): (() => void) => {\n const sessionReconcilers = reconcilersRef.current.get(sessionId) ?? new Map();\n sessionReconcilers.set(key, reconcile);\n reconcilersRef.current.set(sessionId, sessionReconcilers);\n return () => {\n const current = reconcilersRef.current.get(sessionId);\n current?.delete(key);\n if (current?.size === 0) reconcilersRef.current.delete(sessionId);\n };\n },\n [],\n );\n const reconcileSession = useMemo(\n () =>\n (sessionId: string): Promise<void> => {\n const existing = reconcileInFlightRef.current.get(sessionId);\n if (existing) return existing;\n // This read also crosses the exact API-contract handshake before stale\n // state can be presented as live after a deployment.\n const promise = (async () => {\n await withTimeout(verifyApiContract(), 10_000, \"API contract reconciliation\");\n const callbacks = [...(reconcilersRef.current.get(sessionId)?.values() ?? [])];\n await withTimeout(\n Promise.all(callbacks.map((reconcile) => reconcile())).then(() => undefined),\n 15_000,\n \"session reconciliation\",\n );\n })().finally(() => {\n if (reconcileInFlightRef.current.get(sessionId) === promise) {\n reconcileInFlightRef.current.delete(sessionId);\n }\n });\n reconcileInFlightRef.current.set(sessionId, promise);\n return promise;\n },\n [verifyApiContract],\n );\n\n useEffect(() => {\n if (!supportsWorkspaceLiveStream) return;\n const openLiveStream = client.streamWorkspaceLiveEvents!;\n setWorkspaceControlEvent(null);\n setWorkspaceInteractionEvent(null);\n if (!pageLive) {\n setWorkspaceControlConnectionState(\"idle\");\n setWorkspaceInteractionConnectionState(\"idle\");\n return;\n }\n const controller = new AbortController();\n const setConnectionState = (state: StreamConnectionState) => {\n setWorkspaceControlConnectionState(state);\n setWorkspaceInteractionConnectionState(state);\n };\n setConnectionState(\"connecting\");\n void (async () => {\n try {\n await verifyApiContract();\n const workspace = await client.getWorkspace(workspaceId);\n const controlAfter = Math.max(\n workspaceControlSequencesRef.current.get(workspaceId) ?? 0,\n workspace.inferenceControl.revision,\n );\n const interactionAfter = workspaceInteractionSequencesRef.current.get(workspaceId) ?? 0;\n workspaceControlSequencesRef.current.set(workspaceId, controlAfter);\n const stream = openLiveStream.call(client, workspaceId, {\n controlAfter,\n interactionAfter,\n signal: controller.signal,\n onStateChange: setConnectionState,\n });\n for await (const event of stream) {\n if (controller.signal.aborted) return;\n if (event.type === \"workspace.control.changed\") {\n workspaceControlSequencesRef.current.set(\n workspaceId,\n Math.max(workspaceControlSequencesRef.current.get(workspaceId) ?? 0, event.sequence),\n );\n setWorkspaceControlEvent((current) =>\n !current || event.sequence > current.sequence ? event : current,\n );\n callbackRef.current?.(event);\n } else {\n workspaceInteractionSequencesRef.current.set(\n workspaceId,\n Math.max(\n workspaceInteractionSequencesRef.current.get(workspaceId) ?? 0,\n event.sequence,\n ),\n );\n setWorkspaceInteractionEvent((current) =>\n !current || event.sequence > current.sequence ? event : current,\n );\n interactionCallbackRef.current?.(event);\n }\n }\n } catch (error) {\n if (strictContract && error instanceof OpenGeniApiContractMismatchError) {\n setContractMismatch(error);\n reloadForContractMismatchOnce(error);\n }\n if (!controller.signal.aborted) {\n setWorkspaceControlConnectionState(\"error\");\n setWorkspaceInteractionConnectionState(\"error\");\n }\n }\n })();\n return () => controller.abort();\n }, [\n client,\n pageLive,\n strictContract,\n supportsWorkspaceLiveStream,\n verifyApiContract,\n workspaceId,\n ]);\n\n useEffect(() => {\n if (supportsWorkspaceLiveStream) return;\n if (!pageLive) {\n setWorkspaceControlConnectionState(\"idle\");\n return;\n }\n const controller = new AbortController();\n setWorkspaceControlConnectionState(\"connecting\");\n void (async () => {\n try {\n await verifyApiContract();\n const workspace = await client.getWorkspace(workspaceId);\n const resumeAfter = Math.max(\n workspaceControlSequencesRef.current.get(workspaceId) ?? 0,\n workspace.inferenceControl.revision,\n );\n workspaceControlSequencesRef.current.set(workspaceId, resumeAfter);\n const stream = client.streamWorkspaceControlEvents(workspaceId, {\n after: resumeAfter,\n signal: controller.signal,\n onStateChange: setWorkspaceControlConnectionState,\n });\n for await (const event of stream) {\n if (controller.signal.aborted) return;\n workspaceControlSequencesRef.current.set(\n workspaceId,\n Math.max(workspaceControlSequencesRef.current.get(workspaceId) ?? 0, event.sequence),\n );\n setWorkspaceControlEvent((current) =>\n !current || event.sequence > current.sequence ? event : current,\n );\n callbackRef.current?.(event);\n }\n } catch (error) {\n if (strictContract && error instanceof OpenGeniApiContractMismatchError) {\n setContractMismatch(error);\n reloadForContractMismatchOnce(error);\n }\n if (!controller.signal.aborted) setWorkspaceControlConnectionState(\"error\");\n }\n })();\n return () => controller.abort();\n }, [\n client,\n pageLive,\n strictContract,\n supportsWorkspaceLiveStream,\n verifyApiContract,\n workspaceId,\n ]);\n\n useEffect(() => {\n if (supportsWorkspaceLiveStream) return;\n setWorkspaceInteractionEvent(null);\n if (!pageLive) {\n setWorkspaceInteractionConnectionState(\"idle\");\n return;\n }\n const controller = new AbortController();\n setWorkspaceInteractionConnectionState(\"connecting\");\n void (async () => {\n try {\n await verifyApiContract();\n const resumeAfter = workspaceInteractionSequencesRef.current.get(workspaceId) ?? 0;\n const stream = client.streamWorkspaceInteractionRevisions(workspaceId, {\n after: resumeAfter,\n signal: controller.signal,\n onStateChange: setWorkspaceInteractionConnectionState,\n });\n for await (const event of stream) {\n if (controller.signal.aborted) return;\n workspaceInteractionSequencesRef.current.set(\n workspaceId,\n Math.max(\n workspaceInteractionSequencesRef.current.get(workspaceId) ?? 0,\n event.sequence,\n ),\n );\n setWorkspaceInteractionEvent((current) =>\n !current || event.sequence > current.sequence ? event : current,\n );\n interactionCallbackRef.current?.(event);\n }\n } catch (error) {\n if (strictContract && error instanceof OpenGeniApiContractMismatchError) {\n setContractMismatch(error);\n reloadForContractMismatchOnce(error);\n }\n if (!controller.signal.aborted) setWorkspaceInteractionConnectionState(\"error\");\n }\n })();\n return () => controller.abort();\n }, [\n client,\n pageLive,\n strictContract,\n supportsWorkspaceLiveStream,\n verifyApiContract,\n workspaceId,\n ]);\n\n const value = useMemo(\n () => ({\n client,\n workspaceId,\n workspaceControlEvent,\n workspaceControlConnectionState,\n workspaceInteractionEvent,\n workspaceInteractionConnectionState,\n registerSessionReconciler,\n reconcileSession,\n }),\n [\n client,\n workspaceId,\n workspaceControlEvent,\n workspaceControlConnectionState,\n workspaceInteractionEvent,\n workspaceInteractionConnectionState,\n registerSessionReconciler,\n reconcileSession,\n ],\n );\n return (\n <ErrorMessageContext.Provider value={formatError}>\n <OpenGeniContext.Provider value={value}>\n {children}\n {contractMismatch ? <ApiContractMismatchScreen mismatch={contractMismatch} /> : null}\n </OpenGeniContext.Provider>\n </ErrorMessageContext.Provider>\n );\n}\n\nfunction withTimeout<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined;\n return Promise.race([\n promise,\n new Promise<T>((_resolve, reject) => {\n timer = setTimeout(\n () => reject(new Error(`${label} timed out after ${timeoutMs}ms`)),\n timeoutMs,\n );\n }),\n ]).finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n });\n}\n\nfunction ApiContractMismatchScreen({ mismatch }: { mismatch: OpenGeniApiContractMismatchError }) {\n return (\n <div\n className=\"og-root fixed inset-0 z-[2147483647] grid place-items-center bg-og-bg/95 p-6 backdrop-blur-sm\"\n role=\"alert\"\n aria-live=\"assertive\"\n data-opengeni-api-contract-mismatch\n >\n <div className=\"w-full max-w-md rounded-xl border border-og-border bg-og-surface p-6 shadow-2xl\">\n <p className=\"text-og-menu font-semibold text-og-fg\">Opengeni updated</p>\n <p className=\"mt-2 text-og-menu leading-6 text-og-muted\">\n This tab cannot safely continue with the new server version. Reload it before sending or\n controlling work.\n </p>\n <p className=\"mt-3 font-mono text-og-control text-og-subtle\">\n Client {mismatch.expected} · API {mismatch.actual}\n </p>\n <button\n type=\"button\"\n className=\"mt-5 inline-flex h-9 items-center rounded-md border border-og-primary-border bg-og-primary text-og-primary-fg hover:bg-og-primary-hover px-3 text-og-menu font-medium\"\n onClick={() => window.location.reload()}\n >\n Reload now\n </button>\n </div>\n </div>\n );\n}\n\nfunction reloadForContractMismatchOnce(mismatch: OpenGeniApiContractMismatchError): void {\n if (typeof window === \"undefined\" || typeof sessionStorage === \"undefined\") return;\n const key = `${CONTRACT_RELOAD_STORAGE_PREFIX}${mismatch.actual}`;\n if (sessionStorage.getItem(key) === OPENGENI_API_CONTRACT_REVISION) return;\n sessionStorage.setItem(key, OPENGENI_API_CONTRACT_REVISION);\n window.setTimeout(() => window.location.reload(), 150);\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
usePageLiveActivity
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-YQEAA6LT.js";
|
|
4
4
|
import {
|
|
5
5
|
useEmbeddedInterventions
|
|
6
6
|
} from "./chunk-NEXLLTP4.js";
|
|
@@ -225,6 +225,13 @@ function asError(cause) {
|
|
|
225
225
|
|
|
226
226
|
// src/lib/interaction-errors.ts
|
|
227
227
|
import { OpenGeniApiError } from "@opengeni/sdk";
|
|
228
|
+
import { interactionControlFailureFromError } from "@opengeni/sdk/interaction";
|
|
229
|
+
function isInteractionControlUnavailable(error, request = "control") {
|
|
230
|
+
if (!(error instanceof OpenGeniApiError)) return false;
|
|
231
|
+
const failure = interactionControlFailureFromError(error);
|
|
232
|
+
if (failure) return failure.code === "agent_offline" || failure.code === "draining";
|
|
233
|
+
return request === "control" && !error.outcomeUnknown && (error.status >= 500 || error.status === 0);
|
|
234
|
+
}
|
|
228
235
|
function isNonRetryableInteractionError(error) {
|
|
229
236
|
return error instanceof OpenGeniApiError && error.retryable === false;
|
|
230
237
|
}
|
|
@@ -322,8 +329,9 @@ function interventionTitle(kind) {
|
|
|
322
329
|
export {
|
|
323
330
|
useInteractionInvalidation,
|
|
324
331
|
useInteractionInterventions,
|
|
332
|
+
isInteractionControlUnavailable,
|
|
325
333
|
isNonRetryableInteractionError,
|
|
326
334
|
isSourcePlacementChangedError,
|
|
327
335
|
InteractionInterventionBanner
|
|
328
336
|
};
|
|
329
|
-
//# sourceMappingURL=chunk-
|
|
337
|
+
//# sourceMappingURL=chunk-GISEVGS6.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/hooks/use-interaction-interventions.ts","../src/hooks/use-interaction-invalidation.ts","../src/lib/interaction-errors.ts","../src/components/interaction-intervention-banner.tsx"],"sourcesContent":["import type {\n CreateInteractionInterventionRequest,\n InteractionIntervention,\n InteractionInterventionMutationResponse,\n ResolveInteractionInterventionRequest,\n} from \"@opengeni/sdk/interaction\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { EmbeddedInterventionClientLike } from \"../client\";\nimport {\n type EmbeddedInterventionClientOverride,\n useEmbeddedInterventions,\n} from \"../session-context\";\nimport { useInteractionInvalidation } from \"./use-interaction-invalidation\";\n\nexport type UseInteractionInterventionsOptions = EmbeddedInterventionClientOverride & {\n enabled?: boolean | undefined;\n resourceKind?: \"browser_session\" | \"computer_session\" | undefined;\n resourceId?: string | null | undefined;\n includeSettled?: boolean | undefined;\n pollIntervalMs?: number | undefined;\n};\n\nexport type UseInteractionInterventionsResult = {\n interventions: InteractionIntervention[];\n loading: boolean;\n refreshing: boolean;\n mutating: boolean;\n error: Error | null;\n refresh: () => Promise<void>;\n create: (\n request: Omit<CreateInteractionInterventionRequest, \"operationId\"> & {\n operationId?: string;\n },\n ) => Promise<InteractionInterventionMutationResponse>;\n resolve: (\n interventionId: string,\n request: Omit<ResolveInteractionInterventionRequest, \"operationId\"> & {\n operationId?: string;\n },\n ) => Promise<InteractionInterventionMutationResponse>;\n};\n\n/** Human-action bridge shared by Browser and Computer surfaces. */\nexport function useInteractionInterventions(\n options: UseInteractionInterventionsOptions = {},\n): UseInteractionInterventionsResult {\n const { client, workspaceId, workspaceInteractionEvent, workspaceInteractionConnectionState } =\n useEmbeddedInterventions(options);\n const enabled = (options.enabled ?? true) && options.resourceId !== null;\n const resourceKind = options.resourceKind;\n const resourceId = options.resourceId ?? undefined;\n const includeSettled = options.includeSettled ?? false;\n const key = `${workspaceId}:${resourceKind ?? \"*\"}:${resourceId ?? \"*\"}:${includeSettled}`;\n const [state, setState] = useState(() => emptyState(key, enabled));\n const [mutationCount, setMutationCount] = useState(0);\n const requestRef = useRef<{ id: number; controller: AbortController | null }>({\n id: 0,\n controller: null,\n });\n const mountedRef = useRef(true);\n const visible = state.key === key ? state : emptyState(key, enabled);\n\n const cancelLoad = useCallback(() => {\n requestRef.current.controller?.abort();\n requestRef.current = { id: requestRef.current.id + 1, controller: null };\n }, []);\n\n const load = useCallback(\n async (foreground: boolean, replace = true): Promise<void> => {\n if (!enabled) return;\n if (requestRef.current.controller && !replace) return;\n const id = requestRef.current.id + 1;\n requestRef.current.controller?.abort();\n const controller = new AbortController();\n requestRef.current = { id, controller };\n if (foreground || replace) {\n setState((current) => ({\n ...(current.key === key ? current : emptyState(key, true)),\n loading: foreground,\n refreshing: !foreground,\n error: foreground ? null : current.error,\n }));\n }\n try {\n const response = await client.listInteractionInterventions(workspaceId, {\n ...(resourceKind ? { resourceKind } : {}),\n ...(resourceId ? { resourceId } : {}),\n includeSettled,\n signal: controller.signal,\n });\n if (!mountedRef.current || requestRef.current.id !== id) return;\n setState({\n key,\n interventions: sortInterventions(response.interventions),\n loading: false,\n refreshing: false,\n error: null,\n });\n } catch (cause) {\n if (controller.signal.aborted || !mountedRef.current || requestRef.current.id !== id)\n return;\n setState((current) => ({\n ...(current.key === key ? current : emptyState(key, true)),\n loading: false,\n refreshing: false,\n error: asError(cause),\n }));\n } finally {\n if (requestRef.current.id === id) requestRef.current = { id, controller: null };\n }\n },\n [client, enabled, includeSettled, key, resourceId, resourceKind, workspaceId],\n );\n\n const refresh = useCallback(async () => await load(false, true), [load]);\n\n useEffect(() => {\n mountedRef.current = true;\n if (!enabled) {\n cancelLoad();\n setState(emptyState(key, false));\n return;\n }\n void load(true);\n return () => {\n mountedRef.current = false;\n cancelLoad();\n };\n }, [cancelLoad, enabled, key, load]);\n\n useInteractionInvalidation({\n workspaceId,\n key,\n enabled,\n event: workspaceInteractionEvent,\n connectionState: workspaceInteractionConnectionState,\n refresh,\n fallbackPollIntervalMs: options.pollIntervalMs ?? 2_000,\n });\n\n const mutate = useCallback(async <T>(operation: () => Promise<T>): Promise<T> => {\n setMutationCount((count) => count + 1);\n try {\n return await operation();\n } finally {\n if (mountedRef.current) setMutationCount((count) => Math.max(0, count - 1));\n }\n }, []);\n\n const merge = useCallback(\n (intervention: InteractionIntervention) => {\n setState((current) => {\n if (current.key !== key) return current;\n const interventions = current.interventions.filter(\n (candidate) => candidate.id !== intervention.id,\n );\n const matches =\n (!resourceKind || intervention.resourceKind === resourceKind) &&\n (!resourceId || intervention.resourceId === resourceId);\n if (matches && (includeSettled || intervention.status === \"open\")) {\n interventions.push(intervention);\n }\n return {\n ...current,\n interventions: sortInterventions(interventions),\n error: null,\n };\n });\n },\n [includeSettled, key, resourceId, resourceKind],\n );\n\n const create = useCallback(\n async (\n request: Omit<CreateInteractionInterventionRequest, \"operationId\"> & {\n operationId?: string;\n },\n ): Promise<InteractionInterventionMutationResponse> =>\n await mutate(async () => {\n const response = await client.createInteractionIntervention(workspaceId, {\n ...request,\n operationId: request.operationId ?? crypto.randomUUID(),\n });\n merge(response.intervention);\n return response;\n }),\n [client, merge, mutate, workspaceId],\n );\n\n const resolve = useCallback(\n async (\n interventionId: string,\n request: Omit<ResolveInteractionInterventionRequest, \"operationId\"> & {\n operationId?: string;\n },\n ): Promise<InteractionInterventionMutationResponse> =>\n await mutate(async () => {\n const response = await client.resolveInteractionIntervention(workspaceId, interventionId, {\n ...request,\n operationId: request.operationId ?? crypto.randomUUID(),\n });\n merge(response.intervention);\n return response;\n }),\n [client, merge, mutate, workspaceId],\n );\n\n return {\n interventions: visible.interventions,\n loading: visible.loading,\n refreshing: visible.refreshing,\n mutating: mutationCount > 0,\n error: visible.error,\n refresh,\n create,\n resolve,\n };\n}\n\nfunction emptyState(key: string, loading: boolean) {\n return {\n key,\n interventions: [] as InteractionIntervention[],\n loading,\n refreshing: false,\n error: null as Error | null,\n };\n}\n\nfunction sortInterventions(\n interventions: readonly InteractionIntervention[],\n): InteractionIntervention[] {\n return [...interventions].sort(\n (left, right) => Date.parse(right.updatedAt) - Date.parse(left.updatedAt),\n );\n}\n\nfunction asError(cause: unknown): Error {\n return cause instanceof Error ? cause : new Error(String(cause));\n}\n\nexport type InteractionInterventionsClient = EmbeddedInterventionClientLike;\n","import type { StreamConnectionState, WorkspaceInteractionRevisionEvent } from \"@opengeni/sdk\";\nimport { useEffect, useRef } from \"react\";\nimport { usePageLiveActivity } from \"./internal\";\n\nexport type InteractionInvalidationOptions = {\n workspaceId: string;\n /** Distinguishes filtered projections of the same workspace catalog. */\n key: string;\n enabled: boolean;\n event: WorkspaceInteractionRevisionEvent | null;\n connectionState: StreamConnectionState | \"idle\" | \"error\";\n /** Catalog responses carry the workspace revision; live-state lists do not. */\n knownRevision?: number | undefined;\n refresh: () => Promise<void>;\n fallbackPollIntervalMs?: number | undefined;\n};\n\n/**\n * Refetch authoritative lists on the shared latest-revision stream. Poll only\n * while that stream is unavailable, preserving standalone-hook degradation\n * without multiplying healthy-provider traffic.\n */\nexport function useInteractionInvalidation(options: InteractionInvalidationOptions): void {\n const {\n workspaceId,\n key,\n enabled,\n event,\n connectionState,\n knownRevision,\n refresh,\n fallbackPollIntervalMs,\n } = options;\n const pageLive = usePageLiveActivity();\n const lastUnversionedEvent = useRef<{ key: string; sequence: number }>({\n key,\n sequence: 0,\n });\n const eventSequence = event?.workspaceId === workspaceId ? event.sequence : 0;\n\n useEffect(() => {\n if (!enabled || eventSequence <= 0) return;\n if (knownRevision !== undefined) {\n if (eventSequence > knownRevision) void refresh();\n return;\n }\n if (lastUnversionedEvent.current.key !== key) {\n lastUnversionedEvent.current = { key, sequence: 0 };\n }\n if (eventSequence <= lastUnversionedEvent.current.sequence) return;\n lastUnversionedEvent.current = { key, sequence: eventSequence };\n void refresh();\n }, [enabled, eventSequence, key, knownRevision, refresh]);\n\n useEffect(() => {\n if (!enabled || !pageLive || connectionState === \"live\") return;\n const interval = boundedPollInterval(fallbackPollIntervalMs ?? 3_000);\n const timer = setInterval(() => void refresh(), interval);\n return () => clearInterval(timer);\n }, [connectionState, enabled, fallbackPollIntervalMs, pageLive, refresh]);\n}\n\nfunction boundedPollInterval(value: number): number {\n if (!Number.isFinite(value)) return 3_000;\n return Math.min(60_000, Math.max(1_000, Math.floor(value)));\n}\n","import { OpenGeniApiError } from \"@opengeni/sdk\";\nimport { interactionControlFailureFromError } from \"@opengeni/sdk/interaction\";\n\n/** Media can remain live when the independent control service is unavailable.\n * A target refusal or an uncertain mutation does not establish a service outage. */\nexport function isInteractionControlUnavailable(\n error: unknown,\n request: \"control\" | \"observation\" = \"control\",\n): error is OpenGeniApiError {\n if (!(error instanceof OpenGeniApiError)) return false;\n const failure = interactionControlFailureFromError(error);\n if (failure) return failure.code === \"agent_offline\" || failure.code === \"draining\";\n return (\n request === \"control\" && !error.outcomeUnknown && (error.status >= 500 || error.status === 0)\n );\n}\n\nexport function isNonRetryableInteractionError(error: unknown): error is OpenGeniApiError {\n return error instanceof OpenGeniApiError && error.retryable === false;\n}\n\nexport function isSourcePlacementChangedError(\n error: unknown,\n resource: \"browser_session\" | \"computer_session\",\n): error is OpenGeniApiError {\n return (\n isNonRetryableInteractionError(error) &&\n error.status === 409 &&\n error.details?.interactionResource === resource &&\n error.details?.interactionFailureCode === \"source_placement_changed\" &&\n error.details?.interactionLifecycle === \"lost\"\n );\n}\n","import type { InteractionIntervention } from \"@opengeni/sdk/interaction\";\nimport { CheckIcon, CircleAlertIcon, LoaderCircleIcon, XIcon } from \"lucide-react\";\nimport { cn } from \"../lib/cn\";\n\nexport type InteractionInterventionBannerProps = {\n interventions: InteractionIntervention[];\n activeTargetId?: string | null | undefined;\n mutating?: boolean | undefined;\n className?: string | undefined;\n onOpen?: ((intervention: InteractionIntervention) => void) | undefined;\n onResolve: (intervention: InteractionIntervention, outcome: \"completed\" | \"dismissed\") => void;\n};\n\n/** Compact durable human-action prompt shared by Browser and Computer viewers. */\nexport function InteractionInterventionBanner({\n interventions,\n activeTargetId,\n mutating = false,\n className,\n onOpen,\n onResolve,\n}: InteractionInterventionBannerProps) {\n const intervention = interventions[0];\n if (!intervention) return null;\n const targetOpen = activeTargetId === undefined || activeTargetId === intervention.targetId;\n return (\n <div\n className={cn(\n \"flex shrink-0 items-center gap-2 border-b border-og-status-waiting/25 bg-og-status-waiting/[0.07] px-3 py-2\",\n className,\n )}\n role=\"status\"\n >\n <span className=\"grid size-7 shrink-0 place-items-center rounded-og-sm bg-og-status-waiting/10 text-og-status-waiting\">\n <CircleAlertIcon className=\"size-3.5\" />\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"flex items-center gap-1.5 text-og-control font-medium text-og-fg\">\n {interventionTitle(intervention.kind)}\n {interventions.length > 1 ? (\n <span className=\"rounded-full bg-og-surface-2 px-1.5 py-0.5 text-[10px] font-normal text-og-muted\">\n +{interventions.length - 1}\n </span>\n ) : null}\n </span>\n <span className=\"block truncate text-og-xs text-og-muted\">{intervention.reason}</span>\n </span>\n {!targetOpen && onOpen ? (\n <button\n type=\"button\"\n onClick={() => onOpen(intervention)}\n disabled={mutating}\n className=\"h-7 shrink-0 rounded-og-sm border border-og-primary-border bg-og-primary px-2.5 text-og-control font-medium text-og-primary-fg transition hover:bg-og-primary-hover disabled:opacity-50\"\n >\n Open\n </button>\n ) : (\n <button\n type=\"button\"\n onClick={() => onResolve(intervention, \"completed\")}\n disabled={mutating}\n className=\"inline-flex h-7 shrink-0 items-center gap-1 rounded-og-sm border border-og-primary-border bg-og-primary text-og-primary-fg px-2.5 text-og-control font-medium transition hover:bg-og-primary-hover disabled:opacity-50\"\n >\n {mutating ? (\n <LoaderCircleIcon className=\"size-3 animate-spin\" />\n ) : (\n <CheckIcon className=\"size-3\" />\n )}\n Done\n </button>\n )}\n <button\n type=\"button\"\n onClick={() => onResolve(intervention, \"dismissed\")}\n disabled={mutating}\n className=\"grid size-7 shrink-0 place-items-center rounded-og-sm text-og-muted transition hover:bg-og-surface-2 hover:text-og-fg disabled:opacity-50\"\n aria-label=\"Cancel request\"\n title=\"Cancel request\"\n >\n <XIcon className=\"size-3.5\" />\n </button>\n </div>\n );\n}\n\nfunction interventionTitle(kind: InteractionIntervention[\"kind\"]): string {\n switch (kind) {\n case \"manual_login\":\n return \"Sign in needed\";\n case \"mfa\":\n return \"Verification needed\";\n case \"external_action\":\n return \"Action needed\";\n case \"confirmation\":\n return \"Confirmation needed\";\n case \"other\":\n return \"Agent needs your help\";\n }\n}\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
shouldSteerOnKey,
|
|
3
3
|
shouldSubmitOnKey
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Q5QBEZIQ.js";
|
|
5
5
|
import {
|
|
6
6
|
Tooltip,
|
|
7
7
|
TooltipContent,
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-BRM6FVZA.js";
|
|
12
12
|
import {
|
|
13
13
|
groupPickerRowsByBillingClass
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-6ZSWSH4I.js";
|
|
15
15
|
import {
|
|
16
16
|
ComposerResponsiveContext
|
|
17
17
|
} from "./chunk-VZTQ73XT.js";
|
|
@@ -19,7 +19,10 @@ import {
|
|
|
19
19
|
composerSubmissionErrorMessage,
|
|
20
20
|
formatBytes,
|
|
21
21
|
formatRelativeTime
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-UTRTG6LH.js";
|
|
23
|
+
import {
|
|
24
|
+
useErrorMessage
|
|
25
|
+
} from "./chunk-UGLEYEMP.js";
|
|
23
26
|
import {
|
|
24
27
|
cn
|
|
25
28
|
} from "./chunk-22KP6LR5.js";
|
|
@@ -28,6 +31,7 @@ import {
|
|
|
28
31
|
var OPEN_WORKSTREAM_CONTROL_EVENT = "opengeni:open-workstream-control";
|
|
29
32
|
|
|
30
33
|
// src/commands/registry.ts
|
|
34
|
+
import { formatErrorMessage } from "@opengeni/sdk";
|
|
31
35
|
function parseCommandLine(value) {
|
|
32
36
|
if (value[0] !== "/") {
|
|
33
37
|
return null;
|
|
@@ -146,7 +150,10 @@ var defaultCommands = [
|
|
|
146
150
|
});
|
|
147
151
|
return { status: "ok", message: action === "pause" ? "Goal paused." : "Goal resumed." };
|
|
148
152
|
} catch (cause) {
|
|
149
|
-
return {
|
|
153
|
+
return {
|
|
154
|
+
status: "error",
|
|
155
|
+
message: commandErrorMessage(ctx, cause, goalErrorMessage(cause, action))
|
|
156
|
+
};
|
|
150
157
|
}
|
|
151
158
|
}
|
|
152
159
|
},
|
|
@@ -161,7 +168,7 @@ var defaultCommands = [
|
|
|
161
168
|
const result = await ctx.client.compactSessionContext(ctx.workspaceId, sessionId);
|
|
162
169
|
return { status: "ok", message: result.message };
|
|
163
170
|
} catch (cause) {
|
|
164
|
-
return { status: "error", message:
|
|
171
|
+
return { status: "error", message: commandErrorMessage(ctx, cause) };
|
|
165
172
|
}
|
|
166
173
|
}
|
|
167
174
|
},
|
|
@@ -181,16 +188,16 @@ var defaultCommands = [
|
|
|
181
188
|
await ctx.client.clearSessionContext(ctx.workspaceId, sessionId);
|
|
182
189
|
return { status: "ok", message: "Context cleared." };
|
|
183
190
|
} catch (cause) {
|
|
184
|
-
return {
|
|
191
|
+
return {
|
|
192
|
+
status: "error",
|
|
193
|
+
message: commandErrorMessage(ctx, cause, clearErrorMessage(cause))
|
|
194
|
+
};
|
|
185
195
|
}
|
|
186
196
|
}
|
|
187
197
|
}
|
|
188
198
|
];
|
|
189
|
-
function
|
|
190
|
-
|
|
191
|
-
return cause.message;
|
|
192
|
-
}
|
|
193
|
-
return void 0;
|
|
199
|
+
function commandErrorMessage(ctx, cause, message = formatErrorMessage(cause)) {
|
|
200
|
+
return ctx.formatError?.(cause, message) || message;
|
|
194
201
|
}
|
|
195
202
|
function statusCode(cause) {
|
|
196
203
|
if (cause && typeof cause === "object" && "status" in cause && typeof cause.status === "number") {
|
|
@@ -206,18 +213,19 @@ function goalErrorMessage(cause, action) {
|
|
|
206
213
|
if (code === 409) {
|
|
207
214
|
return action === "resume" ? "Only a paused goal can be resumed." : "Goal is already in a terminal state.";
|
|
208
215
|
}
|
|
209
|
-
return
|
|
216
|
+
return formatErrorMessage(cause);
|
|
210
217
|
}
|
|
211
218
|
function clearErrorMessage(cause) {
|
|
212
219
|
if (statusCode(cause) === 409) {
|
|
213
220
|
return "Pause the session and wait for the current inference to settle, then clear context.";
|
|
214
221
|
}
|
|
215
|
-
return
|
|
222
|
+
return formatErrorMessage(cause);
|
|
216
223
|
}
|
|
217
224
|
|
|
218
225
|
// src/hooks/use-slash-commands.ts
|
|
219
226
|
import { useCallback, useMemo, useRef, useState } from "react";
|
|
220
227
|
function useSlashCommands(options) {
|
|
228
|
+
const formatError = useErrorMessage();
|
|
221
229
|
const { commands, context, handlers, value, setValue } = options;
|
|
222
230
|
const [highlight, setHighlight] = useState(0);
|
|
223
231
|
const [dismissedValue, setDismissedValue] = useState(null);
|
|
@@ -261,9 +269,9 @@ function useSlashCommands(options) {
|
|
|
261
269
|
if (!context) {
|
|
262
270
|
return null;
|
|
263
271
|
}
|
|
264
|
-
return { ...context, ...handlers, confirm: () => handlers.confirm(command) };
|
|
272
|
+
return { ...context, ...handlers, formatError, confirm: () => handlers.confirm(command) };
|
|
265
273
|
},
|
|
266
|
-
[context, handlers]
|
|
274
|
+
[context, handlers, formatError]
|
|
267
275
|
);
|
|
268
276
|
const execute = useCallback(
|
|
269
277
|
async (command, args) => {
|
|
@@ -280,10 +288,10 @@ function useSlashCommands(options) {
|
|
|
280
288
|
setValue("");
|
|
281
289
|
}
|
|
282
290
|
} catch (cause) {
|
|
283
|
-
ctx.notice({ tone: "error", message:
|
|
291
|
+
ctx.notice({ tone: "error", message: formatError(cause) });
|
|
284
292
|
}
|
|
285
293
|
},
|
|
286
|
-
[buildContext, setValue]
|
|
294
|
+
[buildContext, setValue, formatError]
|
|
287
295
|
);
|
|
288
296
|
const autocomplete = useCallback(
|
|
289
297
|
(command) => {
|
|
@@ -417,12 +425,6 @@ function useSlashCommands(options) {
|
|
|
417
425
|
autocompleteHighlighted
|
|
418
426
|
};
|
|
419
427
|
}
|
|
420
|
-
function errorMessage2(cause) {
|
|
421
|
-
if (cause instanceof Error) {
|
|
422
|
-
return cause.message;
|
|
423
|
-
}
|
|
424
|
-
return String(cause);
|
|
425
|
-
}
|
|
426
428
|
|
|
427
429
|
// src/components/command-palette.tsx
|
|
428
430
|
import { AnimatePresence, motion } from "motion/react";
|
|
@@ -647,7 +649,9 @@ var defaultChatComposerMessages = {
|
|
|
647
649
|
messagePlaceholder: "Message the agent\u2026",
|
|
648
650
|
pausedPlaceholder: "Message the agent \u2014 it will wait in the queue\u2026",
|
|
649
651
|
inputLabel: "Message the agent",
|
|
650
|
-
|
|
652
|
+
// Shortcuts live in the send button's title; the footer stays quiet unless
|
|
653
|
+
// the host supplies its own hint.
|
|
654
|
+
keyboardHint: "",
|
|
651
655
|
slashCommandBlocked: "That's a slash command \u2014 press Enter in the command list to run it, or edit the line to send a message.",
|
|
652
656
|
controlChangedError: "This workstream was paused while you were sending. Nothing was sent, and your draft is still here.",
|
|
653
657
|
sendFailedError: "Sending failed \u2014 your draft is still here. Try again.",
|
|
@@ -784,6 +788,7 @@ function useChatComposerController({
|
|
|
784
788
|
onPaste,
|
|
785
789
|
messages: messageOverrides
|
|
786
790
|
}) {
|
|
791
|
+
const formatError = useErrorMessage();
|
|
787
792
|
const messages = useMemo3(
|
|
788
793
|
() => ({ ...defaultChatComposerMessages, ...messageOverrides }),
|
|
789
794
|
[messageOverrides]
|
|
@@ -1027,7 +1032,10 @@ function useChatComposerController({
|
|
|
1027
1032
|
);
|
|
1028
1033
|
const activeNotice = notice ?? (delivery.error ? {
|
|
1029
1034
|
tone: "error",
|
|
1030
|
-
message: /control changed|paused while/i.test(delivery.error.message) ? messages.controlChangedError :
|
|
1035
|
+
message: /control changed|paused while/i.test(delivery.error.message) ? messages.controlChangedError : formatError(
|
|
1036
|
+
delivery.error,
|
|
1037
|
+
composerSubmissionErrorMessage(delivery.error) || messages.sendFailedError
|
|
1038
|
+
)
|
|
1031
1039
|
} : null);
|
|
1032
1040
|
useEffect(() => {
|
|
1033
1041
|
if (notice?.tone !== "ok") return;
|
|
@@ -4336,8 +4344,8 @@ function ComposerTranscriptionControl({
|
|
|
4336
4344
|
const savedTranscript = status === "transcript-ready" && transcription.savedTranscript !== null;
|
|
4337
4345
|
const unavailableMessage = composer.disabled ? messages.unavailableDisabled : !capability?.available || !workspaceEnabled ? messages.unavailable : !transcription.available ? messages.errorStorageUnavailable : null;
|
|
4338
4346
|
const idleLabel = unavailableMessage ?? (status === "error" ? messages.retry : messages.start);
|
|
4339
|
-
const
|
|
4340
|
-
const announcement = status === "requesting-permission" ? messages.requestingPermission : status === "recording" ? messages.recording : status === "saving" ? messages.saving : status === "transcribing" ? messages.transcribing : retrying ? messages.retrying : status === "recovered" ? messages.recovered : status === "transcript-ready" ? messages.recoveredTranscript : status === "error" ?
|
|
4347
|
+
const errorMessage = transcription.error ? transcriptionErrorMessage(transcription.error, messages) : null;
|
|
4348
|
+
const announcement = status === "requesting-permission" ? messages.requestingPermission : status === "recording" ? messages.recording : status === "saving" ? messages.saving : status === "transcribing" ? messages.transcribing : retrying ? messages.retrying : status === "recovered" ? messages.recovered : status === "transcript-ready" ? messages.recoveredTranscript : status === "error" ? errorMessage ?? messages.errorUnknown : unavailableMessage;
|
|
4341
4349
|
function start(event) {
|
|
4342
4350
|
if (unavailableMessage) {
|
|
4343
4351
|
event.preventDefault();
|
|
@@ -4374,7 +4382,7 @@ function ComposerTranscriptionControl({
|
|
|
4374
4382
|
"bg-og-surface-2/70 pl-2 pr-1 pointer-coarse:h-11"
|
|
4375
4383
|
),
|
|
4376
4384
|
children: [
|
|
4377
|
-
/* @__PURE__ */ jsx4("span", { className: "og-transcription-recovered-label max-w-44 truncate text-og-xs text-og-fg-muted max-sm:max-w-28", children: savedTranscript ?
|
|
4385
|
+
/* @__PURE__ */ jsx4("span", { className: "og-transcription-recovered-label max-w-44 truncate text-og-xs text-og-fg-muted max-sm:max-w-28", children: savedTranscript ? errorMessage ?? messages.recoveredTranscript : retrying ? messages.retrying : status === "error" ? errorMessage ?? messages.errorRetryable : messages.recovered }),
|
|
4378
4386
|
/* @__PURE__ */ jsx4(
|
|
4379
4387
|
Tip,
|
|
4380
4388
|
{
|
|
@@ -4503,12 +4511,12 @@ function ComposerTranscriptionControl({
|
|
|
4503
4511
|
children: /* @__PURE__ */ jsx4(MicIcon, { className: "size-4" })
|
|
4504
4512
|
}
|
|
4505
4513
|
) }, "idle") }),
|
|
4506
|
-
status === "error" &&
|
|
4514
|
+
status === "error" && errorMessage && !recoverable ? /* @__PURE__ */ jsx4(Tip, { tip: errorMessage, children: /* @__PURE__ */ jsx4(
|
|
4507
4515
|
"span",
|
|
4508
4516
|
{
|
|
4509
4517
|
"aria-hidden": "true",
|
|
4510
4518
|
className: "og-transcription-error-label max-w-40 truncate text-og-xs text-og-status-failed max-sm:max-w-24",
|
|
4511
|
-
children:
|
|
4519
|
+
children: errorMessage
|
|
4512
4520
|
}
|
|
4513
4521
|
) }) : null,
|
|
4514
4522
|
/* @__PURE__ */ jsx4(
|
|
@@ -4691,4 +4699,4 @@ export {
|
|
|
4691
4699
|
useVoiceInput,
|
|
4692
4700
|
ComposerTranscriptionControl
|
|
4693
4701
|
};
|
|
4694
|
-
//# sourceMappingURL=chunk-
|
|
4702
|
+
//# sourceMappingURL=chunk-HNFCAQ5R.js.map
|