deepspace 0.10.1 → 0.10.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/CHANGELOG.md +8 -0
- package/dist/chunk-T7V4GUIN.js +1638 -0
- package/dist/chunk-T7V4GUIN.js.map +1 -0
- package/dist/cli.js +731 -324
- package/dist/cli.js.map +1 -1
- package/dist/documentation-client-core.d.ts +18 -0
- package/dist/documentation-client-core.js +395 -0
- package/dist/documentation-client-core.js.map +1 -0
- package/dist/documentation-default-renderer.cjs +124 -0
- package/dist/documentation-react.d.ts +2 -0
- package/dist/documentation-react.js +35 -0
- package/dist/documentation-react.js.map +1 -0
- package/dist/documentation-runtime.js +71 -0
- package/dist/documentation-server-core.d.ts +11 -0
- package/dist/documentation-server-core.js +48 -0
- package/dist/documentation-server-core.js.map +1 -0
- package/dist/documentation.d.ts +366 -0
- package/dist/documentation.js +3953 -0
- package/dist/documentation.js.map +1 -0
- package/dist/feature-installer.js +145 -0
- package/dist/feature-installer.js.map +1 -1
- package/dist/index.d.ts +177 -1
- package/dist/index.js +133 -0
- package/dist/index.js.map +1 -1
- package/dist/public-BGRX_Cjd.d.ts +234 -0
- package/dist/schema.d.ts +186 -0
- package/dist/schema.js +610 -0
- package/dist/schema.js.map +1 -0
- package/dist/server.d.ts +83 -4
- package/dist/server.js +296 -1
- package/dist/server.js.map +1 -1
- package/dist/testing.d.ts +5 -8
- package/dist/testing.js +48 -14
- package/dist/testing.js.map +1 -1
- package/dist/worker.d.ts +249 -5
- package/dist/worker.js +1438 -19
- package/dist/worker.js.map +1 -1
- package/features/admin-page/src/admin-schema.ts +1 -1
- package/features/ai-chat/feature.json +2 -2
- package/features/ai-chat/src/ChatPanel.tsx +6 -11
- package/features/ai-chat/src/ai-chat-schema.ts +1 -2
- package/features/canvas/src/canvas-schema.ts +1 -1
- package/features/documentation/content/index.mdx +14 -0
- package/features/documentation/content/quickstart.mdx +12 -0
- package/features/documentation/documentation.json +18 -0
- package/features/documentation/feature.json +68 -0
- package/features/{docs → documents}/feature.json +27 -27
- package/features/{docs/src/DocsEditorPage.tsx → documents/src/DocumentsEditorPage.tsx} +74 -74
- package/features/{docs/src/DocsListPage.tsx → documents/src/DocumentsListPage.tsx} +102 -102
- package/features/{docs/src/DocsOutlinePanel.tsx → documents/src/DocumentsOutlinePanel.tsx} +9 -9
- package/features/{docs/src/DocsPresence.tsx → documents/src/DocumentsPresence.tsx} +18 -18
- package/features/{docs → documents}/src/InviteDialog.tsx +21 -21
- package/features/{docs → documents}/src/LibrarySidebar.tsx +25 -25
- package/features/documents/src/__tests__/documents-presence-access.test.ts +71 -0
- package/features/{docs/src/docs-library-types.ts → documents/src/documents-library-types.ts} +3 -3
- package/features/{docs/src/docs-schema.ts → documents/src/documents-schema.ts} +6 -6
- package/features/{docs/src/docs-ui.css → documents/src/documents-ui.css} +89 -89
- package/features/{docs → documents}/src/editor/DocEditorSurface.tsx +11 -11
- package/features/{docs/src/editor/DocsTiptapToolbar.tsx → documents/src/editor/DocumentsTiptapToolbar.tsx} +21 -21
- package/features/{docs → documents}/src/editor/useDocEditor.ts +4 -4
- package/features/{docs/src/use-docs-presence-access.ts → documents/src/use-documents-presence-access.ts} +51 -51
- package/features/file-attachments/src/attachments-schema.ts +1 -1
- package/features/items/src/items-schema.ts +1 -1
- package/features/leaderboard/src/leaderboard-schema.ts +1 -1
- package/features/messaging/src/ChatMultiPage.tsx +1 -1
- package/features/messaging/src/ChatPage.tsx +1 -1
- package/features/messaging/src/messaging-schema.ts +2 -2
- package/features/tasks/src/tasks-schema.ts +1 -1
- package/features/testing/src/test-schema.ts +2 -2
- package/package.json +26 -1
- package/features/docs/src/__tests__/docs-presence-access.test.ts +0 -71
package/dist/testing.d.ts
CHANGED
|
@@ -26,9 +26,10 @@ declare const test: _playwright_test.TestType<_playwright_test.PlaywrightTestArg
|
|
|
26
26
|
/**
|
|
27
27
|
* Account-credential plumbing for the testing module.
|
|
28
28
|
*
|
|
29
|
-
* Reads test accounts from
|
|
30
|
-
*
|
|
31
|
-
*
|
|
29
|
+
* Reads test accounts from the auth-origin-scoped registry at
|
|
30
|
+
* `~/.deepspace/test-accounts.json` (the same file
|
|
31
|
+
* `deepspace test accounts create` writes). Each account has at minimum
|
|
32
|
+
* `{email, password}`; `name` and `label` are optional.
|
|
32
33
|
*
|
|
33
34
|
* Used by the multi-user Playwright fixture in `./fixtures.ts` and is
|
|
34
35
|
* also exported standalone in case suites want to do their own
|
|
@@ -43,11 +44,7 @@ interface TestAccount {
|
|
|
43
44
|
userId?: string;
|
|
44
45
|
createdAt?: number;
|
|
45
46
|
}
|
|
46
|
-
|
|
47
|
-
* Load all test accounts the developer has created. Returns an empty
|
|
48
|
-
* array if the file doesn't exist yet.
|
|
49
|
-
*/
|
|
50
|
-
declare function loadAllTestAccounts(): TestAccount[];
|
|
47
|
+
declare function loadAllTestAccounts(scope?: string): TestAccount[];
|
|
51
48
|
/**
|
|
52
49
|
* Pick `count` test accounts from the local registry, optionally
|
|
53
50
|
* filtered by `label`. Order-stable: sorted by `createdAt` ascending so
|
package/dist/testing.js
CHANGED
|
@@ -2,21 +2,55 @@
|
|
|
2
2
|
import { test as baseTest } from "@playwright/test";
|
|
3
3
|
|
|
4
4
|
// src/testing/accounts.ts
|
|
5
|
-
import { existsSync, readFileSync } from "fs";
|
|
5
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
6
6
|
import { homedir } from "os";
|
|
7
7
|
import { join } from "path";
|
|
8
|
-
var
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
var TEST_ACCOUNTS_PATH = join(homedir(), ".deepspace", "test-accounts.json");
|
|
9
|
+
var PRODUCTION_AUTH_ORIGIN = "https://auth.deep.space";
|
|
10
|
+
var STAGING_AUTH_ORIGIN = "https://auth.deepspacesites.com";
|
|
11
|
+
function currentTestAccountScope(env = process.env) {
|
|
12
|
+
const selected = env.DEEPSPACE_AUTH_URL ?? (env.DEEPSPACE_ENV === "staging" ? STAGING_AUTH_ORIGIN : PRODUCTION_AUTH_ORIGIN);
|
|
13
|
+
return normalizeTestAccountScope(selected);
|
|
14
|
+
}
|
|
15
|
+
function normalizeTestAccountScope(value) {
|
|
11
16
|
try {
|
|
12
|
-
|
|
13
|
-
if (!Array.isArray(raw)) return [];
|
|
14
|
-
return raw.filter(
|
|
15
|
-
(r) => r && typeof r.email === "string" && typeof r.password === "string"
|
|
16
|
-
);
|
|
17
|
+
return new URL(value).origin;
|
|
17
18
|
} catch {
|
|
18
|
-
return
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
function loadAllTestAccounts(scope = currentTestAccountScope()) {
|
|
23
|
+
const store = readTestAccountStore();
|
|
24
|
+
return mergeTestAccounts(store.scopes[scope] ?? [], store.unscoped);
|
|
25
|
+
}
|
|
26
|
+
function readTestAccountStore() {
|
|
27
|
+
if (!existsSync(TEST_ACCOUNTS_PATH)) return { version: 2, scopes: {}, unscoped: [] };
|
|
28
|
+
try {
|
|
29
|
+
const raw = JSON.parse(readFileSync(TEST_ACCOUNTS_PATH, "utf-8"));
|
|
30
|
+
if (Array.isArray(raw)) return { version: 2, scopes: {}, unscoped: validTestAccounts(raw) };
|
|
31
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
32
|
+
return { version: 2, scopes: {}, unscoped: [] };
|
|
33
|
+
}
|
|
34
|
+
const candidate = raw;
|
|
35
|
+
const scopes = candidate.scopes && typeof candidate.scopes === "object" && !Array.isArray(candidate.scopes) ? Object.fromEntries(Object.entries(candidate.scopes).map(([key, value]) => [key, validTestAccounts(value)])) : {};
|
|
36
|
+
return { version: 2, scopes, unscoped: validTestAccounts(candidate.unscoped) };
|
|
37
|
+
} catch {
|
|
38
|
+
return { version: 2, scopes: {}, unscoped: [] };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function validTestAccounts(value) {
|
|
42
|
+
if (!Array.isArray(value)) return [];
|
|
43
|
+
return value.filter((item) => Boolean(
|
|
44
|
+
item && typeof item === "object" && typeof item.email === "string" && typeof item.password === "string"
|
|
45
|
+
));
|
|
46
|
+
}
|
|
47
|
+
function mergeTestAccounts(...groups) {
|
|
48
|
+
const accounts = /* @__PURE__ */ new Map();
|
|
49
|
+
for (const account of groups.flat()) {
|
|
50
|
+
const key = account.id ? `id:${account.id}` : `email:${account.email}`;
|
|
51
|
+
if (!accounts.has(key)) accounts.set(key, account);
|
|
19
52
|
}
|
|
53
|
+
return [...accounts.values()];
|
|
20
54
|
}
|
|
21
55
|
function pickTestAccounts(count, options) {
|
|
22
56
|
const all = loadAllTestAccounts();
|
|
@@ -25,7 +59,7 @@ function pickTestAccounts(count, options) {
|
|
|
25
59
|
if (sorted.length < count) {
|
|
26
60
|
const labelHint = options?.label ? ` (label="${options.label}")` : "";
|
|
27
61
|
throw new Error(
|
|
28
|
-
`Multiplayer test needs ${count} test accounts${labelHint}, but only ${sorted.length} are present in ${
|
|
62
|
+
`Multiplayer test needs ${count} test accounts${labelHint}, but only ${sorted.length} are present in ${TEST_ACCOUNTS_PATH}. Create more with:
|
|
29
63
|
deepspace test accounts create --email <name>@deepspace.test --password <pw> --name "<name>"${options?.label ? ` --label ${options.label}` : ""}`
|
|
30
64
|
);
|
|
31
65
|
}
|
|
@@ -36,7 +70,7 @@ function findTestAccountByName(name) {
|
|
|
36
70
|
const match = all.find((a) => a.name === name);
|
|
37
71
|
if (!match) {
|
|
38
72
|
throw new Error(
|
|
39
|
-
`No test account named "${name}" in ${
|
|
73
|
+
`No test account named "${name}" in ${TEST_ACCOUNTS_PATH}. Create with:
|
|
40
74
|
deepspace test accounts create --email ${name.toLowerCase()}@deepspace.test --password <pw> --name "${name}"`
|
|
41
75
|
);
|
|
42
76
|
}
|
|
@@ -45,7 +79,7 @@ function findTestAccountByName(name) {
|
|
|
45
79
|
|
|
46
80
|
// src/testing/storage-state.ts
|
|
47
81
|
import { createHash } from "crypto";
|
|
48
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, statSync } from "fs";
|
|
82
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, statSync } from "fs";
|
|
49
83
|
import { homedir as homedir2 } from "os";
|
|
50
84
|
import { join as join2 } from "path";
|
|
51
85
|
var STATES_DIR = join2(homedir2(), ".deepspace", "playwright-states");
|
|
@@ -55,7 +89,7 @@ function statePathForEmail(email) {
|
|
|
55
89
|
return join2(STATES_DIR, `${hash}.json`);
|
|
56
90
|
}
|
|
57
91
|
function ensureStatesDir() {
|
|
58
|
-
if (!existsSync2(STATES_DIR))
|
|
92
|
+
if (!existsSync2(STATES_DIR)) mkdirSync2(STATES_DIR, { recursive: true });
|
|
59
93
|
}
|
|
60
94
|
function isCacheFresh(path, maxAgeMs) {
|
|
61
95
|
if (!existsSync2(path)) return false;
|
package/dist/testing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/testing/fixtures.ts","../src/testing/accounts.ts","../src/testing/storage-state.ts"],"sourcesContent":["/**\n * Multi-user Playwright fixture for DeepSpace apps.\n *\n * Usage:\n *\n * import { test, expect } from 'deepspace/testing'\n *\n * test('A sends, B sees', async ({ users }) => {\n * const [a, b] = await users(2)\n * await a.page.goto('/chat')\n * await b.page.goto('/chat')\n * await a.page.getByTestId('message-input').fill('hi')\n * await a.page.getByTestId('send-message-btn').click()\n * await expect(b.page.getByText('hi')).toBeVisible()\n * })\n *\n * `users(N)` picks the first N test accounts from\n * `~/.deepspace/test-accounts.json` (created via\n * `deepspace test accounts create`). `users(['Alice', 'Bob'])` picks\n * specific accounts by name.\n *\n * Each user gets a separate browser context with cached storageState\n * (per-account JSON in `~/.deepspace/playwright-states/`). Sign-in\n * happens once per account, not once per test, sidestepping Better\n * Auth's per-IP rate limit on `/api/auth/sign-in/email`.\n *\n * Contexts are auto-closed when the test finishes.\n */\n\nimport { test as baseTest, type Browser, type BrowserContext, type Page } from '@playwright/test'\nimport {\n type TestAccount,\n pickTestAccounts,\n findTestAccountByName,\n} from './accounts'\nimport { ensureStorageState } from './storage-state'\n\nexport interface MultiplayerUser {\n context: BrowserContext\n page: Page\n email: string\n name: string\n /** Test account user ID, if known from the accounts registry. */\n userId?: string\n}\n\n/**\n * Fixture function signature. Pass either a count (`users(2)`) or an\n * array of account names (`users(['Alice', 'Bob'])`). Returns one entry\n * per requested user.\n */\nexport type UsersFixture = (\n selector: number | string[],\n options?: { label?: string },\n) => Promise<MultiplayerUser[]>\n\ninterface MultiplayerFixtures {\n users: UsersFixture\n}\n\nasync function buildUser(\n browser: Browser,\n account: TestAccount,\n baseURL: string,\n): Promise<{ user: MultiplayerUser; cleanup: () => Promise<void> }> {\n const statePath = await ensureStorageState(browser, account, baseURL)\n const context = await browser.newContext({ storageState: statePath, baseURL })\n const page = await context.newPage()\n return {\n user: {\n context,\n page,\n email: account.email,\n name: account.name ?? account.email.split('@')[0],\n userId: account.userId,\n },\n cleanup: async () => {\n await context.close()\n },\n }\n}\n\nexport const test = baseTest.extend<MultiplayerFixtures>({\n users: async ({ browser, baseURL }, use) => {\n if (!baseURL) {\n throw new Error(\n '`users` fixture requires a baseURL. Set it on your Playwright config ' +\n '(e.g. `use: { baseURL: \"http://localhost:5173\" }`) or via the ' +\n 'webServer.url shortcut.',\n )\n }\n\n const cleanups: Array<() => Promise<void>> = []\n\n const usersFn: UsersFixture = async (selector, options) => {\n const accounts: TestAccount[] = Array.isArray(selector)\n ? selector.map((name) => findTestAccountByName(name))\n : pickTestAccounts(selector, options)\n\n const built = await Promise.all(\n accounts.map((acct) => buildUser(browser, acct, baseURL)),\n )\n for (const b of built) cleanups.push(b.cleanup)\n return built.map((b) => b.user)\n }\n\n await use(usersFn)\n\n // Tear down any contexts we created. Errors are swallowed — a test\n // failure shouldn't be masked by a cleanup error.\n for (const cleanup of cleanups) {\n await cleanup().catch(() => {})\n }\n },\n})\n\nexport { expect } from '@playwright/test'\n","/**\n * Account-credential plumbing for the testing module.\n *\n * Reads test accounts from `~/.deepspace/test-accounts.json` (the same\n * file `deepspace test accounts create` writes). Each account has at\n * minimum `{email, password}`; `name` and `label` are optional.\n *\n * Used by the multi-user Playwright fixture in `./fixtures.ts` and is\n * also exported standalone in case suites want to do their own\n * orchestration.\n */\n\nimport { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport interface TestAccount {\n email: string\n password: string\n name?: string\n label?: string | null\n id?: string\n userId?: string\n createdAt?: number\n}\n\nconst ACCOUNTS_PATH = join(homedir(), '.deepspace', 'test-accounts.json')\n\n/**\n * Load all test accounts the developer has created. Returns an empty\n * array if the file doesn't exist yet.\n */\nexport function loadAllTestAccounts(): TestAccount[] {\n if (!existsSync(ACCOUNTS_PATH)) return []\n try {\n const raw = JSON.parse(readFileSync(ACCOUNTS_PATH, 'utf-8'))\n if (!Array.isArray(raw)) return []\n // Filter out any malformed entries (missing email or password). Keep\n // bare {email, password} rows so the file format stays forgiving.\n return raw.filter(\n (r) => r && typeof r.email === 'string' && typeof r.password === 'string',\n )\n } catch {\n return []\n }\n}\n\n/**\n * Pick `count` test accounts from the local registry, optionally\n * filtered by `label`. Order-stable: sorted by `createdAt` ascending so\n * the first test account you created is always the first one returned.\n *\n * Throws with a helpful message if not enough accounts exist.\n */\nexport function pickTestAccounts(\n count: number,\n options?: { label?: string },\n): TestAccount[] {\n const all = loadAllTestAccounts()\n const filtered = options?.label\n ? all.filter((a) => a.label === options.label)\n : all\n const sorted = filtered.slice().sort((a, b) => (a.createdAt ?? 0) - (b.createdAt ?? 0))\n\n if (sorted.length < count) {\n const labelHint = options?.label ? ` (label=\"${options.label}\")` : ''\n throw new Error(\n `Multiplayer test needs ${count} test accounts${labelHint}, but only ${sorted.length} ` +\n `are present in ${ACCOUNTS_PATH}. Create more with:\\n` +\n ` deepspace test accounts create --email <name>@deepspace.test --password <pw> --name \"<name>\"${\n options?.label ? ` --label ${options.label}` : ''\n }`,\n )\n }\n\n return sorted.slice(0, count)\n}\n\n/**\n * Find a single account by name. Used by `users(['Alice', 'Bob'])`.\n * Throws if not found.\n */\nexport function findTestAccountByName(name: string): TestAccount {\n const all = loadAllTestAccounts()\n const match = all.find((a) => a.name === name)\n if (!match) {\n throw new Error(\n `No test account named \"${name}\" in ${ACCOUNTS_PATH}. Create with:\\n` +\n ` deepspace test accounts create --email ${name.toLowerCase()}@deepspace.test --password <pw> --name \"${name}\"`,\n )\n }\n return match\n}\n","/**\n * Per-account `storageState` cache for Playwright.\n *\n * Better Auth applies a per-IP rate limit on `/api/auth/sign-in/email`\n * (~5 sign-ins / 60s / endpoint). A multiplayer suite that spins up\n * 5+ users per spec would hit the limit and start failing in non-obvious\n * ways. This module signs each account in *once*, persists the\n * resulting browser cookies + storage to disk, and reuses the file on\n * subsequent runs.\n *\n * Cache layout:\n * ~/.deepspace/playwright-states/<sha256(email)>.json\n *\n * Validity: a cached file is reused if Playwright successfully loads it\n * AND the resulting context produces a non-anonymous session on the\n * target app. If validation fails, we fall back to a fresh sign-in and\n * overwrite the cache.\n */\n\nimport { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, statSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport type { Browser, BrowserContext } from '@playwright/test'\n\nconst STATES_DIR = join(homedir(), '.deepspace', 'playwright-states')\n\n/** Default freshness window — re-sign-in if the cache is older than this. */\nconst DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000 // 7 days\n\nfunction statePathForEmail(email: string): string {\n const hash = createHash('sha256').update(email.trim().toLowerCase()).digest('hex').slice(0, 24)\n return join(STATES_DIR, `${hash}.json`)\n}\n\nfunction ensureStatesDir() {\n if (!existsSync(STATES_DIR)) mkdirSync(STATES_DIR, { recursive: true })\n}\n\n/** Returns true if a cache file exists and is younger than `maxAgeMs`. */\nfunction isCacheFresh(path: string, maxAgeMs: number): boolean {\n if (!existsSync(path)) return false\n try {\n const age = Date.now() - statSync(path).mtimeMs\n return age < maxAgeMs\n } catch {\n return false\n }\n}\n\n/**\n * Sign `account` in by POSTing `/api/auth/sign-in/email` against\n * `baseURL` and capturing the resulting cookies. Returns the path to the\n * Playwright `storageState` JSON file.\n *\n * The browser-driven approach is intentional: we want the cookies set\n * on the same origin Playwright contexts will load from, otherwise the\n * Set-Cookie domain attribute won't match.\n */\nasync function signInAndSaveState(\n browser: Browser,\n account: { email: string; password: string },\n baseURL: string,\n outPath: string,\n): Promise<string> {\n ensureStatesDir()\n const ctx = await browser.newContext({ baseURL })\n try {\n const page = await ctx.newPage()\n // Hit the app first so the origin is established (some auth plugins\n // require a same-origin Origin header on sign-in).\n await page.goto('/')\n const ok = await page.evaluate(\n async ({ email, password }: { email: string; password: string }) => {\n const res = await fetch('/api/auth/sign-in/email', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email, password }),\n })\n return res.ok\n },\n account,\n )\n if (!ok) {\n throw new Error(\n `Sign-in failed for ${account.email}. Check the password is current; ` +\n `if the account was deleted on the server, re-create with ` +\n `\\`deepspace test accounts create\\`.`,\n )\n }\n await ctx.storageState({ path: outPath })\n return outPath\n } finally {\n await ctx.close()\n }\n}\n\nexport interface EnsureStorageStateOptions {\n /** Max age of a cached state file before we re-sign-in. Default 7 days. */\n maxAgeMs?: number\n /** Force a fresh sign-in even if the cache is fresh. */\n force?: boolean\n}\n\n/**\n * Ensure a Playwright `storageState` file exists for `account` and\n * return its path. Signs in once if the cache is missing, stale, or\n * `force: true`.\n */\nexport async function ensureStorageState(\n browser: Browser,\n account: { email: string; password: string },\n baseURL: string,\n options: EnsureStorageStateOptions = {},\n): Promise<string> {\n const path = statePathForEmail(account.email)\n const maxAgeMs = options.maxAgeMs ?? DEFAULT_MAX_AGE_MS\n\n if (!options.force && isCacheFresh(path, maxAgeMs)) {\n return path\n }\n\n return signInAndSaveState(browser, account, baseURL, path)\n}\n\n/**\n * Convenience: open a fresh `BrowserContext` for `account` using the\n * cached storage state (signing in if needed). The caller is responsible\n * for closing the context.\n */\nexport async function newSignedInContext(\n browser: Browser,\n account: { email: string; password: string },\n baseURL: string,\n options: EnsureStorageStateOptions = {},\n): Promise<BrowserContext> {\n const statePath = await ensureStorageState(browser, account, baseURL, options)\n return browser.newContext({ storageState: statePath, baseURL })\n}\n\n/** Read a cached storageState file (mostly for debugging). */\nexport function readCachedState(email: string): unknown | null {\n const path = statePathForEmail(email)\n if (!existsSync(path)) return null\n try {\n return JSON.parse(readFileSync(path, 'utf-8'))\n } catch {\n return null\n }\n}\n\n/** Where the cache for `email` lives. Useful for diagnostics. */\nexport function getStatePathForEmail(email: string): string {\n return statePathForEmail(email)\n}\n"],"mappings":";AA6BA,SAAS,QAAQ,gBAA8D;;;ACjB/E,SAAS,YAAY,oBAAoB;AACzC,SAAS,eAAe;AACxB,SAAS,YAAY;AAYrB,IAAM,gBAAgB,KAAK,QAAQ,GAAG,cAAc,oBAAoB;AAMjE,SAAS,sBAAqC;AACnD,MAAI,CAAC,WAAW,aAAa,EAAG,QAAO,CAAC;AACxC,MAAI;AACF,UAAM,MAAM,KAAK,MAAM,aAAa,eAAe,OAAO,CAAC;AAC3D,QAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,QAAO,CAAC;AAGjC,WAAO,IAAI;AAAA,MACT,CAAC,MAAM,KAAK,OAAO,EAAE,UAAU,YAAY,OAAO,EAAE,aAAa;AAAA,IACnE;AAAA,EACF,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AASO,SAAS,iBACd,OACA,SACe;AACf,QAAM,MAAM,oBAAoB;AAChC,QAAM,WAAW,SAAS,QACtB,IAAI,OAAO,CAAC,MAAM,EAAE,UAAU,QAAQ,KAAK,IAC3C;AACJ,QAAM,SAAS,SAAS,MAAM,EAAE,KAAK,CAAC,GAAG,OAAO,EAAE,aAAa,MAAM,EAAE,aAAa,EAAE;AAEtF,MAAI,OAAO,SAAS,OAAO;AACzB,UAAM,YAAY,SAAS,QAAQ,YAAY,QAAQ,KAAK,OAAO;AACnE,UAAM,IAAI;AAAA,MACR,0BAA0B,KAAK,iBAAiB,SAAS,cAAc,OAAO,MAAM,mBAChE,aAAa;AAAA,gGAE7B,SAAS,QAAQ,YAAY,QAAQ,KAAK,KAAK,EACjD;AAAA,IACJ;AAAA,EACF;AAEA,SAAO,OAAO,MAAM,GAAG,KAAK;AAC9B;AAMO,SAAS,sBAAsB,MAA2B;AAC/D,QAAM,MAAM,oBAAoB;AAChC,QAAM,QAAQ,IAAI,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI;AAC7C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR,0BAA0B,IAAI,QAAQ,aAAa;AAAA,2CACL,KAAK,YAAY,CAAC,2CAA2C,IAAI;AAAA,IACjH;AAAA,EACF;AACA,SAAO;AACT;;;ACzEA,SAAS,kBAAkB;AAC3B,SAAS,cAAAA,aAAY,WAAW,gBAAAC,eAAc,gBAAgB;AAC9D,SAAS,WAAAC,gBAAe;AACxB,SAAS,QAAAC,aAAY;AAGrB,IAAM,aAAaA,MAAKD,SAAQ,GAAG,cAAc,mBAAmB;AAGpE,IAAM,qBAAqB,IAAI,KAAK,KAAK,KAAK;AAE9C,SAAS,kBAAkB,OAAuB;AAChD,QAAM,OAAO,WAAW,QAAQ,EAAE,OAAO,MAAM,KAAK,EAAE,YAAY,CAAC,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC9F,SAAOC,MAAK,YAAY,GAAG,IAAI,OAAO;AACxC;AAEA,SAAS,kBAAkB;AACzB,MAAI,CAACH,YAAW,UAAU,EAAG,WAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AACxE;AAGA,SAAS,aAAa,MAAc,UAA2B;AAC7D,MAAI,CAACA,YAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,UAAM,MAAM,KAAK,IAAI,IAAI,SAAS,IAAI,EAAE;AACxC,WAAO,MAAM;AAAA,EACf,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAWA,eAAe,mBACb,SACA,SACA,SACA,SACiB;AACjB,kBAAgB;AAChB,QAAM,MAAM,MAAM,QAAQ,WAAW,EAAE,QAAQ,CAAC;AAChD,MAAI;AACF,UAAM,OAAO,MAAM,IAAI,QAAQ;AAG/B,UAAM,KAAK,KAAK,GAAG;AACnB,UAAM,KAAK,MAAM,KAAK;AAAA,MACpB,OAAO,EAAE,OAAO,SAAS,MAA2C;AAClE,cAAM,MAAM,MAAM,MAAM,2BAA2B;AAAA,UACjD,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,UAC9C,MAAM,KAAK,UAAU,EAAE,OAAO,SAAS,CAAC;AAAA,QAC1C,CAAC;AACD,eAAO,IAAI;AAAA,MACb;AAAA,MACA;AAAA,IACF;AACA,QAAI,CAAC,IAAI;AACP,YAAM,IAAI;AAAA,QACR,sBAAsB,QAAQ,KAAK;AAAA,MAGrC;AAAA,IACF;AACA,UAAM,IAAI,aAAa,EAAE,MAAM,QAAQ,CAAC;AACxC,WAAO;AAAA,EACT,UAAE;AACA,UAAM,IAAI,MAAM;AAAA,EAClB;AACF;AAcA,eAAsB,mBACpB,SACA,SACA,SACA,UAAqC,CAAC,GACrB;AACjB,QAAM,OAAO,kBAAkB,QAAQ,KAAK;AAC5C,QAAM,WAAW,QAAQ,YAAY;AAErC,MAAI,CAAC,QAAQ,SAAS,aAAa,MAAM,QAAQ,GAAG;AAClD,WAAO;AAAA,EACT;AAEA,SAAO,mBAAmB,SAAS,SAAS,SAAS,IAAI;AAC3D;AAOA,eAAsB,mBACpB,SACA,SACA,SACA,UAAqC,CAAC,GACb;AACzB,QAAM,YAAY,MAAM,mBAAmB,SAAS,SAAS,SAAS,OAAO;AAC7E,SAAO,QAAQ,WAAW,EAAE,cAAc,WAAW,QAAQ,CAAC;AAChE;AAGO,SAAS,gBAAgB,OAA+B;AAC7D,QAAM,OAAO,kBAAkB,KAAK;AACpC,MAAI,CAACA,YAAW,IAAI,EAAG,QAAO;AAC9B,MAAI;AACF,WAAO,KAAK,MAAMC,cAAa,MAAM,OAAO,CAAC;AAAA,EAC/C,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAGO,SAAS,qBAAqB,OAAuB;AAC1D,SAAO,kBAAkB,KAAK;AAChC;;;AFtCA,SAAS,cAAc;AAxDvB,eAAe,UACb,SACA,SACA,SACkE;AAClE,QAAM,YAAY,MAAM,mBAAmB,SAAS,SAAS,OAAO;AACpE,QAAM,UAAU,MAAM,QAAQ,WAAW,EAAE,cAAc,WAAW,QAAQ,CAAC;AAC7E,QAAM,OAAO,MAAM,QAAQ,QAAQ;AACnC,SAAO;AAAA,IACL,MAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA,OAAO,QAAQ;AAAA,MACf,MAAM,QAAQ,QAAQ,QAAQ,MAAM,MAAM,GAAG,EAAE,CAAC;AAAA,MAChD,QAAQ,QAAQ;AAAA,IAClB;AAAA,IACA,SAAS,YAAY;AACnB,YAAM,QAAQ,MAAM;AAAA,IACtB;AAAA,EACF;AACF;AAEO,IAAM,OAAO,SAAS,OAA4B;AAAA,EACvD,OAAO,OAAO,EAAE,SAAS,QAAQ,GAAG,QAAQ;AAC1C,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI;AAAA,QACR;AAAA,MAGF;AAAA,IACF;AAEA,UAAM,WAAuC,CAAC;AAE9C,UAAM,UAAwB,OAAO,UAAU,YAAY;AACzD,YAAM,WAA0B,MAAM,QAAQ,QAAQ,IAClD,SAAS,IAAI,CAAC,SAAS,sBAAsB,IAAI,CAAC,IAClD,iBAAiB,UAAU,OAAO;AAEtC,YAAM,QAAQ,MAAM,QAAQ;AAAA,QAC1B,SAAS,IAAI,CAAC,SAAS,UAAU,SAAS,MAAM,OAAO,CAAC;AAAA,MAC1D;AACA,iBAAW,KAAK,MAAO,UAAS,KAAK,EAAE,OAAO;AAC9C,aAAO,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,IAChC;AAEA,UAAM,IAAI,OAAO;AAIjB,eAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ,EAAE,MAAM,MAAM;AAAA,MAAC,CAAC;AAAA,IAChC;AAAA,EACF;AACF,CAAC;","names":["existsSync","readFileSync","homedir","join"]}
|
|
1
|
+
{"version":3,"sources":["../src/testing/fixtures.ts","../src/testing/accounts.ts","../src/testing/storage-state.ts"],"sourcesContent":["/**\n * Multi-user Playwright fixture for DeepSpace apps.\n *\n * Usage:\n *\n * import { test, expect } from 'deepspace/testing'\n *\n * test('A sends, B sees', async ({ users }) => {\n * const [a, b] = await users(2)\n * await a.page.goto('/chat')\n * await b.page.goto('/chat')\n * await a.page.getByTestId('message-input').fill('hi')\n * await a.page.getByTestId('send-message-btn').click()\n * await expect(b.page.getByText('hi')).toBeVisible()\n * })\n *\n * `users(N)` picks the first N test accounts from\n * `~/.deepspace/test-accounts.json` (created via\n * `deepspace test accounts create`). `users(['Alice', 'Bob'])` picks\n * specific accounts by name.\n *\n * Each user gets a separate browser context with cached storageState\n * (per-account JSON in `~/.deepspace/playwright-states/`). Sign-in\n * happens once per account, not once per test, sidestepping Better\n * Auth's per-IP rate limit on `/api/auth/sign-in/email`.\n *\n * Contexts are auto-closed when the test finishes.\n */\n\nimport { test as baseTest, type Browser, type BrowserContext, type Page } from '@playwright/test'\nimport {\n type TestAccount,\n pickTestAccounts,\n findTestAccountByName,\n} from './accounts'\nimport { ensureStorageState } from './storage-state'\n\nexport interface MultiplayerUser {\n context: BrowserContext\n page: Page\n email: string\n name: string\n /** Test account user ID, if known from the accounts registry. */\n userId?: string\n}\n\n/**\n * Fixture function signature. Pass either a count (`users(2)`) or an\n * array of account names (`users(['Alice', 'Bob'])`). Returns one entry\n * per requested user.\n */\nexport type UsersFixture = (\n selector: number | string[],\n options?: { label?: string },\n) => Promise<MultiplayerUser[]>\n\ninterface MultiplayerFixtures {\n users: UsersFixture\n}\n\nasync function buildUser(\n browser: Browser,\n account: TestAccount,\n baseURL: string,\n): Promise<{ user: MultiplayerUser; cleanup: () => Promise<void> }> {\n const statePath = await ensureStorageState(browser, account, baseURL)\n const context = await browser.newContext({ storageState: statePath, baseURL })\n const page = await context.newPage()\n return {\n user: {\n context,\n page,\n email: account.email,\n name: account.name ?? account.email.split('@')[0],\n userId: account.userId,\n },\n cleanup: async () => {\n await context.close()\n },\n }\n}\n\nexport const test = baseTest.extend<MultiplayerFixtures>({\n users: async ({ browser, baseURL }, use) => {\n if (!baseURL) {\n throw new Error(\n '`users` fixture requires a baseURL. Set it on your Playwright config ' +\n '(e.g. `use: { baseURL: \"http://localhost:5173\" }`) or via the ' +\n 'webServer.url shortcut.',\n )\n }\n\n const cleanups: Array<() => Promise<void>> = []\n\n const usersFn: UsersFixture = async (selector, options) => {\n const accounts: TestAccount[] = Array.isArray(selector)\n ? selector.map((name) => findTestAccountByName(name))\n : pickTestAccounts(selector, options)\n\n const built = await Promise.all(\n accounts.map((acct) => buildUser(browser, acct, baseURL)),\n )\n for (const b of built) cleanups.push(b.cleanup)\n return built.map((b) => b.user)\n }\n\n await use(usersFn)\n\n // Tear down any contexts we created. Errors are swallowed — a test\n // failure shouldn't be masked by a cleanup error.\n for (const cleanup of cleanups) {\n await cleanup().catch(() => {})\n }\n },\n})\n\nexport { expect } from '@playwright/test'\n","/**\n * Account-credential plumbing for the testing module.\n *\n * Reads test accounts from the auth-origin-scoped registry at\n * `~/.deepspace/test-accounts.json` (the same file\n * `deepspace test accounts create` writes). Each account has at minimum\n * `{email, password}`; `name` and `label` are optional.\n *\n * Used by the multi-user Playwright fixture in `./fixtures.ts` and is\n * also exported standalone in case suites want to do their own\n * orchestration.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport interface TestAccount {\n email: string\n password: string\n name?: string\n label?: string | null\n id?: string\n userId?: string\n createdAt?: number\n}\n\nexport const TEST_ACCOUNTS_PATH = join(homedir(), '.deepspace', 'test-accounts.json')\n\nconst PRODUCTION_AUTH_ORIGIN = 'https://auth.deep.space'\nconst STAGING_AUTH_ORIGIN = 'https://auth.deepspacesites.com'\n\nexport interface TestAccountCredentialStore {\n version: 2\n scopes: Record<string, TestAccount[]>\n /** Legacy credentials stay here until a remote id proves their plane. */\n unscoped: TestAccount[]\n}\n\nexport interface RemoteTestAccount {\n id: string\n email: string\n userId: string\n label: string | null\n createdAt: number\n}\n\n/**\n * Load all test accounts the developer has created. Returns an empty\n * array if the file doesn't exist yet.\n */\nexport function currentTestAccountScope(env: NodeJS.ProcessEnv = process.env): string {\n const selected = env.DEEPSPACE_AUTH_URL ??\n (env.DEEPSPACE_ENV === 'staging' ? STAGING_AUTH_ORIGIN : PRODUCTION_AUTH_ORIGIN)\n return normalizeTestAccountScope(selected)\n}\n\nexport function normalizeTestAccountScope(value: string): string {\n try {\n return new URL(value).origin\n } catch {\n return value\n }\n}\n\nexport function loadAllTestAccounts(scope = currentTestAccountScope()): TestAccount[] {\n const store = readTestAccountStore()\n return mergeTestAccounts(store.scopes[scope] ?? [], store.unscoped)\n}\n\n/**\n * Replace the local credential registry with the subset that still exists\n * remotely. Passwords and display names remain local-only; a recreated email\n * with a different id is deliberately treated as a different account.\n */\nexport function reconcileTestAccountStore(\n remote: RemoteTestAccount[],\n scope = currentTestAccountScope(),\n): {\n accounts: TestAccount[]\n removed: number\n} {\n const result = reconcileTestAccountScopes(readTestAccountStore(), remote, scope)\n saveTestAccountStore(result.store)\n return { accounts: result.accounts, removed: result.removed }\n}\n\nexport function reconcileTestAccountScopes(\n store: TestAccountCredentialStore,\n remote: RemoteTestAccount[],\n scope: string,\n): { store: TestAccountCredentialStore; accounts: TestAccount[]; removed: number } {\n const scoped = store.scopes[scope] ?? []\n const current = reconcileTestAccounts(scoped, remote)\n const migrated = reconcileTestAccounts(store.unscoped, remote)\n const accounts = mergeTestAccounts(current, migrated)\n return {\n accounts,\n removed: Math.max(0, scoped.length - current.length),\n store: {\n version: 2,\n scopes: { ...store.scopes, [scope]: accounts },\n unscoped: store.unscoped.filter((account) => !remote.some((item) => accountMatchesRemote(account, item))),\n },\n }\n}\n\nexport function reconcileTestAccounts(\n local: TestAccount[],\n remote: RemoteTestAccount[],\n): TestAccount[] {\n const localById = new Map(local.filter((account) => account.id).map((account) => [account.id, account]))\n const legacyByEmail = new Map(local.filter((account) => !account.id).map((account) => [account.email, account]))\n return remote.flatMap((account) => {\n const stored = localById.get(account.id) ?? legacyByEmail.get(account.email)\n return stored ? [{ ...stored, ...account }] : []\n })\n}\n\n/** Add or replace one locally stored credential without creating duplicates. */\nexport function upsertTestAccount(account: TestAccount, scope = currentTestAccountScope()): void {\n const store = readTestAccountStore()\n const accounts = (store.scopes[scope] ?? []).filter(\n (stored) => stored.id !== account.id && stored.email !== account.email,\n )\n saveTestAccountStore({\n version: 2,\n scopes: { ...store.scopes, [scope]: [...accounts, account] },\n unscoped: store.unscoped.filter(\n (stored) => stored.id !== account.id && stored.email !== account.email,\n ),\n })\n}\n\n/** Remove credentials after the corresponding remote delete succeeds. */\nexport function removeTestAccounts(\n ids: string[],\n emails: string[] = [],\n scope = currentTestAccountScope(),\n): void {\n const idSet = new Set(ids)\n const emailSet = new Set(emails)\n const keep = (account: TestAccount): boolean =>\n !idSet.has(account.id ?? '') && !emailSet.has(account.email)\n const store = readTestAccountStore()\n saveTestAccountStore({\n version: 2,\n scopes: { ...store.scopes, [scope]: (store.scopes[scope] ?? []).filter(keep) },\n unscoped: store.unscoped.filter(keep),\n })\n}\n\nfunction readTestAccountStore(): TestAccountCredentialStore {\n if (!existsSync(TEST_ACCOUNTS_PATH)) return { version: 2, scopes: {}, unscoped: [] }\n try {\n const raw: unknown = JSON.parse(readFileSync(TEST_ACCOUNTS_PATH, 'utf-8'))\n if (Array.isArray(raw)) return { version: 2, scopes: {}, unscoped: validTestAccounts(raw) }\n if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {\n return { version: 2, scopes: {}, unscoped: [] }\n }\n const candidate = raw as { scopes?: unknown; unscoped?: unknown }\n const scopes = candidate.scopes && typeof candidate.scopes === 'object' && !Array.isArray(candidate.scopes)\n ? Object.fromEntries(Object.entries(candidate.scopes).map(([key, value]) => [key, validTestAccounts(value)]))\n : {}\n return { version: 2, scopes, unscoped: validTestAccounts(candidate.unscoped) }\n } catch {\n return { version: 2, scopes: {}, unscoped: [] }\n }\n}\n\nfunction validTestAccounts(value: unknown): TestAccount[] {\n if (!Array.isArray(value)) return []\n return value.filter((item): item is TestAccount => Boolean(\n item && typeof item === 'object' &&\n typeof (item as TestAccount).email === 'string' &&\n typeof (item as TestAccount).password === 'string',\n ))\n}\n\nfunction mergeTestAccounts(...groups: TestAccount[][]): TestAccount[] {\n const accounts = new Map<string, TestAccount>()\n for (const account of groups.flat()) {\n const key = account.id ? `id:${account.id}` : `email:${account.email}`\n if (!accounts.has(key)) accounts.set(key, account)\n }\n return [...accounts.values()]\n}\n\nfunction accountMatchesRemote(local: TestAccount, remote: RemoteTestAccount): boolean {\n return local.id ? local.id === remote.id : local.email === remote.email\n}\n\nfunction saveTestAccountStore(store: TestAccountCredentialStore): void {\n mkdirSync(join(homedir(), '.deepspace'), { recursive: true })\n writeFileSync(TEST_ACCOUNTS_PATH, JSON.stringify(store, null, 2), { mode: 0o600 })\n}\n\n/**\n * Pick `count` test accounts from the local registry, optionally\n * filtered by `label`. Order-stable: sorted by `createdAt` ascending so\n * the first test account you created is always the first one returned.\n *\n * Throws with a helpful message if not enough accounts exist.\n */\nexport function pickTestAccounts(\n count: number,\n options?: { label?: string },\n): TestAccount[] {\n const all = loadAllTestAccounts()\n const filtered = options?.label\n ? all.filter((a) => a.label === options.label)\n : all\n const sorted = filtered.slice().sort((a, b) => (a.createdAt ?? 0) - (b.createdAt ?? 0))\n\n if (sorted.length < count) {\n const labelHint = options?.label ? ` (label=\"${options.label}\")` : ''\n throw new Error(\n `Multiplayer test needs ${count} test accounts${labelHint}, but only ${sorted.length} ` +\n `are present in ${TEST_ACCOUNTS_PATH}. Create more with:\\n` +\n ` deepspace test accounts create --email <name>@deepspace.test --password <pw> --name \"<name>\"${\n options?.label ? ` --label ${options.label}` : ''\n }`,\n )\n }\n\n return sorted.slice(0, count)\n}\n\n/**\n * Find a single account by name. Used by `users(['Alice', 'Bob'])`.\n * Throws if not found.\n */\nexport function findTestAccountByName(name: string): TestAccount {\n const all = loadAllTestAccounts()\n const match = all.find((a) => a.name === name)\n if (!match) {\n throw new Error(\n `No test account named \"${name}\" in ${TEST_ACCOUNTS_PATH}. Create with:\\n` +\n ` deepspace test accounts create --email ${name.toLowerCase()}@deepspace.test --password <pw> --name \"${name}\"`,\n )\n }\n return match\n}\n","/**\n * Per-account `storageState` cache for Playwright.\n *\n * Better Auth applies a per-IP rate limit on `/api/auth/sign-in/email`\n * (~5 sign-ins / 60s / endpoint). A multiplayer suite that spins up\n * 5+ users per spec would hit the limit and start failing in non-obvious\n * ways. This module signs each account in *once*, persists the\n * resulting browser cookies + storage to disk, and reuses the file on\n * subsequent runs.\n *\n * Cache layout:\n * ~/.deepspace/playwright-states/<sha256(email)>.json\n *\n * Validity: a cached file is reused if Playwright successfully loads it\n * AND the resulting context produces a non-anonymous session on the\n * target app. If validation fails, we fall back to a fresh sign-in and\n * overwrite the cache.\n */\n\nimport { createHash } from 'node:crypto'\nimport { existsSync, mkdirSync, readFileSync, statSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport type { Browser, BrowserContext } from '@playwright/test'\n\nconst STATES_DIR = join(homedir(), '.deepspace', 'playwright-states')\n\n/** Default freshness window — re-sign-in if the cache is older than this. */\nconst DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000 // 7 days\n\nfunction statePathForEmail(email: string): string {\n const hash = createHash('sha256').update(email.trim().toLowerCase()).digest('hex').slice(0, 24)\n return join(STATES_DIR, `${hash}.json`)\n}\n\nfunction ensureStatesDir() {\n if (!existsSync(STATES_DIR)) mkdirSync(STATES_DIR, { recursive: true })\n}\n\n/** Returns true if a cache file exists and is younger than `maxAgeMs`. */\nfunction isCacheFresh(path: string, maxAgeMs: number): boolean {\n if (!existsSync(path)) return false\n try {\n const age = Date.now() - statSync(path).mtimeMs\n return age < maxAgeMs\n } catch {\n return false\n }\n}\n\n/**\n * Sign `account` in by POSTing `/api/auth/sign-in/email` against\n * `baseURL` and capturing the resulting cookies. Returns the path to the\n * Playwright `storageState` JSON file.\n *\n * The browser-driven approach is intentional: we want the cookies set\n * on the same origin Playwright contexts will load from, otherwise the\n * Set-Cookie domain attribute won't match.\n */\nasync function signInAndSaveState(\n browser: Browser,\n account: { email: string; password: string },\n baseURL: string,\n outPath: string,\n): Promise<string> {\n ensureStatesDir()\n const ctx = await browser.newContext({ baseURL })\n try {\n const page = await ctx.newPage()\n // Hit the app first so the origin is established (some auth plugins\n // require a same-origin Origin header on sign-in).\n await page.goto('/')\n const ok = await page.evaluate(\n async ({ email, password }: { email: string; password: string }) => {\n const res = await fetch('/api/auth/sign-in/email', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ email, password }),\n })\n return res.ok\n },\n account,\n )\n if (!ok) {\n throw new Error(\n `Sign-in failed for ${account.email}. Check the password is current; ` +\n `if the account was deleted on the server, re-create with ` +\n `\\`deepspace test accounts create\\`.`,\n )\n }\n await ctx.storageState({ path: outPath })\n return outPath\n } finally {\n await ctx.close()\n }\n}\n\nexport interface EnsureStorageStateOptions {\n /** Max age of a cached state file before we re-sign-in. Default 7 days. */\n maxAgeMs?: number\n /** Force a fresh sign-in even if the cache is fresh. */\n force?: boolean\n}\n\n/**\n * Ensure a Playwright `storageState` file exists for `account` and\n * return its path. Signs in once if the cache is missing, stale, or\n * `force: true`.\n */\nexport async function ensureStorageState(\n browser: Browser,\n account: { email: string; password: string },\n baseURL: string,\n options: EnsureStorageStateOptions = {},\n): Promise<string> {\n const path = statePathForEmail(account.email)\n const maxAgeMs = options.maxAgeMs ?? DEFAULT_MAX_AGE_MS\n\n if (!options.force && isCacheFresh(path, maxAgeMs)) {\n return path\n }\n\n return signInAndSaveState(browser, account, baseURL, path)\n}\n\n/**\n * Convenience: open a fresh `BrowserContext` for `account` using the\n * cached storage state (signing in if needed). The caller is responsible\n * for closing the context.\n */\nexport async function newSignedInContext(\n browser: Browser,\n account: { email: string; password: string },\n baseURL: string,\n options: EnsureStorageStateOptions = {},\n): Promise<BrowserContext> {\n const statePath = await ensureStorageState(browser, account, baseURL, options)\n return browser.newContext({ storageState: statePath, baseURL })\n}\n\n/** Read a cached storageState file (mostly for debugging). */\nexport function readCachedState(email: string): unknown | null {\n const path = statePathForEmail(email)\n if (!existsSync(path)) return null\n try {\n return JSON.parse(readFileSync(path, 'utf-8'))\n } catch {\n return null\n }\n}\n\n/** Where the cache for `email` lives. Useful for diagnostics. */\nexport function getStatePathForEmail(email: string): string {\n return statePathForEmail(email)\n}\n"],"mappings":"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","names":["existsSync","mkdirSync","readFileSync","homedir","join"]}
|
package/dist/worker.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as Y from 'yjs';
|
|
2
|
-
import { LanguageModel, ToolSet, ModelMessage } from 'ai';
|
|
2
|
+
import { LanguageModel, ToolSet, StreamTextResult, streamText, ModelMessage } from 'ai';
|
|
3
|
+
import { Hono } from 'hono';
|
|
3
4
|
import * as zod_v4_core from 'zod/v4/core';
|
|
4
5
|
import * as zod from 'zod';
|
|
5
6
|
import * as better_auth_plugins from 'better-auth/plugins';
|
|
6
7
|
import * as better_auth from 'better-auth';
|
|
7
8
|
import { betterAuth } from 'better-auth';
|
|
8
|
-
import { Hono } from 'hono';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Wire protocol constants.
|
|
@@ -2087,6 +2087,14 @@ type CustomBinding = {
|
|
|
2087
2087
|
type: 'hyperdrive';
|
|
2088
2088
|
name: string;
|
|
2089
2089
|
id: string;
|
|
2090
|
+
} | {
|
|
2091
|
+
type: 'ratelimit';
|
|
2092
|
+
name: string;
|
|
2093
|
+
namespace_id: string;
|
|
2094
|
+
simple: {
|
|
2095
|
+
limit: number;
|
|
2096
|
+
period: 10 | 60;
|
|
2097
|
+
};
|
|
2090
2098
|
};
|
|
2091
2099
|
type CustomBindingManifest = CustomBinding[];
|
|
2092
2100
|
/** Sentinel string in an ID field that requests platform-side provisioning. */
|
|
@@ -2552,6 +2560,182 @@ type AppMigrationIdsValidation = {
|
|
|
2552
2560
|
/** Validate the small, provider-neutral migration manifest shipped with an app bundle. */
|
|
2553
2561
|
declare function validateAppMigrationIds(value: unknown): AppMigrationIdsValidation;
|
|
2554
2562
|
|
|
2563
|
+
/**
|
|
2564
|
+
* Canonical DeepSpace model catalog and agent policy.
|
|
2565
|
+
*
|
|
2566
|
+
* Provider catalogs are discovery inputs, not a safe runtime allowlist: a
|
|
2567
|
+
* model is promoted here only after its tool loop, transport, pricing, and
|
|
2568
|
+
* streaming contract have been verified end to end through the DeepSpace
|
|
2569
|
+
* proxy. Every client picker and server agent profile consumes this module.
|
|
2570
|
+
*/
|
|
2571
|
+
type DeepSpaceAIProvider = 'anthropic' | 'openai' | 'cerebras';
|
|
2572
|
+
type DeepSpaceAgentProfileId = 'application' | 'documentation';
|
|
2573
|
+
type DeepSpaceAgentSupport = 'multi-step' | 'single-step' | 'none';
|
|
2574
|
+
interface DeepSpaceAIModel {
|
|
2575
|
+
id: string;
|
|
2576
|
+
label: string;
|
|
2577
|
+
provider: DeepSpaceAIProvider;
|
|
2578
|
+
providerLabel: string;
|
|
2579
|
+
family: string;
|
|
2580
|
+
/** Whether the model is eligible for DeepSpace's server-owned agent loop. */
|
|
2581
|
+
agentSupport: DeepSpaceAgentSupport;
|
|
2582
|
+
/** Profiles in which the model has passed the complete runtime contract. */
|
|
2583
|
+
agentProfiles: readonly DeepSpaceAgentProfileId[];
|
|
2584
|
+
/** Provider transport currently used by the DeepSpace proxy adapter. */
|
|
2585
|
+
transport: 'messages' | 'chat-completions';
|
|
2586
|
+
recommendation: 'frontier' | 'balanced' | 'fast' | 'available' | 'limited';
|
|
2587
|
+
note?: string;
|
|
2588
|
+
}
|
|
2589
|
+
interface DeepSpaceAgentProfile {
|
|
2590
|
+
id: DeepSpaceAgentProfileId;
|
|
2591
|
+
defaultModel: string;
|
|
2592
|
+
maxSteps: number;
|
|
2593
|
+
maxToolCalls?: number;
|
|
2594
|
+
allowedTools: 'application-defined' | readonly string[];
|
|
2595
|
+
}
|
|
2596
|
+
/**
|
|
2597
|
+
* Versioned provenance for the provider catalogs used during the latest
|
|
2598
|
+
* promotion review. Keeping this in the shipped artifact makes selection
|
|
2599
|
+
* policy auditable without allowing a mutable upstream list to change a
|
|
2600
|
+
* deployed app underneath a commit.
|
|
2601
|
+
*/
|
|
2602
|
+
declare const DEEPSPACE_MODEL_CATALOG_PROVENANCE: {
|
|
2603
|
+
readonly version: "2026-08-04";
|
|
2604
|
+
readonly verifiedAt: "2026-08-04";
|
|
2605
|
+
readonly sources: {
|
|
2606
|
+
readonly anthropic: "https://platform.claude.com/docs/en/api/beta/models/list";
|
|
2607
|
+
readonly openai: "https://developers.openai.com/api/docs/models/all";
|
|
2608
|
+
readonly cerebras: "https://inference-docs.cerebras.ai/models/overview";
|
|
2609
|
+
};
|
|
2610
|
+
};
|
|
2611
|
+
declare const DEEPSPACE_AI_MODELS: readonly [{
|
|
2612
|
+
readonly id: "claude-fable-5";
|
|
2613
|
+
readonly label: "Claude Fable 5";
|
|
2614
|
+
readonly family: "Claude 5";
|
|
2615
|
+
readonly recommendation: "frontier";
|
|
2616
|
+
} & {
|
|
2617
|
+
readonly provider: "anthropic";
|
|
2618
|
+
readonly providerLabel: "Anthropic";
|
|
2619
|
+
readonly transport: "messages";
|
|
2620
|
+
} & {
|
|
2621
|
+
agentSupport: "multi-step";
|
|
2622
|
+
agentProfiles: readonly ["application", "documentation"];
|
|
2623
|
+
}, {
|
|
2624
|
+
readonly id: "claude-opus-5";
|
|
2625
|
+
readonly label: "Claude Opus 5";
|
|
2626
|
+
readonly family: "Claude 5";
|
|
2627
|
+
readonly recommendation: "frontier";
|
|
2628
|
+
} & {
|
|
2629
|
+
readonly provider: "anthropic";
|
|
2630
|
+
readonly providerLabel: "Anthropic";
|
|
2631
|
+
readonly transport: "messages";
|
|
2632
|
+
} & {
|
|
2633
|
+
agentSupport: "multi-step";
|
|
2634
|
+
agentProfiles: readonly ["application", "documentation"];
|
|
2635
|
+
}, {
|
|
2636
|
+
readonly id: "claude-sonnet-5";
|
|
2637
|
+
readonly label: "Claude Sonnet 5";
|
|
2638
|
+
readonly family: "Claude 5";
|
|
2639
|
+
readonly recommendation: "balanced";
|
|
2640
|
+
} & {
|
|
2641
|
+
readonly provider: "anthropic";
|
|
2642
|
+
readonly providerLabel: "Anthropic";
|
|
2643
|
+
readonly transport: "messages";
|
|
2644
|
+
} & {
|
|
2645
|
+
agentSupport: "multi-step";
|
|
2646
|
+
agentProfiles: readonly ["application", "documentation"];
|
|
2647
|
+
}, {
|
|
2648
|
+
readonly id: "claude-haiku-4-5";
|
|
2649
|
+
readonly label: "Claude Haiku 4.5";
|
|
2650
|
+
readonly family: "Claude 4.5";
|
|
2651
|
+
readonly recommendation: "fast";
|
|
2652
|
+
} & {
|
|
2653
|
+
readonly provider: "anthropic";
|
|
2654
|
+
readonly providerLabel: "Anthropic";
|
|
2655
|
+
readonly transport: "messages";
|
|
2656
|
+
} & {
|
|
2657
|
+
agentSupport: "multi-step";
|
|
2658
|
+
agentProfiles: readonly ["application", "documentation"];
|
|
2659
|
+
}, {
|
|
2660
|
+
readonly id: "gpt-5.6-sol";
|
|
2661
|
+
readonly label: "GPT-5.6 Sol";
|
|
2662
|
+
readonly family: "GPT-5.6";
|
|
2663
|
+
readonly recommendation: "frontier";
|
|
2664
|
+
} & {
|
|
2665
|
+
readonly provider: "openai";
|
|
2666
|
+
readonly providerLabel: "OpenAI";
|
|
2667
|
+
readonly transport: "chat-completions";
|
|
2668
|
+
} & {
|
|
2669
|
+
agentSupport: "multi-step";
|
|
2670
|
+
agentProfiles: readonly ["application", "documentation"];
|
|
2671
|
+
}, {
|
|
2672
|
+
readonly id: "gpt-5.6-terra";
|
|
2673
|
+
readonly label: "GPT-5.6 Terra";
|
|
2674
|
+
readonly family: "GPT-5.6";
|
|
2675
|
+
readonly recommendation: "balanced";
|
|
2676
|
+
} & {
|
|
2677
|
+
readonly provider: "openai";
|
|
2678
|
+
readonly providerLabel: "OpenAI";
|
|
2679
|
+
readonly transport: "chat-completions";
|
|
2680
|
+
} & {
|
|
2681
|
+
agentSupport: "multi-step";
|
|
2682
|
+
agentProfiles: readonly ["application", "documentation"];
|
|
2683
|
+
}, {
|
|
2684
|
+
readonly id: "gpt-5.6-luna";
|
|
2685
|
+
readonly label: "GPT-5.6 Luna";
|
|
2686
|
+
readonly family: "GPT-5.6";
|
|
2687
|
+
readonly recommendation: "fast";
|
|
2688
|
+
} & {
|
|
2689
|
+
readonly provider: "openai";
|
|
2690
|
+
readonly providerLabel: "OpenAI";
|
|
2691
|
+
readonly transport: "chat-completions";
|
|
2692
|
+
} & {
|
|
2693
|
+
agentSupport: "multi-step";
|
|
2694
|
+
agentProfiles: readonly ["application", "documentation"];
|
|
2695
|
+
}, {
|
|
2696
|
+
readonly id: "gpt-oss-120b";
|
|
2697
|
+
readonly label: "GPT-OSS 120B";
|
|
2698
|
+
readonly provider: "cerebras";
|
|
2699
|
+
readonly providerLabel: "Cerebras";
|
|
2700
|
+
readonly family: "GPT-OSS";
|
|
2701
|
+
readonly agentSupport: "single-step";
|
|
2702
|
+
readonly agentProfiles: readonly [];
|
|
2703
|
+
readonly transport: "chat-completions";
|
|
2704
|
+
readonly recommendation: "limited";
|
|
2705
|
+
readonly note: "Available for direct generation; the current proxy adapter has not passed multi-step tool-result continuation.";
|
|
2706
|
+
}];
|
|
2707
|
+
declare const DEEPSPACE_AI_DEFAULTS: {
|
|
2708
|
+
readonly agent: "claude-sonnet-5";
|
|
2709
|
+
readonly directGeneration: "claude-sonnet-5";
|
|
2710
|
+
readonly summarization: "claude-haiku-4-5";
|
|
2711
|
+
};
|
|
2712
|
+
declare const DEEPSPACE_AGENT_PROFILES: {
|
|
2713
|
+
readonly application: {
|
|
2714
|
+
readonly id: "application";
|
|
2715
|
+
readonly defaultModel: "claude-sonnet-5";
|
|
2716
|
+
readonly maxSteps: 21;
|
|
2717
|
+
readonly maxToolCalls: 20;
|
|
2718
|
+
readonly allowedTools: "application-defined";
|
|
2719
|
+
};
|
|
2720
|
+
readonly documentation: {
|
|
2721
|
+
readonly id: "documentation";
|
|
2722
|
+
readonly defaultModel: "claude-sonnet-5";
|
|
2723
|
+
readonly maxSteps: 21;
|
|
2724
|
+
readonly maxToolCalls: 20;
|
|
2725
|
+
readonly allowedTools: readonly ["documentation_search", "documentation_read"];
|
|
2726
|
+
};
|
|
2727
|
+
};
|
|
2728
|
+
type DeepSpaceAIModelId = (typeof DEEPSPACE_AI_MODELS)[number]['id'];
|
|
2729
|
+
declare function getDeepSpaceAIModel(modelId: unknown): DeepSpaceAIModel | null;
|
|
2730
|
+
declare function listDeepSpaceAgentModels(profileId?: DeepSpaceAgentProfileId): readonly DeepSpaceAIModel[];
|
|
2731
|
+
interface ResolvedDeepSpaceAgentModel {
|
|
2732
|
+
modelId: string;
|
|
2733
|
+
provider: DeepSpaceAIProvider;
|
|
2734
|
+
model: DeepSpaceAIModel;
|
|
2735
|
+
profile: DeepSpaceAgentProfile;
|
|
2736
|
+
}
|
|
2737
|
+
declare function resolveDeepSpaceAgentModel(modelId: unknown, profileId?: DeepSpaceAgentProfileId): ResolvedDeepSpaceAgentModel | null;
|
|
2738
|
+
|
|
2555
2739
|
/**
|
|
2556
2740
|
* Wildcard-aware CORS origin matching for the platform workers.
|
|
2557
2741
|
*
|
|
@@ -3058,7 +3242,6 @@ declare function buildCronContext(env: CronEnv, ownerUserId: string, roomId?: st
|
|
|
3058
3242
|
* paths into the published `dist/index.d.ts`.
|
|
3059
3243
|
*/
|
|
3060
3244
|
type DeepSpaceModelFactory = (modelId: string) => LanguageModel;
|
|
3061
|
-
type Provider = 'anthropic' | 'openai' | 'cerebras';
|
|
3062
3245
|
interface DeepSpaceAIEnv extends ApiWorkerEnv {
|
|
3063
3246
|
/**
|
|
3064
3247
|
* Long-lived owner-scoped JWT minted at deploy time (or by `deepspace dev start`).
|
|
@@ -3086,7 +3269,39 @@ interface DeepSpaceAIOptions {
|
|
|
3086
3269
|
* (explicit or `env.APP_OWNER_JWT`) automatically. Throws a clear error if
|
|
3087
3270
|
* either is unconfigured.
|
|
3088
3271
|
*/
|
|
3089
|
-
declare function createDeepSpaceAI(env: DeepSpaceAIEnv, provider:
|
|
3272
|
+
declare function createDeepSpaceAI(env: DeepSpaceAIEnv, provider: DeepSpaceAIProvider, options?: DeepSpaceAIOptions): DeepSpaceModelFactory;
|
|
3273
|
+
|
|
3274
|
+
type StreamTextOptions<TOOLS extends ToolSet> = Parameters<typeof streamText<TOOLS>>[0];
|
|
3275
|
+
type DeepSpaceAgentStreamOptions<TOOLS extends ToolSet> = Omit<StreamTextOptions<TOOLS>, 'model' | 'providerOptions' | 'stopWhen'> & {
|
|
3276
|
+
profile: DeepSpaceAgentProfileId;
|
|
3277
|
+
modelId?: unknown;
|
|
3278
|
+
authToken?: string;
|
|
3279
|
+
};
|
|
3280
|
+
interface DeepSpaceAgentStream<TOOLS extends ToolSet> {
|
|
3281
|
+
selection: ResolvedDeepSpaceAgentModel;
|
|
3282
|
+
result: StreamTextResult<TOOLS, never>;
|
|
3283
|
+
}
|
|
3284
|
+
declare class DeepSpaceAgentModelError extends Error {
|
|
3285
|
+
readonly modelId: unknown;
|
|
3286
|
+
readonly profile: DeepSpaceAgentProfileId;
|
|
3287
|
+
readonly code = "unsupported_agent_model";
|
|
3288
|
+
constructor(modelId: unknown, profile: DeepSpaceAgentProfileId);
|
|
3289
|
+
}
|
|
3290
|
+
declare class DeepSpaceAgentProfileError extends Error {
|
|
3291
|
+
readonly profile: DeepSpaceAgentProfileId;
|
|
3292
|
+
readonly toolName: string;
|
|
3293
|
+
readonly code = "agent_profile_violation";
|
|
3294
|
+
constructor(profile: DeepSpaceAgentProfileId, toolName: string);
|
|
3295
|
+
}
|
|
3296
|
+
/** The sole provider/model/tool-loop implementation for every DeepSpace agent surface. */
|
|
3297
|
+
declare function streamDeepSpaceAgent<TOOLS extends ToolSet>(env: DeepSpaceAIEnv, options: DeepSpaceAgentStreamOptions<TOOLS>): DeepSpaceAgentStream<TOOLS>;
|
|
3298
|
+
interface DeepSpaceAgentDiagnosticContext {
|
|
3299
|
+
profile?: DeepSpaceAgentProfileId;
|
|
3300
|
+
provider?: string;
|
|
3301
|
+
modelId?: string;
|
|
3302
|
+
}
|
|
3303
|
+
/** Preserve safe structured provider diagnostics in bounded Worker logs. */
|
|
3304
|
+
declare function deepSpaceAgentErrorSummary(error: unknown, context?: DeepSpaceAgentDiagnosticContext): string;
|
|
3090
3305
|
|
|
3091
3306
|
/**
|
|
3092
3307
|
* Composio tools for the Vercel AI SDK.
|
|
@@ -3554,6 +3769,35 @@ interface RunMigrationsResult {
|
|
|
3554
3769
|
*/
|
|
3555
3770
|
declare function runMigrations(db: D1Database, migrations: readonly string[]): Promise<RunMigrationsResult>;
|
|
3556
3771
|
|
|
3772
|
+
interface DocumentationAssistantRouteEnv extends DeepSpaceAIEnv {
|
|
3773
|
+
ASSETS: Fetcher;
|
|
3774
|
+
APP_NAME: string;
|
|
3775
|
+
DEEPSPACE_APP_ID: string;
|
|
3776
|
+
DOCUMENTATION_CLIENT_RATE_LIMITER?: RateLimit;
|
|
3777
|
+
DOCUMENTATION_APP_RATE_LIMITER?: RateLimit;
|
|
3778
|
+
}
|
|
3779
|
+
|
|
3780
|
+
interface DocumentationMcpRouteEnv {
|
|
3781
|
+
ASSETS: Fetcher;
|
|
3782
|
+
DEEPSPACE_APP_ID: string;
|
|
3783
|
+
DOCUMENTATION_CLIENT_RATE_LIMITER?: RateLimit;
|
|
3784
|
+
DOCUMENTATION_APP_RATE_LIMITER?: RateLimit;
|
|
3785
|
+
}
|
|
3786
|
+
|
|
3787
|
+
interface DeepSpaceDocumentationRouteEnv extends DocumentationAssistantRouteEnv, DocumentationMcpRouteEnv {
|
|
3788
|
+
}
|
|
3789
|
+
interface DeepSpaceDocumentationRouteOptions<Env extends DeepSpaceDocumentationRouteEnv> {
|
|
3790
|
+
resolveAuth: (request: Request, env: Env) => Promise<unknown | null>;
|
|
3791
|
+
config?: {
|
|
3792
|
+
domains?: readonly string[];
|
|
3793
|
+
[key: string]: unknown;
|
|
3794
|
+
};
|
|
3795
|
+
}
|
|
3796
|
+
/** Register the complete native documentation protocol surface in its required order. */
|
|
3797
|
+
declare function registerDeepSpaceDocumentation<Env extends DeepSpaceDocumentationRouteEnv>(app: Hono<{
|
|
3798
|
+
Bindings: Env;
|
|
3799
|
+
}>, options: DeepSpaceDocumentationRouteOptions<Env>): void;
|
|
3800
|
+
|
|
3557
3801
|
/**
|
|
3558
3802
|
* Auth types for the DeepSpace SDK.
|
|
3559
3803
|
*
|
|
@@ -4894,4 +5138,4 @@ interface AppLogsResponse {
|
|
|
4894
5138
|
declare const APP_LOG_EVENT_KEYS: readonly ["id", "timestamp", "level", "eventType", "message", "source", "outcome", "request", "exception"];
|
|
4895
5139
|
type AppLogEventKey = (typeof APP_LOG_EVENT_KEYS)[number];
|
|
4896
5140
|
|
|
4897
|
-
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 AppMigrationIdsValidation, type AppNameResolution, type AppNameValidation, type AuthWorkerEnv, Awareness, type AwarenessState, type AwarenessStates, BASE_USERS_SCHEMA, BUILT_IN_TOOLS, type BaseMessage, BaseRoom, CANONICAL_APP_IDENTITY_MIGRATION_ID, 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, RESOURCE_ID_RE, 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, validateAppMigrationIds, validateAppName, validateBindingManifest, validateDoManifest, verifyJwt, workspaceAccountsSchema, workspaceContentSharesSchema, workspaceEmailHandlesSchema, workspaceFormResponsesSchema, workspacePeopleSchema, workspaceProjectsSchema, workspaceTagsSchema, workspaceTasksSchema, workspaceTeamMembersSchema, workspaceTeamsSchema, workspaceTransactionsSchema, writeVarUint, writeVarUint8Array };
|
|
5141
|
+
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 AppMigrationIdsValidation, type AppNameResolution, type AppNameValidation, type AuthWorkerEnv, Awareness, type AwarenessState, type AwarenessStates, BASE_USERS_SCHEMA, BUILT_IN_TOOLS, type BaseMessage, BaseRoom, CANONICAL_APP_IDENTITY_MIGRATION_ID, 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, DEEPSPACE_AGENT_PROFILES, DEEPSPACE_AI_DEFAULTS, DEEPSPACE_AI_MODELS, DEEPSPACE_MODEL_CATALOG_PROVENANCE, DEFAULT_CONTEXT_CONFIG, DEFAULT_DO_MANIFEST, DEFAULT_QUERY_LIMIT, DEPLOYED_APPS_DEFAULTS, DIRECTORY_SCHEMAS, type DOBindings, type DOManifest, type DOManifestEntry, type DeepSpaceAIEnv, type DeepSpaceAIModel, type DeepSpaceAIModelId, type DeepSpaceAIOptions, type DeepSpaceAIProvider, type DeepSpaceAgentDiagnosticContext, DeepSpaceAgentModelError, type DeepSpaceAgentProfile, DeepSpaceAgentProfileError, type DeepSpaceAgentProfileId, type DeepSpaceAgentStream, type DeepSpaceAgentStreamOptions, type DeepSpaceAgentSupport, type DeepSpaceAuth, type DeepSpaceAuthConfig, type DeepSpaceDocumentationRouteEnv, type DeepSpaceDocumentationRouteOptions, 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, RESOURCE_ID_RE, ROLE_ADMIN, ROLE_ANONYMOUS, ROLE_DEFAULT, RecordRoom, type RecordRoomConfig, RegistryClientError, type ResolvedColumn, type ResolvedDeepSpaceAgentModel, 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, deepSpaceAgentErrorSummary, deleteChatCascade, dispatch, encode, encodeAwarenessMessage, encodeSyncStep1, encodeSyncStep2, encodeUpdate, enqueueJob, getChat, getDeepSpaceAIModel, getGlobalDOSchemas, getGlobalDOType, getMessageType, getRolePermissions, handleAwarenessMessage, handleClientErrorReport, handleSyncMessage, hasContent, isAutoProvision, isOwner, isTestAccountClaims, isTestAccountEmail, isTestAccountTier, lintSchema, listDeepSpaceAgentModels, loadMessages, makeDefaultSummarizer, matchOrigin, meterAi, meterUsage, meterVectorize, noopPermissionContext, parseQuotaLimit, platformCorsPatterns, platformWorkerFetch, prepareMessagesWithCompaction, priceBindingUsageEvent, readVarUint, readVarUint8Array, registerClientErrorRoute, registerDeepSpaceDocumentation, registryErrorJson, registryStub, resolveAppName, resolveColumn, resolveDeepSpaceAgentModel, rowToData, runMigrations, serverBuild, streamDeepSpaceAgent, timingSafeEqualHex, timingSafeEqualStrings, toUint8Array, totalChars, truncateOldToolResults, turnsToCoreMessages, unwrapToolOutput, updateChat, validateAppMigrationIds, validateAppName, validateBindingManifest, validateDoManifest, verifyJwt, workspaceAccountsSchema, workspaceContentSharesSchema, workspaceEmailHandlesSchema, workspaceFormResponsesSchema, workspacePeopleSchema, workspaceProjectsSchema, workspaceTagsSchema, workspaceTasksSchema, workspaceTeamMembersSchema, workspaceTeamsSchema, workspaceTransactionsSchema, writeVarUint, writeVarUint8Array };
|