@opengeni/react 1.4.4 → 1.4.5-canary.37485542607001
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 +17 -6
- package/dist/artifacts.d.ts +1 -0
- package/dist/artifacts.js +22 -15
- package/dist/artifacts.js.map +1 -1
- package/dist/{browser-viewer-5EEAS3IU.js → browser-viewer-CV23VIHB.js} +8 -6
- package/dist/{chunk-XS67YG5R.js → chunk-4O7OE7ON.js} +45 -4
- package/dist/chunk-4O7OE7ON.js.map +1 -0
- package/dist/{chunk-JHTIMBOL.js → chunk-5JSUNNQN.js} +26 -4
- package/dist/{chunk-JHTIMBOL.js.map → chunk-5JSUNNQN.js.map} +1 -1
- package/dist/{chunk-QMMCJGFI.js → chunk-6BAMPGBV.js} +6 -3
- package/dist/chunk-6BAMPGBV.js.map +1 -0
- package/dist/{chunk-I6OY3MWC.js → chunk-6FOTSVWU.js} +2 -2
- package/dist/{chunk-LVS3MH5T.js → chunk-ATIRUHBZ.js} +128 -10
- package/dist/chunk-ATIRUHBZ.js.map +1 -0
- package/dist/chunk-BOFEQC6K.js +162 -0
- package/dist/chunk-BOFEQC6K.js.map +1 -0
- package/dist/{chunk-2OQA3CPB.js → chunk-CESBPQP5.js} +19 -5
- package/dist/chunk-CESBPQP5.js.map +1 -0
- package/dist/{chunk-YVFRBXST.js → chunk-GMNGUPMX.js} +2 -2
- package/dist/{chunk-PHBFJCEU.js → chunk-I5EGRXXG.js} +110 -7
- package/dist/chunk-I5EGRXXG.js.map +1 -0
- package/dist/{chunk-PBCZL4JP.js → chunk-INIZSNXT.js} +2 -2
- package/dist/chunk-IZV5FTJC.js +55 -0
- package/dist/chunk-IZV5FTJC.js.map +1 -0
- package/dist/chunk-JDJJMBB3.js +1883 -0
- package/dist/chunk-JDJJMBB3.js.map +1 -0
- package/dist/chunk-LHF6BVM4.js +83 -0
- package/dist/chunk-LHF6BVM4.js.map +1 -0
- package/dist/{chunk-C5BF4L26.js → chunk-LSMWZSCJ.js} +7 -7
- package/dist/chunk-LTKGTXUQ.js +174 -0
- package/dist/chunk-LTKGTXUQ.js.map +1 -0
- package/dist/chunk-N7S72EXK.js +25 -0
- package/dist/chunk-N7S72EXK.js.map +1 -0
- package/dist/{chunk-CVYCLFMH.js → chunk-PEHTX3V7.js} +19 -1
- package/dist/chunk-PEHTX3V7.js.map +1 -0
- package/dist/chunk-R5R5RQQD.js +51 -0
- package/dist/chunk-R5R5RQQD.js.map +1 -0
- package/dist/{chunk-IYQCWGU5.js → chunk-RGTZ2VDR.js} +35 -62
- package/dist/chunk-RGTZ2VDR.js.map +1 -0
- package/dist/chunk-RI42H5IU.js +326 -0
- package/dist/chunk-RI42H5IU.js.map +1 -0
- package/dist/{chunk-EAOSEIXB.js → chunk-RRRS5D5T.js} +727 -1983
- package/dist/chunk-RRRS5D5T.js.map +1 -0
- package/dist/{chunk-JH7V627O.js → chunk-SHLZMAJN.js} +2 -11
- package/dist/chunk-SHLZMAJN.js.map +1 -0
- package/dist/{chunk-IUHHPMAX.js → chunk-SZOCY5VG.js} +18 -87
- package/dist/chunk-SZOCY5VG.js.map +1 -0
- package/dist/{chunk-L2J3PU7A.js → chunk-VYIPNDUZ.js} +29 -100
- package/dist/chunk-VYIPNDUZ.js.map +1 -0
- package/dist/{chunk-G6YRCIYJ.js → chunk-YK6QMGVL.js} +55 -60
- package/dist/chunk-YK6QMGVL.js.map +1 -0
- package/dist/chunk-ZIB4H5LN.js +101 -0
- package/dist/chunk-ZIB4H5LN.js.map +1 -0
- package/dist/client.d.ts +9 -3
- package/dist/clipboard.js +1 -1
- package/dist/components/browser-viewer.d.ts +6 -0
- package/dist/components/composer.d.ts +3 -69
- package/dist/components/human-input-form.d.ts +3 -32
- package/dist/components/markdown.d.ts +8 -0
- package/dist/components/model-policy-picker.d.ts +4 -37
- package/dist/components/opper-mark.d.ts +7 -0
- package/dist/components/provider-recovery-notice.d.ts +15 -0
- package/dist/components/remark-soft-line-breaks.d.ts +38 -0
- package/dist/components/sandbox-workspace.d.ts +13 -0
- package/dist/components/session-chrome.d.ts +5 -3
- package/dist/components/session-conversation.d.ts +15 -3
- package/dist/composer-messages.d.ts +74 -0
- package/dist/composer-messages.js +9 -0
- package/dist/composer.js +15 -10
- package/dist/{computer-viewer-ELNLZGHI.js → computer-viewer-K4CKYRX6.js} +4 -4
- package/dist/connect-setup.d.ts +2 -0
- package/dist/connect.d.ts +1 -1
- package/dist/connect.js +21 -6
- package/dist/connect.js.map +1 -1
- package/dist/{embedded-voice-NIL4RDX3.js → embedded-voice-K7SOZVVZ.js} +6 -4
- package/dist/{embedded-voice-NIL4RDX3.js.map → embedded-voice-K7SOZVVZ.js.map} +1 -1
- package/dist/hooks/shared-machines-list.d.ts +4 -0
- package/dist/hooks/use-client-config-flags.d.ts +6 -0
- package/dist/hooks/use-goal.d.ts +2 -1
- package/dist/hooks/use-new-session-draft.d.ts +74 -0
- package/dist/human-input-model.d.ts +40 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +116 -73
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +5 -5
- package/dist/{latest-question-2POFPYNB.js → latest-question-27HGRPVF.js} +3 -3
- package/dist/lib/clipboard.d.ts +7 -0
- package/dist/lib/provider-recovery.d.ts +49 -0
- package/dist/lib/transient-retry.d.ts +25 -0
- package/dist/machines.js +2 -2
- package/dist/model-mark-paths.d.ts +34 -0
- package/dist/model-mark-paths.js +16 -0
- package/dist/model-picker-model.d.ts +111 -0
- package/dist/model-picker-model.js +25 -0
- package/dist/model-picker-model.js.map +1 -0
- package/dist/{model-policy-picker-menu-WRNSRFQC.js → model-policy-picker-menu-I5KPC3D6.js} +6 -4
- package/dist/model-policy-picker-menu-I5KPC3D6.js.map +1 -0
- package/dist/model-policy.d.ts +10 -0
- package/dist/model-policy.js +5 -1
- package/dist/new-session-draft.d.ts +7 -0
- package/dist/new-session-draft.js +639 -0
- package/dist/new-session-draft.js.map +1 -0
- package/dist/organization-model.d.ts +32 -0
- package/dist/organization-model.js +65 -0
- package/dist/organization-model.js.map +1 -0
- package/dist/{platform-activity-row-PJJVATTZ.js → platform-activity-row-NJ47YBXW.js} +7 -84
- package/dist/platform-activity-row-NJ47YBXW.js.map +1 -0
- package/dist/queue-presentation-model.d.ts +72 -0
- package/dist/queue-presentation-model.js +38 -0
- package/dist/queue-presentation-model.js.map +1 -0
- package/dist/{queue-surface-implementation-67FS7FUI.js → queue-surface-implementation-YPJFQ3O6.js} +24 -252
- package/dist/queue-surface-implementation-YPJFQ3O6.js.map +1 -0
- package/dist/realtime.js +5 -3
- package/dist/{sandbox-files-34CJJNOY.js → sandbox-files-2DGDO6NI.js} +5 -5
- package/dist/sandbox-files-2DGDO6NI.js.map +1 -0
- package/dist/sandbox-label-model.d.ts +23 -0
- package/dist/sandbox-label-model.js +28 -0
- package/dist/sandbox-label-model.js.map +1 -0
- package/dist/session-agents-model.d.ts +10 -0
- package/dist/session-agents-model.js +25 -0
- package/dist/session-agents-model.js.map +1 -0
- package/dist/session-attention-model.d.ts +8 -0
- package/dist/session-attention-model.js +46 -0
- package/dist/session-attention-model.js.map +1 -0
- package/dist/session-feedback-model.d.ts +20 -0
- package/dist/session-feedback-model.js +56 -0
- package/dist/session-feedback-model.js.map +1 -0
- package/dist/session-list-model.d.ts +119 -0
- package/dist/session-list-model.js +244 -0
- package/dist/session-list-model.js.map +1 -0
- package/dist/session-status-model.d.ts +19 -0
- package/dist/session-ui.js +26 -17
- package/dist/session-ui.js.map +1 -1
- package/dist/session.js +8 -6
- package/dist/testing/session-scenarios.d.ts +10 -0
- package/dist/testing/session-scenarios.js +303 -0
- package/dist/testing/session-scenarios.js.map +1 -0
- package/dist/timeline/genie-copy.d.ts +3 -0
- package/dist/timeline/genie-loading.d.ts +11 -0
- package/dist/timeline/index.d.ts +1 -1
- package/dist/timeline/notice-presentation.d.ts +7 -0
- package/dist/timeline/patch-apply-command.d.ts +18 -0
- package/dist/timeline/platform-activity-presentation.d.ts +7 -0
- package/dist/timeline/presented-image.d.ts +6 -1
- package/dist/timeline/question-nav-model.d.ts +23 -0
- package/dist/timeline/registry.d.ts +10 -1
- package/dist/timeline/retained-loaders.d.ts +1 -1
- package/dist/timeline/tool-presentation.d.ts +172 -0
- package/dist/timeline/turn-summary-model.d.ts +90 -0
- package/dist/timeline/turn-summary.d.ts +4 -74
- package/dist/timeline/work-presentation.d.ts +42 -0
- package/dist/timeline-model.d.ts +24 -0
- package/dist/timeline-model.js +152 -0
- package/dist/timeline-model.js.map +1 -0
- package/package.json +55 -3
- package/src/artifacts.ts +1 -0
- package/src/client.ts +9 -3
- package/src/components/browser-viewer.tsx +23 -2
- package/src/components/claude-mark.tsx +2 -1
- package/src/components/composer.tsx +8 -146
- package/src/components/grok-mark.tsx +2 -1
- package/src/components/human-input-form.tsx +13 -124
- package/src/components/markdown.tsx +19 -1
- package/src/components/message-timeline.tsx +45 -99
- package/src/components/model-mark.tsx +2 -1
- package/src/components/model-policy-picker-menu.tsx +30 -85
- package/src/components/model-policy-picker.tsx +20 -150
- package/src/components/opper-mark.tsx +18 -0
- package/src/components/provider-recovery-notice.tsx +41 -0
- package/src/components/queue-surface-implementation.tsx +20 -349
- package/src/components/remark-soft-line-breaks.ts +166 -0
- package/src/components/sandbox-workspace.tsx +17 -1
- package/src/components/session-chrome.tsx +114 -99
- package/src/components/session-conversation.tsx +55 -6
- package/src/components/session-status.tsx +17 -16
- package/src/composer-messages.ts +150 -0
- package/src/connect-setup.tsx +45 -11
- package/src/connect.ts +1 -1
- package/src/hooks/shared-machines-list.ts +34 -1
- package/src/hooks/use-client-config-flags.ts +8 -0
- package/src/hooks/use-goal.ts +66 -10
- package/src/hooks/use-new-session-draft.ts +813 -0
- package/src/human-input-model.ts +147 -0
- package/src/index.ts +16 -0
- package/src/lib/clipboard.ts +29 -0
- package/src/lib/format.ts +7 -0
- package/src/lib/provider-recovery.ts +202 -0
- package/src/lib/transient-retry.ts +99 -0
- package/src/model-mark-paths.ts +53 -0
- package/src/model-picker-model.ts +330 -0
- package/src/model-policy.ts +75 -5
- package/src/new-session-draft.ts +22 -0
- package/src/organization-model.ts +118 -0
- package/src/queue-presentation-model.ts +464 -0
- package/src/sandbox-label-model.ts +41 -0
- package/src/session-agents-model.ts +33 -0
- package/src/session-attention-model.ts +59 -0
- package/src/session-feedback-model.ts +95 -0
- package/src/session-list-model.ts +377 -0
- package/src/session-status-model.ts +62 -0
- package/src/testing/session-scenarios.ts +326 -0
- package/src/timeline/activity-rail.tsx +54 -24
- package/src/timeline/genie-copy.ts +19 -0
- package/src/timeline/genie-loading.tsx +15 -19
- package/src/timeline/index.ts +1 -0
- package/src/timeline/notice-presentation.ts +22 -0
- package/src/timeline/patch-apply-command.tsx +135 -0
- package/src/timeline/platform-activity-presentation.ts +122 -0
- package/src/timeline/platform-activity-row.tsx +6 -96
- package/src/timeline/presented-image.ts +16 -2
- package/src/timeline/projection.ts +12 -1
- package/src/timeline/question-nav-model.ts +28 -0
- package/src/timeline/registry.ts +11 -1
- package/src/timeline/retained-loaders.ts +9 -4
- package/src/timeline/rolling-activity.tsx +7 -19
- package/src/timeline/tool-presentation.ts +1316 -0
- package/src/timeline/tool-renderers.tsx +254 -1024
- package/src/timeline/turn-summary-model.ts +338 -0
- package/src/timeline/turn-summary.tsx +21 -326
- package/src/timeline/work-presentation.ts +139 -0
- package/src/timeline-model.ts +108 -0
- package/styles/compiled.css +17 -4
- package/styles/connect.css +4 -0
- package/styles/responsive.css +11 -2
- package/dist/chunk-2OQA3CPB.js.map +0 -1
- package/dist/chunk-CVYCLFMH.js.map +0 -1
- package/dist/chunk-EAOSEIXB.js.map +0 -1
- package/dist/chunk-G6YRCIYJ.js.map +0 -1
- package/dist/chunk-HXYOSSQO.js +0 -117
- package/dist/chunk-HXYOSSQO.js.map +0 -1
- package/dist/chunk-IUHHPMAX.js.map +0 -1
- package/dist/chunk-IYQCWGU5.js.map +0 -1
- package/dist/chunk-JH7V627O.js.map +0 -1
- package/dist/chunk-L2J3PU7A.js.map +0 -1
- package/dist/chunk-LVS3MH5T.js.map +0 -1
- package/dist/chunk-PHBFJCEU.js.map +0 -1
- package/dist/chunk-QMMCJGFI.js.map +0 -1
- package/dist/chunk-XS67YG5R.js.map +0 -1
- package/dist/platform-activity-row-PJJVATTZ.js.map +0 -1
- package/dist/queue-surface-implementation-67FS7FUI.js.map +0 -1
- /package/dist/{browser-viewer-5EEAS3IU.js.map → browser-viewer-CV23VIHB.js.map} +0 -0
- /package/dist/{chunk-I6OY3MWC.js.map → chunk-6FOTSVWU.js.map} +0 -0
- /package/dist/{chunk-YVFRBXST.js.map → chunk-GMNGUPMX.js.map} +0 -0
- /package/dist/{chunk-PBCZL4JP.js.map → chunk-INIZSNXT.js.map} +0 -0
- /package/dist/{chunk-C5BF4L26.js.map → chunk-LSMWZSCJ.js.map} +0 -0
- /package/dist/{computer-viewer-ELNLZGHI.js.map → composer-messages.js.map} +0 -0
- /package/dist/{model-policy-picker-menu-WRNSRFQC.js.map → computer-viewer-K4CKYRX6.js.map} +0 -0
- /package/dist/{latest-question-2POFPYNB.js.map → latest-question-27HGRPVF.js.map} +0 -0
- /package/dist/{sandbox-files-34CJJNOY.js.map → model-mark-paths.js.map} +0 -0
package/src/client.ts
CHANGED
|
@@ -193,7 +193,7 @@ type SessionClientMethods = Pick<
|
|
|
193
193
|
|
|
194
194
|
/** Compact list transport is optional for scripted and older clients. */
|
|
195
195
|
export type SessionClientLike = SessionClientMethods &
|
|
196
|
-
Partial<Pick<OpenGeniClient, "listSessionSummaryPage">>;
|
|
196
|
+
Partial<Pick<OpenGeniClient, "listSessionSummaryPage" | "findGoal">>;
|
|
197
197
|
|
|
198
198
|
/**
|
|
199
199
|
* Tenant-safe client surface required by the session-only React entry.
|
|
@@ -233,9 +233,15 @@ export type EmbeddedSessionEventClientLike = Pick<OpenGeniClient, "getSession" |
|
|
|
233
233
|
export type EmbeddedSessionReadClientLike = EmbeddedSessionEventClientLike &
|
|
234
234
|
Pick<OpenGeniClient, "getSession" | "updateSession">;
|
|
235
235
|
|
|
236
|
-
/**
|
|
236
|
+
/**
|
|
237
|
+
* Exact client surface required by {@link useGoal}. `findGoal` is optional:
|
|
238
|
+
* when present the hook reads a goal-less session as a successful `null`
|
|
239
|
+
* instead of an absorbed 404.
|
|
240
|
+
*/
|
|
237
241
|
export type EmbeddedGoalClientLike = EmbeddedSessionEventClientLike &
|
|
238
|
-
Pick<OpenGeniClient, "getGoal" | "updateGoal" | "deleteGoal"
|
|
242
|
+
Pick<OpenGeniClient, "getGoal" | "updateGoal" | "deleteGoal"> & {
|
|
243
|
+
findGoal?: OpenGeniClient["findGoal"] | undefined;
|
|
244
|
+
};
|
|
239
245
|
|
|
240
246
|
/** Exact client surface required by {@link useSessionLineage}. */
|
|
241
247
|
export type EmbeddedSessionLineageClientLike = EmbeddedSessionEventClientLike &
|
|
@@ -82,6 +82,22 @@ import { InteractionInterventionBanner } from "./interaction-intervention-banner
|
|
|
82
82
|
import { BrowserSelectControl } from "./browser-select-control";
|
|
83
83
|
import { useViewerMenuDismiss } from "./use-viewer-menu-dismiss";
|
|
84
84
|
|
|
85
|
+
/** Auto-ending a lost attached-device browser: bounded retries for transient failures only. */
|
|
86
|
+
const STALE_BROWSER_END_MAX_ATTEMPTS = 3;
|
|
87
|
+
const STALE_BROWSER_END_RETRY_BASE_MS = 5_000;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Delay before retrying an automatic end of a lost attached-device browser, or null to stop.
|
|
91
|
+
* A refusal (4xx, e.g. 409 when the server will not end it) is never retried: re-sending it on
|
|
92
|
+
* every registry refresh looped about one request per second on prod.
|
|
93
|
+
*/
|
|
94
|
+
export function staleBrowserEndRetryDelayMs(cause: unknown, failedAttempts: number): number | null {
|
|
95
|
+
const status = (cause as { status?: unknown } | null)?.status;
|
|
96
|
+
if (typeof status === "number" && status >= 400 && status < 500) return null;
|
|
97
|
+
if (failedAttempts >= STALE_BROWSER_END_MAX_ATTEMPTS) return null;
|
|
98
|
+
return STALE_BROWSER_END_RETRY_BASE_MS * 2 ** (failedAttempts - 1);
|
|
99
|
+
}
|
|
100
|
+
|
|
85
101
|
export type BrowserViewerNotification = {
|
|
86
102
|
kind: "error" | "info";
|
|
87
103
|
message: string;
|
|
@@ -190,6 +206,7 @@ export function BrowserViewer({
|
|
|
190
206
|
[registry.sessions],
|
|
191
207
|
);
|
|
192
208
|
const endedGenerationLossRef = useRef(new Set<string>());
|
|
209
|
+
const endStaleBrowserAttemptsRef = useRef(new Map<string, number>());
|
|
193
210
|
const endStaleBrowser = registry.end;
|
|
194
211
|
useEffect(() => {
|
|
195
212
|
if (!enabled) return;
|
|
@@ -203,8 +220,12 @@ export function BrowserViewer({
|
|
|
203
220
|
}
|
|
204
221
|
if (endedGenerationLossRef.current.has(session.id)) continue;
|
|
205
222
|
endedGenerationLossRef.current.add(session.id);
|
|
206
|
-
void endStaleBrowser(session.id).catch(() => {
|
|
207
|
-
|
|
223
|
+
void endStaleBrowser(session.id).catch((cause: unknown) => {
|
|
224
|
+
const attempts = (endStaleBrowserAttemptsRef.current.get(session.id) ?? 0) + 1;
|
|
225
|
+
endStaleBrowserAttemptsRef.current.set(session.id, attempts);
|
|
226
|
+
const delay = staleBrowserEndRetryDelayMs(cause, attempts);
|
|
227
|
+
if (delay === null) return;
|
|
228
|
+
setTimeout(() => endedGenerationLossRef.current.delete(session.id), delay);
|
|
208
229
|
});
|
|
209
230
|
}
|
|
210
231
|
}, [enabled, endStaleBrowser, registry.sessions]);
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import { CLAUDE_MARK_PATH } from "../model-mark-paths";
|
|
1
2
|
import type { SVGProps } from "react";
|
|
2
3
|
|
|
3
4
|
/** ClaudeMark: Simple Icons, CC0; https://github.com/simple-icons/simple-icons */
|
|
4
5
|
export function ClaudeMark(props: SVGProps<SVGSVGElement>) {
|
|
5
6
|
return (
|
|
6
7
|
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" {...props}>
|
|
7
|
-
<path d=
|
|
8
|
+
<path d={CLAUDE_MARK_PATH} />
|
|
8
9
|
</svg>
|
|
9
10
|
);
|
|
10
11
|
}
|
|
@@ -52,7 +52,8 @@ import {
|
|
|
52
52
|
ComposerResponsiveContext,
|
|
53
53
|
type ResponsiveBasis,
|
|
54
54
|
} from "../lib/composer-responsive-context";
|
|
55
|
-
import { composerSubmissionErrorMessage
|
|
55
|
+
import { composerSubmissionErrorMessage } from "../lib/format";
|
|
56
|
+
import { defaultChatComposerMessages, type ChatComposerMessages } from "../composer-messages";
|
|
56
57
|
import type { PickerModelRow } from "../model-policy";
|
|
57
58
|
import { useLightboxOptional } from "../timeline/screenshot-lightbox";
|
|
58
59
|
import { OPEN_WORKSTREAM_CONTROL_EVENT } from "../workstream-control-event";
|
|
@@ -107,149 +108,8 @@ export type ComposerControlLinks = {
|
|
|
107
108
|
sessionHref?: ((sessionId: string) => string) | undefined;
|
|
108
109
|
};
|
|
109
110
|
|
|
110
|
-
export
|
|
111
|
-
|
|
112
|
-
pausedPlaceholder: string;
|
|
113
|
-
inputLabel: string;
|
|
114
|
-
keyboardHint: string;
|
|
115
|
-
slashCommandBlocked: string;
|
|
116
|
-
controlChangedError: string;
|
|
117
|
-
sendFailedError: string;
|
|
118
|
-
dropFiles: string;
|
|
119
|
-
attachFiles: string;
|
|
120
|
-
pauseAriaLabel: string;
|
|
121
|
-
pauseTitle: string;
|
|
122
|
-
/** Stop control shown while a response runs (`runControl="stop"`). */
|
|
123
|
-
stopAriaLabel?: string | undefined;
|
|
124
|
-
stopTitle?: string | undefined;
|
|
125
|
-
sendMessageAriaLabel: string;
|
|
126
|
-
sendAndResumeAriaLabel: string;
|
|
127
|
-
sendTitle: string;
|
|
128
|
-
sendAndResumeTitle: string;
|
|
129
|
-
annotationNotesRequired: string;
|
|
130
|
-
workspacePaused: string;
|
|
131
|
-
pausedHere: string;
|
|
132
|
-
parentBlocker: string;
|
|
133
|
-
narrowerPause: string;
|
|
134
|
-
pausedBy: (displayName: string) => string;
|
|
135
|
-
queuedAhead: (count: number) => string;
|
|
136
|
-
resumingAndSending: string;
|
|
137
|
-
nextMessageResumes: string;
|
|
138
|
-
resumeThisWorkstream: string;
|
|
139
|
-
resumeShort: string;
|
|
140
|
-
hidePauseDetails: string;
|
|
141
|
-
showPauseDetails: string;
|
|
142
|
-
pauseReasonsLabel: string;
|
|
143
|
-
pausedByLabel: string;
|
|
144
|
-
alsoPausedByLabel: string;
|
|
145
|
-
resumeWorkspace: string;
|
|
146
|
-
resumeFromSession: string;
|
|
147
|
-
sessionCanRun: string;
|
|
148
|
-
stillPausedBy: (displayName: string) => string;
|
|
149
|
-
restoredResourcesLabel: string;
|
|
150
|
-
restoredFile: (fileId: string) => string;
|
|
151
|
-
removeRestoredResource: (index: number) => string;
|
|
152
|
-
uploading: string;
|
|
153
|
-
uploadFailed: string;
|
|
154
|
-
previewAttachment: (name: string) => string;
|
|
155
|
-
previewUnavailable?: string | undefined;
|
|
156
|
-
attachmentPreviewLabel: string;
|
|
157
|
-
downloadAttachment: (name: string) => string;
|
|
158
|
-
closeAttachmentPreview: string;
|
|
159
|
-
retryAttachment: (name: string) => string;
|
|
160
|
-
retryUpload: string;
|
|
161
|
-
removeAttachment: (name: string) => string;
|
|
162
|
-
confirmCommand: (name: string) => string;
|
|
163
|
-
confirmDescription: (command: SlashCommand) => string;
|
|
164
|
-
cancel: string;
|
|
165
|
-
runCommand: (name: string) => string;
|
|
166
|
-
commands: string;
|
|
167
|
-
slashCommandsLabel: string;
|
|
168
|
-
modelLabel: string;
|
|
169
|
-
close: string;
|
|
170
|
-
danger: string;
|
|
171
|
-
draftConflict: string;
|
|
172
|
-
useOtherDraft: string;
|
|
173
|
-
keepMine: string;
|
|
174
|
-
savingDraft: string;
|
|
175
|
-
formatBytes: (bytes: number) => string;
|
|
176
|
-
formatRelativeTime: (changedAt: string) => string;
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
export const defaultChatComposerMessages: ChatComposerMessages = {
|
|
180
|
-
messagePlaceholder: "Message the agent…",
|
|
181
|
-
pausedPlaceholder: "Message the agent — it will wait in the queue…",
|
|
182
|
-
inputLabel: "Message the agent",
|
|
183
|
-
// Shortcuts live in the send button's title; the footer stays quiet unless
|
|
184
|
-
// the host supplies its own hint.
|
|
185
|
-
keyboardHint: "",
|
|
186
|
-
slashCommandBlocked:
|
|
187
|
-
"That's a slash command — press Enter in the command list to run it, or edit the line to send a message.",
|
|
188
|
-
controlChangedError:
|
|
189
|
-
"This workstream was paused while you were sending. Nothing was sent, and your draft is still here.",
|
|
190
|
-
sendFailedError: "Sending failed — your draft is still here. Try again.",
|
|
191
|
-
dropFiles: "Drop files to attach",
|
|
192
|
-
attachFiles: "Attach files",
|
|
193
|
-
pauseAriaLabel: "Pause this workstream",
|
|
194
|
-
pauseTitle: "Pause this workstream; queued prompts and approvals are preserved",
|
|
195
|
-
stopAriaLabel: "Stop",
|
|
196
|
-
stopTitle: "Stop the response",
|
|
197
|
-
sendMessageAriaLabel: "Send message",
|
|
198
|
-
sendAndResumeAriaLabel: "Add message to queue",
|
|
199
|
-
sendTitle: "Queue message (Enter); steer with Cmd/Ctrl+Enter",
|
|
200
|
-
sendAndResumeTitle: "Add to queue (Enter); steer now with Cmd/Ctrl+Enter",
|
|
201
|
-
annotationNotesRequired: "Add a note to each quote before sending.",
|
|
202
|
-
workspacePaused: "Workspace paused",
|
|
203
|
-
pausedHere: "Paused here",
|
|
204
|
-
parentBlocker: "parent",
|
|
205
|
-
narrowerPause: "a narrower pause",
|
|
206
|
-
pausedBy: (displayName) => `Paused by ${displayName}`,
|
|
207
|
-
queuedAhead: (count) =>
|
|
208
|
-
`${count} waiting prompt${count === 1 ? "" : "s"}; your message joins the queue.`,
|
|
209
|
-
resumingAndSending: "Sending…",
|
|
210
|
-
nextMessageResumes: "Messages wait in the queue until you resume.",
|
|
211
|
-
resumeThisWorkstream: "Resume this workstream",
|
|
212
|
-
resumeShort: "Resume",
|
|
213
|
-
hidePauseDetails: "Hide pause details",
|
|
214
|
-
showPauseDetails: "Show pause details",
|
|
215
|
-
pauseReasonsLabel: "Reasons this workstream is paused",
|
|
216
|
-
pausedByLabel: "Paused by ",
|
|
217
|
-
alsoPausedByLabel: "Also paused by ",
|
|
218
|
-
resumeWorkspace: "Resume workspace",
|
|
219
|
-
resumeFromSession: "Resume from this session",
|
|
220
|
-
sessionCanRun: "This session will be able to run",
|
|
221
|
-
stillPausedBy: (displayName) => `Still paused by ${displayName}`,
|
|
222
|
-
restoredResourcesLabel: "Restored prompt resources",
|
|
223
|
-
restoredFile: (fileId) => `File ${fileId.slice(0, 8)}`,
|
|
224
|
-
removeRestoredResource: (index) => `Remove restored resource ${index + 1}`,
|
|
225
|
-
uploading: "Uploading",
|
|
226
|
-
uploadFailed: "Upload failed",
|
|
227
|
-
previewAttachment: (name) => `Preview ${name}`,
|
|
228
|
-
previewUnavailable: "Preview unavailable",
|
|
229
|
-
attachmentPreviewLabel: "Attachment preview",
|
|
230
|
-
downloadAttachment: (name) => `Download ${name}`,
|
|
231
|
-
closeAttachmentPreview: "Close",
|
|
232
|
-
retryAttachment: (name) => `Retry ${name}`,
|
|
233
|
-
retryUpload: "Retry upload",
|
|
234
|
-
removeAttachment: (name) => `Remove ${name}`,
|
|
235
|
-
confirmCommand: (name) => `Confirm /${name}`,
|
|
236
|
-
confirmDescription: (command) => `Run /${command.name}? ${command.description}`,
|
|
237
|
-
cancel: "Cancel",
|
|
238
|
-
runCommand: (name) => `Run /${name}`,
|
|
239
|
-
commands: "Commands",
|
|
240
|
-
slashCommandsLabel: "Slash commands",
|
|
241
|
-
modelLabel: "Model",
|
|
242
|
-
close: "Close",
|
|
243
|
-
danger: "danger",
|
|
244
|
-
draftConflict: "This draft changed in another tab. Your local draft is still here.",
|
|
245
|
-
useOtherDraft: "Use other draft",
|
|
246
|
-
keepMine: "Keep mine",
|
|
247
|
-
// Kept for embedder message overrides / back-compat. Routine autosave is
|
|
248
|
-
// silent — only draft conflicts surface under the composer.
|
|
249
|
-
savingDraft: "Saving draft…",
|
|
250
|
-
formatBytes,
|
|
251
|
-
formatRelativeTime,
|
|
252
|
-
};
|
|
111
|
+
export { defaultChatComposerMessages } from "../composer-messages";
|
|
112
|
+
export type { ChatComposerMessages } from "../composer-messages";
|
|
253
113
|
|
|
254
114
|
export type ComposerSubmitMode = "queue" | "steer";
|
|
255
115
|
export type ComposerSubmitBlocker =
|
|
@@ -1185,7 +1045,9 @@ export const Controls = forwardRef<HTMLSpanElement, ComposerControlsProps>(
|
|
|
1185
1045
|
ref={ref}
|
|
1186
1046
|
className={cn(
|
|
1187
1047
|
"og-composer-controls flex min-w-0 flex-1 flex-wrap items-center gap-1.5",
|
|
1188
|
-
|
|
1048
|
+
// Phone: 44px touch targets already space themselves; tight gaps leave
|
|
1049
|
+
// the model pill room for its name.
|
|
1050
|
+
"max-sm:flex-nowrap max-sm:gap-0.5",
|
|
1189
1051
|
className,
|
|
1190
1052
|
)}
|
|
1191
1053
|
/>
|
|
@@ -1226,7 +1088,7 @@ export const Actions = forwardRef<HTMLSpanElement, ComposerActionsProps>(functio
|
|
|
1226
1088
|
ref={ref}
|
|
1227
1089
|
className={cn(
|
|
1228
1090
|
"og-composer-actions ml-auto flex shrink-0 items-center gap-1.5",
|
|
1229
|
-
"max-sm:flex-nowrap max-sm:gap-
|
|
1091
|
+
"max-sm:flex-nowrap max-sm:gap-0.5",
|
|
1230
1092
|
className,
|
|
1231
1093
|
)}
|
|
1232
1094
|
/>
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { GROK_MARK_PATH } from "../model-mark-paths";
|
|
1
2
|
import type { SVGProps } from "react";
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -27,7 +28,7 @@ import type { SVGProps } from "react";
|
|
|
27
28
|
export function GrokMark(props: SVGProps<SVGSVGElement>) {
|
|
28
29
|
return (
|
|
29
30
|
<svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" {...props}>
|
|
30
|
-
<path d=
|
|
31
|
+
<path d={GROK_MARK_PATH} />
|
|
31
32
|
</svg>
|
|
32
33
|
);
|
|
33
34
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
HumanInputAnswer,
|
|
3
2
|
HumanInputQuestion,
|
|
4
3
|
SkillRecord,
|
|
5
4
|
SessionHumanInputRequest,
|
|
@@ -9,64 +8,24 @@ import { ChevronDownIcon, ChevronUpIcon, MessageCircleQuestionIcon } from "lucid
|
|
|
9
8
|
import { useEffect, useId, useRef, useState, type FormEvent, type ReactNode } from "react";
|
|
10
9
|
import { cn } from "../lib/cn";
|
|
11
10
|
import { useErrorMessage } from "../lib/error-message";
|
|
11
|
+
import {
|
|
12
|
+
answersFromDrafts,
|
|
13
|
+
defaultHumanInputFormMessages,
|
|
14
|
+
emptyDraft,
|
|
15
|
+
initialDrafts,
|
|
16
|
+
type HumanInputAnswerDraft,
|
|
17
|
+
type HumanInputFormMessages,
|
|
18
|
+
} from "../human-input-model";
|
|
12
19
|
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
20
|
+
export {
|
|
21
|
+
answersFromDrafts,
|
|
22
|
+
defaultHumanInputFormMessages,
|
|
23
|
+
type HumanInputAnswerDraft,
|
|
24
|
+
type HumanInputFormMessages,
|
|
17
25
|
};
|
|
18
26
|
|
|
19
27
|
class SkillReviewVerificationError extends Error {}
|
|
20
28
|
|
|
21
|
-
export type HumanInputFormMessages = {
|
|
22
|
-
title: string;
|
|
23
|
-
description: string;
|
|
24
|
-
submit: string;
|
|
25
|
-
skip: string;
|
|
26
|
-
submitting: string;
|
|
27
|
-
other: string;
|
|
28
|
-
deadlineLabel: string;
|
|
29
|
-
formatDeadline: (value: string) => string;
|
|
30
|
-
required: string;
|
|
31
|
-
otherRequired: string;
|
|
32
|
-
minSelections: (count: number) => string;
|
|
33
|
-
maxSelections: (count: number) => string;
|
|
34
|
-
optional: string;
|
|
35
|
-
/** Shown when the question list overflows the card and more content is below. */
|
|
36
|
-
moreBelow: string;
|
|
37
|
-
questionCount: (count: number) => string;
|
|
38
|
-
collapse: string;
|
|
39
|
-
expand: string;
|
|
40
|
-
selectionHint: (min: number | null | undefined, max: number | null | undefined) => string | null;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export const defaultHumanInputFormMessages: HumanInputFormMessages = {
|
|
44
|
-
title: "Input required",
|
|
45
|
-
/** Multi-question chrome has no default subtitle; hosts may still override. */
|
|
46
|
-
description: "",
|
|
47
|
-
submit: "Send answers",
|
|
48
|
-
skip: "Skip",
|
|
49
|
-
submitting: "Submitting…",
|
|
50
|
-
other: "Other",
|
|
51
|
-
deadlineLabel: "Expires",
|
|
52
|
-
formatDeadline,
|
|
53
|
-
required: "This question is required.",
|
|
54
|
-
otherRequired: "Enter a value for Other.",
|
|
55
|
-
minSelections: (count) => `Choose at least ${count} option${count === 1 ? "" : "s"}.`,
|
|
56
|
-
maxSelections: (count) => `Choose no more than ${count} option${count === 1 ? "" : "s"}.`,
|
|
57
|
-
optional: "Optional",
|
|
58
|
-
moreBelow: "More below",
|
|
59
|
-
questionCount: (count) => `${count} questions`,
|
|
60
|
-
collapse: "Collapse",
|
|
61
|
-
expand: "Expand",
|
|
62
|
-
selectionHint: (min, max) => {
|
|
63
|
-
if (min != null && max != null) return `Choose ${min}–${max}.`;
|
|
64
|
-
if (min != null) return `Choose at least ${min}.`;
|
|
65
|
-
if (max != null) return `Choose up to ${max}.`;
|
|
66
|
-
return null;
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
|
|
70
29
|
export type HumanInputFormProps = {
|
|
71
30
|
/** Scoped immutable revision reader. Saving a Skill fails closed without its full preview. */
|
|
72
31
|
loadSkillReview?:
|
|
@@ -1006,73 +965,3 @@ function QuestionControls({
|
|
|
1006
965
|
</>
|
|
1007
966
|
);
|
|
1008
967
|
}
|
|
1009
|
-
|
|
1010
|
-
export function answersFromDrafts(
|
|
1011
|
-
questions: HumanInputQuestion[],
|
|
1012
|
-
drafts: Record<string, HumanInputAnswerDraft>,
|
|
1013
|
-
messageOverrides: Partial<HumanInputFormMessages> = {},
|
|
1014
|
-
): { answers: HumanInputAnswer[]; errors: Record<string, string> } {
|
|
1015
|
-
const messages = { ...defaultHumanInputFormMessages, ...messageOverrides };
|
|
1016
|
-
const answers: HumanInputAnswer[] = [];
|
|
1017
|
-
const errors: Record<string, string> = {};
|
|
1018
|
-
for (const question of questions) {
|
|
1019
|
-
const draft = drafts[question.id] ?? emptyDraft();
|
|
1020
|
-
const values = question.kind === "text" ? draft.values.filter(Boolean) : draft.values;
|
|
1021
|
-
const other = draft.otherSelected ? draft.other : "";
|
|
1022
|
-
const hasOther = Boolean(other.trim());
|
|
1023
|
-
const supplied = values.length + (hasOther ? 1 : 0);
|
|
1024
|
-
|
|
1025
|
-
// Other-selected-but-empty must win over generic "required" — otherwise the
|
|
1026
|
-
// user sees the wrong diagnosis next to a clearly selected control.
|
|
1027
|
-
if (question.kind !== "text" && draft.otherSelected && !hasOther) {
|
|
1028
|
-
errors[question.id] = messages.otherRequired;
|
|
1029
|
-
continue;
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
if (question.required && supplied === 0) {
|
|
1033
|
-
errors[question.id] = messages.required;
|
|
1034
|
-
continue;
|
|
1035
|
-
}
|
|
1036
|
-
if (question.kind !== "text") {
|
|
1037
|
-
const min = question.validation?.minSelections;
|
|
1038
|
-
const max = question.kind === "single_select" ? 1 : question.validation?.maxSelections;
|
|
1039
|
-
if (min != null && supplied < min) {
|
|
1040
|
-
errors[question.id] = messages.minSelections(min);
|
|
1041
|
-
continue;
|
|
1042
|
-
}
|
|
1043
|
-
if (max != null && supplied > max) {
|
|
1044
|
-
errors[question.id] = messages.maxSelections(max);
|
|
1045
|
-
continue;
|
|
1046
|
-
}
|
|
1047
|
-
}
|
|
1048
|
-
if (supplied > 0) {
|
|
1049
|
-
answers.push({
|
|
1050
|
-
questionId: question.id,
|
|
1051
|
-
values,
|
|
1052
|
-
...(hasOther ? { other } : {}),
|
|
1053
|
-
});
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
return { answers, errors };
|
|
1057
|
-
}
|
|
1058
|
-
|
|
1059
|
-
function initialDrafts(questions: HumanInputQuestion[]): Record<string, HumanInputAnswerDraft> {
|
|
1060
|
-
return Object.fromEntries(questions.map((question) => [question.id, emptyDraft()]));
|
|
1061
|
-
}
|
|
1062
|
-
|
|
1063
|
-
function emptyDraft(): HumanInputAnswerDraft {
|
|
1064
|
-
return { values: [], other: "", otherSelected: false };
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
function formatDeadline(value: string): string {
|
|
1068
|
-
const date = new Date(value);
|
|
1069
|
-
if (Number.isNaN(date.getTime())) return value;
|
|
1070
|
-
const ms = date.getTime() - Date.now();
|
|
1071
|
-
if (ms <= 0) return "deadline passed";
|
|
1072
|
-
const minutes = Math.round(ms / 60_000);
|
|
1073
|
-
if (minutes < 1) return "in under a minute";
|
|
1074
|
-
if (minutes < 60) return `in ${minutes}m`;
|
|
1075
|
-
const hours = Math.round(minutes / 60);
|
|
1076
|
-
if (hours < 48) return `in ${hours}h`;
|
|
1077
|
-
return date.toLocaleString();
|
|
1078
|
-
}
|
|
@@ -28,6 +28,7 @@ import { MOTION_INSPECT_SCALE } from "../lib/motion-inspect";
|
|
|
28
28
|
import { CopyButton } from "./copy-button";
|
|
29
29
|
import { PreviewLoading } from "./preview-loading";
|
|
30
30
|
import type { observeMarkdownTableLayout } from "./markdown-table-layout";
|
|
31
|
+
import { remarkSoftLineBreaks } from "./remark-soft-line-breaks";
|
|
31
32
|
import { softenStreamingMarkdown } from "./soften-streaming-markdown";
|
|
32
33
|
import { createStreamReveal, rehypeStreamReveal, type StreamReveal } from "./stream-reveal";
|
|
33
34
|
import { TooltipProvider } from "./tooltip";
|
|
@@ -81,6 +82,14 @@ export type MarkdownProps = {
|
|
|
81
82
|
renderInteractiveBlock?: ((block: MarkdownInteractiveBlock) => ReactNode) | undefined;
|
|
82
83
|
children: string;
|
|
83
84
|
className?: string | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Render a single newline inside prose as a line break (`<br>`), the way chat
|
|
87
|
+
* apps show messages; CommonMark otherwise folds it into a space. Chat message
|
|
88
|
+
* bodies enable this. Leave it off for documents and other authored Markdown.
|
|
89
|
+
* Code (fenced and inline), lists, tables, and blank-line paragraphs are
|
|
90
|
+
* unaffected either way.
|
|
91
|
+
*/
|
|
92
|
+
softLineBreaks?: boolean | undefined;
|
|
84
93
|
/**
|
|
85
94
|
* While true, newly arrived source fades in through tip ink (`.og-stream-ink`):
|
|
86
95
|
* an age window over each append batch — fast streams keep a large soft band,
|
|
@@ -630,10 +639,19 @@ function MarkdownTable({ children, className, ...props }: ComponentPropsWithoutR
|
|
|
630
639
|
);
|
|
631
640
|
}
|
|
632
641
|
|
|
642
|
+
type RemarkPlugins = NonNullable<Parameters<typeof ReactMarkdown>[0]["remarkPlugins"]>;
|
|
643
|
+
const REMARK_PLUGINS: RemarkPlugins = [remarkGfm];
|
|
644
|
+
// Structural plugin types (see remark-soft-line-breaks.ts) need one cast at the seam.
|
|
645
|
+
const SOFT_LINE_BREAK_REMARK_PLUGINS = [
|
|
646
|
+
remarkGfm,
|
|
647
|
+
remarkSoftLineBreaks,
|
|
648
|
+
] as unknown as RemarkPlugins;
|
|
649
|
+
|
|
633
650
|
function MarkdownImpl({
|
|
634
651
|
children,
|
|
635
652
|
artifactHref,
|
|
636
653
|
className,
|
|
654
|
+
softLineBreaks = false,
|
|
637
655
|
streaming = false,
|
|
638
656
|
onSandboxFile,
|
|
639
657
|
renderInteractiveBlock,
|
|
@@ -760,7 +778,7 @@ function MarkdownImpl({
|
|
|
760
778
|
)}
|
|
761
779
|
>
|
|
762
780
|
<ReactMarkdown
|
|
763
|
-
remarkPlugins={
|
|
781
|
+
remarkPlugins={softLineBreaks ? SOFT_LINE_BREAK_REMARK_PLUGINS : REMARK_PLUGINS}
|
|
764
782
|
rehypePlugins={rehypePlugins}
|
|
765
783
|
components={markdownComponents}
|
|
766
784
|
urlTransform={markdownUrlTransform}
|