gigaclaw 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/README.md +237 -0
- package/api/CLAUDE.md +19 -0
- package/api/index.js +265 -0
- package/bin/cli.js +823 -0
- package/bin/local.sh +85 -0
- package/bin/postinstall.js +63 -0
- package/config/index.js +26 -0
- package/config/instrumentation.js +62 -0
- package/drizzle/0000_initial.sql +52 -0
- package/drizzle/0001_nostalgic_sersi.sql +11 -0
- package/drizzle/0002_black_daimon_hellstrom.sql +19 -0
- package/drizzle/0003_rename_code_workspaces.sql +5 -0
- package/drizzle/meta/0000_snapshot.json +321 -0
- package/drizzle/meta/0001_snapshot.json +390 -0
- package/drizzle/meta/0002_snapshot.json +411 -0
- package/drizzle/meta/0003_snapshot.json +419 -0
- package/drizzle/meta/_journal.json +34 -0
- package/lib/actions.js +44 -0
- package/lib/ai/agent.js +86 -0
- package/lib/ai/index.js +342 -0
- package/lib/ai/model.js +180 -0
- package/lib/ai/tools.js +269 -0
- package/lib/ai/web-search.js +42 -0
- package/lib/auth/actions.js +28 -0
- package/lib/auth/config.js +27 -0
- package/lib/auth/edge-config.js +27 -0
- package/lib/auth/index.js +27 -0
- package/lib/auth/middleware.js +62 -0
- package/lib/channels/base.js +56 -0
- package/lib/channels/index.js +15 -0
- package/lib/channels/telegram.js +148 -0
- package/lib/chat/actions.js +579 -0
- package/lib/chat/api.js +140 -0
- package/lib/chat/components/app-sidebar.js +213 -0
- package/lib/chat/components/app-sidebar.jsx +279 -0
- package/lib/chat/components/chat-header.js +192 -0
- package/lib/chat/components/chat-header.jsx +223 -0
- package/lib/chat/components/chat-input.js +236 -0
- package/lib/chat/components/chat-input.jsx +249 -0
- package/lib/chat/components/chat-nav-context.js +11 -0
- package/lib/chat/components/chat-nav-context.jsx +11 -0
- package/lib/chat/components/chat-page.js +99 -0
- package/lib/chat/components/chat-page.jsx +121 -0
- package/lib/chat/components/chat.js +153 -0
- package/lib/chat/components/chat.jsx +199 -0
- package/lib/chat/components/chats-page.js +367 -0
- package/lib/chat/components/chats-page.jsx +394 -0
- package/lib/chat/components/code-mode-toggle.js +132 -0
- package/lib/chat/components/code-mode-toggle.jsx +163 -0
- package/lib/chat/components/crons-page.js +172 -0
- package/lib/chat/components/crons-page.jsx +244 -0
- package/lib/chat/components/greeting.js +11 -0
- package/lib/chat/components/greeting.jsx +16 -0
- package/lib/chat/components/icons.js +805 -0
- package/lib/chat/components/icons.jsx +751 -0
- package/lib/chat/components/index.js +20 -0
- package/lib/chat/components/message.js +363 -0
- package/lib/chat/components/message.jsx +422 -0
- package/lib/chat/components/messages.js +65 -0
- package/lib/chat/components/messages.jsx +74 -0
- package/lib/chat/components/notifications-page.js +56 -0
- package/lib/chat/components/notifications-page.jsx +87 -0
- package/lib/chat/components/page-layout.js +21 -0
- package/lib/chat/components/page-layout.jsx +28 -0
- package/lib/chat/components/pull-requests-page.js +103 -0
- package/lib/chat/components/pull-requests-page.jsx +113 -0
- package/lib/chat/components/settings-layout.js +39 -0
- package/lib/chat/components/settings-layout.jsx +53 -0
- package/lib/chat/components/settings-secrets-page.js +216 -0
- package/lib/chat/components/settings-secrets-page.jsx +264 -0
- package/lib/chat/components/sidebar-history-item.js +138 -0
- package/lib/chat/components/sidebar-history-item.jsx +119 -0
- package/lib/chat/components/sidebar-history.js +167 -0
- package/lib/chat/components/sidebar-history.jsx +220 -0
- package/lib/chat/components/sidebar-user-nav.js +61 -0
- package/lib/chat/components/sidebar-user-nav.jsx +77 -0
- package/lib/chat/components/swarm-page.js +157 -0
- package/lib/chat/components/swarm-page.jsx +210 -0
- package/lib/chat/components/tool-call.js +89 -0
- package/lib/chat/components/tool-call.jsx +107 -0
- package/lib/chat/components/triggers-page.js +153 -0
- package/lib/chat/components/triggers-page.jsx +221 -0
- package/lib/chat/components/ui/combobox.js +98 -0
- package/lib/chat/components/ui/combobox.jsx +114 -0
- package/lib/chat/components/ui/confirm-dialog.js +53 -0
- package/lib/chat/components/ui/confirm-dialog.jsx +57 -0
- package/lib/chat/components/ui/dropdown-menu.js +194 -0
- package/lib/chat/components/ui/dropdown-menu.jsx +215 -0
- package/lib/chat/components/ui/rename-dialog.js +78 -0
- package/lib/chat/components/ui/rename-dialog.jsx +74 -0
- package/lib/chat/components/ui/scroll-area.js +13 -0
- package/lib/chat/components/ui/scroll-area.jsx +17 -0
- package/lib/chat/components/ui/separator.js +21 -0
- package/lib/chat/components/ui/separator.jsx +18 -0
- package/lib/chat/components/ui/sheet.js +75 -0
- package/lib/chat/components/ui/sheet.jsx +95 -0
- package/lib/chat/components/ui/sidebar.js +228 -0
- package/lib/chat/components/ui/sidebar.jsx +246 -0
- package/lib/chat/components/ui/tooltip.js +56 -0
- package/lib/chat/components/ui/tooltip.jsx +66 -0
- package/lib/chat/components/upgrade-dialog.js +151 -0
- package/lib/chat/components/upgrade-dialog.jsx +170 -0
- package/lib/chat/utils.js +11 -0
- package/lib/code/actions.js +153 -0
- package/lib/code/code-page.js +22 -0
- package/lib/code/code-page.jsx +25 -0
- package/lib/code/index.js +1 -0
- package/lib/code/terminal-view.js +201 -0
- package/lib/code/terminal-view.jsx +224 -0
- package/lib/code/ws-proxy.js +80 -0
- package/lib/cron.js +246 -0
- package/lib/db/api-keys.js +163 -0
- package/lib/db/chats.js +168 -0
- package/lib/db/code-workspaces.js +110 -0
- package/lib/db/index.js +52 -0
- package/lib/db/notifications.js +99 -0
- package/lib/db/schema.js +66 -0
- package/lib/db/update-check.js +96 -0
- package/lib/db/users.js +89 -0
- package/lib/paths.js +42 -0
- package/lib/tools/create-job.js +97 -0
- package/lib/tools/docker.js +146 -0
- package/lib/tools/github.js +271 -0
- package/lib/tools/openai.js +35 -0
- package/lib/tools/telegram.js +292 -0
- package/lib/triggers.js +104 -0
- package/lib/utils/render-md.js +111 -0
- package/package.json +118 -0
- package/setup/lib/auth.mjs +81 -0
- package/setup/lib/env.mjs +21 -0
- package/setup/lib/fs-utils.mjs +20 -0
- package/setup/lib/github.mjs +149 -0
- package/setup/lib/prerequisites.mjs +155 -0
- package/setup/lib/prompts.mjs +267 -0
- package/setup/lib/providers.mjs +105 -0
- package/setup/lib/sync.mjs +125 -0
- package/setup/lib/targets.mjs +45 -0
- package/setup/lib/telegram-verify.mjs +63 -0
- package/setup/lib/telegram.mjs +76 -0
- package/setup/setup-cloud.mjs +833 -0
- package/setup/setup-local.mjs +377 -0
- package/setup/setup-telegram.mjs +265 -0
- package/setup/setup.mjs +87 -0
- package/templates/.dockerignore +5 -0
- package/templates/.env.example +104 -0
- package/templates/.github/workflows/auto-merge.yml +117 -0
- package/templates/.github/workflows/notify-job-failed.yml +64 -0
- package/templates/.github/workflows/notify-pr-complete.yml +119 -0
- package/templates/.github/workflows/rebuild-event-handler.yml +121 -0
- package/templates/.github/workflows/run-job.yml +89 -0
- package/templates/.github/workflows/upgrade-event-handler.yml +62 -0
- package/templates/.gitignore.template +45 -0
- package/templates/.pi/extensions/env-sanitizer/index.ts +48 -0
- package/templates/.pi/extensions/env-sanitizer/package.json +5 -0
- package/templates/CLAUDE.md +29 -0
- package/templates/CLAUDE.md.template +308 -0
- package/templates/app/api/[...gigaclaw]/route.js +1 -0
- package/templates/app/api/auth/[...nextauth]/route.js +1 -0
- package/templates/app/chat/[chatId]/page.js +9 -0
- package/templates/app/chats/page.js +7 -0
- package/templates/app/code/[codeWorkspaceId]/page.js +9 -0
- package/templates/app/components/ascii-logo.jsx +12 -0
- package/templates/app/components/login-form.jsx +92 -0
- package/templates/app/components/setup-form.jsx +82 -0
- package/templates/app/components/theme-provider.jsx +11 -0
- package/templates/app/components/theme-toggle.jsx +38 -0
- package/templates/app/components/ui/button.jsx +21 -0
- package/templates/app/components/ui/card.jsx +23 -0
- package/templates/app/components/ui/input.jsx +10 -0
- package/templates/app/components/ui/label.jsx +10 -0
- package/templates/app/crons/page.js +5 -0
- package/templates/app/globals.css +90 -0
- package/templates/app/layout.js +33 -0
- package/templates/app/login/page.js +15 -0
- package/templates/app/notifications/page.js +7 -0
- package/templates/app/page.js +7 -0
- package/templates/app/pull-requests/page.js +7 -0
- package/templates/app/settings/crons/page.js +5 -0
- package/templates/app/settings/layout.js +7 -0
- package/templates/app/settings/page.js +5 -0
- package/templates/app/settings/secrets/page.js +5 -0
- package/templates/app/settings/triggers/page.js +5 -0
- package/templates/app/stream/chat/route.js +1 -0
- package/templates/app/swarm/page.js +7 -0
- package/templates/app/triggers/page.js +5 -0
- package/templates/config/CODE_PLANNING.md +14 -0
- package/templates/config/CRONS.json +56 -0
- package/templates/config/HEARTBEAT.md +3 -0
- package/templates/config/JOB_AGENT.md +30 -0
- package/templates/config/JOB_PLANNING.md +240 -0
- package/templates/config/JOB_SUMMARY.md +130 -0
- package/templates/config/SKILL_BUILDING_GUIDE.md +96 -0
- package/templates/config/SOUL.md +48 -0
- package/templates/config/TRIGGERS.json +58 -0
- package/templates/config/WEB_SEARCH_AVAILABLE.md +5 -0
- package/templates/config/WEB_SEARCH_UNAVAILABLE.md +3 -0
- package/templates/docker/claude-code-job/Dockerfile +34 -0
- package/templates/docker/claude-code-job/entrypoint.sh +149 -0
- package/templates/docker/claude-code-workspace/.tmux.conf +5 -0
- package/templates/docker/claude-code-workspace/Dockerfile +61 -0
- package/templates/docker/claude-code-workspace/entrypoint.sh +51 -0
- package/templates/docker/event-handler/Dockerfile +20 -0
- package/templates/docker/event-handler/ecosystem.config.cjs +7 -0
- package/templates/docker/pi-coding-agent-job/Dockerfile +51 -0
- package/templates/docker/pi-coding-agent-job/entrypoint.sh +164 -0
- package/templates/docker-compose.local.yml +78 -0
- package/templates/docker-compose.yml +64 -0
- package/templates/instrumentation.js +6 -0
- package/templates/middleware.js +23 -0
- package/templates/next.config.mjs +3 -0
- package/templates/postcss.config.mjs +5 -0
- package/templates/public/favicon.ico +0 -0
- package/templates/server.js +25 -0
- package/templates/skills/LICENSE +21 -0
- package/templates/skills/README.md +119 -0
- package/templates/skills/brave-search/SKILL.md +79 -0
- package/templates/skills/brave-search/content.js +86 -0
- package/templates/skills/brave-search/package-lock.json +621 -0
- package/templates/skills/brave-search/package.json +14 -0
- package/templates/skills/brave-search/search.js +199 -0
- package/templates/skills/browser-tools/SKILL.md +196 -0
- package/templates/skills/browser-tools/browser-content.js +103 -0
- package/templates/skills/browser-tools/browser-cookies.js +35 -0
- package/templates/skills/browser-tools/browser-eval.js +53 -0
- package/templates/skills/browser-tools/browser-hn-scraper.js +108 -0
- package/templates/skills/browser-tools/browser-nav.js +44 -0
- package/templates/skills/browser-tools/browser-pick.js +162 -0
- package/templates/skills/browser-tools/browser-screenshot.js +34 -0
- package/templates/skills/browser-tools/browser-start.js +87 -0
- package/templates/skills/browser-tools/package-lock.json +2556 -0
- package/templates/skills/browser-tools/package.json +19 -0
- package/templates/skills/google-docs/SKILL.md +23 -0
- package/templates/skills/google-docs/create.sh +69 -0
- package/templates/skills/google-drive/SKILL.md +47 -0
- package/templates/skills/google-drive/delete.sh +47 -0
- package/templates/skills/google-drive/download.sh +50 -0
- package/templates/skills/google-drive/list.sh +41 -0
- package/templates/skills/google-drive/upload.sh +76 -0
- package/templates/skills/kie-ai/SKILL.md +38 -0
- package/templates/skills/kie-ai/generate-image.sh +77 -0
- package/templates/skills/kie-ai/generate-video.sh +69 -0
- package/templates/skills/llm-secrets/SKILL.md +34 -0
- package/templates/skills/llm-secrets/llm-secrets.js +33 -0
- package/templates/skills/modify-self/SKILL.md +12 -0
- package/templates/skills/youtube-transcript/SKILL.md +41 -0
- package/templates/skills/youtube-transcript/package-lock.json +24 -0
- package/templates/skills/youtube-transcript/package.json +8 -0
- package/templates/skills/youtube-transcript/transcript.js +84 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useRef, useEffect, createContext, useContext, cloneElement } from 'react';
|
|
4
|
+
import { cn } from '../../utils.js';
|
|
5
|
+
|
|
6
|
+
const TooltipContext = createContext({ open: false });
|
|
7
|
+
|
|
8
|
+
export function TooltipProvider({ children, delayDuration = 200 }) {
|
|
9
|
+
return children;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function Tooltip({ children }) {
|
|
13
|
+
const [open, setOpen] = useState(false);
|
|
14
|
+
const timeoutRef = useRef(null);
|
|
15
|
+
|
|
16
|
+
const handleOpen = () => {
|
|
17
|
+
timeoutRef.current = setTimeout(() => setOpen(true), 200);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const handleClose = () => {
|
|
21
|
+
clearTimeout(timeoutRef.current);
|
|
22
|
+
setOpen(false);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
useEffect(() => () => clearTimeout(timeoutRef.current), []);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<TooltipContext.Provider value={{ open, handleOpen, handleClose }}>
|
|
29
|
+
<div className="relative inline-flex" onMouseEnter={handleOpen} onMouseLeave={handleClose}>
|
|
30
|
+
{children}
|
|
31
|
+
</div>
|
|
32
|
+
</TooltipContext.Provider>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function TooltipTrigger({ children, asChild }) {
|
|
37
|
+
if (asChild && children) {
|
|
38
|
+
return children;
|
|
39
|
+
}
|
|
40
|
+
return children;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function TooltipContent({ children, className, align = 'center', side = 'bottom', ...props }) {
|
|
44
|
+
const { open } = useContext(TooltipContext);
|
|
45
|
+
if (!open) return null;
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div
|
|
49
|
+
className={cn(
|
|
50
|
+
'absolute z-50 overflow-hidden rounded-md border border-border bg-muted px-3 py-1.5 text-sm text-foreground shadow-md',
|
|
51
|
+
'animate-in fade-in-0 zoom-in-95',
|
|
52
|
+
side === 'bottom' && 'top-full mt-1',
|
|
53
|
+
side === 'top' && 'bottom-full mb-1',
|
|
54
|
+
side === 'right' && 'left-full ml-1 top-1/2 -translate-y-1/2',
|
|
55
|
+
side === 'left' && 'right-full mr-1 top-1/2 -translate-y-1/2',
|
|
56
|
+
side !== 'right' && side !== 'left' && align === 'center' && 'left-1/2 -translate-x-1/2',
|
|
57
|
+
side !== 'right' && side !== 'left' && align === 'end' && 'right-0',
|
|
58
|
+
side !== 'right' && side !== 'left' && align === 'start' && 'left-0',
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useEffect, useCallback } from "react";
|
|
4
|
+
import { ArrowUpCircleIcon, SpinnerIcon, CheckIcon, XIcon, RefreshIcon } from "./icons.js";
|
|
5
|
+
import { triggerUpgrade } from "../actions.js";
|
|
6
|
+
function UpgradeDialog({ open, onClose, version, updateAvailable, changelog }) {
|
|
7
|
+
const [upgrading, setUpgrading] = useState(false);
|
|
8
|
+
const [result, setResult] = useState(null);
|
|
9
|
+
const handleClose = useCallback(() => onClose(), [onClose]);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (!open) return;
|
|
12
|
+
const handleEsc = (e) => {
|
|
13
|
+
if (e.key === "Escape") handleClose();
|
|
14
|
+
};
|
|
15
|
+
document.addEventListener("keydown", handleEsc);
|
|
16
|
+
return () => document.removeEventListener("keydown", handleEsc);
|
|
17
|
+
}, [open, handleClose]);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!open) {
|
|
20
|
+
setUpgrading(false);
|
|
21
|
+
setResult(null);
|
|
22
|
+
}
|
|
23
|
+
}, [open]);
|
|
24
|
+
if (!open) return null;
|
|
25
|
+
const handleUpgrade = async () => {
|
|
26
|
+
setUpgrading(true);
|
|
27
|
+
setResult(null);
|
|
28
|
+
try {
|
|
29
|
+
await triggerUpgrade();
|
|
30
|
+
setResult("success");
|
|
31
|
+
} catch {
|
|
32
|
+
setResult("error");
|
|
33
|
+
} finally {
|
|
34
|
+
setUpgrading(false);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
|
|
38
|
+
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 bg-black/50", onClick: handleClose }),
|
|
39
|
+
/* @__PURE__ */ jsx("div", { className: "relative z-50 w-full max-w-md rounded-lg border border-border bg-background p-6 shadow-lg", onClick: (e) => e.stopPropagation(), children: result === "success" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
40
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
41
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: "Upgrade Initiated" }),
|
|
42
|
+
/* @__PURE__ */ jsx("button", { onClick: handleClose, className: "text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx(XIcon, { size: 16 }) })
|
|
43
|
+
] }),
|
|
44
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
45
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-10 w-10 rounded-full bg-emerald-500/10 shrink-0", children: /* @__PURE__ */ jsx(CheckIcon, { size: 20, className: "text-emerald-500" }) }),
|
|
46
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm font-medium", children: [
|
|
47
|
+
"Upgrading to ",
|
|
48
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono text-emerald-500", children: [
|
|
49
|
+
"v",
|
|
50
|
+
updateAvailable
|
|
51
|
+
] })
|
|
52
|
+
] })
|
|
53
|
+
] }),
|
|
54
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3 text-sm text-muted-foreground", children: [
|
|
55
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
56
|
+
"The upgrade process has been triggered and could take",
|
|
57
|
+
" ",
|
|
58
|
+
/* @__PURE__ */ jsx("strong", { className: "text-foreground", children: "5\u201310 minutes" }),
|
|
59
|
+
" to complete."
|
|
60
|
+
] }),
|
|
61
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
62
|
+
"You can monitor progress from the",
|
|
63
|
+
" ",
|
|
64
|
+
/* @__PURE__ */ jsx("a", { href: "/swarm", className: "text-emerald-500 hover:underline font-medium", children: "Swarm" }),
|
|
65
|
+
" page."
|
|
66
|
+
] }),
|
|
67
|
+
/* @__PURE__ */ jsx("p", { children: "The site may be briefly unresponsive for a few seconds when the server restarts." }),
|
|
68
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
69
|
+
"Some files (prompts, crons, triggers) won't be auto-updated to avoid breaking your bot.",
|
|
70
|
+
" ",
|
|
71
|
+
/* @__PURE__ */ jsx(
|
|
72
|
+
"a",
|
|
73
|
+
{
|
|
74
|
+
href: "https://github.com/gignaati/gigaclaw?tab=readme-ov-file#understanding-init",
|
|
75
|
+
target: "_blank",
|
|
76
|
+
rel: "noopener noreferrer",
|
|
77
|
+
className: "text-emerald-500 hover:underline",
|
|
78
|
+
children: "Learn more"
|
|
79
|
+
}
|
|
80
|
+
),
|
|
81
|
+
"."
|
|
82
|
+
] })
|
|
83
|
+
] }),
|
|
84
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 rounded-md border border-border bg-muted/30 p-3", children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
85
|
+
"If you hit unrecoverable errors, see the",
|
|
86
|
+
" ",
|
|
87
|
+
/* @__PURE__ */ jsx(
|
|
88
|
+
"a",
|
|
89
|
+
{
|
|
90
|
+
href: "https://github.com/gignaati/gigaclaw?tab=readme-ov-file#manual-updating",
|
|
91
|
+
target: "_blank",
|
|
92
|
+
rel: "noopener noreferrer",
|
|
93
|
+
className: "text-emerald-500 hover:underline",
|
|
94
|
+
children: "manual update guide"
|
|
95
|
+
}
|
|
96
|
+
),
|
|
97
|
+
"."
|
|
98
|
+
] }) })
|
|
99
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
100
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-4", children: [
|
|
101
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: "Upgrade Available" }),
|
|
102
|
+
/* @__PURE__ */ jsx("button", { onClick: handleClose, className: "text-muted-foreground hover:text-foreground", children: /* @__PURE__ */ jsx(XIcon, { size: 16 }) })
|
|
103
|
+
] }),
|
|
104
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
105
|
+
/* @__PURE__ */ jsx(ArrowUpCircleIcon, { size: 24 }),
|
|
106
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
107
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Installed version" }),
|
|
108
|
+
/* @__PURE__ */ jsxs("p", { className: "text-lg font-mono font-semibold", children: [
|
|
109
|
+
"v",
|
|
110
|
+
version
|
|
111
|
+
] })
|
|
112
|
+
] })
|
|
113
|
+
] }),
|
|
114
|
+
/* @__PURE__ */ jsx("div", { className: "rounded-md border border-emerald-500/30 bg-emerald-500/5 p-3 mb-4", children: /* @__PURE__ */ jsxs("p", { className: "text-sm font-medium", children: [
|
|
115
|
+
"Version ",
|
|
116
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono text-emerald-500", children: [
|
|
117
|
+
"v",
|
|
118
|
+
updateAvailable
|
|
119
|
+
] }),
|
|
120
|
+
" is available"
|
|
121
|
+
] }) }),
|
|
122
|
+
changelog && /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
123
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium mb-2", children: "What's new" }),
|
|
124
|
+
/* @__PURE__ */ jsx("div", { className: "max-h-48 overflow-y-auto rounded-md border border-border bg-muted/30 p-3 text-sm text-muted-foreground whitespace-pre-wrap", children: changelog })
|
|
125
|
+
] }),
|
|
126
|
+
/* @__PURE__ */ jsx(
|
|
127
|
+
"button",
|
|
128
|
+
{
|
|
129
|
+
onClick: handleUpgrade,
|
|
130
|
+
disabled: upgrading,
|
|
131
|
+
className: "w-full inline-flex items-center justify-center gap-2 rounded-md px-4 py-2.5 text-sm font-medium bg-emerald-500 text-white hover:bg-emerald-600 disabled:opacity-50 disabled:pointer-events-none",
|
|
132
|
+
children: upgrading ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
133
|
+
/* @__PURE__ */ jsx(SpinnerIcon, { size: 16 }),
|
|
134
|
+
"Triggering upgrade..."
|
|
135
|
+
] }) : result === "error" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
136
|
+
/* @__PURE__ */ jsx(RefreshIcon, { size: 16 }),
|
|
137
|
+
"Retry"
|
|
138
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
139
|
+
/* @__PURE__ */ jsx(ArrowUpCircleIcon, { size: 16 }),
|
|
140
|
+
"Upgrade to v",
|
|
141
|
+
updateAvailable
|
|
142
|
+
] })
|
|
143
|
+
}
|
|
144
|
+
),
|
|
145
|
+
result === "error" && /* @__PURE__ */ jsx("p", { className: "text-xs text-red-400 mt-3", children: "Failed to trigger the upgrade workflow. Check that your GitHub token has workflow permissions." })
|
|
146
|
+
] }) })
|
|
147
|
+
] });
|
|
148
|
+
}
|
|
149
|
+
export {
|
|
150
|
+
UpgradeDialog
|
|
151
|
+
};
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useState, useEffect, useCallback } from 'react';
|
|
4
|
+
import { ArrowUpCircleIcon, SpinnerIcon, CheckIcon, XIcon, RefreshIcon } from './icons.js';
|
|
5
|
+
import { triggerUpgrade } from '../actions.js';
|
|
6
|
+
|
|
7
|
+
export function UpgradeDialog({ open, onClose, version, updateAvailable, changelog }) {
|
|
8
|
+
const [upgrading, setUpgrading] = useState(false);
|
|
9
|
+
const [result, setResult] = useState(null);
|
|
10
|
+
|
|
11
|
+
const handleClose = useCallback(() => onClose(), [onClose]);
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!open) return;
|
|
15
|
+
const handleEsc = (e) => {
|
|
16
|
+
if (e.key === 'Escape') handleClose();
|
|
17
|
+
};
|
|
18
|
+
document.addEventListener('keydown', handleEsc);
|
|
19
|
+
return () => document.removeEventListener('keydown', handleEsc);
|
|
20
|
+
}, [open, handleClose]);
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!open) {
|
|
24
|
+
setUpgrading(false);
|
|
25
|
+
setResult(null);
|
|
26
|
+
}
|
|
27
|
+
}, [open]);
|
|
28
|
+
|
|
29
|
+
if (!open) return null;
|
|
30
|
+
|
|
31
|
+
const handleUpgrade = async () => {
|
|
32
|
+
setUpgrading(true);
|
|
33
|
+
setResult(null);
|
|
34
|
+
try {
|
|
35
|
+
await triggerUpgrade();
|
|
36
|
+
setResult('success');
|
|
37
|
+
} catch {
|
|
38
|
+
setResult('error');
|
|
39
|
+
} finally {
|
|
40
|
+
setUpgrading(false);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
|
46
|
+
<div className="fixed inset-0 bg-black/50" onClick={handleClose} />
|
|
47
|
+
<div className="relative z-50 w-full max-w-md rounded-lg border border-border bg-background p-6 shadow-lg" onClick={(e) => e.stopPropagation()}>
|
|
48
|
+
{result === 'success' ? (
|
|
49
|
+
<>
|
|
50
|
+
<div className="flex items-center justify-between mb-4">
|
|
51
|
+
<h3 className="text-lg font-semibold">Upgrade Initiated</h3>
|
|
52
|
+
<button onClick={handleClose} className="text-muted-foreground hover:text-foreground">
|
|
53
|
+
<XIcon size={16} />
|
|
54
|
+
</button>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<div className="flex items-center gap-3 mb-4">
|
|
58
|
+
<div className="flex items-center justify-center h-10 w-10 rounded-full bg-emerald-500/10 shrink-0">
|
|
59
|
+
<CheckIcon size={20} className="text-emerald-500" />
|
|
60
|
+
</div>
|
|
61
|
+
<p className="text-sm font-medium">
|
|
62
|
+
Upgrading to <span className="font-mono text-emerald-500">v{updateAvailable}</span>
|
|
63
|
+
</p>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div className="space-y-3 text-sm text-muted-foreground">
|
|
67
|
+
<p>
|
|
68
|
+
The upgrade process has been triggered and could take{' '}
|
|
69
|
+
<strong className="text-foreground">5–10 minutes</strong> to complete.
|
|
70
|
+
</p>
|
|
71
|
+
<p>
|
|
72
|
+
You can monitor progress from the{' '}
|
|
73
|
+
<a href="/swarm" className="text-emerald-500 hover:underline font-medium">Swarm</a> page.
|
|
74
|
+
</p>
|
|
75
|
+
<p>
|
|
76
|
+
The site may be briefly unresponsive for a few seconds when the server restarts.
|
|
77
|
+
</p>
|
|
78
|
+
<p>
|
|
79
|
+
Some files (prompts, crons, triggers) won't be auto-updated to avoid breaking your bot.{' '}
|
|
80
|
+
<a
|
|
81
|
+
href="https://github.com/gignaati/gigaclaw?tab=readme-ov-file#understanding-init"
|
|
82
|
+
target="_blank"
|
|
83
|
+
rel="noopener noreferrer"
|
|
84
|
+
className="text-emerald-500 hover:underline"
|
|
85
|
+
>
|
|
86
|
+
Learn more
|
|
87
|
+
</a>.
|
|
88
|
+
</p>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<div className="mt-4 rounded-md border border-border bg-muted/30 p-3">
|
|
92
|
+
<p className="text-xs text-muted-foreground">
|
|
93
|
+
If you hit unrecoverable errors, see the{' '}
|
|
94
|
+
<a
|
|
95
|
+
href="https://github.com/gignaati/gigaclaw?tab=readme-ov-file#manual-updating"
|
|
96
|
+
target="_blank"
|
|
97
|
+
rel="noopener noreferrer"
|
|
98
|
+
className="text-emerald-500 hover:underline"
|
|
99
|
+
>
|
|
100
|
+
manual update guide
|
|
101
|
+
</a>.
|
|
102
|
+
</p>
|
|
103
|
+
</div>
|
|
104
|
+
</>
|
|
105
|
+
) : (
|
|
106
|
+
<>
|
|
107
|
+
<div className="flex items-center justify-between mb-4">
|
|
108
|
+
<h3 className="text-lg font-semibold">Upgrade Available</h3>
|
|
109
|
+
<button onClick={handleClose} className="text-muted-foreground hover:text-foreground">
|
|
110
|
+
<XIcon size={16} />
|
|
111
|
+
</button>
|
|
112
|
+
</div>
|
|
113
|
+
|
|
114
|
+
<div className="flex items-center gap-3 mb-4">
|
|
115
|
+
<ArrowUpCircleIcon size={24} />
|
|
116
|
+
<div>
|
|
117
|
+
<p className="text-sm text-muted-foreground">Installed version</p>
|
|
118
|
+
<p className="text-lg font-mono font-semibold">v{version}</p>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div className="rounded-md border border-emerald-500/30 bg-emerald-500/5 p-3 mb-4">
|
|
123
|
+
<p className="text-sm font-medium">
|
|
124
|
+
Version <span className="font-mono text-emerald-500">v{updateAvailable}</span> is available
|
|
125
|
+
</p>
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
{changelog && (
|
|
129
|
+
<div className="mb-4">
|
|
130
|
+
<p className="text-sm font-medium mb-2">What's new</p>
|
|
131
|
+
<div className="max-h-48 overflow-y-auto rounded-md border border-border bg-muted/30 p-3 text-sm text-muted-foreground whitespace-pre-wrap">
|
|
132
|
+
{changelog}
|
|
133
|
+
</div>
|
|
134
|
+
</div>
|
|
135
|
+
)}
|
|
136
|
+
|
|
137
|
+
<button
|
|
138
|
+
onClick={handleUpgrade}
|
|
139
|
+
disabled={upgrading}
|
|
140
|
+
className="w-full inline-flex items-center justify-center gap-2 rounded-md px-4 py-2.5 text-sm font-medium bg-emerald-500 text-white hover:bg-emerald-600 disabled:opacity-50 disabled:pointer-events-none"
|
|
141
|
+
>
|
|
142
|
+
{upgrading ? (
|
|
143
|
+
<>
|
|
144
|
+
<SpinnerIcon size={16} />
|
|
145
|
+
Triggering upgrade...
|
|
146
|
+
</>
|
|
147
|
+
) : result === 'error' ? (
|
|
148
|
+
<>
|
|
149
|
+
<RefreshIcon size={16} />
|
|
150
|
+
Retry
|
|
151
|
+
</>
|
|
152
|
+
) : (
|
|
153
|
+
<>
|
|
154
|
+
<ArrowUpCircleIcon size={16} />
|
|
155
|
+
Upgrade to v{updateAvailable}
|
|
156
|
+
</>
|
|
157
|
+
)}
|
|
158
|
+
</button>
|
|
159
|
+
|
|
160
|
+
{result === 'error' && (
|
|
161
|
+
<p className="text-xs text-red-400 mt-3">
|
|
162
|
+
Failed to trigger the upgrade workflow. Check that your GitHub token has workflow permissions.
|
|
163
|
+
</p>
|
|
164
|
+
)}
|
|
165
|
+
</>
|
|
166
|
+
)}
|
|
167
|
+
</div>
|
|
168
|
+
</div>
|
|
169
|
+
);
|
|
170
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Merge Tailwind CSS classes with conflict resolution.
|
|
6
|
+
* @param {...any} inputs - Class name inputs
|
|
7
|
+
* @returns {string}
|
|
8
|
+
*/
|
|
9
|
+
export function cn(...inputs) {
|
|
10
|
+
return twMerge(clsx(inputs));
|
|
11
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
'use server';
|
|
2
|
+
|
|
3
|
+
import { auth } from '../auth/index.js';
|
|
4
|
+
import {
|
|
5
|
+
createCodeWorkspace as dbCreateCodeWorkspace,
|
|
6
|
+
getCodeWorkspaceById,
|
|
7
|
+
getCodeWorkspacesByUser,
|
|
8
|
+
updateCodeWorkspaceTitle,
|
|
9
|
+
toggleCodeWorkspaceStarred,
|
|
10
|
+
deleteCodeWorkspace as dbDeleteCodeWorkspace,
|
|
11
|
+
} from '../db/code-workspaces.js';
|
|
12
|
+
|
|
13
|
+
const RECOVERABLE_STATES = new Set(['exited', 'created', 'paused']);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get the authenticated user or throw.
|
|
17
|
+
*/
|
|
18
|
+
async function requireAuth() {
|
|
19
|
+
const session = await auth();
|
|
20
|
+
if (!session?.user?.id) {
|
|
21
|
+
throw new Error('Unauthorized');
|
|
22
|
+
}
|
|
23
|
+
return session.user;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Get all code workspaces for the authenticated user.
|
|
28
|
+
* @returns {Promise<object[]>}
|
|
29
|
+
*/
|
|
30
|
+
export async function getCodeWorkspaces() {
|
|
31
|
+
const user = await requireAuth();
|
|
32
|
+
return getCodeWorkspacesByUser(user.id);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Create a new code workspace.
|
|
37
|
+
* @param {string} containerName - Docker container DNS name
|
|
38
|
+
* @param {string} [title='Code Workspace']
|
|
39
|
+
* @returns {Promise<object>}
|
|
40
|
+
*/
|
|
41
|
+
export async function createCodeWorkspace(containerName, title = 'Code Workspace') {
|
|
42
|
+
const user = await requireAuth();
|
|
43
|
+
return dbCreateCodeWorkspace(user.id, { containerName, title });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Rename a code workspace (with ownership check).
|
|
48
|
+
* @param {string} id
|
|
49
|
+
* @param {string} title
|
|
50
|
+
* @returns {Promise<{success: boolean}>}
|
|
51
|
+
*/
|
|
52
|
+
export async function renameCodeWorkspace(id, title) {
|
|
53
|
+
const user = await requireAuth();
|
|
54
|
+
const workspace = getCodeWorkspaceById(id);
|
|
55
|
+
if (!workspace || workspace.userId !== user.id) {
|
|
56
|
+
return { success: false };
|
|
57
|
+
}
|
|
58
|
+
updateCodeWorkspaceTitle(id, title);
|
|
59
|
+
return { success: true };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Toggle a code workspace's starred status (with ownership check).
|
|
64
|
+
* @param {string} id
|
|
65
|
+
* @returns {Promise<{success: boolean, starred?: number}>}
|
|
66
|
+
*/
|
|
67
|
+
export async function starCodeWorkspace(id) {
|
|
68
|
+
const user = await requireAuth();
|
|
69
|
+
const workspace = getCodeWorkspaceById(id);
|
|
70
|
+
if (!workspace || workspace.userId !== user.id) {
|
|
71
|
+
return { success: false };
|
|
72
|
+
}
|
|
73
|
+
const starred = toggleCodeWorkspaceStarred(id);
|
|
74
|
+
return { success: true, starred };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Delete a code workspace (with ownership check).
|
|
79
|
+
* @param {string} id
|
|
80
|
+
* @returns {Promise<{success: boolean}>}
|
|
81
|
+
*/
|
|
82
|
+
export async function deleteCodeWorkspace(id) {
|
|
83
|
+
const user = await requireAuth();
|
|
84
|
+
const workspace = getCodeWorkspaceById(id);
|
|
85
|
+
if (!workspace || workspace.userId !== user.id) {
|
|
86
|
+
return { success: false };
|
|
87
|
+
}
|
|
88
|
+
dbDeleteCodeWorkspace(id);
|
|
89
|
+
return { success: true };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Ensure a code workspace's Docker container is running.
|
|
94
|
+
* Recovers stopped/removed containers automatically.
|
|
95
|
+
* @param {string} id - Workspace ID
|
|
96
|
+
* @returns {Promise<{status: string, message?: string}>}
|
|
97
|
+
*/
|
|
98
|
+
export async function ensureCodeWorkspaceContainer(id) {
|
|
99
|
+
const user = await requireAuth();
|
|
100
|
+
const workspace = getCodeWorkspaceById(id);
|
|
101
|
+
if (!workspace || workspace.userId !== user.id) {
|
|
102
|
+
return { status: 'error', message: 'Workspace not found' };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!workspace.containerName) {
|
|
106
|
+
return { status: 'no_container' };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const { inspectContainer, startContainer, removeContainer, createCodeWorkspaceContainer } =
|
|
111
|
+
await import('../tools/docker.js');
|
|
112
|
+
|
|
113
|
+
const info = await inspectContainer(workspace.containerName);
|
|
114
|
+
|
|
115
|
+
if (!info) {
|
|
116
|
+
// Container not found — recreate
|
|
117
|
+
await createCodeWorkspaceContainer({
|
|
118
|
+
containerName: workspace.containerName,
|
|
119
|
+
repo: workspace.repo,
|
|
120
|
+
branch: workspace.branch,
|
|
121
|
+
codingAgent: workspace.codingAgent,
|
|
122
|
+
});
|
|
123
|
+
return { status: 'created' };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const state = info.State?.Status;
|
|
127
|
+
|
|
128
|
+
if (state === 'running') {
|
|
129
|
+
return { status: 'running' };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (RECOVERABLE_STATES.has(state)) {
|
|
133
|
+
try {
|
|
134
|
+
await startContainer(workspace.containerName);
|
|
135
|
+
return { status: 'started' };
|
|
136
|
+
} catch {
|
|
137
|
+
// Start failed — fall through to remove + recreate
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Dead, bad state, or start failed — remove and recreate
|
|
142
|
+
await removeContainer(workspace.containerName);
|
|
143
|
+
await createCodeWorkspaceContainer({
|
|
144
|
+
containerName: workspace.containerName,
|
|
145
|
+
repo: workspace.repo,
|
|
146
|
+
branch: workspace.branch,
|
|
147
|
+
codingAgent: workspace.codingAgent,
|
|
148
|
+
});
|
|
149
|
+
return { status: 'created' };
|
|
150
|
+
} catch (err) {
|
|
151
|
+
return { status: 'error', message: err.message };
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import dynamic from "next/dynamic";
|
|
4
|
+
import { AppSidebar } from "../chat/components/app-sidebar.js";
|
|
5
|
+
import { SidebarProvider, SidebarInset } from "../chat/components/ui/sidebar.js";
|
|
6
|
+
import { ChatNavProvider } from "../chat/components/chat-nav-context.js";
|
|
7
|
+
import { ChatHeader } from "../chat/components/chat-header.js";
|
|
8
|
+
const TerminalView = dynamic(() => import("./terminal-view.js"), { ssr: false });
|
|
9
|
+
function CodePage({ session, codeWorkspaceId }) {
|
|
10
|
+
return /* @__PURE__ */ jsx(ChatNavProvider, { value: { activeChatId: null, navigateToChat: (id) => {
|
|
11
|
+
window.location.href = id ? `/chat/${id}` : "/";
|
|
12
|
+
} }, children: /* @__PURE__ */ jsxs(SidebarProvider, { children: [
|
|
13
|
+
/* @__PURE__ */ jsx(AppSidebar, { user: session.user }),
|
|
14
|
+
/* @__PURE__ */ jsx(SidebarInset, { children: /* @__PURE__ */ jsxs("div", { className: "flex h-svh flex-col overflow-hidden", children: [
|
|
15
|
+
/* @__PURE__ */ jsx(ChatHeader, { workspaceId: codeWorkspaceId }),
|
|
16
|
+
/* @__PURE__ */ jsx(TerminalView, { codeWorkspaceId })
|
|
17
|
+
] }) })
|
|
18
|
+
] }) });
|
|
19
|
+
}
|
|
20
|
+
export {
|
|
21
|
+
CodePage as default
|
|
22
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import dynamic from 'next/dynamic';
|
|
4
|
+
import { AppSidebar } from '../chat/components/app-sidebar.js';
|
|
5
|
+
import { SidebarProvider, SidebarInset } from '../chat/components/ui/sidebar.js';
|
|
6
|
+
import { ChatNavProvider } from '../chat/components/chat-nav-context.js';
|
|
7
|
+
import { ChatHeader } from '../chat/components/chat-header.js';
|
|
8
|
+
|
|
9
|
+
const TerminalView = dynamic(() => import('./terminal-view.js'), { ssr: false });
|
|
10
|
+
|
|
11
|
+
export default function CodePage({ session, codeWorkspaceId }) {
|
|
12
|
+
return (
|
|
13
|
+
<ChatNavProvider value={{ activeChatId: null, navigateToChat: (id) => { window.location.href = id ? `/chat/${id}` : '/'; } }}>
|
|
14
|
+
<SidebarProvider>
|
|
15
|
+
<AppSidebar user={session.user} />
|
|
16
|
+
<SidebarInset>
|
|
17
|
+
<div className="flex h-svh flex-col overflow-hidden">
|
|
18
|
+
<ChatHeader workspaceId={codeWorkspaceId} />
|
|
19
|
+
<TerminalView codeWorkspaceId={codeWorkspaceId} />
|
|
20
|
+
</div>
|
|
21
|
+
</SidebarInset>
|
|
22
|
+
</SidebarProvider>
|
|
23
|
+
</ChatNavProvider>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CodePage } from './code-page.js';
|