@aleph-alpha/chat-kit 2.0.0 → 2.1.0
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/composables/fileUpload/useFileUpload.d.ts.map +1 -1
- package/dist/composables/index.js +1 -1
- package/dist/{index-Ct5hD214.js → index-DrtHeZpl.js} +14 -3
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/composables/fileUpload/useFileUpload.spec.ts +111 -0
- package/src/composables/fileUpload/useFileUpload.ts +30 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFileUpload.d.ts","sourceRoot":"","sources":["../../../src/composables/fileUpload/useFileUpload.ts"],"names":[],"mappings":"AACA,OAAO,EAkBL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EAKzB,MAAM,SAAS,CAAC;AAEjB,cAAc,SAAS,CAAC;AAybxB,wBAAgB,aAAa,CAC3B,OAAO,EAAE,oBAAoB,GAC5B,mBAAmB,
|
|
1
|
+
{"version":3,"file":"useFileUpload.d.ts","sourceRoot":"","sources":["../../../src/composables/fileUpload/useFileUpload.ts"],"names":[],"mappings":"AACA,OAAO,EAkBL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EAKzB,MAAM,SAAS,CAAC;AAEjB,cAAc,SAAS,CAAC;AAybxB,wBAAgB,aAAa,CAC3B,OAAO,EAAE,oBAAoB,GAC5B,mBAAmB,CA6xBrB"}
|
|
@@ -1033,6 +1033,19 @@ function useFileUpload(options) {
|
|
|
1033
1033
|
for (const key of involvedStateKeys) {
|
|
1034
1034
|
updateEntry(key, { status: "processing", progress: 0 });
|
|
1035
1035
|
}
|
|
1036
|
+
const completeInvolvedFiles = (documents = []) => {
|
|
1037
|
+
const documentIdByFileId = new Map(
|
|
1038
|
+
documents.filter((doc) => doc.file_id && doc.document_id).map((doc) => [doc.file_id, doc.document_id])
|
|
1039
|
+
);
|
|
1040
|
+
for (const key of involvedStateKeys) {
|
|
1041
|
+
updateEntry(key, { status: "success", progress: 100 });
|
|
1042
|
+
const remoteFileId = files.value.get(key)?.remoteFileId;
|
|
1043
|
+
const documentId = remoteFileId ? documentIdByFileId.get(remoteFileId) : void 0;
|
|
1044
|
+
if (documentId) {
|
|
1045
|
+
updateFileMetadata(key, { documentId });
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
};
|
|
1036
1049
|
const runResponse = await client.post(
|
|
1037
1050
|
endpoints.workflowRun(storeId, workflowId),
|
|
1038
1051
|
{ input },
|
|
@@ -1075,9 +1088,7 @@ function useFileUpload(options) {
|
|
|
1075
1088
|
if (data.status === "completed") {
|
|
1076
1089
|
workflowRun.value.status = "completed";
|
|
1077
1090
|
workflowRun.value.completedAt = now();
|
|
1078
|
-
|
|
1079
|
-
updateEntry(key, { status: "success", progress: 100 });
|
|
1080
|
-
}
|
|
1091
|
+
completeInvolvedFiles(Array.isArray(data.documents) ? data.documents : []);
|
|
1081
1092
|
emit({ type: "workflow:completed", runId });
|
|
1082
1093
|
} else if (data.status === "failed" || data.status === "error") {
|
|
1083
1094
|
workflowRun.value.status = "failed";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { u } from "./useMessageHandler-CMdy-lm0.js";
|
|
2
2
|
import { C, d, p, u as u2, a } from "./useChatKitLabels-ZutacPad.js";
|
|
3
|
-
import { S, c, d as d2, a as a2, u as u3, b, e, f } from "./index-
|
|
3
|
+
import { S, c, d as d2, a as a2, u as u3, b, e, f } from "./index-DrtHeZpl.js";
|
|
4
4
|
import { _, a as a3, b as b2, C as C2, c as c2, d as d3, e as e2, f as f2, g, h, i, j, k, l, m, n, o, p as p2, q, r, s, t } from "./CkInput.vue_vue_type_script_setup_true_lang-DPZedAQS.js";
|
|
5
5
|
export {
|
|
6
6
|
C as CHAT_KIT_LABELS,
|
package/package.json
CHANGED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { useFileUpload } from './useFileUpload';
|
|
2
|
+
import type { FileEntry, HttpClient, SseEvent } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Build a minimal `FileEntry` in the post-upload `processing` state so
|
|
6
|
+
* `runWorkflow` treats it as an involved file (it filters on `remoteFileId`).
|
|
7
|
+
*/
|
|
8
|
+
function makeEntry(id: string, remoteFileId: string): FileEntry {
|
|
9
|
+
return {
|
|
10
|
+
id,
|
|
11
|
+
groupId: 'group-1',
|
|
12
|
+
fileName: `${id}.pdf`,
|
|
13
|
+
fileSize: 1,
|
|
14
|
+
fileType: 'application/pdf',
|
|
15
|
+
status: 'processing',
|
|
16
|
+
progress: 0,
|
|
17
|
+
queuedAt: 'now',
|
|
18
|
+
uploadStartedAt: null,
|
|
19
|
+
uploadCompletedAt: null,
|
|
20
|
+
cancelledAt: null,
|
|
21
|
+
removedAt: null,
|
|
22
|
+
uploadDurationMs: null,
|
|
23
|
+
remoteFileId,
|
|
24
|
+
error: null,
|
|
25
|
+
attemptCount: 0,
|
|
26
|
+
lastAttemptAt: null,
|
|
27
|
+
thumbnail: null,
|
|
28
|
+
metadata: {},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Mock `HttpClient` whose `stream` captures the subscriber so the test can
|
|
34
|
+
* drive SSE events synchronously. `post` resolves the workflow run id.
|
|
35
|
+
*/
|
|
36
|
+
function createMockClient(captured: { cb?: (event: SseEvent) => void }) {
|
|
37
|
+
return {
|
|
38
|
+
get: vi.fn(),
|
|
39
|
+
delete: vi.fn(),
|
|
40
|
+
post: vi.fn().mockResolvedValue({ id: 'run-1' }),
|
|
41
|
+
stream: vi.fn(() => ({
|
|
42
|
+
subscribe: (cb: (event: SseEvent) => void) => {
|
|
43
|
+
captured.cb = cb;
|
|
44
|
+
},
|
|
45
|
+
close: vi.fn(),
|
|
46
|
+
})),
|
|
47
|
+
} as unknown as HttpClient;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function completeEvent(
|
|
51
|
+
documents: Array<{ document_id?: string; file_id?: string }>,
|
|
52
|
+
): SseEvent {
|
|
53
|
+
return {
|
|
54
|
+
event: 'complete',
|
|
55
|
+
data: JSON.stringify({
|
|
56
|
+
document_ids: documents.map((d) => d.document_id),
|
|
57
|
+
documents,
|
|
58
|
+
status: 'completed',
|
|
59
|
+
}),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe('useFileUpload runWorkflow', () => {
|
|
64
|
+
it('stamps documentId onto each file from the completed event, matched by file_id', async () => {
|
|
65
|
+
const captured: { cb?: (event: SseEvent) => void } = {};
|
|
66
|
+
const upload = useFileUpload({
|
|
67
|
+
client: createMockClient(captured),
|
|
68
|
+
workflowId: 'wf',
|
|
69
|
+
storeId: 'ss-1',
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
upload.files.value.set('key-1', makeEntry('key-1', 'file-1'));
|
|
73
|
+
upload.files.value.set('key-2', makeEntry('key-2', 'file-2'));
|
|
74
|
+
|
|
75
|
+
await upload.runWorkflow(['file-1', 'file-2']);
|
|
76
|
+
expect(captured.cb).toBeDefined();
|
|
77
|
+
|
|
78
|
+
// Reverse order on purpose: mapping must be keyed by file_id, not position.
|
|
79
|
+
captured.cb!(
|
|
80
|
+
completeEvent([
|
|
81
|
+
{ document_id: 'doc-2', file_id: 'file-2' },
|
|
82
|
+
{ document_id: 'doc-1', file_id: 'file-1' },
|
|
83
|
+
]),
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
expect(upload.getFileState('key-1')?.metadata.documentId).toBe('doc-1');
|
|
87
|
+
expect(upload.getFileState('key-2')?.metadata.documentId).toBe('doc-2');
|
|
88
|
+
expect(upload.getFileState('key-1')?.status).toBe('success');
|
|
89
|
+
expect(upload.getFileState('key-2')?.status).toBe('success');
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('marks files successful without a documentId when the event has no documents', async () => {
|
|
93
|
+
const captured: { cb?: (event: SseEvent) => void } = {};
|
|
94
|
+
const upload = useFileUpload({
|
|
95
|
+
client: createMockClient(captured),
|
|
96
|
+
workflowId: 'wf',
|
|
97
|
+
storeId: 'ss-1',
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
upload.files.value.set('key-1', makeEntry('key-1', 'file-1'));
|
|
101
|
+
|
|
102
|
+
await upload.runWorkflow(['file-1']);
|
|
103
|
+
captured.cb!({
|
|
104
|
+
event: 'complete',
|
|
105
|
+
data: JSON.stringify({ status: 'completed' }),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
expect(upload.getFileState('key-1')?.status).toBe('success');
|
|
109
|
+
expect(upload.getFileState('key-1')?.metadata.documentId).toBeUndefined();
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -1054,6 +1054,30 @@ export function useFileUpload(
|
|
|
1054
1054
|
updateEntry(key, { status: 'processing', progress: 0 });
|
|
1055
1055
|
}
|
|
1056
1056
|
|
|
1057
|
+
// Mark the involved files successful and stamp the `documentId` resolved
|
|
1058
|
+
// from the terminal event's `documents` array (mapping `file_id` ->
|
|
1059
|
+
// `document_id`) onto each matching entry, so consumers can reference the
|
|
1060
|
+
// produced document directly without a separate lookup.
|
|
1061
|
+
const completeInvolvedFiles = (
|
|
1062
|
+
documents: Array<{ document_id?: string; file_id?: string }> = [],
|
|
1063
|
+
) => {
|
|
1064
|
+
const documentIdByFileId = new Map(
|
|
1065
|
+
documents
|
|
1066
|
+
.filter((doc) => doc.file_id && doc.document_id)
|
|
1067
|
+
.map((doc) => [doc.file_id, doc.document_id] as const),
|
|
1068
|
+
);
|
|
1069
|
+
for (const key of involvedStateKeys) {
|
|
1070
|
+
updateEntry(key, { status: 'success', progress: 100 });
|
|
1071
|
+
const remoteFileId = files.value.get(key)?.remoteFileId;
|
|
1072
|
+
const documentId = remoteFileId
|
|
1073
|
+
? documentIdByFileId.get(remoteFileId)
|
|
1074
|
+
: undefined;
|
|
1075
|
+
if (documentId) {
|
|
1076
|
+
updateFileMetadata(key, { documentId });
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
};
|
|
1080
|
+
|
|
1057
1081
|
const runResponse = await client.post<{ id: string }>(
|
|
1058
1082
|
endpoints.workflowRun(storeId, workflowId),
|
|
1059
1083
|
{ input },
|
|
@@ -1087,7 +1111,11 @@ export function useFileUpload(
|
|
|
1087
1111
|
sseStream.subscribe((event: SseEvent) => {
|
|
1088
1112
|
if (!workflowRun.value) return;
|
|
1089
1113
|
|
|
1090
|
-
let data: {
|
|
1114
|
+
let data: {
|
|
1115
|
+
id?: string;
|
|
1116
|
+
status?: string;
|
|
1117
|
+
documents?: Array<{ document_id?: string; file_id?: string }>;
|
|
1118
|
+
};
|
|
1091
1119
|
try {
|
|
1092
1120
|
data = JSON.parse(event.data);
|
|
1093
1121
|
} catch {
|
|
@@ -1105,9 +1133,7 @@ export function useFileUpload(
|
|
|
1105
1133
|
if (data.status === 'completed') {
|
|
1106
1134
|
workflowRun.value.status = 'completed';
|
|
1107
1135
|
workflowRun.value.completedAt = now();
|
|
1108
|
-
|
|
1109
|
-
updateEntry(key, { status: 'success', progress: 100 });
|
|
1110
|
-
}
|
|
1136
|
+
completeInvolvedFiles(Array.isArray(data.documents) ? data.documents : []);
|
|
1111
1137
|
emit({ type: 'workflow:completed', runId });
|
|
1112
1138
|
} else if (data.status === 'failed' || data.status === 'error') {
|
|
1113
1139
|
workflowRun.value.status = 'failed';
|