@stigmer/react 3.8.0 → 3.10.0
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/attachment/AttachmentChipList.d.ts +16 -4
- package/attachment/AttachmentChipList.d.ts.map +1 -1
- package/attachment/AttachmentChipList.js +106 -11
- package/attachment/AttachmentChipList.js.map +1 -1
- package/attachment/AttachmentImageLightbox.d.ts +39 -0
- package/attachment/AttachmentImageLightbox.d.ts.map +1 -0
- package/attachment/AttachmentImageLightbox.js +57 -0
- package/attachment/AttachmentImageLightbox.js.map +1 -0
- package/attachment/attachment-utils.d.ts +11 -0
- package/attachment/attachment-utils.d.ts.map +1 -1
- package/attachment/attachment-utils.js +23 -0
- package/attachment/attachment-utils.js.map +1 -1
- package/attachment/clipboard.d.ts +51 -0
- package/attachment/clipboard.d.ts.map +1 -0
- package/attachment/clipboard.js +89 -0
- package/attachment/clipboard.js.map +1 -0
- package/attachment/index.d.ts +6 -1
- package/attachment/index.d.ts.map +1 -1
- package/attachment/index.js +4 -1
- package/attachment/index.js.map +1 -1
- package/attachment/prepare-image.d.ts +43 -0
- package/attachment/prepare-image.d.ts.map +1 -0
- package/attachment/prepare-image.js +162 -0
- package/attachment/prepare-image.js.map +1 -0
- package/attachment/useAttachments.d.ts.map +1 -1
- package/attachment/useAttachments.js +23 -3
- package/attachment/useAttachments.js.map +1 -1
- package/attachment/useObjectUrl.d.ts +15 -0
- package/attachment/useObjectUrl.d.ts.map +1 -0
- package/attachment/useObjectUrl.js +25 -0
- package/attachment/useObjectUrl.js.map +1 -0
- package/attachment/vision-fit.d.ts +50 -0
- package/attachment/vision-fit.d.ts.map +1 -0
- package/attachment/vision-fit.js +76 -0
- package/attachment/vision-fit.js.map +1 -0
- package/composer/SessionComposer.d.ts +3 -1
- package/composer/SessionComposer.d.ts.map +1 -1
- package/composer/SessionComposer.js +50 -4
- package/composer/SessionComposer.js.map +1 -1
- package/conversation/ConversationMediaAttachment.d.ts +45 -0
- package/conversation/ConversationMediaAttachment.d.ts.map +1 -0
- package/conversation/ConversationMediaAttachment.js +153 -0
- package/conversation/ConversationMediaAttachment.js.map +1 -0
- package/conversation/ConversationTimelineView.d.ts +18 -1
- package/conversation/ConversationTimelineView.d.ts.map +1 -1
- package/conversation/ConversationTimelineView.js +14 -5
- package/conversation/ConversationTimelineView.js.map +1 -1
- package/conversation/ConversationsWorkbench.d.ts.map +1 -1
- package/conversation/ConversationsWorkbench.js +1 -1
- package/conversation/ConversationsWorkbench.js.map +1 -1
- package/conversation/conversationPresentation.d.ts +10 -3
- package/conversation/conversationPresentation.d.ts.map +1 -1
- package/conversation/conversationPresentation.js +10 -3
- package/conversation/conversationPresentation.js.map +1 -1
- package/conversation/index.d.ts +2 -0
- package/conversation/index.d.ts.map +1 -1
- package/conversation/index.js +1 -0
- package/conversation/index.js.map +1 -1
- package/conversation/useConversationMediaUrl.d.ts +65 -0
- package/conversation/useConversationMediaUrl.d.ts.map +1 -0
- package/conversation/useConversationMediaUrl.js +61 -0
- package/conversation/useConversationMediaUrl.js.map +1 -0
- package/execution/MessageAttachments.d.ts +52 -0
- package/execution/MessageAttachments.d.ts.map +1 -0
- package/execution/MessageAttachments.js +142 -0
- package/execution/MessageAttachments.js.map +1 -0
- package/execution/MessageEntry.d.ts +18 -0
- package/execution/MessageEntry.d.ts.map +1 -1
- package/execution/MessageEntry.js +5 -4
- package/execution/MessageEntry.js.map +1 -1
- package/execution/MessageThread.d.ts +15 -2
- package/execution/MessageThread.d.ts.map +1 -1
- package/execution/MessageThread.js +24 -7
- package/execution/MessageThread.js.map +1 -1
- package/execution/index.d.ts +2 -0
- package/execution/index.d.ts.map +1 -1
- package/execution/index.js +1 -0
- package/execution/index.js.map +1 -1
- package/github/decodeGitHubContent.d.ts +10 -5
- package/github/decodeGitHubContent.d.ts.map +1 -1
- package/github/decodeGitHubContent.js +21 -7
- package/github/decodeGitHubContent.js.map +1 -1
- package/github/useGitHubFileReader.d.ts.map +1 -1
- package/github/useGitHubFileReader.js +5 -5
- package/github/useGitHubFileReader.js.map +1 -1
- package/index.d.ts +5 -5
- package/index.d.ts.map +1 -1
- package/index.js +5 -4
- package/index.js.map +1 -1
- package/internal/form-primitives.d.ts +13 -0
- package/internal/form-primitives.d.ts.map +1 -1
- package/internal/form-primitives.js +13 -0
- package/internal/form-primitives.js.map +1 -1
- package/package.json +4 -4
- package/session/SessionViewer.js +1 -1
- package/session/SessionViewer.js.map +1 -1
- package/session/useSessionConversation.d.ts +8 -0
- package/session/useSessionConversation.d.ts.map +1 -1
- package/session/useSessionConversation.js +12 -2
- package/session/useSessionConversation.js.map +1 -1
- package/src/attachment/AttachmentChipList.tsx +330 -40
- package/src/attachment/AttachmentImageLightbox.tsx +156 -0
- package/src/attachment/__tests__/AttachmentChipList.test.tsx +326 -0
- package/src/attachment/__tests__/attachment-utils.test.ts +54 -0
- package/src/attachment/__tests__/clipboard.test.ts +110 -0
- package/src/attachment/__tests__/prepare-image.browser.test.ts +166 -0
- package/src/attachment/__tests__/prepare-image.test.ts +32 -0
- package/src/attachment/__tests__/vision-fit.test.ts +93 -0
- package/src/attachment/attachment-utils.ts +27 -0
- package/src/attachment/clipboard.ts +102 -0
- package/src/attachment/index.ts +13 -0
- package/src/attachment/prepare-image.ts +179 -0
- package/src/attachment/useAttachments.ts +26 -2
- package/src/attachment/useObjectUrl.ts +28 -0
- package/src/attachment/vision-fit.ts +90 -0
- package/src/composer/SessionComposer.tsx +73 -4
- package/src/composer/__tests__/SessionComposer-paste.test.tsx +263 -0
- package/src/composer/__tests__/SessionComposer-uploadGate.test.tsx +239 -0
- package/src/conversation/ConversationMediaAttachment.tsx +308 -0
- package/src/conversation/ConversationTimelineView.tsx +60 -10
- package/src/conversation/ConversationsWorkbench.tsx +2 -0
- package/src/conversation/__tests__/ConversationTimelineView.test.tsx +233 -6
- package/src/conversation/__tests__/a11y/conversation-surfaces.a11y.test.tsx +67 -1
- package/src/conversation/__tests__/useConversationMediaUrl.test.tsx +66 -0
- package/src/conversation/conversationPresentation.ts +10 -3
- package/src/conversation/index.ts +6 -0
- package/src/conversation/useConversationMediaUrl.ts +121 -0
- package/src/execution/MessageAttachments.tsx +364 -0
- package/src/execution/MessageEntry.tsx +38 -0
- package/src/execution/MessageThread.tsx +44 -4
- package/src/execution/__tests__/MessageEntry-attachments.test.tsx +228 -0
- package/src/execution/__tests__/buildThreadItems-attachments.test.ts +174 -0
- package/src/execution/index.ts +6 -0
- package/src/github/__tests__/decodeGitHubContent.test.ts +42 -1
- package/src/github/decodeGitHubContent.ts +22 -5
- package/src/github/useGitHubFileReader.ts +13 -3
- package/src/index.ts +16 -1
- package/src/internal/form-primitives.tsx +14 -0
- package/src/session/SessionViewer.tsx +1 -0
- package/src/session/__tests__/useSessionConversation.test.tsx +62 -0
- package/src/session/useSessionConversation.ts +21 -2
- package/src/workspace/FileViewer.tsx +109 -0
- package/src/workspace/WorkspaceFileReader.ts +55 -1
- package/src/workspace/__tests__/FileViewer.test.tsx +98 -0
- package/src/workspace/index.ts +2 -0
- package/styles.css +1 -1
- package/workspace/FileViewer.d.ts.map +1 -1
- package/workspace/FileViewer.js +40 -2
- package/workspace/FileViewer.js.map +1 -1
- package/workspace/WorkspaceFileReader.d.ts +29 -1
- package/workspace/WorkspaceFileReader.d.ts.map +1 -1
- package/workspace/WorkspaceFileReader.js +42 -0
- package/workspace/WorkspaceFileReader.js.map +1 -1
- package/workspace/index.d.ts +1 -1
- package/workspace/index.d.ts.map +1 -1
- package/workspace/index.js +1 -1
- package/workspace/index.js.map +1 -1
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-side image preparation for agent vision — the canvas half of
|
|
3
|
+
* "paste a screenshot and the agent sees it" (stigmer/stigmer#284).
|
|
4
|
+
*
|
|
5
|
+
* A screenshot from a large display is routinely a 4-10 MB PNG. The runner
|
|
6
|
+
* delivers images to the model inline only under its per-image byte cap
|
|
7
|
+
* (3 MiB raw; see the runner's `shared/attachment-vision.ts`), so an
|
|
8
|
+
* unprepared paste degrades to "I can't see this file". Bounding the image
|
|
9
|
+
* to the resolution providers actually process (see vision-fit.ts) is
|
|
10
|
+
* quality-neutral and brings real screenshots far under that cap — while
|
|
11
|
+
* also making the upload roughly 20× faster.
|
|
12
|
+
*
|
|
13
|
+
* Applied to PASTED images only, by the composer's paste handler. Picked
|
|
14
|
+
* and dragged files are never re-encoded: a chosen file may be the subject
|
|
15
|
+
* of the task ("read the EXIF", "embed this logo"), and silently altering
|
|
16
|
+
* it would be a regression. A pasted image has no file identity to preserve.
|
|
17
|
+
*
|
|
18
|
+
* Failure policy: this module never throws and never returns a broken file.
|
|
19
|
+
* Every failure path — no canvas API (old browsers, privacy extensions,
|
|
20
|
+
* non-browser test environments), undecodable bytes, encoder failure —
|
|
21
|
+
* returns the ORIGINAL file, which still works end to end: it uploads,
|
|
22
|
+
* mounts in the workspace, and merely degrades at the runner with the
|
|
23
|
+
* standard "not viewable inline" disclosure.
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Bounds a pasted image to the resolution vision providers actually
|
|
27
|
+
* process, re-encoding to a format both harnesses can display inline.
|
|
28
|
+
*
|
|
29
|
+
* - PNG and JPEG within the resolution limits pass through byte-identical
|
|
30
|
+
* (also guards edit-and-resubmit flows against generation loss).
|
|
31
|
+
* - GIF within the limits passes through untouched — re-encoding would
|
|
32
|
+
* silently flatten an animation the agent also receives as a file.
|
|
33
|
+
* - Oversized images resize to {@link fitToVisionResolution}; other formats
|
|
34
|
+
* (WebP, TIFF, BMP…) re-encode even when small, for harness visibility.
|
|
35
|
+
* - Output format: JPEG stays JPEG; everything else prefers PNG (crisp UI
|
|
36
|
+
* text), switching to JPEG only for photographic content — detected by
|
|
37
|
+
* PNG byte density, where PNG can exceed the runner's inline byte cap.
|
|
38
|
+
*
|
|
39
|
+
* Never throws; every failure path returns the original file (see module
|
|
40
|
+
* doc). Non-image files are returned unchanged.
|
|
41
|
+
*/
|
|
42
|
+
export declare function prepareImageForVision(file: File): Promise<File>;
|
|
43
|
+
//# sourceMappingURL=prepare-image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-image.d.ts","sourceRoot":"","sources":["../../src/attachment/prepare-image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAqDH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAqFrE"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Browser-side image preparation for agent vision — the canvas half of
|
|
3
|
+
* "paste a screenshot and the agent sees it" (stigmer/stigmer#284).
|
|
4
|
+
*
|
|
5
|
+
* A screenshot from a large display is routinely a 4-10 MB PNG. The runner
|
|
6
|
+
* delivers images to the model inline only under its per-image byte cap
|
|
7
|
+
* (3 MiB raw; see the runner's `shared/attachment-vision.ts`), so an
|
|
8
|
+
* unprepared paste degrades to "I can't see this file". Bounding the image
|
|
9
|
+
* to the resolution providers actually process (see vision-fit.ts) is
|
|
10
|
+
* quality-neutral and brings real screenshots far under that cap — while
|
|
11
|
+
* also making the upload roughly 20× faster.
|
|
12
|
+
*
|
|
13
|
+
* Applied to PASTED images only, by the composer's paste handler. Picked
|
|
14
|
+
* and dragged files are never re-encoded: a chosen file may be the subject
|
|
15
|
+
* of the task ("read the EXIF", "embed this logo"), and silently altering
|
|
16
|
+
* it would be a regression. A pasted image has no file identity to preserve.
|
|
17
|
+
*
|
|
18
|
+
* Failure policy: this module never throws and never returns a broken file.
|
|
19
|
+
* Every failure path — no canvas API (old browsers, privacy extensions,
|
|
20
|
+
* non-browser test environments), undecodable bytes, encoder failure —
|
|
21
|
+
* returns the ORIGINAL file, which still works end to end: it uploads,
|
|
22
|
+
* mounts in the workspace, and merely degrades at the runner with the
|
|
23
|
+
* standard "not viewable inline" disclosure.
|
|
24
|
+
*/
|
|
25
|
+
import { exceedsVisionResolution, fitToVisionResolution, } from "./vision-fit.js";
|
|
26
|
+
/**
|
|
27
|
+
* Formats the harnesses can display inline everywhere: the Cursor harness
|
|
28
|
+
* re-sniffs magic bytes and recognizes ONLY PNG and JPEG (the deep-agent
|
|
29
|
+
* harness also takes WebP/GIF). Anything else that must ride as pixels is
|
|
30
|
+
* re-encoded to PNG so a Safari TIFF or Chrome WebP paste is not invisible
|
|
31
|
+
* on one harness.
|
|
32
|
+
*/
|
|
33
|
+
const UNIVERSAL_VISION_TYPES = new Set(["image/png", "image/jpeg"]);
|
|
34
|
+
/**
|
|
35
|
+
* PNG density (encoded bytes per pixel) above which content is treated as
|
|
36
|
+
* photographic and re-encoded as JPEG instead.
|
|
37
|
+
*
|
|
38
|
+
* PNG keeps UI text crisp and compresses flat screenshot content to
|
|
39
|
+
* 0.1-0.5 B/px, but photographic content in PNG runs 1.5-3 B/px and can
|
|
40
|
+
* exceed the runner's 3 MiB inline cap even at the fitted resolution
|
|
41
|
+
* (measured: ~3.4 MB for worst-case noise at 1.15 MP). Density is the
|
|
42
|
+
* content signal — scale-invariant, so small UI images never flip to JPEG
|
|
43
|
+
* just because their absolute sizes are tiny (a pure size ratio fails
|
|
44
|
+
* exactly that way) — and it bounds every kept PNG by construction:
|
|
45
|
+
* 1.15 MP × 1.0 B/px ≈ 1.1 MB, far inside the runner's cap, without this
|
|
46
|
+
* module ever referencing the runner's byte constant.
|
|
47
|
+
*/
|
|
48
|
+
const PHOTOGRAPHIC_PNG_BYTES_PER_PIXEL = 1.0;
|
|
49
|
+
const JPEG_QUALITY = 0.9;
|
|
50
|
+
function replaceExtension(name, ext) {
|
|
51
|
+
const dotIndex = name.lastIndexOf(".");
|
|
52
|
+
const stem = dotIndex > 0 ? name.slice(0, dotIndex) : name;
|
|
53
|
+
return `${stem}.${ext}`;
|
|
54
|
+
}
|
|
55
|
+
function encodeCanvas(canvas, type, quality) {
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
try {
|
|
58
|
+
canvas.toBlob(resolve, type, quality);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
resolve(null);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Bounds a pasted image to the resolution vision providers actually
|
|
67
|
+
* process, re-encoding to a format both harnesses can display inline.
|
|
68
|
+
*
|
|
69
|
+
* - PNG and JPEG within the resolution limits pass through byte-identical
|
|
70
|
+
* (also guards edit-and-resubmit flows against generation loss).
|
|
71
|
+
* - GIF within the limits passes through untouched — re-encoding would
|
|
72
|
+
* silently flatten an animation the agent also receives as a file.
|
|
73
|
+
* - Oversized images resize to {@link fitToVisionResolution}; other formats
|
|
74
|
+
* (WebP, TIFF, BMP…) re-encode even when small, for harness visibility.
|
|
75
|
+
* - Output format: JPEG stays JPEG; everything else prefers PNG (crisp UI
|
|
76
|
+
* text), switching to JPEG only for photographic content — detected by
|
|
77
|
+
* PNG byte density, where PNG can exceed the runner's inline byte cap.
|
|
78
|
+
*
|
|
79
|
+
* Never throws; every failure path returns the original file (see module
|
|
80
|
+
* doc). Non-image files are returned unchanged.
|
|
81
|
+
*/
|
|
82
|
+
export async function prepareImageForVision(file) {
|
|
83
|
+
const sourceType = file.type.toLowerCase();
|
|
84
|
+
if (!sourceType.startsWith("image/"))
|
|
85
|
+
return file;
|
|
86
|
+
if (typeof createImageBitmap !== "function" || typeof document === "undefined") {
|
|
87
|
+
return file;
|
|
88
|
+
}
|
|
89
|
+
let bitmap;
|
|
90
|
+
try {
|
|
91
|
+
// "from-image" applies EXIF orientation, so a pasted phone photo lands
|
|
92
|
+
// upright instead of sideways (most browsers default to this, older
|
|
93
|
+
// Safari does not).
|
|
94
|
+
bitmap = await createImageBitmap(file, { imageOrientation: "from-image" });
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
return file;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
const needsResize = exceedsVisionResolution(bitmap.width, bitmap.height);
|
|
101
|
+
const isGif = sourceType === "image/gif";
|
|
102
|
+
// Within limits and already displayable everywhere (or an animated GIF,
|
|
103
|
+
// which only the resize case may flatten): leave every byte alone.
|
|
104
|
+
if (!needsResize && (UNIVERSAL_VISION_TYPES.has(sourceType) || isGif)) {
|
|
105
|
+
return file;
|
|
106
|
+
}
|
|
107
|
+
const target = needsResize
|
|
108
|
+
? fitToVisionResolution(bitmap.width, bitmap.height)
|
|
109
|
+
: { width: bitmap.width, height: bitmap.height };
|
|
110
|
+
const canvas = document.createElement("canvas");
|
|
111
|
+
canvas.width = target.width;
|
|
112
|
+
canvas.height = target.height;
|
|
113
|
+
const ctx = canvas.getContext("2d");
|
|
114
|
+
if (!ctx)
|
|
115
|
+
return file;
|
|
116
|
+
ctx.drawImage(bitmap, 0, 0, target.width, target.height);
|
|
117
|
+
let blob;
|
|
118
|
+
let outType;
|
|
119
|
+
if (sourceType === "image/jpeg") {
|
|
120
|
+
outType = "image/jpeg";
|
|
121
|
+
blob = await encodeCanvas(canvas, outType, JPEG_QUALITY);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
const png = await encodeCanvas(canvas, "image/png");
|
|
125
|
+
const pngDensity = png ? png.size / (target.width * target.height) : Infinity;
|
|
126
|
+
if (png && pngDensity <= PHOTOGRAPHIC_PNG_BYTES_PER_PIXEL) {
|
|
127
|
+
outType = "image/png";
|
|
128
|
+
blob = png;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
// Photographic content (or a failed PNG encode): take JPEG. JPEG
|
|
132
|
+
// cannot represent alpha, so composite onto white first —
|
|
133
|
+
// destination-over paints beneath the already-drawn image, and the
|
|
134
|
+
// alpha-preserving PNG encode above is already done.
|
|
135
|
+
ctx.globalCompositeOperation = "destination-over";
|
|
136
|
+
ctx.fillStyle = "#ffffff";
|
|
137
|
+
ctx.fillRect(0, 0, target.width, target.height);
|
|
138
|
+
const jpeg = await encodeCanvas(canvas, "image/jpeg", JPEG_QUALITY);
|
|
139
|
+
blob = jpeg ?? png;
|
|
140
|
+
outType = jpeg ? "image/jpeg" : "image/png";
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!blob)
|
|
144
|
+
return file;
|
|
145
|
+
// A pure resize that somehow grew the file is a regression, not a win:
|
|
146
|
+
// the runner caps bytes, not pixels, so the smaller original is the
|
|
147
|
+
// better payload. (Cross-format re-encodes are exempt — growing a WebP
|
|
148
|
+
// into a PNG is the price of being visible on the Cursor harness.)
|
|
149
|
+
if (outType === sourceType && blob.size >= file.size)
|
|
150
|
+
return file;
|
|
151
|
+
const extension = outType === "image/jpeg" ? "jpg" : "png";
|
|
152
|
+
const name = outType === sourceType ? file.name : replaceExtension(file.name, extension);
|
|
153
|
+
return new File([blob], name, {
|
|
154
|
+
type: outType,
|
|
155
|
+
lastModified: file.lastModified,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
bitmap.close();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=prepare-image.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prepare-image.js","sourceRoot":"","sources":["../../src/attachment/prepare-image.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAttachments.d.ts","sourceRoot":"","sources":["../../src/attachment/useAttachments.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"useAttachments.d.ts","sourceRoot":"","sources":["../../src/attachment/useAttachments.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAcpD;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,OAAO,GAAG,OAAO,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,eAAe,CAAC;IAChC,kDAAkD;IAClD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,mEAAmE;IACnE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,0CAA0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACxD;AAED,8CAA8C;AAC9C,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,QAAQ,CAAC,OAAO,EAAE,SAAS,eAAe,EAAE,CAAC;IAC7C,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,uDAAuD;IACvD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,iFAAiF;IACjF,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,4DAA4D;IAC5D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,EAAE,KAAK,IAAI,CAAC;IACtD,kEAAkE;IAClE,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3C,6BAA6B;IAC7B,QAAQ,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,yDAAyD;IACzD,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,kBAAkB,EAAE,MAAM,eAAe,EAAE,CAAC;CACtD;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,wBAAgB,cAAc,CAC5B,OAAO,CAAC,EAAE,qBAAqB,GAC9B,oBAAoB,CA4KtB"}
|
|
@@ -4,7 +4,7 @@ import { create } from "@bufbuild/protobuf";
|
|
|
4
4
|
import { UploadAttachmentRequestSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/io_pb";
|
|
5
5
|
import { useStigmer } from "../hooks.js";
|
|
6
6
|
import { toError } from "../internal/toError.js";
|
|
7
|
-
import { detectContentType, validateAttachmentSize, } from "./attachment-utils.js";
|
|
7
|
+
import { detectContentType, uniquifyFilename, validateAttachmentSize, } from "./attachment-utils.js";
|
|
8
8
|
// ---------------------------------------------------------------------------
|
|
9
9
|
// Hook
|
|
10
10
|
// ---------------------------------------------------------------------------
|
|
@@ -65,6 +65,13 @@ export function useAttachments(options) {
|
|
|
65
65
|
const stigmer = useStigmer();
|
|
66
66
|
const [entries, setEntries] = useState([]);
|
|
67
67
|
const abortControllers = useRef(new Map());
|
|
68
|
+
// Latest-entries mirror so `addFiles` can uniquify filenames against
|
|
69
|
+
// current entries without depending on `entries` (which would give the
|
|
70
|
+
// callback a new identity every upload-phase change). Re-assigned each
|
|
71
|
+
// render to reconcile removals, and synchronously inside `addFiles` so
|
|
72
|
+
// two adds in one tick still see each other's names.
|
|
73
|
+
const entriesRef = useRef(entries);
|
|
74
|
+
entriesRef.current = entries;
|
|
68
75
|
const uploadFile = useCallback(async (id, file, contentType) => {
|
|
69
76
|
const controller = new AbortController();
|
|
70
77
|
abortControllers.current.set(id, controller);
|
|
@@ -98,12 +105,24 @@ export function useAttachments(options) {
|
|
|
98
105
|
const addFiles = useCallback((files) => {
|
|
99
106
|
const fileArray = Array.from(files);
|
|
100
107
|
const validEntries = [];
|
|
101
|
-
|
|
102
|
-
|
|
108
|
+
const takenNames = new Set(entriesRef.current.map((e) => e.file.name));
|
|
109
|
+
for (const rawFile of fileArray) {
|
|
110
|
+
const sizeError = validateAttachmentSize(rawFile);
|
|
103
111
|
if (sizeError) {
|
|
104
112
|
options?.onValidationError?.(sizeError);
|
|
105
113
|
continue;
|
|
106
114
|
}
|
|
115
|
+
// Duplicate names within a turn break the execution downstream
|
|
116
|
+
// (see uniquifyFilename) — rename before the bytes ever upload,
|
|
117
|
+
// so the chip, the upload, and the mounted file all agree.
|
|
118
|
+
const uniqueName = uniquifyFilename(rawFile.name, takenNames);
|
|
119
|
+
takenNames.add(uniqueName);
|
|
120
|
+
const file = uniqueName === rawFile.name
|
|
121
|
+
? rawFile
|
|
122
|
+
: new File([rawFile], uniqueName, {
|
|
123
|
+
type: rawFile.type,
|
|
124
|
+
lastModified: rawFile.lastModified,
|
|
125
|
+
});
|
|
107
126
|
const id = generateId();
|
|
108
127
|
const contentType = detectContentType(file);
|
|
109
128
|
validEntries.push({
|
|
@@ -117,6 +136,7 @@ export function useAttachments(options) {
|
|
|
117
136
|
uploadFile(id, file, contentType);
|
|
118
137
|
}
|
|
119
138
|
if (validEntries.length > 0) {
|
|
139
|
+
entriesRef.current = [...entriesRef.current, ...validEntries];
|
|
120
140
|
setEntries((prev) => [...prev, ...validEntries]);
|
|
121
141
|
}
|
|
122
142
|
}, [options, uploadFile]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAttachments.js","sourceRoot":"","sources":["../../src/attachment/useAttachments.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,6BAA6B,EAAE,MAAM,4DAA4D,CAAC;AAE3G,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EACL,iBAAiB,EAEjB,sBAAsB,GACvB,MAAM,uBAAuB,CAAC;AA2F/B,8EAA8E;AAC9E,OAAO;AACP,8EAA8E;AAE9E,IAAI,MAAM,GAAG,CAAC,CAAC;AACf,SAAS,UAAU;IACjB,OAAO,cAAc,EAAE,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,MAAM,UAAU,cAAc,CAC5B,OAA+B;IAE/B,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAoB,EAAE,CAAC,CAAC;IAC9D,MAAM,gBAAgB,GAAG,MAAM,CAA+B,IAAI,GAAG,EAAE,CAAC,CAAC;IAEzE,MAAM,UAAU,GAAG,WAAW,CAC5B,KAAK,EAAE,EAAU,EAAE,IAAU,EAAE,WAAmB,EAAE,EAAE;QACpD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,gBAAgB,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QAE7C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YAEvD,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO;YAEtC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,cAAc,CAAC,gBAAgB,CAC5D,MAAM,CAAC,6BAA6B,EAAE;gBACpC,QAAQ,EAAE,IAAI,CAAC,IAAI;gBACnB,OAAO,EAAE,KAAK;gBACd,WAAW;aACZ,CAAC,CACH,CAAC;YAEF,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO;YAEtC,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAClB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACb,CAAC,CAAC,EAAE,KAAK,EAAE;gBACT,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,OAAgB,EAAE,UAAU,EAAE,QAAQ,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE;gBACjF,CAAC,CAAC,CAAC,CACN,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,UAAU,CAAC,MAAM,CAAC,OAAO;gBAAE,OAAO;YAEtC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;YACrC,UAAU,CAAC,CAAC,IAAI,EAAE,EAAE,CAClB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACb,CAAC,CAAC,EAAE,KAAK,EAAE;gBACT,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,OAAgB,EAAE,KAAK,EAAE,OAAO,EAAE;gBACnD,CAAC,CAAC,CAAC,CACN,CACF,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,gBAAgB,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACtC,CAAC;IACH,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,KAAwB,EAAE,EAAE;QAC3B,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,YAAY,GAAsB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"useAttachments.js","sourceRoot":"","sources":["../../src/attachment/useAttachments.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Object URL over a locally-held `Blob` (or `File`), alive for the lifetime
|
|
3
|
+
* of the mounted component (no fetch — the bytes are already in memory).
|
|
4
|
+
*
|
|
5
|
+
* The URL is created in an effect, not a memo: StrictMode double-invokes
|
|
6
|
+
* memos and would leak the first URL without a revoke. The effect cleanup
|
|
7
|
+
* revokes on unmount and on blob change. Returns `null` until the effect
|
|
8
|
+
* runs (first paint) — callers render a fallback for that frame.
|
|
9
|
+
*
|
|
10
|
+
* Deliberately display-oriented: the SDK's other `createObjectURL` calls
|
|
11
|
+
* (`useExportResource`, `useExportCSV`) are fire-and-forget download
|
|
12
|
+
* helpers with an immediate revoke, a different lifecycle from this one.
|
|
13
|
+
*/
|
|
14
|
+
export declare function useObjectUrl(blob: Blob): string | null;
|
|
15
|
+
//# sourceMappingURL=useObjectUrl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useObjectUrl.d.ts","sourceRoot":"","sources":["../../src/attachment/useObjectUrl.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAUtD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Object URL over a locally-held `Blob` (or `File`), alive for the lifetime
|
|
5
|
+
* of the mounted component (no fetch — the bytes are already in memory).
|
|
6
|
+
*
|
|
7
|
+
* The URL is created in an effect, not a memo: StrictMode double-invokes
|
|
8
|
+
* memos and would leak the first URL without a revoke. The effect cleanup
|
|
9
|
+
* revokes on unmount and on blob change. Returns `null` until the effect
|
|
10
|
+
* runs (first paint) — callers render a fallback for that frame.
|
|
11
|
+
*
|
|
12
|
+
* Deliberately display-oriented: the SDK's other `createObjectURL` calls
|
|
13
|
+
* (`useExportResource`, `useExportCSV`) are fire-and-forget download
|
|
14
|
+
* helpers with an immediate revoke, a different lifecycle from this one.
|
|
15
|
+
*/
|
|
16
|
+
export function useObjectUrl(blob) {
|
|
17
|
+
const [url, setUrl] = useState(null);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const objectUrl = URL.createObjectURL(blob);
|
|
20
|
+
setUrl(objectUrl);
|
|
21
|
+
return () => URL.revokeObjectURL(objectUrl);
|
|
22
|
+
}, [blob]);
|
|
23
|
+
return url;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=useObjectUrl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useObjectUrl.js","sourceRoot":"","sources":["../../src/attachment/useObjectUrl.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAEpD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,SAAS,GAAG,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,CAAC,SAAS,CAAC,CAAC;QAClB,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IAC9C,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution policy for images attached to agent executions — the pure math
|
|
3
|
+
* behind {@link prepareImageForVision}.
|
|
4
|
+
*
|
|
5
|
+
* Vision providers cap what they will actually look at: Anthropic's standard
|
|
6
|
+
* tier downscales anything beyond a 1568 px long edge or ~1.15 megapixels
|
|
7
|
+
* before the model sees it (OpenAI's high-detail tiling lands in the same
|
|
8
|
+
* range). Shrinking to that ceiling in the browser is therefore
|
|
9
|
+
* quality-neutral — the provider would do it anyway — while cutting a 4-10 MB
|
|
10
|
+
* screenshot paste to a few hundred KB before it ever hits the wire.
|
|
11
|
+
*
|
|
12
|
+
* Deliberately NOT named "budget": in this codebase *vision budget* means the
|
|
13
|
+
* runner's per-turn byte/count budget (`VisionBudget` in the runner's
|
|
14
|
+
* `shared/attachment-vision.ts`, 3 MiB per image raw). That byte cap stays
|
|
15
|
+
* the runner's concern alone; this module bounds pixels, the provider's
|
|
16
|
+
* concern. Two limits, one owner each, no constants to drift.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Maximum long-edge length, mirroring Anthropic's standard-tier limit.
|
|
20
|
+
* @see https://platform.claude.com/docs/en/build-with-claude/vision
|
|
21
|
+
*/
|
|
22
|
+
export declare const MAX_VISION_LONG_EDGE_PX = 1568;
|
|
23
|
+
/**
|
|
24
|
+
* Maximum total pixels, mirroring Anthropic's standard-tier visual-token
|
|
25
|
+
* ceiling (1568 tokens ≈ 1.15 megapixels). For nearly all photos and
|
|
26
|
+
* screenshots this — not the edge limit — is the binding constraint: a
|
|
27
|
+
* 1920×1080 screenshot fits the edge limit but still resizes to 1456×819.
|
|
28
|
+
*/
|
|
29
|
+
export declare const MAX_VISION_PIXELS = 1150000;
|
|
30
|
+
/** Integer pixel dimensions produced by {@link fitToVisionResolution}. */
|
|
31
|
+
export interface VisionFitSize {
|
|
32
|
+
readonly width: number;
|
|
33
|
+
readonly height: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* True when an image of these dimensions would be downscaled by the
|
|
37
|
+
* provider — i.e. when resizing it ourselves loses nothing.
|
|
38
|
+
*/
|
|
39
|
+
export declare function exceedsVisionResolution(width: number, height: number): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* The largest size that fits both vision limits while preserving aspect
|
|
42
|
+
* ratio. Never upscales: dimensions already within the limits come back
|
|
43
|
+
* unchanged. Mirrors Anthropic's published "max API fit" computation.
|
|
44
|
+
*
|
|
45
|
+
* Degenerate inputs (zero, negative, or non-finite dimensions) come back
|
|
46
|
+
* unchanged — the caller's decode has already failed or will fail, and this
|
|
47
|
+
* module never turns a bad input into a crash.
|
|
48
|
+
*/
|
|
49
|
+
export declare function fitToVisionResolution(width: number, height: number): VisionFitSize;
|
|
50
|
+
//# sourceMappingURL=vision-fit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision-fit.d.ts","sourceRoot":"","sources":["../../src/attachment/vision-fit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;GAGG;AACH,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,UAAY,CAAC;AAE3C,0EAA0E;AAC1E,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAK9E;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CA+BlF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolution policy for images attached to agent executions — the pure math
|
|
3
|
+
* behind {@link prepareImageForVision}.
|
|
4
|
+
*
|
|
5
|
+
* Vision providers cap what they will actually look at: Anthropic's standard
|
|
6
|
+
* tier downscales anything beyond a 1568 px long edge or ~1.15 megapixels
|
|
7
|
+
* before the model sees it (OpenAI's high-detail tiling lands in the same
|
|
8
|
+
* range). Shrinking to that ceiling in the browser is therefore
|
|
9
|
+
* quality-neutral — the provider would do it anyway — while cutting a 4-10 MB
|
|
10
|
+
* screenshot paste to a few hundred KB before it ever hits the wire.
|
|
11
|
+
*
|
|
12
|
+
* Deliberately NOT named "budget": in this codebase *vision budget* means the
|
|
13
|
+
* runner's per-turn byte/count budget (`VisionBudget` in the runner's
|
|
14
|
+
* `shared/attachment-vision.ts`, 3 MiB per image raw). That byte cap stays
|
|
15
|
+
* the runner's concern alone; this module bounds pixels, the provider's
|
|
16
|
+
* concern. Two limits, one owner each, no constants to drift.
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Maximum long-edge length, mirroring Anthropic's standard-tier limit.
|
|
20
|
+
* @see https://platform.claude.com/docs/en/build-with-claude/vision
|
|
21
|
+
*/
|
|
22
|
+
export const MAX_VISION_LONG_EDGE_PX = 1568;
|
|
23
|
+
/**
|
|
24
|
+
* Maximum total pixels, mirroring Anthropic's standard-tier visual-token
|
|
25
|
+
* ceiling (1568 tokens ≈ 1.15 megapixels). For nearly all photos and
|
|
26
|
+
* screenshots this — not the edge limit — is the binding constraint: a
|
|
27
|
+
* 1920×1080 screenshot fits the edge limit but still resizes to 1456×819.
|
|
28
|
+
*/
|
|
29
|
+
export const MAX_VISION_PIXELS = 1_150_000;
|
|
30
|
+
/**
|
|
31
|
+
* True when an image of these dimensions would be downscaled by the
|
|
32
|
+
* provider — i.e. when resizing it ourselves loses nothing.
|
|
33
|
+
*/
|
|
34
|
+
export function exceedsVisionResolution(width, height) {
|
|
35
|
+
return (width * height > MAX_VISION_PIXELS ||
|
|
36
|
+
Math.max(width, height) > MAX_VISION_LONG_EDGE_PX);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The largest size that fits both vision limits while preserving aspect
|
|
40
|
+
* ratio. Never upscales: dimensions already within the limits come back
|
|
41
|
+
* unchanged. Mirrors Anthropic's published "max API fit" computation.
|
|
42
|
+
*
|
|
43
|
+
* Degenerate inputs (zero, negative, or non-finite dimensions) come back
|
|
44
|
+
* unchanged — the caller's decode has already failed or will fail, and this
|
|
45
|
+
* module never turns a bad input into a crash.
|
|
46
|
+
*/
|
|
47
|
+
export function fitToVisionResolution(width, height) {
|
|
48
|
+
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
|
|
49
|
+
return { width, height };
|
|
50
|
+
}
|
|
51
|
+
if (!exceedsVisionResolution(width, height)) {
|
|
52
|
+
return { width, height };
|
|
53
|
+
}
|
|
54
|
+
const aspect = width / height;
|
|
55
|
+
// Largest size under the pixel ceiling at this aspect ratio.
|
|
56
|
+
let fitHeight = Math.sqrt(MAX_VISION_PIXELS / aspect);
|
|
57
|
+
let fitWidth = fitHeight * aspect;
|
|
58
|
+
// The edge limit takes over only for extreme aspect ratios (panoramas,
|
|
59
|
+
// tall phone screenshots), where the pixel-fitted size still has a long
|
|
60
|
+
// edge beyond the cap.
|
|
61
|
+
if (Math.max(fitWidth, fitHeight) > MAX_VISION_LONG_EDGE_PX) {
|
|
62
|
+
if (fitWidth >= fitHeight) {
|
|
63
|
+
fitWidth = MAX_VISION_LONG_EDGE_PX;
|
|
64
|
+
fitHeight = fitWidth / aspect;
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
fitHeight = MAX_VISION_LONG_EDGE_PX;
|
|
68
|
+
fitWidth = fitHeight * aspect;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
width: Math.max(1, Math.floor(Math.min(fitWidth, width))),
|
|
73
|
+
height: Math.max(1, Math.floor(Math.min(fitHeight, height))),
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=vision-fit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vision-fit.js","sourceRoot":"","sources":["../../src/attachment/vision-fit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAE5C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,SAAS,CAAC;AAQ3C;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAa,EAAE,MAAc;IACnE,OAAO,CACL,KAAK,GAAG,MAAM,GAAG,iBAAiB;QAClC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,uBAAuB,CAClD,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa,EAAE,MAAc;IACjE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QACrF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC;IACD,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;QAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;IAE9B,6DAA6D;IAC7D,IAAI,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,CAAC;IACtD,IAAI,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;IAElC,uEAAuE;IACvE,wEAAwE;IACxE,uBAAuB;IACvB,IAAI,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,uBAAuB,EAAE,CAAC;QAC5D,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;YAC1B,QAAQ,GAAG,uBAAuB,CAAC;YACnC,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;QAChC,CAAC;aAAM,CAAC;YACN,SAAS,GAAG,uBAAuB,CAAC;YACpC,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;QAChC,CAAC;IACH,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;QACzD,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;KAC7D,CAAC;AACJ,CAAC"}
|
|
@@ -374,7 +374,9 @@ export interface SessionComposerProps {
|
|
|
374
374
|
* Enable file attachment support in the composer.
|
|
375
375
|
*
|
|
376
376
|
* When `true`, renders an attach button in the toolbar and enables
|
|
377
|
-
* drag-and-drop file upload on the textarea
|
|
377
|
+
* drag-and-drop file upload plus clipboard paste on the textarea —
|
|
378
|
+
* pasting a screenshot attaches it exactly like a picked file, with
|
|
379
|
+
* a generated `pasted-image-*` filename. Attachments are uploaded
|
|
378
380
|
* immediately via `agentExecution.uploadAttachment()` and included
|
|
379
381
|
* in `context.attachments` on submit.
|
|
380
382
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionComposer.d.ts","sourceRoot":"","sources":["../../src/composer/SessionComposer.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAkB,KAAK,eAAe,EAAE,KAAK,WAAW,EAAE,KAAK,mBAAmB,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAIlI,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAKxE,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAOhF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AACrF,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"SessionComposer.d.ts","sourceRoot":"","sources":["../../src/composer/SessionComposer.tsx"],"names":[],"mappings":"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"}
|