claudeship 0.2.9 → 0.2.11

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 (58) hide show
  1. package/apps/server/dist/chat/prompts/fullstack-express-prompt.d.ts +1 -1
  2. package/apps/server/dist/chat/prompts/fullstack-express-prompt.js +16 -0
  3. package/apps/server/dist/chat/prompts/fullstack-express-prompt.js.map +1 -1
  4. package/apps/server/dist/chat/prompts/fullstack-fastapi-prompt.d.ts +1 -1
  5. package/apps/server/dist/chat/prompts/fullstack-fastapi-prompt.js +16 -0
  6. package/apps/server/dist/chat/prompts/fullstack-fastapi-prompt.js.map +1 -1
  7. package/apps/server/dist/chat/prompts/web-system-prompt.d.ts +1 -1
  8. package/apps/server/dist/chat/prompts/web-system-prompt.js +15 -0
  9. package/apps/server/dist/chat/prompts/web-system-prompt.js.map +1 -1
  10. package/apps/server/dist/preview/preview.controller.d.ts +1 -0
  11. package/apps/server/dist/preview/preview.controller.js +10 -0
  12. package/apps/server/dist/preview/preview.controller.js.map +1 -1
  13. package/apps/server/dist/preview/preview.service.d.ts +1 -0
  14. package/apps/server/dist/preview/preview.service.js +26 -2
  15. package/apps/server/dist/preview/preview.service.js.map +1 -1
  16. package/apps/server/dist/tsconfig.tsbuildinfo +1 -1
  17. package/apps/server/package.json +1 -1
  18. package/apps/web/.next/BUILD_ID +1 -1
  19. package/apps/web/.next/app-build-manifest.json +2 -2
  20. package/apps/web/.next/build-manifest.json +2 -2
  21. package/apps/web/.next/cache/.previewinfo +1 -1
  22. package/apps/web/.next/cache/.rscinfo +1 -1
  23. package/apps/web/.next/cache/.tsbuildinfo +1 -1
  24. package/apps/web/.next/cache/config.json +3 -3
  25. package/apps/web/.next/cache/eslint/.cache_j3uhuz +1 -1
  26. package/apps/web/.next/cache/webpack/client-production/0.pack +0 -0
  27. package/apps/web/.next/cache/webpack/client-production/index.pack +0 -0
  28. package/apps/web/.next/cache/webpack/edge-server-production/index.pack +0 -0
  29. package/apps/web/.next/cache/webpack/server-production/0.pack +0 -0
  30. package/apps/web/.next/cache/webpack/server-production/index.pack +0 -0
  31. package/apps/web/.next/prerender-manifest.json +10 -10
  32. package/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  33. package/apps/web/.next/server/app/_not-found.html +1 -1
  34. package/apps/web/.next/server/app/_not-found.rsc +1 -1
  35. package/apps/web/.next/server/app/index.html +1 -1
  36. package/apps/web/.next/server/app/index.rsc +1 -1
  37. package/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  38. package/apps/web/.next/server/app/project/[id]/page.js +2 -2
  39. package/apps/web/.next/server/app/project/[id]/page_client-reference-manifest.js +1 -1
  40. package/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  41. package/apps/web/.next/server/app/settings.html +1 -1
  42. package/apps/web/.next/server/app/settings.rsc +1 -1
  43. package/apps/web/.next/server/pages/404.html +1 -1
  44. package/apps/web/.next/server/pages/500.html +1 -1
  45. package/apps/web/.next/server/server-reference-manifest.json +1 -1
  46. package/apps/web/.next/static/chunks/298-6f3d6b321c288cd3.js +1 -0
  47. package/apps/web/.next/static/chunks/app/project/[id]/page-e5cda6f9050b0a52.js +1 -0
  48. package/apps/web/.next/trace +17 -17
  49. package/apps/web/package.json +1 -1
  50. package/apps/web/src/components/preview/PreviewPanel.tsx +16 -1
  51. package/apps/web/src/components/workspace/WorkspaceLayout.tsx +5 -5
  52. package/apps/web/src/stores/useChatStore.ts +34 -9
  53. package/apps/web/src/stores/usePreviewStore.ts +22 -0
  54. package/package.json +1 -1
  55. package/apps/web/.next/static/chunks/595-00a84eeccb7bfc27.js +0 -1
  56. package/apps/web/.next/static/chunks/app/project/[id]/page-4c15c33bf78552cb.js +0 -1
  57. /package/apps/web/.next/static/{yVw9J0lkf1zLx2qq5O3Tu → zw4FcukMOho6_dzgpEdNW}/_buildManifest.js +0 -0
  58. /package/apps/web/.next/static/{yVw9J0lkf1zLx2qq5O3Tu → zw4FcukMOho6_dzgpEdNW}/_ssgManifest.js +0 -0
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claudeship/web",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "dev": "node scripts/dev-with-recovery.mjs",
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { useEffect, useState, useRef, useCallback } from "react";
4
- import { Play, Square, RefreshCw, ExternalLink, Package, Loader2, Zap } from "lucide-react";
4
+ import { Play, Square, RefreshCw, ExternalLink, Package, Loader2, Zap, RotateCcw } from "lucide-react";
5
5
  import { Button } from "@/components/ui/button";
6
6
  import { usePreviewStore } from "@/stores/usePreviewStore";
7
7
  import { useTranslation } from "@/lib/i18n";
@@ -27,6 +27,7 @@ export function PreviewPanel({ projectId }: PreviewPanelProps) {
27
27
  projectReady,
28
28
  startPreview,
29
29
  stopPreview,
30
+ restartPreview,
30
31
  refreshPreview,
31
32
  fetchStatus,
32
33
  checkProjectReady,
@@ -187,6 +188,7 @@ export function PreviewPanel({ projectId }: PreviewPanelProps) {
187
188
 
188
189
  const handleStart = () => startPreview(projectId);
189
190
  const handleStop = () => stopPreview(projectId);
191
+ const handleRestart = () => restartPreview(projectId);
190
192
  const handleRefresh = () => refreshPreview();
191
193
  const handleOpenExternal = () => {
192
194
  if (url) {
@@ -243,14 +245,26 @@ export function PreviewPanel({ projectId }: PreviewPanelProps) {
243
245
  onClick={handleRefresh}
244
246
  disabled={isLoading}
245
247
  className="h-8 w-8 p-0"
248
+ title="Refresh"
246
249
  >
247
250
  <RefreshCw className="h-4 w-4" />
248
251
  </Button>
252
+ <Button
253
+ variant="ghost"
254
+ size="sm"
255
+ onClick={handleRestart}
256
+ disabled={isLoading}
257
+ className="h-8 w-8 p-0"
258
+ title="Restart server"
259
+ >
260
+ <RotateCcw className="h-4 w-4" />
261
+ </Button>
249
262
  <Button
250
263
  variant="ghost"
251
264
  size="sm"
252
265
  onClick={handleOpenExternal}
253
266
  className="h-8 w-8 p-0"
267
+ title="Open in new tab"
254
268
  >
255
269
  <ExternalLink className="h-4 w-4" />
256
270
  </Button>
@@ -260,6 +274,7 @@ export function PreviewPanel({ projectId }: PreviewPanelProps) {
260
274
  onClick={handleStop}
261
275
  disabled={isLoading}
262
276
  className="h-8 w-8 p-0"
277
+ title="Stop"
263
278
  >
264
279
  <Square className="h-4 w-4" />
265
280
  </Button>
@@ -57,18 +57,18 @@ export function WorkspaceLayout({ projectId }: WorkspaceLayoutProps) {
57
57
  </div>
58
58
  )}
59
59
 
60
- {/* Chat Panel */}
60
+ {/* Chat Panel - 30% width */}
61
61
  <div
62
- className="border-r flex-1"
63
- style={{ maxWidth: showFileExplorer ? "calc(50% - 8rem)" : "50%" }}
62
+ className="border-r flex-shrink-0"
63
+ style={{ width: showFileExplorer ? "calc(30% - 8rem)" : "30%" }}
64
64
  >
65
65
  <ChatPanel projectId={projectId} />
66
66
  </div>
67
67
 
68
- {/* Preview Panel */}
68
+ {/* Preview Panel - 70% width */}
69
69
  <div
70
70
  className="flex-1"
71
- style={{ maxWidth: showFileExplorer ? "calc(50% - 8rem)" : "50%" }}
71
+ style={{ width: showFileExplorer ? "calc(70%)" : "70%" }}
72
72
  >
73
73
  <PreviewPanel projectId={projectId} />
74
74
  </div>
@@ -1,6 +1,12 @@
1
1
  import { create } from "zustand";
2
2
  import { api, type UploadedFile } from "@/lib/api";
3
3
  import { Role, type ChatMessage, type StreamEvent, type ChatMode, type AskUserQuestionData } from "@claudeship/shared";
4
+ import { usePreviewStore } from "./usePreviewStore";
5
+
6
+ // Marker detection constants
7
+ const RESTART_MARKER_REGEX = /<restart-preview\s*\/>/g;
8
+ const RESTART_DEBOUNCE_MS = 3000;
9
+ let lastRestartTime = 0;
4
10
 
5
11
  export interface AttachedFile {
6
12
  id: string;
@@ -452,15 +458,34 @@ export const useChatStore = create<ChatState>((set, get) => ({
452
458
  console.log("[SSE Event]", data.type, data);
453
459
 
454
460
  if (data.type === "text" && data.content) {
455
- // Add text block
456
- const textBlock: StreamingBlock = {
457
- id: `text-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
458
- type: "text",
459
- content: data.content,
460
- };
461
- set((state) => ({
462
- streamingBlocks: [...state.streamingBlocks, textBlock],
463
- }));
461
+ // Check for restart-preview marker
462
+ const hasRestartMarker = RESTART_MARKER_REGEX.test(data.content);
463
+ // Reset regex lastIndex after test()
464
+ RESTART_MARKER_REGEX.lastIndex = 0;
465
+
466
+ // Filter out the marker from content
467
+ const filteredContent = data.content.replace(RESTART_MARKER_REGEX, '').trim();
468
+
469
+ // Trigger preview restart with debouncing
470
+ if (hasRestartMarker) {
471
+ const now = Date.now();
472
+ if (now - lastRestartTime > RESTART_DEBOUNCE_MS) {
473
+ lastRestartTime = now;
474
+ usePreviewStore.getState().restartPreview(projectId);
475
+ }
476
+ }
477
+
478
+ // Only add text block if there's content after filtering
479
+ if (filteredContent) {
480
+ const textBlock: StreamingBlock = {
481
+ id: `text-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
482
+ type: "text",
483
+ content: filteredContent,
484
+ };
485
+ set((state) => ({
486
+ streamingBlocks: [...state.streamingBlocks, textBlock],
487
+ }));
488
+ }
464
489
  } else if (data.type === "tool_use" && data.tool) {
465
490
  // Add tool_use block
466
491
  const toolBlock: StreamingBlock = {
@@ -36,6 +36,7 @@ interface PreviewState {
36
36
 
37
37
  startPreview: (projectId: string) => Promise<void>;
38
38
  stopPreview: (projectId: string) => Promise<void>;
39
+ restartPreview: (projectId: string) => Promise<void>;
39
40
  refreshPreview: () => void;
40
41
  fetchStatus: (projectId: string) => Promise<void>;
41
42
  checkProjectReady: (projectId: string) => Promise<void>;
@@ -92,6 +93,27 @@ export const usePreviewStore = create<PreviewState>((set, get) => ({
92
93
  }
93
94
  },
94
95
 
96
+ restartPreview: async (projectId: string) => {
97
+ set({ isLoading: true, error: null, status: "starting" });
98
+ try {
99
+ const result = await api.post<PreviewStatus>(
100
+ `/projects/${projectId}/preview/restart`
101
+ );
102
+ set({
103
+ status: result.status,
104
+ url: result.url || null,
105
+ isLoading: false,
106
+ });
107
+ } catch (error) {
108
+ set({
109
+ error:
110
+ error instanceof Error ? error.message : "Failed to restart preview",
111
+ status: "error",
112
+ isLoading: false,
113
+ });
114
+ }
115
+ },
116
+
95
117
  refreshPreview: () => {
96
118
  const currentUrl = get().url;
97
119
  if (currentUrl) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudeship",
3
- "version": "0.2.9",
3
+ "version": "0.2.11",
4
4
  "description": "AI-Powered App Builder using Claude Code CLI",
5
5
  "bin": {
6
6
  "claudeship": "./bin/claudeship.js"