@usecontextlayer/sdk 0.14.3 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -25
- package/dist/index-Dle7CHzb.d.ts +10 -0
- package/dist/index-Dle7CHzb.d.ts.map +1 -0
- package/dist/index.d.ts +3 -10
- package/dist/index.js +3 -7
- package/dist/local.d.ts +51 -7
- package/dist/local.d.ts.map +1 -1
- package/dist/local.js +83 -12
- package/dist/local.js.map +1 -1
- package/dist/react.js +2 -2
- package/dist/react.js.map +1 -1
- package/dist/sdk-BMmzPuDi.js +18 -0
- package/dist/sdk-BMmzPuDi.js.map +1 -0
- package/dist/tools-BDLYKxEr.js +15 -0
- package/dist/tools-BDLYKxEr.js.map +1 -0
- package/dist/tools-BLXbCgQU-D3L2WEEd.d.ts +46 -0
- package/dist/tools-BLXbCgQU-D3L2WEEd.d.ts.map +1 -0
- package/dist/vite.d.ts +1 -1
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +164 -16
- package/dist/vite.js.map +1 -1
- package/dist/worker.d.ts +23 -7
- package/dist/worker.d.ts.map +1 -1
- package/dist/worker.js +18 -4
- package/dist/worker.js.map +1 -1
- package/examples/{gmail.tsx → gmail/app/routes/home.tsx} +2 -1
- package/examples/gmail/public/slate.json +9 -0
- package/package.json +12 -4
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
# @usecontextlayer/sdk
|
|
2
2
|
|
|
3
|
-
ContextLayer integration for
|
|
3
|
+
ContextLayer integration for slates: the app's shared document Layout, a Worker serving app routes and MCP tools, and Tools and Databases capabilities. The [domain model](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#domain-model) defines slates, declarations, resources, Owners, and assignments.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Use Node.js 24 or newer, pnpm, and Git with configured author identity. Start with login, then create and run your slate:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```sh
|
|
8
|
+
npx @usecontextlayer/cli login
|
|
9
|
+
npx @usecontextlayer/cli init my-slate
|
|
10
|
+
cd my-slate
|
|
11
|
+
pnpm dev
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
The CLI installs this package and configures local development. Open the local URL printed by the development server. Initialization prints your dashboard link, hosted URL, and Git deployment steps; the hosted URL becomes usable after deployment succeeds. Use `npx @usecontextlayer/cli` for subsequent CLI commands. First-party `@usecontextlayer/*` packages are exempt from pnpm's release-age policy in generated checkouts.
|
|
8
15
|
|
|
9
|
-
|
|
16
|
+
## Local login and assignment
|
|
10
17
|
|
|
11
|
-
|
|
18
|
+
Declare resources in `public/slate.json` and `agents/<name>/slate.json`, following the [resource invariants](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#resource-configuration-and-execution--principles). Use `npx @usecontextlayer/cli connections --help` and `npx @usecontextlayer/cli connection --help` for listing, connecting personal accounts, and assignment syntax. Local assignments are saved in ignored `.contextlayer/connections.json`.
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
For local tool calls, assign your personal connected accounts even when the hosted declaration uses `owner` mode or the slate belongs to an organization. Keep `.contextlayer/` ignored in Git. Local database state lives in `.contextlayer/databases`; local secret values come from environment variables with their declared names.
|
|
14
21
|
|
|
15
|
-
|
|
22
|
+
When the app declares connections, Vite startup needs a matching CLI login and the generated Git origin to identify the slate. This also applies when running a local agent because that command starts Vite. Restart `pnpm dev` after changing declarations, assignments, secret values, or migrations, and when the startup access token expires. The [local resource architecture](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#resource-configuration-and-execution--principles) describes preparation and credential boundaries.
|
|
16
23
|
|
|
17
24
|
## App Layout
|
|
18
25
|
|
|
@@ -22,15 +29,11 @@ The generated `app/root.tsx` re-exports the SDK's document Layout:
|
|
|
22
29
|
export { Layout } from "@usecontextlayer/sdk/react"
|
|
23
30
|
```
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
The header and tray are served by platform in a cross-origin iframe on slate.usecontextlayer.com. Platform owns their styles, Fugaz One font, and data loading. Layout receives only a height message and resizes the frame to keep the expanding tray in document flow. The app's Tailwind/shadcn setup is independent; there is no SDK stylesheet export or chrome root loader.
|
|
28
|
-
|
|
29
|
-
The frame authenticates directly with the native web session. Its cookie always uses Secure, HttpOnly, and SameSite=None, in every environment. When browser third-party-cookie policy permits delivery, the existing web login authenticates the header automatically, without a separate sign-in or frame cookie. Web logout revokes subsequent frame authentication. The surrounding authored page receives neither credentials nor chrome data. Hosted private-app cookie delivery still requires deployed browser verification.
|
|
32
|
+
Keep this re-export when editing the app's root component, error boundary, stylesheet, and font links. Layout supplies React Router's document elements and mounts the [chrome](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#slate-chrome) outside Vite development. Use the chrome's header to configure hosted connections, then refresh the page. Use CLI assignments during local development.
|
|
30
33
|
|
|
31
34
|
## A loader that reads Gmail
|
|
32
35
|
|
|
33
|
-
|
|
36
|
+
Pass the connection slug from `public/slate.json` as the first argument to `tools.call`, followed by the tool name and its arguments:
|
|
34
37
|
|
|
35
38
|
```ts
|
|
36
39
|
import { toolsContext } from "@usecontextlayer/sdk"
|
|
@@ -46,17 +49,39 @@ export async function loader({ context }: LoaderFunctionArgs) {
|
|
|
46
49
|
}
|
|
47
50
|
```
|
|
48
51
|
|
|
49
|
-
Calls return `{ data, logId }`. Validate the tool-specific `data` in your loader. The
|
|
52
|
+
Calls return `{ data, logId }`. Validate the tool-specific `data` in your loader. The [Gmail route](examples/gmail/app/routes/home.tsx) validates the response with Zod and renders a message list. Its [declaration](examples/gmail/public/slate.json) declares `work-email` as viewer-mode Gmail. The example follows the same `app/routes/home.tsx` and `public/slate.json` layout as your checkout.
|
|
53
|
+
|
|
54
|
+
From a newly generated checkout's root, copy both files from the installed SDK:
|
|
55
|
+
|
|
56
|
+
```sh
|
|
57
|
+
cp node_modules/@usecontextlayer/sdk/examples/gmail/app/routes/home.tsx app/routes/home.tsx
|
|
58
|
+
cp node_modules/@usecontextlayer/sdk/examples/gmail/public/slate.json public/slate.json
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If you have no connected Gmail account yet, connect one:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
npx @usecontextlayer/cli connections add gmail
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Open the printed link to connect your Gmail account in your browser. Next, assign the connected account to this slate's `work-email` connection, then start development. If your Gmail account is already connected, begin with assignment:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
npx @usecontextlayer/cli connection local assign work-email
|
|
71
|
+
pnpm dev
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Open the local URL printed by the development server to see your inbox. If development is already running, restart it after copying the declaration and assigning the connected account so startup reads the new configuration.
|
|
50
75
|
|
|
51
|
-
|
|
76
|
+
If the declared connection has no assignment yet, the generated app's error boundary shows guidance for the unassigned connection. Locally, follow its assignment command and restart `pnpm dev`. In a hosted slate, open the connections menu in the chrome's header, assign a connected account, and refresh the page. Join the slate before executing a viewer-mode resource; see [membership and provisioning](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#slate-forking-membership-and-resource-ownership).
|
|
52
77
|
|
|
53
|
-
|
|
78
|
+
## Handling tool errors
|
|
54
79
|
|
|
55
|
-
|
|
80
|
+
For a custom error boundary, use React Router's `isRouteErrorResponse(error)` and the SDK's `connectionRequiredSchema.safeParse(error.data)` to recognize the HTTP 409 payload `{ reason: "connection-required", slug }`. The generated root already handles this response. See the [execution boundary](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#resource-configuration-and-execution--principles) for authorization and credential handling.
|
|
56
81
|
|
|
57
|
-
## Vite configuration
|
|
82
|
+
## Vite and Worker configuration
|
|
58
83
|
|
|
59
|
-
|
|
84
|
+
Compose `contextlayer` with the app's React Router and Tailwind plugins:
|
|
60
85
|
|
|
61
86
|
```ts
|
|
62
87
|
import { contextlayer } from "@usecontextlayer/sdk/vite"
|
|
@@ -70,14 +95,24 @@ export default defineConfig((env) => ({
|
|
|
70
95
|
}))
|
|
71
96
|
```
|
|
72
97
|
|
|
73
|
-
This integration supplies the Cloudflare plugin; do not add a second instance.
|
|
98
|
+
This integration supplies the Cloudflare plugin; do not add a second instance. Keep the generated `workers/local-resources/wrangler.jsonc` and `workers/local-resources/index.ts` for local development. Follow the [startup and restart prerequisites](#local-login-and-assignment) when changing resources.
|
|
74
99
|
|
|
75
|
-
|
|
100
|
+
Keep the generated `workers/app.ts` wiring to `createSlateWorker` from `@usecontextlayer/sdk/worker`. It supplies the virtual React Router server build, Vite mode and development flag, and authored MCP modules. `createSlateWorker` returns the exported `SlateWorker` type. The [runtime architecture](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#resource-configuration-and-execution--principles) owns capability wiring and trust boundaries.
|
|
76
101
|
|
|
77
|
-
##
|
|
102
|
+
## A loader that queries cached data
|
|
78
103
|
|
|
79
|
-
|
|
104
|
+
Declare a database slug in `public/slate.json` and the same slug in `agents/<name>/slate.json` when both should share data, following the [resource invariants](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#resource-configuration-and-execution--principles). Store its authored SQL migrations under `databases/<slug>/migrations`. The template supplies Drizzle configuration and query schema; `pnpm db:migration --config databases/<slug>/drizzle.config.ts --name <change>` scaffolds a blank migration for you to write explicitly. Commit the SQL and native `meta/_journal.json` together. Update the TypeScript schema for query types alongside the migration; it does not create tables.
|
|
80
105
|
|
|
81
|
-
|
|
106
|
+
```ts
|
|
107
|
+
import { database, databasesContext } from "@usecontextlayer/sdk"
|
|
108
|
+
import { eq } from "drizzle-orm"
|
|
109
|
+
import type { LoaderFunctionArgs } from "react-router"
|
|
110
|
+
import * as schema from "@/databases/updates/schema"
|
|
111
|
+
|
|
112
|
+
export async function loader({ context }: LoaderFunctionArgs) {
|
|
113
|
+
const db = database(context.get(databasesContext), "updates", schema)
|
|
114
|
+
return db.select().from(schema.updates).where(eq(schema.updates.kind, "email"))
|
|
115
|
+
}
|
|
116
|
+
```
|
|
82
117
|
|
|
83
|
-
|
|
118
|
+
For direct SQL, use `context.get(databasesContext).query("updates", sql, params)`. Agents use `database_query` for persistent data. Restart local development after adding migrations, and push committed migrations to `main` for hosted provisioning. See [database ownership and provisioning](https://github.com/usecontextlayer/contextlayer/blob/main/ARCHITECTURE.md#slate-databases-and-authored-migrations) for the lifecycle and isolation rules.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { a as Databases, t as Tools } from "./tools-BLXbCgQU-D3L2WEEd.js";
|
|
2
|
+
//#region database.d.ts
|
|
3
|
+
declare function database<TSchema extends Record<string, unknown>>(databases: Databases, slug: string, schema: TSchema): import("drizzle-orm/sqlite-proxy").SqliteRemoteDatabase<TSchema>;
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region index.d.ts
|
|
6
|
+
declare const toolsContext: import("react-router").RouterContext<Tools>;
|
|
7
|
+
declare const databasesContext: import("react-router").RouterContext<Databases>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { toolsContext as n, database as r, databasesContext as t };
|
|
10
|
+
//# sourceMappingURL=index-Dle7CHzb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-Dle7CHzb.d.ts","names":[],"sources":["../database.ts","../index.ts"],"mappings":";;iBAGgB,SAAS,gBAAgB,yBACxC,WAAW,WACX,cACA,QAAQ,6CAAO,qBAAA;;;cCAH,qCAAY,cAAA;cAEZ,yCAAgB,cAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
data: unknown;
|
|
5
|
-
logId: string;
|
|
6
|
-
}>;
|
|
7
|
-
}
|
|
8
|
-
export declare const toolsContext: import("react-router").RouterContext<Tools>;
|
|
9
|
-
//#endregion
|
|
10
|
-
//# sourceMappingURL=index.d.ts.map
|
|
1
|
+
import { a as Databases, r as connectionRequiredSchema, t as Tools } from "./tools-BLXbCgQU-D3L2WEEd.js";
|
|
2
|
+
import { n as toolsContext, r as database, t as databasesContext } from "./index-Dle7CHzb.js";
|
|
3
|
+
export { type Databases, type Tools, connectionRequiredSchema, database, databasesContext, toolsContext };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
//#endregion
|
|
5
|
-
export { toolsContext };
|
|
6
|
-
|
|
7
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { t as connectionRequiredSchema } from "./tools-BDLYKxEr.js";
|
|
2
|
+
import { n as toolsContext, r as database, t as databasesContext } from "./sdk-BMmzPuDi.js";
|
|
3
|
+
export { connectionRequiredSchema, database, databasesContext, toolsContext };
|
package/dist/local.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { i as DatabaseMigrations, o as SqlValue } from "./tools-BLXbCgQU-D3L2WEEd.js";
|
|
1
2
|
import { z } from "zod";
|
|
2
|
-
import { WorkerEntrypoint } from "cloudflare:workers";
|
|
3
|
-
//#region ../shared/dist/
|
|
3
|
+
import { DurableObject, WorkerEntrypoint } from "cloudflare:workers";
|
|
4
|
+
//#region ../shared/dist/slate-resources-zjMlTUWg.d.mts
|
|
4
5
|
declare const localResourceConfigurationSchema: z.ZodObject<{
|
|
5
6
|
connections: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
6
7
|
mode: z.ZodEnum<{
|
|
@@ -16,7 +17,7 @@ declare const localResourceConfigurationSchema: z.ZodObject<{
|
|
|
16
17
|
}, z.core.$strict>], "type">>;
|
|
17
18
|
connection_id: z.ZodNullable<z.ZodString>;
|
|
18
19
|
}, z.core.$strict>>;
|
|
19
|
-
|
|
20
|
+
databases: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
20
21
|
mode: z.ZodEnum<{
|
|
21
22
|
owner: "owner";
|
|
22
23
|
viewer: "viewer";
|
|
@@ -27,7 +28,18 @@ declare const localResourceConfigurationSchema: z.ZodObject<{
|
|
|
27
28
|
name: z.ZodString;
|
|
28
29
|
type: z.ZodLiteral<"agent">;
|
|
29
30
|
}, z.core.$strict>], "type">>;
|
|
30
|
-
|
|
31
|
+
instance_name: z.ZodString;
|
|
32
|
+
migrations: z.ZodObject<{
|
|
33
|
+
journal: z.ZodObject<{
|
|
34
|
+
entries: z.ZodArray<z.ZodObject<{
|
|
35
|
+
breakpoints: z.ZodBoolean;
|
|
36
|
+
idx: z.ZodNumber;
|
|
37
|
+
tag: z.ZodString;
|
|
38
|
+
when: z.ZodNumber;
|
|
39
|
+
}, z.core.$strip>>;
|
|
40
|
+
}, z.core.$strip>;
|
|
41
|
+
migrations: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
42
|
+
}, z.core.$strip>;
|
|
31
43
|
}, z.core.$strict>>;
|
|
32
44
|
secrets: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
33
45
|
mode: z.ZodEnum<{
|
|
@@ -45,10 +57,42 @@ declare const localResourceConfigurationSchema: z.ZodObject<{
|
|
|
45
57
|
}, z.core.$strict>;
|
|
46
58
|
type LocalResourceConfiguration = z.infer<typeof localResourceConfigurationSchema>;
|
|
47
59
|
//#endregion
|
|
60
|
+
//#region ../shared/dist/database-worker.d.mts
|
|
61
|
+
//#region lib/database-worker.d.ts
|
|
62
|
+
export declare class SlateDatabase extends DurableObject {
|
|
63
|
+
migrate(migrations: DatabaseMigrations): Promise<void>;
|
|
64
|
+
query(sql: string, params?: SqlValue[]): Promise<{
|
|
65
|
+
columns: string[];
|
|
66
|
+
rows: (string | number | null)[][];
|
|
67
|
+
rowsRead: number;
|
|
68
|
+
rowsWritten: number;
|
|
69
|
+
}>;
|
|
70
|
+
}
|
|
71
|
+
declare class LocalDatabases extends WorkerEntrypoint<{
|
|
72
|
+
DATABASE_STORAGE: DurableObjectNamespace<SlateDatabase>;
|
|
73
|
+
}, {
|
|
74
|
+
databases: LocalResourceConfiguration["databases"];
|
|
75
|
+
}> {
|
|
76
|
+
fetch(request: Request): Promise<Response>;
|
|
77
|
+
query(slug: string, sql: string, params?: SqlValue[]): Promise<{
|
|
78
|
+
columns: string[];
|
|
79
|
+
rows: (string | number | null)[][];
|
|
80
|
+
rowsRead: number;
|
|
81
|
+
rowsWritten: number;
|
|
82
|
+
} & Disposable>;
|
|
83
|
+
}
|
|
84
|
+
declare class LocalDatabaseProvisioning extends WorkerEntrypoint<{
|
|
85
|
+
DATABASE_STORAGE: DurableObjectNamespace<SlateDatabase>;
|
|
86
|
+
}, {
|
|
87
|
+
databases: LocalResourceConfiguration["databases"];
|
|
88
|
+
}> {
|
|
89
|
+
fetch(): Promise<Response>;
|
|
90
|
+
}
|
|
91
|
+
//#endregion
|
|
48
92
|
//#endregion
|
|
49
93
|
//#region ../shared/dist/tools-worker.d.mts
|
|
50
94
|
interface LocalToolsProps {
|
|
51
|
-
|
|
95
|
+
slateId: string;
|
|
52
96
|
connections: LocalResourceConfiguration["connections"];
|
|
53
97
|
credential: {
|
|
54
98
|
token: string;
|
|
@@ -58,12 +102,12 @@ interface LocalToolsProps {
|
|
|
58
102
|
declare class LocalTools extends WorkerEntrypoint<{
|
|
59
103
|
CTX_PLATFORM_URL: string;
|
|
60
104
|
}, LocalToolsProps> {
|
|
61
|
-
call(slug: string, toolSlug: string, args: Record<string, unknown>): Promise<{
|
|
105
|
+
call(slug: string, toolSlug: string, args: Record<string, unknown>): Promise<Response | {
|
|
62
106
|
data: Record<string, unknown>;
|
|
63
107
|
logId: string;
|
|
64
108
|
}>;
|
|
65
109
|
}
|
|
66
110
|
//#endregion
|
|
67
111
|
//#endregion
|
|
68
|
-
export { LocalTools as Tools };
|
|
112
|
+
export { LocalDatabaseProvisioning as DatabaseProvisioning, LocalDatabases as Databases, LocalTools as Tools };
|
|
69
113
|
//# sourceMappingURL=local.d.ts.map
|
package/dist/local.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local.d.ts","names":[],"sources":["../../shared/dist/
|
|
1
|
+
{"version":3,"file":"local.d.ts","names":[],"sources":["../../shared/dist/slate-resources-zjMlTUWg.d.mts","../../shared/dist/database-worker.d.mts","../../shared/dist/tools-worker.d.mts"],"mappings":";;;;cAiIc,kCAAkC,EAAE;EAChD,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE;IACtC,MAAM,EAAE;MACN;MACA;;IAEF,SAAS,EAAE;IACX,WAAW,EAAE,SAAS,EAAE,uBAAuB,EAAE;MAC/C,MAAM,EAAE;OACP,EAAE,KAAK,UAAU,EAAE;MACpB,MAAM,EAAE;MACR,MAAM,EAAE;OACP,EAAE,KAAK;IACV,eAAe,EAAE,YAAY,EAAE;KAC9B,EAAE,KAAK;EACV,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE;IACpC,MAAM,EAAE;MACN;MACA;;IAEF,WAAW,EAAE,SAAS,EAAE,uBAAuB,EAAE;MAC/C,MAAM,EAAE;OACP,EAAE,KAAK,UAAU,EAAE;MACpB,MAAM,EAAE;MACR,MAAM,EAAE;OACP,EAAE,KAAK;IACV,eAAe,EAAE;IACjB,YAAY,EAAE;MACZ,SAAS,EAAE;QACT,SAAS,EAAE,SAAS,EAAE;UACpB,aAAa,EAAE;UACf,KAAK,EAAE;UACP,KAAK,EAAE;UACP,MAAM,EAAE;WACP,EAAE,KAAK;SACT,EAAE,KAAK;MACV,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE;OACtC,EAAE,KAAK;KACT,EAAE,KAAK;EACV,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE;IAClC,MAAM,EAAE;MACN;MACA;;IAEF,WAAW,EAAE,SAAS,EAAE,uBAAuB,EAAE;MAC/C,MAAM,EAAE;OACP,EAAE,KAAK,UAAU,EAAE;MACpB,MAAM,EAAE;MACR,MAAM,EAAE;OACP,EAAE,KAAK;IACV,OAAO,EAAE,YAAY,EAAE;KACtB,EAAE,KAAK;GACT,EAAE,KAAK;KACL,6BAA6B,EAAE,aAAa;;;;qBClL5B,sBAAsB;EACzC,QAAQ,YAAY,qBAAqB;EACzC,MAAM,aAAa,SAAS,aAAa;IACvC;IACA;IACA;IACA;;;cAGiB,uBAAuB;EAC1C,kBAAkB,uBAAuB;;EAEzC,WAAW;;EAEX,MAAM,SAAS,UAAU,QAAQ;EACjC,MAAM,cAAc,aAAa,SAAS,aAAa;IACrD;IACA;IACA;IACA;MACE;;cAEe,kCAAkC;EACrD,kBAAkB,uBAAuB;;EAEzC,WAAW;;EAEX,SAAS,QAAQ;;;;;UCIF;EACf;EACA,aAAa;EACb;IACE;IACA;;;cAWiB,mBAAmB;EACtC;GACC;EACD,KAAK,cAAc,kBAAkB,MAAM,0BAA0B,QAAQ;IAC3E,MAAM;IACN"}
|
package/dist/local.js
CHANGED
|
@@ -1,23 +1,81 @@
|
|
|
1
|
+
import { n as toolResultSchema, t as connectionRequiredSchema } from "./tools-BDLYKxEr.js";
|
|
1
2
|
import { z } from "zod";
|
|
2
|
-
import { WorkerEntrypoint } from "cloudflare:workers";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
import { DurableObject, WorkerEntrypoint } from "cloudflare:workers";
|
|
4
|
+
import { drizzle } from "drizzle-orm/durable-sqlite";
|
|
5
|
+
import { migrate } from "drizzle-orm/durable-sqlite/migrator";
|
|
6
|
+
//#region ../shared/dist/databases.mjs
|
|
7
|
+
const databaseJournalSchema = z.object({ entries: z.array(z.object({
|
|
8
|
+
breakpoints: z.boolean(),
|
|
9
|
+
idx: z.number().int().nonnegative(),
|
|
10
|
+
tag: z.string().min(1),
|
|
11
|
+
when: z.number()
|
|
12
|
+
})) });
|
|
13
|
+
const databaseMigrationsSchema = z.object({
|
|
14
|
+
journal: databaseJournalSchema,
|
|
15
|
+
migrations: z.record(z.string(), z.string())
|
|
16
|
+
});
|
|
17
|
+
const sqlValueSchema = z.union([
|
|
18
|
+
z.string(),
|
|
19
|
+
z.number(),
|
|
20
|
+
z.null()
|
|
21
|
+
]);
|
|
22
|
+
const databaseQuerySchema = z.strictObject({
|
|
23
|
+
params: z.array(sqlValueSchema).default([]),
|
|
24
|
+
slug: z.string().min(1),
|
|
25
|
+
sql: z.string().min(1)
|
|
26
|
+
});
|
|
27
|
+
const databaseResultSchema = z.object({
|
|
28
|
+
columns: z.array(z.string()),
|
|
29
|
+
rows: z.array(z.array(sqlValueSchema)),
|
|
30
|
+
rowsRead: z.number(),
|
|
31
|
+
rowsWritten: z.number()
|
|
8
32
|
});
|
|
9
33
|
//#endregion
|
|
34
|
+
//#region ../shared/dist/database-worker.mjs
|
|
35
|
+
var SlateDatabase = class extends DurableObject {
|
|
36
|
+
async migrate(migrations) {
|
|
37
|
+
await migrate(drizzle(this.ctx.storage), databaseMigrationsSchema.parse(migrations));
|
|
38
|
+
}
|
|
39
|
+
async query(sql, params = []) {
|
|
40
|
+
const cursor = this.ctx.storage.sql.exec(sql, ...params);
|
|
41
|
+
const rows = Array.from(cursor.raw());
|
|
42
|
+
return databaseResultSchema.parse({
|
|
43
|
+
columns: cursor.columnNames,
|
|
44
|
+
rows,
|
|
45
|
+
rowsRead: cursor.rowsRead,
|
|
46
|
+
rowsWritten: cursor.rowsWritten
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
var LocalDatabases = class extends WorkerEntrypoint {
|
|
51
|
+
async fetch(request) {
|
|
52
|
+
const { slug, sql, params } = databaseQuerySchema.parse(await request.json());
|
|
53
|
+
return Response.json(await this.query(slug, sql, params));
|
|
54
|
+
}
|
|
55
|
+
async query(slug, sql, params = []) {
|
|
56
|
+
const database = this.ctx.props.databases[slug];
|
|
57
|
+
if (!database) throw new Error(`No local database requirement for "${slug}"`);
|
|
58
|
+
return this.env.DATABASE_STORAGE.getByName(database.instance_name).query(sql, params);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var LocalDatabaseProvisioning = class extends WorkerEntrypoint {
|
|
62
|
+
async fetch() {
|
|
63
|
+
for (const database of Object.values(this.ctx.props.databases)) await this.env.DATABASE_STORAGE.getByName(database.instance_name).migrate(database.migrations);
|
|
64
|
+
return new Response(null, { status: 204 });
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
//#endregion
|
|
10
68
|
//#region ../shared/dist/tools-worker.mjs
|
|
11
69
|
var LocalTools = class extends WorkerEntrypoint {
|
|
12
70
|
async call(slug, toolSlug, args) {
|
|
13
|
-
const {
|
|
71
|
+
const { slateId, connections, credential } = this.ctx.props;
|
|
14
72
|
const connection = new Map(Object.entries(connections)).get(slug);
|
|
15
|
-
if (!connection) throw new Error(
|
|
16
|
-
if (connection.connection_id === null)
|
|
73
|
+
if (!connection) throw new Error("not-declared");
|
|
74
|
+
if (connection.connection_id === null) return connectionRequiredResponse(slug);
|
|
17
75
|
return executeToolRequest(new Request(new URL(`/api/connections/${encodeURIComponent(connection.connection_id)}/tools/call`, this.env.CTX_PLATFORM_URL), {
|
|
18
76
|
body: JSON.stringify({
|
|
19
|
-
app_id: appId,
|
|
20
77
|
arguments: args,
|
|
78
|
+
slate_id: slateId,
|
|
21
79
|
tool: toolSlug,
|
|
22
80
|
toolkit: connection.toolkit
|
|
23
81
|
}),
|
|
@@ -31,15 +89,28 @@ var LocalTools = class extends WorkerEntrypoint {
|
|
|
31
89
|
};
|
|
32
90
|
async function executeToolRequest(request) {
|
|
33
91
|
const response = await fetch(request);
|
|
92
|
+
if (response.status === 409) return connectionRequiredResponse(connectionRequiredSchema.parse(await response.json()).slug);
|
|
93
|
+
if (response.status === 402) throw new Error(await response.text());
|
|
34
94
|
if (!response.ok) throw new Error(`Tool call failed: HTTP ${response.status}`);
|
|
35
|
-
|
|
95
|
+
return readToolResult(toolResultSchema.parse(await response.json()));
|
|
96
|
+
}
|
|
97
|
+
function readToolResult(result) {
|
|
36
98
|
if (result.error !== null) throw new Error(`${result.error} (log: ${result.logId})`);
|
|
37
99
|
return {
|
|
38
100
|
data: result.data,
|
|
39
101
|
logId: result.logId
|
|
40
102
|
};
|
|
41
103
|
}
|
|
104
|
+
function connectionRequiredResponse(slug) {
|
|
105
|
+
return Response.json({
|
|
106
|
+
reason: "connection-required",
|
|
107
|
+
slug
|
|
108
|
+
}, {
|
|
109
|
+
status: 409,
|
|
110
|
+
statusText: "Connection required"
|
|
111
|
+
});
|
|
112
|
+
}
|
|
42
113
|
//#endregion
|
|
43
|
-
export { LocalTools as Tools };
|
|
114
|
+
export { LocalDatabaseProvisioning as DatabaseProvisioning, LocalDatabases as Databases, SlateDatabase, LocalTools as Tools };
|
|
44
115
|
|
|
45
116
|
//# sourceMappingURL=local.js.map
|
package/dist/local.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local.js","names":[],"sources":["../../shared/dist/
|
|
1
|
+
{"version":3,"file":"local.js","names":[],"sources":["../../shared/dist/databases.mjs","../../shared/dist/database-worker.mjs","../../shared/dist/tools-worker.mjs"],"sourcesContent":["import { z } from \"zod\";\n\n//#region lib/databases.ts\nconst databaseJournalSchema = z.object({ entries: z.array(z.object({\n\tbreakpoints: z.boolean(),\n\tidx: z.number().int().nonnegative(),\n\ttag: z.string().min(1),\n\twhen: z.number()\n})) });\nconst databaseMigrationsSchema = z.object({\n\tjournal: databaseJournalSchema,\n\tmigrations: z.record(z.string(), z.string())\n});\nasync function readDatabaseMigrations(slug, read) {\n\tconst directory = `databases/${slug}/migrations`;\n\tconst contents = await read(`${directory}/meta/_journal.json`);\n\tif (contents === null) return {\n\t\tjournal: { entries: [] },\n\t\tmigrations: {}\n\t};\n\tconst journal = databaseJournalSchema.parse(JSON.parse(contents));\n\tconst migrations = await Promise.all(journal.entries.map(async (entry) => {\n\t\tconst sql = await read(`${directory}/${entry.tag}.sql`);\n\t\tif (sql === null) throw new Error(`Missing database migration: ${slug}/${entry.tag}.sql`);\n\t\treturn [`m${entry.idx.toString().padStart(4, \"0\")}`, sql];\n\t}));\n\treturn {\n\t\tjournal,\n\t\tmigrations: Object.fromEntries(migrations)\n\t};\n}\nconst sqlValueSchema = z.union([\n\tz.string(),\n\tz.number(),\n\tz.null()\n]);\nconst databaseQuerySchema = z.strictObject({\n\tparams: z.array(sqlValueSchema).default([]),\n\tslug: z.string().min(1),\n\tsql: z.string().min(1)\n});\nconst databaseResultSchema = z.object({\n\tcolumns: z.array(z.string()),\n\trows: z.array(z.array(sqlValueSchema)),\n\trowsRead: z.number(),\n\trowsWritten: z.number()\n});\n\n//#endregion\nexport { databaseJournalSchema, databaseMigrationsSchema, databaseQuerySchema, databaseResultSchema, readDatabaseMigrations, sqlValueSchema };","import { databaseMigrationsSchema, databaseQuerySchema, databaseResultSchema } from \"./databases.mjs\";\nimport { DurableObject, WorkerEntrypoint } from \"cloudflare:workers\";\nimport { drizzle } from \"drizzle-orm/durable-sqlite\";\nimport { migrate } from \"drizzle-orm/durable-sqlite/migrator\";\n\n//#region lib/database-worker.ts\nvar SlateDatabase = class extends DurableObject {\n\tasync migrate(migrations) {\n\t\tawait migrate(drizzle(this.ctx.storage), databaseMigrationsSchema.parse(migrations));\n\t}\n\tasync query(sql, params = []) {\n\t\tconst cursor = this.ctx.storage.sql.exec(sql, ...params);\n\t\tconst rows = Array.from(cursor.raw());\n\t\treturn databaseResultSchema.parse({\n\t\t\tcolumns: cursor.columnNames,\n\t\t\trows,\n\t\t\trowsRead: cursor.rowsRead,\n\t\t\trowsWritten: cursor.rowsWritten\n\t\t});\n\t}\n};\nvar LocalDatabases = class extends WorkerEntrypoint {\n\tasync fetch(request) {\n\t\tconst { slug, sql, params } = databaseQuerySchema.parse(await request.json());\n\t\treturn Response.json(await this.query(slug, sql, params));\n\t}\n\tasync query(slug, sql, params = []) {\n\t\tconst database = this.ctx.props.databases[slug];\n\t\tif (!database) throw new Error(`No local database requirement for \"${slug}\"`);\n\t\treturn this.env.DATABASE_STORAGE.getByName(database.instance_name).query(sql, params);\n\t}\n};\nvar LocalDatabaseProvisioning = class extends WorkerEntrypoint {\n\tasync fetch() {\n\t\tfor (const database of Object.values(this.ctx.props.databases)) await this.env.DATABASE_STORAGE.getByName(database.instance_name).migrate(database.migrations);\n\t\treturn new Response(null, { status: 204 });\n\t}\n};\n\n//#endregion\nexport { LocalDatabaseProvisioning, LocalDatabases, SlateDatabase };","import { connectionRequiredSchema, toolResultSchema } from \"./tools.mjs\";\nimport { WorkerEntrypoint } from \"cloudflare:workers\";\n\n//#region lib/tools-worker.ts\nfunction readHostedExecutionResult(result) {\n\tif (!result.allowed) throw new Error(\"message\" in result ? result.message : result.reason);\n\treturn result.result;\n}\nvar Tools = class extends WorkerEntrypoint {\n\tasync call(slug, toolSlug, args) {\n\t\tconst { slateId, credential } = this.ctx.props;\n\t\tconst result = await this.env.EXECUTION.callTool(slateId, credential.token, {\n\t\t\targuments: args,\n\t\t\tslug,\n\t\t\ttool: toolSlug\n\t\t});\n\t\tif (!result.allowed && result.reason === \"connection-required\") return connectionRequiredResponse(result.slug);\n\t\treturn readToolResult(toolResultSchema.parse(readHostedExecutionResult(result)));\n\t}\n};\nvar LocalTools = class extends WorkerEntrypoint {\n\tasync call(slug, toolSlug, args) {\n\t\tconst { slateId, connections, credential } = this.ctx.props;\n\t\tconst connection = new Map(Object.entries(connections)).get(slug);\n\t\tif (!connection) throw new Error(\"not-declared\");\n\t\tif (connection.connection_id === null) return connectionRequiredResponse(slug);\n\t\treturn executeToolRequest(new Request(new URL(`/api/connections/${encodeURIComponent(connection.connection_id)}/tools/call`, this.env.CTX_PLATFORM_URL), {\n\t\t\tbody: JSON.stringify({\n\t\t\t\targuments: args,\n\t\t\t\tslate_id: slateId,\n\t\t\t\ttool: toolSlug,\n\t\t\t\ttoolkit: connection.toolkit\n\t\t\t}),\n\t\t\theaders: {\n\t\t\t\tauthorization: `Bearer ${credential.token}`,\n\t\t\t\t\"content-type\": \"application/json\"\n\t\t\t},\n\t\t\tmethod: \"POST\"\n\t\t}));\n\t}\n};\nasync function executeToolRequest(request) {\n\tconst response = await fetch(request);\n\tif (response.status === 409) return connectionRequiredResponse(connectionRequiredSchema.parse(await response.json()).slug);\n\tif (response.status === 402) throw new Error(await response.text());\n\tif (!response.ok) throw new Error(`Tool call failed: HTTP ${response.status}`);\n\treturn readToolResult(toolResultSchema.parse(await response.json()));\n}\nfunction readToolResult(result) {\n\tif (result.error !== null) throw new Error(`${result.error} (log: ${result.logId})`);\n\treturn {\n\t\tdata: result.data,\n\t\tlogId: result.logId\n\t};\n}\nfunction connectionRequiredResponse(slug) {\n\treturn Response.json({\n\t\treason: \"connection-required\",\n\t\tslug\n\t}, {\n\t\tstatus: 409,\n\t\tstatusText: \"Connection required\"\n\t});\n}\n\n//#endregion\nexport { LocalTools, Tools, readHostedExecutionResult };"],"mappings":"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"}
|
package/dist/react.js
CHANGED
|
@@ -10,7 +10,7 @@ const chromeHeightSchema = z.object({
|
|
|
10
10
|
});
|
|
11
11
|
//#endregion
|
|
12
12
|
//#region browser-env.ts
|
|
13
|
-
const browserEnv = z.object({ CTX_PLATFORM_URL: z.url().default("https://
|
|
13
|
+
const browserEnv = z.object({ CTX_PLATFORM_URL: z.url().default("https://platform.usecontextlayer.com") }).parse({ CTX_PLATFORM_URL: import.meta.env.CTX_PLATFORM_URL });
|
|
14
14
|
//#endregion
|
|
15
15
|
//#region react.tsx
|
|
16
16
|
function Chrome() {
|
|
@@ -19,7 +19,7 @@ function Chrome() {
|
|
|
19
19
|
const [height, setHeight] = useState(30);
|
|
20
20
|
useEffect(() => {
|
|
21
21
|
const target = window.location.hostname;
|
|
22
|
-
const url = new URL(`${chromePath}/
|
|
22
|
+
const url = new URL(`${chromePath}/slates/${encodeURIComponent(target)}`, browserEnv.CTX_PLATFORM_URL);
|
|
23
23
|
url.searchParams.set("parentOrigin", window.location.origin);
|
|
24
24
|
function resize(event) {
|
|
25
25
|
if (event.origin !== url.origin || event.source !== frame.current?.contentWindow) return;
|
package/dist/react.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react.js","names":[],"sources":["../../shared/dist/chrome.mjs","../browser-env.ts","../react.tsx"],"sourcesContent":["import { z } from \"zod\";\n\n//#region lib/chrome.ts\nconst chromePath = \"/dashboard/chrome\";\nconst chromeHeightSchema = z.object({\n\theight: z.number().finite().nonnegative(),\n\ttype: z.literal(\"ctx:chrome:height\")\n});\n\n//#endregion\nexport { chromeHeightSchema, chromePath };","import { z } from \"zod\"\n\nexport const browserEnv = z\n\t.object({\n\t\tCTX_PLATFORM_URL: z.url().default(\"https://
|
|
1
|
+
{"version":3,"file":"react.js","names":[],"sources":["../../shared/dist/chrome.mjs","../browser-env.ts","../react.tsx"],"sourcesContent":["import { z } from \"zod\";\n\n//#region lib/chrome.ts\nconst chromePath = \"/dashboard/chrome\";\nconst chromeHeightSchema = z.object({\n\theight: z.number().finite().nonnegative(),\n\ttype: z.literal(\"ctx:chrome:height\")\n});\n\n//#endregion\nexport { chromeHeightSchema, chromePath };","import { z } from \"zod\"\n\nexport const browserEnv = z\n\t.object({\n\t\tCTX_PLATFORM_URL: z.url().default(\"https://platform.usecontextlayer.com\"),\n\t})\n\t.parse({\n\t\tCTX_PLATFORM_URL: import.meta.env.CTX_PLATFORM_URL,\n\t})\n","import { chromeHeightSchema, chromePath } from \"@usecontextlayer/shared/chrome\"\nimport { type ReactNode, useEffect, useRef, useState } from \"react\"\nimport { Links, Meta, Scripts, ScrollRestoration } from \"react-router\"\nimport { browserEnv } from \"@/browser-env\"\n\nfunction Chrome() {\n\tconst frame = useRef<HTMLIFrameElement>(null)\n\tconst [src, setSrc] = useState<string>()\n\tconst [height, setHeight] = useState(30)\n\tuseEffect(() => {\n\t\tconst target = window.location.hostname\n\t\tconst url = new URL(\n\t\t\t`${chromePath}/slates/${encodeURIComponent(target)}`,\n\t\t\tbrowserEnv.CTX_PLATFORM_URL,\n\t\t)\n\t\turl.searchParams.set(\"parentOrigin\", window.location.origin)\n\t\tfunction resize(event: MessageEvent) {\n\t\t\tif (event.origin !== url.origin || event.source !== frame.current?.contentWindow)\n\t\t\t\treturn\n\t\t\tconst message = chromeHeightSchema.safeParse(event.data)\n\t\t\tif (message.success) setHeight(message.data.height)\n\t\t}\n\t\twindow.addEventListener(\"message\", resize)\n\t\tsetSrc(url.href)\n\t\treturn () => window.removeEventListener(\"message\", resize)\n\t}, [])\n\treturn (\n\t\t<iframe\n\t\t\tref={frame}\n\t\t\tsrc={src}\n\t\t\ttitle=\"ContextLayer\"\n\t\t\tstyle={{\n\t\t\t\tbackgroundColor: \"oklch(96.8% 0.007 247.896)\",\n\t\t\t\tborder: 0,\n\t\t\t\tborderBottom: \"1px solid oklch(92.9% 0.013 255.508)\",\n\t\t\t\tdisplay: \"block\",\n\t\t\t\theight,\n\t\t\t\twidth: \"100%\",\n\t\t\t}}\n\t\t/>\n\t)\n}\n\nexport function Layout({ children }: { children: ReactNode }) {\n\treturn (\n\t\t<html lang=\"en\">\n\t\t\t<head>\n\t\t\t\t<meta charSet=\"utf-8\" />\n\t\t\t\t<meta\n\t\t\t\t\tname=\"viewport\"\n\t\t\t\t\tcontent=\"width=device-width, initial-scale=1\"\n\t\t\t\t/>\n\t\t\t\t<Meta />\n\t\t\t\t<Links />\n\t\t\t</head>\n\t\t\t<body>\n\t\t\t\t{!import.meta.env.DEV && <Chrome />}\n\t\t\t\t{children}\n\t\t\t\t<ScrollRestoration />\n\t\t\t\t<Scripts />\n\t\t\t</body>\n\t\t</html>\n\t)\n}\n"],"mappings":";;;;;AAGA,MAAM,aAAa;AACnB,MAAM,qBAAqB,EAAE,OAAO;CACnC,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,YAAY;CACxC,MAAM,EAAE,QAAQ,mBAAmB;AACpC,CAAC;;;ACLD,MAAa,aAAa,EACxB,OAAO,EACP,kBAAkB,EAAE,IAAI,CAAC,CAAC,QAAQ,sCAAsC,EACzE,CAAC,CAAC,CACD,MAAM,EACN,kBAAkB,YAAY,IAAI,iBACnC,CAAC;;;ACHF,SAAS,SAAS;CACjB,MAAM,QAAQ,OAA0B,IAAI;CAC5C,MAAM,CAAC,KAAK,UAAU,SAAiB;CACvC,MAAM,CAAC,QAAQ,aAAa,SAAS,EAAE;CACvC,gBAAgB;EACf,MAAM,SAAS,OAAO,SAAS;EAC/B,MAAM,MAAM,IAAI,IACf,GAAG,WAAW,UAAU,mBAAmB,MAAM,KACjD,WAAW,gBACZ;EACA,IAAI,aAAa,IAAI,gBAAgB,OAAO,SAAS,MAAM;EAC3D,SAAS,OAAO,OAAqB;GACpC,IAAI,MAAM,WAAW,IAAI,UAAU,MAAM,WAAW,MAAM,SAAS,eAClE;GACD,MAAM,UAAU,mBAAmB,UAAU,MAAM,IAAI;GACvD,IAAI,QAAQ,SAAS,UAAU,QAAQ,KAAK,MAAM;EACnD;EACA,OAAO,iBAAiB,WAAW,MAAM;EACzC,OAAO,IAAI,IAAI;EACf,aAAa,OAAO,oBAAoB,WAAW,MAAM;CAC1D,GAAG,CAAC,CAAC;CACL,OACC,oBAAC,UAAD;EACC,KAAK;EACA;EACL,OAAM;EACN,OAAO;GACN,iBAAiB;GACjB,QAAQ;GACR,cAAc;GACd,SAAS;GACT;GACA,OAAO;EACR;CACA,CAAA;AAEH;AAEA,SAAgB,OAAO,EAAE,YAAqC;CAC7D,OACC,qBAAC,QAAD;EAAM,MAAK;EAAX,UAAA,CACC,qBAAC,QAAD,EAAA,UAAA;GACC,oBAAC,QAAD,EAAM,SAAQ,QAAS,CAAA;GACvB,oBAAC,QAAD;IACC,MAAK;IACL,SAAQ;GACR,CAAA;GACD,oBAAC,MAAD,CAAO,CAAA;GACP,oBAAC,OAAD,CAAQ,CAAA;EACH,EAAA,CAAA,GACN,qBAAC,QAAD,EAAA,UAAA;GACE,CAAC,YAAY,IAAI,OAAO,oBAAC,QAAD,CAAS,CAAA;GACjC;GACD,oBAAC,mBAAD,CAAoB,CAAA;GACpB,oBAAC,SAAD,CAAU,CAAA;EACL,EAAA,CAAA,CACD;;AAER"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import "./tools-BDLYKxEr.js";
|
|
2
|
+
import { createContext } from "react-router";
|
|
3
|
+
import { drizzle } from "drizzle-orm/sqlite-proxy";
|
|
4
|
+
//#region database.ts
|
|
5
|
+
function database(databases, slug, schema) {
|
|
6
|
+
return drizzle(async (sql, params, method) => {
|
|
7
|
+
const result = await databases.query(slug, sql, params);
|
|
8
|
+
return { rows: method === "get" ? result.rows[0] : result.rows };
|
|
9
|
+
}, { schema });
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region index.ts
|
|
13
|
+
const toolsContext = createContext();
|
|
14
|
+
const databasesContext = createContext();
|
|
15
|
+
//#endregion
|
|
16
|
+
export { toolsContext as n, database as r, databasesContext as t };
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=sdk-BMmzPuDi.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-BMmzPuDi.js","names":[],"sources":["../database.ts","../index.ts"],"sourcesContent":["import type { Databases } from \"@usecontextlayer/shared/databases\"\nimport { drizzle } from \"drizzle-orm/sqlite-proxy\"\n\nexport function database<TSchema extends Record<string, unknown>>(\n\tdatabases: Databases,\n\tslug: string,\n\tschema: TSchema,\n) {\n\treturn drizzle(\n\t\tasync (sql, params, method) => {\n\t\t\tconst result = await databases.query(slug, sql, params)\n\t\t\t// sqlite-proxy maps undefined to a missing row despite its array-only callback type.\n\t\t\treturn { rows: method === \"get\" ? (result.rows[0] as unknown[]) : result.rows }\n\t\t},\n\t\t{ schema },\n\t)\n}\n","import type { Databases } from \"@usecontextlayer/shared/databases\"\nimport type { Tools } from \"@usecontextlayer/shared/tools\"\nimport { createContext } from \"react-router\"\n\nexport { connectionRequiredSchema, type Tools } from \"@usecontextlayer/shared/tools\"\n\nexport const toolsContext = createContext<Tools>()\n\nexport const databasesContext = createContext<Databases>()\nexport type { Databases } from \"@usecontextlayer/shared/databases\"\nexport { database } from \"@/database\"\n"],"mappings":";;;;AAGA,SAAgB,SACf,WACA,MACA,QACC;CACD,OAAO,QACN,OAAO,KAAK,QAAQ,WAAW;EAC9B,MAAM,SAAS,MAAM,UAAU,MAAM,MAAM,KAAK,MAAM;EAEtD,OAAO,EAAE,MAAM,WAAW,QAAS,OAAO,KAAK,KAAmB,OAAO,KAAK;CAC/E,GACA,EAAE,OAAO,CACV;AACD;;;ACVA,MAAa,eAAe,cAAqB;AAEjD,MAAa,mBAAmB,cAAyB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region ../shared/dist/tools.mjs
|
|
3
|
+
const connectionRequiredSchema = z.object({
|
|
4
|
+
reason: z.literal("connection-required"),
|
|
5
|
+
slug: z.string().min(1)
|
|
6
|
+
});
|
|
7
|
+
const toolResultSchema = z.object({
|
|
8
|
+
data: z.record(z.string(), z.unknown()),
|
|
9
|
+
error: z.string().nullable(),
|
|
10
|
+
logId: z.string()
|
|
11
|
+
});
|
|
12
|
+
//#endregion
|
|
13
|
+
export { toolResultSchema as n, connectionRequiredSchema as t };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=tools-BDLYKxEr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools-BDLYKxEr.js","names":[],"sources":["../../shared/dist/tools.mjs"],"sourcesContent":["import { z } from \"zod\";\n\n//#region lib/tools.ts\nconst connectionRequiredSchema = z.object({\n\treason: z.literal(\"connection-required\"),\n\tslug: z.string().min(1)\n});\nconst toolResultSchema = z.object({\n\tdata: z.record(z.string(), z.unknown()),\n\terror: z.string().nullable(),\n\tlogId: z.string()\n});\n\n//#endregion\nexport { connectionRequiredSchema, toolResultSchema };"],"mappings":";;AAGA,MAAM,2BAA2B,EAAE,OAAO;CACzC,QAAQ,EAAE,QAAQ,qBAAqB;CACvC,MAAM,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC;AACvB,CAAC;AACD,MAAM,mBAAmB,EAAE,OAAO;CACjC,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC;CACtC,OAAO,EAAE,OAAO,CAAC,CAAC,SAAS;CAC3B,OAAO,EAAE,OAAO;AACjB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
//#region ../shared/dist/databases.d.mts
|
|
3
|
+
declare const databaseMigrationsSchema: z.ZodObject<{
|
|
4
|
+
journal: z.ZodObject<{
|
|
5
|
+
entries: z.ZodArray<z.ZodObject<{
|
|
6
|
+
breakpoints: z.ZodBoolean;
|
|
7
|
+
idx: z.ZodNumber;
|
|
8
|
+
tag: z.ZodString;
|
|
9
|
+
when: z.ZodNumber;
|
|
10
|
+
}, z.core.$strip>>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
migrations: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
13
|
+
}, z.core.$strip>;
|
|
14
|
+
type DatabaseMigrations = z.infer<typeof databaseMigrationsSchema>;
|
|
15
|
+
declare const sqlValueSchema: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodNull]>;
|
|
16
|
+
type SqlValue = z.infer<typeof sqlValueSchema>;
|
|
17
|
+
declare const databaseResultSchema: z.ZodObject<{
|
|
18
|
+
columns: z.ZodArray<z.ZodString>;
|
|
19
|
+
rows: z.ZodArray<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodNull]>>>;
|
|
20
|
+
rowsRead: z.ZodNumber;
|
|
21
|
+
rowsWritten: z.ZodNumber;
|
|
22
|
+
}, z.core.$strip>;
|
|
23
|
+
type DatabaseResult = z.infer<typeof databaseResultSchema>;
|
|
24
|
+
interface Databases {
|
|
25
|
+
query(slug: string, sql: string, params?: SqlValue[]): Promise<DatabaseResult>;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region ../shared/dist/tools-BLXbCgQU.d.mts
|
|
30
|
+
//#region lib/tools.d.ts
|
|
31
|
+
declare const connectionRequiredSchema: z.ZodObject<{
|
|
32
|
+
reason: z.ZodLiteral<"connection-required">;
|
|
33
|
+
slug: z.ZodString;
|
|
34
|
+
}, z.core.$strip>;
|
|
35
|
+
interface Tools {
|
|
36
|
+
call(slug: string, toolSlug: string, args: Record<string, unknown>): Promise<{
|
|
37
|
+
data: unknown;
|
|
38
|
+
logId: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
interface ToolsBinding {
|
|
42
|
+
call(...args: Parameters<Tools["call"]>): Promise<Awaited<ReturnType<Tools["call"]>> | Response>;
|
|
43
|
+
}
|
|
44
|
+
//#endregion
|
|
45
|
+
export { Databases as a, DatabaseMigrations as i, ToolsBinding as n, SqlValue as o, connectionRequiredSchema as r, Tools as t };
|
|
46
|
+
//# sourceMappingURL=tools-BLXbCgQU-D3L2WEEd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools-BLXbCgQU-D3L2WEEd.d.ts","names":[],"sources":["../../shared/dist/databases.d.mts","../../shared/dist/tools-BLXbCgQU.d.mts"],"mappings":";;cAUqB,0BAA0B,EAAE;EAC/C,SAAS,EAAE;IACT,SAAS,EAAE,SAAS,EAAE;MACpB,aAAa,EAAE;MACf,KAAK,EAAE;MACP,KAAK,EAAE;MACP,MAAM,EAAE;OACP,EAAE,KAAK;KACT,EAAE,KAAK;EACV,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE;GACtC,EAAE,KAAK;KACE,qBAAqB,EAAE,aAAa;cAE3B,gBAAgB,EAAE,mBAAmB,EAAE,WAAW,EAAE,WAAW,EAAE;KAM1E,WAAW,EAAE,aAAa;cACjB,sBAAsB,EAAE;EAC3C,SAAS,EAAE,SAAS,EAAE;EACtB,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,mBAAmB,EAAE,WAAW,EAAE,WAAW,EAAE;EAC7E,UAAU,EAAE;EACZ,aAAa,EAAE;GACd,EAAE,KAAK;KACE,iBAAiB,EAAE,aAAa;UAC3B;EACf,MAAM,cAAc,aAAa,SAAS,aAAa,QAAQ;;;;;;cCpCnD,0BAA0B,EAAE;EACxC,QAAQ,EAAE;EACV,MAAM,EAAE;GACP,EAAE,KAAK;UAMA;EACR,KAAK,cAAc,kBAAkB,MAAM,0BAA0B;IACnE;IACA;;;UAGM;EACR,QAAQ,MAAM,WAAW,iBAAiB,QAAQ,QAAQ,WAAW,kBAAkB"}
|
package/dist/vite.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ConfigEnv } from "vite";
|
|
2
2
|
//#region vite.d.ts
|
|
3
|
-
export declare function contextlayer({ command }: ConfigEnv): Promise<import("vite").Plugin<any>[][]>;
|
|
3
|
+
export declare function contextlayer({ command }: ConfigEnv): Promise<(import("vite").Plugin<any>[] | import("vite").Plugin<any> | undefined)[]>;
|
|
4
4
|
//#endregion
|
|
5
5
|
//# sourceMappingURL=vite.d.ts.map
|
package/dist/vite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.d.ts","names":[],"sources":["../vite.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"vite.d.ts","names":[],"sources":["../vite.ts"],"mappings":";;wBAQsB,eAAe,WAAW,YAAS,wBAAA,+BAAA"}
|
package/dist/vite.js
CHANGED
|
@@ -1,22 +1,170 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
1
2
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
|
2
|
-
import {
|
|
3
|
+
import { getLocalResourcesBindings, localDatabaseProvisioning } from "@usecontextlayer/cli/vite";
|
|
4
|
+
import { glob, readFile } from "node:fs/promises";
|
|
5
|
+
import { dirname, join, relative } from "node:path";
|
|
6
|
+
import { RESOURCE_MIME_TYPE } from "@modelcontextprotocol/ext-apps/server";
|
|
7
|
+
import { ResourceSchema, ToolSchema } from "@modelcontextprotocol/core";
|
|
8
|
+
import { build, createServer, createServerModuleRunner } from "vite";
|
|
9
|
+
import { viteSingleFile } from "vite-plugin-singlefile";
|
|
10
|
+
//#region ../shared/dist/declaration.mjs
|
|
11
|
+
const credentialModeSchema = z.enum(["viewer", "owner"]);
|
|
12
|
+
const connectionRequirementSchema = z.strictObject({
|
|
13
|
+
mode: credentialModeSchema,
|
|
14
|
+
toolkit: z.string().min(1)
|
|
15
|
+
});
|
|
16
|
+
const secretNameSchema = z.string().regex(/^[A-Z_][A-Z0-9_]*$/);
|
|
17
|
+
const secretRequirementSchema = z.strictObject({ mode: credentialModeSchema });
|
|
18
|
+
const databaseRequirementSchema = z.strictObject({ mode: credentialModeSchema });
|
|
19
|
+
const databaseSlugSchema = z.string().min(1).regex(/^(?!\.{1,2}$)[^/\\]+$/);
|
|
20
|
+
const declarationSchema = z.strictObject({
|
|
21
|
+
connections: z.record(z.string().min(1), connectionRequirementSchema),
|
|
22
|
+
databases: z.record(databaseSlugSchema, databaseRequirementSchema).default({}),
|
|
23
|
+
secrets: z.record(secretNameSchema, secretRequirementSchema).default({})
|
|
24
|
+
});
|
|
25
|
+
z.strictObject({
|
|
26
|
+
agents: z.record(z.string().min(1), declarationSchema),
|
|
27
|
+
app: declarationSchema
|
|
28
|
+
});
|
|
29
|
+
const resourceConsumerSchema = z.discriminatedUnion("type", [z.strictObject({ type: z.literal("app") }), z.strictObject({
|
|
30
|
+
name: z.string().min(1),
|
|
31
|
+
type: z.literal("agent")
|
|
32
|
+
})]);
|
|
33
|
+
declarationSchema.extend({
|
|
34
|
+
connections: z.record(z.string().min(1), connectionRequirementSchema.extend({ consumers: z.array(resourceConsumerSchema) })),
|
|
35
|
+
databases: z.record(databaseSlugSchema, databaseRequirementSchema.extend({ consumers: z.array(resourceConsumerSchema) })),
|
|
36
|
+
secrets: z.record(secretNameSchema, secretRequirementSchema.extend({ consumers: z.array(resourceConsumerSchema) }))
|
|
37
|
+
});
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region ../shared/dist/mcp.mjs
|
|
40
|
+
const MCP_MANIFEST_PATH = "/mcp.json";
|
|
41
|
+
const mcpManifestSchema = z.object({
|
|
42
|
+
resources: z.array(ResourceSchema.extend({ path: z.string() })),
|
|
43
|
+
tools: z.array(ToolSchema.extend({ declaration: declarationSchema }))
|
|
44
|
+
});
|
|
45
|
+
//#endregion
|
|
46
|
+
//#region mcp-vite.ts
|
|
47
|
+
function mcpApps() {
|
|
48
|
+
let root;
|
|
49
|
+
let compiled;
|
|
50
|
+
async function compile() {
|
|
51
|
+
const server = await createServer({
|
|
52
|
+
appType: "custom",
|
|
53
|
+
configFile: false,
|
|
54
|
+
resolve: { tsconfigPaths: true },
|
|
55
|
+
root,
|
|
56
|
+
server: { middlewareMode: true }
|
|
57
|
+
});
|
|
58
|
+
const runner = createServerModuleRunner(server.environments.ssr);
|
|
59
|
+
try {
|
|
60
|
+
const tools = [];
|
|
61
|
+
for await (const file of glob("mcp/*/index.ts", { cwd: root })) {
|
|
62
|
+
const { tool } = await runner.import(join(root, file));
|
|
63
|
+
const declaration = declarationSchema.parse(JSON.parse(await readFile(join(root, dirname(file), "slate.json"), "utf8")));
|
|
64
|
+
if (Object.keys(declaration.connections).length || Object.keys(declaration.databases).length || Object.keys(declaration.secrets).length) throw new Error(`${file}: MCP resource consumers are not implemented yet`);
|
|
65
|
+
tools.push({
|
|
66
|
+
...tool,
|
|
67
|
+
declaration,
|
|
68
|
+
inputSchema: z.toJSONSchema(tool.inputSchema),
|
|
69
|
+
outputSchema: tool.outputSchema ? z.toJSONSchema(tool.outputSchema) : void 0
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const assets = [];
|
|
73
|
+
const resources = [];
|
|
74
|
+
for await (const file of glob("mcp-ui/*/index.html", { cwd: root })) {
|
|
75
|
+
const name = relative("mcp-ui", dirname(file));
|
|
76
|
+
const result = await build({
|
|
77
|
+
build: {
|
|
78
|
+
rolldownOptions: { input: join(root, file) },
|
|
79
|
+
write: false
|
|
80
|
+
},
|
|
81
|
+
configFile: false,
|
|
82
|
+
plugins: [viteSingleFile()],
|
|
83
|
+
publicDir: false,
|
|
84
|
+
resolve: { tsconfigPaths: true },
|
|
85
|
+
root
|
|
86
|
+
});
|
|
87
|
+
if (Array.isArray(result) || !("output" in result)) throw new Error("MCP View build must produce one bundle");
|
|
88
|
+
const html = result.output.find((asset) => asset.type === "asset" && asset.fileName.endsWith(".html"));
|
|
89
|
+
if (html?.type !== "asset") throw new Error(`${file}: missing built HTML`);
|
|
90
|
+
const path = `/mcp-ui/${name}`;
|
|
91
|
+
assets.push({
|
|
92
|
+
fileName: `${path.slice(1)}.html`,
|
|
93
|
+
source: html.source,
|
|
94
|
+
type: "asset"
|
|
95
|
+
});
|
|
96
|
+
resources.push({
|
|
97
|
+
mimeType: RESOURCE_MIME_TYPE,
|
|
98
|
+
name,
|
|
99
|
+
path,
|
|
100
|
+
uri: `ui://${name}/index.html`
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
const manifest = mcpManifestSchema.parse({
|
|
104
|
+
resources,
|
|
105
|
+
tools
|
|
106
|
+
});
|
|
107
|
+
assets.push({
|
|
108
|
+
fileName: MCP_MANIFEST_PATH.slice(1),
|
|
109
|
+
source: JSON.stringify(manifest),
|
|
110
|
+
type: "asset"
|
|
111
|
+
});
|
|
112
|
+
return assets;
|
|
113
|
+
} finally {
|
|
114
|
+
await runner.close();
|
|
115
|
+
await server.close();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
configResolved(config) {
|
|
120
|
+
root = config.root;
|
|
121
|
+
},
|
|
122
|
+
async generateBundle() {
|
|
123
|
+
if (this.environment.config.consumer !== "client") return;
|
|
124
|
+
compiled ??= compile();
|
|
125
|
+
for (const asset of await compiled) this.emitFile(asset);
|
|
126
|
+
},
|
|
127
|
+
name: "contextlayer-mcp-apps"
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
//#endregion
|
|
3
131
|
//#region vite.ts
|
|
4
132
|
async function contextlayer({ command }) {
|
|
5
|
-
const bindings = command === "serve" ? await
|
|
6
|
-
return [
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
133
|
+
const bindings = command === "serve" ? await getLocalResourcesBindings() : void 0;
|
|
134
|
+
return [
|
|
135
|
+
mcpApps(),
|
|
136
|
+
cloudflare({
|
|
137
|
+
auxiliaryWorkers: [{
|
|
138
|
+
config: bindings ? {
|
|
139
|
+
name: bindings.workerName,
|
|
140
|
+
vars: bindings.vars
|
|
141
|
+
} : {},
|
|
142
|
+
configPath: "workers/local-resources/wrangler.jsonc",
|
|
143
|
+
devOnly: true
|
|
144
|
+
}],
|
|
145
|
+
config: {
|
|
146
|
+
assets: { run_worker_first: [
|
|
147
|
+
"/*",
|
|
148
|
+
"!/mcp.json",
|
|
149
|
+
"!/mcp-ui/*"
|
|
150
|
+
] },
|
|
151
|
+
...bindings ? { services: [...bindings.props ? [{
|
|
152
|
+
binding: "TOOLS",
|
|
153
|
+
entrypoint: "Tools",
|
|
154
|
+
props: bindings.props,
|
|
155
|
+
service: bindings.workerName
|
|
156
|
+
}] : [], {
|
|
157
|
+
binding: "DATABASES",
|
|
158
|
+
entrypoint: "Databases",
|
|
159
|
+
props: bindings.databaseProps,
|
|
160
|
+
service: bindings.workerName
|
|
161
|
+
}] } : {}
|
|
162
|
+
},
|
|
163
|
+
persistState: { path: ".contextlayer/databases" },
|
|
164
|
+
viteEnvironment: { name: "ssr" }
|
|
165
|
+
}),
|
|
166
|
+
bindings ? localDatabaseProvisioning(bindings) : void 0
|
|
167
|
+
];
|
|
20
168
|
}
|
|
21
169
|
//#endregion
|
|
22
170
|
export { contextlayer };
|
package/dist/vite.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.js","names":[],"sources":["../vite.ts"],"sourcesContent":["import { cloudflare } from \"@cloudflare/vite-plugin\"\nimport { getLocalToolsBindings } from \"@usecontextlayer/cli/vite\"\nimport type { ConfigEnv } from \"vite\"\n\nexport async function contextlayer({ command }: ConfigEnv) {\n\tconst bindings = command === \"serve\" ? await getLocalToolsBindings() : undefined\n\treturn [\n\t\tcloudflare({\n\t\t\tauxiliaryWorkers: [\n\t\t\t\t{\n\t\t\t\t\tconfig: bindings ? { vars: bindings.vars } : {},\n\t\t\t\t\tconfigPath: \"workers/local-tools/wrangler.jsonc\",\n\t\t\t\t\tdevOnly: true,\n\t\t\t\t},\n\t\t\t],\n\t\t\tconfig: bindings\n\t\t\t\t? {\n\t\t\t\t\t\tservices: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tbinding: \"TOOLS\",\n\t\t\t\t\t\t\t\tentrypoint: \"Tools\",\n\t\t\t\t\t\t\t\tprops: bindings.props,\n\t\t\t\t\t\t\t\tservice: \"ctx-local-tools\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t}\n\t\t\t\t: {},\n\t\t\tviteEnvironment: { name: \"ssr\" },\n\t\t}),\n\t]\n}\n"],"mappings":";;;AAIA,eAAsB,aAAa,EAAE,WAAsB;CAC1D,MAAM,WAAW,YAAY,UAAU,MAAM,sBAAsB,IAAI,KAAA;CACvE,OAAO,CACN,WAAW;EACV,kBAAkB,CACjB;GACC,QAAQ,WAAW,EAAE,MAAM,SAAS,KAAK,IAAI,CAAC;GAC9C,YAAY;GACZ,SAAS;EACV,CACD;EACA,QAAQ,WACL,EACA,UAAU,CACT;GACC,SAAS;GACT,YAAY;GACZ,OAAO,SAAS;GAChB,SAAS;EACV,CACD,EACD,IACC,CAAC;EACJ,iBAAiB,EAAE,MAAM,MAAM;CAChC,CAAC,CACF;AACD"}
|
|
1
|
+
{"version":3,"file":"vite.js","names":[],"sources":["../../shared/dist/declaration.mjs","../../shared/dist/mcp.mjs","../mcp-vite.ts","../vite.ts"],"sourcesContent":["import { z } from \"zod\";\n\n//#region lib/declaration.ts\nconst credentialModeSchema = z.enum([\"viewer\", \"owner\"]);\nconst connectionRequirementSchema = z.strictObject({\n\tmode: credentialModeSchema,\n\ttoolkit: z.string().min(1)\n});\nconst secretNameSchema = z.string().regex(/^[A-Z_][A-Z0-9_]*$/);\nconst secretRequirementSchema = z.strictObject({ mode: credentialModeSchema });\nconst databaseRequirementSchema = z.strictObject({ mode: credentialModeSchema });\nconst databaseSlugSchema = z.string().min(1).regex(/^(?!\\.{1,2}$)[^/\\\\]+$/);\nconst declarationSchema = z.strictObject({\n\tconnections: z.record(z.string().min(1), connectionRequirementSchema),\n\tdatabases: z.record(databaseSlugSchema, databaseRequirementSchema).default({}),\n\tsecrets: z.record(secretNameSchema, secretRequirementSchema).default({})\n});\nconst slateDeclarationsSchema = z.strictObject({\n\tagents: z.record(z.string().min(1), declarationSchema),\n\tapp: declarationSchema\n});\nconst resourceConsumerSchema = z.discriminatedUnion(\"type\", [z.strictObject({ type: z.literal(\"app\") }), z.strictObject({\n\tname: z.string().min(1),\n\ttype: z.literal(\"agent\")\n})]);\nconst resourcesSchema = declarationSchema.extend({\n\tconnections: z.record(z.string().min(1), connectionRequirementSchema.extend({ consumers: z.array(resourceConsumerSchema) })),\n\tdatabases: z.record(databaseSlugSchema, databaseRequirementSchema.extend({ consumers: z.array(resourceConsumerSchema) })),\n\tsecrets: z.record(secretNameSchema, secretRequirementSchema.extend({ consumers: z.array(resourceConsumerSchema) }))\n});\nfunction hasViewerResources(resources) {\n\treturn Object.values(resources).some((requirements) => Object.values(requirements).some(({ mode }) => mode === \"viewer\"));\n}\nfunction collectSlateResources(slateDeclarations) {\n\tconst declarations = [{\n\t\tconsumer: { type: \"app\" },\n\t\tdeclaration: slateDeclarations.app\n\t}, ...Object.entries(slateDeclarations.agents).map(([name, declaration]) => ({\n\t\tconsumer: {\n\t\t\tname,\n\t\t\ttype: \"agent\"\n\t\t},\n\t\tdeclaration\n\t}))];\n\treturn {\n\t\tconnections: collectRequirements(\"connections\", declarations, (declaration) => declaration.connections),\n\t\tdatabases: collectRequirements(\"databases\", declarations, (declaration) => declaration.databases),\n\t\tsecrets: collectRequirements(\"secrets\", declarations, (declaration) => declaration.secrets)\n\t};\n}\nfunction resourcesForConsumer(resources, consumer) {\n\treturn {\n\t\tconnections: filterRequirements(resources.connections, consumer),\n\t\tdatabases: filterRequirements(resources.databases, consumer),\n\t\tsecrets: filterRequirements(resources.secrets, consumer)\n\t};\n}\nfunction filterRequirements(requirements, consumer) {\n\treturn Object.fromEntries(Object.entries(requirements).filter(([, requirement]) => requirement.consumers.some((declared) => declared.type === consumer.type && (consumer.type === \"app\" || declared.type === \"agent\" && declared.name === consumer.name))));\n}\nfunction collectRequirements(category, declarations, select) {\n\tconst resources = /* @__PURE__ */ new Map();\n\tfor (const { consumer, declaration } of declarations) for (const [key, requirement] of Object.entries(select(declaration))) {\n\t\tconst existing = resources.get(key);\n\t\tif (!existing) {\n\t\t\tresources.set(key, {\n\t\t\t\t...requirement,\n\t\t\t\tconsumers: [consumer]\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\t\tif (existing.mode !== requirement.mode || existing.toolkit !== requirement.toolkit) throw new z.ZodError([{\n\t\t\tcode: \"custom\",\n\t\t\tmessage: `Conflicting ${category} requirement \"${key}\": declarations must agree on mode${category === \"connections\" ? \" and toolkit\" : \"\"}`,\n\t\t\tpath: [\n\t\t\t\t...consumer.type === \"app\" ? [\"app\"] : [\"agents\", consumer.name],\n\t\t\t\tcategory,\n\t\t\t\tkey\n\t\t\t]\n\t\t}]);\n\t\texisting.consumers.push(consumer);\n\t}\n\treturn Object.fromEntries(resources);\n}\n\n//#endregion\nexport { collectSlateResources, connectionRequirementSchema, credentialModeSchema, databaseRequirementSchema, databaseSlugSchema, declarationSchema, hasViewerResources, resourceConsumerSchema, resourcesForConsumer, resourcesSchema, secretNameSchema, secretRequirementSchema, slateDeclarationsSchema };","import { declarationSchema } from \"./declaration.mjs\";\nimport { z } from \"zod\";\nimport { ResourceSchema, ToolSchema } from \"@modelcontextprotocol/core\";\n\n//#region lib/mcp.ts\nconst MCP_MANIFEST_PATH = \"/mcp.json\";\nconst mcpManifestSchema = z.object({\n\tresources: z.array(ResourceSchema.extend({ path: z.string() })),\n\ttools: z.array(ToolSchema.extend({ declaration: declarationSchema }))\n});\n\n//#endregion\nexport { MCP_MANIFEST_PATH, mcpManifestSchema };","import { glob, readFile } from \"node:fs/promises\"\nimport { dirname, join, relative } from \"node:path\"\nimport { RESOURCE_MIME_TYPE } from \"@modelcontextprotocol/ext-apps/server\"\nimport { declarationSchema } from \"@usecontextlayer/shared/declaration\"\nimport { MCP_MANIFEST_PATH, mcpManifestSchema } from \"@usecontextlayer/shared/mcp\"\nimport { build, createServer, createServerModuleRunner, type Plugin } from \"vite\"\nimport { viteSingleFile } from \"vite-plugin-singlefile\"\nimport { z } from \"zod\"\nimport type { McpToolModule } from \"@/worker\"\n\nexport function mcpApps(): Plugin {\n\tlet root: string\n\tlet compiled: ReturnType<typeof compile>\n\n\tasync function compile() {\n\t\tconst server = await createServer({\n\t\t\tappType: \"custom\",\n\t\t\tconfigFile: false,\n\t\t\tresolve: { tsconfigPaths: true },\n\t\t\troot,\n\t\t\tserver: { middlewareMode: true },\n\t\t})\n\t\tconst runner = createServerModuleRunner(server.environments.ssr)\n\t\ttry {\n\t\t\tconst tools = []\n\t\t\tfor await (const file of glob(\"mcp/*/index.ts\", { cwd: root })) {\n\t\t\t\tconst { tool } = await runner.import<McpToolModule>(join(root, file))\n\t\t\t\tconst declaration = declarationSchema.parse(\n\t\t\t\t\tJSON.parse(await readFile(join(root, dirname(file), \"slate.json\"), \"utf8\")),\n\t\t\t\t)\n\t\t\t\tif (\n\t\t\t\t\tObject.keys(declaration.connections).length ||\n\t\t\t\t\tObject.keys(declaration.databases).length ||\n\t\t\t\t\tObject.keys(declaration.secrets).length\n\t\t\t\t) {\n\t\t\t\t\tthrow new Error(`${file}: MCP resource consumers are not implemented yet`)\n\t\t\t\t}\n\t\t\t\ttools.push({\n\t\t\t\t\t...tool,\n\t\t\t\t\tdeclaration,\n\t\t\t\t\tinputSchema: z.toJSONSchema(tool.inputSchema),\n\t\t\t\t\toutputSchema: tool.outputSchema ? z.toJSONSchema(tool.outputSchema) : undefined,\n\t\t\t\t})\n\t\t\t}\n\t\t\tconst assets = []\n\t\t\tconst resources = []\n\t\t\tfor await (const file of glob(\"mcp-ui/*/index.html\", { cwd: root })) {\n\t\t\t\tconst name = relative(\"mcp-ui\", dirname(file))\n\t\t\t\tconst result = await build({\n\t\t\t\t\tbuild: { rolldownOptions: { input: join(root, file) }, write: false },\n\t\t\t\t\tconfigFile: false,\n\t\t\t\t\tplugins: [viteSingleFile()],\n\t\t\t\t\tpublicDir: false,\n\t\t\t\t\tresolve: { tsconfigPaths: true },\n\t\t\t\t\troot,\n\t\t\t\t})\n\t\t\t\tif (Array.isArray(result) || !(\"output\" in result)) {\n\t\t\t\t\tthrow new Error(\"MCP View build must produce one bundle\")\n\t\t\t\t}\n\t\t\t\tconst html = result.output.find(\n\t\t\t\t\t(asset) => asset.type === \"asset\" && asset.fileName.endsWith(\".html\"),\n\t\t\t\t)\n\t\t\t\tif (html?.type !== \"asset\") throw new Error(`${file}: missing built HTML`)\n\t\t\t\tconst path = `/mcp-ui/${name}`\n\t\t\t\tassets.push({\n\t\t\t\t\tfileName: `${path.slice(1)}.html`,\n\t\t\t\t\tsource: html.source,\n\t\t\t\t\ttype: \"asset\" as const,\n\t\t\t\t})\n\t\t\t\tresources.push({\n\t\t\t\t\tmimeType: RESOURCE_MIME_TYPE,\n\t\t\t\t\tname,\n\t\t\t\t\tpath,\n\t\t\t\t\turi: `ui://${name}/index.html`,\n\t\t\t\t})\n\t\t\t}\n\t\t\tconst manifest = mcpManifestSchema.parse({ resources, tools })\n\t\t\tassets.push({\n\t\t\t\tfileName: MCP_MANIFEST_PATH.slice(1),\n\t\t\t\tsource: JSON.stringify(manifest),\n\t\t\t\ttype: \"asset\" as const,\n\t\t\t})\n\t\t\treturn assets\n\t\t} finally {\n\t\t\tawait runner.close()\n\t\t\tawait server.close()\n\t\t}\n\t}\n\n\treturn {\n\t\tconfigResolved(config) {\n\t\t\troot = config.root\n\t\t},\n\t\tasync generateBundle() {\n\t\t\tif (this.environment.config.consumer !== \"client\") return\n\t\t\tcompiled ??= compile()\n\t\t\tfor (const asset of await compiled) this.emitFile(asset)\n\t\t},\n\t\tname: \"contextlayer-mcp-apps\",\n\t}\n}\n","import { cloudflare } from \"@cloudflare/vite-plugin\"\nimport {\n\tgetLocalResourcesBindings,\n\tlocalDatabaseProvisioning,\n} from \"@usecontextlayer/cli/vite\"\nimport type { ConfigEnv } from \"vite\"\nimport { mcpApps } from \"@/mcp-vite\"\n\nexport async function contextlayer({ command }: ConfigEnv) {\n\tconst bindings = command === \"serve\" ? await getLocalResourcesBindings() : undefined\n\treturn [\n\t\tmcpApps(),\n\t\tcloudflare({\n\t\t\tauxiliaryWorkers: [\n\t\t\t\t{\n\t\t\t\t\tconfig: bindings ? { name: bindings.workerName, vars: bindings.vars } : {},\n\t\t\t\t\tconfigPath: \"workers/local-resources/wrangler.jsonc\",\n\t\t\t\t\tdevOnly: true,\n\t\t\t\t},\n\t\t\t],\n\t\t\tconfig: {\n\t\t\t\tassets: { run_worker_first: [\"/*\", \"!/mcp.json\", \"!/mcp-ui/*\"] },\n\t\t\t\t...(bindings\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tservices: [\n\t\t\t\t\t\t\t\t...(bindings.props\n\t\t\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\tbinding: \"TOOLS\",\n\t\t\t\t\t\t\t\t\t\t\t\tentrypoint: \"Tools\",\n\t\t\t\t\t\t\t\t\t\t\t\tprops: bindings.props,\n\t\t\t\t\t\t\t\t\t\t\t\tservice: bindings.workerName,\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t\t\t: []),\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tbinding: \"DATABASES\",\n\t\t\t\t\t\t\t\t\tentrypoint: \"Databases\",\n\t\t\t\t\t\t\t\t\tprops: bindings.databaseProps,\n\t\t\t\t\t\t\t\t\tservice: bindings.workerName,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t\tpersistState: { path: \".contextlayer/databases\" },\n\t\t\tviteEnvironment: { name: \"ssr\" },\n\t\t}),\n\t\tbindings ? localDatabaseProvisioning(bindings) : undefined,\n\t]\n}\n"],"mappings":"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"}
|
package/dist/worker.d.ts
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
|
-
import { Tools } from "./
|
|
1
|
+
import { a as Databases, n as ToolsBinding, t as Tools } from "./tools-BLXbCgQU-D3L2WEEd.js";
|
|
2
|
+
import "./index-Dle7CHzb.js";
|
|
2
3
|
import { createRequestHandler } from "react-router";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { ToolConfig } from "@modelcontextprotocol/ext-apps/server";
|
|
6
|
+
import { CallToolResult } from "@modelcontextprotocol/server";
|
|
3
7
|
//#region worker.d.ts
|
|
4
8
|
interface LocalBindings {
|
|
5
|
-
|
|
9
|
+
DATABASES: Databases;
|
|
10
|
+
TOOLS: ToolsBinding;
|
|
6
11
|
}
|
|
7
|
-
interface
|
|
8
|
-
|
|
12
|
+
interface SlateWorkerProps {
|
|
13
|
+
databases: Databases;
|
|
14
|
+
tools: ToolsBinding;
|
|
15
|
+
mcpTool?: string;
|
|
9
16
|
}
|
|
10
|
-
export
|
|
11
|
-
|
|
17
|
+
export interface McpToolModule {
|
|
18
|
+
tool: Omit<ToolConfig, "inputSchema" | "outputSchema"> & {
|
|
19
|
+
name: string;
|
|
20
|
+
inputSchema: z.ZodType;
|
|
21
|
+
outputSchema?: z.ZodType;
|
|
22
|
+
};
|
|
23
|
+
handler(args: unknown, tools: Tools): CallToolResult | Promise<CallToolResult>;
|
|
24
|
+
}
|
|
25
|
+
export type SlateWorker = Required<Pick<ExportedHandler<LocalBindings, unknown, unknown, SlateWorkerProps>, "fetch">>;
|
|
26
|
+
export declare function createSlateWorker({ build, mode, development, mcp }: {
|
|
12
27
|
build: Parameters<typeof createRequestHandler>[0];
|
|
13
28
|
mode: string;
|
|
14
29
|
development: boolean;
|
|
15
|
-
|
|
30
|
+
mcp?: Record<string, McpToolModule>;
|
|
31
|
+
}): SlateWorker;
|
|
16
32
|
//#endregion
|
|
17
33
|
//# sourceMappingURL=worker.d.ts.map
|
package/dist/worker.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.ts","names":[],"sources":["../worker.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"worker.d.ts","names":[],"sources":["../worker.ts"],"mappings":";;;;;;;UAOU;EACT,WAAW;EACX,OAAO;;UAGE;EACT,WAAW;EACX,OAAO;EACP;;iBAGgB;EAChB,MAAM,KAAK;IACV;IACA,aAAa,EAAE;IACf,eAAe,EAAE;;EAElB,QAAQ,eAAe,OAAO,QAAQ,iBAAiB,QAAQ;;YAGpD,cAAc,SACzB,KAAK,gBAAgB,iCAAiC;wBAGvC,oBACf,OACA,MACA,aACA;EAEA,OAAO,kBAAkB;EACzB;EACA;EACA,MAAM,eAAe;IAClB"}
|
package/dist/worker.js
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
|
-
import { toolsContext } from "./
|
|
1
|
+
import { n as toolsContext, t as databasesContext } from "./sdk-BMmzPuDi.js";
|
|
2
2
|
import { RouterContextProvider, createRequestHandler } from "react-router";
|
|
3
3
|
//#region worker.ts
|
|
4
|
-
function
|
|
4
|
+
function createSlateWorker({ build, mode, development, mcp = {} }) {
|
|
5
5
|
const requestHandler = createRequestHandler(build, mode);
|
|
6
6
|
return { async fetch(request, env, ctx) {
|
|
7
|
+
if (ctx.props.mcpTool) {
|
|
8
|
+
const module = Object.values(mcp).find(({ tool }) => tool.name === ctx.props.mcpTool);
|
|
9
|
+
if (!module) throw new Error(`Unknown MCP tool: ${ctx.props.mcpTool}`);
|
|
10
|
+
const args = await module.tool.inputSchema.parseAsync(await request.json());
|
|
11
|
+
return Response.json(await module.handler(args, createTools(ctx.props.tools)));
|
|
12
|
+
}
|
|
7
13
|
const context = new RouterContextProvider();
|
|
8
|
-
context.set(
|
|
14
|
+
context.set(databasesContext, development ? env.DATABASES : ctx.props.databases);
|
|
15
|
+
context.set(toolsContext, createTools(development ? env.TOOLS : ctx.props.tools));
|
|
9
16
|
return requestHandler(request, context);
|
|
10
17
|
} };
|
|
11
18
|
}
|
|
19
|
+
function createTools(binding) {
|
|
20
|
+
return { async call(...args) {
|
|
21
|
+
const result = await binding.call(...args);
|
|
22
|
+
if (result instanceof Response) throw result;
|
|
23
|
+
return result;
|
|
24
|
+
} };
|
|
25
|
+
}
|
|
12
26
|
//#endregion
|
|
13
|
-
export {
|
|
27
|
+
export { createSlateWorker };
|
|
14
28
|
|
|
15
29
|
//# sourceMappingURL=worker.js.map
|
package/dist/worker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.js","names":[],"sources":["../worker.ts"],"sourcesContent":["import { createRequestHandler, RouterContextProvider } from \"react-router\"\nimport { type Tools, toolsContext } from \"@/index\"\n\ninterface LocalBindings {\n\tTOOLS:
|
|
1
|
+
{"version":3,"file":"worker.js","names":[],"sources":["../worker.ts"],"sourcesContent":["import type { ToolConfig } from \"@modelcontextprotocol/ext-apps/server\"\nimport type { CallToolResult } from \"@modelcontextprotocol/server\"\nimport type { ToolsBinding } from \"@usecontextlayer/shared/tools\"\nimport { createRequestHandler, RouterContextProvider } from \"react-router\"\nimport type { z } from \"zod\"\nimport { type Databases, databasesContext, type Tools, toolsContext } from \"@/index\"\n\ninterface LocalBindings {\n\tDATABASES: Databases\n\tTOOLS: ToolsBinding\n}\n\ninterface SlateWorkerProps {\n\tdatabases: Databases\n\ttools: ToolsBinding\n\tmcpTool?: string\n}\n\nexport interface McpToolModule {\n\ttool: Omit<ToolConfig, \"inputSchema\" | \"outputSchema\"> & {\n\t\tname: string\n\t\tinputSchema: z.ZodType\n\t\toutputSchema?: z.ZodType\n\t}\n\thandler(args: unknown, tools: Tools): CallToolResult | Promise<CallToolResult>\n}\n\nexport type SlateWorker = Required<\n\tPick<ExportedHandler<LocalBindings, unknown, unknown, SlateWorkerProps>, \"fetch\">\n>\n\nexport function createSlateWorker({\n\tbuild,\n\tmode,\n\tdevelopment,\n\tmcp = {},\n}: {\n\tbuild: Parameters<typeof createRequestHandler>[0]\n\tmode: string\n\tdevelopment: boolean\n\tmcp?: Record<string, McpToolModule>\n}): SlateWorker {\n\tconst requestHandler = createRequestHandler(build, mode)\n\treturn {\n\t\tasync fetch(request, env, ctx) {\n\t\t\tif (ctx.props.mcpTool) {\n\t\t\t\tconst module = Object.values(mcp).find(\n\t\t\t\t\t({ tool }) => tool.name === ctx.props.mcpTool,\n\t\t\t\t)\n\t\t\t\tif (!module) throw new Error(`Unknown MCP tool: ${ctx.props.mcpTool}`)\n\t\t\t\tconst args = await module.tool.inputSchema.parseAsync(await request.json())\n\t\t\t\treturn Response.json(await module.handler(args, createTools(ctx.props.tools)))\n\t\t\t}\n\t\t\tconst context = new RouterContextProvider()\n\t\t\tcontext.set(databasesContext, development ? env.DATABASES : ctx.props.databases)\n\t\t\tcontext.set(toolsContext, createTools(development ? env.TOOLS : ctx.props.tools))\n\t\t\treturn requestHandler(request, context)\n\t\t},\n\t}\n}\n\nfunction createTools(binding: ToolsBinding): Tools {\n\treturn {\n\t\tasync call(...args) {\n\t\t\tconst result = await binding.call(...args)\n\t\t\tif (result instanceof Response) throw result\n\t\t\treturn result\n\t\t},\n\t}\n}\n"],"mappings":";;;AA+BA,SAAgB,kBAAkB,EACjC,OACA,MACA,aACA,MAAM,CAAC,KAMQ;CACf,MAAM,iBAAiB,qBAAqB,OAAO,IAAI;CACvD,OAAO,EACN,MAAM,MAAM,SAAS,KAAK,KAAK;EAC9B,IAAI,IAAI,MAAM,SAAS;GACtB,MAAM,SAAS,OAAO,OAAO,GAAG,CAAC,CAAC,MAChC,EAAE,WAAW,KAAK,SAAS,IAAI,MAAM,OACvC;GACA,IAAI,CAAC,QAAQ,MAAM,IAAI,MAAM,qBAAqB,IAAI,MAAM,SAAS;GACrE,MAAM,OAAO,MAAM,OAAO,KAAK,YAAY,WAAW,MAAM,QAAQ,KAAK,CAAC;GAC1E,OAAO,SAAS,KAAK,MAAM,OAAO,QAAQ,MAAM,YAAY,IAAI,MAAM,KAAK,CAAC,CAAC;EAC9E;EACA,MAAM,UAAU,IAAI,sBAAsB;EAC1C,QAAQ,IAAI,kBAAkB,cAAc,IAAI,YAAY,IAAI,MAAM,SAAS;EAC/E,QAAQ,IAAI,cAAc,YAAY,cAAc,IAAI,QAAQ,IAAI,MAAM,KAAK,CAAC;EAChF,OAAO,eAAe,SAAS,OAAO;CACvC,EACD;AACD;AAEA,SAAS,YAAY,SAA8B;CAClD,OAAO,EACN,MAAM,KAAK,GAAG,MAAM;EACnB,MAAM,SAAS,MAAM,QAAQ,KAAK,GAAG,IAAI;EACzC,IAAI,kBAAkB,UAAU,MAAM;EACtC,OAAO;CACR,EACD;AACD"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// This example's public/slate.json declares the connection; follow the SDK README to copy the app files and assign a connected Gmail account.
|
|
1
2
|
import { toolsContext } from "@usecontextlayer/sdk"
|
|
2
3
|
import { type LoaderFunctionArgs, useLoaderData } from "react-router"
|
|
3
4
|
import { z } from "zod"
|
|
@@ -31,7 +32,7 @@ export default function Home() {
|
|
|
31
32
|
<main className="mx-auto max-w-3xl p-8">
|
|
32
33
|
<h1 className="text-2xl font-semibold">Your Gmail inbox</h1>
|
|
33
34
|
<p className="mt-2 text-sm text-gray-500">
|
|
34
|
-
Fetched by this page's server loader through your
|
|
35
|
+
Fetched by this page's server loader through your connected Gmail account.
|
|
35
36
|
</p>
|
|
36
37
|
<ul className="mt-6 divide-y divide-gray-200">
|
|
37
38
|
{loaderData.messages.map((message) => (
|
package/package.json
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"dependencies": {
|
|
3
|
-
"
|
|
4
|
-
"@
|
|
3
|
+
"@modelcontextprotocol/client": "2.3.1",
|
|
4
|
+
"@modelcontextprotocol/core": "2.3.1",
|
|
5
|
+
"@modelcontextprotocol/ext-apps": "2.0.3",
|
|
6
|
+
"@modelcontextprotocol/server": "2.3.1",
|
|
7
|
+
"drizzle-orm": "0.45.3",
|
|
8
|
+
"vite-plugin-singlefile": "2.3.3",
|
|
9
|
+
"zod": "^4.6.5",
|
|
10
|
+
"@usecontextlayer/cli": "0.16.0"
|
|
5
11
|
},
|
|
6
12
|
"devDependencies": {
|
|
7
13
|
"@cloudflare/vite-plugin": "^1.62.4",
|
|
@@ -15,7 +21,8 @@
|
|
|
15
21
|
"tsdown": "latest",
|
|
16
22
|
"typescript": "latest",
|
|
17
23
|
"vite": "^8.3.2",
|
|
18
|
-
"
|
|
24
|
+
"vitest": "^4.1.11",
|
|
25
|
+
"@usecontextlayer/shared": "0.16.0"
|
|
19
26
|
},
|
|
20
27
|
"exports": {
|
|
21
28
|
".": {
|
|
@@ -52,10 +59,11 @@
|
|
|
52
59
|
"vite": "^8.3.2"
|
|
53
60
|
},
|
|
54
61
|
"type": "module",
|
|
55
|
-
"version": "0.
|
|
62
|
+
"version": "0.16.0",
|
|
56
63
|
"scripts": {
|
|
57
64
|
"build": "tsdown",
|
|
58
65
|
"dev:watch": "tsdown --watch",
|
|
66
|
+
"test": "vitest run --config vitest.config.ts",
|
|
59
67
|
"tsc": "tsc -b tsconfig.json"
|
|
60
68
|
}
|
|
61
69
|
}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../index.ts"],"mappings":";iBAEiB;EAChB,KACC,cACA,kBACA,MAAM,0BACJ;IAAU;IAAe;;;qBAGhB,qCAAY,cAAA"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../index.ts"],"sourcesContent":["import { createContext } from \"react-router\"\n\nexport interface Tools {\n\tcall(\n\t\tslug: string,\n\t\ttoolSlug: string,\n\t\targs: Record<string, unknown>,\n\t): Promise<{ data: unknown; logId: string }>\n}\n\nexport const toolsContext = createContext<Tools>()\n"],"mappings":";;AAUA,MAAa,eAAe,cAAqB"}
|