deepspace 0.6.2 → 0.8.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.
Files changed (63) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +22 -8
  3. package/dist/cli.js +10348 -5025
  4. package/dist/cli.js.map +1 -1
  5. package/dist/feature-installer.js +638 -0
  6. package/dist/feature-installer.js.map +1 -0
  7. package/dist/index.d.ts +229 -116
  8. package/dist/index.js +767 -788
  9. package/dist/index.js.map +1 -1
  10. package/dist/server.d.ts +403 -167
  11. package/dist/server.js +498 -367
  12. package/dist/server.js.map +1 -1
  13. package/dist/testing.d.ts +1 -1
  14. package/dist/testing.js +3 -3
  15. package/dist/testing.js.map +1 -1
  16. package/dist/worker.d.ts +541 -159
  17. package/dist/worker.js +611 -367
  18. package/dist/worker.js.map +1 -1
  19. package/features/ai-chat/feature.json +2 -0
  20. package/features/ai-chat/src/AiChatPage.tsx +2 -3
  21. package/features/ai-chat/src/ChatPanel.messages.tsx +344 -0
  22. package/features/ai-chat/src/ChatPanel.stream.ts +397 -0
  23. package/features/ai-chat/src/ChatPanel.tsx +159 -825
  24. package/features/ai-chat/src/__tests__/ChatPanel.stream.test.ts +163 -0
  25. package/features/canvas/src/CanvasListPage.tsx +1 -1
  26. package/features/docs/feature.json +4 -8
  27. package/features/docs/src/DocsEditorPage.tsx +33 -326
  28. package/features/docs/src/DocsListPage.tsx +33 -29
  29. package/features/docs/src/InviteDialog.tsx +11 -40
  30. package/features/docs/src/__tests__/docs-presence-access.test.ts +71 -0
  31. package/features/docs/src/docs-library-types.ts +28 -3
  32. package/features/docs/src/docs-ui.css +1 -4
  33. package/features/docs/src/use-docs-presence-access.ts +330 -0
  34. package/features/file-attachments/feature.json +2 -2
  35. package/features/file-attachments/src/AttachmentPreview.tsx +428 -0
  36. package/features/file-attachments/src/AttachmentsPage.tsx +100 -462
  37. package/features/file-attachments/src/useFilePreview.ts +54 -68
  38. package/features/file-manager/src/FileManagerPage.tsx +1 -1
  39. package/features/integration-test/src/integration.spec.ts +1 -1
  40. package/features/items/feature.json +1 -5
  41. package/features/items/src/ItemsPage.tsx +207 -135
  42. package/features/landing/feature.json +3 -0
  43. package/features/landing/src/LandingPage.tsx +4 -18
  44. package/features/leaderboard/feature.json +1 -5
  45. package/features/leaderboard/src/LeaderboardPage.tsx +333 -198
  46. package/features/messaging/feature.json +0 -4
  47. package/features/messaging/src/ChatMultiPage.tsx +1 -3
  48. package/features/messaging/src/ChatPage.tsx +1 -3
  49. package/features/messaging/src/components/chat/MessageActionSheet.tsx +40 -16
  50. package/features/search-bar/feature.json +8 -3
  51. package/features/search-bar/src/SearchOverlay.tsx +108 -252
  52. package/features/search-bar/src/__tests__/search-model.test.ts +40 -0
  53. package/features/search-bar/src/search-model.ts +223 -0
  54. package/features/tasks/src/TasksPage.tsx +3 -3
  55. package/features/topbar/src/Topbar.tsx +0 -17
  56. package/package.json +1 -2
  57. package/features/docs/src/docs-favorites.ts +0 -18
  58. package/features/docs/src/use-yjs-room-with-awareness.ts +0 -289
  59. package/features/file-attachments/src/attachments-constants.ts +0 -9
  60. package/features/items/src/items-constants.ts +0 -10
  61. package/features/leaderboard/src/leaderboard-constants.ts +0 -21
  62. package/features/messaging/src/components/chat/ReactionPicker.tsx +0 -2
  63. package/scripts/add-feature.cjs +0 -807
package/dist/worker.d.ts CHANGED
@@ -2,9 +2,10 @@ import * as Y from 'yjs';
2
2
  import { LanguageModel, ToolSet, ModelMessage } from 'ai';
3
3
  import * as zod_v4_core from 'zod/v4/core';
4
4
  import * as zod from 'zod';
5
+ import * as better_auth_plugins from 'better-auth/plugins';
5
6
  import * as better_auth from 'better-auth';
6
7
  import { betterAuth } from 'better-auth';
7
- import * as better_auth_plugins from 'better-auth/plugins';
8
+ import { Hono } from 'hono';
8
9
 
9
10
  /**
10
11
  * Wire protocol constants.
@@ -937,7 +938,7 @@ declare abstract class BaseRoom<E = Record<string, unknown>> {
937
938
  private handleWebSocketUpgrade;
938
939
  webSocketMessage(ws: WebSocket, message: ArrayBuffer | string): Promise<void>;
939
940
  webSocketClose(ws: WebSocket, _code: number, _reason: string): Promise<void>;
940
- webSocketError(ws: WebSocket, error: unknown): Promise<void>;
941
+ webSocketError(_ws: WebSocket, error: unknown): Promise<void>;
941
942
  alarm(): Promise<void>;
942
943
  /**
943
944
  * Called when a new WebSocket connects (after auth parsing).
@@ -1035,6 +1036,95 @@ declare abstract class BaseRoom<E = Record<string, unknown>> {
1035
1036
  protected broadcastBinary(data: Uint8Array | ArrayBuffer, exclude?: WebSocket): void;
1036
1037
  }
1037
1038
 
1039
+ /**
1040
+ * Shared type definitions for the DeepSpace SDK
1041
+ *
1042
+ * Types used by both client-side SDK and server-side workers.
1043
+ */
1044
+ type ColumnInterpretation = {
1045
+ kind: 'plain';
1046
+ } | {
1047
+ kind: 'currency';
1048
+ symbol: string;
1049
+ decimals: number;
1050
+ } | {
1051
+ kind: 'date';
1052
+ format?: string;
1053
+ } | {
1054
+ kind: 'datetime';
1055
+ format?: string;
1056
+ } | {
1057
+ kind: 'boolean';
1058
+ trueLabel?: string;
1059
+ falseLabel?: string;
1060
+ } | {
1061
+ kind: 'percent';
1062
+ decimals?: number;
1063
+ } | {
1064
+ kind: 'select';
1065
+ options: string[];
1066
+ } | {
1067
+ kind: 'multiselect';
1068
+ options: string[];
1069
+ } | {
1070
+ kind: 'url';
1071
+ } | {
1072
+ kind: 'email';
1073
+ } | {
1074
+ kind: 'json';
1075
+ } | {
1076
+ kind: 'reference';
1077
+ targetTable: string;
1078
+ displayColumn: string;
1079
+ };
1080
+ interface ColumnDefinition {
1081
+ /** Stable ID override (survives renames). Falls back to `col_{name}`. */
1082
+ id?: string;
1083
+ name: string;
1084
+ storage: 'number' | 'text';
1085
+ interpretation: ColumnInterpretation | string;
1086
+ expression?: string;
1087
+ userBound?: boolean;
1088
+ immutable?: boolean;
1089
+ required?: boolean;
1090
+ default?: unknown;
1091
+ timestampTrigger?: {
1092
+ field: string;
1093
+ value?: unknown;
1094
+ };
1095
+ }
1096
+ type PermissionLevel = boolean | 'own' | 'unclaimed-or-own' | 'collaborator' | 'team' | 'access' | 'published' | 'shared';
1097
+ interface RolePermissions {
1098
+ read: PermissionLevel;
1099
+ /** Create has no existing record to evaluate, so it is an explicit grant. */
1100
+ create: boolean;
1101
+ update: PermissionLevel;
1102
+ delete: PermissionLevel;
1103
+ /** If set, only these columns can be updated by this role. */
1104
+ writableFields?: string[];
1105
+ }
1106
+ interface CollectionSchema {
1107
+ name: string;
1108
+ /** Every collection is stored in typed SQL columns. */
1109
+ columns: ColumnDefinition[];
1110
+ /** Composite uniqueness constraint (for example `['userId', 'taskId']`). */
1111
+ uniqueOn?: string[];
1112
+ /** Ownership column; defaults to the row creator. */
1113
+ ownerField?: string;
1114
+ /** Column containing a JSON array of collaborator user ids. */
1115
+ collaboratorsField?: string;
1116
+ /** Column containing the team id used by team permission rules. */
1117
+ teamField?: string;
1118
+ /** A string is public when equal to `public`; an object supplies an exact value. */
1119
+ visibilityField?: string | {
1120
+ field: string;
1121
+ value: unknown;
1122
+ };
1123
+ /** Permissions per role; `*` is the catch-all role. */
1124
+ permissions: Record<string, RolePermissions>;
1125
+ /** Default role assigned on the `users` collection. */
1126
+ defaultRole?: string;
1127
+ }
1038
1128
  interface Query {
1039
1129
  collection: string;
1040
1130
  where?: Record<string, unknown>;
@@ -1158,8 +1248,6 @@ interface ConnectionAttachment extends UserAttachment {
1158
1248
  subscriptions: Subscription[];
1159
1249
  /** Yjs docs this connection is editing */
1160
1250
  yjsSubscriptions: YjsSubscription[];
1161
- /** Yjs client ID for awareness */
1162
- yjsClientId?: number;
1163
1251
  /** Client-side Yjs awareness clientId (extracted from first awareness message) */
1164
1252
  awarenessClientId?: number;
1165
1253
  }
@@ -1184,63 +1272,7 @@ interface HandlerContext {
1184
1272
  *
1185
1273
  * All collections use typed SQL columns. No document-mode / fields-based storage.
1186
1274
  */
1187
- type ColumnInterpretation = {
1188
- kind: 'plain';
1189
- } | {
1190
- kind: 'currency';
1191
- symbol: string;
1192
- decimals: number;
1193
- } | {
1194
- kind: 'date';
1195
- format?: string;
1196
- } | {
1197
- kind: 'datetime';
1198
- format?: string;
1199
- } | {
1200
- kind: 'boolean';
1201
- trueLabel?: string;
1202
- falseLabel?: string;
1203
- } | {
1204
- kind: 'percent';
1205
- decimals?: number;
1206
- } | {
1207
- kind: 'select';
1208
- options: string[];
1209
- } | {
1210
- kind: 'multiselect';
1211
- options: string[];
1212
- } | {
1213
- kind: 'url';
1214
- } | {
1215
- kind: 'email';
1216
- } | {
1217
- kind: 'json';
1218
- } | {
1219
- kind: 'reference';
1220
- targetTable: string;
1221
- displayColumn: string;
1222
- };
1223
- interface ColumnDefinition {
1224
- /** Stable ID override (survives renames). Falls back to `col_{name}`. */
1225
- id?: string;
1226
- name: string;
1227
- storage: 'number' | 'text';
1228
- interpretation: ColumnInterpretation | string;
1229
- expression?: string;
1230
- /** Auto-populate with current user ID on create. */
1231
- userBound?: boolean;
1232
- /** Cannot be changed after initial creation. */
1233
- immutable?: boolean;
1234
- /** Must be provided on create (non-null). */
1235
- required?: boolean;
1236
- /** Default value if not provided on create. */
1237
- default?: unknown;
1238
- /** Auto-set ISO timestamp when the named field changes (optionally to a specific value). */
1239
- timestampTrigger?: {
1240
- field: string;
1241
- value?: unknown;
1242
- };
1243
- }
1275
+
1244
1276
  interface ResolvedColumn {
1245
1277
  id: string;
1246
1278
  name: string;
@@ -1264,41 +1296,6 @@ declare function rowToData(row: Record<string, unknown>, columns: ResolvedColumn
1264
1296
  declare function dataToColumnValues(data: Record<string, unknown>, columns: ResolvedColumn[]): Record<string, unknown>;
1265
1297
  declare function coerceValue(value: unknown, storage: 'number' | 'text', interpretation: ColumnInterpretation): unknown;
1266
1298
  declare function buildTableSelect(collectionName: string, columns: ResolvedColumn[]): string;
1267
- type PermissionLevel = boolean | 'own' | 'unclaimed-or-own' | 'collaborator' | 'team' | 'access' | 'published' | 'shared';
1268
- interface RolePermissions {
1269
- read: PermissionLevel;
1270
- create: boolean;
1271
- update: PermissionLevel;
1272
- delete: PermissionLevel;
1273
- /** If set, only these columns can be updated by this role. */
1274
- writableFields?: string[];
1275
- }
1276
- interface CollectionSchema {
1277
- name: string;
1278
- /** Column definitions — every collection is stored in a typed SQL table. */
1279
- columns: ColumnDefinition[];
1280
- /** Composite uniqueness constraint (e.g., ['userId', 'taskId']). */
1281
- uniqueOn?: string[];
1282
- /** Column name used for ownership checks (default: `_created_by`). */
1283
- ownerField?: string;
1284
- /** Column containing JSON array of collaborator user IDs. */
1285
- collaboratorsField?: string;
1286
- /** Column containing team ID for team-based access. */
1287
- teamField?: string;
1288
- /**
1289
- * Column controlling per-record read visibility.
1290
- * String: visible when `data[field] === 'public'`.
1291
- * Object: visible when `data[field] === value`.
1292
- */
1293
- visibilityField?: string | {
1294
- field: string;
1295
- value: unknown;
1296
- };
1297
- /** Permissions per role. Use '*' for a catch-all fallback. */
1298
- permissions: Record<string, RolePermissions>;
1299
- /** Default role for new users (only on 'users' collection). */
1300
- defaultRole?: string;
1301
- }
1302
1299
  interface User {
1303
1300
  id: string;
1304
1301
  email: string;
@@ -1433,8 +1430,6 @@ declare class RecordRoom<E = Record<string, unknown>> extends BaseRoom<E> {
1433
1430
  private initPromise;
1434
1431
  /** Yjs docs loaded in memory (key: collection:recordId:fieldName) */
1435
1432
  private yjsDocs;
1436
- /** Next Yjs client ID counter */
1437
- private nextYjsClientId;
1438
1433
  /** Owner user ID — gets admin role automatically */
1439
1434
  private ownerUserId;
1440
1435
  /** True until the first fetch() completes — detects hibernation wake-up */
@@ -1449,7 +1444,7 @@ declare class RecordRoom<E = Record<string, unknown>> extends BaseRoom<E> {
1449
1444
  * The HTTP debug API (`/api/debug/*`) runs arbitrary SQL and role changes
1450
1445
  * with no auth of its own, so it is gated here at the DO's single ingress.
1451
1446
  * Off unless a deployment opts in with `ALLOW_DEBUG_ROUTES=true`
1452
- * (`deepspace dev`/`test` set it automatically). Deployments holding shared
1447
+ * (`deepspace dev start`/`test run` set it automatically). Deployments holding shared
1453
1448
  * data override this to always return false.
1454
1449
  */
1455
1450
  protected get debugRoutesEnabled(): boolean;
@@ -1474,7 +1469,7 @@ declare class RecordRoom<E = Record<string, unknown>> extends BaseRoom<E> {
1474
1469
  protected onMessage(): void;
1475
1470
  webSocketMessage(ws: WebSocket, message: ArrayBuffer | string): Promise<void>;
1476
1471
  webSocketClose(ws: WebSocket, code: number, reason: string): Promise<void>;
1477
- webSocketError(ws: WebSocket, error: unknown): Promise<void>;
1472
+ webSocketError(_ws: WebSocket, error: unknown): Promise<void>;
1478
1473
  private handleRecordMessage;
1479
1474
  private handleListSchemas;
1480
1475
  private createHandlerContext;
@@ -1519,7 +1514,7 @@ declare class YjsRoom<E = Record<string, unknown>> extends BaseRoom<E> {
1519
1514
  type: string;
1520
1515
  [key: string]: unknown;
1521
1516
  }): void;
1522
- protected onBinaryMessage(ws: WebSocket, user: UserAttachment, data: ArrayBuffer): void;
1517
+ protected onBinaryMessage(ws: WebSocket, _user: UserAttachment, data: ArrayBuffer): void;
1523
1518
  protected onDisconnect(ws: WebSocket, _user: UserAttachment): void;
1524
1519
  private handleSync;
1525
1520
  private handleAwareness;
@@ -1586,7 +1581,7 @@ declare abstract class GameRoom<E = Record<string, unknown>> extends BaseRoom<E>
1586
1581
  type: string;
1587
1582
  [key: string]: unknown;
1588
1583
  }): Promise<void>;
1589
- protected onDisconnect(ws: WebSocket, user: UserAttachment): void;
1584
+ protected onDisconnect(_ws: WebSocket, user: UserAttachment): void;
1590
1585
  protected onAlarm(): Promise<void>;
1591
1586
  private checkAutoStart;
1592
1587
  private startGame;
@@ -1686,7 +1681,7 @@ declare class CanvasRoom<E = Record<string, unknown>> extends BaseRoom<E> {
1686
1681
  type: string;
1687
1682
  [key: string]: unknown;
1688
1683
  }): Promise<void>;
1689
- protected onDisconnect(ws: WebSocket, user: UserAttachment): void;
1684
+ protected onDisconnect(_ws: WebSocket, user: UserAttachment): void;
1690
1685
  private pushUndo;
1691
1686
  private clearRedo;
1692
1687
  private handleUndo;
@@ -1740,6 +1735,19 @@ declare class PresenceRoom<E = Record<string, unknown>> extends BaseRoom<E> {
1740
1735
  protected onDisconnect(ws: WebSocket, user: UserAttachment): void;
1741
1736
  }
1742
1737
 
1738
+ /** Pure validation and evaluation for CronRoom schedules. */
1739
+ interface CronTask {
1740
+ name: string;
1741
+ /** Interval in minutes (interval mode) — mutually exclusive with `schedule`. */
1742
+ intervalMinutes?: number;
1743
+ /** 5-field cron expression (cron mode) — requires `timezone`. */
1744
+ schedule?: string;
1745
+ /** IANA timezone string (e.g. "America/New_York"). Required with `schedule`. */
1746
+ timezone?: string;
1747
+ /** Whether the task starts paused. */
1748
+ paused?: boolean;
1749
+ }
1750
+
1743
1751
  /**
1744
1752
  * CronRoom — Per-app scheduled task execution Durable Object.
1745
1753
  *
@@ -1758,17 +1766,6 @@ declare class PresenceRoom<E = Record<string, unknown>> extends BaseRoom<E> {
1758
1766
  * Message types: cron.*
1759
1767
  */
1760
1768
 
1761
- interface CronTask {
1762
- name: string;
1763
- /** Interval in minutes (interval mode) — mutually exclusive with `schedule`. */
1764
- intervalMinutes?: number;
1765
- /** 5-field cron expression (cron mode) — requires `timezone`. */
1766
- schedule?: string;
1767
- /** IANA timezone string (e.g. "America/New_York"). Required with `schedule`. */
1768
- timezone?: string;
1769
- /** Whether the task starts paused. */
1770
- paused?: boolean;
1771
- }
1772
1769
  interface CronRoomConfig {
1773
1770
  tasks: CronTask[];
1774
1771
  }
@@ -2523,6 +2520,8 @@ declare class Awareness {
2523
2520
  * Remove awareness states for disconnected clients
2524
2521
  */
2525
2522
  removeStates(clientIds: number[]): void;
2523
+ /** Release all state and listeners owned by this awareness instance. */
2524
+ destroy(): void;
2526
2525
  }
2527
2526
  /**
2528
2527
  * Encode a full awareness message
@@ -2541,11 +2540,99 @@ declare function handleAwarenessMessage(awareness: Awareness, data: Uint8Array):
2541
2540
  */
2542
2541
  declare function getMessageType(data: Uint8Array): number;
2543
2542
 
2543
+ /**
2544
+ * Wildcard-aware CORS origin matching for the platform workers.
2545
+ *
2546
+ * Hono's array form of `cors({ origin: [...] })` is an exact `includes()` — it
2547
+ * never expands `*`. Every worker that listed `https://*.app.space` or
2548
+ * `http://localhost:*` in an array had a dead entry: the wildcard rows matched
2549
+ * nothing, silently narrowing the effective CORS surface to the literal
2550
+ * entries. This helper is the single implementation both the api and deploy
2551
+ * workers pass to Hono's function-form `origin`, so the pattern semantics
2552
+ * can't drift between them.
2553
+ *
2554
+ * `*` stands for exactly one host label or a port: it never crosses a dot or
2555
+ * a slash, so `https://*.app.space` matches `https://x.app.space` but neither
2556
+ * `https://a.b.app.space` nor `https://x.app.space.evil.com`.
2557
+ */
2558
+ declare function matchOrigin(origin: string, patterns: string[]): string | null;
2559
+ /**
2560
+ * The platform's standard browser-origin allow-list, derived from the
2561
+ * environment's apexes so a second constellation (staging) trusts its own
2562
+ * hosts and only its own. Both values are explicit deployment-plane config.
2563
+ * Dedupes for environments that serve both roles from one apex.
2564
+ */
2565
+ declare function platformCorsPatterns(env: {
2566
+ APP_DOMAIN: string;
2567
+ PLATFORM_DOMAIN: string;
2568
+ }): string[];
2569
+
2570
+ /**
2571
+ * Deployed-app quota defaults — the ONE copy.
2572
+ *
2573
+ * Two workers use these numbers for different jobs: the deploy worker
2574
+ * ENFORCES them at registration time, the api worker DISPLAYS them via
2575
+ * GET /api/plan-limits. They used to be independent literal sets (plus the
2576
+ * same numbers again in six wrangler [vars] blocks as overrides) and had
2577
+ * already diverged once — the display copy was missing the admin tier
2578
+ * entirely. The env vars remain the per-plane override mechanism; only the
2579
+ * fallbacks live here.
2580
+ */
2581
+ declare const DEPLOYED_APPS_DEFAULTS: {
2582
+ readonly free: 1;
2583
+ readonly starter: 4;
2584
+ readonly premium: 10;
2585
+ readonly admin: 100;
2586
+ };
2587
+ /** Parse a quota env override; anything non-integer/negative = fallback. */
2588
+ declare function parseQuotaLimit(raw: string | undefined, fallback: number): number;
2589
+
2590
+ /**
2591
+ * The ONE registry client. Every platform worker reaches the app-registry
2592
+ * Durable Object (hosted by the deploy worker, singleton `v1:global`) through
2593
+ * a cross-script REGISTRY binding — and before this module, each of the five
2594
+ * workers hand-rolled its own copy of the same mechanics: the instance name
2595
+ * appeared in 6 places, the `https://registry/` URL in 6, `APP_ID_RE` in 5,
2596
+ * and `RegistryClientError` + `registryErrorJson` existed byte-identical in
2597
+ * two workers. Copies that must agree and nothing enforcing it.
2598
+ *
2599
+ * This module owns the MECHANICS: instance name, stub lookup, the wire call,
2600
+ * the error type, and the standard route mapping. Each worker still declares
2601
+ * its own typed convenience wrapper listing only the actions it uses — that
2602
+ * subset is genuinely per-worker; the plumbing is not.
2603
+ */
2604
+ /** The singleton registry instance — one DO holds every app/route/collaborator. */
2605
+ declare const REGISTRY_INSTANCE = "v1:global";
2606
+ /** App id shape: a ULID-minted `app_…` id, or a legacy name-as-id. */
2607
+ declare const APP_ID_RE: RegExp;
2608
+ /** ONLY a ULID-minted id — surfaces that must not accept a legacy name. */
2609
+ declare const STRICT_APP_ID_RE: RegExp;
2610
+ declare class RegistryClientError extends Error {
2611
+ readonly code: string;
2612
+ readonly status: number;
2613
+ constructor(message: string, code: string, status: number);
2614
+ }
2615
+ declare function registryStub(ns: DurableObjectNamespace): DurableObjectStub;
2616
+ /**
2617
+ * One registry action over the wire. Non-2xx answers throw
2618
+ * {@link RegistryClientError} carrying the DO's structured `code` (or
2619
+ * `'error'` for a transport-shaped body) — callers distinguish a registry-
2620
+ * REPORTED miss (`code === 'not_found'`) from an outage by that code, never
2621
+ * by treating every throw as "not found".
2622
+ */
2623
+ declare function callRegistry<T>(stub: DurableObjectStub, body: {
2624
+ action: string;
2625
+ } & Record<string, unknown>): Promise<T>;
2626
+ /** Standard mapping of a registry failure onto a route response. */
2627
+ declare function registryErrorJson(c: {
2628
+ json: (body: unknown, status?: number) => Response;
2629
+ }, err: unknown): Response;
2630
+
2544
2631
  /**
2545
2632
  * Tools API Types and Definitions
2546
2633
  *
2547
2634
  * MCP-like interface for agent tool calls.
2548
- * Built-in tools for storage and backup operations.
2635
+ * Built-in tools for records, schemas, users, and Yjs documents.
2549
2636
  */
2550
2637
  interface ToolSchema {
2551
2638
  name: string;
@@ -2593,7 +2680,7 @@ declare const DEFAULT_QUERY_LIMIT = 50;
2593
2680
  */
2594
2681
  declare function applyAiToolDefaults(toolName: string, params: Record<string, unknown>): Record<string, unknown>;
2595
2682
  /**
2596
- * Built-in tool definitions for storage, record, schema, user, and backup operations
2683
+ * Built-in tool definitions for record, schema, user, and Yjs operations.
2597
2684
  */
2598
2685
  declare const BUILT_IN_TOOLS: ToolSchema[];
2599
2686
 
@@ -2789,7 +2876,7 @@ type ActionHandler<TEnv = Record<string, unknown>> = (ctx: ActionContext<TEnv>)
2789
2876
  * in deployed apps.
2790
2877
  *
2791
2878
  * 2. **HTTPS URL** (`env.API_WORKER_URL` / `env.PLATFORM_WORKER_URL`) — the
2792
- * fallback used in local development. `deepspace dev` writes these
2879
+ * fallback used in local development. `deepspace dev start` writes these
2793
2880
  * into `.dev.vars`, which `wrangler dev` exposes as env vars. Service
2794
2881
  * bindings don't work cross-process under `wrangler dev` for SDK apps,
2795
2882
  * so the URL is the only working path in dev.
@@ -2807,7 +2894,7 @@ type ActionHandler<TEnv = Record<string, unknown>> = (ctx: ActionContext<TEnv>)
2807
2894
  * History: a previous in-tree helper folded the binding/URL fallback into
2808
2895
  * the AI module's `resolveTransport`. Inline call sites in the starter
2809
2896
  * template (integrations, files, debug) used `c.env.X.fetch(...)` directly,
2810
- * which broke `npx deepspace dev` for any app calling those routes — the
2897
+ * which broke `npx deepspace dev start` for any app calling those routes — the
2811
2898
  * binding is undefined locally, so the fetch threw. These helpers
2812
2899
  * standardize on the same shape `resolveTransport` had, so every upstream
2813
2900
  * call works in both dev and prod.
@@ -2928,13 +3015,13 @@ declare function buildCronContext(env: CronEnv, ownerUserId: string, roomId?: st
2928
3015
  * - Service binding `env.API_WORKER` (Cloudflare Fetcher) — preferred in
2929
3016
  * production if the app has declared the binding in wrangler.toml.
2930
3017
  * - HTTPS URL `env.API_WORKER_URL` — used in local dev and in production
2931
- * for apps that don't declare the binding. `deepspace dev` writes this
3018
+ * for apps that don't declare the binding. `deepspace dev start` writes this
2932
3019
  * into `.dev.vars` automatically.
2933
3020
  *
2934
3021
  * Auth is automatic by default:
2935
3022
  * - For server-side autonomous calls (cron, DO alarms, background agents),
2936
3023
  * the helper reads the long-lived `env.APP_OWNER_JWT` minted at deploy
2937
- * time (or by `deepspace dev` in local development) and uses it for the
3024
+ * time (or by `deepspace dev start` in local development) and uses it for the
2938
3025
  * proxy auth header. The owner is billed automatically via the JWT sub.
2939
3026
  * - For user-initiated calls (e.g. an `/api/ai/chat` route handling a
2940
3027
  * browser request), pass `options.authToken` explicitly with the user's
@@ -2961,7 +3048,7 @@ type DeepSpaceModelFactory = (modelId: string) => LanguageModel;
2961
3048
  type Provider = 'anthropic' | 'openai' | 'cerebras';
2962
3049
  interface DeepSpaceAIEnv extends ApiWorkerEnv {
2963
3050
  /**
2964
- * Long-lived owner-scoped JWT minted at deploy time (or by `deepspace dev`).
3051
+ * Long-lived owner-scoped JWT minted at deploy time (or by `deepspace dev start`).
2965
3052
  * Used as the default proxy auth token when `options.authToken` is absent.
2966
3053
  * Bills the app owner.
2967
3054
  */
@@ -3038,10 +3125,9 @@ declare function composioTools(env: ApiWorkerEnv, options: ComposioToolsOptions)
3038
3125
  * own bundle. The platform holds the binding; consumers call this
3039
3126
  * helper to get PNG bytes for a URL.
3040
3127
  *
3041
- * The platform enforces: a host allowlist (*.app.space / *.deep.space),
3042
- * a per-app sliding rate limit, and viewport/timeout clamping. Returns
3043
- * `null` on any non-2xx — callers should treat as "no preview available"
3044
- * and surface their own fallback UX.
3128
+ * The platform enforces HTTPS, a DeepSpace host allowlist, a per-app rate
3129
+ * limit, and one fixed viewport-only capture profile. Returns `null` on any
3130
+ * non-2xx — callers should treat that as "no preview available".
3045
3131
  *
3046
3132
  * Auth is the same HMAC-of-appId pattern `/internal/files` uses:
3047
3133
  * x-app-identity-token = hmac(PLATFORM_IDENTITY_SECRET, DEEPSPACE_APP_ID)
@@ -3051,16 +3137,6 @@ declare function composioTools(env: ApiWorkerEnv, options: ComposioToolsOptions)
3051
3137
  * so this helper is a thin wrapper — no extra secrets to manage.
3052
3138
  */
3053
3139
 
3054
- interface ScreenshotOptions {
3055
- url: string;
3056
- viewport?: {
3057
- width: number;
3058
- height: number;
3059
- };
3060
- waitUntil?: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
3061
- timeoutMs?: number;
3062
- fullPage?: boolean;
3063
- }
3064
3140
  interface ScreenshotEnv extends PlatformWorkerEnv {
3065
3141
  /** Immutable app id — the identity the platform verifies (HMAC input). */
3066
3142
  DEEPSPACE_APP_ID: string;
@@ -3074,14 +3150,13 @@ interface ScreenshotResult {
3074
3150
  contentType: string;
3075
3151
  }
3076
3152
  /**
3077
- * Capture a screenshot of `opts.url` and return the PNG bytes.
3153
+ * Capture a screenshot of `url` and return the PNG bytes.
3078
3154
  *
3079
3155
  * Returns null on capture failure (target unreachable, timeout, BR
3080
- * binding misconfigured platform-side). The platform endpoint logs the
3081
- * underlying error; callers should treat null as "no preview available"
3082
- * and surface their own UX fallback.
3156
+ * binding misconfigured platform-side). The platform logs a generic failure
3157
+ * without target details; callers should surface their own fallback UX.
3083
3158
  */
3084
- declare function captureScreenshot(env: ScreenshotEnv, opts: ScreenshotOptions): Promise<ScreenshotResult | null>;
3159
+ declare function captureScreenshot(env: ScreenshotEnv, url: string): Promise<ScreenshotResult | null>;
3085
3160
 
3086
3161
  /**
3087
3162
  * Chat context pipeline — keeps the per-request payload to the LLM bounded.
@@ -3225,23 +3300,8 @@ declare function makeDefaultSummarizer(env: DeepSpaceAIEnv, options?: {
3225
3300
  * The tools API returns records as `{ recordId, data, createdAt, updatedAt }`
3226
3301
  * envelopes; helpers below flatten them into ChatRow / ChatMessageRow.
3227
3302
  */
3228
- /**
3229
- * Canonical chat row.
3230
- *
3231
- * `recordId` is the primary identifier — same envelope shape as every
3232
- * other DeepSpace data type (records.* tools, useQuery results, etc.).
3233
- *
3234
- * `id` is kept as a deprecated alias so existing callers don't break,
3235
- * but every new caller should prefer `recordId`. Without this rename
3236
- * an integrator who reads `chat.recordId` (the obvious thing given the
3237
- * rest of the SDK) silently gets `undefined`, then ships code that
3238
- * sends `{"chatId": undefined}` to `/api/ai/chat` and gets back a 400
3239
- * with a misleading error.
3240
- */
3241
3303
  type ChatRow = {
3242
3304
  recordId: string;
3243
- /** @deprecated Use `recordId`. Retained for backward compatibility. */
3244
- id: string;
3245
3305
  userId: string;
3246
3306
  title: string;
3247
3307
  model?: string;
@@ -3252,8 +3312,6 @@ type ChatRow = {
3252
3312
  };
3253
3313
  type ChatMessageRow = {
3254
3314
  recordId: string;
3255
- /** @deprecated Use `recordId`. Retained for backward compatibility. */
3256
- id: string;
3257
3315
  chatId: string;
3258
3316
  userId: string;
3259
3317
  role: 'user' | 'assistant' | 'system';
@@ -3568,7 +3626,7 @@ declare function decodeJwtPayload(token: string | null | undefined): TokenDebugI
3568
3626
  /**
3569
3627
  * Test-account identification, shared by every platform worker.
3570
3628
  *
3571
- * Test accounts (created via `deepspace test-accounts`) are real Better Auth
3629
+ * Test accounts (created via `deepspace test accounts`) are real Better Auth
3572
3630
  * users demarcated three ways, and a caller may present as any of them
3573
3631
  * depending on where the check runs:
3574
3632
  * - their email always ends with @deepspace.test (enforced at creation)
@@ -3629,8 +3687,184 @@ interface DeepSpaceAuthConfig {
3629
3687
  emailAndPassword?: boolean;
3630
3688
  /** Trusted origins for CORS */
3631
3689
  trustedOrigins?: string[];
3690
+ /**
3691
+ * Called after a new user row is created (any flow: social OAuth callback,
3692
+ * email/password, server-side `auth.api.signUpEmail`). When the signup came
3693
+ * in over HTTP, `ctx.request` exposes the inbound request; some better-auth
3694
+ * entry points carry standalone `ctx.headers` instead of (or as well as) a
3695
+ * request, so both are forwarded. For server-side creations (`auth.api.*`
3696
+ * calls) an endpoint context usually still exists but may carry NEITHER —
3697
+ * guard every field.
3698
+ *
3699
+ * Better Auth awaits `user.create.after` hooks inline before the response
3700
+ * is sent, so keep this cheap (e.g. a single D1 write) and hand slow work
3701
+ * to `ctx.waitUntil` at the call site. Exceptions are caught and logged so
3702
+ * a failing observer can never break signup itself.
3703
+ */
3704
+ onUserCreated?: (user: {
3705
+ id: string;
3706
+ email: string;
3707
+ name: string;
3708
+ }, ctx: {
3709
+ request?: Request;
3710
+ headers?: Headers;
3711
+ } | null) => Promise<void>;
3632
3712
  }
3633
3713
  declare function createDeepSpaceAuth(config: DeepSpaceAuthConfig): better_auth.Auth<{
3714
+ databaseHooks: {
3715
+ user?: {
3716
+ create?: {
3717
+ before?: (user: better_auth.User & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void | {
3718
+ data: {
3719
+ id?: string | undefined;
3720
+ createdAt?: Date | undefined;
3721
+ updatedAt?: Date | undefined;
3722
+ email?: string | undefined;
3723
+ emailVerified?: boolean | undefined;
3724
+ name?: string | undefined;
3725
+ image?: string | null | undefined;
3726
+ } & Record<string, any>;
3727
+ }>;
3728
+ after?: (user: better_auth.User & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3729
+ };
3730
+ update?: {
3731
+ before?: (user: Partial<better_auth.User> & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void | {
3732
+ data: {
3733
+ [x: string]: any;
3734
+ id?: string | undefined;
3735
+ createdAt?: Date | undefined;
3736
+ updatedAt?: Date | undefined;
3737
+ email?: string | undefined;
3738
+ emailVerified?: boolean | undefined;
3739
+ name?: string | undefined;
3740
+ image?: string | null | undefined;
3741
+ };
3742
+ }>;
3743
+ after?: (user: better_auth.User & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3744
+ };
3745
+ delete?: {
3746
+ before?: (user: better_auth.User & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void>;
3747
+ after?: (user: better_auth.User & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3748
+ };
3749
+ };
3750
+ session?: {
3751
+ create?: {
3752
+ before?: (session: better_auth.Session & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void | {
3753
+ data: {
3754
+ id?: string | undefined;
3755
+ createdAt?: Date | undefined;
3756
+ updatedAt?: Date | undefined;
3757
+ userId?: string | undefined;
3758
+ expiresAt?: Date | undefined;
3759
+ token?: string | undefined;
3760
+ ipAddress?: string | null | undefined;
3761
+ userAgent?: string | null | undefined;
3762
+ } & Record<string, any>;
3763
+ }>;
3764
+ after?: (session: better_auth.Session & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3765
+ };
3766
+ update?: {
3767
+ before?: (session: Partial<better_auth.Session> & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void | {
3768
+ data: {
3769
+ [x: string]: any;
3770
+ id?: string | undefined;
3771
+ createdAt?: Date | undefined;
3772
+ updatedAt?: Date | undefined;
3773
+ userId?: string | undefined;
3774
+ expiresAt?: Date | undefined;
3775
+ token?: string | undefined;
3776
+ ipAddress?: string | null | undefined;
3777
+ userAgent?: string | null | undefined;
3778
+ };
3779
+ }>;
3780
+ after?: (session: better_auth.Session & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3781
+ };
3782
+ delete?: {
3783
+ before?: (session: better_auth.Session & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void>;
3784
+ after?: (session: better_auth.Session & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3785
+ };
3786
+ };
3787
+ account?: {
3788
+ create?: {
3789
+ before?: (account: better_auth.Account, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void | {
3790
+ data: {
3791
+ id?: string | undefined;
3792
+ createdAt?: Date | undefined;
3793
+ updatedAt?: Date | undefined;
3794
+ providerId?: string | undefined;
3795
+ accountId?: string | undefined;
3796
+ userId?: string | undefined;
3797
+ accessToken?: string | null | undefined;
3798
+ refreshToken?: string | null | undefined;
3799
+ idToken?: string | null | undefined;
3800
+ accessTokenExpiresAt?: Date | null | undefined;
3801
+ refreshTokenExpiresAt?: Date | null | undefined;
3802
+ scope?: string | null | undefined;
3803
+ password?: string | null | undefined;
3804
+ } & Record<string, any>;
3805
+ }>;
3806
+ after?: (account: better_auth.Account, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3807
+ };
3808
+ update?: {
3809
+ before?: (account: Partial<better_auth.Account> & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void | {
3810
+ data: {
3811
+ [x: string]: any;
3812
+ id?: string | undefined;
3813
+ createdAt?: Date | undefined;
3814
+ updatedAt?: Date | undefined;
3815
+ providerId?: string | undefined;
3816
+ accountId?: string | undefined;
3817
+ userId?: string | undefined;
3818
+ accessToken?: string | null | undefined;
3819
+ refreshToken?: string | null | undefined;
3820
+ idToken?: string | null | undefined;
3821
+ accessTokenExpiresAt?: Date | null | undefined;
3822
+ refreshTokenExpiresAt?: Date | null | undefined;
3823
+ scope?: string | null | undefined;
3824
+ password?: string | null | undefined;
3825
+ };
3826
+ }>;
3827
+ after?: (account: better_auth.Account & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3828
+ };
3829
+ delete?: {
3830
+ before?: (account: better_auth.Account & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void>;
3831
+ after?: (account: better_auth.Account & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3832
+ };
3833
+ };
3834
+ verification?: {
3835
+ create?: {
3836
+ before?: (verification: better_auth.Verification & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void | {
3837
+ data: {
3838
+ id?: string | undefined;
3839
+ createdAt?: Date | undefined;
3840
+ updatedAt?: Date | undefined;
3841
+ value?: string | undefined;
3842
+ expiresAt?: Date | undefined;
3843
+ identifier?: string | undefined;
3844
+ } & Record<string, any>;
3845
+ }>;
3846
+ after?: (verification: better_auth.Verification & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3847
+ };
3848
+ update?: {
3849
+ before?: (verification: Partial<better_auth.Verification> & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void | {
3850
+ data: {
3851
+ [x: string]: any;
3852
+ id?: string | undefined;
3853
+ createdAt?: Date | undefined;
3854
+ updatedAt?: Date | undefined;
3855
+ value?: string | undefined;
3856
+ expiresAt?: Date | undefined;
3857
+ identifier?: string | undefined;
3858
+ };
3859
+ }>;
3860
+ after?: (verification: better_auth.Verification & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3861
+ };
3862
+ delete?: {
3863
+ before?: (verification: better_auth.Verification & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<boolean | void>;
3864
+ after?: (verification: better_auth.Verification & Record<string, unknown>, context: better_auth.GenericEndpointContext | null) => Promise<void>;
3865
+ };
3866
+ };
3867
+ } | undefined;
3634
3868
  plugins: [{
3635
3869
  id: "organization";
3636
3870
  version: string;
@@ -4483,6 +4717,10 @@ declare function createDeepSpaceAuth(config: DeepSpaceAuthConfig): better_auth.A
4483
4717
  database: D1Database;
4484
4718
  baseURL: string;
4485
4719
  secret: string;
4720
+ session: {
4721
+ expiresIn: number;
4722
+ updateAge: number;
4723
+ };
4486
4724
  emailAndPassword: {
4487
4725
  enabled: boolean;
4488
4726
  };
@@ -4498,4 +4736,148 @@ type DeepSpaceAuth = ReturnType<typeof createDeepSpaceAuth>;
4498
4736
  /** Collections that bypass schema checks (permissive access) */
4499
4737
  declare const SYSTEM_COLLECTIONS: Set<string>;
4500
4738
 
4501
- export { AI_CHATS_SCHEMA, AI_MESSAGES_SCHEMA, ALLOWED_BINDING_TYPES, APP_NAME_RULES, AUTO_PROVISIONABLE_TYPES, AUTO_PROVISION_SENTINEL, type ActionContext, type ActionHandler, type ActionResult, type ActionTools, type ApiWorkerEnv, type AppNameResolution, type AppNameValidation, type AuthWorkerEnv, Awareness, type AwarenessState, type AwarenessStates, BASE_USERS_SCHEMA, BUILT_IN_TOOLS, type BaseMessage, BaseRoom, CHANNELS_SCHEMA, CHANNEL_INVITATIONS_SCHEMA, CHANNEL_MEMBERS_SCHEMA, CONVERSATION_SCHEMAS, COST_RATES, CanvasRoom, type CanvasShape, type ChatContextConfig, type ChatMessageRow, type ChatRow, type ChatTurn, type ClientMessage, type CollectionPermissionSummary, type CollectionSchema, type ColumnDefinition, type ColumnInterpretation, type ComposioToolsOptions, type ConnectionAttachment, type ConvMemberData, type ConvMessageData, type ConvReactionData, type ConvReadCursorData, type ConvVoteData, type ConversationStateData, type CronContext, type CronExecution, CronRoom, type CronRoomConfig, type CronTask, type CustomBinding, type CustomBindingManifest, DEFAULT_CONTEXT_CONFIG, DEFAULT_DO_MANIFEST, DEFAULT_QUERY_LIMIT, DIRECTORY_SCHEMAS, type DOBindings, type DOManifest, type DOManifestEntry, type DeepSpaceAIEnv, type DeepSpaceAIOptions, type DeepSpaceAuth, type DeepSpaceAuthConfig, type DirectoryCommunityData, type DirectoryConversationData, type DirectoryMembershipData, type DirectoryPostData, type DoMigrationDirective, type DoMigrationPlan, type ExistingDOBinding, GLOBAL_DO_TYPES, GLOBAL_DO_TYPE_NAMES, type GameInput, GameRoom, type GameRoomConfig, type GetActionData, type GlobalDOType, type HandlerContext, type Job, type JobContext, JobRoom, type JobRoomConfig, type JobStatus, type JwtClaims, type JwtVerifierConfig, MESSAGES_SCHEMA, MSG, MSG_AWARENESS, MSG_SYNC, MSG_SYNC_STEP1, MSG_SYNC_STEP2, MSG_SYNC_UPDATE, MSG_YJS_AWARENESS, MSG_YJS_SYNC, type MessageHandlers, type MsgType, type MutateActionData, type PermissionAnalysis, type PermissionContext, type PermissionLevel, type PermissionSource, type PlatformWorkerEnv, type Player, type PrefixResult, type PresencePeer, PresenceRoom, type ProtocolMessage, type QueryActionData, REACTIONS_SCHEMA, READ_RECEIPTS_SCHEMA, RESERVED_BINDING_NAMES, RESERVED_COLLECTION_NAMES, ROLE_ADMIN, ROLE_ANONYMOUS, ROLE_DEFAULT, RecordRoom, type RecordRoomConfig, type ResolvedColumn, type ResolvedPermission, type RolePermissions, type RunMigrationsResult, SYSTEM_COLLECTIONS, SYSTEM_MANAGED_COLUMNS, SchemaRegistry, type ScopeContext, type ScopedR2Auth, type ScopedR2Config, type ScopedR2Handler, type ScreenshotEnv, type ScreenshotOptions, type ScreenshotResult, type ServerMessage, type SharedConnection, type StoredRecord, type Summarizer, type SyncResult, TEST_ACCOUNT_EMAIL_SUFFIX, type TokenDebugInfo, type ToolResult, type ToolSchema, USERS_COLUMNS, type User, type UserAttachment, VOTING_SCHEMAS, type ValidationError, type VerifiedAuth, type VerifyOutcome, type VerifyResult, type Viewport, WORKSPACE_SCHEMAS, YjsRoom, analyzePermissions, apiWorkerFetch, appendMessage, applyAiToolDefaults, applySlidingWindow, authWorkerFetch, bindingManifestFromOutputConfig, buildCronContext, buildTableSelect, buildUiParts, canCreate, canDelete, canRead, canUpdate, capToolResultSize, captureScreenshot, checkFieldPermissions, clientBuild, coerceValue, collectionTableName, columnId, composioTools, computeDoMigration, computeHmacHex, createChat, createDecoder, createDeepSpaceAI, createDeepSpaceAuth, createEncoder, createScopedR2Handler, dataToColumnValues, decodeJwtPayload, deleteChatCascade, dispatch, encode, encodeAwarenessMessage, encodeSyncStep1, encodeSyncStep2, encodeUpdate, enqueueJob, getChat, getGlobalDOSchemas, getGlobalDOType, getMessageType, getRolePermissions, handleAwarenessMessage, handleSyncMessage, hasContent, isAutoProvision, isOwner, isTestAccountClaims, isTestAccountEmail, isTestAccountTier, lintSchema, loadMessages, makeDefaultSummarizer, meterAi, meterUsage, meterVectorize, noopPermissionContext, platformWorkerFetch, prepareMessagesWithCompaction, priceBindingUsageEvent, readVarUint, readVarUint8Array, resolveAppName, resolveColumn, rowToData, runMigrations, serverBuild, timingSafeEqualHex, timingSafeEqualStrings, toUint8Array, totalChars, truncateOldToolResults, turnsToCoreMessages, unwrapToolOutput, updateChat, validateAppName, validateBindingManifest, validateDoManifest, verifyJwt, workspaceAccountsSchema, workspaceContentSharesSchema, workspaceEmailHandlesSchema, workspaceFormResponsesSchema, workspacePeopleSchema, workspaceProjectsSchema, workspaceTagsSchema, workspaceTasksSchema, workspaceTeamMembersSchema, workspaceTeamsSchema, workspaceTransactionsSchema, writeVarUint, writeVarUint8Array };
4739
+ /**
4740
+ * Client-error ingestion route (opt-in) — the Worker half of client-side
4741
+ * error reporting.
4742
+ *
4743
+ * Mount it in your app Worker with a single line:
4744
+ *
4745
+ * import { registerClientErrorRoute } from 'deepspace/worker'
4746
+ * registerClientErrorRoute(app) // BEFORE the app.all('/_deepspace/*') proxy
4747
+ *
4748
+ * Then, in the browser, `installClientErrorReporter()` (from 'deepspace')
4749
+ * forwards uncaught errors here. The handler runs in the app's OWN Worker, so
4750
+ * the `console.error` it emits is tagged by Cloudflare with this app's id —
4751
+ * meaning a browser can only ever write to its own app's log stream, never
4752
+ * another tenant's or the platform's. Reports then surface in `deepspace logs`
4753
+ * (and the dashboard) tagged `CLIENT`.
4754
+ *
4755
+ * Anonymous by design (logged-out visitors hit client errors too), so the
4756
+ * defenses are size caps (normalizeClientErrorReport) + a best-effort
4757
+ * per-isolate throttle. It never blocks the page: it returns 204 and swallows
4758
+ * work quickly.
4759
+ */
4760
+
4761
+ /**
4762
+ * Handle one client-error report. Framework-agnostic — pass a raw `Request`.
4763
+ * Returns 204 on success, 400 on a malformed/empty body, 429 when throttled.
4764
+ */
4765
+ declare function handleClientErrorReport(request: Request): Promise<Response>;
4766
+ /**
4767
+ * Register `POST /_deepspace/client-errors` on your Hono app. Mount it BEFORE
4768
+ * the `app.all('/_deepspace/*')` proxy so the specific route wins the match.
4769
+ */
4770
+ declare function registerClientErrorRoute(app: Hono<any, any, any>): void;
4771
+
4772
+ /**
4773
+ * Client-side error reporting — shared contract.
4774
+ *
4775
+ * Browser JS errors never invoke the app's Worker, so they never reach
4776
+ * Workers Logs and are invisible to `deepspace logs`. The opt-in reporter
4777
+ * (`installClientErrorReporter`, client entry) forwards them to the app's own
4778
+ * Worker via `registerClientErrorRoute` (worker entry), which `console.error`s
4779
+ * a marker-prefixed envelope. The platform log reader recognises the marker
4780
+ * and tags the event `source: 'client'`.
4781
+ *
4782
+ * This module is isomorphic — no DOM, no Hono — so both halves import the
4783
+ * exact same marker, caps, and normaliser and can never drift.
4784
+ */
4785
+ /**
4786
+ * Prefix the Worker route prepends before JSON-stringifying a report into a
4787
+ * single `console.error` line. The platform mapper
4788
+ * (platform/deploy-worker/src/lib/workers-logs.ts) detects this prefix to set
4789
+ * `source: 'client'`. Deliberately distinctive so an ordinary app log is
4790
+ * vanishingly unlikely to collide. The marker is added SERVER-SIDE by the app
4791
+ * Worker — a browser cannot forge it onto a genuine server log.
4792
+ *
4793
+ * The platform copy is kept in sync by a drift test; if you change this
4794
+ * string, that test fails until the platform const matches.
4795
+ */
4796
+ declare const CLIENT_LOG_MARKER = "[deepspace:client-error]";
4797
+ type ClientErrorKind = 'error' | 'unhandledrejection' | 'react';
4798
+ /** A sanitized, capped browser-error report — the wire + log-line payload. */
4799
+ interface ClientErrorReport {
4800
+ kind: ClientErrorKind;
4801
+ message: string;
4802
+ name?: string;
4803
+ stack?: string;
4804
+ /** Page URL where it fired (href or the script filename). */
4805
+ url?: string;
4806
+ line?: number;
4807
+ col?: number;
4808
+ }
4809
+
4810
+ /**
4811
+ * `deepspace logs` wire DTO — the single source of truth for the whitelisted
4812
+ * shape the platform telemetry reader emits and every consumer reads.
4813
+ *
4814
+ * The producer is `platform/deploy-worker/src/lib/workers-logs.ts` (which
4815
+ * rebuilds each event field-by-field from a raw Cloudflare row — see the
4816
+ * security invariant there). The consumers are the CLI tail
4817
+ * (`cli/commands/logs.ts`), the dashboard Logs panel
4818
+ * (`apps/dashboard/src/lib/apps.ts`), and the e2e whitelist assertion
4819
+ * (`tests/e2e/tests/logs.spec.ts`). This module used to be hand-mirrored in
4820
+ * all four places; `source` was added to three of them and missed in the
4821
+ * e2e whitelist, so it now lives here once and they import it.
4822
+ *
4823
+ * Isomorphic — no DOM, no Hono, no platform types — so it re-exports cleanly
4824
+ * from both `deepspace` (client) and `deepspace/worker` and is safe to import
4825
+ * from the private deploy-worker.
4826
+ */
4827
+ declare const LOG_LEVELS: readonly ["debug", "log", "info", "warn", "error"];
4828
+ type LogLevel = (typeof LOG_LEVELS)[number];
4829
+ /** One log / request / exception event, rebuilt field-by-field from a CF row. */
4830
+ interface AppLogEvent {
4831
+ /** `$metadata.id` — unique per event; the client's dedupe key. */
4832
+ id: string;
4833
+ /** Unix ms. */
4834
+ timestamp: number;
4835
+ level: LogLevel;
4836
+ eventType: 'log' | 'request' | 'exception' | 'other';
4837
+ message: string;
4838
+ /**
4839
+ * Present (= `'client'`) only for a browser-forwarded error the app's own
4840
+ * Worker re-logged via `registerClientErrorRoute`. Absent means the log was
4841
+ * emitted server-side — there is no explicit `'server'` value, so consumers
4842
+ * branch on `source === 'client'`, never on a truthy/other check.
4843
+ */
4844
+ source?: 'client';
4845
+ /** Invocation outcome (`ok`, `exception`, `exceededCpu`, …) when present. */
4846
+ outcome?: string;
4847
+ request?: {
4848
+ method: string;
4849
+ path: string;
4850
+ status?: number;
4851
+ };
4852
+ exception?: {
4853
+ name: string;
4854
+ message: string;
4855
+ stack?: string;
4856
+ };
4857
+ }
4858
+ interface AppLogsResponse {
4859
+ /** Ascending by timestamp (CF returns newest-first; the reader flips). */
4860
+ events: AppLogEvent[];
4861
+ /** Max event timestamp in ms — pass back as `since` to poll; null when empty. */
4862
+ cursor: number | null;
4863
+ /** True when the window returned `limit` events (older events were cut). */
4864
+ truncated: boolean;
4865
+ pollIntervalMs: number;
4866
+ }
4867
+ /**
4868
+ * Runtime tuple of every key a whitelisted `AppLogEvent` may carry — the
4869
+ * canonical whitelist the e2e suite mirrors when asserting no event leaks a key
4870
+ * outside this set. The two type-level assertions below fail compilation if
4871
+ * this tuple and the `AppLogEvent` interface disagree in either direction, so
4872
+ * adding an interface field forces a matching key here.
4873
+ *
4874
+ * NOTE: the e2e spec keeps its OWN copy of this set (it can't import the SDK —
4875
+ * `@deepspace/e2e` has no `deepspace` dependency), kept in step by a comment,
4876
+ * not by these compile-time guards. So this tuple hardens the code copies
4877
+ * (deploy-worker/CLI/dashboard, which import it), while the e2e mirror remains a
4878
+ * knowingly-accepted duplicate.
4879
+ */
4880
+ declare const APP_LOG_EVENT_KEYS: readonly ["id", "timestamp", "level", "eventType", "message", "source", "outcome", "request", "exception"];
4881
+ type AppLogEventKey = (typeof APP_LOG_EVENT_KEYS)[number];
4882
+
4883
+ export { AI_CHATS_SCHEMA, AI_MESSAGES_SCHEMA, ALLOWED_BINDING_TYPES, APP_ID_RE, APP_LOG_EVENT_KEYS, APP_NAME_RULES, AUTO_PROVISIONABLE_TYPES, AUTO_PROVISION_SENTINEL, type ActionContext, type ActionHandler, type ActionResult, type ActionTools, type ApiWorkerEnv, type AppLogEvent, type AppLogEventKey, type AppLogsResponse, type AppNameResolution, type AppNameValidation, type AuthWorkerEnv, Awareness, type AwarenessState, type AwarenessStates, BASE_USERS_SCHEMA, BUILT_IN_TOOLS, type BaseMessage, BaseRoom, CHANNELS_SCHEMA, CHANNEL_INVITATIONS_SCHEMA, CHANNEL_MEMBERS_SCHEMA, CLIENT_LOG_MARKER, CONVERSATION_SCHEMAS, COST_RATES, CanvasRoom, type CanvasShape, type ChatContextConfig, type ChatMessageRow, type ChatRow, type ChatTurn, type ClientErrorKind, type ClientErrorReport, type ClientMessage, type CollectionPermissionSummary, type CollectionSchema, type ColumnDefinition, type ColumnInterpretation, type ComposioToolsOptions, type ConnectionAttachment, type ConvMemberData, type ConvMessageData, type ConvReactionData, type ConvReadCursorData, type ConvVoteData, type ConversationStateData, type CronContext, type CronExecution, CronRoom, type CronRoomConfig, type CronTask, type CustomBinding, type CustomBindingManifest, DEFAULT_CONTEXT_CONFIG, DEFAULT_DO_MANIFEST, DEFAULT_QUERY_LIMIT, DEPLOYED_APPS_DEFAULTS, DIRECTORY_SCHEMAS, type DOBindings, type DOManifest, type DOManifestEntry, type DeepSpaceAIEnv, type DeepSpaceAIOptions, type DeepSpaceAuth, type DeepSpaceAuthConfig, type DirectoryCommunityData, type DirectoryConversationData, type DirectoryMembershipData, type DirectoryPostData, type DoMigrationDirective, type DoMigrationPlan, type ExistingDOBinding, GLOBAL_DO_TYPES, GLOBAL_DO_TYPE_NAMES, type GameInput, GameRoom, type GameRoomConfig, type GetActionData, type GlobalDOType, type HandlerContext, type Job, type JobContext, JobRoom, type JobRoomConfig, type JobStatus, type JwtClaims, type JwtVerifierConfig, LOG_LEVELS, type LogLevel, MESSAGES_SCHEMA, MSG, MSG_AWARENESS, MSG_SYNC, MSG_SYNC_STEP1, MSG_SYNC_STEP2, MSG_SYNC_UPDATE, MSG_YJS_AWARENESS, MSG_YJS_SYNC, type MessageHandlers, type MsgType, type MutateActionData, type PermissionAnalysis, type PermissionContext, type PermissionLevel, type PermissionSource, type PlatformWorkerEnv, type Player, type PrefixResult, type PresencePeer, PresenceRoom, type ProtocolMessage, type QueryActionData, REACTIONS_SCHEMA, READ_RECEIPTS_SCHEMA, REGISTRY_INSTANCE, RESERVED_BINDING_NAMES, RESERVED_COLLECTION_NAMES, ROLE_ADMIN, ROLE_ANONYMOUS, ROLE_DEFAULT, RecordRoom, type RecordRoomConfig, RegistryClientError, type ResolvedColumn, type ResolvedPermission, type RolePermissions, type RunMigrationsResult, STRICT_APP_ID_RE, SYSTEM_COLLECTIONS, SYSTEM_MANAGED_COLUMNS, SchemaRegistry, type ScopeContext, type ScopedR2Auth, type ScopedR2Config, type ScopedR2Handler, type ScreenshotEnv, type ScreenshotResult, type ServerMessage, type SharedConnection, type StoredRecord, type Summarizer, type SyncResult, TEST_ACCOUNT_EMAIL_SUFFIX, type TokenDebugInfo, type ToolResult, type ToolSchema, USERS_COLUMNS, type User, type UserAttachment, VOTING_SCHEMAS, type ValidationError, type VerifiedAuth, type VerifyOutcome, type VerifyResult, type Viewport, WORKSPACE_SCHEMAS, YjsRoom, analyzePermissions, apiWorkerFetch, appendMessage, applyAiToolDefaults, applySlidingWindow, authWorkerFetch, bindingManifestFromOutputConfig, buildCronContext, buildTableSelect, buildUiParts, callRegistry, canCreate, canDelete, canRead, canUpdate, capToolResultSize, captureScreenshot, checkFieldPermissions, clientBuild, coerceValue, collectionTableName, columnId, composioTools, computeDoMigration, computeHmacHex, createChat, createDecoder, createDeepSpaceAI, createDeepSpaceAuth, createEncoder, createScopedR2Handler, dataToColumnValues, decodeJwtPayload, deleteChatCascade, dispatch, encode, encodeAwarenessMessage, encodeSyncStep1, encodeSyncStep2, encodeUpdate, enqueueJob, getChat, getGlobalDOSchemas, getGlobalDOType, getMessageType, getRolePermissions, handleAwarenessMessage, handleClientErrorReport, handleSyncMessage, hasContent, isAutoProvision, isOwner, isTestAccountClaims, isTestAccountEmail, isTestAccountTier, lintSchema, loadMessages, makeDefaultSummarizer, matchOrigin, meterAi, meterUsage, meterVectorize, noopPermissionContext, parseQuotaLimit, platformCorsPatterns, platformWorkerFetch, prepareMessagesWithCompaction, priceBindingUsageEvent, readVarUint, readVarUint8Array, registerClientErrorRoute, registryErrorJson, registryStub, resolveAppName, resolveColumn, rowToData, runMigrations, serverBuild, timingSafeEqualHex, timingSafeEqualStrings, toUint8Array, totalChars, truncateOldToolResults, turnsToCoreMessages, unwrapToolOutput, updateChat, validateAppName, validateBindingManifest, validateDoManifest, verifyJwt, workspaceAccountsSchema, workspaceContentSharesSchema, workspaceEmailHandlesSchema, workspaceFormResponsesSchema, workspacePeopleSchema, workspaceProjectsSchema, workspaceTagsSchema, workspaceTasksSchema, workspaceTeamMembersSchema, workspaceTeamsSchema, workspaceTransactionsSchema, writeVarUint, writeVarUint8Array };