@agimon-ai/po-author 0.0.0-alpha.43 → 0.0.0-alpha.44
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/dist/extensions/native.mjs +56 -35
- package/dist/extensions/native.mjs.map +1 -1
- package/dist/extensions/server.cjs +88 -17
- package/dist/extensions/server.cjs.map +1 -1
- package/dist/extensions/server.mjs +88 -17
- package/dist/extensions/server.mjs.map +1 -1
- package/dist/extensions/web.mjs +31 -31
- package/dist/extensions/web.mjs.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{structuredDocuments-pCTpu4Fh.mjs → structuredDocuments-CgPhyk2v.mjs} +6 -4
- package/dist/structuredDocuments-CgPhyk2v.mjs.map +1 -0
- package/dist/{structuredDocuments-BAFRIGk8.cjs → structuredDocuments-D3T9t2EJ.cjs} +11 -3
- package/dist/structuredDocuments-D3T9t2EJ.cjs.map +1 -0
- package/package.json +9 -9
- package/dist/structuredDocuments-BAFRIGk8.cjs.map +0 -1
- package/dist/structuredDocuments-pCTpu4Fh.mjs.map +0 -1
|
@@ -800,6 +800,27 @@ function authorCaptureContext(packet) {
|
|
|
800
800
|
};
|
|
801
801
|
}
|
|
802
802
|
//#endregion
|
|
803
|
+
//#region src/extensions/workspaces/sessions/(frontend)/_lib/authorFileSave.ts
|
|
804
|
+
/** Web and native commit text, encoded images and serialized documents through this one conditional save. */
|
|
805
|
+
async function saveAuthorFileBytes(transport, url, path, body, expectedSha256, signal) {
|
|
806
|
+
if (path.startsWith("artifact:")) throw new Error("Artifacts are read-only.");
|
|
807
|
+
if (!/^[a-f0-9]{64}$/.test(expectedSha256)) throw new Error("This Author view has no valid source digest.");
|
|
808
|
+
const response = await transport(url, {
|
|
809
|
+
method: "PUT",
|
|
810
|
+
headers: {
|
|
811
|
+
"Content-Type": "application/octet-stream",
|
|
812
|
+
"X-Expected-SHA256": expectedSha256
|
|
813
|
+
},
|
|
814
|
+
body,
|
|
815
|
+
signal
|
|
816
|
+
});
|
|
817
|
+
if (response.status === 409) throw new Error("This file changed elsewhere. Keep your edits and reopen it before saving.");
|
|
818
|
+
if (!response.ok) throw new Error(`Author save failed (${String(response.status)})`);
|
|
819
|
+
const digest = response.headers.get("X-File-SHA256");
|
|
820
|
+
if (digest === null || !/^[a-f0-9]{64}$/.test(digest)) throw new Error("Author save returned an invalid digest.");
|
|
821
|
+
return digest;
|
|
822
|
+
}
|
|
823
|
+
//#endregion
|
|
803
824
|
//#region src/extensions/workspaces/sessions/(frontend)/_lib/authorFiles.native.ts
|
|
804
825
|
const MAX_FILE_BYTES = 5242880;
|
|
805
826
|
const IMAGE_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -856,8 +877,8 @@ function authorNativeCanOpen(path) {
|
|
|
856
877
|
}
|
|
857
878
|
/**
|
|
858
879
|
* The raw reads Author's canvas already uses, restated for the native transport:
|
|
859
|
-
* po-artifact's guarded artifact read and
|
|
860
|
-
*
|
|
880
|
+
* po-artifact's guarded artifact read and Author's session file API, plus the
|
|
881
|
+
* document routes from apiRoutes.ts, whose definer the phone does not load.
|
|
861
882
|
*/
|
|
862
883
|
const artifactFiles = createApiClient({ content: {
|
|
863
884
|
method: "GET",
|
|
@@ -875,14 +896,12 @@ const sessionFiles = createApiClient({
|
|
|
875
896
|
method: "GET",
|
|
876
897
|
path: "/file",
|
|
877
898
|
query: ["path"],
|
|
878
|
-
host: true,
|
|
879
899
|
raw: true
|
|
880
900
|
},
|
|
881
901
|
fileWrite: {
|
|
882
902
|
method: "PUT",
|
|
883
903
|
path: "/file",
|
|
884
904
|
query: ["path"],
|
|
885
|
-
host: true,
|
|
886
905
|
raw: true
|
|
887
906
|
},
|
|
888
907
|
documentsOpen: {
|
|
@@ -958,22 +977,7 @@ async function saveAuthorNativeImage(sessionId, path, image, sourceSha256, signa
|
|
|
958
977
|
return digest;
|
|
959
978
|
}
|
|
960
979
|
async function saveAuthorNativeBytes(sessionId, path, body, sourceSha256, signal) {
|
|
961
|
-
|
|
962
|
-
query: { path },
|
|
963
|
-
headers: {
|
|
964
|
-
"Content-Type": "application/octet-stream",
|
|
965
|
-
"X-Expected-SHA256": sourceSha256
|
|
966
|
-
},
|
|
967
|
-
body,
|
|
968
|
-
signal
|
|
969
|
-
});
|
|
970
|
-
if (!result.ok) {
|
|
971
|
-
if (result.status === 409) throw new Error("This file changed elsewhere. Keep your edits and reopen it before saving.");
|
|
972
|
-
throw new Error(result.error || `Author save failed (${String(result.status)})`);
|
|
973
|
-
}
|
|
974
|
-
const digest = result.response.headers.get("X-File-SHA256");
|
|
975
|
-
if (digest === null || !/^[a-f0-9]{64}$/.test(digest)) throw new Error("Author save returned an invalid digest.");
|
|
976
|
-
return digest;
|
|
980
|
+
return await saveAuthorFileBytes(nativeApiTransport, sessionFiles.session(sessionId).fileWrite.url({ query: { path } }), path, body, sourceSha256, signal);
|
|
977
981
|
}
|
|
978
982
|
/** Reads one document for marking up on the phone: an image as base64, anything textual as a string. */
|
|
979
983
|
async function loadAuthorFile(sessionId, path, signal) {
|
|
@@ -1247,6 +1251,18 @@ function authorNotesContent(path, notes) {
|
|
|
1247
1251
|
}
|
|
1248
1252
|
//#endregion
|
|
1249
1253
|
//#region src/extensions/workspaces/sessions/(frontend)/_lib/authorNativeCapture.ts
|
|
1254
|
+
/** Snapshot layout-unit geometry before asynchronous raster capture and reject any intervening transform change. */
|
|
1255
|
+
async function captureNativeAuthorViewport(capture, getViewport) {
|
|
1256
|
+
const viewport = getViewport();
|
|
1257
|
+
if (!viewport || ![viewport.width, viewport.height].every((value) => Number.isFinite(value) && value > 0)) throw new Error("The document geometry is not ready to capture.");
|
|
1258
|
+
const snapshot = { ...viewport };
|
|
1259
|
+
const result = await capture();
|
|
1260
|
+
if (getViewport() !== viewport) throw new Error("The document moved during capture. Keep it still and try again.");
|
|
1261
|
+
return {
|
|
1262
|
+
capture: result,
|
|
1263
|
+
viewport: snapshot
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1250
1266
|
/** A native mark is feedback on what was displayed, never source-edit authority. */
|
|
1251
1267
|
function nativeAuthorCapture(captureId, capturedAt, document, notes, viewport, alias) {
|
|
1252
1268
|
const regions = notes.map((note) => {
|
|
@@ -1632,14 +1648,15 @@ function AuthorDocumentView(props) {
|
|
|
1632
1648
|
}] : []].filter((mark) => mark.textRange === void 0 && (mark.sourceSha256 === void 0 || mark.sourceSha256 === props.sourceSha256)), body.kind, props.page, props.timeSeconds);
|
|
1633
1649
|
const sending = status.state === "sending";
|
|
1634
1650
|
const inspectingSource = canInspectSource && readingMode === "source";
|
|
1651
|
+
const drawing = !inspectingSource && !draft && !sending && props.onDraw !== void 0 && tool !== "pin";
|
|
1635
1652
|
const annotation = /* @__PURE__ */ jsx(AnnotationSurface, {
|
|
1636
1653
|
accessibilityLabel: props.name,
|
|
1637
|
-
zoomable: body.kind === "image"
|
|
1638
|
-
onViewportChange:
|
|
1654
|
+
zoomable: body.kind === "image",
|
|
1655
|
+
onViewportChange: props.onViewportChange,
|
|
1639
1656
|
marks: inspectingSource ? [] : marks,
|
|
1640
1657
|
selectedId: inspectingSource ? void 0 : draft ? DRAFT_ID : props.selectedId,
|
|
1641
1658
|
onPlace: inspectingSource || draft || sending || tool !== "pin" ? void 0 : props.onPlace,
|
|
1642
|
-
onDraw:
|
|
1659
|
+
onDraw: drawing ? (points) => {
|
|
1643
1660
|
if (tool === "draw") {
|
|
1644
1661
|
props.onDraw?.(points);
|
|
1645
1662
|
return;
|
|
@@ -1695,7 +1712,7 @@ function AuthorDocumentView(props) {
|
|
|
1695
1712
|
accessibilityRole: "button",
|
|
1696
1713
|
accessibilityLabel: `Comment on ${fragment.location}`,
|
|
1697
1714
|
disabled: !!draft || sending || !props.onPlace,
|
|
1698
|
-
style: [s.notes, s.
|
|
1715
|
+
style: [s.notes, s.touchTarget],
|
|
1699
1716
|
onPress: (event) => {
|
|
1700
1717
|
event.stopPropagation();
|
|
1701
1718
|
props.onPlace?.({
|
|
@@ -1759,6 +1776,7 @@ function AuthorDocumentView(props) {
|
|
|
1759
1776
|
}) : null,
|
|
1760
1777
|
props.onDraw && !props.edit && !inspectingSource ? /* @__PURE__ */ jsx(SegmentedControl, {
|
|
1761
1778
|
accessibilityLabel: "Mark tool",
|
|
1779
|
+
style: s.touchTarget,
|
|
1762
1780
|
options: [
|
|
1763
1781
|
{
|
|
1764
1782
|
value: "pin",
|
|
@@ -1794,6 +1812,7 @@ function AuthorDocumentView(props) {
|
|
|
1794
1812
|
}) : null,
|
|
1795
1813
|
canInspectSource && !props.edit ? /* @__PURE__ */ jsx(SegmentedControl, {
|
|
1796
1814
|
accessibilityLabel: "Document view",
|
|
1815
|
+
style: s.touchTarget,
|
|
1797
1816
|
options: [{
|
|
1798
1817
|
value: "read",
|
|
1799
1818
|
label: "Read"
|
|
@@ -1829,6 +1848,7 @@ function AuthorDocumentView(props) {
|
|
|
1829
1848
|
style: s.scroll,
|
|
1830
1849
|
contentContainerStyle: s.content,
|
|
1831
1850
|
keyboardShouldPersistTaps: "handled",
|
|
1851
|
+
scrollEnabled: !drawing,
|
|
1832
1852
|
children: [
|
|
1833
1853
|
props.edit?.image ? /* @__PURE__ */ jsx(Image, {
|
|
1834
1854
|
accessibilityLabel: "Crop preview",
|
|
@@ -2059,7 +2079,7 @@ const s = StyleSheet.create((theme) => ({
|
|
|
2059
2079
|
gap: theme.spacing(2),
|
|
2060
2080
|
uni__dependencies: [0]
|
|
2061
2081
|
},
|
|
2062
|
-
|
|
2082
|
+
touchTarget: { minHeight: 44 },
|
|
2063
2083
|
note: {
|
|
2064
2084
|
minHeight: 44,
|
|
2065
2085
|
flexDirection: "row",
|
|
@@ -2300,7 +2320,14 @@ function AuthorDocumentPanel({ path, ...props }) {
|
|
|
2300
2320
|
const [cropping, setCropping] = useState(false);
|
|
2301
2321
|
const [videoFrame, setVideoFrame] = useState();
|
|
2302
2322
|
const mediaTime = useRef(0);
|
|
2303
|
-
const
|
|
2323
|
+
const geometry = useRef(void 0);
|
|
2324
|
+
const onViewportChange = useCallback((viewport) => {
|
|
2325
|
+
const previous = geometry.current;
|
|
2326
|
+
if (previous?.key !== key || previous.viewport.width !== viewport.width || previous.viewport.height !== viewport.height || previous.viewport.zoom !== viewport.zoom || previous.viewport.originX !== viewport.originX || previous.viewport.originY !== viewport.originY) geometry.current = {
|
|
2327
|
+
key,
|
|
2328
|
+
viewport: { ...viewport }
|
|
2329
|
+
};
|
|
2330
|
+
}, [key]);
|
|
2304
2331
|
const edit = useSyncExternalStore(subscribeEdits, () => editsStore.store.state[key]);
|
|
2305
2332
|
const captureRef = useRef(void 0);
|
|
2306
2333
|
const onCaptureReady = useCallback((capture) => {
|
|
@@ -2494,7 +2521,7 @@ function AuthorDocumentPanel({ path, ...props }) {
|
|
|
2494
2521
|
if (!props.submitCapture) throw new Error("This host cannot confirm feedback delivery. Your notes have not been sent.");
|
|
2495
2522
|
const provider = captureRef.current;
|
|
2496
2523
|
if (provider?.key !== key) throw new Error("The document is not ready to capture. Try again when it has finished opening.");
|
|
2497
|
-
const capture = await provider.capture();
|
|
2524
|
+
const { capture, viewport } = await captureNativeAuthorViewport(provider.capture, () => geometry.current?.key === key ? geometry.current.viewport : void 0);
|
|
2498
2525
|
setStatus({ state: "sending" });
|
|
2499
2526
|
if (capture.bytes.byteLength > 2097152 || Math.max(capture.width, capture.height) > 1600) throw new Error("This capture exceeds the Author evidence budget.");
|
|
2500
2527
|
const { file, body } = current;
|
|
@@ -2509,11 +2536,7 @@ function AuthorDocumentPanel({ path, ...props }) {
|
|
|
2509
2536
|
naturalWidth: body.naturalWidth,
|
|
2510
2537
|
naturalHeight: body.naturalHeight
|
|
2511
2538
|
} : {}
|
|
2512
|
-
}, sent,
|
|
2513
|
-
width: capture.width,
|
|
2514
|
-
height: capture.height,
|
|
2515
|
-
...file.kind === "image" ? { zoom: imageZoom.current } : {}
|
|
2516
|
-
}, alias);
|
|
2539
|
+
}, sent, viewport, alias);
|
|
2517
2540
|
recordNativeAuthorRequest(sessionId, packet, regions);
|
|
2518
2541
|
recorded = true;
|
|
2519
2542
|
await props.submitCapture({
|
|
@@ -2704,9 +2727,7 @@ function AuthorDocumentPanel({ path, ...props }) {
|
|
|
2704
2727
|
children,
|
|
2705
2728
|
onReady: onCaptureReady
|
|
2706
2729
|
}) ?? children,
|
|
2707
|
-
|
|
2708
|
-
imageZoom.current = zoom;
|
|
2709
|
-
},
|
|
2730
|
+
onViewportChange,
|
|
2710
2731
|
onResumeVideo: videoFrame === void 0 ? void 0 : () => {
|
|
2711
2732
|
setSeekSeconds(videoFrame.timeSeconds);
|
|
2712
2733
|
setVideoFrame(void 0);
|