deepspace 0.2.8 → 0.3.3
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 +453 -1
- package/dist/worker.js +444 -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,96 @@ 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
|
+
var META_TABLE = "_dpc_migrations";
|
|
6121
|
+
var META_BOOTSTRAP_SQL = `CREATE TABLE IF NOT EXISTS ${META_TABLE} (
|
|
6122
|
+
idx INTEGER PRIMARY KEY,
|
|
6123
|
+
applied_at TEXT NOT NULL
|
|
6124
|
+
);`;
|
|
6125
|
+
async function runMigrations(db, migrations) {
|
|
6126
|
+
await db.exec(META_BOOTSTRAP_SQL);
|
|
6127
|
+
const row = await db.prepare(`SELECT COUNT(*) AS n FROM ${META_TABLE}`).first();
|
|
6128
|
+
const fromVersion = row?.n ?? 0;
|
|
6129
|
+
if (fromVersion >= migrations.length) {
|
|
6130
|
+
return { fromVersion, toVersion: fromVersion, applied: 0 };
|
|
6131
|
+
}
|
|
6132
|
+
let current = fromVersion;
|
|
6133
|
+
for (let i = fromVersion; i < migrations.length; i++) {
|
|
6134
|
+
const sql = migrations[i];
|
|
6135
|
+
try {
|
|
6136
|
+
await db.exec(sql);
|
|
6137
|
+
} catch (err) {
|
|
6138
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
6139
|
+
throw new Error(`Migration ${i} failed (db at version=${current}): ${msg}`);
|
|
6140
|
+
}
|
|
6141
|
+
await db.prepare(`INSERT INTO ${META_TABLE} (idx, applied_at) VALUES (?, ?)`).bind(i, (/* @__PURE__ */ new Date()).toISOString()).run();
|
|
6142
|
+
current = i + 1;
|
|
6143
|
+
}
|
|
6144
|
+
return { fromVersion, toVersion: current, applied: current - fromVersion };
|
|
6145
|
+
}
|
|
5719
6146
|
export {
|
|
5720
6147
|
AI_CHATS_SCHEMA,
|
|
5721
6148
|
AI_MESSAGES_SCHEMA,
|
|
6149
|
+
ALLOWED_BINDING_TYPES,
|
|
6150
|
+
APP_NAME_RULES,
|
|
6151
|
+
AUTO_PROVISIONABLE_TYPES,
|
|
6152
|
+
AUTO_PROVISION_SENTINEL,
|
|
5722
6153
|
Awareness,
|
|
5723
6154
|
BASE_USERS_SCHEMA,
|
|
5724
6155
|
BUILT_IN_TOOLS,
|
|
@@ -5727,6 +6158,7 @@ export {
|
|
|
5727
6158
|
CHANNEL_INVITATIONS_SCHEMA,
|
|
5728
6159
|
CHANNEL_MEMBERS_SCHEMA,
|
|
5729
6160
|
CONVERSATION_SCHEMAS,
|
|
6161
|
+
COST_RATES,
|
|
5730
6162
|
CanvasRoom,
|
|
5731
6163
|
CronRoom,
|
|
5732
6164
|
DEFAULT_CONTEXT_CONFIG,
|
|
@@ -5748,6 +6180,7 @@ export {
|
|
|
5748
6180
|
PresenceRoom,
|
|
5749
6181
|
REACTIONS_SCHEMA,
|
|
5750
6182
|
READ_RECEIPTS_SCHEMA,
|
|
6183
|
+
RESERVED_BINDING_NAMES,
|
|
5751
6184
|
RESERVED_COLLECTION_NAMES,
|
|
5752
6185
|
ROLE_ADMIN,
|
|
5753
6186
|
ROLE_ANONYMOUS,
|
|
@@ -5765,6 +6198,7 @@ export {
|
|
|
5765
6198
|
appendMessage,
|
|
5766
6199
|
applySlidingWindow,
|
|
5767
6200
|
authWorkerFetch,
|
|
6201
|
+
bindingManifestFromOutputConfig,
|
|
5768
6202
|
buildCronContext,
|
|
5769
6203
|
buildInternalPayload,
|
|
5770
6204
|
buildTableSelect,
|
|
@@ -5779,6 +6213,7 @@ export {
|
|
|
5779
6213
|
coerceValue,
|
|
5780
6214
|
collectionTableName,
|
|
5781
6215
|
columnId,
|
|
6216
|
+
computeDoMigration,
|
|
5782
6217
|
computeHmacHex,
|
|
5783
6218
|
createChat,
|
|
5784
6219
|
createDecoder,
|
|
@@ -5803,16 +6238,22 @@ export {
|
|
|
5803
6238
|
handleAwarenessMessage,
|
|
5804
6239
|
handleSyncMessage,
|
|
5805
6240
|
hasContent,
|
|
6241
|
+
isAutoProvision,
|
|
5806
6242
|
isOwner,
|
|
5807
6243
|
loadMessages,
|
|
5808
6244
|
makeDefaultSummarizer,
|
|
6245
|
+
meterAi,
|
|
6246
|
+
meterUsage,
|
|
6247
|
+
meterVectorize,
|
|
5809
6248
|
noopPermissionContext,
|
|
5810
6249
|
platformWorkerFetch,
|
|
5811
6250
|
prepareMessagesWithCompaction,
|
|
5812
6251
|
readVarUint,
|
|
5813
6252
|
readVarUint8Array,
|
|
6253
|
+
resolveAppName,
|
|
5814
6254
|
resolveColumn,
|
|
5815
6255
|
rowToData,
|
|
6256
|
+
runMigrations,
|
|
5816
6257
|
serverBuild,
|
|
5817
6258
|
signInternalPayload,
|
|
5818
6259
|
timingSafeEqualHex,
|
|
@@ -5822,6 +6263,9 @@ export {
|
|
|
5822
6263
|
turnsToCoreMessages,
|
|
5823
6264
|
unwrapToolOutput,
|
|
5824
6265
|
updateChat,
|
|
6266
|
+
validateAppName,
|
|
6267
|
+
validateBindingManifest,
|
|
6268
|
+
validateDoManifest,
|
|
5825
6269
|
verifyInternalSignature,
|
|
5826
6270
|
verifyJwt,
|
|
5827
6271
|
workspaceAccountsSchema,
|