deepspace 0.28.1 → 0.28.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/worker.js CHANGED
@@ -2600,7 +2600,12 @@ async function executeTool(ctx, toolName, params, userId, userRole, skipUserRbac
2600
2600
  case "user.current": {
2601
2601
  if (!userId) return { success: false, error: "No userId provided" };
2602
2602
  const user = getUser(ctx.sql, userId, ctx.schemaRegistry);
2603
- if (!user) return { success: false, error: "User not found" };
2603
+ if (!user) {
2604
+ return {
2605
+ success: false,
2606
+ 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."
2607
+ };
2608
+ }
2604
2609
  return { success: true, data: { user } };
2605
2610
  }
2606
2611
  // The same roster the socket's `user.list` returns, for the same caller.
@@ -10262,10 +10267,12 @@ function rawJsonResponse(body, status = 200) {
10262
10267
  }
10263
10268
  });
10264
10269
  }
10265
- function errorResponse(status, code) {
10270
+ function errorResponse(status, code, detail) {
10266
10271
  const errors = {
10267
10272
  unauthenticated: "Authentication is required.",
10268
- forbidden: "You are not allowed to use assistant tools.",
10273
+ // The remedy is documented and single-step (local-agent-tools.md): a
10274
+ // signed-in app visit creates or refreshes the caller's user row.
10275
+ 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
10276
  access_check_unavailable: "Access could not be verified. Try again.",
10270
10277
  tool_not_found: "The requested tool is not available.",
10271
10278
  invalid_json: "The request body must be valid JSON.",
@@ -10276,7 +10283,35 @@ function errorResponse(status, code) {
10276
10283
  invalid_tool_result: "The tool returned an invalid result.",
10277
10284
  tool_result_too_large: "The tool returned a result that is too large."
10278
10285
  };
10279
- return jsonResponse3({ ok: false, code, error: errors[code] }, status);
10286
+ const error = detail ? `${errors[code]} ${detail}` : errors[code];
10287
+ return jsonResponse3({ ok: false, code, error }, status);
10288
+ }
10289
+ function validationDetail(error) {
10290
+ const issues = error.issues;
10291
+ if (Array.isArray(issues) && issues.length > 0) {
10292
+ const shown = issues.slice(0, 5).map((issue) => {
10293
+ const { path, message } = issue ?? {};
10294
+ const at = Array.isArray(path) && path.length > 0 ? `${path.join(".")}: ` : "";
10295
+ return `${at}${typeof message === "string" ? message : "invalid"}`;
10296
+ });
10297
+ const more = issues.length - shown.length;
10298
+ return `${shown.join("; ")}${more > 0 ? ` (+${more} more)` : ""}`;
10299
+ }
10300
+ if (!(error instanceof Error) || !error.message) return void 0;
10301
+ const line = error.message.replace(/\s+/g, " ").trim();
10302
+ return line.length > 400 ? `${line.slice(0, 400)}\u2026` : line;
10303
+ }
10304
+ function droppedTopLevelKeys(schema, input, validated) {
10305
+ if (input === null || typeof input !== "object" || Array.isArray(input) || validated === null || typeof validated !== "object" || Array.isArray(validated)) {
10306
+ return [];
10307
+ }
10308
+ try {
10309
+ const jsonSchema2 = schema.jsonSchema;
10310
+ if (jsonSchema2?.type !== "object" || jsonSchema2.additionalProperties !== false) return [];
10311
+ } catch {
10312
+ return [];
10313
+ }
10314
+ return Object.keys(input).filter((key) => !Object.hasOwn(validated, key));
10280
10315
  }
10281
10316
  function parseToolRequestBody(text) {
10282
10317
  let parsed;
@@ -10382,7 +10417,15 @@ function registerAgentToolRoutes(app, options) {
10382
10417
  } catch {
10383
10418
  return errorResponse(500, "tool_configuration_error");
10384
10419
  }
10385
- if (!tool3) return errorResponse(404, "tool_not_found");
10420
+ if (!tool3) {
10421
+ const names = Object.keys(tools).filter((name) => typeof tools[name]?.execute === "function").sort();
10422
+ const listed = names.slice(0, 20).join(", ");
10423
+ return errorResponse(
10424
+ 404,
10425
+ "tool_not_found",
10426
+ names.length > 0 ? `Available tools: ${listed}${names.length > 20 ? ", \u2026" : ""}.` : void 0
10427
+ );
10428
+ }
10386
10429
  let text;
10387
10430
  try {
10388
10431
  text = await readBoundedBodyText(c.req.raw, AGENT_TOOL_REQUEST_BODY_CAP);
@@ -10393,15 +10436,26 @@ function registerAgentToolRoutes(app, options) {
10393
10436
  if (body === void 0) return errorResponse(400, "invalid_json");
10394
10437
  if (body === null) return errorResponse(400, "invalid_tool_input");
10395
10438
  let input = body.input;
10439
+ const schema = asSchema(tool3.inputSchema);
10396
10440
  try {
10397
- const validation = asSchema(tool3.inputSchema).validate;
10441
+ const validation = schema.validate;
10398
10442
  if (validation) {
10399
10443
  const result = await validation(input);
10400
- if (!result.success) return errorResponse(400, "invalid_tool_input");
10444
+ if (!result.success) {
10445
+ return errorResponse(400, "invalid_tool_input", validationDetail(result.error));
10446
+ }
10447
+ const dropped = droppedTopLevelKeys(schema, input, result.value);
10448
+ if (dropped.length > 0) {
10449
+ return errorResponse(
10450
+ 400,
10451
+ "invalid_tool_input",
10452
+ `Unknown input field(s): ${dropped.join(", ")} \u2014 the tool's inputSchema lists the accepted fields.`
10453
+ );
10454
+ }
10401
10455
  input = result.value;
10402
10456
  }
10403
- } catch {
10404
- return errorResponse(400, "invalid_tool_input");
10457
+ } catch (error) {
10458
+ return errorResponse(400, "invalid_tool_input", validationDetail(error));
10405
10459
  }
10406
10460
  let output;
10407
10461
  try {