@opengeni/react 1.4.4 → 1.4.5-canary.37458084490001
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-3ZC6QPOM.js +174 -0
- package/dist/chunk-3ZC6QPOM.js.map +1 -0
- package/dist/{chunk-YVFRBXST.js → chunk-4BCVCJSU.js} +2 -2
- 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-I6OY3MWC.js → chunk-6FOTSVWU.js} +2 -2
- package/dist/{chunk-IUHHPMAX.js → chunk-7RRBX5EM.js} +14 -85
- package/dist/chunk-7RRBX5EM.js.map +1 -0
- package/dist/{chunk-L2J3PU7A.js → chunk-7ZB7I3KP.js} +24 -98
- package/dist/chunk-7ZB7I3KP.js.map +1 -0
- 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-IYQCWGU5.js → chunk-GHJU7XG7.js} +35 -62
- package/dist/chunk-GHJU7XG7.js.map +1 -0
- package/dist/{chunk-G6YRCIYJ.js → chunk-HNVWMDNN.js} +55 -60
- package/dist/chunk-HNVWMDNN.js.map +1 -0
- 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-XS67YG5R.js → chunk-IX3K4THH.js} +24 -3
- package/dist/chunk-IX3K4THH.js.map +1 -0
- 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-C5BF4L26.js → chunk-KHF2VRXF.js} +7 -7
- package/dist/{chunk-QMMCJGFI.js → chunk-L5OKM2VX.js} +2 -2
- package/dist/chunk-LHF6BVM4.js +83 -0
- package/dist/chunk-LHF6BVM4.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-RI42H5IU.js +326 -0
- package/dist/chunk-RI42H5IU.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-EAOSEIXB.js → chunk-TZQSHCZN.js} +692 -1996
- package/dist/chunk-TZQSHCZN.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-3ZFWWJ6O.js} +6 -4
- package/dist/{embedded-voice-NIL4RDX3.js.map → embedded-voice-3ZFWWJ6O.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/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-SWC6QEVN.js} +3 -3
- package/dist/lib/clipboard.d.ts +7 -0
- package/dist/lib/provider-recovery.d.ts +49 -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-NM4RPTY6.js} +6 -4
- package/dist/model-policy-picker-menu-NM4RPTY6.js.map +1 -0
- package/dist/model-policy.d.ts +10 -0
- package/dist/model-policy.js +5 -1
- 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-RCVCMXG7.js} +5 -5
- package/dist/sandbox-files-RCVCMXG7.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-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 +96 -0
- package/dist/session-list-model.js +219 -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 +47 -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 +4 -144
- 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 +15 -148
- 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/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/model-mark-paths.ts +53 -0
- package/src/model-picker-model.ts +330 -0
- package/src/model-policy.ts +43 -2
- 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-attention-model.ts +59 -0
- package/src/session-feedback-model.ts +95 -0
- package/src/session-list-model.ts +327 -0
- package/src/session-status-model.ts +62 -0
- package/src/testing/session-scenarios.ts +326 -0
- package/src/timeline/activity-rail.tsx +5 -17
- package/src/timeline/genie-copy.ts +19 -0
- package/src/timeline/genie-loading.tsx +13 -18
- 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/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 +226 -1025
- 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 +3 -0
- package/styles/connect.css +4 -0
- 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-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-YVFRBXST.js.map → chunk-4BCVCJSU.js.map} +0 -0
- /package/dist/{chunk-I6OY3MWC.js.map → chunk-6FOTSVWU.js.map} +0 -0
- /package/dist/{chunk-PBCZL4JP.js.map → chunk-INIZSNXT.js.map} +0 -0
- /package/dist/{chunk-C5BF4L26.js.map → chunk-KHF2VRXF.js.map} +0 -0
- /package/dist/{chunk-QMMCJGFI.js.map → chunk-L5OKM2VX.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-SWC6QEVN.js.map} +0 -0
- /package/dist/{sandbox-files-34CJJNOY.js.map → model-mark-paths.js.map} +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
copyPendingTextToClipboard
|
|
4
|
+
} from "./chunk-PEHTX3V7.js";
|
|
5
|
+
|
|
6
|
+
// src/timeline/retained-image.ts
|
|
7
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
8
|
+
function useRetainedImageObjectUrl(artifact, load) {
|
|
9
|
+
const [state, setState] = useState({ kind: "loading" });
|
|
10
|
+
const [retrievalAttempt, setRetrievalAttempt] = useState(0);
|
|
11
|
+
const retry = useCallback(() => setRetrievalAttempt((attempt) => attempt + 1), []);
|
|
12
|
+
const artifactValue = retainedArtifactValue(artifact);
|
|
13
|
+
const stableArtifactRef = useRef({ value: artifactValue, artifact });
|
|
14
|
+
if (stableArtifactRef.current.value !== artifactValue) {
|
|
15
|
+
stableArtifactRef.current = { value: artifactValue, artifact };
|
|
16
|
+
}
|
|
17
|
+
const stableArtifact = stableArtifactRef.current.artifact;
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!load) {
|
|
20
|
+
setState({ kind: "unavailable", label: "retrieval is not configured" });
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
let objectUrl = null;
|
|
25
|
+
setState({ kind: "loading" });
|
|
26
|
+
void load(stableArtifact, controller.signal).then((source) => {
|
|
27
|
+
if (controller.signal.aborted) return;
|
|
28
|
+
if (!source) {
|
|
29
|
+
setState({ kind: "unavailable", label: "bytes are unavailable" });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (!(source instanceof Uint8Array)) {
|
|
33
|
+
if (!source.url.trim()) {
|
|
34
|
+
setState({ kind: "unavailable", label: "URL is unavailable" });
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
setState({ kind: "ready", url: source.url });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
objectUrl = URL.createObjectURL(
|
|
41
|
+
new Blob([source], { type: stableArtifact.contentType })
|
|
42
|
+
);
|
|
43
|
+
setState({ kind: "ready", url: objectUrl });
|
|
44
|
+
}).catch((error) => {
|
|
45
|
+
if (controller.signal.aborted) return;
|
|
46
|
+
const status = error && typeof error === "object" && "status" in error ? Number(error.status) : null;
|
|
47
|
+
setState(
|
|
48
|
+
status === 404 ? { kind: "unavailable", label: "deleted" } : status === 410 ? { kind: "unavailable", label: "expired or unavailable" } : { kind: "error", message: "retrieval failed" }
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
return () => {
|
|
52
|
+
controller.abort();
|
|
53
|
+
if (objectUrl) URL.revokeObjectURL(objectUrl);
|
|
54
|
+
};
|
|
55
|
+
}, [stableArtifact, load, retrievalAttempt]);
|
|
56
|
+
return { ...state, retry };
|
|
57
|
+
}
|
|
58
|
+
function retainedArtifactValue(artifact) {
|
|
59
|
+
return [
|
|
60
|
+
artifact.artifactId,
|
|
61
|
+
artifact.kind,
|
|
62
|
+
artifact.contentType,
|
|
63
|
+
artifact.originalBytes,
|
|
64
|
+
artifact.sha256,
|
|
65
|
+
artifact.retainedAt,
|
|
66
|
+
artifact.dimensions?.width ?? "",
|
|
67
|
+
artifact.dimensions?.height ?? "",
|
|
68
|
+
artifact.retention.policy,
|
|
69
|
+
artifact.retention.expiresAt ?? "",
|
|
70
|
+
artifact.retrieval.method,
|
|
71
|
+
artifact.retrieval.path,
|
|
72
|
+
artifact.retrieval.acceptRanges,
|
|
73
|
+
artifact.retrieval.maxRangeBytes
|
|
74
|
+
].join("\0");
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/timeline/patch-apply-command.tsx
|
|
78
|
+
import { CheckIcon, TerminalIcon } from "lucide-react";
|
|
79
|
+
import { useState as useState2 } from "react";
|
|
80
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
81
|
+
function shellQuote(value) {
|
|
82
|
+
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
83
|
+
}
|
|
84
|
+
function patchApplyCommand(url) {
|
|
85
|
+
return `curl -fsSL ${shellQuote(url)} | git apply`;
|
|
86
|
+
}
|
|
87
|
+
function applyCommandLifetime(expiresAt, now = Date.now()) {
|
|
88
|
+
const expires = expiresAt ? Date.parse(expiresAt) : Number.NaN;
|
|
89
|
+
const minutes = Number.isFinite(expires) ? Math.round((expires - now) / 6e4) : 5;
|
|
90
|
+
if (minutes <= 1) return "1 minute";
|
|
91
|
+
return `${minutes} minutes`;
|
|
92
|
+
}
|
|
93
|
+
var BUTTON_CLASS = "inline-flex items-center gap-1.5 rounded-og-sm border border-og-border px-2.5 py-1.5 text-og-sm font-medium text-og-fg transition-colors hover:border-og-border-strong hover:bg-og-surface-2 disabled:cursor-wait disabled:opacity-60";
|
|
94
|
+
function PatchApplyCommand({
|
|
95
|
+
artifact,
|
|
96
|
+
filename,
|
|
97
|
+
load
|
|
98
|
+
}) {
|
|
99
|
+
const [state, setState] = useState2({ kind: "idle" });
|
|
100
|
+
const copy = async () => {
|
|
101
|
+
if (!load) {
|
|
102
|
+
setState({ kind: "unavailable" });
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
setState({ kind: "loading" });
|
|
106
|
+
let lifetime = "5 minutes";
|
|
107
|
+
const command = load(artifact, new AbortController().signal, { prefer: "url" }).then(
|
|
108
|
+
(source) => {
|
|
109
|
+
if (!source || source instanceof Uint8Array) throw new UnavailableError();
|
|
110
|
+
lifetime = applyCommandLifetime(source.expiresAt);
|
|
111
|
+
return patchApplyCommand(source.url);
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
const copied = copyPendingTextToClipboard(command);
|
|
115
|
+
try {
|
|
116
|
+
const text = await command;
|
|
117
|
+
if (await copied) setState({ kind: "copied", lifetime });
|
|
118
|
+
else setState({ kind: "manual", command: text, lifetime });
|
|
119
|
+
} catch (failure) {
|
|
120
|
+
setState({ kind: failure instanceof UnavailableError ? "unavailable" : "error" });
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
const label = state.kind === "loading" ? "Preparing\u2026" : state.kind === "copied" ? "Copied" : state.kind === "error" ? "Try again" : "Copy command to apply these changes";
|
|
124
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-1.5", children: [
|
|
125
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(
|
|
126
|
+
"button",
|
|
127
|
+
{
|
|
128
|
+
type: "button",
|
|
129
|
+
onClick: () => void copy(),
|
|
130
|
+
disabled: state.kind === "loading",
|
|
131
|
+
className: BUTTON_CLASS,
|
|
132
|
+
children: [
|
|
133
|
+
state.kind === "copied" ? /* @__PURE__ */ jsx(CheckIcon, { className: "size-3.5", "aria-hidden": true }) : /* @__PURE__ */ jsx(TerminalIcon, { className: "size-3.5", "aria-hidden": true }),
|
|
134
|
+
label
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
) }),
|
|
138
|
+
/* @__PURE__ */ jsx("p", { className: "m-0 text-og-xs leading-relaxed text-og-fg-muted", role: "status", children: state.kind === "copied" ? `Copied. Paste it in a terminal in your project folder and press Enter. The link in it expires in ${state.lifetime}.` : state.kind === "manual" ? `Copy this command, then run it in your project folder. The link in it expires in ${state.lifetime}.` : state.kind === "unavailable" ? `Download ${filename}, then run git apply ${filename} in your project folder.` : state.kind === "error" ? "Couldn't prepare the command. Try again, or download the file and run git apply." : "Runs git apply in your project folder. Works on macOS, Linux and Git Bash." }),
|
|
139
|
+
state.kind === "manual" ? /* @__PURE__ */ jsx(
|
|
140
|
+
"input",
|
|
141
|
+
{
|
|
142
|
+
readOnly: true,
|
|
143
|
+
value: state.command,
|
|
144
|
+
"aria-label": "Command to apply these changes",
|
|
145
|
+
onFocus: (event) => event.currentTarget.select(),
|
|
146
|
+
className: "w-full min-w-0 rounded-og-sm border border-og-border bg-og-surface-2 px-2 py-1.5 font-mono text-og-xs text-og-fg"
|
|
147
|
+
}
|
|
148
|
+
) : null
|
|
149
|
+
] });
|
|
150
|
+
}
|
|
151
|
+
var UnavailableError = class extends Error {
|
|
152
|
+
constructor() {
|
|
153
|
+
super("A download URL is unavailable here");
|
|
154
|
+
this.name = "UnavailableError";
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export {
|
|
159
|
+
useRetainedImageObjectUrl,
|
|
160
|
+
PatchApplyCommand
|
|
161
|
+
};
|
|
162
|
+
//# sourceMappingURL=chunk-BOFEQC6K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/timeline/retained-image.ts","../src/timeline/patch-apply-command.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { RetainedArtifactReference } from \"@opengeni/sdk\";\nimport type { ToolRendererProps } from \"./registry\";\ntype RetainedImageState =\n | { kind: \"loading\" }\n | { kind: \"ready\"; url: string }\n | { kind: \"unavailable\"; label: string }\n | { kind: \"error\"; message: string };\n\nexport { isRetainedImageContentType } from \"./presented-image\";\n\nexport function useRetainedImageObjectUrl(\n artifact: RetainedArtifactReference,\n load: ToolRendererProps[\"loadRetainedArtifact\"],\n): RetainedImageState & { retry: () => void } {\n const [state, setState] = useState<RetainedImageState>({ kind: \"loading\" });\n const [retrievalAttempt, setRetrievalAttempt] = useState(0);\n // Retry only the immutable retained artifact; never issue a new capture or\n // rewrite the tool receipt/model history to repair a human preview.\n const retry = useCallback(() => setRetrievalAttempt((attempt) => attempt + 1), []);\n // Function outputs are commonly serialized JSON. Parsing them creates a new\n // object on every render, so depend on the immutable wire value rather than\n // object identity; otherwise the loader can refetch after its own setState.\n const artifactValue = retainedArtifactValue(artifact);\n const stableArtifactRef = useRef({ value: artifactValue, artifact });\n if (stableArtifactRef.current.value !== artifactValue) {\n stableArtifactRef.current = { value: artifactValue, artifact };\n }\n const stableArtifact = stableArtifactRef.current.artifact;\n useEffect(() => {\n if (!load) {\n setState({ kind: \"unavailable\", label: \"retrieval is not configured\" });\n return;\n }\n const controller = new AbortController();\n let objectUrl: string | null = null;\n setState({ kind: \"loading\" });\n void load(stableArtifact, controller.signal)\n .then((source) => {\n if (controller.signal.aborted) return;\n if (!source) {\n setState({ kind: \"unavailable\", label: \"bytes are unavailable\" });\n return;\n }\n if (!(source instanceof Uint8Array)) {\n if (!source.url.trim()) {\n setState({ kind: \"unavailable\", label: \"URL is unavailable\" });\n return;\n }\n setState({ kind: \"ready\", url: source.url });\n return;\n }\n objectUrl = URL.createObjectURL(\n new Blob([source as unknown as BlobPart], { type: stableArtifact.contentType }),\n );\n setState({ kind: \"ready\", url: objectUrl });\n })\n .catch((error: unknown) => {\n if (controller.signal.aborted) return;\n const status =\n error && typeof error === \"object\" && \"status\" in error\n ? Number((error as { status?: unknown }).status)\n : null;\n setState(\n status === 404\n ? { kind: \"unavailable\", label: \"deleted\" }\n : status === 410\n ? { kind: \"unavailable\", label: \"expired or unavailable\" }\n : { kind: \"error\", message: \"retrieval failed\" },\n );\n });\n return () => {\n controller.abort();\n if (objectUrl) URL.revokeObjectURL(objectUrl);\n };\n }, [stableArtifact, load, retrievalAttempt]);\n return { ...state, retry };\n}\n\nfunction retainedArtifactValue(artifact: RetainedArtifactReference): string {\n return [\n artifact.artifactId,\n artifact.kind,\n artifact.contentType,\n artifact.originalBytes,\n artifact.sha256,\n artifact.retainedAt,\n artifact.dimensions?.width ?? \"\",\n artifact.dimensions?.height ?? \"\",\n artifact.retention.policy,\n artifact.retention.expiresAt ?? \"\",\n artifact.retrieval.method,\n artifact.retrieval.path,\n artifact.retrieval.acceptRanges,\n artifact.retrieval.maxRangeBytes,\n ].join(\"\\0\");\n}\n","import type { RetainedArtifactReference } from \"@opengeni/sdk\";\nimport { CheckIcon, TerminalIcon } from \"lucide-react\";\nimport { useState } from \"react\";\nimport { copyPendingTextToClipboard } from \"../lib/clipboard\";\nimport type { RetainedArtifactLoader } from \"./registry\";\n\nexport { isPatchFilename } from \"./presented-image\";\n\n/** POSIX single-quote one argument so the URL reaches curl unchanged. */\nfunction shellQuote(value: string): string {\n return `'${value.replaceAll(\"'\", `'\\\\''`)}'`;\n}\n\n/** One command that downloads this patch and applies it in the current folder. */\nexport function patchApplyCommand(url: string): string {\n return `curl -fsSL ${shellQuote(url)} | git apply`;\n}\n\n/** \"5 minutes\" from the signed URL's expiry; the default download URL lifetime otherwise. */\nexport function applyCommandLifetime(expiresAt: string | undefined, now = Date.now()): string {\n const expires = expiresAt ? Date.parse(expiresAt) : Number.NaN;\n const minutes = Number.isFinite(expires) ? Math.round((expires - now) / 60_000) : 5;\n if (minutes <= 1) return \"1 minute\";\n return `${minutes} minutes`;\n}\n\ntype ApplyState =\n | { kind: \"idle\" }\n | { kind: \"loading\" }\n | { kind: \"copied\"; lifetime: string }\n | { kind: \"manual\"; command: string; lifetime: string }\n | { kind: \"unavailable\" }\n | { kind: \"error\" };\n\nconst BUTTON_CLASS =\n \"inline-flex items-center gap-1.5 rounded-og-sm border border-og-border px-2.5 py-1.5 text-og-sm font-medium text-og-fg transition-colors hover:border-og-border-strong hover:bg-og-surface-2 disabled:cursor-wait disabled:opacity-60\";\n\n/**\n * \"Copy command to apply these changes\": mints the existing short-lived,\n * authenticated download URL for this published patch (the same authority as\n * Download) and copies `curl -fsSL '<url>' | git apply`. The URL is minted on\n * click, so the copied command works for the URL's lifetime only.\n */\nexport function PatchApplyCommand({\n artifact,\n filename,\n load,\n}: {\n artifact: RetainedArtifactReference;\n filename: string;\n load: RetainedArtifactLoader | undefined;\n}) {\n const [state, setState] = useState<ApplyState>({ kind: \"idle\" });\n\n const copy = async () => {\n if (!load) {\n setState({ kind: \"unavailable\" });\n return;\n }\n setState({ kind: \"loading\" });\n let lifetime = \"5 minutes\";\n // Start the URL request inside the click so the clipboard write may wait for it.\n const command = load(artifact, new AbortController().signal, { prefer: \"url\" }).then(\n (source) => {\n if (!source || source instanceof Uint8Array) throw new UnavailableError();\n lifetime = applyCommandLifetime(source.expiresAt);\n return patchApplyCommand(source.url);\n },\n );\n const copied = copyPendingTextToClipboard(command);\n try {\n const text = await command;\n if (await copied) setState({ kind: \"copied\", lifetime });\n else setState({ kind: \"manual\", command: text, lifetime });\n } catch (failure) {\n setState({ kind: failure instanceof UnavailableError ? \"unavailable\" : \"error\" });\n }\n };\n\n const label =\n state.kind === \"loading\"\n ? \"Preparing…\"\n : state.kind === \"copied\"\n ? \"Copied\"\n : state.kind === \"error\"\n ? \"Try again\"\n : \"Copy command to apply these changes\";\n\n return (\n <div className=\"flex min-w-0 flex-col gap-1.5\">\n <div>\n <button\n type=\"button\"\n onClick={() => void copy()}\n disabled={state.kind === \"loading\"}\n className={BUTTON_CLASS}\n >\n {state.kind === \"copied\" ? (\n <CheckIcon className=\"size-3.5\" aria-hidden />\n ) : (\n <TerminalIcon className=\"size-3.5\" aria-hidden />\n )}\n {label}\n </button>\n </div>\n <p className=\"m-0 text-og-xs leading-relaxed text-og-fg-muted\" role=\"status\">\n {state.kind === \"copied\"\n ? `Copied. Paste it in a terminal in your project folder and press Enter. The link in it expires in ${state.lifetime}.`\n : state.kind === \"manual\"\n ? `Copy this command, then run it in your project folder. The link in it expires in ${state.lifetime}.`\n : state.kind === \"unavailable\"\n ? `Download ${filename}, then run git apply ${filename} in your project folder.`\n : state.kind === \"error\"\n ? \"Couldn't prepare the command. Try again, or download the file and run git apply.\"\n : \"Runs git apply in your project folder. Works on macOS, Linux and Git Bash.\"}\n </p>\n {state.kind === \"manual\" ? (\n <input\n readOnly\n value={state.command}\n aria-label=\"Command to apply these changes\"\n onFocus={(event) => event.currentTarget.select()}\n className=\"w-full min-w-0 rounded-og-sm border border-og-border bg-og-surface-2 px-2 py-1.5 font-mono text-og-xs text-og-fg\"\n />\n ) : null}\n </div>\n );\n}\n\nclass UnavailableError extends Error {\n constructor() {\n super(\"A download URL is unavailable here\");\n this.name = \"UnavailableError\";\n }\n}\n"],"mappings":"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","names":["useState","useState"]}
|
|
@@ -10,13 +10,13 @@ import {
|
|
|
10
10
|
} from "./chunk-BNKV5ZLF.js";
|
|
11
11
|
import {
|
|
12
12
|
copyTextToClipboard
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-PEHTX3V7.js";
|
|
14
14
|
import {
|
|
15
15
|
interactionHostPlatform
|
|
16
16
|
} from "./chunk-ZUWF4NF7.js";
|
|
17
17
|
import {
|
|
18
18
|
formatBytes
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-ATIRUHBZ.js";
|
|
20
20
|
import {
|
|
21
21
|
STREAM_CLOSE_REASON_NORMAL,
|
|
22
22
|
STREAM_KIND_BROWSER,
|
|
@@ -2157,6 +2157,14 @@ function BrowserSelectControl(props) {
|
|
|
2157
2157
|
|
|
2158
2158
|
// src/components/browser-viewer.tsx
|
|
2159
2159
|
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
2160
|
+
var STALE_BROWSER_END_MAX_ATTEMPTS = 3;
|
|
2161
|
+
var STALE_BROWSER_END_RETRY_BASE_MS = 5e3;
|
|
2162
|
+
function staleBrowserEndRetryDelayMs(cause, failedAttempts) {
|
|
2163
|
+
const status = cause?.status;
|
|
2164
|
+
if (typeof status === "number" && status >= 400 && status < 500) return null;
|
|
2165
|
+
if (failedAttempts >= STALE_BROWSER_END_MAX_ATTEMPTS) return null;
|
|
2166
|
+
return STALE_BROWSER_END_RETRY_BASE_MS * 2 ** (failedAttempts - 1);
|
|
2167
|
+
}
|
|
2160
2168
|
function BrowserViewer({
|
|
2161
2169
|
sessionId,
|
|
2162
2170
|
enabled = true,
|
|
@@ -2195,6 +2203,7 @@ function BrowserViewer({
|
|
|
2195
2203
|
[registry.sessions]
|
|
2196
2204
|
);
|
|
2197
2205
|
const endedGenerationLossRef = useRef9(/* @__PURE__ */ new Set());
|
|
2206
|
+
const endStaleBrowserAttemptsRef = useRef9(/* @__PURE__ */ new Map());
|
|
2198
2207
|
const endStaleBrowser = registry.end;
|
|
2199
2208
|
useEffect9(() => {
|
|
2200
2209
|
if (!enabled) return;
|
|
@@ -2204,8 +2213,12 @@ function BrowserViewer({
|
|
|
2204
2213
|
}
|
|
2205
2214
|
if (endedGenerationLossRef.current.has(session.id)) continue;
|
|
2206
2215
|
endedGenerationLossRef.current.add(session.id);
|
|
2207
|
-
void endStaleBrowser(session.id).catch(() => {
|
|
2208
|
-
|
|
2216
|
+
void endStaleBrowser(session.id).catch((cause) => {
|
|
2217
|
+
const attempts = (endStaleBrowserAttemptsRef.current.get(session.id) ?? 0) + 1;
|
|
2218
|
+
endStaleBrowserAttemptsRef.current.set(session.id, attempts);
|
|
2219
|
+
const delay = staleBrowserEndRetryDelayMs(cause, attempts);
|
|
2220
|
+
if (delay === null) return;
|
|
2221
|
+
setTimeout(() => endedGenerationLossRef.current.delete(session.id), delay);
|
|
2209
2222
|
});
|
|
2210
2223
|
}
|
|
2211
2224
|
}, [enabled, endStaleBrowser, registry.sessions]);
|
|
@@ -4678,6 +4691,7 @@ export {
|
|
|
4678
4691
|
useBrowserSession,
|
|
4679
4692
|
useBrowserDownloads,
|
|
4680
4693
|
useBrowserFrameStream,
|
|
4694
|
+
staleBrowserEndRetryDelayMs,
|
|
4681
4695
|
BrowserViewer
|
|
4682
4696
|
};
|
|
4683
|
-
//# sourceMappingURL=chunk-
|
|
4697
|
+
//# sourceMappingURL=chunk-CESBPQP5.js.map
|