@tangle-network/agent-app 0.45.58 → 0.45.60
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/assistant/index.js +1 -1
- package/dist/chat-routes/attachment-store.d.ts +69 -26
- package/dist/chat-routes/attachment-upload.d.ts +59 -38
- package/dist/chat-routes/attachment-write-safety.d.ts +11 -0
- package/dist/chat-routes/index.js +429 -35
- package/dist/chat-routes/index.js.map +1 -1
- package/dist/chat-routes/promote-file-part.d.ts +30 -13
- package/dist/chat-store/index.js +1 -1
- package/dist/{chunk-UPXDBHEE.js → chunk-FOXGPGXF.js} +16 -3
- package/dist/chunk-FOXGPGXF.js.map +1 -0
- package/dist/chunk-MH74DY2I.js +175 -0
- package/dist/chunk-MH74DY2I.js.map +1 -0
- package/dist/{chunk-LRHVCVEW.js → chunk-Q4ZER4HI.js} +39 -1
- package/dist/chunk-Q4ZER4HI.js.map +1 -0
- package/dist/redact/index.d.ts +1 -0
- package/dist/redact/index.js +10 -116
- package/dist/redact/index.js.map +1 -1
- package/dist/store/index.d.ts +35 -0
- package/dist/store/index.js +3 -1
- package/dist/web-react/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-LRHVCVEW.js.map +0 -1
- package/dist/chunk-UPXDBHEE.js.map +0 -1
package/dist/assistant/index.js
CHANGED
|
@@ -46,39 +46,82 @@ export type AttachmentReadResult = {
|
|
|
46
46
|
* turn-level exception.
|
|
47
47
|
*/
|
|
48
48
|
export type ReadAttachmentFn = (scopeId: string, path: string) => Promise<AttachmentReadResult>;
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
49
|
+
/** The ownership identity for one attempted write. The upload and promotion
|
|
50
|
+
* routes create a unique path for each attempt, and the product adapter stores
|
|
51
|
+
* this id with it. */
|
|
52
|
+
export interface AttachmentWriteOwnership {
|
|
53
|
+
readonly id: string;
|
|
54
|
+
readonly path: string;
|
|
55
|
+
}
|
|
56
|
+
/** Public-safe outcome for a storage outage. Backend details belong in logs. */
|
|
57
|
+
export declare const ATTACHMENT_STORAGE_FAILURE_MESSAGE = "Attachment storage is temporarily unavailable. Please try again.";
|
|
58
|
+
/** Stable client error code when compensating cleanup did not complete. */
|
|
59
|
+
export declare const ATTACHMENT_ROLLBACK_FAILURE_CODE = "rollback_failed";
|
|
60
|
+
/** Public-safe outcome when compensating cleanup did not complete. */
|
|
61
|
+
export declare const ATTACHMENT_ROLLBACK_FAILURE_MESSAGE = "Attachment cleanup failed. Please try again.";
|
|
62
|
+
/** Add a path-safe ownership id to a logical path and return an immutable store key. */
|
|
63
|
+
export declare function immutableAttachmentPath(logicalPath: string, ownershipId: string): string;
|
|
64
|
+
/** Compensation for one attachment write. The adapter MUST compare the stored
|
|
65
|
+
* ownership id before deleting, so an older rollback cannot delete a newer
|
|
66
|
+
* overwrite. */
|
|
67
|
+
export interface AttachmentWriteReceipt {
|
|
68
|
+
rollback(): void | Promise<void>;
|
|
69
|
+
ownership: AttachmentWriteOwnership;
|
|
70
|
+
}
|
|
71
|
+
/** Clean up a write whose function threw after the store may have committed.
|
|
72
|
+
* The adapter must delete only the supplied ownership, never the logical path
|
|
73
|
+
* unconditionally. */
|
|
74
|
+
export type AbortAttachmentWriteFn = (scopeId: string, ownership: AttachmentWriteOwnership) => void | Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* The stable writer result from the original attachment-store contract.
|
|
77
|
+
* Existing products may return this shape and keep using the legacy writer
|
|
78
|
+
* lane. New products should use {@link AtomicAttachmentWriteResult}.
|
|
79
|
+
*/
|
|
51
80
|
export type AttachmentWriteResult = {
|
|
52
81
|
ok: true;
|
|
53
82
|
} | {
|
|
54
83
|
ok: false;
|
|
55
84
|
reason: string;
|
|
56
85
|
};
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
* or a base64 `string` — a string argument is ALWAYS base64 (never utf8), so
|
|
60
|
-
* a store that speaks base64 (gtm's vault) writes it verbatim and one that
|
|
61
|
-
* speaks bytes decodes once. Like the reader, failures resolve to
|
|
62
|
-
* `{ ok: false, reason }` rather than throwing.
|
|
63
|
-
*
|
|
64
|
-
* `opts` mirrors the vault frontmatter gtm's `writeAttachmentVaultFile`
|
|
65
|
-
* persists alongside the body (promote-file-parts.ts:181-190), so a product
|
|
66
|
-
* reimplementing that vault writer through this seam can reproduce it
|
|
67
|
-
* exactly:
|
|
68
|
-
* - `mediaType` — the resolved MIME type; gtm's frontmatter key `mime`.
|
|
69
|
-
* - `name` — the sanitized (store-path-safe) display filename; gtm passes
|
|
70
|
-
* this only to shape its oversize message, not into frontmatter.
|
|
71
|
-
* - `originalName` — the filename as the harness/browser reported it, BEFORE
|
|
72
|
-
* sanitization (`raw.filename ?? filename` — falls back to the sanitized
|
|
73
|
-
* name when the source carried none); gtm's frontmatter key `originalName`.
|
|
74
|
-
* This is the one field with no other recovery path once sanitization has
|
|
75
|
-
* run, so it must ride the write, not be re-derived after the fact.
|
|
76
|
-
* - `size` — the authoritative decoded byte length being written; gtm's
|
|
77
|
-
* frontmatter key `size`.
|
|
78
|
-
*/
|
|
79
|
-
export type WriteAttachmentFn = (scopeId: string, path: string, content: Uint8Array | string, opts: {
|
|
86
|
+
/** Options from the stable attachment-store contract. */
|
|
87
|
+
export interface AttachmentWriteOptions {
|
|
80
88
|
mediaType?: string;
|
|
81
89
|
name?: string;
|
|
82
90
|
originalName?: string;
|
|
83
91
|
size?: number;
|
|
84
|
-
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The stable writer port. It is intentionally unchanged so products released
|
|
95
|
+
* before the ownership receipt contract continue to compile.
|
|
96
|
+
*
|
|
97
|
+
* The legacy lane does not promise batch rollback. Use
|
|
98
|
+
* {@link createAtomicAttachmentWriter} for ownership-safe writes.
|
|
99
|
+
*/
|
|
100
|
+
export type WriteAttachmentFn = (scopeId: string, path: string, content: Uint8Array | string, opts: AttachmentWriteOptions) => Promise<AttachmentWriteResult>;
|
|
101
|
+
/** Options for an ownership-safe writer. */
|
|
102
|
+
export interface AtomicAttachmentWriteOptions extends AttachmentWriteOptions {
|
|
103
|
+
ownership: AttachmentWriteOwnership;
|
|
104
|
+
}
|
|
105
|
+
/** Result for an ownership-safe writer. A receipt is required on both paths. */
|
|
106
|
+
export type AtomicAttachmentWriteResult = {
|
|
107
|
+
ok: true;
|
|
108
|
+
receipt: AttachmentWriteReceipt;
|
|
109
|
+
} | {
|
|
110
|
+
ok: false;
|
|
111
|
+
reason: string;
|
|
112
|
+
receipt: AttachmentWriteReceipt;
|
|
113
|
+
};
|
|
114
|
+
/** Ownership-safe writer port used by the atomic upload and promotion lanes. */
|
|
115
|
+
export type AtomicWriteAttachmentFn = (scopeId: string, path: string, content: Uint8Array | string, opts: AtomicAttachmentWriteOptions) => Promise<AtomicAttachmentWriteResult>;
|
|
116
|
+
/** A complete ownership-safe attachment store adapter. */
|
|
117
|
+
export interface AtomicAttachmentWriter {
|
|
118
|
+
write: AtomicWriteAttachmentFn;
|
|
119
|
+
abort: AbortAttachmentWriteFn;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Build the explicit atomic adapter used by new routes.
|
|
123
|
+
*
|
|
124
|
+
* Keeping the write and abort functions together prevents a caller from
|
|
125
|
+
* enabling ownership paths while forgetting the ambiguous-write cleanup.
|
|
126
|
+
*/
|
|
127
|
+
export declare function createAtomicAttachmentWriter(input: AtomicAttachmentWriter): AtomicAttachmentWriter;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `createAttachmentUploadRoute` — the fleet-primitive durable-store upload
|
|
3
|
-
* route: a two-phase
|
|
4
|
-
*
|
|
3
|
+
* route: a two-phase batch (every file is validated before any file is written),
|
|
4
|
+
* with a stable legacy lane and an ownership-safe receipt lane for new callers,
|
|
5
|
+
* a content-sniffed type gate
|
|
5
6
|
* (`checkAttachmentType` over `sniffBinary`'s magic-byte read, not the
|
|
6
7
|
* extension or the browser-reported MIME), binary/text caps with optional
|
|
7
8
|
* per-sniffed-mime overrides, an aggregate byte cap, and sanitized filenames.
|
|
8
9
|
* Storage is fully seamed through the injected
|
|
9
|
-
* `WriteAttachmentFn` (`./attachment-store`) — no
|
|
10
|
-
* owns where bytes actually live (vault, object
|
|
11
|
-
* limiting is entirely the injected `authorize`
|
|
10
|
+
* `WriteAttachmentFn` or `AtomicAttachmentWriter` (`./attachment-store`) — no
|
|
11
|
+
* default store, the product owns where bytes actually live (vault, object
|
|
12
|
+
* store, …), and auth/rate limiting is entirely the injected `authorize`
|
|
13
|
+
* seam's job: this factory
|
|
12
14
|
* never invents a 401 or 429 response, it only returns `auth.response`
|
|
13
15
|
* verbatim on failure.
|
|
14
16
|
*
|
|
@@ -26,14 +28,9 @@
|
|
|
26
28
|
* comment for the up-to-date framing between the two.
|
|
27
29
|
*/
|
|
28
30
|
import type { ChatAttachmentKind } from './wire';
|
|
29
|
-
import type
|
|
31
|
+
import { type AtomicAttachmentWriter, type WriteAttachmentFn } from './attachment-store';
|
|
30
32
|
import { type AttachmentPathCheck } from './resolve-attachments';
|
|
31
|
-
/**
|
|
32
|
-
* scope resolution, all in one place so a 429 rides `{ok:false, response}`
|
|
33
|
-
* exactly like a 401 does — this factory has no rate-limit opinion of its
|
|
34
|
-
* own. `writeAttachment` lets a single request override the option-level
|
|
35
|
-
* store (e.g. routing per-tenant), defaulting to `options.writeAttachment`
|
|
36
|
-
* when absent. */
|
|
33
|
+
/** Stable authorization result for the original writer contract. */
|
|
37
34
|
export type AttachmentUploadAuthorization = {
|
|
38
35
|
ok: true;
|
|
39
36
|
scopeId: string;
|
|
@@ -42,48 +39,72 @@ export type AttachmentUploadAuthorization = {
|
|
|
42
39
|
ok: false;
|
|
43
40
|
response: Response;
|
|
44
41
|
};
|
|
45
|
-
/**
|
|
46
|
-
export
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
42
|
+
/** Authorization result for an ownership-safe attachment writer. */
|
|
43
|
+
export type AtomicAttachmentUploadAuthorization = {
|
|
44
|
+
ok: true;
|
|
45
|
+
scopeId: string;
|
|
46
|
+
attachmentWriter?: AtomicAttachmentWriter;
|
|
47
|
+
} | {
|
|
48
|
+
ok: false;
|
|
49
|
+
response: Response;
|
|
50
|
+
};
|
|
51
|
+
/** The logger receives only sanitized backend details. The client receives the
|
|
52
|
+
* opaque message below, regardless of the store's failure text. */
|
|
53
|
+
export type AttachmentUploadLogger = Pick<Console, 'error'>;
|
|
54
|
+
interface AttachmentUploadRouteCommonOptions {
|
|
54
55
|
/** Overridable caps. Defaults come from `./attachment-validation`. */
|
|
55
56
|
limits?: {
|
|
56
57
|
/** Most files one request may carry. Default {@link ATTACHMENT_MAX_COUNT}. */
|
|
57
58
|
maxCount?: number;
|
|
58
59
|
/** Ceiling on a binary file's raw size. Default {@link MAX_BINARY_ATTACHMENT_BYTES}. */
|
|
59
60
|
maxBinaryBytes?: number;
|
|
60
|
-
/** Optional binary-file ceilings keyed by the content-sniffed mime.
|
|
61
|
-
* missing mime falls back to `maxBinaryBytes`; text files continue to use
|
|
62
|
-
* `maxTextBytes`. */
|
|
61
|
+
/** Optional binary-file ceilings keyed by the content-sniffed mime. */
|
|
63
62
|
maxBytesBySniffedMime?: ReadonlyMap<string, number>;
|
|
64
63
|
/** Ceiling on a text file's raw size. Default {@link MAX_TEXT_ATTACHMENT_BYTES}. */
|
|
65
64
|
maxTextBytes?: number;
|
|
66
|
-
/** Aggregate raw-byte ceiling
|
|
65
|
+
/** Aggregate raw-byte ceiling. Default {@link MAX_ATTACHMENT_TOTAL_BYTES}. */
|
|
67
66
|
maxTotalBytes?: number;
|
|
68
67
|
};
|
|
69
68
|
/** Attachment kinds this route accepts. Default `['image', 'file']`. */
|
|
70
69
|
allowedKinds?: ChatAttachmentKind[];
|
|
71
|
-
/** Sniffed-mime allowlist fed to `checkAttachmentType`.
|
|
72
|
-
* {@link ALLOWED_ATTACHMENT_SNIFFED_MIMES}. Narrow it to accept less than
|
|
73
|
-
* the default (`new Set(['application/pdf'])`), or widen it to accept a
|
|
74
|
-
* format the default refuses — macro-enabled Office packages are the
|
|
75
|
-
* shipped case:
|
|
76
|
-
* `new Set([...ALLOWED_ATTACHMENT_SNIFFED_MIMES, ...MACRO_ENABLED_OOXML_SNIFFED_MIMES])`. */
|
|
70
|
+
/** Sniffed-mime allowlist fed to `checkAttachmentType`. */
|
|
77
71
|
allowedSniffedMimes?: ReadonlySet<string>;
|
|
78
|
-
/** Sanitized-name → store path.
|
|
79
|
-
* the path); gtm passes `vaultFolderForFileName`, a tenant product a
|
|
80
|
-
* scope prefix. */
|
|
72
|
+
/** Sanitized-name → logical store path. */
|
|
81
73
|
pathFor?: (name: string) => string;
|
|
82
74
|
/** Store-path validator. Default {@link defaultValidateAttachmentPath}. */
|
|
83
75
|
validatePath?: (path: string) => AttachmentPathCheck;
|
|
84
|
-
/** Last-resort media-type hook for text content the sniffer
|
|
85
|
-
* Default {@link sniffMimeFromName}. */
|
|
76
|
+
/** Last-resort media-type hook for text content the sniffer cannot type. */
|
|
86
77
|
sniffMime?: (name: string) => string;
|
|
78
|
+
/** Unique id source for atomic ownership keys. */
|
|
79
|
+
createWriteId?: () => string;
|
|
80
|
+
/** Server-side error sink. Backend text is sanitized before it is logged. */
|
|
81
|
+
logger?: AttachmentUploadLogger;
|
|
82
|
+
}
|
|
83
|
+
/** Stable route options for products using the original writer contract. */
|
|
84
|
+
export interface CreateLegacyAttachmentUploadRouteOptions extends AttachmentUploadRouteCommonOptions {
|
|
85
|
+
/** Authenticate the caller, rate-limit, and resolve the store scope
|
|
86
|
+
* (workspace/tenant id) — never a query param. */
|
|
87
|
+
authorize(args: {
|
|
88
|
+
request: Request;
|
|
89
|
+
}): Promise<AttachmentUploadAuthorization>;
|
|
90
|
+
/** Stable writer. `authorize` may override it per-request. */
|
|
91
|
+
writeAttachment: WriteAttachmentFn;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* The original public route-options interface remains available for consumers
|
|
95
|
+
* that extend it. Ownership-safe callers use the atomic interface below.
|
|
96
|
+
*/
|
|
97
|
+
export interface CreateAttachmentUploadRouteOptions extends CreateLegacyAttachmentUploadRouteOptions {
|
|
98
|
+
}
|
|
99
|
+
/** Ownership-safe route options for new products. */
|
|
100
|
+
export interface CreateAtomicAttachmentUploadRouteOptions extends AttachmentUploadRouteCommonOptions {
|
|
101
|
+
/** Authenticate the caller, rate-limit, and resolve the store scope. */
|
|
102
|
+
authorize(args: {
|
|
103
|
+
request: Request;
|
|
104
|
+
}): Promise<AtomicAttachmentUploadAuthorization>;
|
|
105
|
+
/** Complete writer + ambiguous-write cleanup adapter. */
|
|
106
|
+
attachmentWriter: AtomicAttachmentWriter;
|
|
87
107
|
}
|
|
88
|
-
/** Resolve an attachment upload route handler with customizable limits and validation options */
|
|
89
|
-
export declare function createAttachmentUploadRoute(options: CreateAttachmentUploadRouteOptions): (request: Request) => Promise<Response>;
|
|
108
|
+
/** Resolve an attachment upload route handler with customizable limits and validation options. */
|
|
109
|
+
export declare function createAttachmentUploadRoute(options: CreateAttachmentUploadRouteOptions | CreateAtomicAttachmentUploadRouteOptions): (request: Request) => Promise<Response>;
|
|
110
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AtomicAttachmentWriteResult, AttachmentWriteOwnership, AttachmentWriteResult } from './attachment-store';
|
|
2
|
+
/** Read an injected writer result without allowing hostile getters to escape. */
|
|
3
|
+
export declare function inspectLegacyAttachmentWriteResult(value: unknown): AttachmentWriteResult | undefined;
|
|
4
|
+
/**
|
|
5
|
+
* Read an ownership-aware writer result with strict runtime checks.
|
|
6
|
+
*
|
|
7
|
+
* The public types protect TypeScript callers only. The product adapter is an
|
|
8
|
+
* injection boundary, so a proxy, malformed value, or truthy non-boolean must
|
|
9
|
+
* fail closed before the route invokes cleanup or publishes a path.
|
|
10
|
+
*/
|
|
11
|
+
export declare function inspectAtomicAttachmentWriteResult(value: unknown, ownership: AttachmentWriteOwnership): AtomicAttachmentWriteResult | undefined;
|