deepspace 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +80 -1
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -1
- package/dist/worker.d.ts +188 -10
- package/dist/worker.js +459 -12
- package/dist/worker.js.map +1 -1
- package/package.json +6 -6
package/dist/worker.js
CHANGED
|
@@ -4130,6 +4130,40 @@ var DEFAULT_DO_MANIFEST = [
|
|
|
4130
4130
|
{ binding: "YJS_ROOMS", className: "AppYjsRoom", sqlite: true }
|
|
4131
4131
|
];
|
|
4132
4132
|
|
|
4133
|
+
// src/server/schemas/ai-chat.ts
|
|
4134
|
+
var AI_CHATS_SCHEMA = {
|
|
4135
|
+
name: "ai-chats",
|
|
4136
|
+
columns: [
|
|
4137
|
+
{ name: "userId", storage: "text", interpretation: "plain", userBound: true, immutable: true, required: true },
|
|
4138
|
+
{ name: "title", storage: "text", interpretation: "plain" },
|
|
4139
|
+
{ name: "model", storage: "text", interpretation: "plain" },
|
|
4140
|
+
{ name: "compactedSummary", storage: "text", interpretation: "plain" },
|
|
4141
|
+
{ name: "compactedThroughId", storage: "text", interpretation: "plain" }
|
|
4142
|
+
],
|
|
4143
|
+
ownerField: "userId",
|
|
4144
|
+
permissions: {
|
|
4145
|
+
admin: { read: true, create: true, update: true, delete: true },
|
|
4146
|
+
member: { read: "own", create: false, update: "own", delete: "own" },
|
|
4147
|
+
viewer: { read: "own", create: false, update: false, delete: false }
|
|
4148
|
+
}
|
|
4149
|
+
};
|
|
4150
|
+
var AI_MESSAGES_SCHEMA = {
|
|
4151
|
+
name: "ai-messages",
|
|
4152
|
+
columns: [
|
|
4153
|
+
{ name: "chatId", storage: "text", interpretation: "plain", immutable: true, required: true },
|
|
4154
|
+
{ name: "userId", storage: "text", interpretation: "plain", userBound: true, immutable: true, required: true },
|
|
4155
|
+
{ name: "role", storage: "text", interpretation: "plain", required: true },
|
|
4156
|
+
{ name: "content", storage: "text", interpretation: "plain" },
|
|
4157
|
+
{ name: "parts", storage: "text", interpretation: { kind: "json" } }
|
|
4158
|
+
],
|
|
4159
|
+
ownerField: "userId",
|
|
4160
|
+
permissions: {
|
|
4161
|
+
admin: { read: true, create: true, update: true, delete: true },
|
|
4162
|
+
member: { read: "own", create: false, update: "own", delete: "own" },
|
|
4163
|
+
viewer: { read: "own", create: false, update: false, delete: false }
|
|
4164
|
+
}
|
|
4165
|
+
};
|
|
4166
|
+
|
|
4133
4167
|
// src/server/schemas/messaging.ts
|
|
4134
4168
|
var CHANNELS_SCHEMA = {
|
|
4135
4169
|
name: "channels",
|
|
@@ -5073,7 +5107,7 @@ function buildCronContext(env, ownerUserId, roomId = "default") {
|
|
|
5073
5107
|
const apiBase = env.API_BASE_URL || "https://api.deep.space";
|
|
5074
5108
|
const roomIdObj = env.RECORD_ROOMS.idFromName(roomId);
|
|
5075
5109
|
const room = env.RECORD_ROOMS.get(roomIdObj);
|
|
5076
|
-
async function
|
|
5110
|
+
async function executeTool3(tool, params) {
|
|
5077
5111
|
const response = await room.fetch(new Request("https://internal/api/tools/execute", {
|
|
5078
5112
|
method: "POST",
|
|
5079
5113
|
headers: {
|
|
@@ -5094,17 +5128,17 @@ function buildCronContext(env, ownerUserId, roomId = "default") {
|
|
|
5094
5128
|
const params = { collection };
|
|
5095
5129
|
if (opts?.where) params.where = opts.where;
|
|
5096
5130
|
if (opts?.limit) params.limit = opts.limit;
|
|
5097
|
-
const data = await
|
|
5131
|
+
const data = await executeTool3("records.query", params);
|
|
5098
5132
|
return data.records || [];
|
|
5099
5133
|
},
|
|
5100
5134
|
async create(collection, data) {
|
|
5101
|
-
return
|
|
5135
|
+
return executeTool3("records.create", { collection, data });
|
|
5102
5136
|
},
|
|
5103
5137
|
async update(collection, recordId, data) {
|
|
5104
|
-
return
|
|
5138
|
+
return executeTool3("records.update", { collection, recordId, data });
|
|
5105
5139
|
},
|
|
5106
5140
|
async delete(collection, recordId) {
|
|
5107
|
-
return
|
|
5141
|
+
return executeTool3("records.delete", { collection, recordId });
|
|
5108
5142
|
}
|
|
5109
5143
|
};
|
|
5110
5144
|
const integrations = {
|
|
@@ -5266,13 +5300,10 @@ function createDeepSpaceAI(env, provider, options = {}) {
|
|
|
5266
5300
|
switch (provider) {
|
|
5267
5301
|
case "anthropic":
|
|
5268
5302
|
return createAnthropic({ baseURL, apiKey: "platform-managed", fetch: proxyFetch });
|
|
5269
|
-
case "openai":
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
fetch: proxyFetch,
|
|
5274
|
-
compatibility: "strict"
|
|
5275
|
-
});
|
|
5303
|
+
case "openai": {
|
|
5304
|
+
const op = createOpenAI({ baseURL, apiKey: "platform-managed", fetch: proxyFetch });
|
|
5305
|
+
return op.chat;
|
|
5306
|
+
}
|
|
5276
5307
|
case "cerebras":
|
|
5277
5308
|
return createOpenAICompatible({
|
|
5278
5309
|
name: "cerebras",
|
|
@@ -5287,7 +5318,407 @@ function createDeepSpaceAI(env, provider, options = {}) {
|
|
|
5287
5318
|
}
|
|
5288
5319
|
}
|
|
5289
5320
|
}
|
|
5321
|
+
|
|
5322
|
+
// src/server/utils/chat-context.ts
|
|
5323
|
+
import { generateText } from "ai";
|
|
5324
|
+
var DEFAULT_CONTEXT_CONFIG = {
|
|
5325
|
+
contextBudget: 24e4,
|
|
5326
|
+
toolResultCap: 3e4,
|
|
5327
|
+
keepRecentToolResults: 5,
|
|
5328
|
+
minKept: 10
|
|
5329
|
+
};
|
|
5330
|
+
function sizeOf(m) {
|
|
5331
|
+
return (m.content ?? "").length + (m.parts ? JSON.stringify(m.parts).length : 0);
|
|
5332
|
+
}
|
|
5333
|
+
function totalChars(messages) {
|
|
5334
|
+
return messages.reduce((acc, m) => acc + sizeOf(m), 0);
|
|
5335
|
+
}
|
|
5336
|
+
function truncateOldToolResults(messages, keepRecent) {
|
|
5337
|
+
const assistantIdxs = [];
|
|
5338
|
+
for (let i = 0; i < messages.length; i++) {
|
|
5339
|
+
if (messages[i].role === "assistant") assistantIdxs.push(i);
|
|
5340
|
+
}
|
|
5341
|
+
const protectedStart = assistantIdxs.length > keepRecent ? assistantIdxs[assistantIdxs.length - keepRecent] : 0;
|
|
5342
|
+
return messages.map((msg, idx) => {
|
|
5343
|
+
if (msg.role !== "assistant" || idx >= protectedStart) return msg;
|
|
5344
|
+
if (!Array.isArray(msg.parts) || msg.parts.length === 0) return msg;
|
|
5345
|
+
const newParts = msg.parts.map((p) => {
|
|
5346
|
+
if (!p || typeof p !== "object") return p;
|
|
5347
|
+
const anyP = p;
|
|
5348
|
+
if (anyP.type !== "tool-invocation") return p;
|
|
5349
|
+
const inv = anyP.toolInvocation;
|
|
5350
|
+
if (!inv || inv.state !== "result") return p;
|
|
5351
|
+
const result = inv.result;
|
|
5352
|
+
if (result && result.success === false) return p;
|
|
5353
|
+
return {
|
|
5354
|
+
...anyP,
|
|
5355
|
+
toolInvocation: {
|
|
5356
|
+
...inv,
|
|
5357
|
+
result: {
|
|
5358
|
+
_truncated: true,
|
|
5359
|
+
note: "Result from an earlier turn omitted to save context. Call this tool again if you need the data."
|
|
5360
|
+
}
|
|
5361
|
+
}
|
|
5362
|
+
};
|
|
5363
|
+
});
|
|
5364
|
+
return { ...msg, parts: newParts };
|
|
5365
|
+
});
|
|
5366
|
+
}
|
|
5367
|
+
function applySlidingWindow(messages, charCap, minKept) {
|
|
5368
|
+
let total = totalChars(messages);
|
|
5369
|
+
if (total <= charCap) return messages;
|
|
5370
|
+
const out = [...messages];
|
|
5371
|
+
while (out.length > minKept && total > charCap) {
|
|
5372
|
+
const idx = out.findIndex((m) => m.role !== "system");
|
|
5373
|
+
if (idx < 0) break;
|
|
5374
|
+
const dropped = out.splice(idx, 1)[0];
|
|
5375
|
+
total -= sizeOf(dropped);
|
|
5376
|
+
}
|
|
5377
|
+
return out;
|
|
5378
|
+
}
|
|
5379
|
+
function capToolResultSize(result, byteCap) {
|
|
5380
|
+
let serialized;
|
|
5381
|
+
try {
|
|
5382
|
+
serialized = JSON.stringify(result);
|
|
5383
|
+
} catch {
|
|
5384
|
+
return { success: false, error: "Tool result could not be serialized." };
|
|
5385
|
+
}
|
|
5386
|
+
if (typeof serialized !== "string") return result;
|
|
5387
|
+
if (serialized.length <= byteCap) return result;
|
|
5388
|
+
return {
|
|
5389
|
+
success: false,
|
|
5390
|
+
truncated: true,
|
|
5391
|
+
error: `Tool result exceeded ${byteCap} bytes (was ${serialized.length}). Retry with a narrower query (e.g. add a \`where\` filter, reduce \`limit\`, or call records.get for a single record).`,
|
|
5392
|
+
preview: serialized.slice(0, 2e3)
|
|
5393
|
+
};
|
|
5394
|
+
}
|
|
5395
|
+
function turnsToCoreMessages(turns) {
|
|
5396
|
+
const out = [];
|
|
5397
|
+
for (const t of turns) {
|
|
5398
|
+
if (t.role === "system") {
|
|
5399
|
+
out.push({ role: "system", content: t.content });
|
|
5400
|
+
continue;
|
|
5401
|
+
}
|
|
5402
|
+
if (t.role === "user") {
|
|
5403
|
+
out.push({ role: "user", content: t.content });
|
|
5404
|
+
continue;
|
|
5405
|
+
}
|
|
5406
|
+
if (!Array.isArray(t.parts) || t.parts.length === 0) {
|
|
5407
|
+
if (t.content) out.push({ role: "assistant", content: t.content });
|
|
5408
|
+
continue;
|
|
5409
|
+
}
|
|
5410
|
+
let pending = [];
|
|
5411
|
+
let emittedAny = false;
|
|
5412
|
+
const flushAssistant = () => {
|
|
5413
|
+
if (pending.length === 0) return;
|
|
5414
|
+
out.push({ role: "assistant", content: pending });
|
|
5415
|
+
pending = [];
|
|
5416
|
+
emittedAny = true;
|
|
5417
|
+
};
|
|
5418
|
+
for (const p of t.parts) {
|
|
5419
|
+
if (!p || typeof p !== "object") continue;
|
|
5420
|
+
const anyP = p;
|
|
5421
|
+
if (anyP.type === "text" && typeof anyP.text === "string" && anyP.text) {
|
|
5422
|
+
pending.push({ type: "text", text: anyP.text });
|
|
5423
|
+
continue;
|
|
5424
|
+
}
|
|
5425
|
+
if (anyP.type !== "tool-invocation") continue;
|
|
5426
|
+
const inv = anyP.toolInvocation;
|
|
5427
|
+
const toolCallId = typeof anyP.toolCallId === "string" ? anyP.toolCallId : void 0;
|
|
5428
|
+
const toolName = typeof inv?.toolName === "string" ? inv.toolName : void 0;
|
|
5429
|
+
if (!toolCallId || !toolName) continue;
|
|
5430
|
+
if (inv?.state !== "result") continue;
|
|
5431
|
+
pending.push({ type: "tool-call", toolCallId, toolName, input: inv?.args });
|
|
5432
|
+
flushAssistant();
|
|
5433
|
+
const tr = {
|
|
5434
|
+
type: "tool-result",
|
|
5435
|
+
toolCallId,
|
|
5436
|
+
toolName,
|
|
5437
|
+
output: { type: "json", value: inv.result }
|
|
5438
|
+
};
|
|
5439
|
+
out.push({ role: "tool", content: [tr] });
|
|
5440
|
+
}
|
|
5441
|
+
flushAssistant();
|
|
5442
|
+
if (!emittedAny && t.content) {
|
|
5443
|
+
out.push({ role: "assistant", content: t.content });
|
|
5444
|
+
}
|
|
5445
|
+
}
|
|
5446
|
+
return out;
|
|
5447
|
+
}
|
|
5448
|
+
function buildUiParts(responseMessages) {
|
|
5449
|
+
const toolResults = /* @__PURE__ */ new Map();
|
|
5450
|
+
for (const msg of responseMessages) {
|
|
5451
|
+
if (msg.role !== "tool" || !Array.isArray(msg.content)) continue;
|
|
5452
|
+
for (const c of msg.content) {
|
|
5453
|
+
if (c.type === "tool-result") {
|
|
5454
|
+
toolResults.set(c.toolCallId, unwrapToolOutput(c.output));
|
|
5455
|
+
}
|
|
5456
|
+
}
|
|
5457
|
+
}
|
|
5458
|
+
const parts = [];
|
|
5459
|
+
for (const msg of responseMessages) {
|
|
5460
|
+
if (msg.role !== "assistant") continue;
|
|
5461
|
+
if (typeof msg.content === "string") {
|
|
5462
|
+
if (msg.content) parts.push({ type: "text", text: msg.content });
|
|
5463
|
+
continue;
|
|
5464
|
+
}
|
|
5465
|
+
if (!Array.isArray(msg.content)) continue;
|
|
5466
|
+
for (const c of msg.content) {
|
|
5467
|
+
if (c.type === "text" && typeof c.text === "string" && c.text) {
|
|
5468
|
+
parts.push({ type: "text", text: c.text });
|
|
5469
|
+
} else if (c.type === "tool-call") {
|
|
5470
|
+
const result = toolResults.get(c.toolCallId);
|
|
5471
|
+
if (result === void 0) {
|
|
5472
|
+
continue;
|
|
5473
|
+
}
|
|
5474
|
+
parts.push({
|
|
5475
|
+
type: "tool-invocation",
|
|
5476
|
+
toolCallId: c.toolCallId,
|
|
5477
|
+
toolInvocation: {
|
|
5478
|
+
toolName: c.toolName,
|
|
5479
|
+
state: "result",
|
|
5480
|
+
args: c.input,
|
|
5481
|
+
result
|
|
5482
|
+
}
|
|
5483
|
+
});
|
|
5484
|
+
}
|
|
5485
|
+
}
|
|
5486
|
+
}
|
|
5487
|
+
return parts;
|
|
5488
|
+
}
|
|
5489
|
+
function unwrapToolOutput(output) {
|
|
5490
|
+
if (!output || typeof output !== "object") return output;
|
|
5491
|
+
const o = output;
|
|
5492
|
+
const tag = typeof o.type === "string" ? o.type : null;
|
|
5493
|
+
if (tag === "json" || tag === "text") {
|
|
5494
|
+
return "value" in o ? o.value : output;
|
|
5495
|
+
}
|
|
5496
|
+
if (tag === "error-text" || tag === "error-json") {
|
|
5497
|
+
return { success: false, error: "value" in o ? o.value : "Tool execution failed" };
|
|
5498
|
+
}
|
|
5499
|
+
return output;
|
|
5500
|
+
}
|
|
5501
|
+
function buildSummaryMessage(text, throughId) {
|
|
5502
|
+
return {
|
|
5503
|
+
id: `summary-${throughId}`,
|
|
5504
|
+
role: "system",
|
|
5505
|
+
content: `Earlier conversation summary:
|
|
5506
|
+
${text}`
|
|
5507
|
+
};
|
|
5508
|
+
}
|
|
5509
|
+
async function prepareMessagesWithCompaction(messages, config, options) {
|
|
5510
|
+
const truncated = truncateOldToolResults(messages, config.keepRecentToolResults);
|
|
5511
|
+
let working = truncated;
|
|
5512
|
+
if (options.cachedSummary) {
|
|
5513
|
+
const idx = truncated.findIndex((m) => m.id === options.cachedSummary.throughId);
|
|
5514
|
+
if (idx >= 0) {
|
|
5515
|
+
working = [
|
|
5516
|
+
buildSummaryMessage(options.cachedSummary.text, options.cachedSummary.throughId),
|
|
5517
|
+
...truncated.slice(idx + 1)
|
|
5518
|
+
];
|
|
5519
|
+
}
|
|
5520
|
+
}
|
|
5521
|
+
if (totalChars(working) <= config.contextBudget) {
|
|
5522
|
+
return { messages: working };
|
|
5523
|
+
}
|
|
5524
|
+
const half = Math.max(1, Math.floor(working.length / 2));
|
|
5525
|
+
const older = working.slice(0, half);
|
|
5526
|
+
const newer = working.slice(half);
|
|
5527
|
+
let throughId;
|
|
5528
|
+
for (let i = older.length - 1; i >= 0; i--) {
|
|
5529
|
+
const id = older[i].id;
|
|
5530
|
+
if (id && !id.startsWith("summary-")) {
|
|
5531
|
+
throughId = id;
|
|
5532
|
+
break;
|
|
5533
|
+
}
|
|
5534
|
+
}
|
|
5535
|
+
if (throughId) {
|
|
5536
|
+
try {
|
|
5537
|
+
const text = await options.summarizer(older);
|
|
5538
|
+
return {
|
|
5539
|
+
messages: [buildSummaryMessage(text, throughId), ...newer],
|
|
5540
|
+
newSummary: { text, throughId }
|
|
5541
|
+
};
|
|
5542
|
+
} catch (err) {
|
|
5543
|
+
console.error("prepareMessagesWithCompaction: summarizer failed, falling back to sliding window", err);
|
|
5544
|
+
}
|
|
5545
|
+
} else {
|
|
5546
|
+
console.warn("prepareMessagesWithCompaction: messages lack ids; cannot anchor a summary, falling back to sliding window");
|
|
5547
|
+
}
|
|
5548
|
+
return {
|
|
5549
|
+
messages: applySlidingWindow(working, config.contextBudget, config.minKept)
|
|
5550
|
+
};
|
|
5551
|
+
}
|
|
5552
|
+
var SUMMARIZER_SYSTEM_PROMPT = `You are compressing a conversation between a user and an AI assistant into a
|
|
5553
|
+
concise memory summary. The summary will replace the original messages in the
|
|
5554
|
+
conversation history; the assistant will read it on subsequent turns to
|
|
5555
|
+
maintain continuity.
|
|
5556
|
+
|
|
5557
|
+
Preserve in the summary:
|
|
5558
|
+
- User preferences and constraints the user stated (coding style, tone,
|
|
5559
|
+
skill level, goals).
|
|
5560
|
+
- Decisions made and rejected alternatives ("we chose X over Y because Z").
|
|
5561
|
+
- Current task state (what's in progress, what's been completed).
|
|
5562
|
+
- Any facts the user might reasonably reference later.
|
|
5563
|
+
|
|
5564
|
+
If the messages below contain a prior summary, incorporate its content into
|
|
5565
|
+
your new summary \u2014 do not drop information from earlier summaries.
|
|
5566
|
+
|
|
5567
|
+
Keep the summary under 2000 tokens. Write as a factual note to future-you,
|
|
5568
|
+
not as a narrative. Use terse bullet points where possible.`;
|
|
5569
|
+
function formatTranscript(messages) {
|
|
5570
|
+
return messages.map((m) => {
|
|
5571
|
+
const label = m.role === "user" ? "User" : m.role === "assistant" ? "Assistant" : "System";
|
|
5572
|
+
const tools = Array.isArray(m.parts) ? m.parts.filter((p) => p?.type === "tool-invocation").map((p) => {
|
|
5573
|
+
const name = p.toolInvocation?.toolName;
|
|
5574
|
+
return ` [tool: ${name ?? "unknown"}]`;
|
|
5575
|
+
}).join("\n") : "";
|
|
5576
|
+
return `${label}: ${m.content}${tools ? "\n" + tools : ""}`;
|
|
5577
|
+
}).join("\n\n");
|
|
5578
|
+
}
|
|
5579
|
+
function makeDefaultSummarizer(env, options = {}) {
|
|
5580
|
+
return async (messages) => {
|
|
5581
|
+
const anthropic = createDeepSpaceAI(env, "anthropic", { authToken: options.authToken });
|
|
5582
|
+
const { text } = await generateText({
|
|
5583
|
+
// Stable alias — provider bug-fix snapshots roll forward without code change.
|
|
5584
|
+
model: anthropic("claude-haiku-4-5"),
|
|
5585
|
+
// 2500 gives the model room to finish a sentence after hitting the
|
|
5586
|
+
// "under 2000 tokens" soft limit in the prompt.
|
|
5587
|
+
maxOutputTokens: 2500,
|
|
5588
|
+
system: SUMMARIZER_SYSTEM_PROMPT,
|
|
5589
|
+
messages: [{ role: "user", content: formatTranscript(messages) }]
|
|
5590
|
+
});
|
|
5591
|
+
return text;
|
|
5592
|
+
};
|
|
5593
|
+
}
|
|
5594
|
+
|
|
5595
|
+
// src/server/utils/chat-history.ts
|
|
5596
|
+
async function executeTool2(stub, userId, tool, params) {
|
|
5597
|
+
const res = await stub.fetch(new Request("https://internal/api/tools/execute", {
|
|
5598
|
+
method: "POST",
|
|
5599
|
+
headers: {
|
|
5600
|
+
"Content-Type": "application/json",
|
|
5601
|
+
"X-User-Id": userId,
|
|
5602
|
+
"X-App-Action": "true"
|
|
5603
|
+
},
|
|
5604
|
+
body: JSON.stringify({ tool, params })
|
|
5605
|
+
}));
|
|
5606
|
+
const body = await res.json();
|
|
5607
|
+
if (!body.success) {
|
|
5608
|
+
throw new Error(`chat-history ${tool} failed: ${body.error ?? "unknown error"}`);
|
|
5609
|
+
}
|
|
5610
|
+
return body.data;
|
|
5611
|
+
}
|
|
5612
|
+
function toChatRow(env) {
|
|
5613
|
+
return {
|
|
5614
|
+
id: env.recordId,
|
|
5615
|
+
userId: env.data.userId,
|
|
5616
|
+
title: env.data.title ?? "",
|
|
5617
|
+
model: env.data.model,
|
|
5618
|
+
compactedSummary: env.data.compactedSummary,
|
|
5619
|
+
compactedThroughId: env.data.compactedThroughId,
|
|
5620
|
+
createdAt: env.createdAt,
|
|
5621
|
+
updatedAt: env.updatedAt
|
|
5622
|
+
};
|
|
5623
|
+
}
|
|
5624
|
+
function toMessageRow(env) {
|
|
5625
|
+
return {
|
|
5626
|
+
id: env.recordId,
|
|
5627
|
+
chatId: env.data.chatId,
|
|
5628
|
+
userId: env.data.userId,
|
|
5629
|
+
role: env.data.role,
|
|
5630
|
+
content: env.data.content ?? "",
|
|
5631
|
+
parts: env.data.parts,
|
|
5632
|
+
createdAt: env.createdAt
|
|
5633
|
+
};
|
|
5634
|
+
}
|
|
5635
|
+
async function getChat(stub, chatId, userId) {
|
|
5636
|
+
try {
|
|
5637
|
+
const result = await executeTool2(stub, userId, "records.get", {
|
|
5638
|
+
collection: "ai-chats",
|
|
5639
|
+
recordId: chatId
|
|
5640
|
+
});
|
|
5641
|
+
return result.record ? toChatRow(result.record) : null;
|
|
5642
|
+
} catch (err) {
|
|
5643
|
+
if (err instanceof Error && err.message.includes("Record not found")) return null;
|
|
5644
|
+
throw err;
|
|
5645
|
+
}
|
|
5646
|
+
}
|
|
5647
|
+
async function createChat(stub, userId, opts = {}) {
|
|
5648
|
+
const data = { userId };
|
|
5649
|
+
if (opts.title !== void 0) data.title = opts.title;
|
|
5650
|
+
if (opts.model !== void 0) data.model = opts.model;
|
|
5651
|
+
const result = await executeTool2(stub, userId, "records.create", {
|
|
5652
|
+
collection: "ai-chats",
|
|
5653
|
+
data
|
|
5654
|
+
});
|
|
5655
|
+
return toChatRow(result.record);
|
|
5656
|
+
}
|
|
5657
|
+
async function updateChat(stub, chatId, userId, patch) {
|
|
5658
|
+
await executeTool2(stub, userId, "records.update", {
|
|
5659
|
+
collection: "ai-chats",
|
|
5660
|
+
recordId: chatId,
|
|
5661
|
+
data: patch
|
|
5662
|
+
});
|
|
5663
|
+
}
|
|
5664
|
+
async function deleteChatCascade(stub, chatId, userId) {
|
|
5665
|
+
const list = await executeTool2(stub, userId, "records.query", {
|
|
5666
|
+
collection: "ai-messages",
|
|
5667
|
+
where: { chatId }
|
|
5668
|
+
});
|
|
5669
|
+
const errors = [];
|
|
5670
|
+
for (const env of list.records) {
|
|
5671
|
+
try {
|
|
5672
|
+
await executeTool2(stub, userId, "records.delete", {
|
|
5673
|
+
collection: "ai-messages",
|
|
5674
|
+
recordId: env.recordId
|
|
5675
|
+
});
|
|
5676
|
+
} catch (err) {
|
|
5677
|
+
errors.push(err);
|
|
5678
|
+
}
|
|
5679
|
+
}
|
|
5680
|
+
try {
|
|
5681
|
+
await executeTool2(stub, userId, "records.delete", {
|
|
5682
|
+
collection: "ai-chats",
|
|
5683
|
+
recordId: chatId
|
|
5684
|
+
});
|
|
5685
|
+
} catch (err) {
|
|
5686
|
+
errors.push(err);
|
|
5687
|
+
}
|
|
5688
|
+
if (errors.length > 0) {
|
|
5689
|
+
const first = errors[0];
|
|
5690
|
+
throw new Error(
|
|
5691
|
+
`deleteChatCascade: ${errors.length} delete(s) failed; first: ${first instanceof Error ? first.message : String(first)}`,
|
|
5692
|
+
{ cause: errors }
|
|
5693
|
+
);
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
async function loadMessages(stub, chatId, userId) {
|
|
5697
|
+
const result = await executeTool2(stub, userId, "records.query", {
|
|
5698
|
+
collection: "ai-messages",
|
|
5699
|
+
where: { chatId, userId },
|
|
5700
|
+
orderBy: "createdAt",
|
|
5701
|
+
orderDir: "asc"
|
|
5702
|
+
});
|
|
5703
|
+
return result.records.map(toMessageRow);
|
|
5704
|
+
}
|
|
5705
|
+
async function appendMessage(stub, msg) {
|
|
5706
|
+
const data = {
|
|
5707
|
+
chatId: msg.chatId,
|
|
5708
|
+
userId: msg.userId,
|
|
5709
|
+
role: msg.role,
|
|
5710
|
+
content: msg.content
|
|
5711
|
+
};
|
|
5712
|
+
if (msg.parts !== void 0) data.parts = msg.parts;
|
|
5713
|
+
await executeTool2(stub, msg.userId, "records.create", {
|
|
5714
|
+
collection: "ai-messages",
|
|
5715
|
+
recordId: msg.id,
|
|
5716
|
+
data
|
|
5717
|
+
});
|
|
5718
|
+
}
|
|
5290
5719
|
export {
|
|
5720
|
+
AI_CHATS_SCHEMA,
|
|
5721
|
+
AI_MESSAGES_SCHEMA,
|
|
5291
5722
|
Awareness,
|
|
5292
5723
|
BASE_USERS_SCHEMA,
|
|
5293
5724
|
BUILT_IN_TOOLS,
|
|
@@ -5298,6 +5729,7 @@ export {
|
|
|
5298
5729
|
CONVERSATION_SCHEMAS,
|
|
5299
5730
|
CanvasRoom,
|
|
5300
5731
|
CronRoom,
|
|
5732
|
+
DEFAULT_CONTEXT_CONFIG,
|
|
5301
5733
|
DEFAULT_DO_MANIFEST,
|
|
5302
5734
|
DEFAULT_MAX_SKEW_MS,
|
|
5303
5735
|
DIRECTORY_SCHEMAS,
|
|
@@ -5330,20 +5762,25 @@ export {
|
|
|
5330
5762
|
YjsRoom,
|
|
5331
5763
|
analyzePermissions,
|
|
5332
5764
|
apiWorkerFetch,
|
|
5765
|
+
appendMessage,
|
|
5766
|
+
applySlidingWindow,
|
|
5333
5767
|
authWorkerFetch,
|
|
5334
5768
|
buildCronContext,
|
|
5335
5769
|
buildInternalPayload,
|
|
5336
5770
|
buildTableSelect,
|
|
5771
|
+
buildUiParts,
|
|
5337
5772
|
canCreate,
|
|
5338
5773
|
canDelete,
|
|
5339
5774
|
canRead,
|
|
5340
5775
|
canUpdate,
|
|
5776
|
+
capToolResultSize,
|
|
5341
5777
|
checkFieldPermissions,
|
|
5342
5778
|
clientBuild,
|
|
5343
5779
|
coerceValue,
|
|
5344
5780
|
collectionTableName,
|
|
5345
5781
|
columnId,
|
|
5346
5782
|
computeHmacHex,
|
|
5783
|
+
createChat,
|
|
5347
5784
|
createDecoder,
|
|
5348
5785
|
createDeepSpaceAI,
|
|
5349
5786
|
createDeepSpaceAuth,
|
|
@@ -5351,12 +5788,14 @@ export {
|
|
|
5351
5788
|
createScopedR2Handler,
|
|
5352
5789
|
dataToColumnValues,
|
|
5353
5790
|
decodeJwtPayload,
|
|
5791
|
+
deleteChatCascade,
|
|
5354
5792
|
dispatch,
|
|
5355
5793
|
encode,
|
|
5356
5794
|
encodeAwarenessMessage,
|
|
5357
5795
|
encodeSyncStep1,
|
|
5358
5796
|
encodeSyncStep2,
|
|
5359
5797
|
encodeUpdate,
|
|
5798
|
+
getChat,
|
|
5360
5799
|
getGlobalDOSchemas,
|
|
5361
5800
|
getGlobalDOType,
|
|
5362
5801
|
getMessageType,
|
|
@@ -5365,8 +5804,11 @@ export {
|
|
|
5365
5804
|
handleSyncMessage,
|
|
5366
5805
|
hasContent,
|
|
5367
5806
|
isOwner,
|
|
5807
|
+
loadMessages,
|
|
5808
|
+
makeDefaultSummarizer,
|
|
5368
5809
|
noopPermissionContext,
|
|
5369
5810
|
platformWorkerFetch,
|
|
5811
|
+
prepareMessagesWithCompaction,
|
|
5370
5812
|
readVarUint,
|
|
5371
5813
|
readVarUint8Array,
|
|
5372
5814
|
resolveColumn,
|
|
@@ -5375,6 +5817,11 @@ export {
|
|
|
5375
5817
|
signInternalPayload,
|
|
5376
5818
|
timingSafeEqualHex,
|
|
5377
5819
|
toUint8Array,
|
|
5820
|
+
totalChars,
|
|
5821
|
+
truncateOldToolResults,
|
|
5822
|
+
turnsToCoreMessages,
|
|
5823
|
+
unwrapToolOutput,
|
|
5824
|
+
updateChat,
|
|
5378
5825
|
verifyInternalSignature,
|
|
5379
5826
|
verifyJwt,
|
|
5380
5827
|
workspaceAccountsSchema,
|