@getjack/jack 0.1.28 → 0.1.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/package.json +1 -1
  2. package/src/commands/cd.ts +163 -0
  3. package/src/commands/clone.ts +112 -68
  4. package/src/commands/domain.ts +506 -0
  5. package/src/commands/domains.ts +215 -0
  6. package/src/commands/down.ts +18 -12
  7. package/src/commands/hack.ts +185 -8
  8. package/src/commands/init.ts +52 -1
  9. package/src/commands/link.ts +25 -43
  10. package/src/commands/logs.ts +2 -2
  11. package/src/commands/mcp.ts +74 -3
  12. package/src/commands/new.ts +48 -54
  13. package/src/commands/projects.ts +53 -10
  14. package/src/commands/secrets.ts +5 -1
  15. package/src/commands/services.ts +16 -4
  16. package/src/commands/shell-init.ts +43 -0
  17. package/src/commands/ship.ts +2 -11
  18. package/src/commands/skills.ts +335 -0
  19. package/src/commands/update.ts +31 -0
  20. package/src/commands/upgrade.ts +14 -0
  21. package/src/index.ts +116 -24
  22. package/src/lib/agent-integration.ts +1 -2
  23. package/src/lib/agents.ts +2 -2
  24. package/src/lib/auth/login-flow.ts +1 -1
  25. package/src/lib/clone-core.ts +252 -0
  26. package/src/lib/config.ts +22 -0
  27. package/src/lib/control-plane.ts +31 -5
  28. package/src/lib/fuzzy.ts +93 -0
  29. package/src/lib/managed-deploy.ts +4 -1
  30. package/src/lib/managed-down.ts +20 -5
  31. package/src/lib/output.ts +90 -9
  32. package/src/lib/picker.ts +406 -0
  33. package/src/lib/project-detection.ts +5 -2
  34. package/src/lib/project-list.ts +66 -5
  35. package/src/lib/project-operations.ts +68 -6
  36. package/src/lib/prompts.ts +1 -1
  37. package/src/lib/services/db-execute.ts +8 -1
  38. package/src/lib/services/db-list.ts +4 -1
  39. package/src/lib/services/domain-operations.ts +379 -0
  40. package/src/lib/services/storage-config.ts +1 -5
  41. package/src/lib/services/storage-delete.ts +1 -1
  42. package/src/lib/services/storage-info.ts +2 -4
  43. package/src/lib/services/vectorize-config.ts +1 -5
  44. package/src/lib/services/vectorize-create.ts +3 -1
  45. package/src/lib/shell-integration.ts +202 -0
  46. package/src/lib/telemetry-config.ts +50 -4
  47. package/src/lib/telemetry.ts +71 -2
  48. package/src/lib/version-check.ts +1 -3
  49. package/src/lib/wrangler-config.test.ts +2 -2
  50. package/src/lib/wrangler-config.ts +1 -1
  51. package/src/lib/zip-packager.ts +1 -3
  52. package/src/mcp/tools/index.ts +261 -7
  53. package/src/templates/index.ts +10 -1
  54. package/templates/ai-chat/.jack.json +1 -5
  55. package/templates/ai-chat/public/chat.js +130 -130
  56. package/templates/ai-chat/src/index.ts +9 -13
  57. package/templates/ai-chat/src/jack-ai.ts +6 -2
  58. package/templates/saas/.jack.json +6 -1
  59. package/templates/saas/src/auth.ts +8 -4
  60. package/templates/saas/src/client/App.tsx +22 -7
  61. package/templates/saas/src/client/components/ProtectedRoute.tsx +9 -2
  62. package/templates/saas/src/client/components/ThemeToggle.tsx +1 -6
  63. package/templates/saas/src/client/components/ui/accordion.tsx +1 -1
  64. package/templates/saas/src/client/components/ui/alert-dialog.tsx +2 -2
  65. package/templates/saas/src/client/components/ui/alert.tsx +2 -2
  66. package/templates/saas/src/client/components/ui/avatar.tsx +1 -1
  67. package/templates/saas/src/client/components/ui/badge.tsx +2 -2
  68. package/templates/saas/src/client/components/ui/breadcrumb.tsx +1 -1
  69. package/templates/saas/src/client/components/ui/button-group.tsx +2 -2
  70. package/templates/saas/src/client/components/ui/button.tsx +2 -2
  71. package/templates/saas/src/client/components/ui/card.tsx +1 -1
  72. package/templates/saas/src/client/components/ui/carousel.tsx +2 -2
  73. package/templates/saas/src/client/components/ui/checkbox.tsx +1 -1
  74. package/templates/saas/src/client/components/ui/command.tsx +2 -2
  75. package/templates/saas/src/client/components/ui/context-menu.tsx +1 -1
  76. package/templates/saas/src/client/components/ui/dialog.tsx +1 -1
  77. package/templates/saas/src/client/components/ui/drawer.tsx +1 -1
  78. package/templates/saas/src/client/components/ui/dropdown-menu.tsx +1 -1
  79. package/templates/saas/src/client/components/ui/empty.tsx +1 -1
  80. package/templates/saas/src/client/components/ui/field.tsx +2 -2
  81. package/templates/saas/src/client/components/ui/form.tsx +5 -5
  82. package/templates/saas/src/client/components/ui/hover-card.tsx +1 -1
  83. package/templates/saas/src/client/components/ui/input-group.tsx +3 -3
  84. package/templates/saas/src/client/components/ui/input-otp.tsx +1 -1
  85. package/templates/saas/src/client/components/ui/input.tsx +1 -1
  86. package/templates/saas/src/client/components/ui/item.tsx +3 -3
  87. package/templates/saas/src/client/components/ui/label.tsx +1 -1
  88. package/templates/saas/src/client/components/ui/menubar.tsx +1 -1
  89. package/templates/saas/src/client/components/ui/navigation-menu.tsx +1 -1
  90. package/templates/saas/src/client/components/ui/pagination.tsx +2 -2
  91. package/templates/saas/src/client/components/ui/popover.tsx +1 -1
  92. package/templates/saas/src/client/components/ui/progress.tsx +1 -1
  93. package/templates/saas/src/client/components/ui/radio-group.tsx +1 -1
  94. package/templates/saas/src/client/components/ui/resizable.tsx +1 -1
  95. package/templates/saas/src/client/components/ui/scroll-area.tsx +1 -1
  96. package/templates/saas/src/client/components/ui/select.tsx +1 -1
  97. package/templates/saas/src/client/components/ui/separator.tsx +1 -1
  98. package/templates/saas/src/client/components/ui/sheet.tsx +1 -1
  99. package/templates/saas/src/client/components/ui/sidebar.tsx +4 -4
  100. package/templates/saas/src/client/components/ui/slider.tsx +1 -1
  101. package/templates/saas/src/client/components/ui/switch.tsx +1 -1
  102. package/templates/saas/src/client/components/ui/table.tsx +1 -1
  103. package/templates/saas/src/client/components/ui/tabs.tsx +1 -1
  104. package/templates/saas/src/client/components/ui/textarea.tsx +1 -1
  105. package/templates/saas/src/client/components/ui/toggle-group.tsx +3 -3
  106. package/templates/saas/src/client/components/ui/toggle.tsx +2 -2
  107. package/templates/saas/src/client/components/ui/tooltip.tsx +1 -1
  108. package/templates/saas/src/client/hooks/useSubscription.ts +5 -4
  109. package/templates/saas/src/client/lib/auth-client.ts +1 -1
  110. package/templates/saas/src/client/lib/plans.ts +1 -6
  111. package/templates/saas/src/client/lib/utils.ts +1 -1
  112. package/templates/saas/src/client/main.tsx +1 -1
  113. package/templates/saas/src/client/pages/DashboardPage.tsx +41 -9
  114. package/templates/saas/src/client/pages/ForgotPasswordPage.tsx +11 -2
  115. package/templates/saas/src/client/pages/HomePage.tsx +11 -2
  116. package/templates/saas/src/client/pages/LoginPage.tsx +11 -2
  117. package/templates/saas/src/client/pages/PricingPage.tsx +20 -10
  118. package/templates/saas/src/client/pages/ResetPasswordPage.tsx +14 -11
  119. package/templates/saas/src/client/pages/SignupPage.tsx +11 -2
  120. package/templates/saas/src/index.ts +28 -19
  121. package/templates/saas/vite.config.ts +1 -1
  122. package/templates/semantic-search/.jack.json +1 -5
  123. package/templates/semantic-search/src/index.ts +8 -4
  124. package/templates/semantic-search/src/jack-ai.ts +6 -2
  125. package/templates/semantic-search/src/jack-vectorize.ts +5 -1
@@ -1,11 +1,20 @@
1
- import { useState, useEffect } from "react";
2
- import { authClient } from "../lib/auth-client";
1
+ import { useEffect, useState } from "react";
3
2
  import { toast } from "sonner";
4
3
  import { ThemeToggle } from "../components/ThemeToggle";
5
4
  import { Button } from "../components/ui/button";
5
+ import { authClient } from "../lib/auth-client";
6
6
 
7
7
  interface ResetPasswordPageProps {
8
- navigate: (route: "/" | "/login" | "/signup" | "/pricing" | "/dashboard" | "/forgot-password" | "/reset-password") => void;
8
+ navigate: (
9
+ route:
10
+ | "/"
11
+ | "/login"
12
+ | "/signup"
13
+ | "/pricing"
14
+ | "/dashboard"
15
+ | "/forgot-password"
16
+ | "/reset-password",
17
+ ) => void;
9
18
  }
10
19
 
11
20
  export default function ResetPasswordPage({ navigate }: ResetPasswordPageProps) {
@@ -92,9 +101,7 @@ export default function ResetPasswordPage({ navigate }: ResetPasswordPageProps)
92
101
  <p className="text-muted-foreground mb-6">
93
102
  This password reset link is invalid or has expired. Please request a new one.
94
103
  </p>
95
- <Button onClick={() => navigate("/forgot-password")}>
96
- Request new reset link
97
- </Button>
104
+ <Button onClick={() => navigate("/forgot-password")}>Request new reset link</Button>
98
105
  </div>
99
106
  </div>
100
107
  </div>
@@ -167,11 +174,7 @@ export default function ResetPasswordPage({ navigate }: ResetPasswordPageProps)
167
174
  <Button type="submit" className="w-full" disabled={isLoading}>
168
175
  {isLoading ? (
169
176
  <>
170
- <svg
171
- className="animate-spin -ml-1 mr-2 h-4 w-4"
172
- fill="none"
173
- viewBox="0 0 24 24"
174
- >
177
+ <svg className="animate-spin -ml-1 mr-2 h-4 w-4" fill="none" viewBox="0 0 24 24">
175
178
  <circle
176
179
  className="opacity-25"
177
180
  cx="12"
@@ -1,9 +1,18 @@
1
1
  import { useState } from "react";
2
- import { authClient } from "../lib/auth-client";
3
2
  import { ThemeToggle } from "../components/ThemeToggle";
3
+ import { authClient } from "../lib/auth-client";
4
4
 
5
5
  interface SignupPageProps {
6
- navigate: (route: "/" | "/login" | "/signup" | "/pricing" | "/dashboard" | "/forgot-password" | "/reset-password") => void;
6
+ navigate: (
7
+ route:
8
+ | "/"
9
+ | "/login"
10
+ | "/signup"
11
+ | "/pricing"
12
+ | "/dashboard"
13
+ | "/forgot-password"
14
+ | "/reset-password",
15
+ ) => void;
7
16
  }
8
17
 
9
18
  export default function SignupPage({ navigate }: SignupPageProps) {
@@ -75,21 +75,23 @@ app.get("/api/subscription-status", async (c) => {
75
75
  // Get subscriptions for this customer (active or scheduled to cancel)
76
76
  const subscriptions = await stripeClient.subscriptions.list({
77
77
  customer: customers.data[0].id,
78
- limit: 10, // Get more to find the right one
79
- expand: ["data.default_payment_method"], // Force fresh data
78
+ limit: 10, // Get more to find the right one
79
+ expand: ["data.default_payment_method"], // Force fresh data
80
80
  });
81
81
 
82
82
  // Find active or trialing subscription (even if set to cancel at period end)
83
- const sub = subscriptions.data.find(
84
- (s) => s.status === "active" || s.status === "trialing"
85
- );
83
+ const sub = subscriptions.data.find((s) => s.status === "active" || s.status === "trialing");
86
84
 
87
85
  if (!sub) {
88
- console.log(`[subscription-status] No active subscriptions for customer: ${customers.data[0].id}`);
86
+ console.log(
87
+ `[subscription-status] No active subscriptions for customer: ${customers.data[0].id}`,
88
+ );
89
89
  return c.json({ subscription: null });
90
90
  }
91
91
 
92
- console.log(`[subscription-status] Found: id=${sub.id}, status=${sub.status}, cancel_at_period_end=${sub.cancel_at_period_end}`);
92
+ console.log(
93
+ `[subscription-status] Found: id=${sub.id}, status=${sub.status}, cancel_at_period_end=${sub.cancel_at_period_end}`,
94
+ );
93
95
 
94
96
  return c.json({
95
97
  subscription: {
@@ -104,10 +106,13 @@ app.get("/api/subscription-status", async (c) => {
104
106
  });
105
107
  } catch (err) {
106
108
  console.error("[subscription-status] Error:", err);
107
- return c.json({
108
- error: "Failed to fetch subscription status",
109
- details: err instanceof Error ? err.message : String(err)
110
- }, 500);
109
+ return c.json(
110
+ {
111
+ error: "Failed to fetch subscription status",
112
+ details: err instanceof Error ? err.message : String(err),
113
+ },
114
+ 500,
115
+ );
111
116
  }
112
117
  });
113
118
 
@@ -154,17 +159,20 @@ app.post("/api/resubscribe", async (c) => {
154
159
  }
155
160
 
156
161
  // Also clear the local cancelAt in Better Auth's database
157
- await c.env.DB.prepare(
158
- "UPDATE subscription SET cancelAt = NULL WHERE stripeSubscriptionId = ?"
159
- ).bind(sub.id).run();
162
+ await c.env.DB.prepare("UPDATE subscription SET cancelAt = NULL WHERE stripeSubscriptionId = ?")
163
+ .bind(sub.id)
164
+ .run();
160
165
 
161
166
  return c.json({ success: true });
162
167
  } catch (err) {
163
168
  console.error("[resubscribe] Error:", err);
164
- return c.json({
165
- error: "Failed to resubscribe",
166
- details: err instanceof Error ? err.message : String(err),
167
- }, 500);
169
+ return c.json(
170
+ {
171
+ error: "Failed to resubscribe",
172
+ details: err instanceof Error ? err.message : String(err),
173
+ },
174
+ 500,
175
+ );
168
176
  }
169
177
  });
170
178
 
@@ -190,7 +198,8 @@ app.get("/api/billing-portal", async (c) => {
190
198
  return c.json({ error: "No billing account found" }, 404);
191
199
  }
192
200
 
193
- const returnUrl = c.req.header("origin") || c.req.header("referer") || c.env.BETTER_AUTH_URL || "/";
201
+ const returnUrl =
202
+ c.req.header("origin") || c.req.header("referer") || c.env.BETTER_AUTH_URL || "/";
194
203
 
195
204
  const portalSession = await stripeClient.billingPortal.sessions.create({
196
205
  customer: customers.data[0].id,
@@ -1,7 +1,7 @@
1
+ import { resolve } from "node:path";
1
2
  import { cloudflare } from "@cloudflare/vite-plugin";
2
3
  import tailwindcss from "@tailwindcss/vite";
3
4
  import react from "@vitejs/plugin-react";
4
- import { resolve } from "node:path";
5
5
  import { defineConfig } from "vite";
6
6
 
7
7
  export default defineConfig({
@@ -14,11 +14,7 @@
14
14
  {
15
15
  "action": "box",
16
16
  "title": "{{name}}",
17
- "lines": [
18
- "{{url}}",
19
- "",
20
- "jack open to view in browser"
21
- ]
17
+ "lines": ["{{url}}", "", "jack open to view in browser"]
22
18
  }
23
19
  ]
24
20
  }
@@ -1,5 +1,5 @@
1
- import { createJackAI, type JackAI } from "./jack-ai";
2
- import { createJackVectorize, type JackVectorize } from "./jack-vectorize";
1
+ import { type JackAI, createJackAI } from "./jack-ai";
2
+ import { type JackVectorize, createJackVectorize } from "./jack-vectorize";
3
3
 
4
4
  interface Env {
5
5
  // Direct bindings (for local dev with wrangler)
@@ -26,7 +26,9 @@ type AIClient = {
26
26
  function getAI(env: Env): AIClient {
27
27
  // Prefer jack cloud proxy if available (for metering)
28
28
  if (env.__AI_PROXY && env.__JACK_PROJECT_ID && env.__JACK_ORG_ID) {
29
- return createJackAI(env as Required<Pick<Env, "__AI_PROXY" | "__JACK_PROJECT_ID" | "__JACK_ORG_ID">>) as AIClient;
29
+ return createJackAI(
30
+ env as Required<Pick<Env, "__AI_PROXY" | "__JACK_PROJECT_ID" | "__JACK_ORG_ID">>,
31
+ ) as AIClient;
30
32
  }
31
33
  // Fallback to direct binding for local dev
32
34
  if (env.AI) {
@@ -37,7 +39,9 @@ function getAI(env: Env): AIClient {
37
39
 
38
40
  // Minimal Vectorize interface
39
41
  type VectorizeClient = {
40
- insert: (vectors: { id: string; values: number[]; metadata?: Record<string, unknown> }[]) => Promise<unknown>;
42
+ insert: (
43
+ vectors: { id: string; values: number[]; metadata?: Record<string, unknown> }[],
44
+ ) => Promise<unknown>;
41
45
  query: (
42
46
  vector: number[],
43
47
  options?: { topK?: number; returnMetadata?: "none" | "indexed" | "all" },
@@ -65,9 +65,13 @@ export function createJackAI(env: JackAIEnv): {
65
65
  // Handle quota exceeded
66
66
  if (response.status === 429) {
67
67
  const error = await response.json();
68
- const quotaError = new Error((error as { message?: string }).message || "AI quota exceeded");
68
+ const quotaError = new Error(
69
+ (error as { message?: string }).message || "AI quota exceeded",
70
+ );
69
71
  (quotaError as Error & { code: string }).code = "AI_QUOTA_EXCEEDED";
70
- (quotaError as Error & { resetIn?: number }).resetIn = (error as { resetIn?: number }).resetIn;
72
+ (quotaError as Error & { resetIn?: number }).resetIn = (
73
+ error as { resetIn?: number }
74
+ ).resetIn;
71
75
  throw quotaError;
72
76
  }
73
77
 
@@ -106,7 +106,11 @@ export function createJackVectorize(
106
106
 
107
107
  // Handle quota exceeded
108
108
  if (response.status === 429) {
109
- const error = (await response.json()) as { message?: string; code?: string; resetIn?: number };
109
+ const error = (await response.json()) as {
110
+ message?: string;
111
+ code?: string;
112
+ resetIn?: number;
113
+ };
110
114
  const quotaError = new Error(error.message || "Vectorize quota exceeded");
111
115
  (quotaError as Error & { code: string }).code = error.code || "VECTORIZE_QUOTA_EXCEEDED";
112
116
  (quotaError as Error & { resetIn?: number }).resetIn = error.resetIn;