@opengeni/react 1.4.2 → 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.
Files changed (240) hide show
  1. package/README.md +17 -6
  2. package/dist/artifacts.d.ts +1 -0
  3. package/dist/artifacts.js +22 -15
  4. package/dist/artifacts.js.map +1 -1
  5. package/dist/{browser-viewer-WGJ43YGI.js → browser-viewer-CV23VIHB.js} +8 -6
  6. package/dist/chunk-3ZC6QPOM.js +174 -0
  7. package/dist/chunk-3ZC6QPOM.js.map +1 -0
  8. package/dist/{chunk-YVFRBXST.js → chunk-4BCVCJSU.js} +2 -2
  9. package/dist/{chunk-JHTIMBOL.js → chunk-5JSUNNQN.js} +26 -4
  10. package/dist/{chunk-JHTIMBOL.js.map → chunk-5JSUNNQN.js.map} +1 -1
  11. package/dist/{chunk-MDIXFKA3.js → chunk-6FOTSVWU.js} +303 -109
  12. package/dist/chunk-6FOTSVWU.js.map +1 -0
  13. package/dist/{chunk-IUHHPMAX.js → chunk-7RRBX5EM.js} +14 -85
  14. package/dist/chunk-7RRBX5EM.js.map +1 -0
  15. package/dist/{chunk-L2J3PU7A.js → chunk-7ZB7I3KP.js} +24 -98
  16. package/dist/chunk-7ZB7I3KP.js.map +1 -0
  17. package/dist/{chunk-LVS3MH5T.js → chunk-ATIRUHBZ.js} +128 -10
  18. package/dist/chunk-ATIRUHBZ.js.map +1 -0
  19. package/dist/chunk-BOFEQC6K.js +162 -0
  20. package/dist/chunk-BOFEQC6K.js.map +1 -0
  21. package/dist/{chunk-VCSERYXH.js → chunk-CESBPQP5.js} +309 -162
  22. package/dist/chunk-CESBPQP5.js.map +1 -0
  23. package/dist/{chunk-IYQCWGU5.js → chunk-GHJU7XG7.js} +35 -62
  24. package/dist/chunk-GHJU7XG7.js.map +1 -0
  25. package/dist/{chunk-G6YRCIYJ.js → chunk-HNVWMDNN.js} +55 -60
  26. package/dist/chunk-HNVWMDNN.js.map +1 -0
  27. package/dist/{chunk-PHBFJCEU.js → chunk-I5EGRXXG.js} +110 -7
  28. package/dist/chunk-I5EGRXXG.js.map +1 -0
  29. package/dist/{chunk-PBCZL4JP.js → chunk-INIZSNXT.js} +2 -2
  30. package/dist/{chunk-XS67YG5R.js → chunk-IX3K4THH.js} +24 -3
  31. package/dist/chunk-IX3K4THH.js.map +1 -0
  32. package/dist/chunk-IZV5FTJC.js +55 -0
  33. package/dist/chunk-IZV5FTJC.js.map +1 -0
  34. package/dist/chunk-JDJJMBB3.js +1883 -0
  35. package/dist/chunk-JDJJMBB3.js.map +1 -0
  36. package/dist/{chunk-C5BF4L26.js → chunk-KHF2VRXF.js} +7 -7
  37. package/dist/{chunk-QMMCJGFI.js → chunk-L5OKM2VX.js} +2 -2
  38. package/dist/chunk-LHF6BVM4.js +83 -0
  39. package/dist/chunk-LHF6BVM4.js.map +1 -0
  40. package/dist/chunk-N7S72EXK.js +25 -0
  41. package/dist/chunk-N7S72EXK.js.map +1 -0
  42. package/dist/{chunk-CVYCLFMH.js → chunk-PEHTX3V7.js} +19 -1
  43. package/dist/chunk-PEHTX3V7.js.map +1 -0
  44. package/dist/chunk-R5R5RQQD.js +51 -0
  45. package/dist/chunk-R5R5RQQD.js.map +1 -0
  46. package/dist/chunk-RI42H5IU.js +326 -0
  47. package/dist/chunk-RI42H5IU.js.map +1 -0
  48. package/dist/{chunk-JH7V627O.js → chunk-SHLZMAJN.js} +2 -11
  49. package/dist/chunk-SHLZMAJN.js.map +1 -0
  50. package/dist/{chunk-CREMJMVN.js → chunk-TZQSHCZN.js} +692 -1996
  51. package/dist/chunk-TZQSHCZN.js.map +1 -0
  52. package/dist/chunk-ZIB4H5LN.js +101 -0
  53. package/dist/chunk-ZIB4H5LN.js.map +1 -0
  54. package/dist/client.d.ts +9 -3
  55. package/dist/clipboard.js +1 -1
  56. package/dist/components/browser-viewer.d.ts +6 -0
  57. package/dist/components/composer.d.ts +3 -69
  58. package/dist/components/human-input-form.d.ts +3 -32
  59. package/dist/components/markdown.d.ts +8 -0
  60. package/dist/components/model-policy-picker.d.ts +4 -37
  61. package/dist/components/opper-mark.d.ts +7 -0
  62. package/dist/components/provider-recovery-notice.d.ts +15 -0
  63. package/dist/components/remark-soft-line-breaks.d.ts +38 -0
  64. package/dist/components/sandbox-workspace.d.ts +13 -0
  65. package/dist/components/session-chrome.d.ts +5 -3
  66. package/dist/components/session-conversation.d.ts +15 -3
  67. package/dist/composer-messages.d.ts +74 -0
  68. package/dist/composer-messages.js +9 -0
  69. package/dist/composer.js +15 -10
  70. package/dist/{computer-viewer-46UIN7F3.js → computer-viewer-K4CKYRX6.js} +4 -4
  71. package/dist/connect-setup.d.ts +2 -0
  72. package/dist/connect.d.ts +1 -1
  73. package/dist/connect.js +21 -6
  74. package/dist/connect.js.map +1 -1
  75. package/dist/{embedded-voice-NIL4RDX3.js → embedded-voice-3ZFWWJ6O.js} +6 -4
  76. package/dist/{embedded-voice-NIL4RDX3.js.map → embedded-voice-3ZFWWJ6O.js.map} +1 -1
  77. package/dist/hooks/shared-machines-list.d.ts +4 -0
  78. package/dist/hooks/use-client-config-flags.d.ts +6 -0
  79. package/dist/hooks/use-computer-session.d.ts +2 -0
  80. package/dist/hooks/use-goal.d.ts +2 -1
  81. package/dist/human-input-model.d.ts +40 -0
  82. package/dist/index.d.ts +4 -1
  83. package/dist/index.js +116 -73
  84. package/dist/index.js.map +1 -1
  85. package/dist/interaction.js +5 -5
  86. package/dist/{latest-question-2POFPYNB.js → latest-question-SWC6QEVN.js} +3 -3
  87. package/dist/lib/clipboard.d.ts +7 -0
  88. package/dist/lib/provider-recovery.d.ts +49 -0
  89. package/dist/machines.js +2 -2
  90. package/dist/model-mark-paths.d.ts +34 -0
  91. package/dist/model-mark-paths.js +16 -0
  92. package/dist/model-picker-model.d.ts +111 -0
  93. package/dist/model-picker-model.js +25 -0
  94. package/dist/model-picker-model.js.map +1 -0
  95. package/dist/{model-policy-picker-menu-WRNSRFQC.js → model-policy-picker-menu-NM4RPTY6.js} +6 -4
  96. package/dist/model-policy-picker-menu-NM4RPTY6.js.map +1 -0
  97. package/dist/model-policy.d.ts +10 -0
  98. package/dist/model-policy.js +5 -1
  99. package/dist/organization-model.d.ts +32 -0
  100. package/dist/organization-model.js +65 -0
  101. package/dist/organization-model.js.map +1 -0
  102. package/dist/{platform-activity-row-PJJVATTZ.js → platform-activity-row-NJ47YBXW.js} +7 -84
  103. package/dist/platform-activity-row-NJ47YBXW.js.map +1 -0
  104. package/dist/queue-presentation-model.d.ts +72 -0
  105. package/dist/queue-presentation-model.js +38 -0
  106. package/dist/queue-presentation-model.js.map +1 -0
  107. package/dist/{queue-surface-implementation-67FS7FUI.js → queue-surface-implementation-YPJFQ3O6.js} +24 -252
  108. package/dist/queue-surface-implementation-YPJFQ3O6.js.map +1 -0
  109. package/dist/realtime.js +5 -3
  110. package/dist/{sandbox-files-34CJJNOY.js → sandbox-files-RCVCMXG7.js} +5 -5
  111. package/dist/sandbox-files-RCVCMXG7.js.map +1 -0
  112. package/dist/sandbox-label-model.d.ts +23 -0
  113. package/dist/sandbox-label-model.js +28 -0
  114. package/dist/sandbox-label-model.js.map +1 -0
  115. package/dist/session-attention-model.d.ts +8 -0
  116. package/dist/session-attention-model.js +46 -0
  117. package/dist/session-attention-model.js.map +1 -0
  118. package/dist/session-feedback-model.d.ts +20 -0
  119. package/dist/session-feedback-model.js +56 -0
  120. package/dist/session-feedback-model.js.map +1 -0
  121. package/dist/session-list-model.d.ts +96 -0
  122. package/dist/session-list-model.js +219 -0
  123. package/dist/session-list-model.js.map +1 -0
  124. package/dist/session-status-model.d.ts +19 -0
  125. package/dist/session-ui.js +26 -17
  126. package/dist/session-ui.js.map +1 -1
  127. package/dist/session.js +8 -6
  128. package/dist/testing/session-scenarios.d.ts +10 -0
  129. package/dist/testing/session-scenarios.js +303 -0
  130. package/dist/testing/session-scenarios.js.map +1 -0
  131. package/dist/timeline/genie-copy.d.ts +3 -0
  132. package/dist/timeline/genie-loading.d.ts +11 -0
  133. package/dist/timeline/index.d.ts +1 -1
  134. package/dist/timeline/notice-presentation.d.ts +7 -0
  135. package/dist/timeline/patch-apply-command.d.ts +18 -0
  136. package/dist/timeline/platform-activity-presentation.d.ts +7 -0
  137. package/dist/timeline/presented-image.d.ts +6 -1
  138. package/dist/timeline/question-nav-model.d.ts +23 -0
  139. package/dist/timeline/registry.d.ts +10 -1
  140. package/dist/timeline/retained-loaders.d.ts +1 -1
  141. package/dist/timeline/tool-presentation.d.ts +172 -0
  142. package/dist/timeline/turn-summary-model.d.ts +90 -0
  143. package/dist/timeline/turn-summary.d.ts +4 -74
  144. package/dist/timeline/work-presentation.d.ts +42 -0
  145. package/dist/timeline-model.d.ts +24 -0
  146. package/dist/timeline-model.js +152 -0
  147. package/dist/timeline-model.js.map +1 -0
  148. package/package.json +47 -3
  149. package/src/artifacts.ts +1 -0
  150. package/src/client.ts +9 -3
  151. package/src/components/browser-viewer.tsx +23 -2
  152. package/src/components/claude-mark.tsx +2 -1
  153. package/src/components/composer.tsx +4 -144
  154. package/src/components/computer-viewer.tsx +139 -30
  155. package/src/components/grok-mark.tsx +2 -1
  156. package/src/components/human-input-form.tsx +13 -124
  157. package/src/components/markdown.tsx +19 -1
  158. package/src/components/message-timeline.tsx +45 -99
  159. package/src/components/model-mark.tsx +2 -1
  160. package/src/components/model-policy-picker-menu.tsx +30 -85
  161. package/src/components/model-policy-picker.tsx +15 -148
  162. package/src/components/opper-mark.tsx +18 -0
  163. package/src/components/provider-recovery-notice.tsx +41 -0
  164. package/src/components/queue-surface-implementation.tsx +20 -349
  165. package/src/components/remark-soft-line-breaks.ts +166 -0
  166. package/src/components/sandbox-workspace.tsx +17 -1
  167. package/src/components/session-chrome.tsx +114 -99
  168. package/src/components/session-conversation.tsx +55 -6
  169. package/src/components/session-list.tsx +1 -1
  170. package/src/components/session-status.tsx +17 -16
  171. package/src/composer-messages.ts +150 -0
  172. package/src/connect-setup.tsx +45 -11
  173. package/src/connect.ts +1 -1
  174. package/src/hooks/shared-machines-list.ts +34 -1
  175. package/src/hooks/use-browser-session.ts +445 -168
  176. package/src/hooks/use-client-config-flags.ts +8 -0
  177. package/src/hooks/use-computer-session.ts +334 -98
  178. package/src/hooks/use-goal.ts +66 -10
  179. package/src/human-input-model.ts +147 -0
  180. package/src/index.ts +16 -0
  181. package/src/lib/clipboard.ts +29 -0
  182. package/src/lib/format.ts +7 -0
  183. package/src/lib/provider-recovery.ts +202 -0
  184. package/src/model-mark-paths.ts +53 -0
  185. package/src/model-picker-model.ts +330 -0
  186. package/src/model-policy.ts +43 -2
  187. package/src/organization-model.ts +118 -0
  188. package/src/queue-presentation-model.ts +464 -0
  189. package/src/sandbox-label-model.ts +41 -0
  190. package/src/session-attention-model.ts +59 -0
  191. package/src/session-feedback-model.ts +95 -0
  192. package/src/session-list-model.ts +327 -0
  193. package/src/session-status-model.ts +62 -0
  194. package/src/testing/session-scenarios.ts +326 -0
  195. package/src/timeline/activity-rail.tsx +5 -17
  196. package/src/timeline/genie-copy.ts +19 -0
  197. package/src/timeline/genie-loading.tsx +13 -18
  198. package/src/timeline/index.ts +1 -0
  199. package/src/timeline/notice-presentation.ts +22 -0
  200. package/src/timeline/patch-apply-command.tsx +135 -0
  201. package/src/timeline/platform-activity-presentation.ts +122 -0
  202. package/src/timeline/platform-activity-row.tsx +6 -96
  203. package/src/timeline/presented-image.ts +16 -2
  204. package/src/timeline/question-nav-model.ts +28 -0
  205. package/src/timeline/registry.ts +11 -1
  206. package/src/timeline/retained-loaders.ts +9 -4
  207. package/src/timeline/rolling-activity.tsx +7 -19
  208. package/src/timeline/tool-presentation.ts +1316 -0
  209. package/src/timeline/tool-renderers.tsx +226 -1025
  210. package/src/timeline/turn-summary-model.ts +338 -0
  211. package/src/timeline/turn-summary.tsx +21 -326
  212. package/src/timeline/work-presentation.ts +139 -0
  213. package/src/timeline-model.ts +108 -0
  214. package/styles/compiled.css +8 -0
  215. package/styles/connect.css +4 -0
  216. package/dist/chunk-CREMJMVN.js.map +0 -1
  217. package/dist/chunk-CVYCLFMH.js.map +0 -1
  218. package/dist/chunk-G6YRCIYJ.js.map +0 -1
  219. package/dist/chunk-HXYOSSQO.js +0 -117
  220. package/dist/chunk-HXYOSSQO.js.map +0 -1
  221. package/dist/chunk-IUHHPMAX.js.map +0 -1
  222. package/dist/chunk-IYQCWGU5.js.map +0 -1
  223. package/dist/chunk-JH7V627O.js.map +0 -1
  224. package/dist/chunk-L2J3PU7A.js.map +0 -1
  225. package/dist/chunk-LVS3MH5T.js.map +0 -1
  226. package/dist/chunk-MDIXFKA3.js.map +0 -1
  227. package/dist/chunk-PHBFJCEU.js.map +0 -1
  228. package/dist/chunk-VCSERYXH.js.map +0 -1
  229. package/dist/chunk-XS67YG5R.js.map +0 -1
  230. package/dist/platform-activity-row-PJJVATTZ.js.map +0 -1
  231. package/dist/queue-surface-implementation-67FS7FUI.js.map +0 -1
  232. /package/dist/{browser-viewer-WGJ43YGI.js.map → browser-viewer-CV23VIHB.js.map} +0 -0
  233. /package/dist/{chunk-YVFRBXST.js.map → chunk-4BCVCJSU.js.map} +0 -0
  234. /package/dist/{chunk-PBCZL4JP.js.map → chunk-INIZSNXT.js.map} +0 -0
  235. /package/dist/{chunk-C5BF4L26.js.map → chunk-KHF2VRXF.js.map} +0 -0
  236. /package/dist/{chunk-QMMCJGFI.js.map → chunk-L5OKM2VX.js.map} +0 -0
  237. /package/dist/{computer-viewer-46UIN7F3.js.map → composer-messages.js.map} +0 -0
  238. /package/dist/{model-policy-picker-menu-WRNSRFQC.js.map → computer-viewer-K4CKYRX6.js.map} +0 -0
  239. /package/dist/{latest-question-2POFPYNB.js.map → latest-question-SWC6QEVN.js.map} +0 -0
  240. /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"]}