@getjack/jack 0.1.32 → 0.1.34
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/package.json +1 -1
- package/src/commands/deploys.ts +95 -0
- package/src/commands/link.ts +8 -0
- package/src/commands/mcp.ts +179 -4
- package/src/commands/rollback.ts +53 -0
- package/src/commands/secrets.ts +3 -1
- package/src/commands/services.ts +11 -1
- package/src/commands/ship.ts +3 -1
- package/src/commands/tokens.ts +16 -1
- package/src/commands/whoami.ts +43 -8
- package/src/index.ts +16 -0
- package/src/lib/agent-files.ts +54 -4
- package/src/lib/agent-integration.ts +4 -166
- package/src/lib/claude-hooks-installer.ts +55 -0
- package/src/lib/control-plane.ts +78 -40
- package/src/lib/crypto.ts +84 -0
- package/src/lib/debug.ts +2 -1
- package/src/lib/deploy-upload.ts +13 -3
- package/src/lib/hooks.ts +4 -3
- package/src/lib/managed-deploy.ts +12 -9
- package/src/lib/project-link.ts +6 -0
- package/src/lib/project-operations.ts +92 -30
- package/src/lib/prompts.ts +2 -2
- package/src/lib/telemetry.ts +2 -0
- package/src/mcp/README.md +1 -1
- package/src/mcp/resources/index.ts +1 -16
- package/src/mcp/server.ts +23 -0
- package/src/mcp/tools/index.ts +133 -17
- package/src/mcp/types.ts +1 -0
- package/src/mcp/utils.ts +2 -1
- package/src/templates/index.ts +25 -73
- package/templates/CLAUDE.md +62 -0
- package/templates/ai-chat/.jack.json +10 -5
- package/templates/ai-chat/bun.lock +50 -1
- package/templates/ai-chat/package.json +5 -0
- package/templates/ai-chat/public/app.js +73 -0
- package/templates/ai-chat/public/index.html +14 -197
- package/templates/ai-chat/schema.sql +14 -0
- package/templates/ai-chat/src/index.ts +86 -102
- package/templates/ai-chat/wrangler.jsonc +8 -1
- package/templates/cron/.jack.json +66 -0
- package/templates/cron/bun.lock +23 -0
- package/templates/cron/package.json +16 -0
- package/templates/cron/schema.sql +24 -0
- package/templates/cron/src/index.ts +117 -0
- package/templates/cron/src/jobs.ts +139 -0
- package/templates/cron/src/webhooks.ts +95 -0
- package/templates/cron/tsconfig.json +17 -0
- package/templates/cron/wrangler.jsonc +11 -0
- package/templates/miniapp/.jack.json +1 -1
- package/templates/nextjs/.jack.json +1 -1
- package/templates/nextjs-auth/.jack.json +44 -0
- package/templates/nextjs-auth/app/api/auth/[...all]/route.ts +11 -0
- package/templates/nextjs-auth/app/dashboard/loading.tsx +53 -0
- package/templates/nextjs-auth/app/dashboard/page.tsx +73 -0
- package/templates/nextjs-auth/app/error.tsx +44 -0
- package/templates/nextjs-auth/app/globals.css +1 -0
- package/templates/nextjs-auth/app/health/route.ts +3 -0
- package/templates/nextjs-auth/app/layout.tsx +24 -0
- package/templates/nextjs-auth/app/login/page.tsx +10 -0
- package/templates/nextjs-auth/app/page.tsx +86 -0
- package/templates/nextjs-auth/app/signup/page.tsx +10 -0
- package/templates/nextjs-auth/bun.lock +1065 -0
- package/templates/nextjs-auth/cloudflare-env.d.ts +8 -0
- package/templates/nextjs-auth/components/auth-form.tsx +191 -0
- package/templates/nextjs-auth/components/header.tsx +50 -0
- package/templates/nextjs-auth/components/user-menu.tsx +23 -0
- package/templates/nextjs-auth/lib/auth-client.ts +3 -0
- package/templates/nextjs-auth/lib/auth.ts +43 -0
- package/templates/nextjs-auth/lib/utils.ts +6 -0
- package/templates/nextjs-auth/middleware.ts +33 -0
- package/templates/nextjs-auth/next.config.ts +8 -0
- package/templates/nextjs-auth/open-next.config.ts +6 -0
- package/templates/nextjs-auth/package.json +33 -0
- package/templates/nextjs-auth/postcss.config.mjs +8 -0
- package/templates/nextjs-auth/schema.sql +49 -0
- package/templates/nextjs-auth/tsconfig.json +28 -0
- package/templates/nextjs-auth/wrangler.jsonc +23 -0
- package/templates/nextjs-clerk/.jack.json +54 -0
- package/templates/nextjs-clerk/app/dashboard/page.tsx +69 -0
- package/templates/nextjs-clerk/app/globals.css +1 -0
- package/templates/nextjs-clerk/app/health/route.ts +3 -0
- package/templates/nextjs-clerk/app/layout.tsx +28 -0
- package/templates/nextjs-clerk/app/page.tsx +86 -0
- package/templates/nextjs-clerk/app/sign-in/[[...sign-in]]/page.tsx +9 -0
- package/templates/nextjs-clerk/app/sign-up/[[...sign-up]]/page.tsx +9 -0
- package/templates/nextjs-clerk/bun.lock +1055 -0
- package/templates/nextjs-clerk/cloudflare-env.d.ts +3 -0
- package/templates/nextjs-clerk/components/header.tsx +40 -0
- package/templates/nextjs-clerk/lib/utils.ts +6 -0
- package/templates/nextjs-clerk/middleware.ts +18 -0
- package/templates/nextjs-clerk/next.config.ts +8 -0
- package/templates/nextjs-clerk/open-next.config.ts +6 -0
- package/templates/nextjs-clerk/package.json +31 -0
- package/templates/nextjs-clerk/postcss.config.mjs +8 -0
- package/templates/nextjs-clerk/tsconfig.json +28 -0
- package/templates/nextjs-clerk/wrangler.jsonc +17 -0
- package/templates/nextjs-shadcn/.jack.json +34 -0
- package/templates/nextjs-shadcn/app/dashboard/data.json +614 -0
- package/templates/nextjs-shadcn/app/dashboard/page.tsx +55 -0
- package/templates/nextjs-shadcn/app/globals.css +126 -0
- package/templates/nextjs-shadcn/app/health/route.ts +3 -0
- package/templates/nextjs-shadcn/app/layout.tsx +24 -0
- package/templates/nextjs-shadcn/app/login/page.tsx +19 -0
- package/templates/nextjs-shadcn/app/page.tsx +180 -0
- package/templates/nextjs-shadcn/app/showcase.tsx +1262 -0
- package/templates/nextjs-shadcn/bun.lock +1789 -0
- package/templates/nextjs-shadcn/cloudflare-env.d.ts +4 -0
- package/templates/nextjs-shadcn/components/app-sidebar.tsx +175 -0
- package/templates/nextjs-shadcn/components/chart-area-interactive.tsx +291 -0
- package/templates/nextjs-shadcn/components/data-table.tsx +807 -0
- package/templates/nextjs-shadcn/components/login-form.tsx +95 -0
- package/templates/nextjs-shadcn/components/nav-documents.tsx +92 -0
- package/templates/nextjs-shadcn/components/nav-main.tsx +73 -0
- package/templates/nextjs-shadcn/components/nav-projects.tsx +89 -0
- package/templates/nextjs-shadcn/components/nav-secondary.tsx +42 -0
- package/templates/nextjs-shadcn/components/nav-user.tsx +114 -0
- package/templates/nextjs-shadcn/components/section-cards.tsx +102 -0
- package/templates/nextjs-shadcn/components/site-header.tsx +30 -0
- package/templates/nextjs-shadcn/components/team-switcher.tsx +91 -0
- package/templates/nextjs-shadcn/components/ui/accordion.tsx +66 -0
- package/templates/nextjs-shadcn/components/ui/alert-dialog.tsx +196 -0
- package/templates/nextjs-shadcn/components/ui/alert.tsx +66 -0
- package/templates/nextjs-shadcn/components/ui/aspect-ratio.tsx +11 -0
- package/templates/nextjs-shadcn/components/ui/avatar.tsx +109 -0
- package/templates/nextjs-shadcn/components/ui/badge.tsx +48 -0
- package/templates/nextjs-shadcn/components/ui/breadcrumb.tsx +109 -0
- package/templates/nextjs-shadcn/components/ui/button-group.tsx +83 -0
- package/templates/nextjs-shadcn/components/ui/button.tsx +64 -0
- package/templates/nextjs-shadcn/components/ui/calendar.tsx +220 -0
- package/templates/nextjs-shadcn/components/ui/card.tsx +92 -0
- package/templates/nextjs-shadcn/components/ui/carousel.tsx +241 -0
- package/templates/nextjs-shadcn/components/ui/chart.tsx +357 -0
- package/templates/nextjs-shadcn/components/ui/checkbox.tsx +32 -0
- package/templates/nextjs-shadcn/components/ui/collapsible.tsx +33 -0
- package/templates/nextjs-shadcn/components/ui/combobox.tsx +310 -0
- package/templates/nextjs-shadcn/components/ui/command.tsx +184 -0
- package/templates/nextjs-shadcn/components/ui/context-menu.tsx +252 -0
- package/templates/nextjs-shadcn/components/ui/dialog.tsx +158 -0
- package/templates/nextjs-shadcn/components/ui/direction.tsx +22 -0
- package/templates/nextjs-shadcn/components/ui/drawer.tsx +135 -0
- package/templates/nextjs-shadcn/components/ui/dropdown-menu.tsx +257 -0
- package/templates/nextjs-shadcn/components/ui/empty.tsx +104 -0
- package/templates/nextjs-shadcn/components/ui/field.tsx +248 -0
- package/templates/nextjs-shadcn/components/ui/form.tsx +167 -0
- package/templates/nextjs-shadcn/components/ui/hover-card.tsx +44 -0
- package/templates/nextjs-shadcn/components/ui/input-group.tsx +170 -0
- package/templates/nextjs-shadcn/components/ui/input-otp.tsx +77 -0
- package/templates/nextjs-shadcn/components/ui/input.tsx +21 -0
- package/templates/nextjs-shadcn/components/ui/item.tsx +193 -0
- package/templates/nextjs-shadcn/components/ui/kbd.tsx +28 -0
- package/templates/nextjs-shadcn/components/ui/label.tsx +24 -0
- package/templates/nextjs-shadcn/components/ui/menubar.tsx +276 -0
- package/templates/nextjs-shadcn/components/ui/native-select.tsx +53 -0
- package/templates/nextjs-shadcn/components/ui/navigation-menu.tsx +168 -0
- package/templates/nextjs-shadcn/components/ui/pagination.tsx +127 -0
- package/templates/nextjs-shadcn/components/ui/popover.tsx +89 -0
- package/templates/nextjs-shadcn/components/ui/progress.tsx +31 -0
- package/templates/nextjs-shadcn/components/ui/radio-group.tsx +45 -0
- package/templates/nextjs-shadcn/components/ui/resizable.tsx +53 -0
- package/templates/nextjs-shadcn/components/ui/scroll-area.tsx +58 -0
- package/templates/nextjs-shadcn/components/ui/select.tsx +190 -0
- package/templates/nextjs-shadcn/components/ui/separator.tsx +28 -0
- package/templates/nextjs-shadcn/components/ui/sheet.tsx +143 -0
- package/templates/nextjs-shadcn/components/ui/sidebar.tsx +726 -0
- package/templates/nextjs-shadcn/components/ui/skeleton.tsx +13 -0
- package/templates/nextjs-shadcn/components/ui/slider.tsx +63 -0
- package/templates/nextjs-shadcn/components/ui/sonner.tsx +40 -0
- package/templates/nextjs-shadcn/components/ui/spinner.tsx +16 -0
- package/templates/nextjs-shadcn/components/ui/switch.tsx +35 -0
- package/templates/nextjs-shadcn/components/ui/table.tsx +116 -0
- package/templates/nextjs-shadcn/components/ui/tabs.tsx +91 -0
- package/templates/nextjs-shadcn/components/ui/textarea.tsx +18 -0
- package/templates/nextjs-shadcn/components/ui/toggle-group.tsx +83 -0
- package/templates/nextjs-shadcn/components/ui/toggle.tsx +47 -0
- package/templates/nextjs-shadcn/components/ui/tooltip.tsx +57 -0
- package/templates/nextjs-shadcn/components.json +23 -0
- package/templates/nextjs-shadcn/hooks/use-mobile.ts +19 -0
- package/templates/nextjs-shadcn/lib/utils.ts +6 -0
- package/templates/nextjs-shadcn/next-env.d.ts +6 -0
- package/templates/nextjs-shadcn/next.config.ts +8 -0
- package/templates/nextjs-shadcn/open-next.config.ts +6 -0
- package/templates/nextjs-shadcn/package.json +55 -0
- package/templates/nextjs-shadcn/postcss.config.mjs +8 -0
- package/templates/nextjs-shadcn/tsconfig.json +28 -0
- package/templates/nextjs-shadcn/wrangler.jsonc +23 -0
- package/templates/resend/.jack.json +64 -0
- package/templates/resend/bun.lock +23 -0
- package/templates/resend/package.json +16 -0
- package/templates/resend/schema.sql +13 -0
- package/templates/resend/src/email.ts +165 -0
- package/templates/resend/src/index.ts +108 -0
- package/templates/resend/tsconfig.json +17 -0
- package/templates/resend/wrangler.jsonc +11 -0
- package/templates/saas/.jack.json +1 -1
- package/templates/ai-chat/public/chat.js +0 -149
package/src/mcp/tools/index.ts
CHANGED
|
@@ -7,6 +7,10 @@ import { JackError, JackErrorCode } from "../../lib/errors.ts";
|
|
|
7
7
|
import { getDeployMode, getProjectId } from "../../lib/project-link.ts";
|
|
8
8
|
import { createProject, deployProject, getProjectStatus } from "../../lib/project-operations.ts";
|
|
9
9
|
import { listAllProjects } from "../../lib/project-resolver.ts";
|
|
10
|
+
import { createCronSchedule } from "../../lib/services/cron-create.ts";
|
|
11
|
+
import { deleteCronSchedule } from "../../lib/services/cron-delete.ts";
|
|
12
|
+
import { listCronSchedules } from "../../lib/services/cron-list.ts";
|
|
13
|
+
import { testCronExpression } from "../../lib/services/cron-test.ts";
|
|
10
14
|
import { createDatabase } from "../../lib/services/db-create.ts";
|
|
11
15
|
import {
|
|
12
16
|
DestructiveOperationError,
|
|
@@ -15,10 +19,6 @@ import {
|
|
|
15
19
|
wrapResultsForMcp,
|
|
16
20
|
} from "../../lib/services/db-execute.ts";
|
|
17
21
|
import { listDatabases } from "../../lib/services/db-list.ts";
|
|
18
|
-
import { createCronSchedule } from "../../lib/services/cron-create.ts";
|
|
19
|
-
import { deleteCronSchedule } from "../../lib/services/cron-delete.ts";
|
|
20
|
-
import { listCronSchedules } from "../../lib/services/cron-list.ts";
|
|
21
|
-
import { testCronExpression } from "../../lib/services/cron-test.ts";
|
|
22
22
|
import {
|
|
23
23
|
assignDomain,
|
|
24
24
|
connectDomain,
|
|
@@ -41,7 +41,12 @@ import { formatErrorResponse, formatSuccessResponse } from "../utils.ts";
|
|
|
41
41
|
// Tool schemas
|
|
42
42
|
const CreateProjectSchema = z.object({
|
|
43
43
|
name: z.string().optional().describe("Project name (auto-generated if not provided)"),
|
|
44
|
-
template: z
|
|
44
|
+
template: z
|
|
45
|
+
.string()
|
|
46
|
+
.optional()
|
|
47
|
+
.describe(
|
|
48
|
+
"Template to use (e.g., 'miniapp', 'api'). Also supports forking: use 'username/slug' for published projects or 'my-project' to fork your own.",
|
|
49
|
+
),
|
|
45
50
|
});
|
|
46
51
|
|
|
47
52
|
const DeployProjectSchema = z.object({
|
|
@@ -49,6 +54,12 @@ const DeployProjectSchema = z.object({
|
|
|
49
54
|
.string()
|
|
50
55
|
.optional()
|
|
51
56
|
.describe("Path to project directory (defaults to current directory)"),
|
|
57
|
+
message: z
|
|
58
|
+
.string()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe(
|
|
61
|
+
"Deploy message describing what changed and why (e.g., 'Add user auth', 'Fix CORS bug')",
|
|
62
|
+
),
|
|
52
63
|
});
|
|
53
64
|
|
|
54
65
|
const GetProjectStatusSchema = z.object({
|
|
@@ -200,6 +211,19 @@ const TailLogsSchema = z.object({
|
|
|
200
211
|
.describe("How long to listen before returning (default: 2000ms, max: 10000ms)"),
|
|
201
212
|
});
|
|
202
213
|
|
|
214
|
+
const RollbackProjectSchema = z.object({
|
|
215
|
+
deployment_id: z
|
|
216
|
+
.string()
|
|
217
|
+
.optional()
|
|
218
|
+
.describe(
|
|
219
|
+
"Specific deployment ID to roll back to (defaults to previous successful deployment)",
|
|
220
|
+
),
|
|
221
|
+
project_path: z
|
|
222
|
+
.string()
|
|
223
|
+
.optional()
|
|
224
|
+
.describe("Path to project directory (defaults to current directory)"),
|
|
225
|
+
});
|
|
226
|
+
|
|
203
227
|
const ListDomainsSchema = z.object({});
|
|
204
228
|
|
|
205
229
|
const ConnectDomainSchema = z.object({
|
|
@@ -220,7 +244,9 @@ const DisconnectDomainSchema = z.object({
|
|
|
220
244
|
});
|
|
221
245
|
|
|
222
246
|
const CreateCronSchema = z.object({
|
|
223
|
-
expression: z
|
|
247
|
+
expression: z
|
|
248
|
+
.string()
|
|
249
|
+
.describe("Cron expression (e.g., '0 * * * *' for hourly, '*/15 * * * *' for every 15 min)"),
|
|
224
250
|
project_path: z
|
|
225
251
|
.string()
|
|
226
252
|
.optional()
|
|
@@ -264,7 +290,7 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
264
290
|
{
|
|
265
291
|
name: "create_project",
|
|
266
292
|
description:
|
|
267
|
-
"Create a new
|
|
293
|
+
"Create a new project from a template. Automatically installs dependencies, deploys, and registers the project. Also supports forking: pass a 'username/slug' template to fork a published project, or a project slug to fork your own.",
|
|
268
294
|
inputSchema: {
|
|
269
295
|
type: "object",
|
|
270
296
|
properties: {
|
|
@@ -274,7 +300,8 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
274
300
|
},
|
|
275
301
|
template: {
|
|
276
302
|
type: "string",
|
|
277
|
-
description:
|
|
303
|
+
description:
|
|
304
|
+
"Template to use (e.g., 'miniapp', 'api'). Also supports forking: use 'username/slug' for published projects or 'my-project' to fork your own.",
|
|
278
305
|
},
|
|
279
306
|
},
|
|
280
307
|
},
|
|
@@ -282,7 +309,7 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
282
309
|
{
|
|
283
310
|
name: "deploy_project",
|
|
284
311
|
description:
|
|
285
|
-
"Deploy an existing project
|
|
312
|
+
"Deploy an existing project. Builds if needed and pushes to production. Always provide a 'message' describing what changed and why (e.g., 'Add user auth', 'Fix CORS bug').",
|
|
286
313
|
inputSchema: {
|
|
287
314
|
type: "object",
|
|
288
315
|
properties: {
|
|
@@ -290,13 +317,18 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
290
317
|
type: "string",
|
|
291
318
|
description: "Path to project directory (defaults to current directory)",
|
|
292
319
|
},
|
|
320
|
+
message: {
|
|
321
|
+
type: "string",
|
|
322
|
+
description:
|
|
323
|
+
"Deploy message describing what changed and why (e.g., 'Add user auth', 'Fix CORS bug')",
|
|
324
|
+
},
|
|
293
325
|
},
|
|
294
326
|
},
|
|
295
327
|
},
|
|
296
328
|
{
|
|
297
329
|
name: "get_project_status",
|
|
298
330
|
description:
|
|
299
|
-
"Get
|
|
331
|
+
"Get live deployment state: URL, last deploy time, deploy count, status (live/failed), and deploy source. Call this first to understand what's currently deployed before making changes.",
|
|
300
332
|
inputSchema: {
|
|
301
333
|
type: "object",
|
|
302
334
|
properties: {
|
|
@@ -347,7 +379,7 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
347
379
|
{
|
|
348
380
|
name: "tail_logs",
|
|
349
381
|
description:
|
|
350
|
-
"Collect
|
|
382
|
+
"Collect live log events from production. Use after deploying to verify changes work, or to debug errors. Returns JSON log entries with timestamps and messages.",
|
|
351
383
|
inputSchema: {
|
|
352
384
|
type: "object",
|
|
353
385
|
properties: {
|
|
@@ -370,6 +402,27 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
370
402
|
},
|
|
371
403
|
},
|
|
372
404
|
},
|
|
405
|
+
{
|
|
406
|
+
name: "rollback_project",
|
|
407
|
+
description:
|
|
408
|
+
"Roll back a managed (jack cloud) project to a previous deployment. " +
|
|
409
|
+
"Defaults to the previous successful deployment if no deployment_id is specified. " +
|
|
410
|
+
"Only rolls back code — database state and secrets are unchanged.",
|
|
411
|
+
inputSchema: {
|
|
412
|
+
type: "object",
|
|
413
|
+
properties: {
|
|
414
|
+
deployment_id: {
|
|
415
|
+
type: "string",
|
|
416
|
+
description:
|
|
417
|
+
"Specific deployment ID to roll back to (defaults to previous successful deployment)",
|
|
418
|
+
},
|
|
419
|
+
project_path: {
|
|
420
|
+
type: "string",
|
|
421
|
+
description: "Path to project directory (defaults to current directory)",
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
},
|
|
373
426
|
{
|
|
374
427
|
name: "create_database",
|
|
375
428
|
description:
|
|
@@ -654,13 +707,14 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
654
707
|
{
|
|
655
708
|
name: "create_cron",
|
|
656
709
|
description:
|
|
657
|
-
"Create a cron schedule for a managed (Jack Cloud) project. Minimum interval is 15 minutes. The worker must
|
|
710
|
+
"Create a cron schedule for a managed (Jack Cloud) project. Minimum interval is 15 minutes. The worker must handle POST /__scheduled requests — Cloudflare's native scheduled() export does not work with Jack Cloud crons.",
|
|
658
711
|
inputSchema: {
|
|
659
712
|
type: "object",
|
|
660
713
|
properties: {
|
|
661
714
|
expression: {
|
|
662
715
|
type: "string",
|
|
663
|
-
description:
|
|
716
|
+
description:
|
|
717
|
+
"Cron expression (e.g., '0 * * * *' for hourly, '*/15 * * * *' for every 15 min)",
|
|
664
718
|
},
|
|
665
719
|
project_path: {
|
|
666
720
|
type: "string",
|
|
@@ -719,7 +773,8 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
719
773
|
trigger_production: {
|
|
720
774
|
type: "boolean",
|
|
721
775
|
default: false,
|
|
722
|
-
description:
|
|
776
|
+
description:
|
|
777
|
+
"Whether to trigger the cron handler on production (requires managed project)",
|
|
723
778
|
},
|
|
724
779
|
},
|
|
725
780
|
required: ["expression"],
|
|
@@ -777,12 +832,13 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
777
832
|
|
|
778
833
|
const wrappedDeployProject = withTelemetry(
|
|
779
834
|
"deploy_project",
|
|
780
|
-
async (projectPath?: string) => {
|
|
835
|
+
async (projectPath?: string, message?: string) => {
|
|
781
836
|
const result = await deployProject({
|
|
782
837
|
projectPath,
|
|
783
838
|
interactive: false,
|
|
784
839
|
includeSecrets: false,
|
|
785
840
|
includeSync: false,
|
|
841
|
+
message,
|
|
786
842
|
});
|
|
787
843
|
|
|
788
844
|
// Track business event
|
|
@@ -795,7 +851,7 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
795
851
|
{ platform: "mcp" },
|
|
796
852
|
);
|
|
797
853
|
|
|
798
|
-
const result = await wrappedDeployProject(args.project_path);
|
|
854
|
+
const result = await wrappedDeployProject(args.project_path, args.message);
|
|
799
855
|
|
|
800
856
|
return {
|
|
801
857
|
content: [
|
|
@@ -1046,6 +1102,60 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
1046
1102
|
};
|
|
1047
1103
|
}
|
|
1048
1104
|
|
|
1105
|
+
case "rollback_project": {
|
|
1106
|
+
const args = RollbackProjectSchema.parse(request.params.arguments ?? {});
|
|
1107
|
+
const projectPath = args.project_path ?? process.cwd();
|
|
1108
|
+
|
|
1109
|
+
const deployMode = await getDeployMode(projectPath);
|
|
1110
|
+
if (deployMode !== "managed") {
|
|
1111
|
+
throw new JackError(
|
|
1112
|
+
JackErrorCode.VALIDATION_ERROR,
|
|
1113
|
+
"Rollback is only available for managed (jack cloud) projects",
|
|
1114
|
+
"For BYOC projects, use wrangler to manage deployments.",
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
const projectId = await getProjectId(projectPath);
|
|
1119
|
+
if (!projectId) {
|
|
1120
|
+
throw new JackError(
|
|
1121
|
+
JackErrorCode.PROJECT_NOT_FOUND,
|
|
1122
|
+
"Project not found",
|
|
1123
|
+
"Run this from a linked jack cloud project directory (has .jack/project.json).",
|
|
1124
|
+
);
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
// Import rollbackDeployment from control-plane
|
|
1128
|
+
const { rollbackDeployment } = await import("../../lib/control-plane.ts");
|
|
1129
|
+
|
|
1130
|
+
const wrappedRollback = withTelemetry(
|
|
1131
|
+
"rollback_project",
|
|
1132
|
+
async (id: string, deploymentId?: string) => rollbackDeployment(id, deploymentId),
|
|
1133
|
+
{ platform: "mcp" },
|
|
1134
|
+
);
|
|
1135
|
+
|
|
1136
|
+
const result = await wrappedRollback(projectId, args.deployment_id);
|
|
1137
|
+
|
|
1138
|
+
return {
|
|
1139
|
+
content: [
|
|
1140
|
+
{
|
|
1141
|
+
type: "text",
|
|
1142
|
+
text: JSON.stringify(
|
|
1143
|
+
formatSuccessResponse(
|
|
1144
|
+
{
|
|
1145
|
+
...result.deployment,
|
|
1146
|
+
message:
|
|
1147
|
+
"Code rolled back successfully. Database state and secrets are unchanged.",
|
|
1148
|
+
},
|
|
1149
|
+
startTime,
|
|
1150
|
+
),
|
|
1151
|
+
null,
|
|
1152
|
+
2,
|
|
1153
|
+
),
|
|
1154
|
+
},
|
|
1155
|
+
],
|
|
1156
|
+
};
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1049
1159
|
case "create_database": {
|
|
1050
1160
|
const args = CreateDatabaseSchema.parse(request.params.arguments ?? {});
|
|
1051
1161
|
const projectPath = args.project_path ?? process.cwd();
|
|
@@ -1268,7 +1378,13 @@ export function registerTools(server: McpServer, _options: McpServerOptions, deb
|
|
|
1268
1378
|
content: [
|
|
1269
1379
|
{
|
|
1270
1380
|
type: "text",
|
|
1271
|
-
text: JSON.stringify(
|
|
1381
|
+
text: JSON.stringify(
|
|
1382
|
+
formatSuccessResponse(result, startTime, [
|
|
1383
|
+
"Vectorize indexes have eventual consistency. Newly inserted vectors typically take 2-3 minutes to become queryable.",
|
|
1384
|
+
]),
|
|
1385
|
+
null,
|
|
1386
|
+
2,
|
|
1387
|
+
),
|
|
1272
1388
|
},
|
|
1273
1389
|
],
|
|
1274
1390
|
};
|
package/src/mcp/types.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
export interface McpToolResponse<T = unknown> {
|
|
6
6
|
success: boolean;
|
|
7
7
|
data?: T;
|
|
8
|
+
notes?: string[]; // Situational context for AI agents (e.g. eventual consistency caveats)
|
|
8
9
|
error?: {
|
|
9
10
|
code: string; // Machine-readable: 'AUTH_FAILED', 'PROJECT_NOT_FOUND'
|
|
10
11
|
message: string; // Human-readable description
|
package/src/mcp/utils.ts
CHANGED
|
@@ -5,10 +5,11 @@ import { McpErrorCode, type McpToolResponse } from "./types.ts";
|
|
|
5
5
|
/**
|
|
6
6
|
* Format a successful MCP tool response
|
|
7
7
|
*/
|
|
8
|
-
export function formatSuccessResponse<T>(data: T, startTime: number): McpToolResponse<T> {
|
|
8
|
+
export function formatSuccessResponse<T>(data: T, startTime: number, notes?: string[]): McpToolResponse<T> {
|
|
9
9
|
return {
|
|
10
10
|
success: true,
|
|
11
11
|
data,
|
|
12
|
+
...(notes?.length && { notes }),
|
|
12
13
|
meta: {
|
|
13
14
|
duration_ms: Date.now() - startTime,
|
|
14
15
|
jack_version: packageJson.version,
|
package/src/templates/index.ts
CHANGED
|
@@ -14,11 +14,15 @@ export const BUILTIN_TEMPLATES = [
|
|
|
14
14
|
"hello",
|
|
15
15
|
"miniapp",
|
|
16
16
|
"api",
|
|
17
|
+
"cron",
|
|
18
|
+
"resend",
|
|
17
19
|
"nextjs",
|
|
18
20
|
"saas",
|
|
19
|
-
"simple-api-starter",
|
|
20
21
|
"ai-chat",
|
|
21
22
|
"semantic-search",
|
|
23
|
+
"nextjs-shadcn",
|
|
24
|
+
"nextjs-clerk",
|
|
25
|
+
"nextjs-auth",
|
|
22
26
|
];
|
|
23
27
|
|
|
24
28
|
/**
|
|
@@ -211,64 +215,32 @@ function extractMetadataFromZip(zipData: ArrayBuffer): Record<string, unknown> {
|
|
|
211
215
|
}
|
|
212
216
|
|
|
213
217
|
/**
|
|
214
|
-
* Fetch a
|
|
218
|
+
* Fetch a remote template (own project or published).
|
|
219
|
+
* Both paths require auth.
|
|
215
220
|
*/
|
|
216
|
-
async function
|
|
217
|
-
const response = await fetch(
|
|
218
|
-
`${getControlApiUrl()}/v1/projects/${encodeURIComponent(username)}/${encodeURIComponent(slug)}/source`,
|
|
219
|
-
);
|
|
220
|
-
|
|
221
|
-
if (!response.ok) {
|
|
222
|
-
if (response.status === 404) {
|
|
223
|
-
throw new Error(
|
|
224
|
-
`Template not found: ${username}/${slug}\n\nMake sure the project exists and is published with: jack publish`,
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
throw new Error(`Failed to fetch template: ${response.status}`);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
const zipData = await response.arrayBuffer();
|
|
231
|
-
const metadata = extractMetadataFromZip(zipData);
|
|
232
|
-
const files = extractZipToFiles(zipData);
|
|
233
|
-
|
|
234
|
-
return {
|
|
235
|
-
description: (metadata.description as string) || `Fork of ${username}/${slug}`,
|
|
236
|
-
secrets: (metadata.secrets as string[]) || [],
|
|
237
|
-
optionalSecrets: metadata.optionalSecrets as Template["optionalSecrets"],
|
|
238
|
-
envVars: metadata.envVars as Template["envVars"],
|
|
239
|
-
capabilities: metadata.capabilities as Template["capabilities"],
|
|
240
|
-
requires: metadata.requires as Template["requires"],
|
|
241
|
-
hooks: metadata.hooks as Template["hooks"],
|
|
242
|
-
agentContext: metadata.agentContext as Template["agentContext"],
|
|
243
|
-
intent: metadata.intent as Template["intent"],
|
|
244
|
-
files,
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Fetch user's own project as a template (authenticated)
|
|
250
|
-
*/
|
|
251
|
-
async function fetchUserTemplate(slug: string): Promise<Template | null> {
|
|
221
|
+
async function fetchRemoteTemplate(identifier: string): Promise<Template | null> {
|
|
252
222
|
const { authFetch } = await import("../lib/auth/index.ts");
|
|
253
223
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
224
|
+
// Route to the correct endpoint based on format
|
|
225
|
+
let url: string;
|
|
226
|
+
if (identifier.includes("/")) {
|
|
227
|
+
const [owner, slug] = identifier.split("/", 2) as [string, string];
|
|
228
|
+
url = `${getControlApiUrl()}/v1/projects/${encodeURIComponent(owner)}/${encodeURIComponent(slug)}/source`;
|
|
229
|
+
} else {
|
|
230
|
+
url = `${getControlApiUrl()}/v1/me/projects/${encodeURIComponent(identifier)}/source`;
|
|
260
231
|
}
|
|
261
232
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
233
|
+
const response = await authFetch(url);
|
|
234
|
+
|
|
235
|
+
if (response.status === 404) return null;
|
|
236
|
+
if (!response.ok) throw new Error(`Failed to fetch template: ${response.status}`);
|
|
265
237
|
|
|
266
238
|
const zipData = await response.arrayBuffer();
|
|
267
239
|
const metadata = extractMetadataFromZip(zipData);
|
|
268
240
|
const files = extractZipToFiles(zipData);
|
|
269
241
|
|
|
270
242
|
return {
|
|
271
|
-
description: (metadata.description as string) || `
|
|
243
|
+
description: (metadata.description as string) || `Fork of ${identifier}`,
|
|
272
244
|
secrets: (metadata.secrets as string[]) || [],
|
|
273
245
|
optionalSecrets: metadata.optionalSecrets as Template["optionalSecrets"],
|
|
274
246
|
envVars: metadata.envVars as Template["envVars"],
|
|
@@ -285,33 +257,13 @@ async function fetchUserTemplate(slug: string): Promise<Template | null> {
|
|
|
285
257
|
* Resolve template by name
|
|
286
258
|
*/
|
|
287
259
|
export async function resolveTemplate(template?: string): Promise<Template> {
|
|
288
|
-
|
|
289
|
-
if (
|
|
290
|
-
return loadTemplate("hello");
|
|
291
|
-
}
|
|
260
|
+
if (!template) return loadTemplate("hello");
|
|
261
|
+
if (BUILTIN_TEMPLATES.includes(template)) return loadTemplate(template);
|
|
292
262
|
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// username/slug format - fetch from jack cloud
|
|
299
|
-
if (template.includes("/")) {
|
|
300
|
-
const [username, slug] = template.split("/", 2) as [string, string];
|
|
301
|
-
return fetchPublishedTemplate(username, slug);
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// Try as user's own project first
|
|
305
|
-
try {
|
|
306
|
-
const userTemplate = await fetchUserTemplate(template);
|
|
307
|
-
if (userTemplate) {
|
|
308
|
-
return userTemplate;
|
|
309
|
-
}
|
|
310
|
-
} catch (_err) {
|
|
311
|
-
// If auth fails or project not found, fall through to error
|
|
312
|
-
}
|
|
263
|
+
// Remote: "username/slug" or "my-own-project"
|
|
264
|
+
const result = await fetchRemoteTemplate(template);
|
|
265
|
+
if (result) return result;
|
|
313
266
|
|
|
314
|
-
// Unknown template
|
|
315
267
|
throw new Error(
|
|
316
268
|
`Unknown template: ${template}\n\nAvailable built-in templates: ${BUILTIN_TEMPLATES.join(", ")}\nOr use username/slug format for published projects`,
|
|
317
269
|
);
|
package/templates/CLAUDE.md
CHANGED
|
@@ -114,6 +114,27 @@ Before shipping a new template:
|
|
|
114
114
|
- [ ] Install time < 5s (cold cache + lockfile)
|
|
115
115
|
- [ ] All scripts work without global tools except wrangler
|
|
116
116
|
- [ ] `.gitignore` includes `.env`, `.dev.vars`, `.secrets.json`
|
|
117
|
+
- [ ] Prebuilt builds without env vars: `bun run build` succeeds with zero secrets set
|
|
118
|
+
- [ ] If template has `schema.sql`, verify it's included in prebuild output
|
|
119
|
+
|
|
120
|
+
## Prebuild Compatibility (IMPORTANT)
|
|
121
|
+
|
|
122
|
+
Templates are prebuilt at release time **without any env vars or secrets**. The prebuild runs `bun run build` in a clean environment. If the build depends on runtime env vars, it will fail silently (only discovered when someone runs `prebuild-templates.ts`).
|
|
123
|
+
|
|
124
|
+
**Common failure:** A provider component (e.g., `ClerkProvider`, `AuthProvider`) in the root layout requires an API key at import time. Next.js tries to statically prerender pages and the provider throws because the key is missing.
|
|
125
|
+
|
|
126
|
+
**Fix:** Add `export const dynamic = "force-dynamic"` to the root layout. This tells Next.js to skip static prerendering for all pages, deferring to runtime where env vars are available.
|
|
127
|
+
|
|
128
|
+
```tsx
|
|
129
|
+
// app/layout.tsx
|
|
130
|
+
export const dynamic = "force-dynamic"; // Required: provider needs runtime env vars
|
|
131
|
+
|
|
132
|
+
export default function RootLayout({ children }) {
|
|
133
|
+
return <SomeProvider>{children}</SomeProvider>;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**General rule:** If a template imports any SDK/provider that reads `process.env` or `env.*` at initialization, that template's layout or pages must be force-dynamic to survive a zero-env-var prebuild.
|
|
117
138
|
|
|
118
139
|
## Placeholder System
|
|
119
140
|
|
|
@@ -568,6 +589,47 @@ if (!baseUrl) {
|
|
|
568
589
|
|
|
569
590
|
The Host header approach is reliable because Cloudflare always sets it to the actual domain being accessed.
|
|
570
591
|
|
|
592
|
+
## OpenNext (Next.js on Cloudflare) Gotchas
|
|
593
|
+
|
|
594
|
+
Templates using Next.js via `@opennextjs/cloudflare` have platform-specific limitations. These apply to all Next.js templates (`nextjs-auth`, `nextjs-shadcn`, `nextjs-clerk`, etc.).
|
|
595
|
+
|
|
596
|
+
### Client-side navigation after auth state changes: use window.location, not router.push
|
|
597
|
+
|
|
598
|
+
OpenNext's webpack runtime has an empty chunk URL resolver (`r.u=e=>{}`). This means `router.push()` to a page whose chunks aren't already loaded fails with `ChunkLoadError: Loading chunk X failed`.
|
|
599
|
+
|
|
600
|
+
**Rule:** After any auth state change (sign-in, sign-up, sign-out), always use `window.location.href` for a full page reload. This ensures middleware, server components, and cookies re-evaluate with the new session.
|
|
601
|
+
|
|
602
|
+
```tsx
|
|
603
|
+
// BAD — ChunkLoadError on OpenNext
|
|
604
|
+
await authClient.signOut();
|
|
605
|
+
router.push("/");
|
|
606
|
+
router.refresh();
|
|
607
|
+
|
|
608
|
+
// GOOD — full reload, clean auth state
|
|
609
|
+
await authClient.signOut();
|
|
610
|
+
window.location.href = "/";
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
`<Link>` components work fine for normal navigation because Next.js prefetches their chunks via `<script>` tags in the HTML.
|
|
614
|
+
|
|
615
|
+
### Pages using getCloudflareContext() need `export const dynamic = 'force-dynamic'`
|
|
616
|
+
|
|
617
|
+
Without this, Next.js tries to statically prerender the page at build time, which fails because `getCloudflareContext()` is only available at runtime in the Workers environment.
|
|
618
|
+
|
|
619
|
+
```tsx
|
|
620
|
+
import { getAuth } from "@/lib/auth";
|
|
621
|
+
export const dynamic = "force-dynamic";
|
|
622
|
+
|
|
623
|
+
export default async function DashboardPage() {
|
|
624
|
+
const auth = await getAuth(); // calls getCloudflareContext() internally
|
|
625
|
+
// ...
|
|
626
|
+
}
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
### Edge middleware cannot use Node.js APIs
|
|
630
|
+
|
|
631
|
+
Next.js middleware runs in the edge runtime. Don't call `auth.api.getSession()` (requires `perf_hooks`) — use cookie-only checks instead.
|
|
632
|
+
|
|
571
633
|
## Adding New Templates
|
|
572
634
|
|
|
573
635
|
1. Create directory: `templates/my-template/`
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-chat",
|
|
3
|
-
"description": "AI chat with streaming
|
|
3
|
+
"description": "AI chat with streaming, persistence, and multi-model support",
|
|
4
4
|
"secrets": [],
|
|
5
|
-
"capabilities": ["ai"],
|
|
5
|
+
"capabilities": ["ai", "db"],
|
|
6
|
+
"requires": ["DB"],
|
|
6
7
|
"intent": {
|
|
7
|
-
"keywords": ["ai", "chat", "llm", "llama", "completion", "chatbot"],
|
|
8
|
-
"examples": ["AI chatbot", "chat interface", "LLM chat app"]
|
|
8
|
+
"keywords": ["ai", "chat", "llm", "llama", "completion", "chatbot", "streaming"],
|
|
9
|
+
"examples": ["AI chatbot", "chat interface", "LLM chat app", "persistent chat"]
|
|
10
|
+
},
|
|
11
|
+
"agentContext": {
|
|
12
|
+
"summary": "An AI chat app with streaming UI, D1 chat persistence, and multi-model support via AI SDK.",
|
|
13
|
+
"full_text": "## Project Structure\n\n- `src/index.ts` - Hono API with chat endpoints and AI SDK integration\n- `src/jack-ai.ts` - Jack AI proxy wrapper (do not modify)\n- `public/index.html` - React app shell\n- `public/app.js` - Chat UI with useChat hook from AI SDK\n- `schema.sql` - D1 schema for chat and message persistence\n\n## AI Integration\n\nUses AI SDK with `workers-ai-provider` routed through Jack's metered AI proxy.\n\n### Changing Models\n\nEdit the model string in `src/index.ts`:\n```typescript\nmodel: provider('@cf/meta/llama-3.3-70b-instruct-fp8-fast')\n```\n\nAvailable models: https://developers.cloudflare.com/workers-ai/models/\n\n## Chat Persistence\n\nChats and messages are stored in D1:\n- `chats` table: chat metadata (id, created_at)\n- `messages` table: individual messages (role, content, chat_id)\n\nMessages persist across page refreshes. Each browser session creates a new chat.\n\n## API Endpoints\n\n- `POST /api/chat` - Send message and get streaming AI response\n- `GET /api/chat/:id` - Load chat history\n- `POST /api/chat/new` - Create a new chat\n\n## Resources\n\n- [AI SDK Docs](https://sdk.vercel.ai/docs)\n- [Workers AI Models](https://developers.cloudflare.com/workers-ai/models)"
|
|
9
14
|
},
|
|
10
15
|
"hooks": {
|
|
11
16
|
"postDeploy": [
|
|
@@ -17,7 +22,7 @@
|
|
|
17
22
|
{
|
|
18
23
|
"action": "box",
|
|
19
24
|
"title": "{{name}}",
|
|
20
|
-
"lines": ["{{url}}", "", "jack open to
|
|
25
|
+
"lines": ["{{url}}", "", "Chat history saved to D1.", "jack open to start chatting"]
|
|
21
26
|
}
|
|
22
27
|
]
|
|
23
28
|
}
|
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
"workspaces": {
|
|
5
5
|
"": {
|
|
6
6
|
"name": "jack-template",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"ai": "^4",
|
|
9
|
+
"hono": "^4.6.0",
|
|
10
|
+
"workers-ai-provider": "^0.7",
|
|
11
|
+
},
|
|
7
12
|
"devDependencies": {
|
|
8
13
|
"@cloudflare/workers-types": "^4.20241205.0",
|
|
9
14
|
"typescript": "^5.0.0",
|
|
@@ -11,8 +16,52 @@
|
|
|
11
16
|
},
|
|
12
17
|
},
|
|
13
18
|
"packages": {
|
|
14
|
-
"@
|
|
19
|
+
"@ai-sdk/provider": ["@ai-sdk/provider@1.1.3", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg=="],
|
|
20
|
+
|
|
21
|
+
"@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@2.2.8", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "nanoid": "^3.3.8", "secure-json-parse": "^2.7.0" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA=="],
|
|
22
|
+
|
|
23
|
+
"@ai-sdk/react": ["@ai-sdk/react@1.2.12", "", { "dependencies": { "@ai-sdk/provider-utils": "2.2.8", "@ai-sdk/ui-utils": "1.2.11", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.23.8" }, "optionalPeers": ["zod"] }, "sha512-jK1IZZ22evPZoQW3vlkZ7wvjYGYF+tRBKXtrcolduIkQ/m/sOAVcVeVDUDvh1T91xCnWCdUGCPZg2avZ90mv3g=="],
|
|
24
|
+
|
|
25
|
+
"@ai-sdk/ui-utils": ["@ai-sdk/ui-utils@1.2.11", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "zod-to-json-schema": "^3.24.1" }, "peerDependencies": { "zod": "^3.23.8" } }, "sha512-3zcwCc8ezzFlwp3ZD15wAPjf2Au4s3vAbKsXQVyhxODHcmu0iyPO2Eua6D/vicq/AUm/BAo60r97O6HU+EI0+w=="],
|
|
26
|
+
|
|
27
|
+
"@cloudflare/workers-types": ["@cloudflare/workers-types@4.20260212.0", "", {}, "sha512-ZK+e8T/2tWBCrE8PoAi9oqTxcBen9Apq+dxbsy1R5LFVdB6M4pY+oP49OFuHTTezrvNXbyvmzbf/vjtrCPGdNg=="],
|
|
28
|
+
|
|
29
|
+
"@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="],
|
|
30
|
+
|
|
31
|
+
"@types/diff-match-patch": ["@types/diff-match-patch@1.0.36", "", {}, "sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg=="],
|
|
32
|
+
|
|
33
|
+
"ai": ["ai@4.3.19", "", { "dependencies": { "@ai-sdk/provider": "1.1.3", "@ai-sdk/provider-utils": "2.2.8", "@ai-sdk/react": "1.2.12", "@ai-sdk/ui-utils": "1.2.11", "@opentelemetry/api": "1.9.0", "jsondiffpatch": "0.6.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.23.8" }, "optionalPeers": ["react"] }, "sha512-dIE2bfNpqHN3r6IINp9znguYdhIOheKW2LDigAMrgt/upT3B8eBGPSCblENvaZGoq+hxaN9fSMzjWpbqloP+7Q=="],
|
|
34
|
+
|
|
35
|
+
"chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
|
|
36
|
+
|
|
37
|
+
"dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
|
|
38
|
+
|
|
39
|
+
"diff-match-patch": ["diff-match-patch@1.0.5", "", {}, "sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw=="],
|
|
40
|
+
|
|
41
|
+
"hono": ["hono@4.11.9", "", {}, "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ=="],
|
|
42
|
+
|
|
43
|
+
"json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
|
|
44
|
+
|
|
45
|
+
"jsondiffpatch": ["jsondiffpatch@0.6.0", "", { "dependencies": { "@types/diff-match-patch": "^1.0.36", "chalk": "^5.3.0", "diff-match-patch": "^1.0.5" }, "bin": { "jsondiffpatch": "bin/jsondiffpatch.js" } }, "sha512-3QItJOXp2AP1uv7waBkao5nCvhEv+QmJAd38Ybq7wNI74Q+BBmnLn4EDKz6yI9xGAIQoUF87qHt+kc1IVxB4zQ=="],
|
|
46
|
+
|
|
47
|
+
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
|
|
48
|
+
|
|
49
|
+
"react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
|
|
50
|
+
|
|
51
|
+
"secure-json-parse": ["secure-json-parse@2.7.0", "", {}, "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="],
|
|
52
|
+
|
|
53
|
+
"swr": ["swr@2.4.0", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-sUlC20T8EOt1pHmDiqueUWMmRRX03W7w5YxovWX7VR2KHEPCTMly85x05vpkP5i6Bu4h44ePSMD9Tc+G2MItFw=="],
|
|
54
|
+
|
|
55
|
+
"throttleit": ["throttleit@2.1.0", "", {}, "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw=="],
|
|
15
56
|
|
|
16
57
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
|
58
|
+
|
|
59
|
+
"use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
|
|
60
|
+
|
|
61
|
+
"workers-ai-provider": ["workers-ai-provider@0.7.5", "", { "dependencies": { "@ai-sdk/provider": "^1.1.3", "@ai-sdk/provider-utils": "^2.2.8" } }, "sha512-dhCwgc3D65oDDTpH3k8Gf0Ek7KItzvaQidn2N5L5cqLo3WG8GM/4+Nr4rU56o8O3oZRsloB1gUCHYaRv2j7Y0A=="],
|
|
62
|
+
|
|
63
|
+
"zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
|
|
64
|
+
|
|
65
|
+
"zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
|
|
17
66
|
}
|
|
18
67
|
}
|