deepspace 0.10.0 → 0.10.1

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/worker.js CHANGED
@@ -340,16 +340,6 @@ var ROLE_ANONYMOUS = "viewer";
340
340
  var ROLE_DEFAULT = "member";
341
341
  var ROLE_ADMIN = "admin";
342
342
 
343
- // src/shared/users-schema.ts
344
- var USERS_COLUMNS = [
345
- { name: "email", storage: "text", interpretation: "plain" },
346
- { name: "name", storage: "text", interpretation: "plain" },
347
- { name: "imageUrl", storage: "text", interpretation: "plain" },
348
- { name: "role", storage: "text", interpretation: "plain" },
349
- { name: "createdAt", storage: "text", interpretation: { kind: "datetime" } },
350
- { name: "lastSeenAt", storage: "text", interpretation: { kind: "datetime" } }
351
- ];
352
-
353
343
  // src/server/schemas/registry.ts
354
344
  function collectionTableName(name) {
355
345
  return `c_${name.replace(/[^a-zA-Z0-9_]/g, "_")}`;
@@ -550,6 +540,14 @@ var SYSTEM_MANAGED_COLUMNS = /* @__PURE__ */ new Set([
550
540
  "createdAt",
551
541
  "lastSeenAt"
552
542
  ]);
543
+ var USERS_COLUMNS = [
544
+ { name: "email", storage: "text", interpretation: "plain" },
545
+ { name: "name", storage: "text", interpretation: "plain" },
546
+ { name: "imageUrl", storage: "text", interpretation: "plain" },
547
+ { name: "role", storage: "text", interpretation: "plain" },
548
+ { name: "createdAt", storage: "text", interpretation: { kind: "datetime" } },
549
+ { name: "lastSeenAt", storage: "text", interpretation: { kind: "datetime" } }
550
+ ];
553
551
  var BASE_USERS_SCHEMA = {
554
552
  name: "users",
555
553
  columns: [...USERS_COLUMNS],
@@ -2176,11 +2174,11 @@ async function handleToolsRequest(ctx, request, path) {
2176
2174
  }
2177
2175
  if (path.startsWith("tools/describe/")) {
2178
2176
  const toolName = path.replace("tools/describe/", "");
2179
- const tool3 = BUILT_IN_TOOLS.find((t) => t.name === toolName);
2180
- if (!tool3) {
2177
+ const tool2 = BUILT_IN_TOOLS.find((t) => t.name === toolName);
2178
+ if (!tool2) {
2181
2179
  return Response.json({ error: `Tool not found: ${toolName}` }, { status: 404, headers: CORS_HEADERS });
2182
2180
  }
2183
- return Response.json({ tool: tool3 }, { headers: CORS_HEADERS });
2181
+ return Response.json({ tool: tool2 }, { headers: CORS_HEADERS });
2184
2182
  }
2185
2183
  if (path.startsWith("tools/execute") && request.method === "POST") {
2186
2184
  return handleToolExecute(ctx, request);
@@ -2197,8 +2195,8 @@ async function handleToolExecute(ctx, request) {
2197
2195
  { status: 400, headers: CORS_HEADERS }
2198
2196
  );
2199
2197
  }
2200
- const { tool: tool3, params = {} } = body;
2201
- if (!tool3) {
2198
+ const { tool: tool2, params = {} } = body;
2199
+ if (!tool2) {
2202
2200
  return Response.json(
2203
2201
  { success: false, error: 'Missing "tool" in request body' },
2204
2202
  { status: 400, headers: CORS_HEADERS }
@@ -2215,8 +2213,8 @@ async function handleToolExecute(ctx, request) {
2215
2213
  userRole = user.role;
2216
2214
  }
2217
2215
  }
2218
- if (tool3.startsWith("yjs.")) {
2219
- const result2 = executeYjsTool(ctx, tool3, params, userId, userRole);
2216
+ if (tool2.startsWith("yjs.")) {
2217
+ const result2 = executeYjsTool(ctx, tool2, params, userId, userRole);
2220
2218
  const status2 = result2.success ? 200 : result2.error?.includes("not found") ? 404 : 400;
2221
2219
  return Response.json(result2, { status: status2, headers: CORS_HEADERS });
2222
2220
  }
@@ -2227,7 +2225,7 @@ async function handleToolExecute(ctx, request) {
2227
2225
  getPermissionContext: ctx.getPermissionContext,
2228
2226
  send: ctx.send
2229
2227
  };
2230
- const result = await executeTool(recordCtx, tool3, params, userId, userRole, isAppAction);
2228
+ const result = await executeTool(recordCtx, tool2, params, userId, userRole, isAppAction);
2231
2229
  const status = result.success ? 200 : result.error?.includes("not found") ? 404 : 400;
2232
2230
  return Response.json(result, { status, headers: CORS_HEADERS });
2233
2231
  }
@@ -6024,170 +6022,6 @@ function validateAppMigrationIds(value) {
6024
6022
  return { valid: true, ids };
6025
6023
  }
6026
6024
 
6027
- // src/shared/ai-models.ts
6028
- var DEEPSPACE_MODEL_CATALOG_PROVENANCE = {
6029
- version: "2026-08-03",
6030
- verifiedAt: "2026-08-03",
6031
- sources: {
6032
- anthropic: "https://platform.claude.com/docs/en/api/beta/models/list",
6033
- openai: "https://developers.openai.com/api/docs/models/all",
6034
- cerebras: "https://inference-docs.cerebras.ai/models/overview"
6035
- }
6036
- };
6037
- var MULTI_STEP_AGENT_PROFILES = ["application", "documentation"];
6038
- function createMultiStepModelFactory(provider) {
6039
- return (model) => ({
6040
- ...model,
6041
- ...provider,
6042
- agentSupport: "multi-step",
6043
- agentProfiles: MULTI_STEP_AGENT_PROFILES
6044
- });
6045
- }
6046
- var anthropicModel = createMultiStepModelFactory({
6047
- provider: "anthropic",
6048
- providerLabel: "Anthropic",
6049
- transport: "messages"
6050
- });
6051
- var openAIModel = createMultiStepModelFactory({
6052
- provider: "openai",
6053
- providerLabel: "OpenAI",
6054
- transport: "chat-completions"
6055
- });
6056
- var DEEPSPACE_AI_MODELS = [
6057
- anthropicModel({
6058
- id: "claude-fable-5",
6059
- label: "Claude Fable 5",
6060
- family: "Claude 5",
6061
- recommendation: "frontier"
6062
- }),
6063
- anthropicModel({
6064
- id: "claude-opus-5",
6065
- label: "Claude Opus 5",
6066
- family: "Claude 5",
6067
- recommendation: "frontier"
6068
- }),
6069
- anthropicModel({
6070
- id: "claude-sonnet-5",
6071
- label: "Claude Sonnet 5",
6072
- family: "Claude 5",
6073
- recommendation: "balanced"
6074
- }),
6075
- anthropicModel({
6076
- id: "claude-haiku-4-5",
6077
- label: "Claude Haiku 4.5",
6078
- family: "Claude 4.5",
6079
- recommendation: "fast"
6080
- }),
6081
- openAIModel({
6082
- id: "gpt-5.6-sol",
6083
- label: "GPT-5.6 Sol",
6084
- family: "GPT-5.6",
6085
- recommendation: "frontier"
6086
- }),
6087
- openAIModel({
6088
- id: "gpt-5.6-terra",
6089
- label: "GPT-5.6 Terra",
6090
- family: "GPT-5.6",
6091
- recommendation: "balanced"
6092
- }),
6093
- openAIModel({
6094
- id: "gpt-5.6-luna",
6095
- label: "GPT-5.6 Luna",
6096
- family: "GPT-5.6",
6097
- recommendation: "fast"
6098
- }),
6099
- {
6100
- id: "gpt-oss-120b",
6101
- label: "GPT-OSS 120B",
6102
- provider: "cerebras",
6103
- providerLabel: "Cerebras",
6104
- family: "GPT-OSS",
6105
- agentSupport: "single-step",
6106
- agentProfiles: [],
6107
- transport: "chat-completions",
6108
- recommendation: "limited",
6109
- note: "Available for direct generation; the current proxy adapter has not passed multi-step tool-result continuation."
6110
- }
6111
- ];
6112
- var DEEPSPACE_AI_DEFAULTS = {
6113
- agent: "claude-sonnet-5",
6114
- directGeneration: "claude-sonnet-5",
6115
- summarization: "claude-haiku-4-5"
6116
- };
6117
- var DEEPSPACE_AGENT_PROFILES = {
6118
- application: {
6119
- id: "application",
6120
- defaultModel: DEEPSPACE_AI_DEFAULTS.agent,
6121
- maxSteps: 5,
6122
- allowedTools: "application-defined"
6123
- },
6124
- documentation: {
6125
- id: "documentation",
6126
- defaultModel: DEEPSPACE_AI_DEFAULTS.agent,
6127
- // Permit up to twenty completed read-only tools plus one final synthesis
6128
- // step. The runner disables tools once the tool-call budget is exhausted.
6129
- maxSteps: 21,
6130
- maxToolCalls: 20,
6131
- allowedTools: ["docs_search", "docs_read"]
6132
- }
6133
- };
6134
- function getDeepSpaceAIModel(modelId) {
6135
- if (typeof modelId !== "string") return null;
6136
- return DEEPSPACE_AI_MODELS.find((model) => model.id === modelId) ?? null;
6137
- }
6138
- function listDeepSpaceAgentModels(profileId = "application") {
6139
- const defaultModel = DEEPSPACE_AGENT_PROFILES[profileId].defaultModel;
6140
- return DEEPSPACE_AI_MODELS.filter(
6141
- (model) => model.agentProfiles.includes(profileId)
6142
- ).sort((left, right) => Number(right.id === defaultModel) - Number(left.id === defaultModel));
6143
- }
6144
- function resolveDeepSpaceAgentModel(modelId, profileId = "application") {
6145
- const profile = DEEPSPACE_AGENT_PROFILES[profileId];
6146
- const resolvedId = modelId === void 0 ? profile.defaultModel : modelId;
6147
- const model = getDeepSpaceAIModel(resolvedId);
6148
- if (!model || !model.agentProfiles.includes(profileId)) return null;
6149
- return { modelId: model.id, provider: model.provider, model, profile };
6150
- }
6151
-
6152
- // src/shared/docs-routing.ts
6153
- var DOCS_RESOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
6154
- "7z",
6155
- "avif",
6156
- "css",
6157
- "csv",
6158
- "gif",
6159
- "gz",
6160
- "ico",
6161
- "jpeg",
6162
- "jpg",
6163
- "js",
6164
- "json",
6165
- "map",
6166
- "md",
6167
- "mjs",
6168
- "mp3",
6169
- "mp4",
6170
- "pdf",
6171
- "png",
6172
- "svg",
6173
- "tar",
6174
- "txt",
6175
- "wasm",
6176
- "webm",
6177
- "webp",
6178
- "woff",
6179
- "woff2",
6180
- "xml",
6181
- "yaml",
6182
- "yml",
6183
- "zip"
6184
- ]);
6185
- function isDocsResourcePath(pathname) {
6186
- const leaf = pathname.slice(pathname.lastIndexOf("/") + 1);
6187
- const extension = leaf.includes(".") ? leaf.slice(leaf.lastIndexOf(".") + 1).toLowerCase() : "";
6188
- return extension !== "" && DOCS_RESOURCE_EXTENSIONS.has(extension);
6189
- }
6190
-
6191
6025
  // src/server/utils/cors.ts
6192
6026
  function matchOrigin(origin, patterns) {
6193
6027
  if (!origin) return null;
@@ -6559,7 +6393,7 @@ function authWorkerFetch(env, path, init) {
6559
6393
  function buildCronContext(env, ownerUserId, roomId = "default") {
6560
6394
  const roomIdObj = env.RECORD_ROOMS.idFromName(roomId);
6561
6395
  const room = env.RECORD_ROOMS.get(roomIdObj);
6562
- async function executeTool3(tool3, params) {
6396
+ async function executeTool3(tool2, params) {
6563
6397
  const response = await room.fetch(
6564
6398
  new Request("https://internal/api/tools/execute", {
6565
6399
  method: "POST",
@@ -6568,12 +6402,12 @@ function buildCronContext(env, ownerUserId, roomId = "default") {
6568
6402
  "X-User-Id": ownerUserId,
6569
6403
  "X-App-Action": "true"
6570
6404
  },
6571
- body: JSON.stringify({ tool: tool3, params })
6405
+ body: JSON.stringify({ tool: tool2, params })
6572
6406
  })
6573
6407
  );
6574
6408
  const result = await response.json();
6575
6409
  if (!result.success) {
6576
- throw new Error(`RecordRoom tool ${tool3} failed: ${result.error || "Unknown error"}`);
6410
+ throw new Error(`RecordRoom tool ${tool2} failed: ${result.error || "Unknown error"}`);
6577
6411
  }
6578
6412
  return result.data;
6579
6413
  }
@@ -6695,158 +6529,6 @@ function createDeepSpaceAI(env, provider, options = {}) {
6695
6529
  }
6696
6530
  }
6697
6531
 
6698
- // src/server/utils/agent.ts
6699
- import {
6700
- stepCountIs,
6701
- streamText
6702
- } from "ai";
6703
- var DeepSpaceAgentModelError = class extends Error {
6704
- constructor(modelId, profile) {
6705
- super(
6706
- `Model ${typeof modelId === "string" ? JSON.stringify(modelId) : String(modelId)} is not compatible with the ${profile} agent profile`
6707
- );
6708
- this.modelId = modelId;
6709
- this.profile = profile;
6710
- this.name = "DeepSpaceAgentModelError";
6711
- }
6712
- code = "unsupported_agent_model";
6713
- };
6714
- var DeepSpaceAgentProfileError = class extends Error {
6715
- constructor(profile, toolName) {
6716
- super(`The ${profile} agent profile does not allow tool ${JSON.stringify(toolName)}`);
6717
- this.profile = profile;
6718
- this.toolName = toolName;
6719
- this.name = "DeepSpaceAgentProfileError";
6720
- }
6721
- code = "agent_profile_violation";
6722
- };
6723
- function streamDeepSpaceAgent(env, options) {
6724
- const { profile, modelId, authToken, ...streamOptions } = options;
6725
- const selection = resolveDeepSpaceAgentModel(modelId, profile);
6726
- if (!selection) throw new DeepSpaceAgentModelError(modelId, profile);
6727
- if (selection.profile.allowedTools !== "application-defined") {
6728
- const allowed = selection.profile.allowedTools;
6729
- for (const toolName of Object.keys(streamOptions.tools ?? {})) {
6730
- if (!allowed.includes(toolName)) {
6731
- throw new DeepSpaceAgentProfileError(profile, toolName);
6732
- }
6733
- }
6734
- }
6735
- const provider = createDeepSpaceAI(
6736
- env,
6737
- selection.provider,
6738
- authToken ? { authToken } : {}
6739
- );
6740
- const { prepareStep, tools, ...remainingStreamOptions } = streamOptions;
6741
- const boundedTools = limitToolExecutions(tools, selection.profile.maxToolCalls);
6742
- const result = streamText({
6743
- ...remainingStreamOptions,
6744
- ...boundedTools ? { tools: boundedTools } : {},
6745
- model: provider(selection.modelId),
6746
- stopWhen: stepCountIs(selection.profile.maxSteps),
6747
- prepareStep: enforceToolCallLimit(prepareStep, selection.profile.maxToolCalls),
6748
- ...selection.provider === "openai" ? { providerOptions: { openai: { reasoningEffort: "none" } } } : {}
6749
- });
6750
- return { selection, result };
6751
- }
6752
- function enforceToolCallLimit(prepareStep, maxToolCalls) {
6753
- if (maxToolCalls === void 0) return prepareStep;
6754
- return async (context) => {
6755
- const prepared = await prepareStep?.(context);
6756
- const completedToolCalls = context.steps.reduce(
6757
- (count, step) => count + step.toolCalls.length,
6758
- 0
6759
- );
6760
- if (completedToolCalls < maxToolCalls) return prepared;
6761
- return { ...prepared, activeTools: [], toolChoice: "none" };
6762
- };
6763
- }
6764
- function limitToolExecutions(tools, maxToolCalls) {
6765
- if (!tools || maxToolCalls === void 0) return tools;
6766
- let executions = 0;
6767
- return Object.fromEntries(Object.entries(tools).map(([name, definition]) => {
6768
- if (typeof definition.execute !== "function") return [name, definition];
6769
- const execute = definition.execute;
6770
- return [name, {
6771
- ...definition,
6772
- execute: (...args) => {
6773
- if (executions >= maxToolCalls) {
6774
- return Promise.resolve({
6775
- error: `The agent tool-call limit of ${maxToolCalls} has been reached`
6776
- });
6777
- }
6778
- executions++;
6779
- return execute(...args);
6780
- }
6781
- }];
6782
- }));
6783
- }
6784
- function deepSpaceAgentErrorSummary(error, context = {}) {
6785
- const details = [];
6786
- const contextFields = [
6787
- context.profile ? `profile=${context.profile}` : void 0,
6788
- context.provider ? `provider=${safeLogToken(context.provider)}` : void 0,
6789
- context.modelId ? `model=${safeLogToken(context.modelId)}` : void 0
6790
- ].filter((part) => Boolean(part));
6791
- if (contextFields.length > 0) details.push(contextFields.join(" "));
6792
- const pending = [error];
6793
- const visited = /* @__PURE__ */ new Set();
6794
- while (pending.length > 0 && details.length < 8) {
6795
- const current = pending.shift();
6796
- if (current == null || visited.has(current)) continue;
6797
- visited.add(current);
6798
- if (typeof current === "object") {
6799
- const record = current;
6800
- const parts = [
6801
- typeof record.name === "string" ? `name=${safeLogToken(record.name)}` : current instanceof Error ? `name=${safeLogToken(current.name)}` : void 0,
6802
- safeErrorMessage(current, record),
6803
- typeof record.statusCode === "number" ? `status=${record.statusCode}` : void 0,
6804
- typeof record.code === "string" ? `code=${safeLogToken(record.code)}` : void 0,
6805
- typeof record.requestId === "string" ? `requestId=${safeLogToken(record.requestId)}` : void 0,
6806
- ...safeProviderResponseMetadata(record.responseBody)
6807
- ].filter((part) => Boolean(part));
6808
- details.push(parts.join(" ") || Object.prototype.toString.call(current));
6809
- if (record.lastError != null) pending.push(record.lastError);
6810
- if (record.cause != null) pending.push(record.cause);
6811
- if (Array.isArray(record.errors)) pending.push(...record.errors);
6812
- continue;
6813
- }
6814
- details.push(String(current));
6815
- }
6816
- return details.join(" <- ") || "Unknown error";
6817
- }
6818
- function safeErrorMessage(current, record) {
6819
- if (record.responseBody !== void 0) return void 0;
6820
- const message = current instanceof Error ? current.message : record.message;
6821
- if (typeof message !== "string" || !message.trim()) return void 0;
6822
- return `message=${safeLogText(message)}`;
6823
- }
6824
- function safeProviderResponseMetadata(responseBody) {
6825
- if (typeof responseBody !== "string") return [];
6826
- try {
6827
- const parsed = JSON.parse(responseBody);
6828
- const error = parsed.error && typeof parsed.error === "object" ? parsed.error : void 0;
6829
- const code = typeof error?.code === "string" ? error.code : typeof error?.type === "string" ? error.type : void 0;
6830
- const requestId = typeof parsed.request_id === "string" ? parsed.request_id : void 0;
6831
- return [
6832
- code ? `upstreamCode=${safeLogToken(code)}` : void 0,
6833
- requestId ? `upstreamRequestId=${safeLogToken(requestId)}` : void 0
6834
- ].filter((part) => Boolean(part));
6835
- } catch {
6836
- return [];
6837
- }
6838
- }
6839
- function safeLogToken(value) {
6840
- return value.replace(/[^a-zA-Z0-9._:/-]/g, "_").slice(0, 120);
6841
- }
6842
- function safeLogText(value) {
6843
- const withoutControlCharacters = Array.from(value, (character) => {
6844
- const codePoint = character.codePointAt(0) ?? 0;
6845
- return codePoint <= 31 || codePoint === 127 ? " " : character;
6846
- }).join("");
6847
- return withoutControlCharacters.replace(/\bBearer\s+[A-Za-z0-9._~+/=-]+/gi, "Bearer [redacted]").replace(/\b(api[_ -]?key|authorization|password|secret|token)\b\s*[:=]\s*\S+/gi, "$1=[redacted]").trim().slice(0, 300);
6848
- }
6849
-
6850
6532
  // src/server/utils/composio-tools.ts
6851
6533
  import { tool, jsonSchema } from "ai";
6852
6534
  var EMPTY_SCHEMA = { type: "object", properties: {} };
@@ -7283,11 +6965,10 @@ function formatTranscript(messages) {
7283
6965
  }
7284
6966
  function makeDefaultSummarizer(env, options = {}) {
7285
6967
  return async (messages) => {
7286
- const model = getDeepSpaceAIModel(DEEPSPACE_AI_DEFAULTS.summarization);
7287
- if (!model) throw new Error("DeepSpace summarization model is missing from the catalog");
7288
- const provider = createDeepSpaceAI(env, model.provider, { authToken: options.authToken });
6968
+ const anthropic = createDeepSpaceAI(env, "anthropic", { authToken: options.authToken });
7289
6969
  const { text } = await generateText({
7290
- model: provider(model.id),
6970
+ // Stable alias — provider bug-fix snapshots roll forward without code change.
6971
+ model: anthropic("claude-haiku-4-5"),
7291
6972
  // 2500 gives the model room to finish a sentence after hitting the
7292
6973
  // "under 2000 tokens" soft limit in the prompt.
7293
6974
  maxOutputTokens: 2500,
@@ -7299,7 +6980,7 @@ function makeDefaultSummarizer(env, options = {}) {
7299
6980
  }
7300
6981
 
7301
6982
  // src/server/utils/chat-history.ts
7302
- async function executeTool2(stub, userId, tool3, params) {
6983
+ async function executeTool2(stub, userId, tool2, params) {
7303
6984
  const res = await stub.fetch(new Request("https://internal/api/tools/execute", {
7304
6985
  method: "POST",
7305
6986
  headers: {
@@ -7307,11 +6988,11 @@ async function executeTool2(stub, userId, tool3, params) {
7307
6988
  "X-User-Id": userId,
7308
6989
  "X-App-Action": "true"
7309
6990
  },
7310
- body: JSON.stringify({ tool: tool3, params })
6991
+ body: JSON.stringify({ tool: tool2, params })
7311
6992
  }));
7312
6993
  const body = await res.json();
7313
6994
  if (!body.success) {
7314
- throw new Error(`chat-history ${tool3} failed: ${body.error ?? "unknown error"}`);
6995
+ throw new Error(`chat-history ${tool2} failed: ${body.error ?? "unknown error"}`);
7315
6996
  }
7316
6997
  return body.data;
7317
6998
  }
@@ -7423,1002 +7104,6 @@ async function appendMessage(stub, msg) {
7423
7104
  });
7424
7105
  }
7425
7106
 
7426
- // src/server/utils/docs-assistant.ts
7427
- import { tool as tool2 } from "ai";
7428
- import { z } from "zod/v4";
7429
- var MAX_CHUNKS = 1e4;
7430
- var MAX_CHUNK_CHARS = 2500;
7431
- var MAX_CORPUS_CHARS = 12e6;
7432
- var SEARCH_STOP_WORDS = /* @__PURE__ */ new Set([
7433
- "a",
7434
- "about",
7435
- "an",
7436
- "and",
7437
- "are",
7438
- "can",
7439
- "could",
7440
- "do",
7441
- "does",
7442
- "for",
7443
- "from",
7444
- "has",
7445
- "have",
7446
- "how",
7447
- "i",
7448
- "in",
7449
- "is",
7450
- "it",
7451
- "me",
7452
- "my",
7453
- "of",
7454
- "on",
7455
- "or",
7456
- "our",
7457
- "should",
7458
- "the",
7459
- "this",
7460
- "to",
7461
- "was",
7462
- "we",
7463
- "were",
7464
- "what",
7465
- "when",
7466
- "where",
7467
- "which",
7468
- "will",
7469
- "with",
7470
- "would",
7471
- "you",
7472
- "your"
7473
- ]);
7474
- var indexedChunkCache = /* @__PURE__ */ new WeakMap();
7475
- function parseDocsCorpus(value) {
7476
- if (!Array.isArray(value)) throw new Error("Docs assistant index must be an array");
7477
- if (value.length > MAX_CHUNKS) {
7478
- throw new Error(`Docs assistant index exceeds ${MAX_CHUNKS} chunks`);
7479
- }
7480
- const chunks = [];
7481
- let totalChars2 = 0;
7482
- for (let index = 0; index < value.length; index++) {
7483
- const raw = value[index];
7484
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
7485
- throw new Error(`Docs assistant chunk ${index} must be an object`);
7486
- }
7487
- const chunk = raw;
7488
- if (typeof chunk.id !== "string" || !chunk.id || typeof chunk.route !== "string" || !chunk.route.startsWith("/") || typeof chunk.title !== "string" || !chunk.title || typeof chunk.text !== "string" || !chunk.text) {
7489
- throw new Error(`Docs assistant chunk ${index} has invalid required fields`);
7490
- }
7491
- if (chunk.text.length > MAX_CHUNK_CHARS) {
7492
- throw new Error(`Docs assistant chunk ${chunk.id} exceeds ${MAX_CHUNK_CHARS} characters`);
7493
- }
7494
- totalChars2 += chunk.text.length;
7495
- if (totalChars2 > MAX_CORPUS_CHARS) {
7496
- throw new Error(`Docs assistant corpus exceeds ${MAX_CORPUS_CHARS} characters`);
7497
- }
7498
- chunks.push({
7499
- id: chunk.id,
7500
- route: chunk.route,
7501
- title: chunk.title,
7502
- ...typeof chunk.heading === "string" && chunk.heading ? { heading: chunk.heading } : {},
7503
- text: chunk.text
7504
- });
7505
- }
7506
- return chunks;
7507
- }
7508
- function searchDocsCorpus(corpus, query, limit = 6) {
7509
- const normalized = normalize(query);
7510
- const terms = [
7511
- ...new Set(
7512
- normalized.split(" ").filter((term) => term.length > 1 && !SEARCH_STOP_WORDS.has(term))
7513
- )
7514
- ];
7515
- if (!terms.length) return [];
7516
- const requiredTerms = new Set(terms);
7517
- return corpus.map((chunk) => {
7518
- const { text, textTerms, title, titleTerms } = indexChunk(chunk);
7519
- const textCounts = countTerms(textTerms, requiredTerms);
7520
- let score = 0;
7521
- if (title === normalized) score += 120;
7522
- else if (title.includes(normalized)) score += 55;
7523
- if (text.includes(normalized)) score += 30;
7524
- for (const term of terms) {
7525
- if (titleTerms.has(term)) score += 14;
7526
- score += Math.min(6, textCounts.get(term) ?? 0) * 3;
7527
- }
7528
- const matchedTerms = terms.filter(
7529
- (term) => titleTerms.has(term) || textCounts.has(term)
7530
- ).length;
7531
- score += matchedTerms * matchedTerms * 4;
7532
- score += proximityBonus([...titleTerms, ...textTerms], terms);
7533
- return {
7534
- route: chunk.route,
7535
- title: chunk.title,
7536
- ...chunk.heading ? { heading: chunk.heading } : {},
7537
- excerpt: excerpt(chunk.text, terms),
7538
- score
7539
- };
7540
- }).filter((result) => result.score > 0).sort((left, right) => right.score - left.score || left.route.localeCompare(right.route)).slice(0, Math.max(1, Math.min(limit, 10)));
7541
- }
7542
- function readDocsRoute(corpus, route) {
7543
- const normalizedRoute = normalizeDocsRoute(route);
7544
- return corpus.filter((chunk) => chunk.route === normalizedRoute).slice(0, 12).map(({ route: chunkRoute, title, heading, text }) => ({
7545
- route: chunkRoute,
7546
- title,
7547
- ...heading ? { heading } : {},
7548
- text
7549
- }));
7550
- }
7551
- function buildDocsAssistantTools(corpus) {
7552
- return {
7553
- docs_search: tool2({
7554
- description: "Search the current documentation. Use this before answering factual or how-to questions.",
7555
- inputSchema: z.object({
7556
- query: z.string().trim().min(2).max(300),
7557
- limit: z.number().int().min(1).max(10).optional()
7558
- }),
7559
- execute: async ({ query, limit }) => ({
7560
- results: searchDocsCorpus(corpus, query, limit ?? 6)
7561
- })
7562
- }),
7563
- docs_read: tool2({
7564
- description: "Read bounded source chunks for one exact documentation route returned by docs_search.",
7565
- inputSchema: z.object({ route: z.string().trim().startsWith("/").max(500) }),
7566
- execute: async ({ route }) => ({
7567
- route: normalizeDocsRoute(route),
7568
- chunks: readDocsRoute(corpus, route)
7569
- })
7570
- })
7571
- };
7572
- }
7573
- function buildDocsAssistantPrompt(appName, currentRoute) {
7574
- return [
7575
- `You are the public documentation assistant for "${appName}" on DeepSpace.`,
7576
- "Answer only from the documentation available through docs_search and docs_read.",
7577
- "Search before answering unless the user is only greeting you.",
7578
- "Use docs_read when search excerpts are insufficient or ambiguous.",
7579
- "Never claim access to application records, integrations, private data, or mutation tools.",
7580
- "If the documentation does not support an answer, say so plainly and suggest the closest documented page.",
7581
- "Cite factual answers with Markdown links to the exact documentation routes returned by tools.",
7582
- "Do not invent URLs, APIs, configuration keys, versions, or behavior.",
7583
- "Keep answers concise, practical, and explicit about uncertainty.",
7584
- ...currentRoute ? [`The reader is currently viewing ${normalizeDocsRoute(currentRoute)}.`] : []
7585
- ].join("\n");
7586
- }
7587
- function normalize(value) {
7588
- return value.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, " ").trim().split(" ").filter(Boolean).map(canonicalSearchTerm).join(" ");
7589
- }
7590
- function canonicalSearchTerm(term) {
7591
- if (SEARCH_STOP_WORDS.has(term)) return term;
7592
- if (["doc", "docs", "document", "documents", "documentation"].includes(term)) return "docs";
7593
- if (["builds", "building", "built", "compile", "compiled", "compiles", "compiling"].includes(term)) {
7594
- return "build";
7595
- }
7596
- return term.length > 3 && term.endsWith("s") && !term.endsWith("ss") ? term.slice(0, -1) : term;
7597
- }
7598
- function indexChunk(chunk) {
7599
- const cached = indexedChunkCache.get(chunk);
7600
- if (cached) return cached;
7601
- const title = normalize(`${chunk.title} ${chunk.heading ?? ""}`);
7602
- const text = normalize(chunk.text);
7603
- const indexed = {
7604
- text,
7605
- textTerms: text.split(" "),
7606
- title,
7607
- titleTerms: new Set(title.split(" "))
7608
- };
7609
- indexedChunkCache.set(chunk, indexed);
7610
- return indexed;
7611
- }
7612
- function normalizeDocsRoute(value) {
7613
- let route = `/${value}`.replace(/\/{2,}/g, "/");
7614
- if (route.length > 1) route = route.replace(/\/$/, "");
7615
- return route;
7616
- }
7617
- function countTerms(tokens, required) {
7618
- const counts = /* @__PURE__ */ new Map();
7619
- for (const token of tokens) {
7620
- if (required.has(token)) counts.set(token, (counts.get(token) ?? 0) + 1);
7621
- }
7622
- return counts;
7623
- }
7624
- function proximityBonus(tokens, terms) {
7625
- const required = new Set(terms);
7626
- if (required.size < 2) return 0;
7627
- const counts = /* @__PURE__ */ new Map();
7628
- let matched = 0;
7629
- let start = 0;
7630
- let smallestWindow = Number.POSITIVE_INFINITY;
7631
- for (let end = 0; end < tokens.length; end++) {
7632
- const token = tokens[end] ?? "";
7633
- if (required.has(token)) {
7634
- const count = counts.get(token) ?? 0;
7635
- counts.set(token, count + 1);
7636
- if (count === 0) matched++;
7637
- }
7638
- while (matched === required.size && start <= end) {
7639
- smallestWindow = Math.min(smallestWindow, end - start + 1);
7640
- const first = tokens[start] ?? "";
7641
- if (required.has(first)) {
7642
- const count = counts.get(first) ?? 0;
7643
- counts.set(first, count - 1);
7644
- if (count === 1) matched--;
7645
- }
7646
- start++;
7647
- }
7648
- }
7649
- return Number.isFinite(smallestWindow) ? Math.max(0, 42 - smallestWindow * 2) : 0;
7650
- }
7651
- function excerpt(text, terms) {
7652
- const lower = text.toLowerCase();
7653
- const first = terms.map((term) => lower.indexOf(term)).filter((index) => index >= 0).sort((left, right) => left - right)[0] ?? 0;
7654
- const start = Math.max(0, first - 160);
7655
- const end = Math.min(text.length, start + 520);
7656
- return `${start > 0 ? "\u2026" : ""}${text.slice(start, end).trim()}${end < text.length ? "\u2026" : ""}`;
7657
- }
7658
-
7659
- // src/server/utils/docs-assistant-limiter.ts
7660
- var WINDOW_MS = 6e4;
7661
- var CLIENT_REQUESTS_PER_WINDOW = 12;
7662
- var APP_REQUESTS_PER_WINDOW = 120;
7663
- var MAX_CONCURRENT_REQUESTS = 4;
7664
- var LEASE_TTL_MS = 2 * 6e4;
7665
- var DocsAssistantLimiter = class {
7666
- sql;
7667
- constructor(state) {
7668
- this.sql = state.storage.sql;
7669
- this.sql.exec(`
7670
- CREATE TABLE IF NOT EXISTS request_windows (
7671
- scope TEXT NOT NULL,
7672
- client_key TEXT NOT NULL,
7673
- window INTEGER NOT NULL,
7674
- count INTEGER NOT NULL,
7675
- PRIMARY KEY (scope, client_key, window)
7676
- );
7677
- CREATE TABLE IF NOT EXISTS leases (
7678
- id TEXT PRIMARY KEY,
7679
- expires_at INTEGER NOT NULL
7680
- );
7681
- `);
7682
- }
7683
- async fetch(request) {
7684
- const url = new URL(request.url);
7685
- if (request.method !== "POST") return Response.json({ error: "method_not_allowed" }, { status: 405 });
7686
- if (url.pathname === "/acquire") return this.acquire(request);
7687
- if (url.pathname === "/release") return this.release(request);
7688
- return Response.json({ error: "not_found" }, { status: 404 });
7689
- }
7690
- async acquire(request) {
7691
- const body = await request.json().catch(() => null);
7692
- if (!body || typeof body.clientKey !== "string" || body.clientKey.length !== 64) {
7693
- return Response.json({ error: "invalid_client_key" }, { status: 400 });
7694
- }
7695
- const now = Date.now();
7696
- const window = Math.floor(now / WINDOW_MS);
7697
- this.sql.exec("DELETE FROM request_windows WHERE window < ?", window - 1);
7698
- this.sql.exec("DELETE FROM leases WHERE expires_at <= ?", now);
7699
- if (!this.consumeWindow("client", body.clientKey, window, CLIENT_REQUESTS_PER_WINDOW)) {
7700
- return Response.json({ ok: false, reason: "client_rate" }, { status: 429 });
7701
- }
7702
- if (!this.consumeWindow("app", "all", window, APP_REQUESTS_PER_WINDOW)) {
7703
- return Response.json({ ok: false, reason: "app_rate" }, { status: 429 });
7704
- }
7705
- const concurrent = this.sql.exec("SELECT COUNT(*) AS count FROM leases").one().count;
7706
- if (concurrent >= MAX_CONCURRENT_REQUESTS) {
7707
- return Response.json({ ok: false, reason: "app_concurrency" }, { status: 429 });
7708
- }
7709
- const leaseId = crypto.randomUUID();
7710
- this.sql.exec("INSERT INTO leases (id, expires_at) VALUES (?, ?)", leaseId, now + LEASE_TTL_MS);
7711
- return Response.json({ ok: true, leaseId });
7712
- }
7713
- async release(request) {
7714
- const body = await request.json().catch(() => null);
7715
- if (!body || typeof body.leaseId !== "string") {
7716
- return Response.json({ error: "invalid_lease_id" }, { status: 400 });
7717
- }
7718
- this.sql.exec("DELETE FROM leases WHERE id = ?", body.leaseId);
7719
- return Response.json({ ok: true });
7720
- }
7721
- consumeWindow(scope, clientKey, window, limit) {
7722
- const existing = this.sql.exec(
7723
- "SELECT count FROM request_windows WHERE scope = ? AND client_key = ? AND window = ?",
7724
- scope,
7725
- clientKey,
7726
- window
7727
- ).toArray()[0]?.count ?? 0;
7728
- if (existing >= limit) return false;
7729
- this.sql.exec(
7730
- `INSERT INTO request_windows (scope, client_key, window, count)
7731
- VALUES (?, ?, ?, 1)
7732
- ON CONFLICT(scope, client_key, window) DO UPDATE SET count = count + 1`,
7733
- scope,
7734
- clientKey,
7735
- window
7736
- );
7737
- return true;
7738
- }
7739
- };
7740
-
7741
- // src/server/utils/docs-published-corpus.ts
7742
- var cachedCorpus;
7743
- async function loadDocsPublishedManifest(env, requestUrl = "https://assets.local/") {
7744
- const response = await env.ASSETS.fetch(new URL("/_docs/manifest.json", requestUrl).toString());
7745
- if (!response.ok) return null;
7746
- const value = await response.json().catch(() => null);
7747
- if (!value || typeof value !== "object" || Array.isArray(value)) return null;
7748
- const manifest = value;
7749
- const assistant = parseAssistantPolicy(manifest.assistant);
7750
- if (typeof manifest.sourceHash !== "string" || typeof manifest.name !== "string" || !assistant) return null;
7751
- return {
7752
- sourceHash: manifest.sourceHash,
7753
- name: manifest.name,
7754
- assistant,
7755
- // Older docs artifacts did not carry an MCP policy. Fail closed until the
7756
- // docs bundle is rebuilt by an MCP-aware SDK release.
7757
- mcp: parseMcpPolicy(manifest.mcp) ?? { access: "disabled" }
7758
- };
7759
- }
7760
- async function loadDocsPublishedCorpus(env, sourceHash, requestUrl = "https://assets.local/") {
7761
- if (cachedCorpus?.sourceHash === sourceHash) return cachedCorpus.chunks;
7762
- const response = await env.ASSETS.fetch(
7763
- new URL("/_docs/assistant-index.json", requestUrl).toString()
7764
- );
7765
- if (!response.ok) throw new Error(`assistant-index.json returned ${response.status}`);
7766
- const chunks = parseDocsCorpus(await response.json());
7767
- cachedCorpus = { sourceHash, chunks };
7768
- return chunks;
7769
- }
7770
- async function resolveDocsPublishedCorpus(env, sourceHash, requestUrl = "https://assets.local/") {
7771
- try {
7772
- return { ok: true, chunks: await loadDocsPublishedCorpus(env, sourceHash, requestUrl) };
7773
- } catch (error) {
7774
- return { ok: false, error };
7775
- }
7776
- }
7777
- async function readDocsPublishedPage(env, corpus, requestedRoute, requestUrl = "https://assets.local/") {
7778
- const route = normalizeDocsRoute(requestedRoute.split("#", 1)[0] ?? "/");
7779
- const firstChunk = corpus.find((chunk) => chunk.route === route);
7780
- if (!firstChunk) return null;
7781
- const pathname = route === "/" ? "/_docs/index.md" : `/_docs${route}.md`;
7782
- const response = await env.ASSETS.fetch(new URL(pathname, requestUrl).toString());
7783
- if (!response.ok) return null;
7784
- const markdown = await response.text();
7785
- if (markdown.length > 5e5) throw new Error("Documentation page exceeds 500000 characters");
7786
- return { route, title: firstChunk.title, markdown };
7787
- }
7788
- function parseAssistantPolicy(value) {
7789
- if (!value || typeof value !== "object" || Array.isArray(value)) return null;
7790
- const policy = value;
7791
- if (!["disabled", "public", "authenticated"].includes(String(policy.access))) return null;
7792
- return {
7793
- access: policy.access,
7794
- ...typeof policy.model === "string" ? { model: policy.model } : {}
7795
- };
7796
- }
7797
- function parseMcpPolicy(value) {
7798
- if (!value || typeof value !== "object" || Array.isArray(value)) return null;
7799
- const policy = value;
7800
- if (!["disabled", "public"].includes(String(policy.access))) return null;
7801
- return { access: policy.access };
7802
- }
7803
-
7804
- // src/server/utils/docs-public-limiter.ts
7805
- async function docsPublicClientKey(value) {
7806
- const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
7807
- return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
7808
- }
7809
- async function acquireDocsPublicLease(env, clientKey, logPrefix) {
7810
- if (!env.DOCS_ASSISTANT_LIMITER) return { ok: false, status: 503 };
7811
- const id = env.DOCS_ASSISTANT_LIMITER.idFromName(env.DEEPSPACE_APP_ID);
7812
- const stub = env.DOCS_ASSISTANT_LIMITER.get(id);
7813
- const response = await stub.fetch("https://docs-limiter/acquire", {
7814
- method: "POST",
7815
- headers: { "Content-Type": "application/json" },
7816
- body: JSON.stringify({ clientKey })
7817
- }).catch((error) => {
7818
- console.error(`[${logPrefix}] limiter unavailable:`, error);
7819
- return null;
7820
- });
7821
- if (!response?.ok) {
7822
- return { ok: false, status: response?.status === 429 ? 429 : 503 };
7823
- }
7824
- const body = await response.json().catch(() => null);
7825
- if (!body || typeof body.leaseId !== "string") return { ok: false, status: 503 };
7826
- return { ok: true, lease: { leaseId: body.leaseId, stub } };
7827
- }
7828
- async function releaseDocsPublicLease(lease, logPrefix) {
7829
- if (!lease) return;
7830
- await lease.stub.fetch("https://docs-limiter/release", {
7831
- method: "POST",
7832
- headers: { "Content-Type": "application/json" },
7833
- body: JSON.stringify({ leaseId: lease.leaseId })
7834
- }).catch((error) => console.error(`[${logPrefix}] limiter release failed:`, error));
7835
- }
7836
-
7837
- // src/server/utils/request-body.ts
7838
- var RequestBodyTooLargeError = class extends Error {
7839
- constructor(maxBytes) {
7840
- super(`Request body exceeds ${maxBytes} bytes`);
7841
- this.maxBytes = maxBytes;
7842
- this.name = "RequestBodyTooLargeError";
7843
- }
7844
- };
7845
- async function readBoundedRequestText(request, maxBytes) {
7846
- if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) {
7847
- throw new TypeError("maxBytes must be a positive safe integer");
7848
- }
7849
- const declared = request.headers.get("content-length");
7850
- if (declared && /^\d+$/.test(declared.trim()) && Number(declared) > maxBytes) {
7851
- throw new RequestBodyTooLargeError(maxBytes);
7852
- }
7853
- if (!request.body) return "";
7854
- const reader = request.body.getReader();
7855
- const decoder = new TextDecoder();
7856
- let bytes = 0;
7857
- let text = "";
7858
- while (true) {
7859
- const chunk = await reader.read();
7860
- if (chunk.done) break;
7861
- bytes += chunk.value.byteLength;
7862
- if (bytes > maxBytes) {
7863
- await reader.cancel().catch(() => void 0);
7864
- throw new RequestBodyTooLargeError(maxBytes);
7865
- }
7866
- text += decoder.decode(chunk.value, { stream: true });
7867
- }
7868
- return text + decoder.decode();
7869
- }
7870
-
7871
- // src/server/utils/docs-assistant-routes.ts
7872
- var MAX_QUESTION_CHARS = 4e3;
7873
- var MAX_HISTORY_MESSAGES = 12;
7874
- var MAX_HISTORY_CHARS = 2e4;
7875
- var MAX_REQUEST_BYTES = 128 * 1024;
7876
- function registerDocsAssistantRoutes(app, resolveAuth) {
7877
- app.post("/api/ai/docs", async (c) => {
7878
- if (c.req.header("x-deepspace-surface") !== "docs") return c.notFound();
7879
- const manifest = await loadDocsPublishedManifest(c.env, c.req.url);
7880
- if (!manifest || manifest.assistant.access === "disabled") return c.notFound();
7881
- let authToken;
7882
- let publicClientKey;
7883
- if (manifest.assistant.access === "authenticated") {
7884
- const auth = await resolveAuth(c.req.raw, c.env);
7885
- if (!auth) return c.json({ error: "Sign in required" }, 401);
7886
- const header = c.req.header("Authorization") ?? "";
7887
- if (!header.startsWith("Bearer ")) return c.json({ error: "Sign in required" }, 401);
7888
- authToken = header.slice(7);
7889
- } else {
7890
- if (!c.env.APP_OWNER_JWT) {
7891
- return c.json({ error: "Public documentation assistant billing is not configured" }, 503);
7892
- }
7893
- publicClientKey = await docsPublicClientKey(c.req.header("CF-Connecting-IP") ?? "unknown");
7894
- }
7895
- let body = null;
7896
- try {
7897
- const raw = await readBoundedRequestText(c.req.raw, MAX_REQUEST_BYTES);
7898
- const parsed = JSON.parse(raw);
7899
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
7900
- body = parsed;
7901
- }
7902
- } catch (error) {
7903
- if (error instanceof RequestBodyTooLargeError) {
7904
- return c.json({ error: `request exceeds ${MAX_REQUEST_BYTES} bytes` }, 413);
7905
- }
7906
- return c.json({ error: "request body must be valid JSON" }, 400);
7907
- }
7908
- const question = typeof body?.question === "string" ? body.question.trim() : "";
7909
- if (!question) return c.json({ error: "question is required" }, 400);
7910
- if (question.length > MAX_QUESTION_CHARS) {
7911
- return c.json({ error: `question exceeds ${MAX_QUESTION_CHARS} characters` }, 413);
7912
- }
7913
- const route = typeof body?.route === "string" && body.route.startsWith("/") ? body.route.slice(0, 500) : void 0;
7914
- let history;
7915
- try {
7916
- history = normalizeDocsAssistantHistory(body?.messages);
7917
- } catch (error) {
7918
- return c.json({ error: error instanceof Error ? error.message : "messages are invalid" }, 400);
7919
- }
7920
- const corpusResult = await resolveDocsPublishedCorpus(c.env, manifest.sourceHash, c.req.url);
7921
- if (!corpusResult.ok) {
7922
- console.error("[docs-assistant] corpus unavailable:", corpusResult.error);
7923
- return c.json({ error: "Documentation corpus is unavailable" }, 503);
7924
- }
7925
- const corpus = corpusResult.chunks;
7926
- const selectedModel = resolveDeepSpaceAgentModel(
7927
- manifest.assistant.model,
7928
- "documentation"
7929
- );
7930
- if (!selectedModel) {
7931
- console.error("[docs-assistant] unsupported configured model:", manifest.assistant.model);
7932
- return c.json({ error: "Documentation assistant model is not supported" }, 503);
7933
- }
7934
- const diagnosticContext = {
7935
- profile: "documentation",
7936
- provider: selectedModel.provider,
7937
- modelId: selectedModel.modelId
7938
- };
7939
- if (publicClientKey && !c.env.DOCS_ASSISTANT_LIMITER) {
7940
- return c.json({ error: "Documentation assistant rate limiting is not configured" }, 503);
7941
- }
7942
- const leaseResult = publicClientKey ? await acquireDocsPublicLease(c.env, publicClientKey, "docs-assistant") : void 0;
7943
- if (leaseResult && !leaseResult.ok) {
7944
- return c.json(
7945
- {
7946
- error: leaseResult.status === 429 ? "Documentation assistant rate limit exceeded. Try again shortly." : "Documentation assistant is temporarily unavailable"
7947
- },
7948
- leaseResult.status,
7949
- leaseResult.status === 429 ? { "Retry-After": "60" } : void 0
7950
- );
7951
- }
7952
- const lease = leaseResult?.ok ? leaseResult.lease : void 0;
7953
- let released = false;
7954
- const releaseLease = async () => {
7955
- if (!lease || released) return;
7956
- released = true;
7957
- await releaseDocsPublicLease(lease, "docs-assistant");
7958
- };
7959
- let result;
7960
- try {
7961
- result = streamDeepSpaceAgent(c.env, {
7962
- profile: "documentation",
7963
- modelId: selectedModel.modelId,
7964
- ...authToken ? { authToken } : {},
7965
- system: buildDocsAssistantPrompt(manifest.name || c.env.APP_NAME, route),
7966
- messages: [...history, { role: "user", content: question }],
7967
- tools: buildDocsAssistantTools(corpus),
7968
- abortSignal: c.req.raw.signal,
7969
- onAbort: () => releaseLease(),
7970
- onFinish: releaseLease,
7971
- onError: ({ error }) => {
7972
- console.error(
7973
- `[docs-assistant] stream error: ${deepSpaceAgentErrorSummary(error, diagnosticContext)}`
7974
- );
7975
- void releaseLease();
7976
- }
7977
- }).result;
7978
- } catch (error) {
7979
- console.error(
7980
- `[docs-assistant] agent unavailable: ${deepSpaceAgentErrorSummary(error, diagnosticContext)}`
7981
- );
7982
- await releaseLease();
7983
- return c.json({ error: "Documentation assistant is not configured" }, 503);
7984
- }
7985
- return result.toUIMessageStreamResponse({
7986
- sendReasoning: false,
7987
- onError: (error) => {
7988
- console.error(
7989
- `[docs-assistant] response error: ${deepSpaceAgentErrorSummary(error, diagnosticContext)}`
7990
- );
7991
- void releaseLease();
7992
- return "The documentation assistant could not complete this response.";
7993
- }
7994
- });
7995
- });
7996
- }
7997
- var docsAssistantErrorSummary = deepSpaceAgentErrorSummary;
7998
- function normalizeDocsAssistantHistory(value) {
7999
- if (value === void 0) return [];
8000
- if (!Array.isArray(value)) throw new TypeError("messages must be an array");
8001
- if (value.length > MAX_HISTORY_MESSAGES) {
8002
- throw new TypeError(`messages exceeds ${MAX_HISTORY_MESSAGES} turns`);
8003
- }
8004
- const messages = [];
8005
- let totalChars2 = 0;
8006
- for (const [index, item] of value.entries()) {
8007
- if (!item || typeof item !== "object" || Array.isArray(item)) {
8008
- throw new TypeError(`messages[${index}] must be an object`);
8009
- }
8010
- const candidate = item;
8011
- const expectedRole = index % 2 === 0 ? "user" : "assistant";
8012
- if (candidate.role !== expectedRole) {
8013
- throw new TypeError(`messages[${index}].role must be ${expectedRole}`);
8014
- }
8015
- const content = typeof candidate.content === "string" ? candidate.content.trim() : "";
8016
- if (!content) throw new TypeError(`messages[${index}].content is required`);
8017
- if (content.length > MAX_QUESTION_CHARS) {
8018
- throw new TypeError(`messages[${index}].content exceeds ${MAX_QUESTION_CHARS} characters`);
8019
- }
8020
- totalChars2 += content.length;
8021
- if (totalChars2 > MAX_HISTORY_CHARS) {
8022
- throw new TypeError(`messages exceeds ${MAX_HISTORY_CHARS} characters`);
8023
- }
8024
- messages.push({ role: expectedRole, content });
8025
- }
8026
- if (messages.length % 2 !== 0) {
8027
- throw new TypeError("messages must end with a completed assistant response");
8028
- }
8029
- return messages;
8030
- }
8031
- function registerDocsStaticRoutes(app) {
8032
- app.get("/_docs/*", async (c) => {
8033
- const pathname = new URL(c.req.url).pathname;
8034
- let response = await c.env.ASSETS.fetch(c.req.raw);
8035
- let status = response.status;
8036
- if (status === 404) {
8037
- const url = new URL(c.req.url);
8038
- url.pathname = "/_docs/404.html";
8039
- response = await c.env.ASSETS.fetch(new Request(url.toString(), c.req.raw));
8040
- status = 404;
8041
- }
8042
- return secureDocsResponse(response, status, pathname);
8043
- });
8044
- }
8045
- function secureDocsResponse(response, status, pathname) {
8046
- const headers = new Headers(response.headers);
8047
- if (status !== 404 && pathname.endsWith(".md")) {
8048
- headers.set("Content-Type", "text/markdown; charset=utf-8");
8049
- }
8050
- if (headers.get("Content-Type")?.toLowerCase().includes("text/html")) {
8051
- const cacheControl = headers.get("Cache-Control") ?? "public, max-age=0, must-revalidate";
8052
- if (!/(?:^|,)\s*no-transform(?:\s*,|$)/i.test(cacheControl)) {
8053
- headers.set("Cache-Control", `${cacheControl}, no-transform`);
8054
- }
8055
- }
8056
- headers.set("X-Content-Type-Options", "nosniff");
8057
- headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
8058
- headers.set(
8059
- "Content-Security-Policy",
8060
- "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self' data: https:; connect-src 'self' https:; object-src 'none'; base-uri 'none'; frame-ancestors 'none'; form-action 'self'"
8061
- );
8062
- return new Response(response.body, { status, headers });
8063
- }
8064
-
8065
- // src/server/utils/docs-mcp/protocol.ts
8066
- var MCP_SERVER_VERSION = "1.0.0";
8067
- var CURRENT_PROTOCOL_VERSION = "2025-11-25";
8068
- var SUPPORTED_PROTOCOL_VERSIONS = /* @__PURE__ */ new Set([CURRENT_PROTOCOL_VERSION, "2025-06-18", "2025-03-26"]);
8069
- function initializeResponse(request) {
8070
- const params = objectValue(request.params);
8071
- const requested = typeof params?.protocolVersion === "string" ? params.protocolVersion : CURRENT_PROTOCOL_VERSION;
8072
- const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.has(requested) ? requested : CURRENT_PROTOCOL_VERSION;
8073
- return mcpResult(request.id, {
8074
- protocolVersion,
8075
- capabilities: {
8076
- tools: { listChanged: false },
8077
- resources: { subscribe: false, listChanged: false }
8078
- },
8079
- serverInfo: {
8080
- name: "DeepSpace Docs",
8081
- title: "DeepSpace documentation",
8082
- version: MCP_SERVER_VERSION
8083
- },
8084
- instructions: "Search the published docs before answering, then read exact pages when full context is needed."
8085
- });
8086
- }
8087
- function hasValidOrigin(request) {
8088
- const origin = request.headers.get("Origin");
8089
- if (!origin) return true;
8090
- try {
8091
- return new URL(origin).origin === new URL(request.url).origin;
8092
- } catch {
8093
- return false;
8094
- }
8095
- }
8096
- function parseRequest(raw) {
8097
- let value;
8098
- try {
8099
- value = JSON.parse(raw);
8100
- } catch {
8101
- return { ok: false, message: "Invalid JSON" };
8102
- }
8103
- const candidate = objectValue(value);
8104
- if (!candidate || candidate.jsonrpc !== "2.0" || typeof candidate.method !== "string") {
8105
- return { ok: false, message: "Invalid JSON-RPC request" };
8106
- }
8107
- if (candidate.id !== void 0 && candidate.id !== null && typeof candidate.id !== "string" && typeof candidate.id !== "number")
8108
- return { ok: false, message: "Invalid JSON-RPC id" };
8109
- return {
8110
- ok: true,
8111
- request: {
8112
- jsonrpc: "2.0",
8113
- method: candidate.method,
8114
- ...candidate.id !== void 0 ? { id: candidate.id } : {},
8115
- ...candidate.params !== void 0 ? { params: candidate.params } : {}
8116
- }
8117
- };
8118
- }
8119
- function objectValue(value) {
8120
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
8121
- }
8122
- function toolResult(id, value) {
8123
- return mcpResult(id, {
8124
- content: [{ type: "text", text: JSON.stringify(value) }],
8125
- structuredContent: value,
8126
- isError: false
8127
- });
8128
- }
8129
- function toolError(id, message) {
8130
- return mcpResult(id, {
8131
- content: [{ type: "text", text: message }],
8132
- isError: true
8133
- });
8134
- }
8135
- function mcpResult(id, result) {
8136
- return jsonResponse({ jsonrpc: "2.0", id, result });
8137
- }
8138
- function mcpError(id, code, message, status = 200, headers) {
8139
- return jsonResponse({ jsonrpc: "2.0", id, error: { code, message } }, status, headers);
8140
- }
8141
- function jsonResponse(value, status = 200, headers) {
8142
- return new Response(JSON.stringify(value), {
8143
- status,
8144
- headers: {
8145
- "Content-Type": "application/json; charset=utf-8",
8146
- ...mcpSecurityHeaders(),
8147
- ...headers
8148
- }
8149
- });
8150
- }
8151
- function mcpSecurityHeaders() {
8152
- return {
8153
- "Cache-Control": "no-store",
8154
- "X-Content-Type-Options": "nosniff",
8155
- "Referrer-Policy": "no-referrer"
8156
- };
8157
- }
8158
-
8159
- // src/server/utils/docs-mcp/tools.ts
8160
- var DOCS_TOOLS = [
8161
- {
8162
- name: "docs_search",
8163
- title: "Search documentation",
8164
- description: "Search the published documentation and return ranked, linked excerpts.",
8165
- inputSchema: {
8166
- type: "object",
8167
- properties: {
8168
- query: { type: "string", minLength: 2, maxLength: 300 },
8169
- limit: { type: "integer", minimum: 1, maximum: 10, default: 6 }
8170
- },
8171
- required: ["query"],
8172
- additionalProperties: false
8173
- },
8174
- outputSchema: {
8175
- type: "object",
8176
- properties: { results: { type: "array" } },
8177
- required: ["results"]
8178
- },
8179
- annotations: {
8180
- readOnlyHint: true,
8181
- destructiveHint: false,
8182
- idempotentHint: true,
8183
- openWorldHint: false
8184
- }
8185
- },
8186
- {
8187
- name: "docs_read",
8188
- title: "Read documentation page",
8189
- description: "Read one complete published documentation page as Markdown.",
8190
- inputSchema: {
8191
- type: "object",
8192
- properties: {
8193
- route: { type: "string", minLength: 1, maxLength: 500, pattern: "^/" }
8194
- },
8195
- required: ["route"],
8196
- additionalProperties: false
8197
- },
8198
- outputSchema: {
8199
- type: "object",
8200
- properties: {
8201
- route: { type: "string" },
8202
- title: { type: "string" },
8203
- url: { type: "string" },
8204
- markdown: { type: "string" }
8205
- },
8206
- required: ["route", "title", "url", "markdown"]
8207
- },
8208
- annotations: {
8209
- readOnlyHint: true,
8210
- destructiveHint: false,
8211
- idempotentHint: true,
8212
- openWorldHint: false
8213
- }
8214
- }
8215
- ];
8216
- async function callDocsTool(rawRequest, request, corpus, env) {
8217
- const params = objectValue(request.params);
8218
- const name = typeof params?.name === "string" ? params.name : "";
8219
- const args = objectValue(params?.arguments) ?? {};
8220
- const origin = new URL(rawRequest.url).origin;
8221
- if (name === "docs_search") {
8222
- const query = typeof args.query === "string" ? args.query.trim() : "";
8223
- const limit = args.limit === void 0 ? 6 : args.limit;
8224
- if (query.length < 2 || query.length > 300 || !Number.isInteger(limit) || Number(limit) < 1 || Number(limit) > 10) {
8225
- return mcpError(request.id, -32602, "Invalid docs_search arguments");
8226
- }
8227
- const value = {
8228
- results: searchDocsCorpus(corpus, query, Number(limit)).map((result) => ({
8229
- ...result,
8230
- url: new URL(result.route, origin).toString()
8231
- }))
8232
- };
8233
- return toolResult(request.id, value);
8234
- }
8235
- if (name === "docs_read") {
8236
- const route = typeof args.route === "string" ? args.route.trim() : "";
8237
- if (!route.startsWith("/") || route.length > 500) {
8238
- return mcpError(request.id, -32602, "Invalid docs_read arguments");
8239
- }
8240
- try {
8241
- const page = await readDocsPublishedPage(env, corpus, route, rawRequest.url);
8242
- if (!page) return toolError(request.id, `No published documentation page exists at ${route}`);
8243
- return toolResult(request.id, {
8244
- ...page,
8245
- url: new URL(page.route, origin).toString()
8246
- });
8247
- } catch (error) {
8248
- console.error("[docs-mcp] page unavailable:", error);
8249
- return toolError(request.id, "The documentation page could not be read");
8250
- }
8251
- }
8252
- return mcpError(request.id, -32602, `Unknown documentation tool: ${name || "<missing>"}`);
8253
- }
8254
-
8255
- // src/server/utils/docs-mcp-routes.ts
8256
- var MAX_REQUEST_CHARS = 64e3;
8257
- var MAX_REQUEST_BYTES2 = MAX_REQUEST_CHARS * 4;
8258
- var MAX_SKILL_CHARS = 256e3;
8259
- function registerDocsMcpRoutes(app) {
8260
- app.get("/mcp", async (c) => {
8261
- if (!await publicManifest(c.req.raw, c.env)) return c.notFound();
8262
- return new Response(null, {
8263
- status: 405,
8264
- headers: { Allow: "POST", ...mcpSecurityHeaders() }
8265
- });
8266
- });
8267
- app.post("/mcp", async (c) => {
8268
- const manifest = await publicManifest(c.req.raw, c.env);
8269
- if (!manifest) return c.notFound();
8270
- if (!hasValidOrigin(c.req.raw)) {
8271
- return mcpError(null, -32e3, "Invalid Origin", 403);
8272
- }
8273
- let raw;
8274
- try {
8275
- raw = await readBoundedRequestText(c.req.raw, MAX_REQUEST_BYTES2);
8276
- } catch (error) {
8277
- if (error instanceof RequestBodyTooLargeError) {
8278
- return mcpError(null, -32600, `Request exceeds ${MAX_REQUEST_BYTES2} bytes`, 413);
8279
- }
8280
- return mcpError(null, -32700, "Unable to read request body", 400);
8281
- }
8282
- if (raw.length > MAX_REQUEST_CHARS) {
8283
- return mcpError(null, -32600, `Request exceeds ${MAX_REQUEST_CHARS} characters`, 413);
8284
- }
8285
- const parsed = parseRequest(raw);
8286
- if (!parsed.ok) return mcpError(null, -32700, parsed.message, 400);
8287
- const request = parsed.request;
8288
- if (request.method !== "initialize") {
8289
- const protocolVersion = c.req.header("MCP-Protocol-Version");
8290
- if (protocolVersion && !SUPPORTED_PROTOCOL_VERSIONS.has(protocolVersion)) {
8291
- return mcpError(request.id ?? null, -32600, "Unsupported MCP-Protocol-Version", 400);
8292
- }
8293
- }
8294
- const requestId = request.id;
8295
- if (requestId === void 0) return new Response(null, { status: 202 });
8296
- const requestWithId = { ...request, id: requestId };
8297
- if (request.method === "initialize") return initializeResponse(requestWithId);
8298
- if (request.method === "ping") return mcpResult(requestId, {});
8299
- if (request.method === "tools/list") {
8300
- return mcpResult(requestId, { tools: DOCS_TOOLS });
8301
- }
8302
- if (request.method === "resources/list") {
8303
- return mcpResult(requestId, { resources: [skillResource(c.req.raw, manifest)] });
8304
- }
8305
- if (request.method === "resources/read") {
8306
- return readSkillResource(c.req.raw, requestWithId, manifest, c.env);
8307
- }
8308
- if (request.method !== "tools/call") {
8309
- return mcpError(requestId, -32601, `Method not found: ${request.method}`);
8310
- }
8311
- const corpusResult = await resolveDocsPublishedCorpus(c.env, manifest.sourceHash, c.req.url);
8312
- if (!corpusResult.ok) {
8313
- console.error("[docs-mcp] corpus unavailable:", corpusResult.error);
8314
- return mcpError(requestId, -32002, "Documentation corpus is unavailable", 503);
8315
- }
8316
- const corpus = corpusResult.chunks;
8317
- const clientKey = await docsPublicClientKey(c.req.header("CF-Connecting-IP") ?? "unknown");
8318
- const leaseResult = await acquireDocsPublicLease(c.env, clientKey, "docs-mcp");
8319
- if (!leaseResult.ok) {
8320
- return mcpError(
8321
- requestId,
8322
- leaseResult.status === 429 ? -32029 : -32002,
8323
- leaseResult.status === 429 ? "Documentation tool rate limit exceeded. Try again shortly." : "Documentation tools are temporarily unavailable",
8324
- leaseResult.status,
8325
- leaseResult.status === 429 ? { "Retry-After": "60" } : void 0
8326
- );
8327
- }
8328
- try {
8329
- return await callDocsTool(c.req.raw, requestWithId, corpus, c.env);
8330
- } finally {
8331
- await releaseDocsPublicLease(leaseResult.lease, "docs-mcp");
8332
- }
8333
- });
8334
- for (const path of [
8335
- "/.well-known/mcp",
8336
- "/.well-known/mcp.json",
8337
- "/.well-known/mcp/server-card.json"
8338
- ]) {
8339
- app.get(path, async (c) => {
8340
- const manifest = await publicManifest(c.req.raw, c.env);
8341
- if (!manifest) return c.notFound();
8342
- return discoveryResponse(c.req.raw, manifest);
8343
- });
8344
- }
8345
- app.get("/.well-known/mcp/server-cards.json", async (c) => {
8346
- const manifest = await publicManifest(c.req.raw, c.env);
8347
- if (!manifest) return c.notFound();
8348
- return jsonResponse({ servers: [serverCard(c.req.raw, manifest)] }, 200, {
8349
- "Cache-Control": "public, max-age=300"
8350
- });
8351
- });
8352
- }
8353
- async function readSkillResource(rawRequest, request, manifest, env) {
8354
- const params = objectValue(request.params);
8355
- const requestedUri = typeof params?.uri === "string" ? params.uri : "";
8356
- const resource = skillResource(rawRequest, manifest);
8357
- if (requestedUri !== resource.uri) {
8358
- return mcpError(request.id, -32602, "Unknown documentation resource");
8359
- }
8360
- const assetUrl = new URL("/_docs/skill.md", rawRequest.url);
8361
- const response = await env.ASSETS.fetch(new Request(assetUrl, { method: "GET" }));
8362
- if (!response.ok) return mcpError(request.id, -32002, "Documentation skill is unavailable", 503);
8363
- const text = await response.text();
8364
- if (text.length > MAX_SKILL_CHARS) {
8365
- return mcpError(request.id, -32002, "Documentation skill exceeds the published size limit", 503);
8366
- }
8367
- return mcpResult(request.id, {
8368
- contents: [{ uri: resource.uri, mimeType: resource.mimeType, text }]
8369
- });
8370
- }
8371
- function skillResource(request, manifest) {
8372
- return {
8373
- uri: new URL("/skill.md", request.url).toString(),
8374
- name: `${manifest.name} documentation skill`,
8375
- title: `Use ${manifest.name}`,
8376
- description: `Agent instructions grounded in the published ${manifest.name} documentation.`,
8377
- mimeType: "text/markdown"
8378
- };
8379
- }
8380
- async function publicManifest(request, env) {
8381
- if (request.headers.get("x-deepspace-surface") !== "docs") return null;
8382
- const manifest = await loadDocsPublishedManifest(env, request.url);
8383
- return manifest?.mcp.access === "public" ? manifest : null;
8384
- }
8385
- function discoveryResponse(request, manifest) {
8386
- return jsonResponse(serverCard(request, manifest), 200, {
8387
- "Cache-Control": "public, max-age=300"
8388
- });
8389
- }
8390
- function serverCard(request, manifest) {
8391
- return {
8392
- name: manifest.name,
8393
- description: `Search and read the published ${manifest.name} documentation.`,
8394
- version: MCP_SERVER_VERSION,
8395
- protocolVersion: CURRENT_PROTOCOL_VERSION,
8396
- transport: {
8397
- type: "streamable-http",
8398
- url: new URL("/mcp", request.url).toString()
8399
- },
8400
- authentication: { required: false },
8401
- capabilities: {
8402
- tools: DOCS_TOOLS.map(({ name, title, description }) => ({ name, title, description })),
8403
- resources: [skillResource(request, manifest)]
8404
- }
8405
- };
8406
- }
8407
-
8408
- // src/server/utils/docs-routes.ts
8409
- function registerDeepSpaceDocs(app, options) {
8410
- registerDocsAssistantRoutes(app, options.resolveAuth);
8411
- registerDocsMcpRoutes(app);
8412
- registerDocsStaticRoutes(app);
8413
- }
8414
- function docsAssistantLimiterManifestEntry(className) {
8415
- return {
8416
- binding: "DOCS_ASSISTANT_LIMITER",
8417
- className,
8418
- sqlite: true
8419
- };
8420
- }
8421
-
8422
7107
  // src/server/utils/metering.ts
8423
7108
  function meterUsage(env, kind, fields = {}) {
8424
7109
  const ds = env.USAGE_EVENTS;
@@ -8896,7 +7581,7 @@ function shouldThrottleClientError(now = Date.now()) {
8896
7581
  windowCount += 1;
8897
7582
  return windowCount > THROTTLE_MAX;
8898
7583
  }
8899
- function jsonResponse2(body, status) {
7584
+ function jsonResponse(body, status) {
8900
7585
  return new Response(JSON.stringify(body), {
8901
7586
  status,
8902
7587
  headers: { "Content-Type": "application/json" }
@@ -8912,16 +7597,16 @@ async function handleClientErrorReport(request) {
8912
7597
  }
8913
7598
  const declared = Number(request.headers.get("content-length"));
8914
7599
  if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) {
8915
- return jsonResponse2({ error: "payload_too_large" }, 413);
7600
+ return jsonResponse({ error: "payload_too_large" }, 413);
8916
7601
  }
8917
7602
  let body;
8918
7603
  try {
8919
7604
  body = await request.json();
8920
7605
  } catch {
8921
- return jsonResponse2({ error: "invalid_json" }, 400);
7606
+ return jsonResponse({ error: "invalid_json" }, 400);
8922
7607
  }
8923
7608
  const report = normalizeClientErrorReport(body);
8924
- if (!report) return jsonResponse2({ error: "invalid_report" }, 400);
7609
+ if (!report) return jsonResponse({ error: "invalid_report" }, 400);
8925
7610
  console.error(clientErrorToLogLine(report));
8926
7611
  return new Response(null, { status: 204 });
8927
7612
  }
@@ -8964,18 +7649,11 @@ export {
8964
7649
  COST_RATES,
8965
7650
  CanvasRoom,
8966
7651
  CronRoom,
8967
- DEEPSPACE_AGENT_PROFILES,
8968
- DEEPSPACE_AI_DEFAULTS,
8969
- DEEPSPACE_AI_MODELS,
8970
- DEEPSPACE_MODEL_CATALOG_PROVENANCE,
8971
7652
  DEFAULT_CONTEXT_CONFIG,
8972
7653
  DEFAULT_DO_MANIFEST,
8973
7654
  DEFAULT_QUERY_LIMIT,
8974
7655
  DEPLOYED_APPS_DEFAULTS,
8975
7656
  DIRECTORY_SCHEMAS,
8976
- DeepSpaceAgentModelError,
8977
- DeepSpaceAgentProfileError,
8978
- DocsAssistantLimiter,
8979
7657
  GLOBAL_DO_TYPES,
8980
7658
  GLOBAL_DO_TYPE_NAMES,
8981
7659
  GameRoom,
@@ -9011,7 +7689,6 @@ export {
9011
7689
  VOTING_SCHEMAS,
9012
7690
  WORKSPACE_SCHEMAS,
9013
7691
  YjsRoom,
9014
- acquireDocsPublicLease,
9015
7692
  analyzePermissions,
9016
7693
  apiWorkerFetch,
9017
7694
  appendMessage,
@@ -9020,8 +7697,6 @@ export {
9020
7697
  authWorkerFetch,
9021
7698
  bindingManifestFromOutputConfig,
9022
7699
  buildCronContext,
9023
- buildDocsAssistantPrompt,
9024
- buildDocsAssistantTools,
9025
7700
  buildTableSelect,
9026
7701
  buildUiParts,
9027
7702
  callRegistry,
@@ -9047,12 +7722,8 @@ export {
9047
7722
  createScopedR2Handler,
9048
7723
  dataToColumnValues,
9049
7724
  decodeJwtPayload,
9050
- deepSpaceAgentErrorSummary,
9051
7725
  deleteChatCascade,
9052
7726
  dispatch,
9053
- docsAssistantErrorSummary,
9054
- docsAssistantLimiterManifestEntry,
9055
- docsPublicClientKey,
9056
7727
  encode,
9057
7728
  encodeAwarenessMessage,
9058
7729
  encodeSyncStep1,
@@ -9060,7 +7731,6 @@ export {
9060
7731
  encodeUpdate,
9061
7732
  enqueueJob,
9062
7733
  getChat,
9063
- getDeepSpaceAIModel,
9064
7734
  getGlobalDOSchemas,
9065
7735
  getGlobalDOType,
9066
7736
  getMessageType,
@@ -9070,15 +7740,11 @@ export {
9070
7740
  handleSyncMessage,
9071
7741
  hasContent,
9072
7742
  isAutoProvision,
9073
- isDocsResourcePath,
9074
7743
  isOwner,
9075
7744
  isTestAccountClaims,
9076
7745
  isTestAccountEmail,
9077
7746
  isTestAccountTier,
9078
7747
  lintSchema,
9079
- listDeepSpaceAgentModels,
9080
- loadDocsPublishedCorpus,
9081
- loadDocsPublishedManifest,
9082
7748
  loadMessages,
9083
7749
  makeDefaultSummarizer,
9084
7750
  matchOrigin,
@@ -9086,35 +7752,21 @@ export {
9086
7752
  meterUsage,
9087
7753
  meterVectorize,
9088
7754
  noopPermissionContext,
9089
- normalizeDocsAssistantHistory,
9090
- normalizeDocsRoute,
9091
- parseDocsCorpus,
9092
7755
  parseQuotaLimit,
9093
7756
  platformCorsPatterns,
9094
7757
  platformWorkerFetch,
9095
7758
  prepareMessagesWithCompaction,
9096
7759
  priceBindingUsageEvent,
9097
- readDocsPublishedPage,
9098
- readDocsRoute,
9099
7760
  readVarUint,
9100
7761
  readVarUint8Array,
9101
7762
  registerClientErrorRoute,
9102
- registerDeepSpaceDocs,
9103
- registerDocsAssistantRoutes,
9104
- registerDocsMcpRoutes,
9105
- registerDocsStaticRoutes,
9106
7763
  registryErrorJson,
9107
7764
  registryStub,
9108
- releaseDocsPublicLease,
9109
7765
  resolveAppName,
9110
7766
  resolveColumn,
9111
- resolveDeepSpaceAgentModel,
9112
- resolveDocsPublishedCorpus,
9113
7767
  rowToData,
9114
7768
  runMigrations,
9115
- searchDocsCorpus,
9116
7769
  serverBuild,
9117
- streamDeepSpaceAgent,
9118
7770
  timingSafeEqualHex,
9119
7771
  timingSafeEqualStrings,
9120
7772
  toUint8Array,