@byteplus-iga-pages/agent 0.0.0-stage → 1.0.4
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/LICENSE +20 -0
- package/README.md +84 -2
- package/dist/cjs/261.js +77 -0
- package/dist/cjs/341.js +43 -0
- package/dist/cjs/401.js +3632 -0
- package/dist/cjs/419.js +854 -0
- package/dist/cjs/504.js +760 -0
- package/dist/cjs/521.js +242 -0
- package/dist/cjs/594.js +79 -0
- package/dist/cjs/647.js +1367 -0
- package/dist/cjs/808.js +322 -0
- package/dist/cjs/82.js +10089 -0
- package/dist/cjs/893.js +17720 -0
- package/dist/cjs/893.js.LICENSE.txt +13 -0
- package/dist/cjs/951.js +59 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/runtime.js +79 -0
- package/dist/cjs/sandbox/host.js +125 -0
- package/dist/cjs/sandbox/index.js +286 -0
- package/dist/cjs/store/claude.js +209 -0
- package/dist/cjs/store/host.js +92 -0
- package/dist/cjs/store/index.js +43 -0
- package/dist/cjs/store/langgraph.js +581 -0
- package/dist/cjs/store/openai.js +118 -0
- package/dist/cjs/tools/claude.js +59 -0
- package/dist/cjs/tools/index.js +37 -0
- package/dist/cjs/tools/langchain.js +52 -0
- package/dist/cjs/tools/openai-agents.js +43 -0
- package/dist/cjs/tools/openai.js +43 -0
- package/dist/esm/128.js +10381 -0
- package/dist/esm/261.js +67 -0
- package/dist/esm/341.js +30 -0
- package/dist/esm/392.js +4453 -0
- package/dist/esm/417.js +704 -0
- package/dist/esm/521.js +230 -0
- package/dist/esm/594.js +67 -0
- package/dist/esm/613.js +19042 -0
- package/dist/esm/613.js.LICENSE.txt +13 -0
- package/dist/esm/951.js +44 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/runtime.js +39 -0
- package/dist/esm/sandbox/host.js +1 -0
- package/dist/esm/sandbox/index.js +183 -0
- package/dist/esm/store/claude.js +172 -0
- package/dist/esm/store/host.js +46 -0
- package/dist/esm/store/index.js +2 -0
- package/dist/esm/store/langgraph.js +542 -0
- package/dist/esm/store/openai.js +81 -0
- package/dist/esm/tools/claude.js +22 -0
- package/dist/esm/tools/index.js +1 -0
- package/dist/esm/tools/langchain.js +16 -0
- package/dist/esm/tools/openai-agents.js +6 -0
- package/dist/esm/tools/openai.js +6 -0
- package/dist/types/_internal/data-plane/control-plane-request.d.ts +12 -0
- package/dist/types/_internal/data-plane/control-plane.d.ts +3 -0
- package/dist/types/_internal/data-plane/credential-provider.d.ts +25 -0
- package/dist/types/_internal/data-plane/errors.d.ts +19 -0
- package/dist/types/_internal/data-plane/index.d.ts +11 -0
- package/dist/types/_internal/data-plane/supabase-client.d.ts +12 -0
- package/dist/types/_internal/data-plane/token-client.d.ts +23 -0
- package/dist/types/sandbox/api-client.d.ts +37 -0
- package/dist/types/sandbox/api-types.d.ts +81 -0
- package/dist/types/sandbox/binding-repository.d.ts +62 -0
- package/dist/types/sandbox/error.d.ts +22 -0
- package/dist/types/sandbox/expiry.d.ts +11 -0
- package/dist/types/sandbox/host.d.ts +6 -0
- package/dist/types/sandbox/iga-sandbox.d.ts +208 -0
- package/dist/types/sandbox/index.d.ts +8 -0
- package/dist/types/sandbox/public-surface.d.ts +19 -0
- package/dist/types/sandbox/runtime-sandbox.d.ts +32 -0
- package/dist/types/sandbox/types.d.ts +238 -0
- package/dist/types/store/append.d.ts +41 -0
- package/dist/types/store/claude-repository.d.ts +36 -0
- package/dist/types/store/claude.d.ts +3 -0
- package/dist/types/store/control-plane-request.d.ts +2 -0
- package/dist/types/store/credential-error.d.ts +2 -0
- package/dist/types/store/credential-provider.d.ts +29 -0
- package/dist/types/store/errors.d.ts +29 -0
- package/dist/types/store/factory.d.ts +31 -0
- package/dist/types/store/host.d.ts +5 -0
- package/dist/types/store/index.d.ts +6 -0
- package/dist/types/store/json.d.ts +7 -0
- package/dist/types/store/langgraph-repository.d.ts +98 -0
- package/dist/types/store/langgraph.d.ts +43 -0
- package/dist/types/store/openai.d.ts +12 -0
- package/dist/types/store/pagination.d.ts +27 -0
- package/dist/types/store/runtime-data-plane.d.ts +8 -0
- package/dist/types/store/runtime-provider.d.ts +1 -0
- package/dist/types/store/runtime-store.d.ts +20 -0
- package/dist/types/store/store.d.ts +240 -0
- package/dist/types/store/supabase-transport.d.ts +43 -0
- package/dist/types/store/token-client.d.ts +7 -0
- package/dist/types/tools/adapters.d.ts +5 -0
- package/dist/types/tools/claude.d.ts +4 -0
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/langchain.d.ts +16 -0
- package/dist/types/tools/model-output.d.ts +8 -0
- package/dist/types/tools/openai-agents.d.ts +4 -0
- package/dist/types/tools/openai.d.ts +5 -0
- package/dist/types/tools/registry.d.ts +16 -0
- package/dist/types/tools/result.d.ts +17 -0
- package/dist/types/tools/sandbox-result-mappers.d.ts +10 -0
- package/dist/types/tools/sandbox-tools.d.ts +17 -0
- package/dist/types/tools/types.d.ts +307 -0
- package/package.json +136 -4
package/dist/esm/417.js
ADDED
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
import { DataPlaneError, randomUUID, DataPlaneCredentialProvider, validateDataPlaneRootUrl, createAuthenticatedSupabaseClient, fetchDataPlaneCredentials } from "./128.js";
|
|
2
|
+
class StoreError extends Error {
|
|
3
|
+
toJSON() {
|
|
4
|
+
return {
|
|
5
|
+
code: this.code,
|
|
6
|
+
message: this.error?.message ?? this.message,
|
|
7
|
+
...void 0 !== this.status ? {
|
|
8
|
+
status: this.status
|
|
9
|
+
} : {},
|
|
10
|
+
...void 0 !== this.error ? {
|
|
11
|
+
error: this.error
|
|
12
|
+
} : {}
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
constructor(code, message, options = {}){
|
|
16
|
+
super(options.error?.message ?? message);
|
|
17
|
+
this.name = "StoreError";
|
|
18
|
+
this.code = code;
|
|
19
|
+
if (null !== options.error) this.error = options.error ?? {
|
|
20
|
+
message
|
|
21
|
+
};
|
|
22
|
+
if (Number.isInteger(options.status) && options.status >= 0 && options.status <= 599) this.status = options.status;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function storeCodeForStatus(status) {
|
|
26
|
+
const codes = {
|
|
27
|
+
0: "NetworkError",
|
|
28
|
+
400: "BadRequest",
|
|
29
|
+
401: "Unauthorized",
|
|
30
|
+
402: "PaymentRequired",
|
|
31
|
+
403: "Forbidden",
|
|
32
|
+
404: "NotFound",
|
|
33
|
+
405: "MethodNotAllowed",
|
|
34
|
+
406: "NotAcceptable",
|
|
35
|
+
408: "RequestTimeout",
|
|
36
|
+
409: "Conflict",
|
|
37
|
+
410: "Gone",
|
|
38
|
+
411: "LengthRequired",
|
|
39
|
+
412: "PreconditionFailed",
|
|
40
|
+
413: "PayloadTooLarge",
|
|
41
|
+
414: "URITooLong",
|
|
42
|
+
415: "UnsupportedMediaType",
|
|
43
|
+
416: "RangeNotSatisfiable",
|
|
44
|
+
417: "ExpectationFailed",
|
|
45
|
+
418: "ImATeapot",
|
|
46
|
+
422: "UnprocessableEntity",
|
|
47
|
+
423: "Locked",
|
|
48
|
+
424: "FailedDependency",
|
|
49
|
+
425: "TooEarly",
|
|
50
|
+
426: "UpgradeRequired",
|
|
51
|
+
428: "PreconditionRequired",
|
|
52
|
+
429: "TooManyRequests",
|
|
53
|
+
431: "RequestHeaderFieldsTooLarge",
|
|
54
|
+
451: "UnavailableForLegalReasons",
|
|
55
|
+
500: "InternalServerError",
|
|
56
|
+
501: "NotImplemented",
|
|
57
|
+
502: "BadGateway",
|
|
58
|
+
503: "ServiceUnavailable",
|
|
59
|
+
504: "GatewayTimeout",
|
|
60
|
+
505: "HTTPVersionNotSupported"
|
|
61
|
+
};
|
|
62
|
+
return codes[status] ?? "UnknownError";
|
|
63
|
+
}
|
|
64
|
+
function credential_error_toStoreCredentialError(error) {
|
|
65
|
+
if (error instanceof StoreError) return error;
|
|
66
|
+
const source = error instanceof DataPlaneError ? error : void 0;
|
|
67
|
+
const codes = {
|
|
68
|
+
authentication_failed: "Unauthorized",
|
|
69
|
+
timeout: "TimeoutError",
|
|
70
|
+
aborted: "AbortError",
|
|
71
|
+
rate_limited: "TooManyRequests",
|
|
72
|
+
unavailable: "ServiceUnavailable",
|
|
73
|
+
unknown: "UnknownError"
|
|
74
|
+
};
|
|
75
|
+
let type = "unavailable";
|
|
76
|
+
if (source) {
|
|
77
|
+
if ("authentication_failed" === source.failureKind || "unauthenticated" === source.code || "permission_denied" === source.code) type = "authentication_failed";
|
|
78
|
+
else if ("timeout" === source.failureKind) type = "timeout";
|
|
79
|
+
else if ("aborted" === source.code) type = "aborted";
|
|
80
|
+
else if ("rate_limited" === source.code) type = "rate_limited";
|
|
81
|
+
else if ("unavailable" !== source.code) type = "unknown";
|
|
82
|
+
}
|
|
83
|
+
const messages = {
|
|
84
|
+
authentication_failed: "Store authentication failed",
|
|
85
|
+
timeout: "Store authentication request timed out",
|
|
86
|
+
aborted: "Store request was cancelled",
|
|
87
|
+
rate_limited: "Store authentication is receiving too many requests",
|
|
88
|
+
unavailable: "Store authentication is temporarily unavailable",
|
|
89
|
+
unknown: "Store returned invalid credentials"
|
|
90
|
+
};
|
|
91
|
+
return new StoreError(codes[type], messages[type], {
|
|
92
|
+
status: source?.status,
|
|
93
|
+
error: null
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
function toDataPlaneError(error) {
|
|
97
|
+
if (error instanceof DataPlaneError) return error;
|
|
98
|
+
if (error instanceof StoreError) return new DataPlaneError("Unauthorized" === error.code ? "unauthenticated" : "TooManyRequests" === error.code ? "rate_limited" : "AbortError" === error.code ? "aborted" : "ServiceUnavailable" === error.code || "TimeoutError" === error.code ? "unavailable" : "internal", error.message, {
|
|
99
|
+
operation: "data-plane.authenticate",
|
|
100
|
+
status: error.status,
|
|
101
|
+
..."TimeoutError" === error.code ? {
|
|
102
|
+
failureKind: "timeout"
|
|
103
|
+
} : {}
|
|
104
|
+
});
|
|
105
|
+
return new DataPlaneError("unavailable", "Data plane authentication is temporarily unavailable", {
|
|
106
|
+
operation: "data-plane.authenticate",
|
|
107
|
+
retryable: true
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
class credential_provider_StoreCredentialProvider {
|
|
111
|
+
async getValidCredentials() {
|
|
112
|
+
try {
|
|
113
|
+
return await this.delegate.getValidCredentials();
|
|
114
|
+
} catch (error) {
|
|
115
|
+
throw credential_error_toStoreCredentialError(error);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async getProjectId() {
|
|
119
|
+
try {
|
|
120
|
+
return await this.delegate.getProjectId();
|
|
121
|
+
} catch (error) {
|
|
122
|
+
throw credential_error_toStoreCredentialError(error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
invalidate(jwt) {
|
|
126
|
+
this.delegate.invalidate(jwt);
|
|
127
|
+
}
|
|
128
|
+
constructor(options){
|
|
129
|
+
this.delegate = new DataPlaneCredentialProvider({
|
|
130
|
+
now: options.now,
|
|
131
|
+
fetchCredentials: async ()=>{
|
|
132
|
+
try {
|
|
133
|
+
return await options.fetchCredentials();
|
|
134
|
+
} catch (error) {
|
|
135
|
+
throw toDataPlaneError(error);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
class StoreCredentialProviderCache {
|
|
142
|
+
get(scope) {
|
|
143
|
+
if (!scope.environment || !scope.projectId) throw new StoreError("ServiceUnavailable", "Store credentials are unavailable");
|
|
144
|
+
let projects = this.providers.get(scope.environment);
|
|
145
|
+
if (!projects) {
|
|
146
|
+
projects = new Map();
|
|
147
|
+
this.providers.set(scope.environment, projects);
|
|
148
|
+
}
|
|
149
|
+
let provider = projects.get(scope.projectId);
|
|
150
|
+
if (!provider) {
|
|
151
|
+
provider = this.createProvider(Object.freeze({
|
|
152
|
+
...scope
|
|
153
|
+
}));
|
|
154
|
+
projects.set(scope.projectId, provider);
|
|
155
|
+
}
|
|
156
|
+
return provider;
|
|
157
|
+
}
|
|
158
|
+
clear(scope) {
|
|
159
|
+
if (!scope) return void this.providers.clear();
|
|
160
|
+
const projects = this.providers.get(scope.environment);
|
|
161
|
+
projects?.delete(scope.projectId);
|
|
162
|
+
if (projects?.size === 0) this.providers.delete(scope.environment);
|
|
163
|
+
}
|
|
164
|
+
constructor(options){
|
|
165
|
+
this.providers = new Map();
|
|
166
|
+
this.createProvider = options.createProvider;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function invalidJson(field) {
|
|
170
|
+
return new StoreError("BadRequest", `${field} must contain only JSON-compatible values`);
|
|
171
|
+
}
|
|
172
|
+
function cloneJsonValueInternal(value, field, ancestors) {
|
|
173
|
+
if (null === value || "string" == typeof value || "boolean" == typeof value) return value;
|
|
174
|
+
if ("number" == typeof value) {
|
|
175
|
+
if (!Number.isFinite(value)) throw invalidJson(field);
|
|
176
|
+
return value;
|
|
177
|
+
}
|
|
178
|
+
if (Array.isArray(value)) {
|
|
179
|
+
if (ancestors.has(value)) throw invalidJson(field);
|
|
180
|
+
ancestors.add(value);
|
|
181
|
+
const cloned = [];
|
|
182
|
+
for(let index = 0; index < value.length; index += 1){
|
|
183
|
+
if (!(index in value)) throw invalidJson(field);
|
|
184
|
+
cloned.push(cloneJsonValueInternal(value[index], field, ancestors));
|
|
185
|
+
}
|
|
186
|
+
ancestors.delete(value);
|
|
187
|
+
return cloned;
|
|
188
|
+
}
|
|
189
|
+
if ("object" == typeof value) {
|
|
190
|
+
const prototype = Object.getPrototypeOf(value);
|
|
191
|
+
if (prototype !== Object.prototype && null !== prototype) throw invalidJson(field);
|
|
192
|
+
if (ancestors.has(value)) throw invalidJson(field);
|
|
193
|
+
ancestors.add(value);
|
|
194
|
+
const cloned = {};
|
|
195
|
+
for (const [key, child] of Object.entries(value))Object.defineProperty(cloned, key, {
|
|
196
|
+
configurable: true,
|
|
197
|
+
enumerable: true,
|
|
198
|
+
writable: true,
|
|
199
|
+
value: cloneJsonValueInternal(child, field, ancestors)
|
|
200
|
+
});
|
|
201
|
+
ancestors.delete(value);
|
|
202
|
+
return cloned;
|
|
203
|
+
}
|
|
204
|
+
throw invalidJson(field);
|
|
205
|
+
}
|
|
206
|
+
function cloneJsonValue(value, field) {
|
|
207
|
+
return cloneJsonValueInternal(value, field, new WeakSet());
|
|
208
|
+
}
|
|
209
|
+
function cloneJsonObject(value, field) {
|
|
210
|
+
const cloned = cloneJsonValue(value, field);
|
|
211
|
+
if (null === cloned || Array.isArray(cloned) || "object" != typeof cloned) throw new StoreError("BadRequest", `${field} must be a JSON object`);
|
|
212
|
+
return cloned;
|
|
213
|
+
}
|
|
214
|
+
function materializeAppendMessages(messages, generateUuid = randomUUID) {
|
|
215
|
+
if (!Array.isArray(messages) || messages.length < 1 || messages.length > 100) throw new StoreError("BadRequest", "appendMessages requires between 1 and 100 messages");
|
|
216
|
+
const ids = new Set();
|
|
217
|
+
return messages.map((message, index)=>{
|
|
218
|
+
if (null === message || "object" != typeof message) throw new StoreError("BadRequest", `messages[${index}] must be an object`);
|
|
219
|
+
if (void 0 !== message.role && null !== message.role && "string" != typeof message.role) throw new StoreError("BadRequest", `messages[${index}].role must be a string or null`);
|
|
220
|
+
if (void 0 !== message.type && null !== message.type && "string" != typeof message.type) throw new StoreError("BadRequest", `messages[${index}].type must be a string or null`);
|
|
221
|
+
if (void 0 !== message.messageId && "string" != typeof message.messageId) throw new StoreError("BadRequest", `messages[${index}].messageId must be a string`);
|
|
222
|
+
const messageId = message.messageId ?? generateUuid();
|
|
223
|
+
if (ids.has(messageId)) throw new StoreError("BadRequest", "appendMessages contains duplicate messageId values");
|
|
224
|
+
ids.add(messageId);
|
|
225
|
+
return Object.freeze({
|
|
226
|
+
messageId,
|
|
227
|
+
role: message.role ?? null,
|
|
228
|
+
type: message.type ?? null,
|
|
229
|
+
payload: cloneJsonValue(message.payload, `messages[${index}].payload`),
|
|
230
|
+
metadata: void 0 === message.metadata ? {} : cloneJsonObject(message.metadata, `messages[${index}].metadata`)
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
const DEFAULT_STORE_PAGE_LIMIT = 50;
|
|
235
|
+
const MAX_STORE_PAGE_LIMIT = 100;
|
|
236
|
+
const TIMESTAMP_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
237
|
+
function validationError() {
|
|
238
|
+
return new StoreError("BadRequest", "Store cursor is invalid");
|
|
239
|
+
}
|
|
240
|
+
function encode(value) {
|
|
241
|
+
return Buffer.from(JSON.stringify(value)).toString("base64url");
|
|
242
|
+
}
|
|
243
|
+
function decode(value) {
|
|
244
|
+
try {
|
|
245
|
+
return JSON.parse(Buffer.from(value, "base64url").toString("utf8"));
|
|
246
|
+
} catch {
|
|
247
|
+
throw validationError();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
function isObject(value) {
|
|
251
|
+
return null !== value && "object" == typeof value && !Array.isArray(value);
|
|
252
|
+
}
|
|
253
|
+
function isTimestamp(value) {
|
|
254
|
+
return "string" == typeof value && TIMESTAMP_PATTERN.test(value) && Number.isFinite(Date.parse(value));
|
|
255
|
+
}
|
|
256
|
+
function isConversationId(value) {
|
|
257
|
+
return "string" == typeof value && value.length > 0 && Buffer.byteLength(value, "utf8") <= 256;
|
|
258
|
+
}
|
|
259
|
+
function isSequence(value) {
|
|
260
|
+
return "string" == typeof value && /^(0|[1-9]\d*)$/.test(value);
|
|
261
|
+
}
|
|
262
|
+
function normalizeStorePageLimit(limit) {
|
|
263
|
+
if (void 0 === limit) return DEFAULT_STORE_PAGE_LIMIT;
|
|
264
|
+
if (!Number.isInteger(limit) || limit < 1 || limit > MAX_STORE_PAGE_LIMIT) throw new StoreError("BadRequest", `Store page limit must be an integer from 1 to ${MAX_STORE_PAGE_LIMIT}`);
|
|
265
|
+
return limit;
|
|
266
|
+
}
|
|
267
|
+
function encodeConversationCursor(cursor) {
|
|
268
|
+
return encode({
|
|
269
|
+
version: 1,
|
|
270
|
+
kind: "conversations",
|
|
271
|
+
...cursor
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
function decodeConversationCursor(value) {
|
|
275
|
+
const cursor = decode(value);
|
|
276
|
+
if (!isObject(cursor) || 1 !== cursor.version || "conversations" !== cursor.kind || !isTimestamp(cursor.updatedAt) || !isConversationId(cursor.conversationId)) throw validationError();
|
|
277
|
+
return {
|
|
278
|
+
updatedAt: cursor.updatedAt,
|
|
279
|
+
conversationId: cursor.conversationId
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function encodeMessageCursor(cursor) {
|
|
283
|
+
return encode({
|
|
284
|
+
version: 1,
|
|
285
|
+
kind: "messages",
|
|
286
|
+
...cursor
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
function decodeMessageCursor(value, expected) {
|
|
290
|
+
const cursor = decode(value);
|
|
291
|
+
if (!isObject(cursor) || 1 !== cursor.version || "messages" !== cursor.kind || !isConversationId(cursor.conversationId) || cursor.conversationId !== expected.conversationId || cursor.order !== expected.order || !isSequence(cursor.snapshotSeq) || !isSequence(cursor.lastSeq)) throw validationError();
|
|
292
|
+
return {
|
|
293
|
+
conversationId: cursor.conversationId,
|
|
294
|
+
order: expected.order,
|
|
295
|
+
snapshotSeq: cursor.snapshotSeq,
|
|
296
|
+
lastSeq: cursor.lastSeq
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
const SEQUENCE_PATTERN = /^(0|[1-9]\d*)$/;
|
|
300
|
+
const CONVERSATION_COLUMNS = "conversation_id,metadata,created_at,updated_at";
|
|
301
|
+
const MESSAGE_COLUMNS = "event_id,conversation_id,seq_text,role,event_type,payload,metadata,created_at,updated_at";
|
|
302
|
+
const DEFAULT_STORE_RPC_NAMES = Object.freeze({
|
|
303
|
+
appendMessages: "append_messages",
|
|
304
|
+
updateConversation: "update_conversation",
|
|
305
|
+
deleteConversation: "delete_conversation",
|
|
306
|
+
deleteMessage: "delete_event",
|
|
307
|
+
clearMessages: "clear_messages"
|
|
308
|
+
});
|
|
309
|
+
function invalid(message) {
|
|
310
|
+
throw new StoreError("BadRequest", message);
|
|
311
|
+
}
|
|
312
|
+
function internal() {
|
|
313
|
+
throw new StoreError("UnknownError", "Store returned invalid data");
|
|
314
|
+
}
|
|
315
|
+
function requireObject(value, field) {
|
|
316
|
+
if (null === value || "object" != typeof value || Array.isArray(value)) invalid(`${field} must be an object`);
|
|
317
|
+
return value;
|
|
318
|
+
}
|
|
319
|
+
function requireConversationId(value) {
|
|
320
|
+
if ("string" != typeof value || 0 === value.length) invalid("conversationId must be a non-empty string");
|
|
321
|
+
if (Buffer.byteLength(value, "utf8") > 256) invalid("conversationId must not exceed 256 UTF-8 bytes");
|
|
322
|
+
return value;
|
|
323
|
+
}
|
|
324
|
+
function requireMessageId(value) {
|
|
325
|
+
if ("string" != typeof value || "" === value) invalid("messageId must be a non-empty string");
|
|
326
|
+
return value;
|
|
327
|
+
}
|
|
328
|
+
function requireTimestamp(value) {
|
|
329
|
+
if ("string" != typeof value || "" === value || !Number.isFinite(Date.parse(value))) internal();
|
|
330
|
+
return value;
|
|
331
|
+
}
|
|
332
|
+
function requireNextSequence(value) {
|
|
333
|
+
if ("string" == typeof value && SEQUENCE_PATTERN.test(value)) return value;
|
|
334
|
+
if ("number" == typeof value && Number.isSafeInteger(value) && value >= 0) return String(value);
|
|
335
|
+
internal();
|
|
336
|
+
}
|
|
337
|
+
function mapConversation(value) {
|
|
338
|
+
const row = requireStoreRow(value);
|
|
339
|
+
if ("string" != typeof row.conversation_id) internal();
|
|
340
|
+
return {
|
|
341
|
+
conversationId: row.conversation_id,
|
|
342
|
+
metadata: readStoreJsonObject(row.metadata),
|
|
343
|
+
createdAt: requireTimestamp(row.created_at),
|
|
344
|
+
updatedAt: requireTimestamp(row.updated_at)
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
function mapMessage(value) {
|
|
348
|
+
const row = requireStoreRow(value);
|
|
349
|
+
if ("string" != typeof row.event_id || "string" != typeof row.conversation_id || "string" != typeof row.seq_text || !SEQUENCE_PATTERN.test(row.seq_text) || null !== row.role && "string" != typeof row.role || null !== row.event_type && "string" != typeof row.event_type) internal();
|
|
350
|
+
return {
|
|
351
|
+
messageId: row.event_id,
|
|
352
|
+
conversationId: row.conversation_id,
|
|
353
|
+
seq: row.seq_text,
|
|
354
|
+
role: row.role,
|
|
355
|
+
type: row.event_type,
|
|
356
|
+
payload: readStoreJsonValue(row.payload),
|
|
357
|
+
metadata: readStoreJsonObject(row.metadata),
|
|
358
|
+
createdAt: requireTimestamp(row.created_at),
|
|
359
|
+
updatedAt: requireTimestamp(row.updated_at)
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
function requireStoreRow(value) {
|
|
363
|
+
if (null === value || "object" != typeof value || Array.isArray(value)) internal();
|
|
364
|
+
return value;
|
|
365
|
+
}
|
|
366
|
+
function readStoreJsonValue(value) {
|
|
367
|
+
try {
|
|
368
|
+
return cloneJsonValue(value, "Store data");
|
|
369
|
+
} catch {
|
|
370
|
+
internal();
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
function readStoreJsonObject(value) {
|
|
374
|
+
try {
|
|
375
|
+
return cloneJsonObject(value, "Store data");
|
|
376
|
+
} catch {
|
|
377
|
+
internal();
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
function requireRows(value) {
|
|
381
|
+
if (!Array.isArray(value)) internal();
|
|
382
|
+
return value;
|
|
383
|
+
}
|
|
384
|
+
class SupabaseStore {
|
|
385
|
+
async createConversation(input = {}) {
|
|
386
|
+
const value = requireObject(input, "createConversation input");
|
|
387
|
+
const conversationId = void 0 === value.conversationId ? requireConversationId(this.generateUuid()) : requireConversationId(value.conversationId);
|
|
388
|
+
const metadata = void 0 === value.metadata ? {} : cloneJsonObject(value.metadata, "metadata");
|
|
389
|
+
const data = await this.execute((client)=>client.from("conversations").insert({
|
|
390
|
+
project_id: this.projectId,
|
|
391
|
+
conversation_id: conversationId,
|
|
392
|
+
metadata
|
|
393
|
+
}).select(CONVERSATION_COLUMNS).single(), {
|
|
394
|
+
operation: "store.createConversation",
|
|
395
|
+
retryNetwork: false
|
|
396
|
+
});
|
|
397
|
+
return mapConversation(data);
|
|
398
|
+
}
|
|
399
|
+
async getConversation(input) {
|
|
400
|
+
const value = requireObject(input, "getConversation input");
|
|
401
|
+
const conversationId = requireConversationId(value.conversationId);
|
|
402
|
+
const data = await this.execute((client)=>client.from("conversations").select(CONVERSATION_COLUMNS).eq("project_id", this.projectId).eq("conversation_id", conversationId).maybeSingle(), {
|
|
403
|
+
operation: "store.getConversation",
|
|
404
|
+
retryNetwork: true
|
|
405
|
+
});
|
|
406
|
+
return null === data ? null : mapConversation(data);
|
|
407
|
+
}
|
|
408
|
+
async listConversations(input = {}) {
|
|
409
|
+
const value = requireObject(input, "listConversations input");
|
|
410
|
+
const limit = normalizeStorePageLimit(value.limit);
|
|
411
|
+
const cursor = void 0 === value.cursor ? void 0 : "string" == typeof value.cursor ? decodeConversationCursor(value.cursor) : invalid("cursor must be a string");
|
|
412
|
+
const data = await this.execute((client)=>{
|
|
413
|
+
let query = client.from("conversations").select(CONVERSATION_COLUMNS).eq("project_id", this.projectId).order("updated_at", {
|
|
414
|
+
ascending: false
|
|
415
|
+
}).order("conversation_id", {
|
|
416
|
+
ascending: false
|
|
417
|
+
}).limit(limit + 1);
|
|
418
|
+
if (cursor) {
|
|
419
|
+
const quotedId = `"${cursor.conversationId.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
420
|
+
query = query.or(`updated_at.lt.${cursor.updatedAt},and(updated_at.eq.${cursor.updatedAt},conversation_id.lt.${quotedId})`);
|
|
421
|
+
}
|
|
422
|
+
return query;
|
|
423
|
+
}, {
|
|
424
|
+
operation: "store.listConversations",
|
|
425
|
+
retryNetwork: true
|
|
426
|
+
});
|
|
427
|
+
const rows = requireRows(data);
|
|
428
|
+
const hasMore = rows.length > limit;
|
|
429
|
+
const items = rows.slice(0, limit).map(mapConversation);
|
|
430
|
+
const last = items.at(-1);
|
|
431
|
+
return {
|
|
432
|
+
items,
|
|
433
|
+
nextCursor: hasMore && last ? encodeConversationCursor({
|
|
434
|
+
updatedAt: last.updatedAt,
|
|
435
|
+
conversationId: last.conversationId
|
|
436
|
+
}) : null
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
async updateConversation(input) {
|
|
440
|
+
const value = requireObject(input, "updateConversation input");
|
|
441
|
+
const conversationId = requireConversationId(value.conversationId);
|
|
442
|
+
if (!("metadata" in value)) invalid("metadata is required");
|
|
443
|
+
const metadata = cloneJsonObject(value.metadata, "metadata");
|
|
444
|
+
const removalKeys = [];
|
|
445
|
+
for (const [key, item] of Object.entries(metadata))if (null === item) {
|
|
446
|
+
removalKeys.push(key);
|
|
447
|
+
delete metadata[key];
|
|
448
|
+
}
|
|
449
|
+
const data = await this.execute((client)=>client.rpc(this.rpcNames.updateConversation, {
|
|
450
|
+
p_project_id: this.projectId,
|
|
451
|
+
p_conversation_id: conversationId,
|
|
452
|
+
p_metadata: metadata,
|
|
453
|
+
p_remove_metadata_keys: removalKeys
|
|
454
|
+
}).maybeSingle(), {
|
|
455
|
+
operation: "store.updateConversation",
|
|
456
|
+
retryNetwork: false
|
|
457
|
+
});
|
|
458
|
+
if (null === data) throw new StoreError("NotFound", "Conversation was not found");
|
|
459
|
+
return mapConversation(data);
|
|
460
|
+
}
|
|
461
|
+
async deleteConversation(input) {
|
|
462
|
+
const value = requireObject(input, "deleteConversation input");
|
|
463
|
+
const conversationId = requireConversationId(value.conversationId);
|
|
464
|
+
await this.execute((client)=>client.rpc(this.rpcNames.deleteConversation, {
|
|
465
|
+
p_project_id: this.projectId,
|
|
466
|
+
p_conversation_id: conversationId
|
|
467
|
+
}), {
|
|
468
|
+
operation: "store.deleteConversation",
|
|
469
|
+
retryNetwork: true
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
async appendMessage(input) {
|
|
473
|
+
const value = requireObject(input, "appendMessage input");
|
|
474
|
+
const { conversationId, ...message } = value;
|
|
475
|
+
const [result] = await this.appendMessages({
|
|
476
|
+
conversationId: conversationId,
|
|
477
|
+
messages: [
|
|
478
|
+
message
|
|
479
|
+
]
|
|
480
|
+
});
|
|
481
|
+
return result;
|
|
482
|
+
}
|
|
483
|
+
async appendMessages(input) {
|
|
484
|
+
const value = requireObject(input, "appendMessages input");
|
|
485
|
+
const conversationId = requireConversationId(value.conversationId);
|
|
486
|
+
const materialized = materializeAppendMessages(value.messages, this.generateUuid);
|
|
487
|
+
const rpcMessages = materialized.map((message)=>({
|
|
488
|
+
message_id: message.messageId,
|
|
489
|
+
role: message.role,
|
|
490
|
+
event_type: message.type,
|
|
491
|
+
payload: message.payload,
|
|
492
|
+
metadata: message.metadata
|
|
493
|
+
}));
|
|
494
|
+
const data = await this.execute((client)=>client.rpc(this.rpcNames.appendMessages, {
|
|
495
|
+
p_project_id: this.projectId,
|
|
496
|
+
p_conversation_id: conversationId,
|
|
497
|
+
p_messages: rpcMessages
|
|
498
|
+
}), {
|
|
499
|
+
operation: "store.appendMessages",
|
|
500
|
+
retryNetwork: true
|
|
501
|
+
});
|
|
502
|
+
const byId = new Map(requireRows(data).map((row)=>{
|
|
503
|
+
const message = mapMessage(row);
|
|
504
|
+
return [
|
|
505
|
+
message.messageId,
|
|
506
|
+
message
|
|
507
|
+
];
|
|
508
|
+
}));
|
|
509
|
+
if (byId.size !== materialized.length) internal();
|
|
510
|
+
return materialized.map((inputMessage)=>{
|
|
511
|
+
const message = byId.get(inputMessage.messageId);
|
|
512
|
+
if (!message || message.conversationId !== conversationId) internal();
|
|
513
|
+
return message;
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
async getMessage(input) {
|
|
517
|
+
const value = requireObject(input, "getMessage input");
|
|
518
|
+
const messageId = requireMessageId(value.messageId);
|
|
519
|
+
const data = await this.execute((client)=>client.from("events").select(MESSAGE_COLUMNS).eq("project_id", this.projectId).eq("event_id", messageId).maybeSingle(), {
|
|
520
|
+
operation: "store.getMessage",
|
|
521
|
+
retryNetwork: true
|
|
522
|
+
});
|
|
523
|
+
return null === data ? null : mapMessage(data);
|
|
524
|
+
}
|
|
525
|
+
async listMessages(input) {
|
|
526
|
+
const value = requireObject(input, "listMessages input");
|
|
527
|
+
const conversationId = requireConversationId(value.conversationId);
|
|
528
|
+
const limit = normalizeStorePageLimit(value.limit);
|
|
529
|
+
const order = value.order ?? "asc";
|
|
530
|
+
if ("asc" !== order && "desc" !== order) invalid('order must be "asc" or "desc"');
|
|
531
|
+
const cursor = void 0 === value.cursor ? void 0 : "string" == typeof value.cursor ? decodeMessageCursor(value.cursor, {
|
|
532
|
+
conversationId,
|
|
533
|
+
order
|
|
534
|
+
}) : invalid("cursor must be a string");
|
|
535
|
+
const snapshotSeq = cursor?.snapshotSeq ?? await this.readSnapshotSeq(conversationId);
|
|
536
|
+
if (null === snapshotSeq) return {
|
|
537
|
+
items: [],
|
|
538
|
+
nextCursor: null
|
|
539
|
+
};
|
|
540
|
+
const data = await this.execute((client)=>{
|
|
541
|
+
let query = client.from("events").select(MESSAGE_COLUMNS).eq("project_id", this.projectId).eq("conversation_id", conversationId).lte("seq", snapshotSeq).order("seq", {
|
|
542
|
+
ascending: "asc" === order
|
|
543
|
+
}).limit(limit + 1);
|
|
544
|
+
if (cursor) query = "asc" === order ? query.gt("seq", cursor.lastSeq) : query.lt("seq", cursor.lastSeq);
|
|
545
|
+
return query;
|
|
546
|
+
}, {
|
|
547
|
+
operation: "store.listMessages",
|
|
548
|
+
retryNetwork: true
|
|
549
|
+
});
|
|
550
|
+
const rows = requireRows(data);
|
|
551
|
+
const hasMore = rows.length > limit;
|
|
552
|
+
const items = rows.slice(0, limit).map(mapMessage);
|
|
553
|
+
const last = items.at(-1);
|
|
554
|
+
return {
|
|
555
|
+
items,
|
|
556
|
+
nextCursor: hasMore && last ? encodeMessageCursor({
|
|
557
|
+
conversationId,
|
|
558
|
+
order,
|
|
559
|
+
snapshotSeq,
|
|
560
|
+
lastSeq: last.seq
|
|
561
|
+
}) : null
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
async updateMessage(input) {
|
|
565
|
+
const value = requireObject(input, "updateMessage input");
|
|
566
|
+
const messageId = requireMessageId(value.messageId);
|
|
567
|
+
const update = {};
|
|
568
|
+
if ("role" in value) {
|
|
569
|
+
if (null !== value.role && "string" != typeof value.role) invalid("role must be a string or null");
|
|
570
|
+
update.role = value.role;
|
|
571
|
+
}
|
|
572
|
+
if ("type" in value) {
|
|
573
|
+
if (null !== value.type && "string" != typeof value.type) invalid("type must be a string or null");
|
|
574
|
+
update.event_type = value.type;
|
|
575
|
+
}
|
|
576
|
+
if ("payload" in value) update.payload = cloneJsonValue(value.payload, "payload");
|
|
577
|
+
if ("metadata" in value) update.metadata = cloneJsonObject(value.metadata, "metadata");
|
|
578
|
+
if (0 === Object.keys(update).length) invalid("updateMessage requires at least one mutable field");
|
|
579
|
+
const data = await this.execute((client)=>client.from("events").update(update).eq("project_id", this.projectId).eq("event_id", messageId).select(MESSAGE_COLUMNS).maybeSingle(), {
|
|
580
|
+
operation: "store.updateMessage",
|
|
581
|
+
retryNetwork: false
|
|
582
|
+
});
|
|
583
|
+
if (null === data) throw new StoreError("NotFound", "Message was not found");
|
|
584
|
+
return mapMessage(data);
|
|
585
|
+
}
|
|
586
|
+
async deleteMessage(input) {
|
|
587
|
+
const value = requireObject(input, "deleteMessage input");
|
|
588
|
+
const messageId = requireMessageId(value.messageId);
|
|
589
|
+
await this.execute((client)=>client.rpc(this.rpcNames.deleteMessage, {
|
|
590
|
+
p_project_id: this.projectId,
|
|
591
|
+
p_event_id: messageId
|
|
592
|
+
}), {
|
|
593
|
+
operation: "store.deleteMessage",
|
|
594
|
+
retryNetwork: true
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
async clearMessages(input) {
|
|
598
|
+
const value = requireObject(input, "clearMessages input");
|
|
599
|
+
const conversationId = requireConversationId(value.conversationId);
|
|
600
|
+
await this.execute((client)=>client.rpc(this.rpcNames.clearMessages, {
|
|
601
|
+
p_project_id: this.projectId,
|
|
602
|
+
p_conversation_id: conversationId
|
|
603
|
+
}), {
|
|
604
|
+
operation: "store.clearMessages",
|
|
605
|
+
retryNetwork: true
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
async readSnapshotSeq(conversationId) {
|
|
609
|
+
const data = await this.execute((client)=>client.from("conversations").select("next_seq").eq("project_id", this.projectId).eq("conversation_id", conversationId).maybeSingle(), {
|
|
610
|
+
operation: "store.listMessages",
|
|
611
|
+
retryNetwork: true
|
|
612
|
+
});
|
|
613
|
+
if (null === data) return null;
|
|
614
|
+
const row = requireStoreRow(data);
|
|
615
|
+
const next = BigInt(requireNextSequence(row.next_seq));
|
|
616
|
+
return next > 0n ? String(next - 1n) : "0";
|
|
617
|
+
}
|
|
618
|
+
async execute(operation, options) {
|
|
619
|
+
const result = await this.transport.execute({
|
|
620
|
+
operationName: options.operation,
|
|
621
|
+
retryOnUnauthorized: true,
|
|
622
|
+
retryOnNetworkError: options.retryNetwork,
|
|
623
|
+
operation
|
|
624
|
+
});
|
|
625
|
+
return result.data;
|
|
626
|
+
}
|
|
627
|
+
constructor(options){
|
|
628
|
+
if (!options.projectId) throw new StoreError("UnknownError", "Store project scope is missing");
|
|
629
|
+
this.projectId = options.projectId;
|
|
630
|
+
this.transport = options.transport;
|
|
631
|
+
this.generateUuid = options.generateUuid ?? randomUUID;
|
|
632
|
+
this.rpcNames = {
|
|
633
|
+
...DEFAULT_STORE_RPC_NAMES,
|
|
634
|
+
...options.rpcNames
|
|
635
|
+
};
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
function createStore(options) {
|
|
639
|
+
return new SupabaseStore(options);
|
|
640
|
+
}
|
|
641
|
+
function throwForStatus(status, error) {
|
|
642
|
+
throw new StoreError(storeCodeForStatus(status), error?.message ?? "Store request failed", {
|
|
643
|
+
status,
|
|
644
|
+
...error ? {
|
|
645
|
+
error
|
|
646
|
+
} : {}
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
class SupabaseStoreTransport {
|
|
650
|
+
async execute(options) {
|
|
651
|
+
const attempts = options.retryOnUnauthorized || options.retryOnNetworkError ? 2 : 1;
|
|
652
|
+
for(let attempt = 0; attempt < attempts; attempt += 1){
|
|
653
|
+
const credentials = await this.credentialProvider.getValidCredentials();
|
|
654
|
+
const client = createAuthenticatedSupabaseClient({
|
|
655
|
+
credentials,
|
|
656
|
+
fetch: this.fetch,
|
|
657
|
+
createClient: this.createClient,
|
|
658
|
+
realtimeError: ()=>new StoreError("UnknownError", "Store does not support Supabase Realtime")
|
|
659
|
+
});
|
|
660
|
+
let result;
|
|
661
|
+
try {
|
|
662
|
+
result = await options.operation(client);
|
|
663
|
+
} catch (error) {
|
|
664
|
+
if (error instanceof StoreError) throw error;
|
|
665
|
+
const name = error?.name;
|
|
666
|
+
if ("AbortError" === name) throw new StoreError("AbortError", "Store request was cancelled");
|
|
667
|
+
if (options.retryOnNetworkError && attempt + 1 < attempts) continue;
|
|
668
|
+
throw new StoreError("TimeoutError" === name ? "TimeoutError" : "NetworkError", error instanceof Error ? error.message : "Store request failed");
|
|
669
|
+
}
|
|
670
|
+
if (0 !== result.status || !options.retryOnNetworkError || !(attempt + 1 < attempts)) {
|
|
671
|
+
if (401 === result.status && attempt + 1 < attempts) {
|
|
672
|
+
this.credentialProvider.invalidate(credentials.jwt);
|
|
673
|
+
continue;
|
|
674
|
+
}
|
|
675
|
+
if (!result.success || result.status < 200 || result.status >= 300) throwForStatus(result.status, result.error);
|
|
676
|
+
return {
|
|
677
|
+
data: result.data,
|
|
678
|
+
count: result.count ?? null
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
throw new StoreError("Unauthorized", "Store authorization failed");
|
|
683
|
+
}
|
|
684
|
+
constructor(options){
|
|
685
|
+
this.credentialProvider = options.credentialProvider;
|
|
686
|
+
this.fetch = options.fetch ?? globalThis.fetch;
|
|
687
|
+
this.createClient = options.createClient;
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
function validateStoreRootUrl(value, isAllowedHostname) {
|
|
691
|
+
try {
|
|
692
|
+
return validateDataPlaneRootUrl(value, isAllowedHostname);
|
|
693
|
+
} catch (error) {
|
|
694
|
+
throw credential_error_toStoreCredentialError(error);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
async function fetchStoreCredentials(options) {
|
|
698
|
+
try {
|
|
699
|
+
return await fetchDataPlaneCredentials(options);
|
|
700
|
+
} catch (error) {
|
|
701
|
+
throw credential_error_toStoreCredentialError(error);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
export { StoreCredentialProviderCache, StoreError, SupabaseStoreTransport, cloneJsonObject, createStore, credential_provider_StoreCredentialProvider, fetchStoreCredentials, validateStoreRootUrl };
|