@fias/arche-sdk 2.19.1 → 2.19.2
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/entity-ops.d.ts +7 -4
- package/dist/entity-ops.d.ts.map +1 -1
- package/dist/entity-ops.js +7 -4
- package/dist/entity-ops.js.map +1 -1
- package/dist/generated/permissions.d.ts +1 -1
- package/dist/generated/permissions.d.ts.map +1 -1
- package/dist/generated/permissions.js +2 -0
- package/dist/generated/permissions.js.map +1 -1
- package/dist/hooks.d.ts +86 -3
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +188 -15
- package/dist/hooks.js.map +1 -1
- package/dist/hooks.test.js +291 -2
- package/dist/hooks.test.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +136 -19
- package/dist/types.d.ts +205 -12
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/default/AGENTS.md +145 -6
- package/templates/default/CLAUDE.md +145 -6
package/dist/index.mjs
CHANGED
|
@@ -1008,7 +1008,10 @@ function useFiasStorage() {
|
|
|
1008
1008
|
},
|
|
1009
1009
|
[bridge]
|
|
1010
1010
|
);
|
|
1011
|
-
return
|
|
1011
|
+
return useMemo2(
|
|
1012
|
+
() => ({ readFile, writeFile, listFiles, deleteFile }),
|
|
1013
|
+
[readFile, writeFile, listFiles, deleteFile]
|
|
1014
|
+
);
|
|
1012
1015
|
}
|
|
1013
1016
|
function useEntityInvocation() {
|
|
1014
1017
|
const bridge = useBridge();
|
|
@@ -1243,21 +1246,30 @@ function useFiasNavigation() {
|
|
|
1243
1246
|
bridge.request("open_arche", {
|
|
1244
1247
|
archeId,
|
|
1245
1248
|
newTab: opts?.newTab === true,
|
|
1246
|
-
...opts?.path ? { path: opts.path } : {}
|
|
1249
|
+
...opts?.path ? { path: opts.path } : {},
|
|
1250
|
+
...opts?.payload ? { payload: opts.payload } : {}
|
|
1247
1251
|
});
|
|
1248
1252
|
},
|
|
1249
1253
|
[bridge]
|
|
1250
1254
|
);
|
|
1251
|
-
return
|
|
1255
|
+
return useMemo2(
|
|
1256
|
+
() => ({ navigateTo, openArche, currentPath }),
|
|
1257
|
+
[navigateTo, openArche, currentPath]
|
|
1258
|
+
);
|
|
1252
1259
|
}
|
|
1253
1260
|
function usePersistentState(key, initialValue) {
|
|
1254
1261
|
const bridge = useBridge();
|
|
1255
1262
|
const [value, setValueInternal] = useState2(initialValue);
|
|
1256
1263
|
const initializedRef = useRef(false);
|
|
1257
1264
|
const valueRef = useRef(initialValue);
|
|
1265
|
+
const setByPluginRef = useRef(false);
|
|
1258
1266
|
const writer = useMemo2(() => createDebouncedWriter(bridge), [bridge]);
|
|
1259
1267
|
useEffect2(() => {
|
|
1260
1268
|
invokeEntityOp(bridge, PLUGIN_STORAGE_ENTITY_ID, "read", { path: `__state/${key}` }).then((result) => {
|
|
1269
|
+
if (setByPluginRef.current) {
|
|
1270
|
+
initializedRef.current = true;
|
|
1271
|
+
return;
|
|
1272
|
+
}
|
|
1261
1273
|
if (result.exists && result.content !== null) {
|
|
1262
1274
|
try {
|
|
1263
1275
|
const parsed = JSON.parse(result.content);
|
|
@@ -1277,6 +1289,7 @@ function usePersistentState(key, initialValue) {
|
|
|
1277
1289
|
const setValue = useCallback(
|
|
1278
1290
|
(next) => {
|
|
1279
1291
|
const resolved = typeof next === "function" ? next(valueRef.current) : next;
|
|
1292
|
+
setByPluginRef.current = true;
|
|
1280
1293
|
valueRef.current = resolved;
|
|
1281
1294
|
setValueInternal(resolved);
|
|
1282
1295
|
writer.schedule(`__state/${key}`, JSON.stringify(resolved));
|
|
@@ -1740,9 +1753,10 @@ function useVaultDocuments() {
|
|
|
1740
1753
|
);
|
|
1741
1754
|
const read = useCallback(
|
|
1742
1755
|
async (documentId) => {
|
|
1743
|
-
return bridge.request(
|
|
1744
|
-
|
|
1745
|
-
|
|
1756
|
+
return bridge.request(
|
|
1757
|
+
"vault_documents_read",
|
|
1758
|
+
{ documentId }
|
|
1759
|
+
);
|
|
1746
1760
|
},
|
|
1747
1761
|
[bridge]
|
|
1748
1762
|
);
|
|
@@ -1767,16 +1781,29 @@ function useVaultDocuments() {
|
|
|
1767
1781
|
);
|
|
1768
1782
|
const saveContent = useCallback(
|
|
1769
1783
|
async (params) => {
|
|
1770
|
-
const
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1784
|
+
const routed = await routeSaveContent(params.content);
|
|
1785
|
+
let res;
|
|
1786
|
+
if (routed.lane === "body") {
|
|
1787
|
+
res = await invokeEntityOp(
|
|
1788
|
+
bridge,
|
|
1789
|
+
VAULT_ARCHE_DOCUMENTS_ENTITY_ID,
|
|
1790
|
+
"save_own_document_content",
|
|
1791
|
+
{
|
|
1792
|
+
documentId: params.documentId,
|
|
1793
|
+
content: routed.text,
|
|
1794
|
+
contentType: params.contentType,
|
|
1795
|
+
expectedRevision: params.expectedRevision
|
|
1796
|
+
}
|
|
1797
|
+
);
|
|
1798
|
+
} else {
|
|
1799
|
+
res = await bridge.request("vault_documents_upload", {
|
|
1800
|
+
saveToDocumentId: params.documentId,
|
|
1801
|
+
bytes: bytesToBase64(routed.bytes),
|
|
1802
|
+
mimeType: params.contentType,
|
|
1803
|
+
contentKind: routed.contentKind,
|
|
1804
|
+
expectedRevision: params.expectedRevision
|
|
1805
|
+
});
|
|
1806
|
+
}
|
|
1780
1807
|
downloadUrlCache.delete(params.documentId);
|
|
1781
1808
|
return res;
|
|
1782
1809
|
},
|
|
@@ -1784,6 +1811,12 @@ function useVaultDocuments() {
|
|
|
1784
1811
|
);
|
|
1785
1812
|
const write = useCallback(
|
|
1786
1813
|
async (params) => {
|
|
1814
|
+
if (params.content.length > SAVE_CONTENT_BODY_LANE_MAX_BYTES || !fitsBridgeBodyAsJsonText(params.content)) {
|
|
1815
|
+
throw new FiasBridgeError(
|
|
1816
|
+
"write() takes small text only: at most 200,000 characters, and small enough to travel in one bridge request once JSON-escaped (quotes, backslashes and newlines double). Use upload() for larger documents.",
|
|
1817
|
+
"INVALID_PARAMS"
|
|
1818
|
+
);
|
|
1819
|
+
}
|
|
1787
1820
|
return bridge.request("vault_documents_write", {
|
|
1788
1821
|
name: params.name,
|
|
1789
1822
|
content: params.content,
|
|
@@ -1807,6 +1840,17 @@ function useVaultDocuments() {
|
|
|
1807
1840
|
},
|
|
1808
1841
|
[bridge]
|
|
1809
1842
|
);
|
|
1843
|
+
const promoteToUserFiles = useCallback(
|
|
1844
|
+
async (documentId) => {
|
|
1845
|
+
const res = await bridge.request("vault_documents_update", {
|
|
1846
|
+
documentId,
|
|
1847
|
+
userVisible: true
|
|
1848
|
+
});
|
|
1849
|
+
downloadUrlCache.delete(documentId);
|
|
1850
|
+
return res;
|
|
1851
|
+
},
|
|
1852
|
+
[bridge]
|
|
1853
|
+
);
|
|
1810
1854
|
const deleteDocument = useCallback(
|
|
1811
1855
|
async (documentId) => {
|
|
1812
1856
|
await bridge.request("vault_documents_delete", { documentId });
|
|
@@ -1895,6 +1939,7 @@ function useVaultDocuments() {
|
|
|
1895
1939
|
getDownloadUrl,
|
|
1896
1940
|
write,
|
|
1897
1941
|
update,
|
|
1942
|
+
promoteToUserFiles,
|
|
1898
1943
|
delete: deleteDocument,
|
|
1899
1944
|
search,
|
|
1900
1945
|
attach,
|
|
@@ -1911,6 +1956,7 @@ function useVaultDocuments() {
|
|
|
1911
1956
|
getDownloadUrl,
|
|
1912
1957
|
write,
|
|
1913
1958
|
update,
|
|
1959
|
+
promoteToUserFiles,
|
|
1914
1960
|
deleteDocument,
|
|
1915
1961
|
search,
|
|
1916
1962
|
attach,
|
|
@@ -1921,6 +1967,39 @@ function useVaultDocuments() {
|
|
|
1921
1967
|
]
|
|
1922
1968
|
);
|
|
1923
1969
|
}
|
|
1970
|
+
var SAVE_CONTENT_BODY_LANE_MAX_BYTES = 2e5;
|
|
1971
|
+
var BRIDGE_BODY_TEXT_MAX_SERIALIZED_BYTES = 256 * 1024 - 16 * 1024;
|
|
1972
|
+
function fitsBridgeBodyAsJsonText(text, utf8Bytes) {
|
|
1973
|
+
if (text.length * 6 <= BRIDGE_BODY_TEXT_MAX_SERIALIZED_BYTES) return true;
|
|
1974
|
+
const escapeOverhead = JSON.stringify(text).length - text.length;
|
|
1975
|
+
const bytes = utf8Bytes ?? new TextEncoder().encode(text).length;
|
|
1976
|
+
return bytes + escapeOverhead <= BRIDGE_BODY_TEXT_MAX_SERIALIZED_BYTES;
|
|
1977
|
+
}
|
|
1978
|
+
var SAVE_CONTENT_MAX_BYTES = 15 * 1024 * 1024;
|
|
1979
|
+
async function routeSaveContent(content) {
|
|
1980
|
+
let routed;
|
|
1981
|
+
if (typeof content === "string") {
|
|
1982
|
+
if (content.length * 6 <= SAVE_CONTENT_BODY_LANE_MAX_BYTES) {
|
|
1983
|
+
return { lane: "body", text: content };
|
|
1984
|
+
}
|
|
1985
|
+
const bytes = new TextEncoder().encode(content);
|
|
1986
|
+
routed = bytes.length <= SAVE_CONTENT_BODY_LANE_MAX_BYTES && fitsBridgeBodyAsJsonText(content, bytes.length) ? { lane: "body", text: content } : { lane: "host", bytes, contentKind: "text" };
|
|
1987
|
+
} else {
|
|
1988
|
+
routed = { lane: "host", bytes: await toUint8Array(content), contentKind: "binary" };
|
|
1989
|
+
}
|
|
1990
|
+
if (routed.lane === "host" && routed.bytes.length > SAVE_CONTENT_MAX_BYTES) {
|
|
1991
|
+
throw new FiasBridgeError(
|
|
1992
|
+
`Content is ${routed.bytes.length} bytes; saveContent accepts at most ${SAVE_CONTENT_MAX_BYTES} bytes (15 MB).`,
|
|
1993
|
+
"OWN_DOCUMENT_SAVE_TOO_LARGE"
|
|
1994
|
+
);
|
|
1995
|
+
}
|
|
1996
|
+
return routed;
|
|
1997
|
+
}
|
|
1998
|
+
async function toUint8Array(content) {
|
|
1999
|
+
if (content instanceof Uint8Array) return content;
|
|
2000
|
+
if (content instanceof ArrayBuffer) return new Uint8Array(content);
|
|
2001
|
+
return new Uint8Array(await content.arrayBuffer());
|
|
2002
|
+
}
|
|
1924
2003
|
function base64ToBytes(base64) {
|
|
1925
2004
|
const binary = atob(base64);
|
|
1926
2005
|
const bytes = new Uint8Array(binary.length);
|
|
@@ -2053,7 +2132,43 @@ function useVaultUserDocuments() {
|
|
|
2053
2132
|
const pick = useCallback(
|
|
2054
2133
|
async (options) => {
|
|
2055
2134
|
return bridge.request("vault_documents_pick", {
|
|
2056
|
-
maxDocuments: options?.maxDocuments
|
|
2135
|
+
maxDocuments: options?.maxDocuments,
|
|
2136
|
+
access: options?.access
|
|
2137
|
+
});
|
|
2138
|
+
},
|
|
2139
|
+
[bridge]
|
|
2140
|
+
);
|
|
2141
|
+
const requestEditAccess = useCallback(
|
|
2142
|
+
async (documentId) => {
|
|
2143
|
+
return bridge.request("vault_documents_pick", {
|
|
2144
|
+
maxDocuments: 1,
|
|
2145
|
+
access: "write",
|
|
2146
|
+
documentId
|
|
2147
|
+
});
|
|
2148
|
+
},
|
|
2149
|
+
[bridge]
|
|
2150
|
+
);
|
|
2151
|
+
const saveContent = useCallback(
|
|
2152
|
+
async (params) => {
|
|
2153
|
+
const routed = await routeSaveContent(params.content);
|
|
2154
|
+
if (routed.lane === "body") {
|
|
2155
|
+
return invokeEntityOp(
|
|
2156
|
+
bridge,
|
|
2157
|
+
VAULT_USER_DOCUMENTS_ENTITY_ID,
|
|
2158
|
+
"save_consented_document_content",
|
|
2159
|
+
{
|
|
2160
|
+
documentId: params.documentId,
|
|
2161
|
+
content: routed.text,
|
|
2162
|
+
expectedRevision: params.expectedRevision
|
|
2163
|
+
}
|
|
2164
|
+
);
|
|
2165
|
+
}
|
|
2166
|
+
return bridge.request("vault_documents_upload", {
|
|
2167
|
+
saveToDocumentId: params.documentId,
|
|
2168
|
+
saveTarget: "user",
|
|
2169
|
+
bytes: bytesToBase64(routed.bytes),
|
|
2170
|
+
contentKind: routed.contentKind,
|
|
2171
|
+
expectedRevision: params.expectedRevision
|
|
2057
2172
|
});
|
|
2058
2173
|
},
|
|
2059
2174
|
[bridge]
|
|
@@ -2104,8 +2219,8 @@ function useVaultUserDocuments() {
|
|
|
2104
2219
|
[bridge]
|
|
2105
2220
|
);
|
|
2106
2221
|
return useMemo2(
|
|
2107
|
-
() => ({ pick, list, get, getDownloadUrl, getBytes }),
|
|
2108
|
-
[pick, list, get, getDownloadUrl, getBytes]
|
|
2222
|
+
() => ({ pick, requestEditAccess, saveContent, list, get, getDownloadUrl, getBytes }),
|
|
2223
|
+
[pick, requestEditAccess, saveContent, list, get, getDownloadUrl, getBytes]
|
|
2109
2224
|
);
|
|
2110
2225
|
}
|
|
2111
2226
|
var COMMUNITY_ASSET_URL_REFRESH_BUFFER_MS = 3e4;
|
|
@@ -2423,6 +2538,7 @@ var VALID_PLUGIN_PERMISSIONS = [
|
|
|
2423
2538
|
"user:profile:read",
|
|
2424
2539
|
"vault:documents:read",
|
|
2425
2540
|
"vault:documents:write",
|
|
2541
|
+
"vault:user-documents:edit",
|
|
2426
2542
|
"vault:user-documents:read",
|
|
2427
2543
|
"vault:user-documents:write"
|
|
2428
2544
|
];
|
|
@@ -2451,6 +2567,7 @@ var PLUGIN_PERMISSION_DESCRIPTIONS = {
|
|
|
2451
2567
|
"user:profile:read": "See your display name and avatar.",
|
|
2452
2568
|
"vault:documents:read": "Read documents this app itself created in your Vault.",
|
|
2453
2569
|
"vault:documents:write": "Create and manage its own documents in your Vault.",
|
|
2570
|
+
"vault:user-documents:edit": "Save changes to files of yours that you let it edit \u2014 you choose each file, earlier versions are kept, and you can remove access any time in Vault \u2192 App Access.",
|
|
2454
2571
|
"vault:user-documents:read": "Read documents YOU choose to share with it from your Vault \u2014 you pick each document, and you can remove access any time in Vault \u2192 App Access.",
|
|
2455
2572
|
"vault:user-documents:write": "Save its work to your Fias files, where you can find and reuse it. You confirm each save."
|
|
2456
2573
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -149,7 +149,25 @@ export interface EntityInvocationParams {
|
|
|
149
149
|
* applies). Bounded per call — keep images small (downscale before sending).
|
|
150
150
|
*/
|
|
151
151
|
images?: EntityInvocationImage[];
|
|
152
|
-
|
|
152
|
+
/**
|
|
153
|
+
* Sampling knobs for the resolved model. Out-of-range values are clamped
|
|
154
|
+
* rather than rejected.
|
|
155
|
+
*
|
|
156
|
+
* - `temperature` — 0–2. **A no-op on models that do not accept sampling
|
|
157
|
+
* parameters**, which includes the whole Claude 5 family (Sonnet 5,
|
|
158
|
+
* Opus 5, Fable 5) and Opus 4.7/4.8: Anthropic removed the parameter
|
|
159
|
+
* there, so the platform drops it rather than letting the provider 400.
|
|
160
|
+
* Only the fast tier (Haiku) and the Google models honour it.
|
|
161
|
+
* - `maxTokens` — may only LOWER the resolved model's output ceiling, never
|
|
162
|
+
* raise it. Worth setting when you know the reply is short: it shrinks the
|
|
163
|
+
* credit hold taken up front.
|
|
164
|
+
*
|
|
165
|
+
* Unknown keys are ignored.
|
|
166
|
+
*/
|
|
167
|
+
parameters?: {
|
|
168
|
+
temperature?: number;
|
|
169
|
+
maxTokens?: number;
|
|
170
|
+
};
|
|
153
171
|
/** System prompt to send to the AI model. The arche/plugin provides context; the entity provides the capability. */
|
|
154
172
|
systemPrompt?: string;
|
|
155
173
|
/**
|
|
@@ -638,13 +656,58 @@ export interface FiasNavigationApi {
|
|
|
638
656
|
* @param opts.newTab Best-effort open in a new tab (keeps the current arche
|
|
639
657
|
* open). Browsers may block the popup since user activation does not cross
|
|
640
658
|
* the iframe→host boundary; the host falls back to same-tab navigation.
|
|
659
|
+
* Ignored when `opts.payload` is present — navigation state cannot cross
|
|
660
|
+
* into a new tab, so the handoff would arrive empty.
|
|
661
|
+
* @param opts.payload A typed handoff payload to hand the target arche —
|
|
662
|
+
* e.g. `{ kind: 'sign_document', requestId, documentId, recipients }` to
|
|
663
|
+
* open Document Sign on a draft seeded from one of the user's Vault
|
|
664
|
+
* documents. The host validates it against the target's intake and
|
|
665
|
+
* REJECTS a payload that arche would not accept, so a mistargeted handoff
|
|
666
|
+
* is an error you can see rather than a silent no-op.
|
|
667
|
+
*
|
|
668
|
+
* A handoff only ever PRE-FILLS a UI — it never causes an effect. The
|
|
669
|
+
* user reviews, edits, and acts themself.
|
|
670
|
+
*
|
|
671
|
+
* Mint a fresh `requestId` (uuid) per user intent, not per call: the host
|
|
672
|
+
* keys idempotency on it, so re-presenting one resolves to the SAME draft
|
|
673
|
+
* instead of creating a duplicate. Reusing a stale one reopens the old
|
|
674
|
+
* draft.
|
|
641
675
|
*/
|
|
642
676
|
openArche: (archeId: string, opts?: {
|
|
643
677
|
newTab?: boolean;
|
|
644
678
|
path?: string;
|
|
679
|
+
payload?: ArcheHandoffPayloadInput;
|
|
645
680
|
}) => void;
|
|
646
681
|
currentPath: string;
|
|
647
682
|
}
|
|
683
|
+
/**
|
|
684
|
+
* Handoff payloads a plugin may hand to another arche via `openArche`.
|
|
685
|
+
*
|
|
686
|
+
* Structural rather than a re-export of the platform's Zod-inferred union:
|
|
687
|
+
* the SDK ships to plugin authors and cannot depend on workspace packages.
|
|
688
|
+
* The host re-validates against the canonical contract, so a shape that is
|
|
689
|
+
* wrong here is refused there with a message naming the problem.
|
|
690
|
+
*/
|
|
691
|
+
export type ArcheHandoffPayloadInput = {
|
|
692
|
+
kind: 'open_document';
|
|
693
|
+
documentId: string;
|
|
694
|
+
} | {
|
|
695
|
+
kind: 'sign_document';
|
|
696
|
+
/** Idempotency key for this signing request. One uuid per user intent. */
|
|
697
|
+
requestId: string;
|
|
698
|
+
/** A Vault document the user can open — PDFs only. */
|
|
699
|
+
documentId: string;
|
|
700
|
+
title?: string;
|
|
701
|
+
message?: string;
|
|
702
|
+
signingOrder?: 'parallel' | 'sequential';
|
|
703
|
+
recipients?: Array<{
|
|
704
|
+
email: string;
|
|
705
|
+
name?: string;
|
|
706
|
+
role?: 'signer' | 'viewer' | 'approver';
|
|
707
|
+
}>;
|
|
708
|
+
/** Opaque metadata echoed back on the result. Never interpreted. */
|
|
709
|
+
correlationId?: string;
|
|
710
|
+
};
|
|
648
711
|
/**
|
|
649
712
|
* A document owned by the calling arche in the user's Vault.
|
|
650
713
|
*
|
|
@@ -671,6 +734,14 @@ export interface VaultDocumentSummary {
|
|
|
671
734
|
* scoped by `source_arche_id`, not folder).
|
|
672
735
|
*/
|
|
673
736
|
folderId: string | null;
|
|
737
|
+
/**
|
|
738
|
+
* Opaque token naming the document's current CONTENT — pass it as
|
|
739
|
+
* `saveContent({ expectedRevision })` so a save is refused
|
|
740
|
+
* (`VERSION_CONFLICT`) if the content changed since you read it. Never
|
|
741
|
+
* parse it. Optional: absent on hosts that predate in-place-save
|
|
742
|
+
* preconditions.
|
|
743
|
+
*/
|
|
744
|
+
revision?: string;
|
|
674
745
|
}
|
|
675
746
|
export interface VaultDocumentsListOptions {
|
|
676
747
|
search?: string;
|
|
@@ -731,12 +802,26 @@ export interface VaultDocumentUpdateParams {
|
|
|
731
802
|
}
|
|
732
803
|
/** Input to `useVaultDocuments().saveContent`. */
|
|
733
804
|
export interface VaultDocumentSaveContentParams {
|
|
734
|
-
/** The document to overwrite — one THIS arche created with `write`. */
|
|
805
|
+
/** The document to overwrite — one THIS arche created with `write` / `upload`. */
|
|
735
806
|
documentId: string;
|
|
736
|
-
/**
|
|
737
|
-
|
|
807
|
+
/**
|
|
808
|
+
* The new content, up to 15 MB. A `string` is saved as UTF-8 text (the
|
|
809
|
+
* document must be — or become, via `contentType` — a text type); bytes
|
|
810
|
+
* (`Uint8Array` / `ArrayBuffer` / `Blob`) are saved as-is, for any type.
|
|
811
|
+
* Transport is chosen for you: small text rides the bridge message, and
|
|
812
|
+
* everything else is uploaded by the host — there is one method either way.
|
|
813
|
+
*/
|
|
814
|
+
content: string | Uint8Array | ArrayBuffer | Blob;
|
|
738
815
|
/** New MIME type; omitted keeps the document's current one. */
|
|
739
816
|
contentType?: string;
|
|
817
|
+
/**
|
|
818
|
+
* The `revision` you last saw for this document (from `list`, `readBytes`,
|
|
819
|
+
* or a previous `saveContent` result). When supplied, the save is refused
|
|
820
|
+
* with `VERSION_CONFLICT` if the document has changed since — so a second
|
|
821
|
+
* tab, or another device, cannot be silently overwritten. Omit for
|
|
822
|
+
* last-write-wins.
|
|
823
|
+
*/
|
|
824
|
+
expectedRevision?: string;
|
|
740
825
|
}
|
|
741
826
|
/** Result of `useVaultDocuments().saveContent`. */
|
|
742
827
|
export interface VaultDocumentSaveContentResult {
|
|
@@ -745,6 +830,35 @@ export interface VaultDocumentSaveContentResult {
|
|
|
745
830
|
sizeBytes: number;
|
|
746
831
|
/** ISO timestamp of the save. */
|
|
747
832
|
updatedAt: string;
|
|
833
|
+
/**
|
|
834
|
+
* Opaque token naming the content just saved — pass it as
|
|
835
|
+
* `expectedRevision` on the next save. Optional, like every other
|
|
836
|
+
* `revision` on this hook: a platform that predates revisions saves the
|
|
837
|
+
* text lane without returning one (the next save is then last-write-wins).
|
|
838
|
+
*/
|
|
839
|
+
revision?: string;
|
|
840
|
+
}
|
|
841
|
+
/**
|
|
842
|
+
* Result of `useVaultUserDocuments().saveContent`. Here `revision` is ALWAYS
|
|
843
|
+
* present — a platform that can save to the user's files at all returns it —
|
|
844
|
+
* which matters because that save REQUIRES the next `expectedRevision`.
|
|
845
|
+
*/
|
|
846
|
+
export interface VaultUserDocumentSaveContentResult extends VaultDocumentSaveContentResult {
|
|
847
|
+
revision: string;
|
|
848
|
+
}
|
|
849
|
+
/** Result of `useVaultDocuments().promoteToUserFiles`. */
|
|
850
|
+
export interface VaultDocumentPromoteResult {
|
|
851
|
+
documentId: string;
|
|
852
|
+
visibility: 'user-vault';
|
|
853
|
+
/**
|
|
854
|
+
* Whether the user let your app KEEP EDITING the file (a checkbox on the
|
|
855
|
+
* host's confirmation, offered only when your manifest declares
|
|
856
|
+
* `vault:user-documents:edit`). `true`: keep saving it with
|
|
857
|
+
* `useVaultUserDocuments().saveContent`. `false` or absent: it is read-only
|
|
858
|
+
* to you now — open it read-only and ask with `requestEditAccess` if the
|
|
859
|
+
* user starts editing.
|
|
860
|
+
*/
|
|
861
|
+
editAccess?: boolean;
|
|
748
862
|
}
|
|
749
863
|
export interface VaultDocumentSearchOptions {
|
|
750
864
|
/** Number of results to return. 1..50, default 10. */
|
|
@@ -788,9 +902,39 @@ export interface OpenDocumentHandoff {
|
|
|
788
902
|
kind: 'open_document';
|
|
789
903
|
documentId: string;
|
|
790
904
|
}
|
|
791
|
-
/**
|
|
792
|
-
*
|
|
793
|
-
|
|
905
|
+
/**
|
|
906
|
+
* The REPLY to a `sign_document` handoff your app sent — delivered when the
|
|
907
|
+
* user leaves Document Sign and comes back to you.
|
|
908
|
+
*
|
|
909
|
+
* Contract, and it matters:
|
|
910
|
+
*
|
|
911
|
+
* - It is a POINTER, not a record. It tells you which envelope to look at;
|
|
912
|
+
* it is not evidence of what happened to it. Anything you would act on —
|
|
913
|
+
* who signed, what is outstanding — comes from reading the envelope, never
|
|
914
|
+
* from this payload.
|
|
915
|
+
* - `outcome` is the fact, not `envelopeId`. An envelope id exists from the
|
|
916
|
+
* moment a DRAFT is created, so its presence proves a draft exists and
|
|
917
|
+
* nothing more. A cancellation structurally carries none.
|
|
918
|
+
* - Match it to an OUTSTANDING request by `requestId` and consume it once.
|
|
919
|
+
* Never re-point an existing association because a `correlationId`
|
|
920
|
+
* matched — that is your own metadata, echoed back unverified.
|
|
921
|
+
*/
|
|
922
|
+
export type SignDocumentResultHandoff = {
|
|
923
|
+
kind: 'sign_document_result';
|
|
924
|
+
outcome: 'cancelled';
|
|
925
|
+
requestId: string;
|
|
926
|
+
correlationId?: string;
|
|
927
|
+
} | {
|
|
928
|
+
kind: 'sign_document_result';
|
|
929
|
+
outcome: 'saved_draft' | 'sent';
|
|
930
|
+
requestId: string;
|
|
931
|
+
envelopeId: string;
|
|
932
|
+
correlationId?: string;
|
|
933
|
+
};
|
|
934
|
+
/** Every handoff payload a plugin can receive. Switch on `kind` — the union
|
|
935
|
+
* is the extension point, and a kind you do not handle must be ignored
|
|
936
|
+
* rather than assumed. */
|
|
937
|
+
export type ArcheHandoffPayload = OpenDocumentHandoff | SignDocumentResultHandoff;
|
|
794
938
|
export interface VaultDocumentUploadParams {
|
|
795
939
|
/** Document display name. */
|
|
796
940
|
name: string;
|
|
@@ -842,6 +986,12 @@ export interface VaultDocumentUploadResult {
|
|
|
842
986
|
/** Status after finalize — `'uploaded'`, then `'available'` once the
|
|
843
987
|
* extraction worker indexes the document for search. */
|
|
844
988
|
status: string;
|
|
989
|
+
/**
|
|
990
|
+
* Only on `upload({ userVisible: true })`: whether the user let your app
|
|
991
|
+
* keep editing the file it just saved into their files. See
|
|
992
|
+
* `VaultDocumentPromoteResult.editAccess`.
|
|
993
|
+
*/
|
|
994
|
+
editAccess?: boolean;
|
|
845
995
|
}
|
|
846
996
|
export interface VaultDocumentReferenceResult {
|
|
847
997
|
referenceId: string;
|
|
@@ -875,6 +1025,7 @@ export interface VaultDocumentsApi {
|
|
|
875
1025
|
read: (documentId: string) => Promise<{
|
|
876
1026
|
content: string;
|
|
877
1027
|
contentType: string;
|
|
1028
|
+
revision?: string;
|
|
878
1029
|
}>;
|
|
879
1030
|
/**
|
|
880
1031
|
* Read the raw bytes of a document THIS ARCHE created (any content
|
|
@@ -903,6 +1054,8 @@ export interface VaultDocumentsApi {
|
|
|
903
1054
|
sensitivity: string;
|
|
904
1055
|
createdAt: string;
|
|
905
1056
|
updatedAt: string;
|
|
1057
|
+
/** See `VaultDocumentSummary.revision`. */
|
|
1058
|
+
revision?: string;
|
|
906
1059
|
};
|
|
907
1060
|
bytes: Uint8Array;
|
|
908
1061
|
contentType: string | null;
|
|
@@ -912,9 +1065,17 @@ export interface VaultDocumentsApi {
|
|
|
912
1065
|
* `documentId`, bytes replaced, no version history. The path for an arche
|
|
913
1066
|
* that saves continuously as the user works (a spreadsheet's autosave);
|
|
914
1067
|
* to publish a distinct new version instead, use
|
|
915
|
-
* `write({ replacesDocumentId })`, which keeps the chain.
|
|
916
|
-
*
|
|
917
|
-
*
|
|
1068
|
+
* `write({ replacesDocumentId })`, which keeps the chain. Accepts text OR
|
|
1069
|
+
* bytes, up to 15 MB (OWN_DOCUMENT_SAVE_TOO_LARGE names the cap — it is
|
|
1070
|
+
* the same ceiling `readBytes` serves, so anything you save you can
|
|
1071
|
+
* reopen): a `string` is saved as UTF-8 text and the document must be a
|
|
1072
|
+
* text type; a `Uint8Array` / `ArrayBuffer` / `Blob` is saved as-is, for
|
|
1073
|
+
* any type (a PDF editor saving its PDF). Transport is automatic — small
|
|
1074
|
+
* text rides the bridge message, everything else is uploaded by the host —
|
|
1075
|
+
* so there is no second method to choose. Pass `expectedRevision` to
|
|
1076
|
+
* refuse the save (VERSION_CONFLICT) when another tab or device changed
|
|
1077
|
+
* the document first; re-read, merge, and retry with the new revision.
|
|
1078
|
+
* Only arche-private documents qualify: a
|
|
918
1079
|
* document the user can see in their own files, even one this arche
|
|
919
1080
|
* created, rejects with DOCUMENT_NOT_FOUND. A document whose upload never
|
|
920
1081
|
* finished or that is mid-extraction rejects with
|
|
@@ -932,13 +1093,45 @@ export interface VaultDocumentsApi {
|
|
|
932
1093
|
* results until re-extraction exists.
|
|
933
1094
|
*/
|
|
934
1095
|
saveContent: (params: VaultDocumentSaveContentParams) => Promise<VaultDocumentSaveContentResult>;
|
|
1096
|
+
/**
|
|
1097
|
+
* Move a document THIS ARCHE created out of its private space and into the
|
|
1098
|
+
* user's own Fias files — the SAME document, not a copy: same `documentId`,
|
|
1099
|
+
* no second upload, nothing double-counted against storage. Use it to hand
|
|
1100
|
+
* over a finished working file instead of `upload({ userVisible: true })`,
|
|
1101
|
+
* which would mint a duplicate.
|
|
1102
|
+
*
|
|
1103
|
+
* The user decides. The host shows them its own confirmation naming the
|
|
1104
|
+
* file and where it will go; this resolves once they agree, and rejects
|
|
1105
|
+
* with `SAVE_DECLINED` if they don't (or if the host cannot ask — the dev
|
|
1106
|
+
* harness and the builder preview can't). Nothing the plugin sends can skip
|
|
1107
|
+
* that step. The file lands in your app's folder under My Fias; you cannot
|
|
1108
|
+
* choose another.
|
|
1109
|
+
*
|
|
1110
|
+
* Requires `vault:user-documents:write` in your manifest (it escalates to
|
|
1111
|
+
* human review) and a registered folder for your arche — the same two
|
|
1112
|
+
* things `upload({ userVisible: true })` needs.
|
|
1113
|
+
*
|
|
1114
|
+
* ONE-WAY, and it changes what you can do: once the file is the user's,
|
|
1115
|
+
* THIS hook's `saveContent`, `update` and `delete` reject — it is theirs
|
|
1116
|
+
* now. To keep saving it, declare `vault:user-documents:edit`: the
|
|
1117
|
+
* confirmation then offers the user "let this app keep editing", the result
|
|
1118
|
+
* carries `editAccess`, and you save through
|
|
1119
|
+
* `useVaultUserDocuments().saveContent` instead. Without that, promote when
|
|
1120
|
+
* the user is DONE. There is no plugin-side demote.
|
|
1121
|
+
*
|
|
1122
|
+
* After a `SAVE_DECLINED`, re-`list()` before assuming nothing moved. The
|
|
1123
|
+
* host performs the move itself, so in the rare case its page is torn down
|
|
1124
|
+
* mid-move (the user navigates away) you are told "declined" for a promote
|
|
1125
|
+
* that completed. The document's `visibility` is the truth.
|
|
1126
|
+
*/
|
|
1127
|
+
promoteToUserFiles: (documentId: string) => Promise<VaultDocumentPromoteResult>;
|
|
935
1128
|
/**
|
|
936
1129
|
* Get a fresh presigned download URL for a documentId. The result is
|
|
937
1130
|
* cached client-side and refreshed automatically before expiry.
|
|
938
1131
|
*/
|
|
939
1132
|
getDownloadUrl: (documentId: string) => Promise<VaultDocumentDownloadUrl>;
|
|
940
|
-
/** Create a small text document inline (UTF-8, ≤
|
|
941
|
-
* or larger documents use `upload`. */
|
|
1133
|
+
/** Create a small text document inline (UTF-8, ≤200 KB — the content rides
|
|
1134
|
+
* the bridge request body). For binaries or larger documents use `upload`. */
|
|
942
1135
|
write: (params: VaultDocumentWriteParams) => Promise<{
|
|
943
1136
|
documentId: string;
|
|
944
1137
|
}>;
|