jettypod 4.4.118 → 4.4.121
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/.env +4 -3
- package/Cargo.lock +6450 -0
- package/Cargo.toml +35 -0
- package/README.md +5 -1
- package/TAURI-MIGRATION-PLAN.md +840 -0
- package/apps/dashboard/app/connect-claude/page.tsx +5 -6
- package/apps/dashboard/app/decision/[id]/page.tsx +63 -58
- package/apps/dashboard/app/demo/gates/page.tsx +43 -45
- package/apps/dashboard/app/design-system/page.tsx +868 -0
- package/apps/dashboard/app/globals.css +80 -4
- package/apps/dashboard/app/install-claude/page.tsx +4 -6
- package/apps/dashboard/app/login/page.tsx +72 -54
- package/apps/dashboard/app/page.tsx +101 -48
- package/apps/dashboard/app/settings/page.tsx +61 -13
- package/apps/dashboard/app/signup/page.tsx +242 -0
- package/apps/dashboard/app/subscribe/page.tsx +0 -2
- package/apps/dashboard/app/tests/page.tsx +37 -4
- package/apps/dashboard/app/welcome/page.tsx +13 -16
- package/apps/dashboard/app/work/[id]/page.tsx +117 -118
- package/apps/dashboard/app/work/[id]/proof/page.tsx +1489 -0
- package/apps/dashboard/components/AppShell.tsx +92 -85
- package/apps/dashboard/components/CardMenu.tsx +45 -12
- package/apps/dashboard/components/ClaudePanel.tsx +771 -850
- package/apps/dashboard/components/ClaudePanelInput.tsx +43 -15
- package/apps/dashboard/components/ConnectClaudeScreen.tsx +17 -34
- package/apps/dashboard/components/CopyableId.tsx +3 -4
- package/apps/dashboard/components/DetailReviewActions.tsx +100 -0
- package/apps/dashboard/components/DragContext.tsx +134 -63
- package/apps/dashboard/components/DraggableCard.tsx +3 -5
- package/apps/dashboard/components/DropZone.tsx +6 -7
- package/apps/dashboard/components/EditableDetailDescription.tsx +7 -13
- package/apps/dashboard/components/EditableDetailTitle.tsx +6 -13
- package/apps/dashboard/components/EditableTitle.tsx +26 -7
- package/apps/dashboard/components/ElapsedTimer.tsx +66 -0
- package/apps/dashboard/components/EpicGroup.tsx +359 -0
- package/apps/dashboard/components/GateCard.tsx +79 -17
- package/apps/dashboard/components/GateChoiceCard.tsx +15 -18
- package/apps/dashboard/components/InstallClaudeScreen.tsx +15 -32
- package/apps/dashboard/components/JettyLoader.tsx +37 -0
- package/apps/dashboard/components/KanbanBoard.tsx +368 -958
- package/apps/dashboard/components/KanbanCard.tsx +740 -0
- package/apps/dashboard/components/LazyCard.tsx +62 -0
- package/apps/dashboard/components/LazyMarkdown.tsx +11 -0
- package/apps/dashboard/components/MainNav.tsx +38 -73
- package/apps/dashboard/components/MessageBlock.tsx +468 -0
- package/apps/dashboard/components/ModeStartCard.tsx +15 -16
- package/apps/dashboard/components/OnboardingWelcome.tsx +213 -0
- package/apps/dashboard/components/PlaceholderCard.tsx +3 -4
- package/apps/dashboard/components/ProjectSwitcher.tsx +30 -30
- package/apps/dashboard/components/PrototypeTimeline.tsx +72 -51
- package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +406 -388
- package/apps/dashboard/components/RealTimeTestsWrapper.tsx +373 -235
- package/apps/dashboard/components/ReviewFooter.tsx +139 -0
- package/apps/dashboard/components/SessionList.tsx +19 -19
- package/apps/dashboard/components/SubscribeContent.tsx +91 -47
- package/apps/dashboard/components/TestTree.tsx +16 -16
- package/apps/dashboard/components/TipCard.tsx +16 -17
- package/apps/dashboard/components/Toast.tsx +5 -6
- package/apps/dashboard/components/TypeIcon.tsx +55 -0
- package/apps/dashboard/components/ViewModeToolbar.tsx +104 -0
- package/apps/dashboard/components/WaveCompletionAnimation.tsx +52 -65
- package/apps/dashboard/components/WelcomeScreen.tsx +19 -35
- package/apps/dashboard/components/WorkItemHeader.tsx +4 -5
- package/apps/dashboard/components/WorkItemTree.tsx +11 -32
- package/apps/dashboard/components/settings/AccountSection.tsx +55 -35
- package/apps/dashboard/components/settings/AiContextSection.tsx +89 -0
- package/apps/dashboard/components/settings/ContextDocumentsSection.tsx +317 -0
- package/apps/dashboard/components/settings/EnvVarsSection.tsx +74 -152
- package/apps/dashboard/components/settings/GeneralSection.tsx +162 -56
- package/apps/dashboard/components/settings/ProjectStackSection.tsx +948 -0
- package/apps/dashboard/components/settings/SettingsLayout.tsx +4 -5
- package/apps/dashboard/components/ui/Button.tsx +104 -0
- package/apps/dashboard/components/ui/Input.tsx +78 -0
- package/apps/dashboard/components.json +1 -1
- package/apps/dashboard/contexts/ClaudeSessionContext.tsx +711 -418
- package/apps/dashboard/contexts/ConnectionStatusContext.tsx +25 -5
- package/apps/dashboard/contexts/UsageContext.tsx +87 -32
- package/apps/dashboard/dev.sh +35 -0
- package/apps/dashboard/eslint.config.mjs +9 -9
- package/apps/dashboard/hooks/useKanbanAnimation.ts +29 -0
- package/apps/dashboard/hooks/useKanbanUndo.ts +83 -0
- package/apps/dashboard/hooks/useWebSocket.ts +138 -83
- package/apps/dashboard/index.html +73 -0
- package/apps/dashboard/lib/constants.ts +43 -0
- package/apps/dashboard/lib/data-bridge.ts +722 -0
- package/apps/dashboard/lib/db.ts +69 -1265
- package/apps/dashboard/lib/environment-config.ts +173 -0
- package/apps/dashboard/lib/environment-verification.ts +119 -0
- package/apps/dashboard/lib/kanban-utils.ts +270 -0
- package/apps/dashboard/lib/proof-run.ts +495 -0
- package/apps/dashboard/lib/proof-scenario-runner.ts +346 -0
- package/apps/dashboard/lib/run-migrations.js +27 -2
- package/apps/dashboard/lib/service-recovery.ts +326 -0
- package/apps/dashboard/lib/session-state-machine.ts +1 -0
- package/apps/dashboard/lib/session-state-utils.ts +0 -164
- package/apps/dashboard/lib/session-stream-manager.ts +308 -134
- package/apps/dashboard/lib/shadows.ts +7 -0
- package/apps/dashboard/lib/stream-manager-registry.ts +46 -6
- package/apps/dashboard/lib/tauri-bridge.ts +102 -0
- package/apps/dashboard/lib/tauri.ts +106 -0
- package/apps/dashboard/lib/utils.ts +6 -0
- package/apps/dashboard/next-env.d.ts +1 -1
- package/apps/dashboard/package.json +21 -32
- package/apps/dashboard/public/bug-icon.png +0 -0
- package/apps/dashboard/public/buoy-icon.png +0 -0
- package/apps/dashboard/public/fonts/Satoshi-Variable.woff2 +0 -0
- package/apps/dashboard/public/fonts/Satoshi-VariableItalic.woff2 +0 -0
- package/apps/dashboard/public/in-flight-seagull.png +0 -0
- package/apps/dashboard/public/jetty-icon-loading-alt.svg +11 -0
- package/apps/dashboard/public/jetty-icon-loading.svg +11 -0
- package/apps/dashboard/public/jettypod_logo.png +0 -0
- package/apps/dashboard/public/pier-icon.png +0 -0
- package/apps/dashboard/public/star-icon.png +0 -0
- package/apps/dashboard/public/wrench-icon.png +0 -0
- package/apps/dashboard/scripts/tauri-build.js +228 -0
- package/apps/dashboard/scripts/upload-tauri-to-r2.js +125 -0
- package/apps/dashboard/scripts/ws-server.js +191 -0
- package/apps/dashboard/src/main.tsx +12 -0
- package/apps/dashboard/src/router.tsx +107 -0
- package/apps/dashboard/src/vite-env.d.ts +1 -0
- package/apps/dashboard/tsconfig.json +7 -12
- package/apps/dashboard/tsconfig.tsbuildinfo +1 -1
- package/apps/dashboard/vite.config.ts +33 -0
- package/apps/update-server/src/index.ts +228 -80
- package/claude-hooks/global-guardrails.js +14 -13
- package/crates/jettypod-cli/Cargo.toml +19 -0
- package/crates/jettypod-cli/src/commands.rs +1249 -0
- package/crates/jettypod-cli/src/main.rs +595 -0
- package/crates/jettypod-core/Cargo.toml +26 -0
- package/crates/jettypod-core/build.rs +98 -0
- package/crates/jettypod-core/migrations/V1__baseline.sql +197 -0
- package/crates/jettypod-core/migrations/V2__work_items_indexes.sql +6 -0
- package/crates/jettypod-core/migrations/V3__qa_steps.sql +2 -0
- package/crates/jettypod-core/src/auth.rs +294 -0
- package/crates/jettypod-core/src/config.rs +397 -0
- package/crates/jettypod-core/src/db/mod.rs +507 -0
- package/crates/jettypod-core/src/db/recovery.rs +114 -0
- package/crates/jettypod-core/src/db/startup.rs +101 -0
- package/crates/jettypod-core/src/db/validate.rs +149 -0
- package/crates/jettypod-core/src/error.rs +76 -0
- package/crates/jettypod-core/src/git.rs +458 -0
- package/crates/jettypod-core/src/lib.rs +20 -0
- package/crates/jettypod-core/src/sessions.rs +625 -0
- package/crates/jettypod-core/src/skills.rs +556 -0
- package/crates/jettypod-core/src/work.rs +1086 -0
- package/crates/jettypod-core/src/worktree.rs +628 -0
- package/crates/jettypod-core/src/ws.rs +767 -0
- package/cucumber-test.cjs +6 -0
- package/cucumber.js +9 -3
- package/docs/COMMAND_REFERENCE.md +34 -0
- package/hooks/post-checkout +32 -75
- package/hooks/post-merge +111 -10
- package/jest.setup.js +1 -0
- package/jettypod.js +145 -116
- package/lib/bdd-preflight.js +96 -0
- package/lib/chore-taxonomy.js +33 -10
- package/lib/database.js +36 -16
- package/lib/db-watcher.js +1 -1
- package/lib/git-hooks/pre-commit +1 -1
- package/lib/jettypod-backup.js +27 -4
- package/lib/merge-lock.js +111 -253
- package/lib/migrations/027-plan-at-creation-column.js +3 -1
- package/lib/migrations/029-remove-autoincrement.js +307 -0
- package/lib/migrations/029-rename-corrupted-to-cleaned.js +149 -0
- package/lib/migrations/030-rejection-round-columns.js +54 -0
- package/lib/migrations/031-session-isolation-index.js +17 -0
- package/lib/migrations/index.js +47 -4
- package/lib/schema.js +10 -5
- package/lib/seed-onboarding.js +1 -1
- package/lib/update-command/index.js +9 -175
- package/lib/work-commands/index.js +144 -19
- package/lib/work-tracking/index.js +148 -27
- package/lib/worktree-diagnostics.js +16 -16
- package/lib/worktree-facade.js +1 -1
- package/lib/worktree-manager.js +8 -8
- package/lib/worktree-reconciler.js +5 -5
- package/package.json +9 -2
- package/scripts/ndjson-to-cucumber-json.js +152 -0
- package/scripts/postinstall.js +25 -0
- package/skills-templates/bug-mode/SKILL.md +79 -20
- package/skills-templates/bug-planning/SKILL.md +25 -29
- package/skills-templates/chore-mode/SKILL.md +171 -69
- package/skills-templates/chore-mode/verification.js +51 -10
- package/skills-templates/chore-planning/SKILL.md +47 -18
- package/skills-templates/design-system-selection/SKILL.md +273 -0
- package/skills-templates/epic-planning/SKILL.md +82 -48
- package/skills-templates/external-transition/SKILL.md +47 -47
- package/skills-templates/feature-planning/SKILL.md +173 -74
- package/skills-templates/production-mode/SKILL.md +69 -49
- package/skills-templates/request-routing/SKILL.md +4 -4
- package/skills-templates/simple-improvement/SKILL.md +74 -29
- package/skills-templates/speed-mode/SKILL.md +217 -141
- package/skills-templates/stable-mode/SKILL.md +148 -89
- package/apps/dashboard/README.md +0 -36
- package/apps/dashboard/app/api/claude/[workItemId]/message/route.ts +0 -386
- package/apps/dashboard/app/api/claude/[workItemId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/[workItemId]/route.ts +0 -167
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/content/route.ts +0 -52
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +0 -378
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/sessions/cleanup/route.ts +0 -34
- package/apps/dashboard/app/api/claude/sessions/route.ts +0 -184
- package/apps/dashboard/app/api/decisions/[id]/route.ts +0 -25
- package/apps/dashboard/app/api/internal/set-project/route.ts +0 -17
- package/apps/dashboard/app/api/kanban/route.ts +0 -15
- package/apps/dashboard/app/api/settings/env-vars/route.ts +0 -125
- package/apps/dashboard/app/api/settings/general/route.ts +0 -21
- package/apps/dashboard/app/api/tests/route.ts +0 -9
- package/apps/dashboard/app/api/tests/run/route.ts +0 -82
- package/apps/dashboard/app/api/tests/run/stream/route.ts +0 -71
- package/apps/dashboard/app/api/tests/undefined/route.ts +0 -9
- package/apps/dashboard/app/api/usage/route.ts +0 -17
- package/apps/dashboard/app/api/work/[id]/description/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/epic/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/order/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/status/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/title/route.ts +0 -21
- package/apps/dashboard/app/layout.tsx +0 -43
- package/apps/dashboard/components/UpgradeBanner.tsx +0 -29
- package/apps/dashboard/electron/ipc-handlers.js +0 -1028
- package/apps/dashboard/electron/main.js +0 -2124
- package/apps/dashboard/electron/preload.js +0 -123
- package/apps/dashboard/electron/session-manager.js +0 -141
- package/apps/dashboard/electron-builder.config.js +0 -357
- package/apps/dashboard/hooks/useClaudeSessions.ts +0 -299
- package/apps/dashboard/lib/claude-process-manager.ts +0 -492
- package/apps/dashboard/lib/db-bridge.ts +0 -282
- package/apps/dashboard/lib/prototypes.ts +0 -202
- package/apps/dashboard/lib/test-results-db.ts +0 -307
- package/apps/dashboard/lib/tests.ts +0 -282
- package/apps/dashboard/next.config.js +0 -50
- package/apps/dashboard/postcss.config.mjs +0 -7
- package/apps/dashboard/public/file.svg +0 -1
- package/apps/dashboard/public/globe.svg +0 -1
- package/apps/dashboard/public/next.svg +0 -1
- package/apps/dashboard/public/vercel.svg +0 -1
- package/apps/dashboard/public/window.svg +0 -1
- package/apps/dashboard/scripts/download-node.js +0 -104
- package/apps/dashboard/scripts/upload-to-r2.js +0 -89
- package/docs/bdd-guidance.md +0 -390
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Design system elevation tokens — shared across all components. */
|
|
2
|
+
export const shadow = {
|
|
3
|
+
sm: '0 1px 2px rgba(0,0,0,0.04), 0 2px 6px rgba(0,0,0,0.02)',
|
|
4
|
+
md: '0 1px 3px rgba(0,0,0,0.04), 0 4px 12px rgba(0,0,0,0.03)',
|
|
5
|
+
lg: '0 4px 12px rgba(0,0,0,0.06), 0 12px 28px rgba(0,0,0,0.05)',
|
|
6
|
+
overlay: '0 8px 24px rgba(0,0,0,0.12), 0 16px 48px rgba(0,0,0,0.08)',
|
|
7
|
+
};
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Part of Epic #1000129: Claude Session Architecture Refactor
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { EventEmitter } from '
|
|
12
|
+
import { EventEmitter } from 'eventemitter3';
|
|
13
13
|
import {
|
|
14
14
|
SessionStreamManager,
|
|
15
15
|
createStreamManager,
|
|
@@ -46,6 +46,8 @@ interface ManagerMetadata {
|
|
|
46
46
|
createdAt: number;
|
|
47
47
|
/** Timestamp of last activity (message sent/received) */
|
|
48
48
|
lastActivityAt: number;
|
|
49
|
+
/** Mutable ref for the session ID — allows rekey() to update the closure */
|
|
50
|
+
sessionIdRef: { current: string };
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
/** Configuration for stale manager cleanup */
|
|
@@ -164,10 +166,11 @@ class StreamManagerRegistry extends EventEmitter {
|
|
|
164
166
|
// Skip if recently active
|
|
165
167
|
if (meta.lastActivityAt > staleThreshold) continue;
|
|
166
168
|
|
|
167
|
-
// Skip
|
|
169
|
+
// Skip actively-running managers if configured
|
|
168
170
|
if (this.cleanupConfig.onlyCleanupIdle) {
|
|
169
171
|
const manager = this.managers.get(sessionId);
|
|
170
|
-
|
|
172
|
+
const activeStatuses = ['streaming', 'creating', 'connecting'];
|
|
173
|
+
if (manager && activeStatuses.includes(manager.status)) continue;
|
|
171
174
|
}
|
|
172
175
|
|
|
173
176
|
// Clean up this manager
|
|
@@ -266,21 +269,26 @@ class StreamManagerRegistry extends EventEmitter {
|
|
|
266
269
|
|
|
267
270
|
const now = Date.now();
|
|
268
271
|
|
|
272
|
+
// Mutable ref so the closure always emits with the current session ID,
|
|
273
|
+
// even after rekey() changes it (fixes stream freeze after session linking)
|
|
274
|
+
const sessionIdRef = { current: sessionId };
|
|
275
|
+
|
|
269
276
|
// Create new manager with state change callback that emits registry events
|
|
270
277
|
const manager = createStreamManager(options.context, {
|
|
271
278
|
...options.callbacks,
|
|
272
279
|
onStateChange: (state) => {
|
|
273
280
|
// Record activity on state changes
|
|
274
|
-
this.recordActivity(
|
|
275
|
-
this.emit('stateChange',
|
|
281
|
+
this.recordActivity(sessionIdRef.current);
|
|
282
|
+
this.emit('stateChange', sessionIdRef.current, state);
|
|
276
283
|
},
|
|
277
284
|
});
|
|
278
285
|
|
|
279
|
-
// Initialize metadata
|
|
286
|
+
// Initialize metadata (includes sessionIdRef for rekey support)
|
|
280
287
|
this.metadata.set(sessionId, {
|
|
281
288
|
refCount: 0,
|
|
282
289
|
createdAt: now,
|
|
283
290
|
lastActivityAt: now,
|
|
291
|
+
sessionIdRef,
|
|
284
292
|
});
|
|
285
293
|
|
|
286
294
|
this.managers.set(sessionId, manager);
|
|
@@ -313,6 +321,38 @@ class StreamManagerRegistry extends EventEmitter {
|
|
|
313
321
|
return true;
|
|
314
322
|
}
|
|
315
323
|
|
|
324
|
+
/**
|
|
325
|
+
* Re-key a manager from one session ID to another.
|
|
326
|
+
* Used when a standalone session is linked to a work item — the session ID
|
|
327
|
+
* changes but the stream manager (with all its state) must continue working.
|
|
328
|
+
*
|
|
329
|
+
* Updates the mutable sessionIdRef so the onStateChange closure emits events
|
|
330
|
+
* with the new ID, allowing the React state handler to find the session.
|
|
331
|
+
*
|
|
332
|
+
* @param oldId - The current session ID
|
|
333
|
+
* @param newId - The new session ID to re-key to
|
|
334
|
+
* @returns true if re-keyed, false if old ID not found or new ID already exists
|
|
335
|
+
*/
|
|
336
|
+
rekey(oldId: string, newId: string): boolean {
|
|
337
|
+
const manager = this.managers.get(oldId);
|
|
338
|
+
const meta = this.metadata.get(oldId);
|
|
339
|
+
if (!manager || !meta) return false;
|
|
340
|
+
|
|
341
|
+
// Don't overwrite an existing manager
|
|
342
|
+
if (this.managers.has(newId)) return false;
|
|
343
|
+
|
|
344
|
+
// Update the mutable ref so the closure emits with the new ID
|
|
345
|
+
meta.sessionIdRef.current = newId;
|
|
346
|
+
|
|
347
|
+
// Move manager and metadata to new key
|
|
348
|
+
this.managers.delete(oldId);
|
|
349
|
+
this.managers.set(newId, manager);
|
|
350
|
+
this.metadata.delete(oldId);
|
|
351
|
+
this.metadata.set(newId, meta);
|
|
352
|
+
|
|
353
|
+
return true;
|
|
354
|
+
}
|
|
355
|
+
|
|
316
356
|
/**
|
|
317
357
|
* Get all session IDs in the registry.
|
|
318
358
|
*/
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Tauri IPC bridge for auth, project, Claude CLI, and shell operations.
|
|
2
|
+
// Database operations are in data-bridge.ts.
|
|
3
|
+
// Low-level primitives (invoke, isTauri, openShell, openDialog) live in lib/tauri.ts.
|
|
4
|
+
|
|
5
|
+
import { invoke, isTauri, openShell, openDialog as tauriOpenDialog } from './tauri';
|
|
6
|
+
|
|
7
|
+
export { isTauri };
|
|
8
|
+
|
|
9
|
+
// Auth types
|
|
10
|
+
export interface AuthUser {
|
|
11
|
+
email: string;
|
|
12
|
+
plan: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AuthStatus {
|
|
17
|
+
authenticated: boolean;
|
|
18
|
+
user: AuthUser | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Auth namespace
|
|
22
|
+
export const auth = {
|
|
23
|
+
getStatus: () => invoke<AuthStatus>('auth_get_status'),
|
|
24
|
+
getToken: () => invoke<string | null>('auth_get_token'),
|
|
25
|
+
saveToken: (token: string, user: AuthUser) => invoke<void>('auth_save_token', { token, user }),
|
|
26
|
+
logout: () => invoke<void>('auth_logout'),
|
|
27
|
+
hasLoggedInBefore: () => invoke<boolean>('auth_has_logged_in_before'),
|
|
28
|
+
getPostLoginPath: () => invoke<string | null>('auth_get_post_login_path'),
|
|
29
|
+
setPostLoginPath: (path: string | null) => invoke<void>('auth_set_post_login_path', { path }),
|
|
30
|
+
loginWithGoogle: () => invoke<void>('auth_login_with_google'),
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Project types
|
|
34
|
+
export interface RecentProject {
|
|
35
|
+
name: string;
|
|
36
|
+
path: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Project namespace
|
|
40
|
+
export const project = {
|
|
41
|
+
getRecent: () => invoke<RecentProject[]>('project_get_recent'),
|
|
42
|
+
addRecent: (name: string, path: string) => invoke<void>('project_add_recent', { name, path }),
|
|
43
|
+
async openDialog(): Promise<{ success: boolean; canceled?: boolean; error?: string }> {
|
|
44
|
+
let selected: string | string[] | null;
|
|
45
|
+
try {
|
|
46
|
+
selected = await tauriOpenDialog({ directory: true, title: 'Open JettyPod Project' });
|
|
47
|
+
} catch (err) {
|
|
48
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
49
|
+
console.error('Dialog open failed:', msg);
|
|
50
|
+
return { success: false, error: msg };
|
|
51
|
+
}
|
|
52
|
+
if (!selected || (Array.isArray(selected) && selected.length === 0)) {
|
|
53
|
+
return { success: false, canceled: true };
|
|
54
|
+
}
|
|
55
|
+
const projectPath = Array.isArray(selected) ? selected[0] : selected;
|
|
56
|
+
try {
|
|
57
|
+
await invoke('db_init', { projectPath });
|
|
58
|
+
const name = projectPath.split('/').pop() || projectPath;
|
|
59
|
+
await invoke('project_add_recent', { name, path: projectPath });
|
|
60
|
+
return { success: true };
|
|
61
|
+
} catch (err) {
|
|
62
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
63
|
+
console.error('Project init failed:', msg);
|
|
64
|
+
return { success: false, error: msg };
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
async newProject(): Promise<{ success: boolean; canceled?: boolean }> {
|
|
68
|
+
// Same as openDialog — user picks folder, we initialize it
|
|
69
|
+
return project.openDialog();
|
|
70
|
+
},
|
|
71
|
+
async openRecent(path: string): Promise<{ success: boolean }> {
|
|
72
|
+
try {
|
|
73
|
+
await invoke('db_init', { projectPath: path });
|
|
74
|
+
const name = path.split('/').pop() || path;
|
|
75
|
+
await invoke('project_add_recent', { name, path });
|
|
76
|
+
return { success: true };
|
|
77
|
+
} catch {
|
|
78
|
+
return { success: false };
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// Claude CLI types
|
|
84
|
+
export interface CliResult {
|
|
85
|
+
success: boolean;
|
|
86
|
+
error: string | null;
|
|
87
|
+
output: string | null;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Claude CLI namespace
|
|
91
|
+
export const claudeCode = {
|
|
92
|
+
isAuthenticated: () => invoke<boolean>('claude_code_is_authenticated'),
|
|
93
|
+
login: () => invoke<CliResult>('claude_code_login'),
|
|
94
|
+
install: () => invoke<CliResult>('claude_code_install'),
|
|
95
|
+
update: () => invoke<CliResult>('claude_code_update'),
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
// Shell namespace
|
|
99
|
+
export const shell = {
|
|
100
|
+
openPath: (path: string) => openShell(path),
|
|
101
|
+
openUrl: (url: string) => openShell(url),
|
|
102
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical Tauri IPC bridge — single source of truth for all __TAURI__ access.
|
|
3
|
+
*
|
|
4
|
+
* Every module that needs Tauri globals (invoke, listen, shell, dialog)
|
|
5
|
+
* should import from this file instead of touching window.__TAURI__ directly.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
interface TauriGlobal {
|
|
9
|
+
core: {
|
|
10
|
+
invoke<T>(cmd: string, args?: Record<string, unknown>): Promise<T>;
|
|
11
|
+
};
|
|
12
|
+
shell: {
|
|
13
|
+
open: (path: string) => Promise<void>;
|
|
14
|
+
};
|
|
15
|
+
dialog: {
|
|
16
|
+
open: (options?: {
|
|
17
|
+
directory?: boolean;
|
|
18
|
+
multiple?: boolean;
|
|
19
|
+
title?: string;
|
|
20
|
+
}) => Promise<string | string[] | null>;
|
|
21
|
+
};
|
|
22
|
+
event: {
|
|
23
|
+
listen: <T>(
|
|
24
|
+
event: string,
|
|
25
|
+
handler: (event: { payload: T }) => void
|
|
26
|
+
) => Promise<() => void>;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function getTauri(): TauriGlobal {
|
|
31
|
+
return (window as any).__TAURI__;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Returns true when running inside a Tauri webview. */
|
|
35
|
+
export function isTauri(): boolean {
|
|
36
|
+
return !!(window as any).__TAURI__;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Invoke a Tauri IPC command. */
|
|
40
|
+
export async function invoke<T>(
|
|
41
|
+
cmd: string,
|
|
42
|
+
args?: Record<string, unknown>
|
|
43
|
+
): Promise<T> {
|
|
44
|
+
return getTauri().core.invoke(cmd, args);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Listen for a Tauri event. Returns an unlisten function. */
|
|
48
|
+
export async function listen<T>(
|
|
49
|
+
event: string,
|
|
50
|
+
handler: (event: { payload: T }) => void
|
|
51
|
+
): Promise<() => void> {
|
|
52
|
+
return getTauri().event.listen(event, handler);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Invoke a Tauri IPC command with a timeout. Rejects if the call doesn't resolve within timeoutMs. */
|
|
56
|
+
export async function invokeWithTimeout<T>(
|
|
57
|
+
cmd: string,
|
|
58
|
+
args?: Record<string, unknown>,
|
|
59
|
+
timeoutMs: number = 10000
|
|
60
|
+
): Promise<T> {
|
|
61
|
+
return Promise.race([
|
|
62
|
+
invoke<T>(cmd, args),
|
|
63
|
+
new Promise<never>((_, reject) =>
|
|
64
|
+
setTimeout(() => reject(new Error(`IPC timeout after ${timeoutMs}ms: ${cmd}`)), timeoutMs)
|
|
65
|
+
),
|
|
66
|
+
]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// ─── Shell command result type ──────────────────────────────
|
|
70
|
+
|
|
71
|
+
export interface ShellCommandResult {
|
|
72
|
+
stdout: string;
|
|
73
|
+
stderr: string;
|
|
74
|
+
exit_code: number | null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Run a shell command and return its output.
|
|
79
|
+
* Used by service recovery for pre-flight checks and remedies.
|
|
80
|
+
*/
|
|
81
|
+
export async function runShellCommand(
|
|
82
|
+
command: string,
|
|
83
|
+
args: string[],
|
|
84
|
+
options?: { cwd?: string; timeoutMs?: number }
|
|
85
|
+
): Promise<ShellCommandResult> {
|
|
86
|
+
return invoke<ShellCommandResult>('run_shell_command', {
|
|
87
|
+
command,
|
|
88
|
+
args,
|
|
89
|
+
cwd: options?.cwd ?? null,
|
|
90
|
+
timeoutMs: options?.timeoutMs ?? null,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Open a path or URL via the system shell. */
|
|
95
|
+
export function openShell(path: string): Promise<void> {
|
|
96
|
+
return getTauri().shell.open(path);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Open a native file/directory dialog. */
|
|
100
|
+
export function openDialog(options?: {
|
|
101
|
+
directory?: boolean;
|
|
102
|
+
multiple?: boolean;
|
|
103
|
+
title?: string;
|
|
104
|
+
}): Promise<string | string[] | null> {
|
|
105
|
+
return getTauri().dialog.open(options);
|
|
106
|
+
}
|
|
@@ -4,3 +4,9 @@ import { twMerge } from "tailwind-merge"
|
|
|
4
4
|
export function cn(...inputs: ClassValue[]) {
|
|
5
5
|
return twMerge(clsx(inputs))
|
|
6
6
|
}
|
|
7
|
+
|
|
8
|
+
export const WS_PORT = 47808;
|
|
9
|
+
|
|
10
|
+
export function getWebSocketUrl(): string {
|
|
11
|
+
return `ws://${window.location.hostname}:${WS_PORT}`;
|
|
12
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="next" />
|
|
2
2
|
/// <reference types="next/image-types/global" />
|
|
3
|
-
import "./.next/types/routes.d.ts";
|
|
3
|
+
import "./.next/dev/types/routes.d.ts";
|
|
4
4
|
|
|
5
5
|
// NOTE: This file should not be edited
|
|
6
6
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
|
@@ -1,58 +1,47 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dashboard",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.4.121",
|
|
4
4
|
"private": true,
|
|
5
|
-
"main": "electron/main.js",
|
|
6
5
|
"scripts": {
|
|
7
|
-
"dev": "
|
|
8
|
-
"build": "
|
|
9
|
-
"
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"build": "vite build",
|
|
8
|
+
"preview": "vite preview",
|
|
10
9
|
"lint": "eslint",
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"electron:build:win": "npm run build && npx electron-builder --config electron-builder.config.js --win",
|
|
20
|
-
"electron:build:linux": "npm run build && npx electron-builder --config electron-builder.config.js --linux",
|
|
21
|
-
"electron:pack": "npm run build && npx electron-builder --config electron-builder.config.js --dir",
|
|
22
|
-
"upload:r2": "node scripts/upload-to-r2.js",
|
|
23
|
-
"electron:release": "npm run electron:build:mac && npm run upload:r2"
|
|
10
|
+
"tauri:dev": "cargo tauri dev",
|
|
11
|
+
"tauri:build": "node scripts/tauri-build.js",
|
|
12
|
+
"tauri:build:release": "node scripts/tauri-build.js --release",
|
|
13
|
+
"tauri:build:arm64": "node scripts/tauri-build.js --release --target=arm64",
|
|
14
|
+
"tauri:build:x64": "node scripts/tauri-build.js --release --target=x64",
|
|
15
|
+
"tauri:build:universal": "node scripts/tauri-build.js --release --target=universal",
|
|
16
|
+
"tauri:release": "node scripts/tauri-build.js --release --upload",
|
|
17
|
+
"upload:tauri:r2": "node scripts/upload-tauri-to-r2.js"
|
|
24
18
|
},
|
|
25
19
|
"dependencies": {
|
|
26
20
|
"@dnd-kit/core": "^6.3.1",
|
|
27
21
|
"@dnd-kit/sortable": "^10.0.0",
|
|
28
|
-
"@
|
|
29
|
-
"@
|
|
30
|
-
"better-sqlite3": "^12.5.0",
|
|
22
|
+
"@fontsource-variable/geist-mono": "^5.2.7",
|
|
23
|
+
"@tanstack/react-virtual": "^3.13.19",
|
|
31
24
|
"class-variance-authority": "^0.7.1",
|
|
32
25
|
"clsx": "^2.1.1",
|
|
33
|
-
"
|
|
26
|
+
"eventemitter3": "^5.0.4",
|
|
34
27
|
"framer-motion": "^11.15.0",
|
|
35
|
-
"lucide-react": "^0.555.0",
|
|
36
|
-
"next": "16.0.6",
|
|
37
28
|
"react": "19.2.0",
|
|
38
29
|
"react-dom": "19.2.0",
|
|
39
30
|
"react-markdown": "^10.1.0",
|
|
31
|
+
"react-router-dom": "^7.13.0",
|
|
40
32
|
"remark-gfm": "^4.0.1",
|
|
41
|
-
"tailwind-merge": "^3.4.0"
|
|
42
|
-
"ws": "^8.19.0"
|
|
33
|
+
"tailwind-merge": "^3.4.0"
|
|
43
34
|
},
|
|
44
35
|
"devDependencies": {
|
|
45
|
-
"@tailwindcss/
|
|
46
|
-
"@types/better-sqlite3": "^7.6.13",
|
|
36
|
+
"@tailwindcss/vite": "^4.2.0",
|
|
47
37
|
"@types/node": "^20",
|
|
48
38
|
"@types/react": "^19",
|
|
49
39
|
"@types/react-dom": "^19",
|
|
50
|
-
"
|
|
51
|
-
"electron-builder": "^26.4.0",
|
|
40
|
+
"@vitejs/plugin-react-swc": "^4.2.3",
|
|
52
41
|
"eslint": "^9",
|
|
53
|
-
"eslint-config-next": "16.0.6",
|
|
54
42
|
"tailwindcss": "^4",
|
|
55
43
|
"tw-animate-css": "^1.4.0",
|
|
56
|
-
"typescript": "5.9.3"
|
|
44
|
+
"typescript": "5.9.3",
|
|
45
|
+
"vite": "^7.3.1"
|
|
57
46
|
}
|
|
58
47
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g clip-path="url(#clip0_279_7)">
|
|
3
|
+
<circle cx="250" cy="250" r="250" fill="#819D9F"/>
|
|
4
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M377.995 174.218C379.102 175.321 390.228 178.878 402.718 182.118C421.048 186.871 425.639 189.381 426.499 195.125C428.112 205.865 420.195 206.795 392.295 199.141C359.872 190.245 338.599 190.308 318.209 199.358C295.235 209.551 251.802 209.605 229.322 199.471C208.242 189.968 178.459 189.795 154.142 199.038C122.825 210.938 71.7052 207.041 63.7318 192.145C58.7718 182.878 64.5685 181.211 86.1652 185.695C104.932 189.588 138.229 187.895 145.212 182.691C152.052 177.591 176.352 172.208 192.525 172.208C201.502 172.208 220.662 175.958 235.102 180.541C249.542 185.125 266.928 188.875 273.738 188.875C280.548 188.875 296.459 185.125 309.095 180.541C330.889 172.638 372.588 168.808 377.995 174.218ZM317.099 286.988C325.349 289.371 338.662 293.768 346.685 296.765C366.625 304.208 391.082 303.711 407.099 295.541C422.765 287.548 436.562 286.931 439.312 294.098C442.212 301.655 436.889 305.561 411.695 314.371C381.352 324.981 362.175 324.465 331.569 312.208C302.945 300.748 284.615 299.698 265.415 308.421C230.322 324.361 200.112 324.445 167.498 308.688C150.505 300.478 134.435 300.528 107.099 308.875C81.0885 316.818 72.5985 317.171 67.0985 310.541C61.5918 303.905 67.0985 297.271 78.9252 296.291C83.8252 295.888 94.7952 293.088 103.302 290.071C127.308 281.558 158.109 282.811 183.505 293.338C210.685 304.598 219.342 304.468 253.925 292.275C284.895 281.351 294.729 280.531 317.099 286.988ZM248.765 408.195C254.265 408.801 268.022 412.951 279.335 417.418C293.649 423.071 306.462 425.541 321.479 425.541C338.329 425.541 343.509 426.728 345.132 430.965C346.279 433.945 345.505 438.445 343.415 440.965C337.479 448.118 301.899 446.771 280.385 438.578C240.132 423.248 243.315 423.371 206.985 435.745C171.872 447.708 162.099 447.241 162.099 433.605C162.099 428.935 165.489 426.815 175.742 425.065C183.249 423.781 195.229 420.291 202.369 417.308C219.452 410.171 236.422 406.838 248.765 408.195ZM270.432 65.3847C287.462 73.2213 296.835 75.3746 314.242 75.448C336.999 75.5446 343.072 79.2214 336.905 89.178C334.775 92.618 326.602 93.8547 306.382 93.8014C282.682 93.738 276.405 92.438 262.125 84.6347C241.695 73.4713 236.828 73.4047 214.109 83.9814C204.212 88.588 189.212 92.698 180.775 93.1147C167.312 93.7814 165.305 92.9914 164.409 86.6814C163.585 80.9147 165.569 79.0213 174.409 77.1313C180.472 75.8346 194.412 71.158 205.385 66.738C236.599 54.168 245.645 53.978 270.432 65.3847Z" fill="black"/>
|
|
5
|
+
</g>
|
|
6
|
+
<defs>
|
|
7
|
+
<clipPath id="clip0_279_7">
|
|
8
|
+
<rect width="500" height="500" fill="white"/>
|
|
9
|
+
</clipPath>
|
|
10
|
+
</defs>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg width="500" height="500" viewBox="0 0 500 500" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<g clip-path="url(#clip0_32_14)">
|
|
3
|
+
<circle cx="250" cy="250" r="250" fill="#819D9F"/>
|
|
4
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M124.103 174.218C122.997 175.321 111.87 178.878 99.3799 182.118C81.0499 186.871 76.4599 189.381 75.5999 195.125C73.9865 205.865 81.9032 206.795 109.803 199.141C142.227 190.245 163.5 190.308 183.89 199.358C206.863 209.551 250.297 209.605 272.777 199.471C293.857 189.968 323.64 189.795 347.957 199.038C379.273 210.938 430.393 207.041 438.367 192.145C443.327 182.878 437.53 181.211 415.933 185.695C397.167 189.588 363.87 187.895 356.887 182.691C350.047 177.591 325.747 172.208 309.573 172.208C300.597 172.208 281.437 175.958 266.997 180.541C252.557 185.125 235.17 188.875 228.36 188.875C221.55 188.875 205.64 185.125 193.003 180.541C171.21 172.638 129.51 168.808 124.103 174.218ZM185 286.988C176.75 289.371 163.437 293.768 155.413 296.765C135.473 304.208 111.017 303.711 94.9999 295.541C79.3332 287.548 65.5365 286.931 62.7865 294.098C59.8865 301.655 65.2099 305.561 90.4032 314.371C120.747 324.981 139.923 324.465 170.53 312.208C199.153 300.748 217.483 299.698 236.683 308.421C271.777 324.361 301.987 324.445 334.6 308.688C351.593 300.478 367.663 300.528 395 308.875C421.01 316.818 429.5 317.171 435 310.541C440.507 303.905 435 297.271 423.173 296.291C418.273 295.888 407.303 293.088 398.797 290.071C374.79 281.558 343.99 282.811 318.593 293.338C291.413 304.598 282.757 304.468 248.173 292.275C217.203 281.351 207.37 280.531 185 286.988ZM253.333 408.195C247.833 408.801 234.077 412.951 222.763 417.418C208.45 423.071 195.637 425.541 180.62 425.541C163.77 425.541 158.59 426.728 156.967 430.965C155.82 433.945 156.593 438.445 158.683 440.965C164.62 448.118 200.2 446.771 221.713 438.578C261.967 423.248 258.783 423.371 295.113 435.745C330.227 447.708 340 447.241 340 433.605C340 428.935 336.61 426.815 326.357 425.065C318.85 423.781 306.87 420.291 299.73 417.308C282.647 410.171 265.677 406.838 253.333 408.195ZM231.667 65.3847C214.637 73.2213 205.263 75.3746 187.857 75.448C165.1 75.5446 159.027 79.2214 165.193 89.178C167.323 92.618 175.497 93.8547 195.717 93.8014C219.417 93.738 225.693 92.438 239.973 84.6347C260.403 73.4713 265.27 73.4047 287.99 83.9814C297.887 88.588 312.887 92.698 321.323 93.1147C334.787 93.7814 336.793 92.9914 337.69 86.6814C338.513 80.9147 336.53 79.0213 327.69 77.1313C321.627 75.8346 307.687 71.158 296.713 66.738C265.5 54.168 256.453 53.978 231.667 65.3847Z" fill="black"/>
|
|
5
|
+
</g>
|
|
6
|
+
<defs>
|
|
7
|
+
<clipPath id="clip0_32_14">
|
|
8
|
+
<rect width="500" height="500" fill="white"/>
|
|
9
|
+
</clipPath>
|
|
10
|
+
</defs>
|
|
11
|
+
</svg>
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|