@burdenoff/fe-libs 2026.1028.9 → 2026.1028.11
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/shared/assistant/attachmentAccess.d.ts +15 -0
- package/dist/shared/assistant/attachmentAccess.js +42 -0
- package/dist/shared/assistant/attachmentAccessCopy.d.ts +9 -0
- package/dist/shared/assistant/attachmentAccessCopy.js +18 -0
- package/dist/shared/assistant/attachmentCommit.d.ts +18 -5
- package/dist/shared/assistant/attachmentCommit.js +247 -191
- package/dist/shared/assistant/attachments.d.ts +2 -0
- package/dist/shared/assistant/i18nManifest.js +30 -28
- package/dist/shared/assistant/index.d.ts +2 -0
- package/dist/shared/assistant/ui/composer/AssistantAttachmentChips.js +43 -40
- package/dist/shared/assistant/ui/composer/AssistantComposer.js +114 -112
- package/dist/shared/assistant/useAssistantAttachments.js +1 -0
- package/dist/shared/assistant/useAttachmentCommitter.js +50 -33
- package/dist/shared-assistant.js +242 -240
- package/package.json +2 -2
- package/src/shared/tokens/build/semantic.css +2 -2
- package/src/shared/tokens/build/themes.css +3 -3
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type AttachmentAccess = 'allowed' | 'denied' | 'unknown';
|
|
2
|
+
/** Exact operations needed by the Send-time Files commit; no role-name shortcut. */
|
|
3
|
+
export declare const ATTACHMENT_WRITE_PERMISSIONS: readonly [{
|
|
4
|
+
readonly resourceType: "upload-session";
|
|
5
|
+
readonly action: "create";
|
|
6
|
+
}, {
|
|
7
|
+
readonly resourceType: "folder";
|
|
8
|
+
readonly action: "create";
|
|
9
|
+
}, {
|
|
10
|
+
readonly resourceType: "upload-session";
|
|
11
|
+
readonly action: "update";
|
|
12
|
+
}];
|
|
13
|
+
export declare const ATTACHMENT_ACCESS_QUERY = "query AssistantAttachmentPermissions($inputs: [PermissionCheckInput!]!) {\n checkPermissions(inputs: $inputs) { allowed }\n}";
|
|
14
|
+
/** Advisory preflight. An unreadable answer leaves the decision to the real server call. */
|
|
15
|
+
export declare function probeAttachmentAccess(workspaceId: string, actorId: string | null, isSuperAdmin?: boolean): Promise<AttachmentAccess>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { graphqlFetch as e } from "../graphql/fetch.js";
|
|
2
|
+
import "../../shared-graphql.js";
|
|
3
|
+
//#region src/shared/assistant/attachmentAccess.ts
|
|
4
|
+
var t = [
|
|
5
|
+
{
|
|
6
|
+
resourceType: "upload-session",
|
|
7
|
+
action: "create"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
resourceType: "folder",
|
|
11
|
+
action: "create"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
resourceType: "upload-session",
|
|
15
|
+
action: "update"
|
|
16
|
+
}
|
|
17
|
+
], n = "query AssistantAttachmentPermissions($inputs: [PermissionCheckInput!]!) {\n checkPermissions(inputs: $inputs) { allowed }\n}";
|
|
18
|
+
async function r(r, i, a = !1) {
|
|
19
|
+
if (a) return "allowed";
|
|
20
|
+
if (!r || !i) return "unknown";
|
|
21
|
+
try {
|
|
22
|
+
let a = await e({
|
|
23
|
+
gateway: "workspace",
|
|
24
|
+
workspaceId: r,
|
|
25
|
+
query: n,
|
|
26
|
+
variables: { inputs: t.map((e) => ({
|
|
27
|
+
actorId: i,
|
|
28
|
+
actorType: "USER",
|
|
29
|
+
scopeId: r,
|
|
30
|
+
...e
|
|
31
|
+
})) },
|
|
32
|
+
suppressGlobalErrorEvent: !0
|
|
33
|
+
});
|
|
34
|
+
if (a.errors?.length) return "unknown";
|
|
35
|
+
let o = a.data?.checkPermissions;
|
|
36
|
+
return !Array.isArray(o) || o.length !== t.length || o.some((e) => typeof e?.allowed != "boolean") ? "unknown" : o.every((e) => e.allowed) ? "allowed" : "denied";
|
|
37
|
+
} catch {
|
|
38
|
+
return "unknown";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { n as ATTACHMENT_ACCESS_QUERY, t as ATTACHMENT_WRITE_PERMISSIONS, r as probeAttachmentAccess };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AssistantTr } from './i18n';
|
|
2
|
+
export declare const ATTACHMENT_EDITOR_ACCESS_COPY: {
|
|
3
|
+
readonly key: "attachments.editorAccessRequired";
|
|
4
|
+
readonly fallback: "You need Editor access in this workspace to attach files.";
|
|
5
|
+
};
|
|
6
|
+
/** AI-written, 2026-10-28 (BOFF-9912); native review pending. No seed/apply performed. */
|
|
7
|
+
export declare const ATTACHMENT_EDITOR_ACCESS_TRANSLATIONS: Readonly<Record<string, string>>;
|
|
8
|
+
/** Server translations win; the six bundled values also work before a product seed. */
|
|
9
|
+
export declare function attachmentEditorAccessMessage(tr: AssistantTr, locale: string): string;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/shared/assistant/attachmentAccessCopy.ts
|
|
2
|
+
var e = {
|
|
3
|
+
key: "attachments.editorAccessRequired",
|
|
4
|
+
fallback: "You need Editor access in this workspace to attach files."
|
|
5
|
+
}, t = {
|
|
6
|
+
en: e.fallback,
|
|
7
|
+
hi: "फ़ाइलें संलग्न करने के लिए आपको इस कार्यक्षेत्र में संपादक की अनुमति चाहिए।",
|
|
8
|
+
ta: "கோப்புகளை இணைக்க, இந்தப் பணியிடத்தில் உங்களுக்கு எடிட்டர் அணுகல் தேவை.",
|
|
9
|
+
es: "Necesitas acceso de Editor en este espacio de trabajo para adjuntar archivos.",
|
|
10
|
+
ar: "تحتاج إلى صلاحية محرّر في مساحة العمل هذه لإرفاق الملفات.",
|
|
11
|
+
zh: "你需要此工作区的编辑者权限才能附加文件。"
|
|
12
|
+
};
|
|
13
|
+
function n(n, r) {
|
|
14
|
+
let i = t[r.toLowerCase().split("-")[0] ?? "en"] ?? e.fallback;
|
|
15
|
+
return n(e.key, i);
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { e as ATTACHMENT_EDITOR_ACCESS_COPY, t as ATTACHMENT_EDITOR_ACCESS_TRANSLATIONS, n as attachmentEditorAccessMessage };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FilesPort } from '../../storage/filesPort';
|
|
2
2
|
import { AssistantAttachment } from './attachments';
|
|
3
|
+
import { AttachmentAccess } from './attachmentAccess';
|
|
3
4
|
/** files-svc switches to MULTIPART above this size; the browser cannot upload those. */
|
|
4
5
|
export declare const ATTACHMENT_DIRECT_UPLOAD_MAX_BYTES: number;
|
|
5
6
|
/**
|
|
@@ -38,6 +39,7 @@ export type AttachmentCommitPolicy = {
|
|
|
38
39
|
};
|
|
39
40
|
/** Codes for failures the commit decides itself; a server failure keeps the server's own code. */
|
|
40
41
|
export declare const ATTACHMENT_COMMIT_CODES: {
|
|
42
|
+
readonly editorAccessRequired: "ATTACHMENT_EDITOR_ACCESS_REQUIRED";
|
|
41
43
|
readonly quotaNotProvisioned: "QUOTA_NOT_PROVISIONED";
|
|
42
44
|
readonly quotaExceeded: "QUOTA_EXCEEDED";
|
|
43
45
|
readonly tooLarge: "ATTACHMENT_TOO_LARGE_FOR_DIRECT_UPLOAD";
|
|
@@ -46,6 +48,7 @@ export declare const ATTACHMENT_COMMIT_CODES: {
|
|
|
46
48
|
readonly timeout: "ATTACHMENT_SAVE_TIMEOUT";
|
|
47
49
|
readonly uploadFailed: "ATTACHMENT_UPLOAD_FAILED";
|
|
48
50
|
readonly folderFailed: "ATTACHMENT_FOLDER_FAILED";
|
|
51
|
+
readonly pendingUpload: "ATTACHMENT_UPLOAD_UNRESOLVED";
|
|
49
52
|
};
|
|
50
53
|
/** One draft attachment and the bytes held for it in memory. */
|
|
51
54
|
export interface CommitDraft {
|
|
@@ -61,18 +64,22 @@ export interface AttachmentCommitFailure {
|
|
|
61
64
|
}
|
|
62
65
|
/** What a failed rollback leaves for the next commit (or `discardPending`) to retry. */
|
|
63
66
|
export type PendingDiscard =
|
|
64
|
-
/**
|
|
67
|
+
/** Legacy entry: already completed, retained in Files without a delete request. */
|
|
65
68
|
{
|
|
66
69
|
kind: 'file';
|
|
67
70
|
fileId: string;
|
|
68
71
|
}
|
|
69
|
-
/** A
|
|
72
|
+
/** A complete with an unknown outcome; retain its File if it FINALIZED. */
|
|
70
73
|
| {
|
|
71
74
|
kind: 'session';
|
|
72
75
|
sessionId: string;
|
|
76
|
+
attachmentId?: string;
|
|
73
77
|
};
|
|
78
|
+
type SavedAttachment = Pick<AssistantAttachment, 'fileId' | 'downloadUrl' | 'urlResolvedAt'>;
|
|
74
79
|
export interface PendingDiscardStore {
|
|
75
80
|
entries: PendingDiscard[];
|
|
81
|
+
/** In-memory retry references only. Never persisted across identities or page reloads. */
|
|
82
|
+
retained?: Map<string, SavedAttachment>;
|
|
76
83
|
/**
|
|
77
84
|
* The drain that is running now. A drain takes the entries out of `entries` while it works and
|
|
78
85
|
* puts back what it could not settle, so a second drain (or the final one after an unmount)
|
|
@@ -81,7 +88,7 @@ export interface PendingDiscardStore {
|
|
|
81
88
|
draining?: Promise<void>;
|
|
82
89
|
}
|
|
83
90
|
export type CommitMode =
|
|
84
|
-
/** Any failure
|
|
91
|
+
/** Any failure cancels the send and keeps completed private files for retry (composer). */
|
|
85
92
|
'all-or-nothing'
|
|
86
93
|
/** A failed file is dropped and the rest is kept (voice: the spoken question is still asked). */
|
|
87
94
|
| 'best-effort';
|
|
@@ -93,7 +100,7 @@ export type AttachmentCommitSuccess = {
|
|
|
93
100
|
dropped: AttachmentCommitFailure[];
|
|
94
101
|
/** Call once the files are referenced by a sent message; rollback is a no-op from then on. */
|
|
95
102
|
handedOver: () => void;
|
|
96
|
-
/**
|
|
103
|
+
/** Cancel the send handover; completed Files remain available for retry. Never deletes files. */
|
|
97
104
|
rollback: () => Promise<void>;
|
|
98
105
|
};
|
|
99
106
|
export type AttachmentCommitFailureResult = {
|
|
@@ -107,6 +114,8 @@ export type AttachmentCommitFailureResult = {
|
|
|
107
114
|
export type AttachmentCommitResult = AttachmentCommitSuccess | AttachmentCommitFailureResult;
|
|
108
115
|
export interface CommitOptions {
|
|
109
116
|
port: FilesPort;
|
|
117
|
+
/** Read-only permission check before staging; unknown/error preserves the server decision. */
|
|
118
|
+
preflightAccess?: () => Promise<AttachmentAccess>;
|
|
110
119
|
/** The product's attachments folder, e.g. `/BigConsole/AI Assistant/Attachments`. */
|
|
111
120
|
folderPath: string;
|
|
112
121
|
drafts: readonly CommitDraft[];
|
|
@@ -123,13 +132,16 @@ export interface CommitOptions {
|
|
|
123
132
|
now?: () => number;
|
|
124
133
|
sleep?: (ms: number, signal?: AbortSignal) => Promise<void>;
|
|
125
134
|
}
|
|
126
|
-
/**
|
|
135
|
+
/** Reconcile earlier ambiguous completes without deleting a finalized file. */
|
|
127
136
|
export declare function drainPendingDiscards(port: FilesPort, store: PendingDiscardStore, options?: Pick<CommitOptions, 'sleep'> & {
|
|
128
137
|
policy?: Partial<AttachmentCommitPolicy>;
|
|
129
138
|
}): Promise<void>;
|
|
130
139
|
export declare function commitAttachments(options: CommitOptions): Promise<AttachmentCommitResult>;
|
|
131
140
|
export interface AttachmentCommitterConfig {
|
|
132
141
|
port: FilesPort;
|
|
142
|
+
preflightAccess?: CommitOptions['preflightAccess'];
|
|
143
|
+
/** Scope retry state to the identity/workspace used by the Files port. */
|
|
144
|
+
getScopeKey?: () => string;
|
|
133
145
|
folderPath: string;
|
|
134
146
|
onChange?: CommitOptions['onChange'];
|
|
135
147
|
policy?: CommitOptions['policy'];
|
|
@@ -172,3 +184,4 @@ export declare function attachmentUrlIsStale(attachment: Pick<AssistantAttachmen
|
|
|
172
184
|
* and metadata are intact.
|
|
173
185
|
*/
|
|
174
186
|
export declare function refreshStaleAttachmentUrls(attachments: readonly AssistantAttachment[], resolveUrl: (fileId: string) => Promise<string | null>, now?: number): Promise<AssistantAttachment[]>;
|
|
187
|
+
export {};
|