deepspace 0.4.3 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +331 -384
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +47 -425
- package/dist/index.js +272 -1688
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +122 -27
- package/dist/server.js +218 -17
- package/dist/server.js.map +1 -1
- package/dist/worker.d.ts +122 -27
- package/dist/worker.js +218 -17
- package/dist/worker.js.map +1 -1
- package/features/admin-page/src/AdminPage.tsx +1 -1
- package/features/canvas/src/CanvasListPage.tsx +1 -1
- package/features/canvas/src/components/CanvasView.tsx +1 -1
- package/features/docs/src/DocsEditorPage.tsx +1 -1
- package/features/docs/src/InviteDialog.tsx +130 -139
- package/features/file-attachments/src/AttachmentsPage.tsx +1 -4
- package/features/file-manager/src/FileManagerPage.tsx +2 -1
- package/features/items/src/ItemsPage.tsx +1 -1
- package/features/landing/src/LandingPage.tsx +1 -1
- package/features/landing/src/primitives.tsx +1 -1
- package/features/leaderboard/src/LeaderboardPage.tsx +1 -1
- package/features/leaderboard/src/leaderboard-constants.ts +1 -1
- package/features/search-bar/src/SearchOverlay.tsx +1 -1
- package/features/tasks/src/TasksPage.tsx +1 -1
- package/features/tasks/src/tasks-constants.ts +1 -1
- package/package.json +1 -18
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { LanguageModel, ModelMessage } from 'ai';
|
|
1
|
+
import { LanguageModel, ToolSet, ModelMessage } from 'ai';
|
|
2
2
|
import * as Y from 'yjs';
|
|
3
3
|
import * as better_auth from 'better-auth';
|
|
4
|
+
import { betterAuth } from 'better-auth';
|
|
4
5
|
import * as better_auth_plugins from 'better-auth/plugins';
|
|
5
6
|
import { Context } from 'hono';
|
|
6
7
|
|
|
@@ -31,6 +32,30 @@ type ToolResult = {
|
|
|
31
32
|
success: false;
|
|
32
33
|
error: string;
|
|
33
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Page size the assistant defaults to for `records.query` when it omits
|
|
37
|
+
* `limit`. Keeps a model-issued unbounded scan from blowing the tool-result
|
|
38
|
+
* byte cap and gives the model a usable first page. Raise `limit` to page
|
|
39
|
+
* through more (still subject to the cap; see
|
|
40
|
+
* `DEFAULT_CONTEXT_CONFIG.toolResultCap` / `capToolResultSize`, which truncates
|
|
41
|
+
* oversized pages gracefully rather than dropping them).
|
|
42
|
+
*
|
|
43
|
+
* Applied by the AI tool layer via `applyAiToolDefaults`, never by the shared
|
|
44
|
+
* tools-api dispatch, so internal record readers (chat history, cron, app
|
|
45
|
+
* `actions.query`) stay unbounded.
|
|
46
|
+
*/
|
|
47
|
+
declare const DEFAULT_QUERY_LIMIT = 50;
|
|
48
|
+
/**
|
|
49
|
+
* Fill in assistant-only parameter defaults for a built-in tool call.
|
|
50
|
+
*
|
|
51
|
+
* Applied by the AI tool layer (`buildTools`) before a model-issued tool call
|
|
52
|
+
* is dispatched, so the default only affects calls the assistant makes.
|
|
53
|
+
* `records.query` doubles as the SDK's general record-read primitive (chat
|
|
54
|
+
* history, cron, app `actions.query`); those callers reach the tools dispatch
|
|
55
|
+
* directly and must return every row, so this default must not live in the
|
|
56
|
+
* dispatch itself. Pure and non-mutating.
|
|
57
|
+
*/
|
|
58
|
+
declare function applyAiToolDefaults(toolName: string, params: Record<string, unknown>): Record<string, unknown>;
|
|
34
59
|
/**
|
|
35
60
|
* Built-in tool definitions for storage, record, schema, user, and backup operations
|
|
36
61
|
*/
|
|
@@ -470,7 +495,7 @@ interface CronContext {
|
|
|
470
495
|
};
|
|
471
496
|
/**
|
|
472
497
|
* Call a platform integration endpoint (e.g. "openai/chat-completion",
|
|
473
|
-
* "
|
|
498
|
+
* "fal/run-model"). Billed to the app owner using the same
|
|
474
499
|
* APP_OWNER_JWT the rest of the SDK uses for server-side billed calls.
|
|
475
500
|
*/
|
|
476
501
|
integrations: {
|
|
@@ -569,6 +594,49 @@ interface DeepSpaceAIOptions {
|
|
|
569
594
|
*/
|
|
570
595
|
declare function createDeepSpaceAI(env: DeepSpaceAIEnv, provider: Provider, options?: DeepSpaceAIOptions): DeepSpaceModelFactory;
|
|
571
596
|
|
|
597
|
+
/**
|
|
598
|
+
* Composio tools for the Vercel AI SDK.
|
|
599
|
+
*
|
|
600
|
+
* Turns the platform's Composio integration into ready-to-use Vercel AI SDK
|
|
601
|
+
* tools, so an agent (or the DeepSpace AI chat) can take actions on a user's
|
|
602
|
+
* connected apps. Each returned tool's `execute()` calls our own
|
|
603
|
+
* `composio/execute-tool` endpoint through the api-worker proxy, so our auth
|
|
604
|
+
* and per-user billing apply. This is the managed-proxy equivalent of
|
|
605
|
+
* Composio's `@composio/vercel` provider, which talks straight to Composio.
|
|
606
|
+
*
|
|
607
|
+
* `authToken` must be the END USER's JWT: Composio resolves the user's
|
|
608
|
+
* connected accounts by the JWT subject, and that user is billed.
|
|
609
|
+
*
|
|
610
|
+
* Usage (inside a request handler, e.g. /api/ai/chat):
|
|
611
|
+
*
|
|
612
|
+
* import { composioTools, createDeepSpaceAI } from 'deepspace/worker'
|
|
613
|
+
* const jwt = c.req.header('Authorization')!.slice(7)
|
|
614
|
+
* const tools = await composioTools(c.env, { toolkit: 'gmail', authToken: jwt })
|
|
615
|
+
* const ai = createDeepSpaceAI(c.env, 'anthropic', { authToken: jwt })
|
|
616
|
+
* const result = streamText({ model: ai('claude-sonnet-4-6'), prompt, tools })
|
|
617
|
+
*
|
|
618
|
+
* Merge with your own tools: `tools: { ...buildTools(executor), ...composio }`.
|
|
619
|
+
*/
|
|
620
|
+
|
|
621
|
+
interface ComposioToolsOptions {
|
|
622
|
+
/** End user's JWT. Required: the tools run as this user and bill them. */
|
|
623
|
+
authToken: string;
|
|
624
|
+
/** Restrict to one toolkit (e.g. 'gmail', 'github'). */
|
|
625
|
+
toolkit?: string;
|
|
626
|
+
/** Explicit tool slugs to expose (e.g. ['GMAIL_SEND_EMAIL']). */
|
|
627
|
+
tools?: string[];
|
|
628
|
+
/** Natural-language search to pick relevant tools. */
|
|
629
|
+
search?: string;
|
|
630
|
+
/** Cap how many tools are exposed (default 20). Keep small: the LLM sees them all. */
|
|
631
|
+
limit?: number;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Fetch Composio tools for the given scope and return them as a Vercel AI SDK
|
|
635
|
+
* `ToolSet`. One `list-tools` call provides each tool's JSON Schema; each tool
|
|
636
|
+
* executes via `composio/execute-tool` as the authenticated user.
|
|
637
|
+
*/
|
|
638
|
+
declare function composioTools(env: ApiWorkerEnv, options: ComposioToolsOptions): Promise<ToolSet>;
|
|
639
|
+
|
|
572
640
|
/**
|
|
573
641
|
* captureScreenshot — call platform-worker /internal/screenshot.
|
|
574
642
|
*
|
|
@@ -657,8 +725,17 @@ declare function truncateOldToolResults(messages: ChatTurn[], keepRecent: number
|
|
|
657
725
|
*/
|
|
658
726
|
declare function applySlidingWindow(messages: ChatTurn[], charCap: number, minKept: number): ChatTurn[];
|
|
659
727
|
/**
|
|
660
|
-
*
|
|
661
|
-
*
|
|
728
|
+
* Keep an individual tool result under `byteCap`.
|
|
729
|
+
*
|
|
730
|
+
* If the payload carries a list of items (e.g. a `records.query` result), it is
|
|
731
|
+
* degraded gracefully: as many leading items as fit under the cap are returned,
|
|
732
|
+
* the `success: true` shape is preserved, and `{ truncated, returned, total }`
|
|
733
|
+
* flags are merged in next to the array so callers can still use the partial
|
|
734
|
+
* data and paginate for the rest.
|
|
735
|
+
*
|
|
736
|
+
* Only when there is no array to trim (or even an empty list still overflows
|
|
737
|
+
* because of oversized sibling fields) does it fall back to replacing the
|
|
738
|
+
* result with an error + small preview telling the agent to narrow its query.
|
|
662
739
|
*/
|
|
663
740
|
declare function capToolResultSize(result: unknown, byteCap: number): unknown;
|
|
664
741
|
/**
|
|
@@ -2971,11 +3048,6 @@ declare function timingSafeEqualHex(a: string, b: string): Promise<boolean>;
|
|
|
2971
3048
|
|
|
2972
3049
|
declare function decodeJwtPayload(token: string | null | undefined): TokenDebugInfo | undefined;
|
|
2973
3050
|
|
|
2974
|
-
/**
|
|
2975
|
-
* Better Auth configuration factory for DeepSpace
|
|
2976
|
-
*
|
|
2977
|
-
* Provides pre-configured Better Auth instances for Cloudflare Workers + D1.
|
|
2978
|
-
*/
|
|
2979
3051
|
interface DeepSpaceAuthConfig {
|
|
2980
3052
|
/** D1 database binding */
|
|
2981
3053
|
database: D1Database;
|
|
@@ -2993,29 +3065,28 @@ interface DeepSpaceAuthConfig {
|
|
|
2993
3065
|
clientId: string;
|
|
2994
3066
|
clientSecret: string;
|
|
2995
3067
|
};
|
|
3068
|
+
/** Microsoft (Entra ID) OAuth credentials (optional) */
|
|
3069
|
+
microsoft?: {
|
|
3070
|
+
clientId: string;
|
|
3071
|
+
clientSecret: string;
|
|
3072
|
+
};
|
|
3073
|
+
/**
|
|
3074
|
+
* Apple (Sign in with Apple) credentials (optional). Pass the raw
|
|
3075
|
+
* Sign-in-with-Apple key material; the ES256 client-secret JWT is minted
|
|
3076
|
+
* on demand, so there is no six-month token to rotate by hand.
|
|
3077
|
+
*/
|
|
3078
|
+
apple?: {
|
|
3079
|
+
clientId: string;
|
|
3080
|
+
teamId: string;
|
|
3081
|
+
keyId: string;
|
|
3082
|
+
privateKey: string;
|
|
3083
|
+
};
|
|
2996
3084
|
/** Enable email/password authentication */
|
|
2997
3085
|
emailAndPassword?: boolean;
|
|
2998
3086
|
/** Trusted origins for CORS */
|
|
2999
3087
|
trustedOrigins?: string[];
|
|
3000
3088
|
}
|
|
3001
|
-
/**
|
|
3002
|
-
* Create a Better Auth instance configured for DeepSpace.
|
|
3003
|
-
*
|
|
3004
|
-
* This is called per-request in the auth worker since D1 bindings
|
|
3005
|
-
* are request-scoped in Cloudflare Workers.
|
|
3006
|
-
*/
|
|
3007
3089
|
declare function createDeepSpaceAuth(config: DeepSpaceAuthConfig): better_auth.Auth<{
|
|
3008
|
-
database: D1Database;
|
|
3009
|
-
baseURL: string;
|
|
3010
|
-
secret: string;
|
|
3011
|
-
emailAndPassword: {
|
|
3012
|
-
enabled: boolean;
|
|
3013
|
-
};
|
|
3014
|
-
socialProviders: Record<string, {
|
|
3015
|
-
clientId: string;
|
|
3016
|
-
clientSecret: string;
|
|
3017
|
-
}>;
|
|
3018
|
-
trustedOrigins: string[];
|
|
3019
3090
|
plugins: [{
|
|
3020
3091
|
id: "organization";
|
|
3021
3092
|
endpoints: better_auth_plugins.OrganizationEndpoints<better_auth_plugins.OrganizationOptions & {
|
|
@@ -3815,6 +3886,30 @@ declare function createDeepSpaceAuth(config: DeepSpaceAuthConfig): better_auth.A
|
|
|
3815
3886
|
INVALID_TWO_FACTOR_COOKIE: better_auth.RawError<"INVALID_TWO_FACTOR_COOKIE">;
|
|
3816
3887
|
};
|
|
3817
3888
|
}];
|
|
3889
|
+
advanced?: {
|
|
3890
|
+
cookies: {
|
|
3891
|
+
state: {
|
|
3892
|
+
attributes: {
|
|
3893
|
+
sameSite: "none";
|
|
3894
|
+
secure: true;
|
|
3895
|
+
};
|
|
3896
|
+
};
|
|
3897
|
+
oauth_state: {
|
|
3898
|
+
attributes: {
|
|
3899
|
+
sameSite: "none";
|
|
3900
|
+
secure: true;
|
|
3901
|
+
};
|
|
3902
|
+
};
|
|
3903
|
+
};
|
|
3904
|
+
} | undefined;
|
|
3905
|
+
database: D1Database;
|
|
3906
|
+
baseURL: string;
|
|
3907
|
+
secret: string;
|
|
3908
|
+
emailAndPassword: {
|
|
3909
|
+
enabled: boolean;
|
|
3910
|
+
};
|
|
3911
|
+
socialProviders: Parameters<typeof betterAuth>[0]["socialProviders"];
|
|
3912
|
+
trustedOrigins: string[];
|
|
3818
3913
|
}>;
|
|
3819
3914
|
type DeepSpaceAuth = ReturnType<typeof createDeepSpaceAuth>;
|
|
3820
3915
|
|
|
@@ -3971,4 +4066,4 @@ declare class RefundError extends Error {
|
|
|
3971
4066
|
constructor(message: string, status: number);
|
|
3972
4067
|
}
|
|
3973
4068
|
|
|
3974
|
-
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, BASE_USERS_SCHEMA, BUILT_IN_TOOLS, BaseRoom, CHANNELS_SCHEMA, CHANNEL_INVITATIONS_SCHEMA, CHANNEL_MEMBERS_SCHEMA, CONVERSATION_SCHEMAS, COST_RATES, CancelSubscriptionError, type CancelSubscriptionOpts, type CancelSubscriptionResult, CanvasRoom, type CanvasShape, type ChatContextConfig, type ChatMessageRow, type ChatRow, type ChatTurn, type CollectionPermissionSummary, type CollectionSchema, type ColumnDefinition, type ColumnInterpretation, 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, DIRECTORY_SCHEMAS, type DOBindings, type DOManifest, type DOManifestEntry, type DebugApiContext, 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 Job, type JobContext, JobRoom, type JobRoomConfig, type JobStatus, type JwtClaims, type JwtVerifierConfig, MESSAGES_SCHEMA, type MutateActionData, type PermissionAnalysis, type PermissionContext, type PermissionLevel, type PermissionSource, type PlanInfo, type PlatformWorkerEnv, type Player, type PrefixResult, type PresencePeer, PresenceRoom, type QueryActionData, REACTIONS_SCHEMA, READ_RECEIPTS_SCHEMA, RESERVED_BINDING_NAMES, RESERVED_COLLECTION_NAMES, type RecordContext, RecordRoom, type RecordRoomConfig, RefundError, type RefundOpts, type RefundResult, type ResolvedColumn, type ResolvedPermission, type RolePermissions, type RunMigrationsResult, SYSTEM_COLLECTION_SCHEMAS, SYSTEM_MANAGED_COLUMNS, SchemaRegistry, type ScopeContext, type ScopedR2Auth, type ScopedR2Config, type ScopedR2Handler, type ScreenshotEnv, type ScreenshotOptions, type ScreenshotResult, type SharedConnection, type StoredRecord, SubscriptionAuthError, type SubscriptionContext, type SubscriptionRead, SubscriptionRequiredError, type SubscriptionStatus, type Summarizer, type TokenDebugInfo, type ToolResult, type ToolSchema, type ToolsApiContext, USERS_COLUMNS, type User, type UserAttachment, type UserContext, VOTING_SCHEMAS, type ValidationError, type VerifiedAuth, type VerifyOutcome, type VerifyResult, type Viewport, WORKSPACE_SCHEMAS, type YjsContext, YjsRoom, analyzePermissions, apiWorkerFetch, appendMessage, applySlidingWindow, authWorkerFetch, bindingManifestFromOutputConfig, broadcastChange, broadcastYjsUpdate, buildCronContext, buildTableSelect, buildUiParts, canCreate, canDelete, canRead, canUpdate, cancelSubscription, capToolResultSize, captureScreenshot, checkFieldPermissions, coerceValue, collectionTableName, columnId, computeDoMigration, computeHmacHex, createChat, createDeepSpaceAI, createDeepSpaceAuth, createScopedR2Handler, dataToColumnValues, decodeJwtPayload, deleteChatCascade, deleteRecord, enqueueJob, executeQuery, getAllUsers, getChat, getGlobalDOSchemas, getGlobalDOType, getOrCreateYjsDoc, getRecord, getRolePermissions, getSubscription, getUser, getYjsDocKey, handleApiRequest, handleDelete, handlePut, handleSetRole, handleSubscribe, handleToolsRequest, handleUnsubscribe, handleUserList, handleUserUpdate, handleYjsBinaryMessage, handleYjsJoin, handleYjsLeave, isAutoProvision, isOwner, lintSchema, loadMessages, makeDefaultSummarizer, meterAi, meterUsage, meterVectorize, noopPermissionContext, platformWorkerFetch, prepareMessagesWithCompaction, priceBindingUsageEvent, putRecord, readRecord, recordMatchesSubscription, refundInvoice, registerUser, requireSubscription, resolveAppName, resolveColumn, rowToData, runMigrations, saveYjsDoc, timingSafeEqualHex, totalChars, truncateOldToolResults, turnsToCoreMessages, unwrapToolOutput, updateChat, validateAppName, validateBindingManifest, validateDoManifest, verifyJwt, workspaceAccountsSchema, workspaceContentSharesSchema, workspaceEmailHandlesSchema, workspaceFormResponsesSchema, workspacePeopleSchema, workspaceProjectsSchema, workspaceTagsSchema, workspaceTasksSchema, workspaceTeamMembersSchema, workspaceTeamsSchema, workspaceTransactionsSchema };
|
|
4069
|
+
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, BASE_USERS_SCHEMA, BUILT_IN_TOOLS, BaseRoom, CHANNELS_SCHEMA, CHANNEL_INVITATIONS_SCHEMA, CHANNEL_MEMBERS_SCHEMA, CONVERSATION_SCHEMAS, COST_RATES, CancelSubscriptionError, type CancelSubscriptionOpts, type CancelSubscriptionResult, CanvasRoom, type CanvasShape, type ChatContextConfig, type ChatMessageRow, type ChatRow, type ChatTurn, type CollectionPermissionSummary, type CollectionSchema, type ColumnDefinition, type ColumnInterpretation, type ComposioToolsOptions, 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 DebugApiContext, 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 Job, type JobContext, JobRoom, type JobRoomConfig, type JobStatus, type JwtClaims, type JwtVerifierConfig, MESSAGES_SCHEMA, type MutateActionData, type PermissionAnalysis, type PermissionContext, type PermissionLevel, type PermissionSource, type PlanInfo, type PlatformWorkerEnv, type Player, type PrefixResult, type PresencePeer, PresenceRoom, type QueryActionData, REACTIONS_SCHEMA, READ_RECEIPTS_SCHEMA, RESERVED_BINDING_NAMES, RESERVED_COLLECTION_NAMES, type RecordContext, RecordRoom, type RecordRoomConfig, RefundError, type RefundOpts, type RefundResult, type ResolvedColumn, type ResolvedPermission, type RolePermissions, type RunMigrationsResult, SYSTEM_COLLECTION_SCHEMAS, SYSTEM_MANAGED_COLUMNS, SchemaRegistry, type ScopeContext, type ScopedR2Auth, type ScopedR2Config, type ScopedR2Handler, type ScreenshotEnv, type ScreenshotOptions, type ScreenshotResult, type SharedConnection, type StoredRecord, SubscriptionAuthError, type SubscriptionContext, type SubscriptionRead, SubscriptionRequiredError, type SubscriptionStatus, type Summarizer, type TokenDebugInfo, type ToolResult, type ToolSchema, type ToolsApiContext, USERS_COLUMNS, type User, type UserAttachment, type UserContext, VOTING_SCHEMAS, type ValidationError, type VerifiedAuth, type VerifyOutcome, type VerifyResult, type Viewport, WORKSPACE_SCHEMAS, type YjsContext, YjsRoom, analyzePermissions, apiWorkerFetch, appendMessage, applyAiToolDefaults, applySlidingWindow, authWorkerFetch, bindingManifestFromOutputConfig, broadcastChange, broadcastYjsUpdate, buildCronContext, buildTableSelect, buildUiParts, canCreate, canDelete, canRead, canUpdate, cancelSubscription, capToolResultSize, captureScreenshot, checkFieldPermissions, coerceValue, collectionTableName, columnId, composioTools, computeDoMigration, computeHmacHex, createChat, createDeepSpaceAI, createDeepSpaceAuth, createScopedR2Handler, dataToColumnValues, decodeJwtPayload, deleteChatCascade, deleteRecord, enqueueJob, executeQuery, getAllUsers, getChat, getGlobalDOSchemas, getGlobalDOType, getOrCreateYjsDoc, getRecord, getRolePermissions, getSubscription, getUser, getYjsDocKey, handleApiRequest, handleDelete, handlePut, handleSetRole, handleSubscribe, handleToolsRequest, handleUnsubscribe, handleUserList, handleUserUpdate, handleYjsBinaryMessage, handleYjsJoin, handleYjsLeave, isAutoProvision, isOwner, lintSchema, loadMessages, makeDefaultSummarizer, meterAi, meterUsage, meterVectorize, noopPermissionContext, platformWorkerFetch, prepareMessagesWithCompaction, priceBindingUsageEvent, putRecord, readRecord, recordMatchesSubscription, refundInvoice, registerUser, requireSubscription, resolveAppName, resolveColumn, rowToData, runMigrations, saveYjsDoc, timingSafeEqualHex, totalChars, truncateOldToolResults, turnsToCoreMessages, unwrapToolOutput, updateChat, validateAppName, validateBindingManifest, validateDoManifest, verifyJwt, workspaceAccountsSchema, workspaceContentSharesSchema, workspaceEmailHandlesSchema, workspaceFormResponsesSchema, workspacePeopleSchema, workspaceProjectsSchema, workspaceTagsSchema, workspaceTasksSchema, workspaceTeamMembersSchema, workspaceTeamsSchema, workspaceTransactionsSchema };
|
package/dist/server.js
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
1
|
// src/server/utils/tools.ts
|
|
2
|
+
var DEFAULT_QUERY_LIMIT = 50;
|
|
3
|
+
function applyAiToolDefaults(toolName, params) {
|
|
4
|
+
if (toolName === "records.query" && params.limit === void 0) {
|
|
5
|
+
return { ...params, limit: DEFAULT_QUERY_LIMIT };
|
|
6
|
+
}
|
|
7
|
+
return params;
|
|
8
|
+
}
|
|
2
9
|
var BUILT_IN_TOOLS = [
|
|
3
10
|
// Record tools (structured collections with RBAC)
|
|
4
11
|
{
|
|
5
12
|
name: "records.query",
|
|
6
|
-
description:
|
|
13
|
+
description: `Query records from a collection with optional filtering, ordering, and pagination. Returns at most \`limit\` records (default ${DEFAULT_QUERY_LIMIT}). Large result sets are capped at ~30KB: an oversized page is truncated to the leading records that fit and flagged with \`{ truncated, returned, total }\`, so narrow with a \`where\` filter (or page via \`orderBy\` + \`limit\`) to see the rest.`,
|
|
7
14
|
params: {
|
|
8
15
|
collection: { type: "string", description: "Collection name to query", required: true },
|
|
9
16
|
where: { type: "object", description: "Filter object with field=value equality conditions", required: false },
|
|
10
17
|
orderBy: { type: "string", description: 'Field to order by (or "createdAt"/"updatedAt")', required: false },
|
|
11
18
|
orderDir: { type: "string", description: 'Order direction: "asc" or "desc" (default: "desc")', required: false },
|
|
12
|
-
limit: { type: "number", description:
|
|
19
|
+
limit: { type: "number", description: `Maximum number of records to return (default: ${DEFAULT_QUERY_LIMIT}). Oversized pages are still capped at ~30KB and truncated with returned/total flags.`, required: false }
|
|
13
20
|
}
|
|
14
21
|
},
|
|
15
22
|
{
|
|
@@ -446,7 +453,7 @@ function authWorkerFetch(env, path, init) {
|
|
|
446
453
|
function buildCronContext(env, ownerUserId, roomId = "default") {
|
|
447
454
|
const roomIdObj = env.RECORD_ROOMS.idFromName(roomId);
|
|
448
455
|
const room = env.RECORD_ROOMS.get(roomIdObj);
|
|
449
|
-
async function executeTool3(
|
|
456
|
+
async function executeTool3(tool2, params) {
|
|
450
457
|
const response = await room.fetch(new Request("https://internal/api/tools/execute", {
|
|
451
458
|
method: "POST",
|
|
452
459
|
headers: {
|
|
@@ -454,11 +461,11 @@ function buildCronContext(env, ownerUserId, roomId = "default") {
|
|
|
454
461
|
"X-User-Id": ownerUserId,
|
|
455
462
|
"X-App-Action": "true"
|
|
456
463
|
},
|
|
457
|
-
body: JSON.stringify({ tool, params })
|
|
464
|
+
body: JSON.stringify({ tool: tool2, params })
|
|
458
465
|
}));
|
|
459
466
|
const result = await response.json();
|
|
460
467
|
if (!result.success) {
|
|
461
|
-
throw new Error(`RecordRoom tool ${
|
|
468
|
+
throw new Error(`RecordRoom tool ${tool2} failed: ${result.error || "Unknown error"}`);
|
|
462
469
|
}
|
|
463
470
|
return result.data;
|
|
464
471
|
}
|
|
@@ -579,6 +586,87 @@ function createDeepSpaceAI(env, provider, options = {}) {
|
|
|
579
586
|
}
|
|
580
587
|
}
|
|
581
588
|
|
|
589
|
+
// src/server/utils/composio-tools.ts
|
|
590
|
+
import { tool, jsonSchema } from "ai";
|
|
591
|
+
var EMPTY_SCHEMA = { type: "object", properties: {} };
|
|
592
|
+
async function requestComposio(env, endpoint, params, authToken) {
|
|
593
|
+
const res = await apiWorkerFetch(env, `/api/integrations/composio/${endpoint}`, {
|
|
594
|
+
method: "POST",
|
|
595
|
+
headers: {
|
|
596
|
+
"Content-Type": "application/json",
|
|
597
|
+
Authorization: `Bearer ${authToken}`
|
|
598
|
+
},
|
|
599
|
+
body: JSON.stringify(params)
|
|
600
|
+
});
|
|
601
|
+
const text = await res.text();
|
|
602
|
+
let parsed = {};
|
|
603
|
+
try {
|
|
604
|
+
parsed = text ? JSON.parse(text) : {};
|
|
605
|
+
} catch {
|
|
606
|
+
}
|
|
607
|
+
const detail = parsed.message || parsed.error || text || `HTTP ${res.status}`;
|
|
608
|
+
return { ok: res.ok, success: parsed.success === true, data: parsed.data, detail };
|
|
609
|
+
}
|
|
610
|
+
function toolKey(slug) {
|
|
611
|
+
const key = slug.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
612
|
+
return key.length <= 64 ? key : key.slice(0, 64);
|
|
613
|
+
}
|
|
614
|
+
async function composioTools(env, options) {
|
|
615
|
+
const { authToken } = options;
|
|
616
|
+
if (!authToken) {
|
|
617
|
+
throw new Error(
|
|
618
|
+
"composioTools: options.authToken is required. Pass the end user's JWT so the tools run as that user (Composio resolves their connected accounts by it) and the calls are billed to them."
|
|
619
|
+
);
|
|
620
|
+
}
|
|
621
|
+
const list = await requestComposio(
|
|
622
|
+
env,
|
|
623
|
+
"list-tools",
|
|
624
|
+
{
|
|
625
|
+
toolkit: options.toolkit,
|
|
626
|
+
toolSlugs: options.tools?.length ? options.tools.join(",") : void 0,
|
|
627
|
+
search: options.search,
|
|
628
|
+
limit: options.limit ?? 20
|
|
629
|
+
},
|
|
630
|
+
authToken
|
|
631
|
+
);
|
|
632
|
+
if (!list.ok || !list.success) {
|
|
633
|
+
throw new Error(`composioTools: failed to list Composio tools: ${list.detail}`);
|
|
634
|
+
}
|
|
635
|
+
const items = Array.isArray(list.data?.items) ? list.data.items : [];
|
|
636
|
+
const tools = {};
|
|
637
|
+
for (const item of items) {
|
|
638
|
+
if (!item?.slug) continue;
|
|
639
|
+
const slug = item.slug;
|
|
640
|
+
const schema = item.input_parameters ?? EMPTY_SCHEMA;
|
|
641
|
+
tools[toolKey(slug)] = tool({
|
|
642
|
+
description: item.description ?? item.name ?? slug,
|
|
643
|
+
inputSchema: jsonSchema(schema),
|
|
644
|
+
execute: async (args) => {
|
|
645
|
+
const r = await requestComposio(
|
|
646
|
+
env,
|
|
647
|
+
"execute-tool",
|
|
648
|
+
{ slug, arguments: args ?? {} },
|
|
649
|
+
authToken
|
|
650
|
+
);
|
|
651
|
+
if (!r.ok || !r.success) {
|
|
652
|
+
return { error: true, message: `Composio tool ${slug} failed: ${r.detail}` };
|
|
653
|
+
}
|
|
654
|
+
const data = r.data;
|
|
655
|
+
if (data && typeof data === "object" && data.requiresConnection) {
|
|
656
|
+
const toolkit = data.toolkit;
|
|
657
|
+
return {
|
|
658
|
+
requiresConnection: true,
|
|
659
|
+
toolkit,
|
|
660
|
+
message: `The user has not connected ${toolkit ?? "this app"}. Ask them to connect it before using this tool.`
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
return data;
|
|
664
|
+
}
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
return tools;
|
|
668
|
+
}
|
|
669
|
+
|
|
582
670
|
// src/server/utils/screenshot.ts
|
|
583
671
|
async function captureScreenshot(env, opts) {
|
|
584
672
|
const headers = new Headers({
|
|
@@ -666,6 +754,45 @@ function applySlidingWindow(messages, charCap, minKept) {
|
|
|
666
754
|
}
|
|
667
755
|
return out;
|
|
668
756
|
}
|
|
757
|
+
var TRIMMABLE_ARRAY_PATHS = [
|
|
758
|
+
["records"],
|
|
759
|
+
["data", "records"],
|
|
760
|
+
["items"],
|
|
761
|
+
["data", "items"],
|
|
762
|
+
["data"]
|
|
763
|
+
];
|
|
764
|
+
function getPath(root, path) {
|
|
765
|
+
let cur = root;
|
|
766
|
+
for (const key of path) {
|
|
767
|
+
if (!cur || typeof cur !== "object") return void 0;
|
|
768
|
+
cur = cur[key];
|
|
769
|
+
}
|
|
770
|
+
return cur;
|
|
771
|
+
}
|
|
772
|
+
function setPath(root, path, value, flags) {
|
|
773
|
+
const obj = root && typeof root === "object" ? root : {};
|
|
774
|
+
const [head, ...tail] = path;
|
|
775
|
+
if (tail.length === 0) {
|
|
776
|
+
return { ...obj, [head]: value, ...flags };
|
|
777
|
+
}
|
|
778
|
+
return { ...obj, [head]: setPath(obj[head], tail, value, flags) };
|
|
779
|
+
}
|
|
780
|
+
function locateTrimmableArray(result) {
|
|
781
|
+
for (const path of TRIMMABLE_ARRAY_PATHS) {
|
|
782
|
+
const arr = getPath(result, path);
|
|
783
|
+
if (Array.isArray(arr)) return { path, items: arr };
|
|
784
|
+
}
|
|
785
|
+
for (const [key, value] of Object.entries(result)) {
|
|
786
|
+
if (Array.isArray(value)) return { path: [key], items: value };
|
|
787
|
+
}
|
|
788
|
+
const data = result.data;
|
|
789
|
+
if (data && typeof data === "object") {
|
|
790
|
+
for (const [key, value] of Object.entries(data)) {
|
|
791
|
+
if (Array.isArray(value)) return { path: ["data", key], items: value };
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
return void 0;
|
|
795
|
+
}
|
|
669
796
|
function capToolResultSize(result, byteCap) {
|
|
670
797
|
let serialized;
|
|
671
798
|
try {
|
|
@@ -675,6 +802,31 @@ function capToolResultSize(result, byteCap) {
|
|
|
675
802
|
}
|
|
676
803
|
if (typeof serialized !== "string") return result;
|
|
677
804
|
if (serialized.length <= byteCap) return result;
|
|
805
|
+
if (result && typeof result === "object") {
|
|
806
|
+
const located = locateTrimmableArray(result);
|
|
807
|
+
if (located) {
|
|
808
|
+
const { path, items } = located;
|
|
809
|
+
const total = items.length;
|
|
810
|
+
const build = (k) => setPath(result, path, items.slice(0, k), { truncated: true, returned: k, total });
|
|
811
|
+
const fits = (k) => {
|
|
812
|
+
try {
|
|
813
|
+
return JSON.stringify(build(k)).length <= byteCap;
|
|
814
|
+
} catch {
|
|
815
|
+
return false;
|
|
816
|
+
}
|
|
817
|
+
};
|
|
818
|
+
if (fits(0)) {
|
|
819
|
+
let lo = 0;
|
|
820
|
+
let hi = total;
|
|
821
|
+
while (lo < hi) {
|
|
822
|
+
const mid = Math.ceil((lo + hi) / 2);
|
|
823
|
+
if (fits(mid)) lo = mid;
|
|
824
|
+
else hi = mid - 1;
|
|
825
|
+
}
|
|
826
|
+
if (lo > 0) return build(lo);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
}
|
|
678
830
|
return {
|
|
679
831
|
success: false,
|
|
680
832
|
truncated: true,
|
|
@@ -883,7 +1035,7 @@ function makeDefaultSummarizer(env, options = {}) {
|
|
|
883
1035
|
}
|
|
884
1036
|
|
|
885
1037
|
// src/server/utils/chat-history.ts
|
|
886
|
-
async function executeTool(stub, userId,
|
|
1038
|
+
async function executeTool(stub, userId, tool2, params) {
|
|
887
1039
|
const res = await stub.fetch(new Request("https://internal/api/tools/execute", {
|
|
888
1040
|
method: "POST",
|
|
889
1041
|
headers: {
|
|
@@ -891,11 +1043,11 @@ async function executeTool(stub, userId, tool, params) {
|
|
|
891
1043
|
"X-User-Id": userId,
|
|
892
1044
|
"X-App-Action": "true"
|
|
893
1045
|
},
|
|
894
|
-
body: JSON.stringify({ tool, params })
|
|
1046
|
+
body: JSON.stringify({ tool: tool2, params })
|
|
895
1047
|
}));
|
|
896
1048
|
const body = await res.json();
|
|
897
1049
|
if (!body.success) {
|
|
898
|
-
throw new Error(`chat-history ${
|
|
1050
|
+
throw new Error(`chat-history ${tool2} failed: ${body.error ?? "unknown error"}`);
|
|
899
1051
|
}
|
|
900
1052
|
return body.data;
|
|
901
1053
|
}
|
|
@@ -2790,11 +2942,11 @@ async function handleToolsRequest(ctx, request, path) {
|
|
|
2790
2942
|
}
|
|
2791
2943
|
if (path.startsWith("tools/describe/")) {
|
|
2792
2944
|
const toolName = path.replace("tools/describe/", "");
|
|
2793
|
-
const
|
|
2794
|
-
if (!
|
|
2945
|
+
const tool2 = BUILT_IN_TOOLS.find((t) => t.name === toolName);
|
|
2946
|
+
if (!tool2) {
|
|
2795
2947
|
return Response.json({ error: `Tool not found: ${toolName}` }, { status: 404, headers: CORS_HEADERS2 });
|
|
2796
2948
|
}
|
|
2797
|
-
return Response.json({ tool }, { headers: CORS_HEADERS2 });
|
|
2949
|
+
return Response.json({ tool: tool2 }, { headers: CORS_HEADERS2 });
|
|
2798
2950
|
}
|
|
2799
2951
|
if (path.startsWith("tools/execute") && request.method === "POST") {
|
|
2800
2952
|
return handleToolExecute(ctx, request);
|
|
@@ -2811,8 +2963,8 @@ async function handleToolExecute(ctx, request) {
|
|
|
2811
2963
|
{ status: 400, headers: CORS_HEADERS2 }
|
|
2812
2964
|
);
|
|
2813
2965
|
}
|
|
2814
|
-
const { tool, params = {} } = body;
|
|
2815
|
-
if (!
|
|
2966
|
+
const { tool: tool2, params = {} } = body;
|
|
2967
|
+
if (!tool2) {
|
|
2816
2968
|
return Response.json(
|
|
2817
2969
|
{ success: false, error: 'Missing "tool" in request body' },
|
|
2818
2970
|
{ status: 400, headers: CORS_HEADERS2 }
|
|
@@ -2829,8 +2981,8 @@ async function handleToolExecute(ctx, request) {
|
|
|
2829
2981
|
userRole = user.role;
|
|
2830
2982
|
}
|
|
2831
2983
|
}
|
|
2832
|
-
if (
|
|
2833
|
-
const result2 = await executeYjsTool(ctx,
|
|
2984
|
+
if (tool2.startsWith("yjs.")) {
|
|
2985
|
+
const result2 = await executeYjsTool(ctx, tool2, params, userId, userRole);
|
|
2834
2986
|
const status2 = result2.success ? 200 : result2.error?.includes("not found") ? 404 : 400;
|
|
2835
2987
|
return Response.json(result2, { status: status2, headers: CORS_HEADERS2 });
|
|
2836
2988
|
}
|
|
@@ -2841,7 +2993,7 @@ async function handleToolExecute(ctx, request) {
|
|
|
2841
2993
|
getPermissionContext: ctx.getPermissionContext,
|
|
2842
2994
|
send: ctx.send
|
|
2843
2995
|
};
|
|
2844
|
-
const result = await executeTool2(recordCtx,
|
|
2996
|
+
const result = await executeTool2(recordCtx, tool2, params, userId, userRole, isAppAction);
|
|
2845
2997
|
const status = result.success ? 200 : result.error?.includes("not found") ? 404 : 400;
|
|
2846
2998
|
return Response.json(result, { status, headers: CORS_HEADERS2 });
|
|
2847
2999
|
}
|
|
@@ -6668,6 +6820,7 @@ async function timingSafeEqualHex(a, b) {
|
|
|
6668
6820
|
// src/server/auth/betterAuth.ts
|
|
6669
6821
|
import { betterAuth } from "better-auth";
|
|
6670
6822
|
import { organization, twoFactor } from "better-auth/plugins";
|
|
6823
|
+
import { SignJWT, importPKCS8 } from "jose";
|
|
6671
6824
|
function createDeepSpaceAuth(config) {
|
|
6672
6825
|
const socialProviders = {};
|
|
6673
6826
|
if (config.google) {
|
|
@@ -6676,6 +6829,20 @@ function createDeepSpaceAuth(config) {
|
|
|
6676
6829
|
if (config.github) {
|
|
6677
6830
|
socialProviders.github = config.github;
|
|
6678
6831
|
}
|
|
6832
|
+
if (config.microsoft) {
|
|
6833
|
+
socialProviders.microsoft = config.microsoft;
|
|
6834
|
+
}
|
|
6835
|
+
if (config.apple) {
|
|
6836
|
+
const apple = config.apple;
|
|
6837
|
+
socialProviders.apple = async () => {
|
|
6838
|
+
try {
|
|
6839
|
+
return { clientId: apple.clientId, clientSecret: await generateAppleClientSecret(apple) };
|
|
6840
|
+
} catch (err) {
|
|
6841
|
+
console.error("[deepspace] failed to mint Apple client secret; Apple sign-in disabled", err);
|
|
6842
|
+
return { clientId: apple.clientId, clientSecret: "" };
|
|
6843
|
+
}
|
|
6844
|
+
};
|
|
6845
|
+
}
|
|
6679
6846
|
return betterAuth({
|
|
6680
6847
|
database: config.database,
|
|
6681
6848
|
baseURL: config.baseURL,
|
|
@@ -6688,11 +6855,42 @@ function createDeepSpaceAuth(config) {
|
|
|
6688
6855
|
"https://deep.space",
|
|
6689
6856
|
"https://*.deep.space",
|
|
6690
6857
|
"https://*.app.space",
|
|
6691
|
-
"http://localhost:*"
|
|
6858
|
+
"http://localhost:*",
|
|
6859
|
+
// Apple posts its OAuth callback from this origin (form_post).
|
|
6860
|
+
"https://appleid.apple.com"
|
|
6692
6861
|
],
|
|
6862
|
+
// Apple returns its callback as a cross-site form_post, which a
|
|
6863
|
+
// SameSite=Lax cookie won't ride along with — so the OAuth handshake
|
|
6864
|
+
// cookie must be SameSite=None. Scoped to just that cookie; the session
|
|
6865
|
+
// cookie stays Lax. Gated on Apple being configured: deployments without
|
|
6866
|
+
// Apple keep Lax entirely. Note that when Apple IS configured, this also
|
|
6867
|
+
// relaxes the handshake cookie for Google/GitHub/Microsoft on the same
|
|
6868
|
+
// instance — which is safe, since the state is encrypted and verified
|
|
6869
|
+
// independently of SameSite (plus a separate per-flow CSRF cookie).
|
|
6870
|
+
...config.apple ? {
|
|
6871
|
+
advanced: {
|
|
6872
|
+
cookies: {
|
|
6873
|
+
state: { attributes: { sameSite: "none", secure: true } },
|
|
6874
|
+
oauth_state: { attributes: { sameSite: "none", secure: true } }
|
|
6875
|
+
}
|
|
6876
|
+
}
|
|
6877
|
+
} : {},
|
|
6693
6878
|
plugins: [organization(), twoFactor()]
|
|
6694
6879
|
});
|
|
6695
6880
|
}
|
|
6881
|
+
var cachedAppleSecret = null;
|
|
6882
|
+
async function generateAppleClientSecret(apple) {
|
|
6883
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
6884
|
+
if (cachedAppleSecret && cachedAppleSecret.keyId === apple.keyId && cachedAppleSecret.expiresAt - now > 3600) {
|
|
6885
|
+
return cachedAppleSecret.token;
|
|
6886
|
+
}
|
|
6887
|
+
const pem = apple.privateKey.replace(/\\n/g, "\n");
|
|
6888
|
+
const key = await importPKCS8(pem, "ES256");
|
|
6889
|
+
const expiresAt = now + 180 * 24 * 60 * 60;
|
|
6890
|
+
const token = await new SignJWT({}).setProtectedHeader({ alg: "ES256", kid: apple.keyId }).setIssuer(apple.teamId).setSubject(apple.clientId).setAudience("https://appleid.apple.com").setIssuedAt(now).setExpirationTime(expiresAt).sign(key);
|
|
6891
|
+
cachedAppleSecret = { keyId: apple.keyId, token, expiresAt };
|
|
6892
|
+
return token;
|
|
6893
|
+
}
|
|
6696
6894
|
|
|
6697
6895
|
// src/shared/subscription.ts
|
|
6698
6896
|
var ENTITLED_STATUSES = /* @__PURE__ */ new Set([
|
|
@@ -6858,6 +7056,7 @@ export {
|
|
|
6858
7056
|
CronRoom,
|
|
6859
7057
|
DEFAULT_CONTEXT_CONFIG,
|
|
6860
7058
|
DEFAULT_DO_MANIFEST,
|
|
7059
|
+
DEFAULT_QUERY_LIMIT,
|
|
6861
7060
|
DIRECTORY_SCHEMAS,
|
|
6862
7061
|
GLOBAL_DO_TYPES,
|
|
6863
7062
|
GLOBAL_DO_TYPE_NAMES,
|
|
@@ -6883,6 +7082,7 @@ export {
|
|
|
6883
7082
|
analyzePermissions,
|
|
6884
7083
|
apiWorkerFetch,
|
|
6885
7084
|
appendMessage,
|
|
7085
|
+
applyAiToolDefaults,
|
|
6886
7086
|
applySlidingWindow,
|
|
6887
7087
|
authWorkerFetch,
|
|
6888
7088
|
bindingManifestFromOutputConfig,
|
|
@@ -6902,6 +7102,7 @@ export {
|
|
|
6902
7102
|
coerceValue,
|
|
6903
7103
|
collectionTableName,
|
|
6904
7104
|
columnId,
|
|
7105
|
+
composioTools,
|
|
6905
7106
|
computeDoMigration,
|
|
6906
7107
|
computeHmacHex,
|
|
6907
7108
|
createChat,
|