deepspace 0.2.8 → 0.3.2
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/cli.js +473 -5
- package/dist/cli.js.map +1 -1
- package/dist/worker.d.ts +446 -1
- package/dist/worker.js +438 -0
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
package/dist/worker.js
CHANGED
|
@@ -4129,6 +4129,346 @@ var DEFAULT_DO_MANIFEST = [
|
|
|
4129
4129
|
{ binding: "RECORD_ROOMS", className: "AppRecordRoom", sqlite: true },
|
|
4130
4130
|
{ binding: "YJS_ROOMS", className: "AppYjsRoom", sqlite: true }
|
|
4131
4131
|
];
|
|
4132
|
+
function validateDoManifest(manifest) {
|
|
4133
|
+
if (!Array.isArray(manifest)) {
|
|
4134
|
+
return { valid: false, reason: "doManifest must be an array" };
|
|
4135
|
+
}
|
|
4136
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4137
|
+
for (const entry of manifest) {
|
|
4138
|
+
if (!entry || typeof entry !== "object") {
|
|
4139
|
+
return { valid: false, reason: `doManifest entry must be an object (got ${entry === null ? "null" : typeof entry})` };
|
|
4140
|
+
}
|
|
4141
|
+
const e = entry;
|
|
4142
|
+
if (typeof e.binding !== "string" || !e.binding) {
|
|
4143
|
+
return { valid: false, reason: `doManifest entry missing 'binding' (string)` };
|
|
4144
|
+
}
|
|
4145
|
+
if (typeof e.className !== "string" || !e.className) {
|
|
4146
|
+
return { valid: false, reason: `doManifest entry "${e.binding}" missing 'className' (string)` };
|
|
4147
|
+
}
|
|
4148
|
+
if (typeof e.sqlite !== "boolean") {
|
|
4149
|
+
return { valid: false, reason: `doManifest entry "${e.binding}" 'sqlite' must be a boolean` };
|
|
4150
|
+
}
|
|
4151
|
+
if (seen.has(e.binding)) {
|
|
4152
|
+
return { valid: false, reason: `doManifest has duplicate binding "${e.binding}"` };
|
|
4153
|
+
}
|
|
4154
|
+
seen.add(e.binding);
|
|
4155
|
+
}
|
|
4156
|
+
return { valid: true, manifest };
|
|
4157
|
+
}
|
|
4158
|
+
|
|
4159
|
+
// src/server/rooms/binding-manifest.ts
|
|
4160
|
+
var AUTO_PROVISION_SENTINEL = "auto";
|
|
4161
|
+
var AUTO_PROVISIONABLE_TYPES = /* @__PURE__ */ new Set([
|
|
4162
|
+
"d1",
|
|
4163
|
+
"kv_namespace",
|
|
4164
|
+
"vectorize",
|
|
4165
|
+
"r2_bucket",
|
|
4166
|
+
"queue"
|
|
4167
|
+
]);
|
|
4168
|
+
var VECTORIZE_METRICS = /* @__PURE__ */ new Set(["cosine", "euclidean", "dot-product"]);
|
|
4169
|
+
function isAutoProvision(b) {
|
|
4170
|
+
switch (b.type) {
|
|
4171
|
+
case "d1":
|
|
4172
|
+
return b.id === AUTO_PROVISION_SENTINEL;
|
|
4173
|
+
case "kv_namespace":
|
|
4174
|
+
return b.namespace_id === AUTO_PROVISION_SENTINEL;
|
|
4175
|
+
case "vectorize":
|
|
4176
|
+
return b.index_name === AUTO_PROVISION_SENTINEL;
|
|
4177
|
+
case "r2_bucket":
|
|
4178
|
+
return b.bucket_name === AUTO_PROVISION_SENTINEL;
|
|
4179
|
+
case "queue":
|
|
4180
|
+
return b.queue_name === AUTO_PROVISION_SENTINEL;
|
|
4181
|
+
default:
|
|
4182
|
+
return false;
|
|
4183
|
+
}
|
|
4184
|
+
}
|
|
4185
|
+
var ALLOWED_BINDING_TYPES = /* @__PURE__ */ new Set([
|
|
4186
|
+
"vectorize",
|
|
4187
|
+
"ai",
|
|
4188
|
+
"r2_bucket",
|
|
4189
|
+
"kv_namespace",
|
|
4190
|
+
"d1",
|
|
4191
|
+
"queue",
|
|
4192
|
+
"browser_rendering",
|
|
4193
|
+
"analytics_engine",
|
|
4194
|
+
"hyperdrive"
|
|
4195
|
+
]);
|
|
4196
|
+
var RESERVED_BINDING_NAMES = /* @__PURE__ */ new Set([
|
|
4197
|
+
"ASSETS",
|
|
4198
|
+
"PLATFORM_WORKER",
|
|
4199
|
+
"API_WORKER",
|
|
4200
|
+
"APP_NAME",
|
|
4201
|
+
"OWNER_USER_ID",
|
|
4202
|
+
"AUTH_JWT_PUBLIC_KEY",
|
|
4203
|
+
"AUTH_JWT_ISSUER",
|
|
4204
|
+
"AUTH_WORKER_URL",
|
|
4205
|
+
"APP_IDENTITY_TOKEN",
|
|
4206
|
+
"APP_OWNER_JWT",
|
|
4207
|
+
"INTERNAL_STORAGE_HMAC_SECRET",
|
|
4208
|
+
"USAGE_EVENTS"
|
|
4209
|
+
]);
|
|
4210
|
+
function validateBindingManifest(manifest) {
|
|
4211
|
+
if (!Array.isArray(manifest)) {
|
|
4212
|
+
return { valid: false, errors: [{ reason: "Manifest must be an array" }] };
|
|
4213
|
+
}
|
|
4214
|
+
const errors = [];
|
|
4215
|
+
const seenNames = /* @__PURE__ */ new Set();
|
|
4216
|
+
for (const entry of manifest) {
|
|
4217
|
+
if (!entry || typeof entry !== "object") {
|
|
4218
|
+
errors.push({ reason: `Entry must be an object (got ${entry === null ? "null" : typeof entry})` });
|
|
4219
|
+
continue;
|
|
4220
|
+
}
|
|
4221
|
+
const e = entry;
|
|
4222
|
+
const type = e.type;
|
|
4223
|
+
const name = e.name;
|
|
4224
|
+
if (typeof type !== "string" || !ALLOWED_BINDING_TYPES.has(type)) {
|
|
4225
|
+
errors.push({
|
|
4226
|
+
reason: `Disallowed binding type: ${typeof type === "string" ? type : `(${typeof type})`}. Allowed: ${[...ALLOWED_BINDING_TYPES].sort().join(", ")}`
|
|
4227
|
+
});
|
|
4228
|
+
continue;
|
|
4229
|
+
}
|
|
4230
|
+
if (typeof name !== "string" || !name) {
|
|
4231
|
+
errors.push({ reason: `Binding of type "${type}" missing 'name' (string)` });
|
|
4232
|
+
continue;
|
|
4233
|
+
}
|
|
4234
|
+
if (RESERVED_BINDING_NAMES.has(name)) {
|
|
4235
|
+
errors.push({ reason: `Binding name "${name}" is reserved by the SDK` });
|
|
4236
|
+
continue;
|
|
4237
|
+
}
|
|
4238
|
+
if (seenNames.has(name)) {
|
|
4239
|
+
errors.push({ reason: `Duplicate binding name "${name}"` });
|
|
4240
|
+
continue;
|
|
4241
|
+
}
|
|
4242
|
+
seenNames.add(name);
|
|
4243
|
+
const binding = entry;
|
|
4244
|
+
const fieldErr = requiredFieldError(binding);
|
|
4245
|
+
if (fieldErr) errors.push({ binding, reason: fieldErr });
|
|
4246
|
+
}
|
|
4247
|
+
if (errors.length) return { valid: false, errors };
|
|
4248
|
+
return { valid: true, bindings: manifest };
|
|
4249
|
+
}
|
|
4250
|
+
function requiredFieldError(b) {
|
|
4251
|
+
switch (b.type) {
|
|
4252
|
+
case "vectorize": {
|
|
4253
|
+
if (!b.index_name) return `vectorize binding "${b.name}" missing index_name (or "auto")`;
|
|
4254
|
+
if (b.index_name === AUTO_PROVISION_SENTINEL) {
|
|
4255
|
+
if (typeof b.dimensions !== "number" || b.dimensions <= 0) {
|
|
4256
|
+
return `vectorize binding "${b.name}" with index_name="auto" requires "dimensions" (positive number)`;
|
|
4257
|
+
}
|
|
4258
|
+
if (!b.metric || !VECTORIZE_METRICS.has(b.metric)) {
|
|
4259
|
+
return `vectorize binding "${b.name}" with index_name="auto" requires "metric" (one of: ${[...VECTORIZE_METRICS].join(", ")})`;
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
return null;
|
|
4263
|
+
}
|
|
4264
|
+
case "r2_bucket":
|
|
4265
|
+
return b.bucket_name ? null : `r2_bucket binding "${b.name}" missing bucket_name (or "auto")`;
|
|
4266
|
+
case "kv_namespace": {
|
|
4267
|
+
if (!b.namespace_id) return `kv_namespace binding "${b.name}" missing namespace_id (or "auto")`;
|
|
4268
|
+
if (b.namespace_id === AUTO_PROVISION_SENTINEL && !b.title) {
|
|
4269
|
+
return `kv_namespace binding "${b.name}" with namespace_id="auto" requires "title"`;
|
|
4270
|
+
}
|
|
4271
|
+
return null;
|
|
4272
|
+
}
|
|
4273
|
+
case "d1": {
|
|
4274
|
+
if (!b.id) return `d1 binding "${b.name}" missing id (or "auto")`;
|
|
4275
|
+
if (b.id === AUTO_PROVISION_SENTINEL && !b.database_name) {
|
|
4276
|
+
return `d1 binding "${b.name}" with id="auto" requires "database_name"`;
|
|
4277
|
+
}
|
|
4278
|
+
return null;
|
|
4279
|
+
}
|
|
4280
|
+
case "queue":
|
|
4281
|
+
return b.queue_name ? null : `queue binding "${b.name}" missing queue_name (or "auto")`;
|
|
4282
|
+
case "hyperdrive":
|
|
4283
|
+
if (!b.id) return `hyperdrive binding "${b.name}" missing id`;
|
|
4284
|
+
if (b.id === AUTO_PROVISION_SENTINEL) {
|
|
4285
|
+
return `hyperdrive binding "${b.name}": auto-provisioning not yet supported (provide a real id)`;
|
|
4286
|
+
}
|
|
4287
|
+
return null;
|
|
4288
|
+
case "ai":
|
|
4289
|
+
case "browser_rendering":
|
|
4290
|
+
case "analytics_engine":
|
|
4291
|
+
return null;
|
|
4292
|
+
// no required fields beyond `name`
|
|
4293
|
+
default: {
|
|
4294
|
+
const _exhaustive = b;
|
|
4295
|
+
void _exhaustive;
|
|
4296
|
+
return null;
|
|
4297
|
+
}
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
function bindingManifestFromOutputConfig(outputConfig) {
|
|
4301
|
+
const out = [];
|
|
4302
|
+
const aiBinding = pluckString(outputConfig.ai, "binding");
|
|
4303
|
+
if (aiBinding) out.push({ type: "ai", name: aiBinding });
|
|
4304
|
+
for (const v of asObjectArray(outputConfig.vectorize)) {
|
|
4305
|
+
const name = pluckString(v, "binding");
|
|
4306
|
+
const index_name = pluckString(v, "index_name");
|
|
4307
|
+
if (!name || !index_name) continue;
|
|
4308
|
+
const dimensions = pluckNumber(v, "dimensions");
|
|
4309
|
+
const metric = pluckString(v, "metric");
|
|
4310
|
+
out.push({
|
|
4311
|
+
type: "vectorize",
|
|
4312
|
+
name,
|
|
4313
|
+
index_name,
|
|
4314
|
+
...dimensions != null && { dimensions },
|
|
4315
|
+
...metric && (metric === "cosine" || metric === "euclidean" || metric === "dot-product") && { metric }
|
|
4316
|
+
});
|
|
4317
|
+
}
|
|
4318
|
+
for (const r of asObjectArray(outputConfig.r2_buckets)) {
|
|
4319
|
+
const name = pluckString(r, "binding");
|
|
4320
|
+
const bucket_name = pluckString(r, "bucket_name");
|
|
4321
|
+
if (name && bucket_name) out.push({ type: "r2_bucket", name, bucket_name });
|
|
4322
|
+
}
|
|
4323
|
+
for (const k of asObjectArray(outputConfig.kv_namespaces)) {
|
|
4324
|
+
const name = pluckString(k, "binding");
|
|
4325
|
+
const namespace_id = pluckString(k, "id");
|
|
4326
|
+
if (!name || !namespace_id) continue;
|
|
4327
|
+
const title = pluckString(k, "title");
|
|
4328
|
+
out.push({
|
|
4329
|
+
type: "kv_namespace",
|
|
4330
|
+
name,
|
|
4331
|
+
namespace_id,
|
|
4332
|
+
...title && { title }
|
|
4333
|
+
});
|
|
4334
|
+
}
|
|
4335
|
+
for (const d of asObjectArray(outputConfig.d1_databases)) {
|
|
4336
|
+
const name = pluckString(d, "binding");
|
|
4337
|
+
const id = pluckString(d, "database_id");
|
|
4338
|
+
if (!name || !id) continue;
|
|
4339
|
+
const database_name = pluckString(d, "database_name");
|
|
4340
|
+
out.push({
|
|
4341
|
+
type: "d1",
|
|
4342
|
+
name,
|
|
4343
|
+
id,
|
|
4344
|
+
...database_name && { database_name }
|
|
4345
|
+
});
|
|
4346
|
+
}
|
|
4347
|
+
const queues = isObject(outputConfig.queues) ? outputConfig.queues : null;
|
|
4348
|
+
for (const q of asObjectArray(queues?.producers)) {
|
|
4349
|
+
const name = pluckString(q, "binding");
|
|
4350
|
+
const queue_name = pluckString(q, "queue");
|
|
4351
|
+
if (name && queue_name) out.push({ type: "queue", name, queue_name });
|
|
4352
|
+
}
|
|
4353
|
+
const browserBinding = pluckString(outputConfig.browser, "binding");
|
|
4354
|
+
if (browserBinding) out.push({ type: "browser_rendering", name: browserBinding });
|
|
4355
|
+
for (const a of asObjectArray(outputConfig.analytics_engine_datasets)) {
|
|
4356
|
+
const name = pluckString(a, "binding");
|
|
4357
|
+
const dataset = pluckString(a, "dataset");
|
|
4358
|
+
if (name) out.push({ type: "analytics_engine", name, dataset: dataset ?? void 0 });
|
|
4359
|
+
}
|
|
4360
|
+
for (const h of asObjectArray(outputConfig.hyperdrive)) {
|
|
4361
|
+
const name = pluckString(h, "binding");
|
|
4362
|
+
const id = pluckString(h, "id");
|
|
4363
|
+
if (name && id) out.push({ type: "hyperdrive", name, id });
|
|
4364
|
+
}
|
|
4365
|
+
return out;
|
|
4366
|
+
}
|
|
4367
|
+
function isObject(v) {
|
|
4368
|
+
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
4369
|
+
}
|
|
4370
|
+
function pluckString(v, key) {
|
|
4371
|
+
if (!isObject(v)) return null;
|
|
4372
|
+
const val = v[key];
|
|
4373
|
+
return typeof val === "string" && val.length > 0 ? val : null;
|
|
4374
|
+
}
|
|
4375
|
+
function pluckNumber(v, key) {
|
|
4376
|
+
if (!isObject(v)) return null;
|
|
4377
|
+
const val = v[key];
|
|
4378
|
+
return typeof val === "number" && Number.isFinite(val) ? val : null;
|
|
4379
|
+
}
|
|
4380
|
+
function asObjectArray(v) {
|
|
4381
|
+
if (!Array.isArray(v)) return [];
|
|
4382
|
+
return v.filter(isObject);
|
|
4383
|
+
}
|
|
4384
|
+
|
|
4385
|
+
// src/server/rooms/do-migration.ts
|
|
4386
|
+
function computeDoMigration(manifest, existing, options) {
|
|
4387
|
+
const existingNames = new Set(
|
|
4388
|
+
existing.filter((b) => b.type === "durable_object_namespace").map((b) => b.name)
|
|
4389
|
+
);
|
|
4390
|
+
const manifestBindingNames = new Set(manifest.map((e) => e.binding));
|
|
4391
|
+
const newSqliteClasses = manifest.filter((e) => e.sqlite && !existingNames.has(e.binding)).map((e) => e.className).sort();
|
|
4392
|
+
const deletedClasses = [...existingNames].filter((name) => !manifestBindingNames.has(name)).map((name) => {
|
|
4393
|
+
const m = existing.find((b) => b.name === name);
|
|
4394
|
+
return m?.class_name ?? name;
|
|
4395
|
+
}).sort();
|
|
4396
|
+
const needsMigration = newSqliteClasses.length > 0 || deletedClasses.length > 0;
|
|
4397
|
+
const directive = needsMigration ? {
|
|
4398
|
+
tag: migrationTag(newSqliteClasses, deletedClasses, options),
|
|
4399
|
+
...newSqliteClasses.length ? { new_sqlite_classes: newSqliteClasses } : {},
|
|
4400
|
+
...deletedClasses.length ? { deleted_classes: deletedClasses } : {}
|
|
4401
|
+
} : null;
|
|
4402
|
+
return { newSqliteClasses, deletedClasses, needsMigration, directive };
|
|
4403
|
+
}
|
|
4404
|
+
function migrationTag(addClasses, removeClasses, options) {
|
|
4405
|
+
const ts = (options?.now ?? Date.now()).toString(36);
|
|
4406
|
+
const delta = fnv1a32(
|
|
4407
|
+
JSON.stringify({ add: [...addClasses].sort(), remove: [...removeClasses].sort() })
|
|
4408
|
+
);
|
|
4409
|
+
return `m-${ts}-${delta}`;
|
|
4410
|
+
}
|
|
4411
|
+
function fnv1a32(s) {
|
|
4412
|
+
let h = 2166136261;
|
|
4413
|
+
for (let i = 0; i < s.length; i++) {
|
|
4414
|
+
h ^= s.charCodeAt(i);
|
|
4415
|
+
h = Math.imul(h, 16777619) >>> 0;
|
|
4416
|
+
}
|
|
4417
|
+
return h.toString(16).padStart(8, "0");
|
|
4418
|
+
}
|
|
4419
|
+
|
|
4420
|
+
// src/server/rooms/app-name.ts
|
|
4421
|
+
var APP_NAME_RULES = {
|
|
4422
|
+
/** ^[a-z0-9](-?[a-z0-9])+$ — RFC 1035 host label, no consecutive dashes. */
|
|
4423
|
+
pattern: /^[a-z0-9](?:-?[a-z0-9])+$/,
|
|
4424
|
+
minLength: 2,
|
|
4425
|
+
maxLength: 63
|
|
4426
|
+
};
|
|
4427
|
+
function validateAppName(raw) {
|
|
4428
|
+
if (typeof raw !== "string") {
|
|
4429
|
+
return { valid: false, reason: "App name must be a string" };
|
|
4430
|
+
}
|
|
4431
|
+
const name = raw.trim();
|
|
4432
|
+
if (!name) {
|
|
4433
|
+
return { valid: false, reason: "App name is required" };
|
|
4434
|
+
}
|
|
4435
|
+
if (name.length < APP_NAME_RULES.minLength) {
|
|
4436
|
+
return { valid: false, reason: `App name "${name}" is too short (min ${APP_NAME_RULES.minLength} chars)` };
|
|
4437
|
+
}
|
|
4438
|
+
if (name.length > APP_NAME_RULES.maxLength) {
|
|
4439
|
+
return { valid: false, reason: `App name "${name}" is too long (max ${APP_NAME_RULES.maxLength} chars)` };
|
|
4440
|
+
}
|
|
4441
|
+
if (!APP_NAME_RULES.pattern.test(name)) {
|
|
4442
|
+
return {
|
|
4443
|
+
valid: false,
|
|
4444
|
+
reason: `App name "${name}" is invalid. Use lowercase letters, digits, and single hyphens only (must start + end with alphanumeric). Examples: my-app, search-v2, unison-search.`
|
|
4445
|
+
};
|
|
4446
|
+
}
|
|
4447
|
+
return { valid: true, name };
|
|
4448
|
+
}
|
|
4449
|
+
function resolveAppName(raw) {
|
|
4450
|
+
const strict = validateAppName(raw);
|
|
4451
|
+
if (strict.valid) return { ok: true, name: strict.name };
|
|
4452
|
+
if (typeof raw !== "string") return { ok: false, reason: strict.reason };
|
|
4453
|
+
const trimmed = raw.trim();
|
|
4454
|
+
if (!trimmed) return { ok: false, reason: "App name is required" };
|
|
4455
|
+
const sanitized = sanitizeAppName(trimmed);
|
|
4456
|
+
const sanitizedStrict = validateAppName(sanitized);
|
|
4457
|
+
if (!sanitizedStrict.valid) {
|
|
4458
|
+
return {
|
|
4459
|
+
ok: false,
|
|
4460
|
+
reason: `App name "${trimmed}" can't be sanitized into a valid name (${sanitizedStrict.reason}). Pick something matching: lowercase letters, digits, single hyphens, ${APP_NAME_RULES.minLength}-${APP_NAME_RULES.maxLength} chars.`
|
|
4461
|
+
};
|
|
4462
|
+
}
|
|
4463
|
+
return {
|
|
4464
|
+
ok: true,
|
|
4465
|
+
name: sanitized,
|
|
4466
|
+
warning: `App name "${trimmed}" doesn't conform to deploy rules \u2014 using "${sanitized}" instead. Update wrangler.toml's \`name\` to silence this warning.`
|
|
4467
|
+
};
|
|
4468
|
+
}
|
|
4469
|
+
function sanitizeAppName(raw) {
|
|
4470
|
+
return raw.toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
|
|
4471
|
+
}
|
|
4132
4472
|
|
|
4133
4473
|
// src/server/schemas/ai-chat.ts
|
|
4134
4474
|
var AI_CHATS_SCHEMA = {
|
|
@@ -5611,6 +5951,8 @@ async function executeTool2(stub, userId, tool, params) {
|
|
|
5611
5951
|
}
|
|
5612
5952
|
function toChatRow(env) {
|
|
5613
5953
|
return {
|
|
5954
|
+
recordId: env.recordId,
|
|
5955
|
+
// Deprecated alias — populated for back-compat with callers reading `id`.
|
|
5614
5956
|
id: env.recordId,
|
|
5615
5957
|
userId: env.data.userId,
|
|
5616
5958
|
title: env.data.title ?? "",
|
|
@@ -5623,6 +5965,8 @@ function toChatRow(env) {
|
|
|
5623
5965
|
}
|
|
5624
5966
|
function toMessageRow(env) {
|
|
5625
5967
|
return {
|
|
5968
|
+
recordId: env.recordId,
|
|
5969
|
+
// Deprecated alias — populated for back-compat with callers reading `id`.
|
|
5626
5970
|
id: env.recordId,
|
|
5627
5971
|
chatId: env.data.chatId,
|
|
5628
5972
|
userId: env.data.userId,
|
|
@@ -5716,9 +6060,90 @@ async function appendMessage(stub, msg) {
|
|
|
5716
6060
|
data
|
|
5717
6061
|
});
|
|
5718
6062
|
}
|
|
6063
|
+
|
|
6064
|
+
// src/server/utils/metering.ts
|
|
6065
|
+
function meterUsage(env, kind, fields = {}) {
|
|
6066
|
+
const ds = env.USAGE_EVENTS;
|
|
6067
|
+
if (!ds) return false;
|
|
6068
|
+
try {
|
|
6069
|
+
ds.writeDataPoint({
|
|
6070
|
+
indexes: [env.OWNER_USER_ID ?? "unknown"],
|
|
6071
|
+
blobs: [env.APP_NAME ?? "unknown", kind, fields.id ?? "", fields.op ?? ""],
|
|
6072
|
+
doubles: [fields.units ?? 0, fields.count ?? 0]
|
|
6073
|
+
});
|
|
6074
|
+
return true;
|
|
6075
|
+
} catch {
|
|
6076
|
+
return false;
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
function meterAi(env, model, fields = {}) {
|
|
6080
|
+
const calls = fields.calls ?? 1;
|
|
6081
|
+
const inChars = fields.inputChars ?? 0;
|
|
6082
|
+
const outChars = fields.outputChars ?? 0;
|
|
6083
|
+
let ok = true;
|
|
6084
|
+
if (inChars > 0) {
|
|
6085
|
+
ok = meterUsage(env, "ai", { id: model, op: "input", units: inChars, count: calls }) && ok;
|
|
6086
|
+
}
|
|
6087
|
+
if (outChars > 0) {
|
|
6088
|
+
ok = meterUsage(env, "ai", { id: model, op: "output", units: outChars, count: calls }) && ok;
|
|
6089
|
+
}
|
|
6090
|
+
if (inChars === 0 && outChars === 0) {
|
|
6091
|
+
ok = meterUsage(env, "ai", { id: model, op: "call", units: 0, count: calls }) && ok;
|
|
6092
|
+
}
|
|
6093
|
+
return ok;
|
|
6094
|
+
}
|
|
6095
|
+
function meterVectorize(env, indexName, op, fields = {}) {
|
|
6096
|
+
const vectors = fields.vectors ?? 0;
|
|
6097
|
+
const dims = fields.dims ?? 0;
|
|
6098
|
+
const stored = fields.storedCount ?? 0;
|
|
6099
|
+
const units = op === "query" ? (vectors + stored) * dims : vectors * dims;
|
|
6100
|
+
return meterUsage(env, "vectorize", { id: indexName, op, units, count: vectors });
|
|
6101
|
+
}
|
|
6102
|
+
var CHARS_PER_TOKEN = 4;
|
|
6103
|
+
var AI_EMBED_USD_PER_M_TOKENS = 0.012;
|
|
6104
|
+
var VECTORIZE_QUERIED_USD_PER_M_DIMS = 0.01;
|
|
6105
|
+
var VECTORIZE_STORED_USD_PER_100M_DIMS = 0.05;
|
|
6106
|
+
var COST_RATES = {
|
|
6107
|
+
ai: {
|
|
6108
|
+
/** USD per character (input or output). */
|
|
6109
|
+
perChar: AI_EMBED_USD_PER_M_TOKENS / 1e6 / CHARS_PER_TOKEN
|
|
6110
|
+
},
|
|
6111
|
+
vectorize: {
|
|
6112
|
+
/** USD per queried dimension (per query, per stored vector compared). */
|
|
6113
|
+
queriedPerDim: VECTORIZE_QUERIED_USD_PER_M_DIMS / 1e6,
|
|
6114
|
+
/** USD per stored dimension per month. */
|
|
6115
|
+
storedPerDimPerMonth: VECTORIZE_STORED_USD_PER_100M_DIMS / 1e8
|
|
6116
|
+
}
|
|
6117
|
+
};
|
|
6118
|
+
|
|
6119
|
+
// src/server/utils/d1-migrations.ts
|
|
6120
|
+
async function runMigrations(db, migrations) {
|
|
6121
|
+
const versionRow = await db.prepare("PRAGMA user_version").first();
|
|
6122
|
+
const fromVersion = versionRow?.user_version ?? 0;
|
|
6123
|
+
if (fromVersion >= migrations.length) {
|
|
6124
|
+
return { fromVersion, toVersion: fromVersion, applied: 0 };
|
|
6125
|
+
}
|
|
6126
|
+
let current = fromVersion;
|
|
6127
|
+
for (let i = fromVersion; i < migrations.length; i++) {
|
|
6128
|
+
const sql = migrations[i];
|
|
6129
|
+
try {
|
|
6130
|
+
await db.exec(sql);
|
|
6131
|
+
} catch (err) {
|
|
6132
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6133
|
+
throw new Error(`Migration ${i} failed (db at user_version=${current}): ${msg}`);
|
|
6134
|
+
}
|
|
6135
|
+
current = i + 1;
|
|
6136
|
+
await db.exec(`PRAGMA user_version = ${current}`);
|
|
6137
|
+
}
|
|
6138
|
+
return { fromVersion, toVersion: current, applied: current - fromVersion };
|
|
6139
|
+
}
|
|
5719
6140
|
export {
|
|
5720
6141
|
AI_CHATS_SCHEMA,
|
|
5721
6142
|
AI_MESSAGES_SCHEMA,
|
|
6143
|
+
ALLOWED_BINDING_TYPES,
|
|
6144
|
+
APP_NAME_RULES,
|
|
6145
|
+
AUTO_PROVISIONABLE_TYPES,
|
|
6146
|
+
AUTO_PROVISION_SENTINEL,
|
|
5722
6147
|
Awareness,
|
|
5723
6148
|
BASE_USERS_SCHEMA,
|
|
5724
6149
|
BUILT_IN_TOOLS,
|
|
@@ -5727,6 +6152,7 @@ export {
|
|
|
5727
6152
|
CHANNEL_INVITATIONS_SCHEMA,
|
|
5728
6153
|
CHANNEL_MEMBERS_SCHEMA,
|
|
5729
6154
|
CONVERSATION_SCHEMAS,
|
|
6155
|
+
COST_RATES,
|
|
5730
6156
|
CanvasRoom,
|
|
5731
6157
|
CronRoom,
|
|
5732
6158
|
DEFAULT_CONTEXT_CONFIG,
|
|
@@ -5748,6 +6174,7 @@ export {
|
|
|
5748
6174
|
PresenceRoom,
|
|
5749
6175
|
REACTIONS_SCHEMA,
|
|
5750
6176
|
READ_RECEIPTS_SCHEMA,
|
|
6177
|
+
RESERVED_BINDING_NAMES,
|
|
5751
6178
|
RESERVED_COLLECTION_NAMES,
|
|
5752
6179
|
ROLE_ADMIN,
|
|
5753
6180
|
ROLE_ANONYMOUS,
|
|
@@ -5765,6 +6192,7 @@ export {
|
|
|
5765
6192
|
appendMessage,
|
|
5766
6193
|
applySlidingWindow,
|
|
5767
6194
|
authWorkerFetch,
|
|
6195
|
+
bindingManifestFromOutputConfig,
|
|
5768
6196
|
buildCronContext,
|
|
5769
6197
|
buildInternalPayload,
|
|
5770
6198
|
buildTableSelect,
|
|
@@ -5779,6 +6207,7 @@ export {
|
|
|
5779
6207
|
coerceValue,
|
|
5780
6208
|
collectionTableName,
|
|
5781
6209
|
columnId,
|
|
6210
|
+
computeDoMigration,
|
|
5782
6211
|
computeHmacHex,
|
|
5783
6212
|
createChat,
|
|
5784
6213
|
createDecoder,
|
|
@@ -5803,16 +6232,22 @@ export {
|
|
|
5803
6232
|
handleAwarenessMessage,
|
|
5804
6233
|
handleSyncMessage,
|
|
5805
6234
|
hasContent,
|
|
6235
|
+
isAutoProvision,
|
|
5806
6236
|
isOwner,
|
|
5807
6237
|
loadMessages,
|
|
5808
6238
|
makeDefaultSummarizer,
|
|
6239
|
+
meterAi,
|
|
6240
|
+
meterUsage,
|
|
6241
|
+
meterVectorize,
|
|
5809
6242
|
noopPermissionContext,
|
|
5810
6243
|
platformWorkerFetch,
|
|
5811
6244
|
prepareMessagesWithCompaction,
|
|
5812
6245
|
readVarUint,
|
|
5813
6246
|
readVarUint8Array,
|
|
6247
|
+
resolveAppName,
|
|
5814
6248
|
resolveColumn,
|
|
5815
6249
|
rowToData,
|
|
6250
|
+
runMigrations,
|
|
5816
6251
|
serverBuild,
|
|
5817
6252
|
signInternalPayload,
|
|
5818
6253
|
timingSafeEqualHex,
|
|
@@ -5822,6 +6257,9 @@ export {
|
|
|
5822
6257
|
turnsToCoreMessages,
|
|
5823
6258
|
unwrapToolOutput,
|
|
5824
6259
|
updateChat,
|
|
6260
|
+
validateAppName,
|
|
6261
|
+
validateBindingManifest,
|
|
6262
|
+
validateDoManifest,
|
|
5825
6263
|
verifyInternalSignature,
|
|
5826
6264
|
verifyJwt,
|
|
5827
6265
|
workspaceAccountsSchema,
|