@nextclaw/ncp-react 0.3.5 → 0.3.6
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/index.d.ts +10 -2
- package/dist/index.js +87 -25
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -34,13 +34,17 @@ declare function useNcpAgent(sessionId: string, client: NcpAgentClientEndpoint):
|
|
|
34
34
|
|
|
35
35
|
declare const DEFAULT_NCP_IMAGE_ATTACHMENT_ACCEPT = "image/png,image/jpeg,image/webp,image/gif";
|
|
36
36
|
declare const DEFAULT_NCP_IMAGE_ATTACHMENT_MIME_TYPES: readonly ["image/png", "image/jpeg", "image/webp", "image/gif"];
|
|
37
|
+
declare const DEFAULT_NCP_ATTACHMENT_MAX_BYTES: number;
|
|
37
38
|
declare const DEFAULT_NCP_IMAGE_ATTACHMENT_MAX_BYTES: number;
|
|
39
|
+
declare const DEFAULT_NCP_FALLBACK_ATTACHMENT_MIME_TYPE = "application/octet-stream";
|
|
38
40
|
type NcpDraftAttachment = {
|
|
39
41
|
id: string;
|
|
40
42
|
name: string;
|
|
41
43
|
mimeType: string;
|
|
42
|
-
contentBase64: string;
|
|
43
44
|
sizeBytes: number;
|
|
45
|
+
attachmentUri?: string;
|
|
46
|
+
url?: string;
|
|
47
|
+
contentBase64?: string;
|
|
44
48
|
};
|
|
45
49
|
type NcpRejectedAttachment = {
|
|
46
50
|
fileName: string;
|
|
@@ -52,6 +56,9 @@ type ReadNcpDraftAttachmentsOptions = {
|
|
|
52
56
|
acceptedMimeTypes?: readonly string[];
|
|
53
57
|
maxBytes?: number;
|
|
54
58
|
};
|
|
59
|
+
type UploadNcpDraftAttachmentsOptions = ReadNcpDraftAttachmentsOptions & {
|
|
60
|
+
uploadBatch: (files: File[]) => Promise<NcpDraftAttachment[]>;
|
|
61
|
+
};
|
|
55
62
|
type ReadNcpDraftAttachmentsResult = {
|
|
56
63
|
attachments: NcpDraftAttachment[];
|
|
57
64
|
rejected: NcpRejectedAttachment[];
|
|
@@ -67,5 +74,6 @@ declare function buildNcpRequestEnvelope(params: {
|
|
|
67
74
|
timestamp?: string;
|
|
68
75
|
}): NcpRequestEnvelope | null;
|
|
69
76
|
declare function readFilesAsNcpDraftAttachments(files: Iterable<File>, options?: ReadNcpDraftAttachmentsOptions): Promise<ReadNcpDraftAttachmentsResult>;
|
|
77
|
+
declare function uploadFilesAsNcpDraftAttachments(files: Iterable<File>, options: UploadNcpDraftAttachmentsOptions): Promise<ReadNcpDraftAttachmentsResult>;
|
|
70
78
|
|
|
71
|
-
export { DEFAULT_NCP_IMAGE_ATTACHMENT_ACCEPT, DEFAULT_NCP_IMAGE_ATTACHMENT_MAX_BYTES, DEFAULT_NCP_IMAGE_ATTACHMENT_MIME_TYPES, type NcpConversationSeed, type NcpConversationSeedLoader, type NcpDraftAttachment, type NcpRejectedAttachment, type ReadNcpDraftAttachmentsOptions, type ReadNcpDraftAttachmentsResult, type UseHydratedNcpAgentOptions, type UseHydratedNcpAgentResult, type UseNcpAgentResult, buildNcpImageAttachmentDataUrl, buildNcpRequestEnvelope, readFilesAsNcpDraftAttachments, useHydratedNcpAgent, useNcpAgent };
|
|
79
|
+
export { DEFAULT_NCP_ATTACHMENT_MAX_BYTES, DEFAULT_NCP_FALLBACK_ATTACHMENT_MIME_TYPE, DEFAULT_NCP_IMAGE_ATTACHMENT_ACCEPT, DEFAULT_NCP_IMAGE_ATTACHMENT_MAX_BYTES, DEFAULT_NCP_IMAGE_ATTACHMENT_MIME_TYPES, type NcpConversationSeed, type NcpConversationSeedLoader, type NcpDraftAttachment, type NcpRejectedAttachment, type ReadNcpDraftAttachmentsOptions, type ReadNcpDraftAttachmentsResult, type UploadNcpDraftAttachmentsOptions, type UseHydratedNcpAgentOptions, type UseHydratedNcpAgentResult, type UseNcpAgentResult, buildNcpImageAttachmentDataUrl, buildNcpRequestEnvelope, readFilesAsNcpDraftAttachments, uploadFilesAsNcpDraftAttachments, useHydratedNcpAgent, useNcpAgent };
|
package/dist/index.js
CHANGED
|
@@ -233,7 +233,9 @@ var DEFAULT_NCP_IMAGE_ATTACHMENT_MIME_TYPES = [
|
|
|
233
233
|
"image/webp",
|
|
234
234
|
"image/gif"
|
|
235
235
|
];
|
|
236
|
-
var
|
|
236
|
+
var DEFAULT_NCP_ATTACHMENT_MAX_BYTES = 10 * 1024 * 1024;
|
|
237
|
+
var DEFAULT_NCP_IMAGE_ATTACHMENT_MAX_BYTES = DEFAULT_NCP_ATTACHMENT_MAX_BYTES;
|
|
238
|
+
var DEFAULT_NCP_FALLBACK_ATTACHMENT_MIME_TYPE = "application/octet-stream";
|
|
237
239
|
function createAttachmentId() {
|
|
238
240
|
return `ncp-file-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
239
241
|
}
|
|
@@ -255,7 +257,45 @@ function toBase64Content(dataUrl) {
|
|
|
255
257
|
const commaIndex = dataUrl.indexOf(",");
|
|
256
258
|
return commaIndex >= 0 ? dataUrl.slice(commaIndex + 1) : dataUrl;
|
|
257
259
|
}
|
|
260
|
+
function normalizeAttachmentMimeType(file) {
|
|
261
|
+
const mimeType = file.type.trim().toLowerCase();
|
|
262
|
+
return mimeType.length > 0 ? mimeType : DEFAULT_NCP_FALLBACK_ATTACHMENT_MIME_TYPE;
|
|
263
|
+
}
|
|
264
|
+
function validateAttachmentFile(file, options) {
|
|
265
|
+
const acceptedMimeTypes = options.acceptedMimeTypes && options.acceptedMimeTypes.length > 0 ? new Set(options.acceptedMimeTypes.map((mimeType2) => mimeType2.trim().toLowerCase())) : null;
|
|
266
|
+
const maxBytes = options.maxBytes ?? DEFAULT_NCP_ATTACHMENT_MAX_BYTES;
|
|
267
|
+
const mimeType = normalizeAttachmentMimeType(file);
|
|
268
|
+
if (acceptedMimeTypes && !acceptedMimeTypes.has(mimeType)) {
|
|
269
|
+
return {
|
|
270
|
+
ok: false,
|
|
271
|
+
rejected: {
|
|
272
|
+
fileName: file.name,
|
|
273
|
+
mimeType,
|
|
274
|
+
sizeBytes: file.size,
|
|
275
|
+
reason: "unsupported-type"
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
if (file.size > maxBytes) {
|
|
280
|
+
return {
|
|
281
|
+
ok: false,
|
|
282
|
+
rejected: {
|
|
283
|
+
fileName: file.name,
|
|
284
|
+
mimeType,
|
|
285
|
+
sizeBytes: file.size,
|
|
286
|
+
reason: "too-large"
|
|
287
|
+
}
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
return { ok: true, mimeType };
|
|
291
|
+
}
|
|
258
292
|
function buildNcpImageAttachmentDataUrl(attachment) {
|
|
293
|
+
if (attachment.url?.trim()) {
|
|
294
|
+
return attachment.url.trim();
|
|
295
|
+
}
|
|
296
|
+
if (!attachment.contentBase64?.trim()) {
|
|
297
|
+
throw new Error(`Attachment ${attachment.name} does not have image content.`);
|
|
298
|
+
}
|
|
259
299
|
return `data:${attachment.mimeType};base64,${attachment.contentBase64}`;
|
|
260
300
|
}
|
|
261
301
|
function buildNcpRequestEnvelope(params) {
|
|
@@ -265,7 +305,9 @@ function buildNcpRequestEnvelope(params) {
|
|
|
265
305
|
type: "file",
|
|
266
306
|
name: attachment.name,
|
|
267
307
|
mimeType: attachment.mimeType,
|
|
268
|
-
|
|
308
|
+
...attachment.attachmentUri?.trim() ? { attachmentUri: attachment.attachmentUri.trim() } : {},
|
|
309
|
+
...attachment.url?.trim() ? { url: attachment.url.trim() } : {},
|
|
310
|
+
...attachment.contentBase64?.trim() ? { contentBase64: attachment.contentBase64.trim() } : {},
|
|
269
311
|
sizeBytes: attachment.sizeBytes
|
|
270
312
|
}))
|
|
271
313
|
];
|
|
@@ -289,30 +331,12 @@ function buildNcpRequestEnvelope(params) {
|
|
|
289
331
|
};
|
|
290
332
|
}
|
|
291
333
|
async function readFilesAsNcpDraftAttachments(files, options = {}) {
|
|
292
|
-
const acceptedMimeTypes = new Set(
|
|
293
|
-
options.acceptedMimeTypes ?? DEFAULT_NCP_IMAGE_ATTACHMENT_MIME_TYPES
|
|
294
|
-
);
|
|
295
|
-
const maxBytes = options.maxBytes ?? DEFAULT_NCP_IMAGE_ATTACHMENT_MAX_BYTES;
|
|
296
334
|
const attachments = [];
|
|
297
335
|
const rejected = [];
|
|
298
336
|
for (const file of files) {
|
|
299
|
-
const
|
|
300
|
-
if (!
|
|
301
|
-
rejected.push(
|
|
302
|
-
fileName: file.name,
|
|
303
|
-
mimeType,
|
|
304
|
-
sizeBytes: file.size,
|
|
305
|
-
reason: "unsupported-type"
|
|
306
|
-
});
|
|
307
|
-
continue;
|
|
308
|
-
}
|
|
309
|
-
if (file.size > maxBytes) {
|
|
310
|
-
rejected.push({
|
|
311
|
-
fileName: file.name,
|
|
312
|
-
mimeType,
|
|
313
|
-
sizeBytes: file.size,
|
|
314
|
-
reason: "too-large"
|
|
315
|
-
});
|
|
337
|
+
const validation = validateAttachmentFile(file, options);
|
|
338
|
+
if (!validation.ok) {
|
|
339
|
+
rejected.push(validation.rejected);
|
|
316
340
|
continue;
|
|
317
341
|
}
|
|
318
342
|
try {
|
|
@@ -320,14 +344,14 @@ async function readFilesAsNcpDraftAttachments(files, options = {}) {
|
|
|
320
344
|
attachments.push({
|
|
321
345
|
id: createAttachmentId(),
|
|
322
346
|
name: file.name,
|
|
323
|
-
mimeType,
|
|
347
|
+
mimeType: validation.mimeType,
|
|
324
348
|
contentBase64: toBase64Content(dataUrl),
|
|
325
349
|
sizeBytes: file.size
|
|
326
350
|
});
|
|
327
351
|
} catch {
|
|
328
352
|
rejected.push({
|
|
329
353
|
fileName: file.name,
|
|
330
|
-
mimeType,
|
|
354
|
+
mimeType: validation.mimeType,
|
|
331
355
|
sizeBytes: file.size,
|
|
332
356
|
reason: "read-failed"
|
|
333
357
|
});
|
|
@@ -335,13 +359,51 @@ async function readFilesAsNcpDraftAttachments(files, options = {}) {
|
|
|
335
359
|
}
|
|
336
360
|
return { attachments, rejected };
|
|
337
361
|
}
|
|
362
|
+
async function uploadFilesAsNcpDraftAttachments(files, options) {
|
|
363
|
+
const validFiles = [];
|
|
364
|
+
const rejected = [];
|
|
365
|
+
for (const file of files) {
|
|
366
|
+
const validation = validateAttachmentFile(file, options);
|
|
367
|
+
if (!validation.ok) {
|
|
368
|
+
rejected.push(validation.rejected);
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
validFiles.push(file);
|
|
372
|
+
}
|
|
373
|
+
if (validFiles.length === 0) {
|
|
374
|
+
return { attachments: [], rejected };
|
|
375
|
+
}
|
|
376
|
+
try {
|
|
377
|
+
const attachments = await options.uploadBatch(validFiles);
|
|
378
|
+
return {
|
|
379
|
+
attachments,
|
|
380
|
+
rejected
|
|
381
|
+
};
|
|
382
|
+
} catch {
|
|
383
|
+
rejected.push(
|
|
384
|
+
...validFiles.map((file) => ({
|
|
385
|
+
fileName: file.name,
|
|
386
|
+
mimeType: normalizeAttachmentMimeType(file),
|
|
387
|
+
sizeBytes: file.size,
|
|
388
|
+
reason: "read-failed"
|
|
389
|
+
}))
|
|
390
|
+
);
|
|
391
|
+
return {
|
|
392
|
+
attachments: [],
|
|
393
|
+
rejected
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
}
|
|
338
397
|
export {
|
|
398
|
+
DEFAULT_NCP_ATTACHMENT_MAX_BYTES,
|
|
399
|
+
DEFAULT_NCP_FALLBACK_ATTACHMENT_MIME_TYPE,
|
|
339
400
|
DEFAULT_NCP_IMAGE_ATTACHMENT_ACCEPT,
|
|
340
401
|
DEFAULT_NCP_IMAGE_ATTACHMENT_MAX_BYTES,
|
|
341
402
|
DEFAULT_NCP_IMAGE_ATTACHMENT_MIME_TYPES,
|
|
342
403
|
buildNcpImageAttachmentDataUrl,
|
|
343
404
|
buildNcpRequestEnvelope,
|
|
344
405
|
readFilesAsNcpDraftAttachments,
|
|
406
|
+
uploadFilesAsNcpDraftAttachments,
|
|
345
407
|
useHydratedNcpAgent,
|
|
346
408
|
useNcpAgent
|
|
347
409
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextclaw/ncp-react",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "React bindings for building NCP-based agent applications.",
|
|
6
6
|
"type": "module",
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"dist"
|
|
16
16
|
],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@nextclaw/ncp": "0.3
|
|
19
|
-
"@nextclaw/ncp
|
|
18
|
+
"@nextclaw/ncp-toolkit": "0.4.3",
|
|
19
|
+
"@nextclaw/ncp": "0.3.3"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"react": "^18.0.0 || ^19.0.0"
|