deepspace 0.28.1 → 0.29.0
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/CHANGELOG.md +50 -0
- package/dist/{chunk-PVEUIQN4.js → chunk-ZWFH5HON.js} +2 -2
- package/dist/{chunk-PVEUIQN4.js.map → chunk-ZWFH5HON.js.map} +1 -1
- package/dist/cli.js +128 -81
- package/dist/cli.js.map +1 -1
- package/dist/documentation-client-core.js +1 -1
- package/dist/documentation-default-renderer.cjs +1 -1
- package/dist/documentation-react.js +1 -1
- package/dist/documentation-runtime.js +1 -1
- package/dist/documentation-server-core.js +1 -1
- package/dist/documentation.js +1 -1
- package/dist/documentation.js.map +1 -1
- package/dist/index.d.ts +56 -67
- package/dist/index.js +97 -129
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +0 -1
- package/dist/server.js +119 -31
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +72 -90
- package/dist/worker.js +219 -143
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
package/dist/worker.js
CHANGED
|
@@ -72,6 +72,116 @@ var ROLE_DEFAULT = "member";
|
|
|
72
72
|
var ROLE_ADMIN = "admin";
|
|
73
73
|
var RECORD_NOT_FOUND = "Record not found";
|
|
74
74
|
|
|
75
|
+
// src/shared/log-events.ts
|
|
76
|
+
var LOG_LEVELS = ["debug", "log", "info", "warn", "error"];
|
|
77
|
+
var APP_LOG_EVENT_KEYS = [
|
|
78
|
+
"id",
|
|
79
|
+
"timestamp",
|
|
80
|
+
"level",
|
|
81
|
+
"eventType",
|
|
82
|
+
"message",
|
|
83
|
+
"outcome",
|
|
84
|
+
"request",
|
|
85
|
+
"exception"
|
|
86
|
+
];
|
|
87
|
+
function logEventText(e) {
|
|
88
|
+
if (e.eventType === "exception" && e.exception) {
|
|
89
|
+
const where = e.request ? ` \u2014 ${e.request.method} ${e.request.path}` : "";
|
|
90
|
+
return `${e.exception.name}: ${e.exception.message}${where}`;
|
|
91
|
+
}
|
|
92
|
+
if (e.eventType === "request" && e.request) {
|
|
93
|
+
const status = e.request.status !== void 0 ? ` ${e.request.status}` : "";
|
|
94
|
+
const outcome = e.outcome && e.outcome !== "ok" ? ` (${e.outcome})` : "";
|
|
95
|
+
return `${e.request.method} ${e.request.path}${status}${outcome}`;
|
|
96
|
+
}
|
|
97
|
+
return e.message;
|
|
98
|
+
}
|
|
99
|
+
function loggableError(err) {
|
|
100
|
+
try {
|
|
101
|
+
return truncateLogText(renderError(err, 0));
|
|
102
|
+
} catch {
|
|
103
|
+
return tagOf(err);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function truncateLogText(s) {
|
|
107
|
+
if (s.length <= MAX_LOG_TEXT_LENGTH) return s;
|
|
108
|
+
let cut = MAX_LOG_TEXT_LENGTH - TRUNCATION_MARKER.length;
|
|
109
|
+
const last = s.charCodeAt(cut - 1);
|
|
110
|
+
if (last >= 55296 && last <= 56319) cut -= 1;
|
|
111
|
+
return s.slice(0, cut) + TRUNCATION_MARKER;
|
|
112
|
+
}
|
|
113
|
+
var MAX_LOG_TEXT_LENGTH = 8 * 1024;
|
|
114
|
+
var TRUNCATION_MARKER = "\u2026 [truncated]";
|
|
115
|
+
var MAX_CAUSE_DEPTH = 4;
|
|
116
|
+
function tagOf(err) {
|
|
117
|
+
try {
|
|
118
|
+
return Object.prototype.toString.call(err);
|
|
119
|
+
} catch {
|
|
120
|
+
return "[unloggable error]";
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
function renderError(err, depth) {
|
|
124
|
+
let isError;
|
|
125
|
+
try {
|
|
126
|
+
isError = err instanceof Error;
|
|
127
|
+
} catch {
|
|
128
|
+
return tagOf(err);
|
|
129
|
+
}
|
|
130
|
+
if (!isError) {
|
|
131
|
+
try {
|
|
132
|
+
return String(err).slice(0, MAX_LOG_TEXT_LENGTH + 1);
|
|
133
|
+
} catch {
|
|
134
|
+
return tagOf(err);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const e = err;
|
|
138
|
+
let out;
|
|
139
|
+
try {
|
|
140
|
+
const stack = typeof e.stack === "string" ? e.stack : void 0;
|
|
141
|
+
const head = (e.message ? `${e.name}: ${e.message}` : `${e.name}`).slice(
|
|
142
|
+
0,
|
|
143
|
+
MAX_LOG_TEXT_LENGTH + 1
|
|
144
|
+
);
|
|
145
|
+
if (!stack) out = head;
|
|
146
|
+
else if (stack.startsWith(head)) out = stack.slice(0, MAX_LOG_TEXT_LENGTH + 1);
|
|
147
|
+
else out = `${head}
|
|
148
|
+
${stack.slice(0, MAX_LOG_TEXT_LENGTH + 1)}`;
|
|
149
|
+
} catch {
|
|
150
|
+
return tagOf(err);
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
if (e instanceof AggregateError && Array.isArray(e.errors)) {
|
|
154
|
+
if (depth < MAX_CAUSE_DEPTH) {
|
|
155
|
+
for (const sub of e.errors.slice(0, MAX_CAUSE_DEPTH)) {
|
|
156
|
+
if (out.length >= MAX_LOG_TEXT_LENGTH) return out + "\n\u2026 [cause chain truncated]";
|
|
157
|
+
out += `
|
|
158
|
+
caused by: ${renderError(sub, depth + 1)}`;
|
|
159
|
+
}
|
|
160
|
+
if (e.errors.length > MAX_CAUSE_DEPTH) {
|
|
161
|
+
out += `
|
|
162
|
+
\u2026 [${e.errors.length - MAX_CAUSE_DEPTH} more errors]`;
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
out += "\n\u2026 [cause chain truncated]";
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const cause = e.cause;
|
|
169
|
+
if (cause != null) {
|
|
170
|
+
if (depth >= MAX_CAUSE_DEPTH) {
|
|
171
|
+
if (!out.endsWith("\u2026 [cause chain truncated]")) out += "\n\u2026 [cause chain truncated]";
|
|
172
|
+
} else if (out.length < MAX_LOG_TEXT_LENGTH) {
|
|
173
|
+
out += `
|
|
174
|
+
caused by: ${renderError(cause, depth + 1)}`;
|
|
175
|
+
} else {
|
|
176
|
+
out += "\n\u2026 [cause chain truncated]";
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
} catch {
|
|
180
|
+
out += "\n\u2026 [cause chain unrenderable]";
|
|
181
|
+
}
|
|
182
|
+
return out;
|
|
183
|
+
}
|
|
184
|
+
|
|
75
185
|
// src/shared/room-identity-headers.ts
|
|
76
186
|
var BASE64URL = /^[A-Za-z0-9_-]*$/;
|
|
77
187
|
var IDENTITY_QUERY_PARAMS = ["userId", "userName", "userEmail", "userImageUrl", "role"];
|
|
@@ -215,7 +325,7 @@ var BaseRoom = class {
|
|
|
215
325
|
try {
|
|
216
326
|
await this.onBinaryMessage(ws, attachment, message);
|
|
217
327
|
} catch (e) {
|
|
218
|
-
console.error(`[${this.constructor.name}] Binary message error
|
|
328
|
+
console.error(`[${this.constructor.name}] Binary message error: ${loggableError(e)}`);
|
|
219
329
|
}
|
|
220
330
|
}
|
|
221
331
|
return;
|
|
@@ -224,7 +334,7 @@ var BaseRoom = class {
|
|
|
224
334
|
const msg = JSON.parse(message);
|
|
225
335
|
await this.onMessage(ws, attachment, msg);
|
|
226
336
|
} catch (e) {
|
|
227
|
-
console.error(`[${this.constructor.name}] Message error
|
|
337
|
+
console.error(`[${this.constructor.name}] Message error: ${loggableError(e)}`);
|
|
228
338
|
}
|
|
229
339
|
}
|
|
230
340
|
async webSocketClose(ws, _code, _reason) {
|
|
@@ -237,7 +347,7 @@ var BaseRoom = class {
|
|
|
237
347
|
}
|
|
238
348
|
}
|
|
239
349
|
async webSocketError(_ws, error) {
|
|
240
|
-
console.error(`[${this.constructor.name}] webSocketError
|
|
350
|
+
console.error(`[${this.constructor.name}] webSocketError: ${loggableError(error)}`);
|
|
241
351
|
}
|
|
242
352
|
async alarm() {
|
|
243
353
|
if (this.onAlarm) {
|
|
@@ -1684,7 +1794,7 @@ function getOrCreateYjsDoc(ctx, docKey) {
|
|
|
1684
1794
|
try {
|
|
1685
1795
|
Y2.applyUpdate(doc, new Uint8Array(row.state));
|
|
1686
1796
|
} catch (e) {
|
|
1687
|
-
console.error(`Failed to load Yjs doc ${docKey}
|
|
1797
|
+
console.error(`Failed to load Yjs doc ${docKey}: ${loggableError(e)}`);
|
|
1688
1798
|
}
|
|
1689
1799
|
}
|
|
1690
1800
|
const saveDoc = () => {
|
|
@@ -2600,7 +2710,12 @@ async function executeTool(ctx, toolName, params, userId, userRole, skipUserRbac
|
|
|
2600
2710
|
case "user.current": {
|
|
2601
2711
|
if (!userId) return { success: false, error: "No userId provided" };
|
|
2602
2712
|
const user = getUser(ctx.sql, userId, ctx.schemaRegistry);
|
|
2603
|
-
if (!user)
|
|
2713
|
+
if (!user) {
|
|
2714
|
+
return {
|
|
2715
|
+
success: false,
|
|
2716
|
+
error: "No users row for this identity yet \u2014 it is created by signing in to the app in a browser. Tool access does not require one, so other tools keep working."
|
|
2717
|
+
};
|
|
2718
|
+
}
|
|
2604
2719
|
return { success: true, data: { user } };
|
|
2605
2720
|
}
|
|
2606
2721
|
// The same roster the socket's `user.list` returns, for the same caller.
|
|
@@ -3193,7 +3308,7 @@ var RecordRoom = class extends BaseRoom {
|
|
|
3193
3308
|
new Uint8Array(message)
|
|
3194
3309
|
);
|
|
3195
3310
|
} catch (e) {
|
|
3196
|
-
console.error(
|
|
3311
|
+
console.error(`[RecordRoom] Yjs binary message error: ${loggableError(e)}`);
|
|
3197
3312
|
}
|
|
3198
3313
|
return;
|
|
3199
3314
|
}
|
|
@@ -3203,7 +3318,9 @@ var RecordRoom = class extends BaseRoom {
|
|
|
3203
3318
|
} catch (e) {
|
|
3204
3319
|
const errMsg = e instanceof Error ? e.message : String(e);
|
|
3205
3320
|
const msgPreview = typeof message === "string" ? message.slice(0, 200) : "(non-string)";
|
|
3206
|
-
console.error(`[RecordRoom] Message handler error: ${
|
|
3321
|
+
console.error(`[RecordRoom] Message handler error: ${loggableError(e)}`, {
|
|
3322
|
+
message: msgPreview
|
|
3323
|
+
});
|
|
3207
3324
|
this.send(ws, { type: MSG.ERROR, payload: { error: `Invalid message: ${errMsg}` } });
|
|
3208
3325
|
}
|
|
3209
3326
|
}
|
|
@@ -3217,9 +3334,6 @@ var RecordRoom = class extends BaseRoom {
|
|
|
3217
3334
|
} catch {
|
|
3218
3335
|
}
|
|
3219
3336
|
}
|
|
3220
|
-
async webSocketError(_ws, error) {
|
|
3221
|
-
console.error(`[RecordRoom] webSocketError:`, error);
|
|
3222
|
-
}
|
|
3223
3337
|
// ============================================================================
|
|
3224
3338
|
// Message Routing
|
|
3225
3339
|
// ============================================================================
|
|
@@ -4359,8 +4473,7 @@ var CronRoom = class extends BaseRoom {
|
|
|
4359
4473
|
if (success) {
|
|
4360
4474
|
console.log(`[cron] ${taskName} ok ${durationMs}ms`);
|
|
4361
4475
|
} else {
|
|
4362
|
-
|
|
4363
|
-
console.error(`[cron] ${taskName} failed ${durationMs}ms: ${error}`, ...stack ? [stack] : []);
|
|
4476
|
+
console.error(`[cron] ${taskName} failed ${durationMs}ms: ${loggableError(thrown)}`);
|
|
4364
4477
|
}
|
|
4365
4478
|
this.sql.exec(
|
|
4366
4479
|
`INSERT INTO cron_history (task_name, started_at, completed_at, success, duration_ms, error, created_at)
|
|
@@ -4543,12 +4656,8 @@ var JobRoom = class extends BaseRoom {
|
|
|
4543
4656
|
next_run_at TEXT
|
|
4544
4657
|
)
|
|
4545
4658
|
`);
|
|
4546
|
-
this.sql.exec(
|
|
4547
|
-
|
|
4548
|
-
);
|
|
4549
|
-
this.sql.exec(
|
|
4550
|
-
`CREATE INDEX IF NOT EXISTS jobs_completed_at ON jobs (completed_at)`
|
|
4551
|
-
);
|
|
4659
|
+
this.sql.exec(`CREATE INDEX IF NOT EXISTS jobs_status_next_run ON jobs (status, next_run_at)`);
|
|
4660
|
+
this.sql.exec(`CREATE INDEX IF NOT EXISTS jobs_completed_at ON jobs (completed_at)`);
|
|
4552
4661
|
this.recoverStuckRunning();
|
|
4553
4662
|
this.scheduleNextAlarm();
|
|
4554
4663
|
}
|
|
@@ -4816,8 +4925,7 @@ var JobRoom = class extends BaseRoom {
|
|
|
4816
4925
|
} catch (e) {
|
|
4817
4926
|
outcome = "failed";
|
|
4818
4927
|
errorMessage = e instanceof Error ? e.message : String(e);
|
|
4819
|
-
|
|
4820
|
-
console.error(`[jobs] ${row.type} (${row.id}) failed: ${errorMessage}`, ...stack ? [stack] : []);
|
|
4928
|
+
console.error(`[jobs] ${row.type} (${row.id}) failed: ${loggableError(e)}`);
|
|
4821
4929
|
} finally {
|
|
4822
4930
|
this.inFlight.delete(row.id);
|
|
4823
4931
|
}
|
|
@@ -6164,7 +6272,7 @@ async function measuredAllocationUsage(bucket, storage, prefixes, excludedMarker
|
|
|
6164
6272
|
);
|
|
6165
6273
|
if (budget.staleKeys.length > 0) {
|
|
6166
6274
|
await bucket.delete(budget.staleKeys).catch((error) => {
|
|
6167
|
-
console.error(
|
|
6275
|
+
console.error(`[files:quota] stale marker cleanup: ${loggableError(error)}`);
|
|
6168
6276
|
});
|
|
6169
6277
|
}
|
|
6170
6278
|
return total;
|
|
@@ -6224,7 +6332,7 @@ async function markQuotaDirty(bucket, storage) {
|
|
|
6224
6332
|
}
|
|
6225
6333
|
console.error("[files:quota] could not mark summary reclaimable after concurrent writes");
|
|
6226
6334
|
} catch (error) {
|
|
6227
|
-
console.error(
|
|
6335
|
+
console.error(`[files:quota] could not mark summary reclaimable: ${loggableError(error)}`);
|
|
6228
6336
|
}
|
|
6229
6337
|
}
|
|
6230
6338
|
async function neutralizeMarker(bucket, markerKey) {
|
|
@@ -6264,7 +6372,7 @@ async function releaseQuotaMarker(bucket, storage, markerKey, summaryMayBeStale)
|
|
|
6264
6372
|
}
|
|
6265
6373
|
return true;
|
|
6266
6374
|
} catch (error) {
|
|
6267
|
-
console.error(
|
|
6375
|
+
console.error(`[files:quota] reservation cleanup: ${loggableError(error)}`);
|
|
6268
6376
|
return false;
|
|
6269
6377
|
}
|
|
6270
6378
|
}
|
|
@@ -6294,7 +6402,7 @@ async function readMultipartReservation(bucket, storage, reservationId) {
|
|
|
6294
6402
|
try {
|
|
6295
6403
|
object = await bucket.get(key);
|
|
6296
6404
|
} catch (error) {
|
|
6297
|
-
console.error(
|
|
6405
|
+
console.error(`[files:quota] reservation read: ${loggableError(error)}`);
|
|
6298
6406
|
return "invalid";
|
|
6299
6407
|
}
|
|
6300
6408
|
if (!object) return null;
|
|
@@ -6490,7 +6598,7 @@ async function admitStorage(bucket, storage, incomingBytes, replacedBytes, marke
|
|
|
6490
6598
|
}
|
|
6491
6599
|
return { markerKey: effectiveMarker?.key ?? null };
|
|
6492
6600
|
} catch (error) {
|
|
6493
|
-
console.error(
|
|
6601
|
+
console.error(`[files:quota] admission: ${loggableError(error)}`);
|
|
6494
6602
|
await releaseQuotaMarker(bucket, storage, markerKey, true);
|
|
6495
6603
|
return quotaUnavailable(
|
|
6496
6604
|
"The storage used by this account could not be verified. Retry shortly."
|
|
@@ -6504,7 +6612,7 @@ async function storageUsage(bucket, storage) {
|
|
|
6504
6612
|
const current = await ensureQuotaSummary(bucket, storage, prefixes, "repairDirty");
|
|
6505
6613
|
return current?.summary?.usedBytes ?? null;
|
|
6506
6614
|
} catch (error) {
|
|
6507
|
-
console.error(
|
|
6615
|
+
console.error(`[files:quota] usage: ${loggableError(error)}`);
|
|
6508
6616
|
return null;
|
|
6509
6617
|
}
|
|
6510
6618
|
}
|
|
@@ -7090,7 +7198,7 @@ async function finishCompletedMultipart(bucket, session, reservation, object, au
|
|
|
7090
7198
|
if (current?.etag === object.etag) await bucket.delete(session.key);
|
|
7091
7199
|
remaining = await bucket.head(session.key);
|
|
7092
7200
|
} catch (error) {
|
|
7093
|
-
console.error(
|
|
7201
|
+
console.error(`[files:multipart] invalid object cleanup: ${loggableError(error)}`);
|
|
7094
7202
|
return quotaUnavailable("The invalid assembled file could not be removed. Retry completion.");
|
|
7095
7203
|
}
|
|
7096
7204
|
if (remaining?.etag === object.etag) {
|
|
@@ -8107,8 +8215,7 @@ async function prepareMessagesWithCompaction(messages, config, options) {
|
|
|
8107
8215
|
};
|
|
8108
8216
|
} catch (err) {
|
|
8109
8217
|
console.error(
|
|
8110
|
-
|
|
8111
|
-
err
|
|
8218
|
+
`prepareMessagesWithCompaction: summarizer failed, falling back to sliding window: ${loggableError(err)}`
|
|
8112
8219
|
);
|
|
8113
8220
|
}
|
|
8114
8221
|
} else {
|
|
@@ -9586,7 +9693,7 @@ async function callDocumentationTool(rawRequest, request2, corpus, env, basePath
|
|
|
9586
9693
|
url: new URL(documentationPublicPath(basePath, page.route), origin).toString()
|
|
9587
9694
|
});
|
|
9588
9695
|
} catch (error) {
|
|
9589
|
-
console.error(
|
|
9696
|
+
console.error(`[documentation-mcp] page unavailable: ${loggableError(error)}`);
|
|
9590
9697
|
return toolError(request2.id, "The documentation page could not be read");
|
|
9591
9698
|
}
|
|
9592
9699
|
}
|
|
@@ -10060,7 +10167,9 @@ function createDeepSpaceAuth(config) {
|
|
|
10060
10167
|
try {
|
|
10061
10168
|
return { clientId: apple.clientId, clientSecret: await generateAppleClientSecret(apple) };
|
|
10062
10169
|
} catch (err) {
|
|
10063
|
-
console.error(
|
|
10170
|
+
console.error(
|
|
10171
|
+
`[deepspace] failed to mint Apple client secret; Apple sign-in disabled: ${loggableError(err)}`
|
|
10172
|
+
);
|
|
10064
10173
|
return { clientId: apple.clientId, clientSecret: "" };
|
|
10065
10174
|
}
|
|
10066
10175
|
};
|
|
@@ -10135,7 +10244,9 @@ function buildDatabaseHooks(onUserCreated) {
|
|
|
10135
10244
|
ctx ? { request: ctx.request, headers: ctx.headers ?? void 0 } : null
|
|
10136
10245
|
);
|
|
10137
10246
|
} catch (err) {
|
|
10138
|
-
console.error(
|
|
10247
|
+
console.error(
|
|
10248
|
+
`[deepspace] onUserCreated hook failed (signup unaffected): ${loggableError(err)}`
|
|
10249
|
+
);
|
|
10139
10250
|
}
|
|
10140
10251
|
}
|
|
10141
10252
|
}
|
|
@@ -10156,92 +10267,6 @@ async function generateAppleClientSecret(apple) {
|
|
|
10156
10267
|
return token;
|
|
10157
10268
|
}
|
|
10158
10269
|
|
|
10159
|
-
// src/shared/client-errors.ts
|
|
10160
|
-
var CLIENT_LOG_MARKER = "[deepspace:client-error]";
|
|
10161
|
-
var CLIENT_ERROR_PATH = "/_deepspace/client-errors";
|
|
10162
|
-
var CLIENT_ERROR_CAPS = {
|
|
10163
|
-
message: 1024,
|
|
10164
|
-
stack: 4096,
|
|
10165
|
-
name: 256,
|
|
10166
|
-
url: 512
|
|
10167
|
-
};
|
|
10168
|
-
function capText(value, max) {
|
|
10169
|
-
if (typeof value !== "string") return void 0;
|
|
10170
|
-
return value.length > max ? value.slice(0, max) : value;
|
|
10171
|
-
}
|
|
10172
|
-
function finiteNumber(value) {
|
|
10173
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
10174
|
-
}
|
|
10175
|
-
function normalizeClientErrorReport(raw) {
|
|
10176
|
-
if (typeof raw !== "object" || raw === null) return null;
|
|
10177
|
-
const o = raw;
|
|
10178
|
-
const kind = o.kind === "unhandledrejection" || o.kind === "react" ? o.kind : "error";
|
|
10179
|
-
const message = capText(o.message, CLIENT_ERROR_CAPS.message) ?? "";
|
|
10180
|
-
const name = capText(o.name, CLIENT_ERROR_CAPS.name);
|
|
10181
|
-
const stack = capText(o.stack, CLIENT_ERROR_CAPS.stack);
|
|
10182
|
-
const url = capText(o.url, CLIENT_ERROR_CAPS.url);
|
|
10183
|
-
const line = finiteNumber(o.line);
|
|
10184
|
-
const col = finiteNumber(o.col);
|
|
10185
|
-
if (!message && !stack) return null;
|
|
10186
|
-
const report = { kind, message: message || (name ?? "Error") };
|
|
10187
|
-
if (name) report.name = name;
|
|
10188
|
-
if (stack) report.stack = stack;
|
|
10189
|
-
if (url) report.url = url;
|
|
10190
|
-
if (line !== void 0) report.line = line;
|
|
10191
|
-
if (col !== void 0) report.col = col;
|
|
10192
|
-
return report;
|
|
10193
|
-
}
|
|
10194
|
-
function clientErrorToLogLine(report) {
|
|
10195
|
-
return `${CLIENT_LOG_MARKER} ${JSON.stringify(report)}`;
|
|
10196
|
-
}
|
|
10197
|
-
|
|
10198
|
-
// src/server/client-errors.ts
|
|
10199
|
-
var THROTTLE_WINDOW_MS = 1e3;
|
|
10200
|
-
var THROTTLE_MAX = 20;
|
|
10201
|
-
var windowStart = 0;
|
|
10202
|
-
var windowCount = 0;
|
|
10203
|
-
var MAX_BODY_BYTES = 64 * 1024;
|
|
10204
|
-
function shouldThrottleClientError(now = Date.now()) {
|
|
10205
|
-
if (now - windowStart >= THROTTLE_WINDOW_MS) {
|
|
10206
|
-
windowStart = now;
|
|
10207
|
-
windowCount = 0;
|
|
10208
|
-
}
|
|
10209
|
-
windowCount += 1;
|
|
10210
|
-
return windowCount > THROTTLE_MAX;
|
|
10211
|
-
}
|
|
10212
|
-
function jsonResponse2(body, status) {
|
|
10213
|
-
return new Response(JSON.stringify(body), {
|
|
10214
|
-
status,
|
|
10215
|
-
headers: { "Content-Type": "application/json" }
|
|
10216
|
-
});
|
|
10217
|
-
}
|
|
10218
|
-
async function handleClientErrorReport(request2) {
|
|
10219
|
-
const site = request2.headers.get("sec-fetch-site");
|
|
10220
|
-
if (site && site !== "same-origin" && site !== "none") {
|
|
10221
|
-
return new Response(null, { status: 403 });
|
|
10222
|
-
}
|
|
10223
|
-
if (shouldThrottleClientError()) {
|
|
10224
|
-
return new Response(null, { status: 429, headers: { "Retry-After": "1" } });
|
|
10225
|
-
}
|
|
10226
|
-
const declared = Number(request2.headers.get("content-length"));
|
|
10227
|
-
if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) {
|
|
10228
|
-
return jsonResponse2({ error: "payload_too_large" }, 413);
|
|
10229
|
-
}
|
|
10230
|
-
let body;
|
|
10231
|
-
try {
|
|
10232
|
-
body = await request2.json();
|
|
10233
|
-
} catch {
|
|
10234
|
-
return jsonResponse2({ error: "invalid_json" }, 400);
|
|
10235
|
-
}
|
|
10236
|
-
const report = normalizeClientErrorReport(body);
|
|
10237
|
-
if (!report) return jsonResponse2({ error: "invalid_report" }, 400);
|
|
10238
|
-
console.error(clientErrorToLogLine(report));
|
|
10239
|
-
return new Response(null, { status: 204 });
|
|
10240
|
-
}
|
|
10241
|
-
function registerClientErrorRoute(app) {
|
|
10242
|
-
app.post(CLIENT_ERROR_PATH, (c) => handleClientErrorReport(c.req.raw));
|
|
10243
|
-
}
|
|
10244
|
-
|
|
10245
10270
|
// src/server/agent-tools.ts
|
|
10246
10271
|
import { asSchema } from "ai";
|
|
10247
10272
|
|
|
@@ -10250,7 +10275,7 @@ var AGENT_TOOL_REQUEST_BODY_CAP = 64 * 1024;
|
|
|
10250
10275
|
var AGENT_TOOL_RESPONSE_BODY_CAP = 1024 * 1024;
|
|
10251
10276
|
|
|
10252
10277
|
// src/server/agent-tools.ts
|
|
10253
|
-
function
|
|
10278
|
+
function jsonResponse2(body, status = 200) {
|
|
10254
10279
|
return rawJsonResponse(JSON.stringify(body), status);
|
|
10255
10280
|
}
|
|
10256
10281
|
function rawJsonResponse(body, status = 200) {
|
|
@@ -10262,10 +10287,12 @@ function rawJsonResponse(body, status = 200) {
|
|
|
10262
10287
|
}
|
|
10263
10288
|
});
|
|
10264
10289
|
}
|
|
10265
|
-
function errorResponse(status, code) {
|
|
10290
|
+
function errorResponse(status, code, detail) {
|
|
10266
10291
|
const errors = {
|
|
10267
10292
|
unauthenticated: "Authentication is required.",
|
|
10268
|
-
|
|
10293
|
+
// The remedy is documented and single-step (local-agent-tools.md): a
|
|
10294
|
+
// signed-in app visit creates or refreshes the caller's user row.
|
|
10295
|
+
forbidden: "You are not allowed to use assistant tools. Sign in to the app once in a browser (a signed-in visit creates your user row), or ask the app owner for access.",
|
|
10269
10296
|
access_check_unavailable: "Access could not be verified. Try again.",
|
|
10270
10297
|
tool_not_found: "The requested tool is not available.",
|
|
10271
10298
|
invalid_json: "The request body must be valid JSON.",
|
|
@@ -10276,7 +10303,35 @@ function errorResponse(status, code) {
|
|
|
10276
10303
|
invalid_tool_result: "The tool returned an invalid result.",
|
|
10277
10304
|
tool_result_too_large: "The tool returned a result that is too large."
|
|
10278
10305
|
};
|
|
10279
|
-
|
|
10306
|
+
const error = detail ? `${errors[code]} ${detail}` : errors[code];
|
|
10307
|
+
return jsonResponse2({ ok: false, code, error }, status);
|
|
10308
|
+
}
|
|
10309
|
+
function validationDetail(error) {
|
|
10310
|
+
const issues = error.issues;
|
|
10311
|
+
if (Array.isArray(issues) && issues.length > 0) {
|
|
10312
|
+
const shown = issues.slice(0, 5).map((issue) => {
|
|
10313
|
+
const { path, message } = issue ?? {};
|
|
10314
|
+
const at = Array.isArray(path) && path.length > 0 ? `${path.join(".")}: ` : "";
|
|
10315
|
+
return `${at}${typeof message === "string" ? message : "invalid"}`;
|
|
10316
|
+
});
|
|
10317
|
+
const more = issues.length - shown.length;
|
|
10318
|
+
return `${shown.join("; ")}${more > 0 ? ` (+${more} more)` : ""}`;
|
|
10319
|
+
}
|
|
10320
|
+
if (!(error instanceof Error) || !error.message) return void 0;
|
|
10321
|
+
const line = error.message.replace(/\s+/g, " ").trim();
|
|
10322
|
+
return line.length > 400 ? `${line.slice(0, 400)}\u2026` : line;
|
|
10323
|
+
}
|
|
10324
|
+
function droppedTopLevelKeys(schema, input, validated) {
|
|
10325
|
+
if (input === null || typeof input !== "object" || Array.isArray(input) || validated === null || typeof validated !== "object" || Array.isArray(validated)) {
|
|
10326
|
+
return [];
|
|
10327
|
+
}
|
|
10328
|
+
try {
|
|
10329
|
+
const jsonSchema2 = schema.jsonSchema;
|
|
10330
|
+
if (jsonSchema2?.type !== "object" || jsonSchema2.additionalProperties !== false) return [];
|
|
10331
|
+
} catch {
|
|
10332
|
+
return [];
|
|
10333
|
+
}
|
|
10334
|
+
return Object.keys(input).filter((key) => !Object.hasOwn(validated, key));
|
|
10280
10335
|
}
|
|
10281
10336
|
function parseToolRequestBody(text) {
|
|
10282
10337
|
let parsed;
|
|
@@ -10382,7 +10437,15 @@ function registerAgentToolRoutes(app, options) {
|
|
|
10382
10437
|
} catch {
|
|
10383
10438
|
return errorResponse(500, "tool_configuration_error");
|
|
10384
10439
|
}
|
|
10385
|
-
if (!tool3)
|
|
10440
|
+
if (!tool3) {
|
|
10441
|
+
const names = Object.keys(tools).filter((name) => typeof tools[name]?.execute === "function").sort();
|
|
10442
|
+
const listed = names.slice(0, 20).join(", ");
|
|
10443
|
+
return errorResponse(
|
|
10444
|
+
404,
|
|
10445
|
+
"tool_not_found",
|
|
10446
|
+
names.length > 0 ? `Available tools: ${listed}${names.length > 20 ? ", \u2026" : ""}.` : void 0
|
|
10447
|
+
);
|
|
10448
|
+
}
|
|
10386
10449
|
let text;
|
|
10387
10450
|
try {
|
|
10388
10451
|
text = await readBoundedBodyText(c.req.raw, AGENT_TOOL_REQUEST_BODY_CAP);
|
|
@@ -10393,15 +10456,26 @@ function registerAgentToolRoutes(app, options) {
|
|
|
10393
10456
|
if (body === void 0) return errorResponse(400, "invalid_json");
|
|
10394
10457
|
if (body === null) return errorResponse(400, "invalid_tool_input");
|
|
10395
10458
|
let input = body.input;
|
|
10459
|
+
const schema = asSchema(tool3.inputSchema);
|
|
10396
10460
|
try {
|
|
10397
|
-
const validation =
|
|
10461
|
+
const validation = schema.validate;
|
|
10398
10462
|
if (validation) {
|
|
10399
10463
|
const result = await validation(input);
|
|
10400
|
-
if (!result.success)
|
|
10464
|
+
if (!result.success) {
|
|
10465
|
+
return errorResponse(400, "invalid_tool_input", validationDetail(result.error));
|
|
10466
|
+
}
|
|
10467
|
+
const dropped = droppedTopLevelKeys(schema, input, result.value);
|
|
10468
|
+
if (dropped.length > 0) {
|
|
10469
|
+
return errorResponse(
|
|
10470
|
+
400,
|
|
10471
|
+
"invalid_tool_input",
|
|
10472
|
+
`Unknown input field(s): ${dropped.join(", ")} \u2014 the tool's inputSchema lists the accepted fields.`
|
|
10473
|
+
);
|
|
10474
|
+
}
|
|
10401
10475
|
input = result.value;
|
|
10402
10476
|
}
|
|
10403
|
-
} catch {
|
|
10404
|
-
return errorResponse(400, "invalid_tool_input");
|
|
10477
|
+
} catch (error) {
|
|
10478
|
+
return errorResponse(400, "invalid_tool_input", validationDetail(error));
|
|
10405
10479
|
}
|
|
10406
10480
|
let output;
|
|
10407
10481
|
try {
|
|
@@ -10467,19 +10541,19 @@ function normalizeAgentTargetOrigin(value, policy) {
|
|
|
10467
10541
|
// src/shared/auth-session.ts
|
|
10468
10542
|
var SESSION_COOKIE = "__Secure-better-auth.session_token";
|
|
10469
10543
|
|
|
10470
|
-
// src/
|
|
10471
|
-
|
|
10472
|
-
|
|
10473
|
-
|
|
10474
|
-
|
|
10475
|
-
|
|
10476
|
-
|
|
10477
|
-
|
|
10478
|
-
|
|
10479
|
-
|
|
10480
|
-
|
|
10481
|
-
|
|
10482
|
-
|
|
10544
|
+
// src/server/worker-error.ts
|
|
10545
|
+
function workerErrorHandler(prefix, respond = (c) => c.text("Internal Server Error", 500)) {
|
|
10546
|
+
return (err, c) => {
|
|
10547
|
+
if ("getResponse" in err) {
|
|
10548
|
+
const res = err.getResponse();
|
|
10549
|
+
return c.newResponse(res.body, res);
|
|
10550
|
+
}
|
|
10551
|
+
console.error(
|
|
10552
|
+
`[${prefix}] ${c.req.method} ${new URL(c.req.url).pathname}: ${loggableError(err)}`
|
|
10553
|
+
);
|
|
10554
|
+
return respond(c);
|
|
10555
|
+
};
|
|
10556
|
+
}
|
|
10483
10557
|
export {
|
|
10484
10558
|
ACCOUNT_STORAGE_LIMIT_BYTES,
|
|
10485
10559
|
ACTION_ROUTES_BEARER_GUARD_MIGRATION_ID,
|
|
@@ -10505,7 +10579,6 @@ export {
|
|
|
10505
10579
|
BaseRoom,
|
|
10506
10580
|
CHANNELS_SCHEMA,
|
|
10507
10581
|
CHANNEL_MEMBERS_SCHEMA,
|
|
10508
|
-
CLIENT_LOG_MARKER,
|
|
10509
10582
|
COST_RATES,
|
|
10510
10583
|
CanvasRoom,
|
|
10511
10584
|
CronRoom,
|
|
@@ -10527,6 +10600,7 @@ export {
|
|
|
10527
10600
|
MAX_DELETE_WHERE_LIMIT,
|
|
10528
10601
|
MAX_DEPLOY_ASSET_FILE_BYTES,
|
|
10529
10602
|
MAX_ENV_VAR_BYTES,
|
|
10603
|
+
MAX_LOG_TEXT_LENGTH,
|
|
10530
10604
|
MAX_UPLOAD_PARTS,
|
|
10531
10605
|
MAX_UPLOAD_REQUEST_BYTES,
|
|
10532
10606
|
MESSAGES_SCHEMA,
|
|
@@ -10624,7 +10698,6 @@ export {
|
|
|
10624
10698
|
getMessageType,
|
|
10625
10699
|
getRolePermissions,
|
|
10626
10700
|
handleAwarenessMessage,
|
|
10627
|
-
handleClientErrorReport,
|
|
10628
10701
|
handleSyncMessage,
|
|
10629
10702
|
hasContent,
|
|
10630
10703
|
isAnonymousUserId,
|
|
@@ -10642,6 +10715,8 @@ export {
|
|
|
10642
10715
|
lintSchemas,
|
|
10643
10716
|
listDeepSpaceAgentModels,
|
|
10644
10717
|
loadMessages,
|
|
10718
|
+
logEventText,
|
|
10719
|
+
loggableError,
|
|
10645
10720
|
makeDefaultSummarizer,
|
|
10646
10721
|
matchOrigin,
|
|
10647
10722
|
meterAi,
|
|
@@ -10660,7 +10735,6 @@ export {
|
|
|
10660
10735
|
readVarUint,
|
|
10661
10736
|
readVarUint8Array,
|
|
10662
10737
|
registerAgentToolRoutes,
|
|
10663
|
-
registerClientErrorRoute,
|
|
10664
10738
|
registerDeepSpaceDocumentation,
|
|
10665
10739
|
registryErrorJson,
|
|
10666
10740
|
registryStub,
|
|
@@ -10680,6 +10754,7 @@ export {
|
|
|
10680
10754
|
timingSafeEqualStrings,
|
|
10681
10755
|
toUint8Array,
|
|
10682
10756
|
totalChars,
|
|
10757
|
+
truncateLogText,
|
|
10683
10758
|
truncateOldToolResults,
|
|
10684
10759
|
turnsToCoreMessages,
|
|
10685
10760
|
unwrapToolOutput,
|
|
@@ -10690,6 +10765,7 @@ export {
|
|
|
10690
10765
|
validateDoManifest,
|
|
10691
10766
|
verifyAgentToken,
|
|
10692
10767
|
verifyJwt,
|
|
10768
|
+
workerErrorHandler,
|
|
10693
10769
|
writeVarUint,
|
|
10694
10770
|
writeVarUint8Array
|
|
10695
10771
|
};
|