thepopebot 1.2.75-beta.20 → 1.2.75-beta.22
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/lib/chat/actions.js +9 -0
- package/lib/chat/components/chats-page.js +6 -1
- package/lib/chat/components/chats-page.jsx +3 -1
- package/lib/chat/components/code-mode-toggle.js +9 -13
- package/lib/chat/components/code-mode-toggle.jsx +17 -13
- package/lib/chat/components/ui/confirm-dialog.js +32 -28
- package/lib/chat/components/ui/confirm-dialog.jsx +6 -4
- package/lib/code/actions.js +10 -10
- package/lib/code/code-page.js +40 -40
- package/lib/code/code-page.jsx +36 -36
- package/lib/code/terminal-view.js +7 -7
- package/lib/code/terminal-view.jsx +7 -7
- package/package.json +2 -1
package/lib/chat/actions.js
CHANGED
|
@@ -95,6 +95,15 @@ export async function deleteChat(chatId) {
|
|
|
95
95
|
if (!chat || chat.userId !== user.id) {
|
|
96
96
|
return { success: false };
|
|
97
97
|
}
|
|
98
|
+
|
|
99
|
+
// Clean up associated code workspace container and volume
|
|
100
|
+
if (chat.codeWorkspaceId) {
|
|
101
|
+
try {
|
|
102
|
+
const { deleteCodeWorkspace } = await import('../code/actions.js');
|
|
103
|
+
await deleteCodeWorkspace(chat.codeWorkspaceId);
|
|
104
|
+
} catch {}
|
|
105
|
+
}
|
|
106
|
+
|
|
98
107
|
dbDeleteChat(chatId);
|
|
99
108
|
return { success: true };
|
|
100
109
|
}
|
|
@@ -220,6 +220,7 @@ function ChatRow({ chat, onNavigate, onDelete, onStar, onRename }) {
|
|
|
220
220
|
const [editing, setEditing] = useState(false);
|
|
221
221
|
const [editTitle, setEditTitle] = useState(chat.title || "");
|
|
222
222
|
const inputRef = useRef(null);
|
|
223
|
+
const menuRef = useRef(null);
|
|
223
224
|
const showMenu = hovered || dropdownOpen;
|
|
224
225
|
useEffect(() => {
|
|
225
226
|
if (editing && inputRef.current) {
|
|
@@ -255,6 +256,10 @@ function ChatRow({ chat, onNavigate, onDelete, onStar, onRename }) {
|
|
|
255
256
|
e.preventDefault();
|
|
256
257
|
return;
|
|
257
258
|
}
|
|
259
|
+
if (menuRef.current && menuRef.current.contains(e.target)) {
|
|
260
|
+
e.preventDefault();
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
258
263
|
e.preventDefault();
|
|
259
264
|
if (chat.codeWorkspaceId && chat.containerName) {
|
|
260
265
|
window.location.href = `/code/${chat.codeWorkspaceId}`;
|
|
@@ -299,7 +304,7 @@ function ChatRow({ chat, onNavigate, onDelete, onStar, onRename }) {
|
|
|
299
304
|
timeAgo(chat.updatedAt)
|
|
300
305
|
] })
|
|
301
306
|
] }),
|
|
302
|
-
!editing && /* @__PURE__ */ jsx("div", { className: cn(
|
|
307
|
+
!editing && /* @__PURE__ */ jsx("div", { ref: menuRef, className: cn(
|
|
303
308
|
"shrink-0",
|
|
304
309
|
showMenu ? "opacity-100" : "opacity-100 md:opacity-0 md:pointer-events-none"
|
|
305
310
|
), children: /* @__PURE__ */ jsxs(DropdownMenu, { open: dropdownOpen, onOpenChange: setDropdownOpen, children: [
|
|
@@ -267,6 +267,7 @@ function ChatRow({ chat, onNavigate, onDelete, onStar, onRename }) {
|
|
|
267
267
|
const [editing, setEditing] = useState(false);
|
|
268
268
|
const [editTitle, setEditTitle] = useState(chat.title || '');
|
|
269
269
|
const inputRef = useRef(null);
|
|
270
|
+
const menuRef = useRef(null);
|
|
270
271
|
|
|
271
272
|
const showMenu = hovered || dropdownOpen;
|
|
272
273
|
|
|
@@ -304,6 +305,7 @@ function ChatRow({ chat, onNavigate, onDelete, onStar, onRename }) {
|
|
|
304
305
|
onMouseLeave={() => setHovered(false)}
|
|
305
306
|
onClick={(e) => {
|
|
306
307
|
if (editing) { e.preventDefault(); return; }
|
|
308
|
+
if (menuRef.current && menuRef.current.contains(e.target)) { e.preventDefault(); return; }
|
|
307
309
|
e.preventDefault();
|
|
308
310
|
if (chat.codeWorkspaceId && chat.containerName) {
|
|
309
311
|
window.location.href = `/code/${chat.codeWorkspaceId}`;
|
|
@@ -347,7 +349,7 @@ function ChatRow({ chat, onNavigate, onDelete, onStar, onRename }) {
|
|
|
347
349
|
</span>
|
|
348
350
|
</div>
|
|
349
351
|
{!editing && (
|
|
350
|
-
<div className={cn(
|
|
352
|
+
<div ref={menuRef} className={cn(
|
|
351
353
|
'shrink-0',
|
|
352
354
|
showMenu ? 'opacity-100' : 'opacity-100 md:opacity-0 md:pointer-events-none'
|
|
353
355
|
)}>
|
|
@@ -7,13 +7,9 @@ import { Combobox } from "./ui/combobox.js";
|
|
|
7
7
|
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from "./ui/dropdown-menu.js";
|
|
8
8
|
import { cn } from "../utils.js";
|
|
9
9
|
import { CodeLogView } from "./code-log-view.js";
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
"create-pr": "Create PR",
|
|
14
|
-
"rebase-branch": "Rebase Branch",
|
|
15
|
-
"resolve-conflicts": "Resolve Conflicts"
|
|
16
|
-
};
|
|
10
|
+
function getCommandLabel(slug) {
|
|
11
|
+
return slug.split("-").map((word) => word.length <= 2 ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
12
|
+
}
|
|
17
13
|
function RepoBranchPicker({
|
|
18
14
|
repo,
|
|
19
15
|
onRepoChange,
|
|
@@ -315,7 +311,7 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
315
311
|
children: commandRunning ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
316
312
|
/* @__PURE__ */ jsx(SpinnerIcon, { size: 12, className: "animate-spin" }),
|
|
317
313
|
"Running..."
|
|
318
|
-
] }) :
|
|
314
|
+
] }) : getCommandLabel(selectedCommand)
|
|
319
315
|
}
|
|
320
316
|
),
|
|
321
317
|
/* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
@@ -329,9 +325,9 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
329
325
|
}
|
|
330
326
|
) }),
|
|
331
327
|
/* @__PURE__ */ jsxs(DropdownMenuContent, { side: "top", align: "end", className: "whitespace-nowrap", children: [
|
|
332
|
-
["commit
|
|
328
|
+
["commit", "push", "create-pr"].map((cmd) => /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: () => setSelectedCommand(cmd), children: getCommandLabel(cmd) }, cmd)),
|
|
333
329
|
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
334
|
-
["
|
|
330
|
+
["pull"].map((cmd) => /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: () => setSelectedCommand(cmd), children: getCommandLabel(cmd) }, cmd))
|
|
335
331
|
] })
|
|
336
332
|
] })
|
|
337
333
|
] })
|
|
@@ -339,7 +335,7 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
339
335
|
dialogOpen && /* @__PURE__ */ jsx(
|
|
340
336
|
CommandOutputDialog,
|
|
341
337
|
{
|
|
342
|
-
title:
|
|
338
|
+
title: getCommandLabel(selectedCommand),
|
|
343
339
|
logs: commandLogs,
|
|
344
340
|
exitCode: commandExitCode,
|
|
345
341
|
running: commandRunning,
|
|
@@ -349,8 +345,8 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
349
345
|
] });
|
|
350
346
|
}
|
|
351
347
|
export {
|
|
352
|
-
COMMAND_LABELS,
|
|
353
348
|
CommandOutputDialog,
|
|
354
349
|
RepoBranchPicker,
|
|
355
|
-
WorkspaceBar
|
|
350
|
+
WorkspaceBar,
|
|
351
|
+
getCommandLabel
|
|
356
352
|
};
|
|
@@ -8,13 +8,16 @@ import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuIte
|
|
|
8
8
|
import { cn } from '../utils.js';
|
|
9
9
|
import { CodeLogView } from './code-log-view.js';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Auto-generates display labels from command slug.
|
|
13
|
+
* Splits on hyphens, capitalizes each word. Words ≤2 chars are uppercased (e.g. pr → PR).
|
|
14
|
+
*/
|
|
15
|
+
export function getCommandLabel(slug) {
|
|
16
|
+
return slug
|
|
17
|
+
.split('-')
|
|
18
|
+
.map(word => word.length <= 2 ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1))
|
|
19
|
+
.join(' ');
|
|
20
|
+
}
|
|
18
21
|
|
|
19
22
|
/**
|
|
20
23
|
* Repo/branch picker dropdowns for the empty state (below chat input).
|
|
@@ -244,6 +247,7 @@ const STORAGE_KEY = 'thepopebot-workspace-command';
|
|
|
244
247
|
function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, onShowDiff }) {
|
|
245
248
|
const [selectedCommand, setSelectedCommandState] = useState(() => {
|
|
246
249
|
try { return localStorage.getItem(STORAGE_KEY) || 'create-pr'; } catch { return 'create-pr'; }
|
|
250
|
+
|
|
247
251
|
});
|
|
248
252
|
const setSelectedCommand = (cmd) => {
|
|
249
253
|
setSelectedCommandState(cmd);
|
|
@@ -357,7 +361,7 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
357
361
|
Running...
|
|
358
362
|
</span>
|
|
359
363
|
) : (
|
|
360
|
-
|
|
364
|
+
getCommandLabel(selectedCommand)
|
|
361
365
|
)}
|
|
362
366
|
</button>
|
|
363
367
|
<DropdownMenu>
|
|
@@ -371,15 +375,15 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
371
375
|
</button>
|
|
372
376
|
</DropdownMenuTrigger>
|
|
373
377
|
<DropdownMenuContent side="top" align="end" className="whitespace-nowrap">
|
|
374
|
-
{['commit
|
|
378
|
+
{['commit', 'push', 'create-pr'].map((cmd) => (
|
|
375
379
|
<DropdownMenuItem key={cmd} onClick={() => setSelectedCommand(cmd)}>
|
|
376
|
-
{
|
|
380
|
+
{getCommandLabel(cmd)}
|
|
377
381
|
</DropdownMenuItem>
|
|
378
382
|
))}
|
|
379
383
|
<DropdownMenuSeparator />
|
|
380
|
-
{['
|
|
384
|
+
{['pull'].map((cmd) => (
|
|
381
385
|
<DropdownMenuItem key={cmd} onClick={() => setSelectedCommand(cmd)}>
|
|
382
|
-
{
|
|
386
|
+
{getCommandLabel(cmd)}
|
|
383
387
|
</DropdownMenuItem>
|
|
384
388
|
))}
|
|
385
389
|
</DropdownMenuContent>
|
|
@@ -389,7 +393,7 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
389
393
|
|
|
390
394
|
{dialogOpen && (
|
|
391
395
|
<CommandOutputDialog
|
|
392
|
-
title={
|
|
396
|
+
title={getCommandLabel(selectedCommand)}
|
|
393
397
|
logs={commandLogs}
|
|
394
398
|
exitCode={commandExitCode}
|
|
395
399
|
running={commandRunning}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef } from "react";
|
|
4
|
+
import { createPortal } from "react-dom";
|
|
4
5
|
import { cn } from "../../utils.js";
|
|
5
6
|
function ConfirmDialog({ open, onConfirm, onCancel, title, description, confirmLabel = "Delete", cancelLabel = "Cancel", variant = "destructive" }) {
|
|
6
7
|
const cancelRef = useRef(null);
|
|
@@ -18,35 +19,38 @@ function ConfirmDialog({ open, onConfirm, onCancel, title, description, confirmL
|
|
|
18
19
|
return () => document.removeEventListener("keydown", handleEsc);
|
|
19
20
|
}, [open, onCancel]);
|
|
20
21
|
if (!open) return null;
|
|
21
|
-
return
|
|
22
|
-
/* @__PURE__ */
|
|
23
|
-
|
|
24
|
-
/* @__PURE__ */
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
/* @__PURE__ */
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
22
|
+
return createPortal(
|
|
23
|
+
/* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-[100] flex items-center justify-center", children: [
|
|
24
|
+
/* @__PURE__ */ jsx("div", { className: "fixed inset-0 bg-black/50", onClick: onCancel }),
|
|
25
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-[100] w-full max-w-sm mx-4 rounded-lg border border-border bg-background p-6 shadow-lg", onClick: (e) => e.stopPropagation(), children: [
|
|
26
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold", children: title }),
|
|
27
|
+
description && /* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: description }),
|
|
28
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-4 flex justify-end gap-2", children: [
|
|
29
|
+
/* @__PURE__ */ jsx(
|
|
30
|
+
"button",
|
|
31
|
+
{
|
|
32
|
+
ref: cancelRef,
|
|
33
|
+
onClick: onCancel,
|
|
34
|
+
className: "rounded-md px-3 py-1.5 text-sm font-medium border border-input bg-background hover:bg-muted",
|
|
35
|
+
children: cancelLabel
|
|
36
|
+
}
|
|
37
|
+
),
|
|
38
|
+
/* @__PURE__ */ jsx(
|
|
39
|
+
"button",
|
|
40
|
+
{
|
|
41
|
+
onClick: onConfirm,
|
|
42
|
+
className: cn(
|
|
43
|
+
"rounded-md px-3 py-1.5 text-sm font-medium text-white",
|
|
44
|
+
variant === "destructive" ? "bg-destructive hover:bg-destructive/90" : "bg-foreground hover:bg-foreground/90"
|
|
45
|
+
),
|
|
46
|
+
children: confirmLabel
|
|
47
|
+
}
|
|
48
|
+
)
|
|
49
|
+
] })
|
|
47
50
|
] })
|
|
48
|
-
] })
|
|
49
|
-
|
|
51
|
+
] }),
|
|
52
|
+
document.body
|
|
53
|
+
);
|
|
50
54
|
}
|
|
51
55
|
export {
|
|
52
56
|
ConfirmDialog
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useEffect, useRef } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
4
5
|
import { cn } from '../../utils.js';
|
|
5
6
|
|
|
6
7
|
export function ConfirmDialog({ open, onConfirm, onCancel, title, description, confirmLabel = 'Delete', cancelLabel = 'Cancel', variant = 'destructive' }) {
|
|
@@ -23,10 +24,10 @@ export function ConfirmDialog({ open, onConfirm, onCancel, title, description, c
|
|
|
23
24
|
|
|
24
25
|
if (!open) return null;
|
|
25
26
|
|
|
26
|
-
return (
|
|
27
|
-
<div className="fixed inset-0 z-
|
|
27
|
+
return createPortal(
|
|
28
|
+
<div className="fixed inset-0 z-[100] flex items-center justify-center">
|
|
28
29
|
<div className="fixed inset-0 bg-black/50" onClick={onCancel} />
|
|
29
|
-
<div className="relative z-
|
|
30
|
+
<div className="relative z-[100] w-full max-w-sm mx-4 rounded-lg border border-border bg-background p-6 shadow-lg" onClick={(e) => e.stopPropagation()}>
|
|
30
31
|
<h3 className="text-lg font-semibold">{title}</h3>
|
|
31
32
|
{description && (
|
|
32
33
|
<p className="mt-2 text-sm text-muted-foreground">{description}</p>
|
|
@@ -52,6 +53,7 @@ export function ConfirmDialog({ open, onConfirm, onCancel, title, description, c
|
|
|
52
53
|
</button>
|
|
53
54
|
</div>
|
|
54
55
|
</div>
|
|
55
|
-
</div
|
|
56
|
+
</div>,
|
|
57
|
+
document.body
|
|
56
58
|
);
|
|
57
59
|
}
|
package/lib/code/actions.js
CHANGED
|
@@ -694,7 +694,7 @@ export async function getWorkspaceDiffFull(id, authenticatedUser) {
|
|
|
694
694
|
* Launch a workspace command container and return immediately.
|
|
695
695
|
* The client connects to /stream/containers/logs?name=...&cleanup=true for live output.
|
|
696
696
|
* @param {string} id - Workspace ID
|
|
697
|
-
* @param {string} command - 'commit
|
|
697
|
+
* @param {string} command - 'commit' | 'push' | 'create-pr' | 'pull'
|
|
698
698
|
* @returns {Promise<{success: boolean, containerName?: string, message?: string}>}
|
|
699
699
|
*/
|
|
700
700
|
export async function launchWorkspaceCommand(id, command) {
|
|
@@ -718,10 +718,10 @@ export async function launchWorkspaceCommand(id, command) {
|
|
|
718
718
|
const branch = workspace.branch || 'main';
|
|
719
719
|
const featureBranch = workspace.featureBranch || '';
|
|
720
720
|
const prompts = {
|
|
721
|
-
'commit
|
|
722
|
-
'push
|
|
723
|
-
'create-pr': `
|
|
724
|
-
'
|
|
721
|
+
'commit': 'Stage all changes with `git add -A`. Review the staged diff with `git diff --cached`. Write a clear conventional commit message and run `git commit`. If anything fails, diagnose the issue and fix it. Do not modify any source files.',
|
|
722
|
+
'push': `Stage all changes with \`git add -A\`. Review the staged diff with \`git diff --cached\`. Write a clear conventional commit message and run \`git commit\`. Then run \`git push origin ${featureBranch || branch}\`. If anything fails, diagnose the issue and fix it. Do not modify any source files.`,
|
|
723
|
+
'create-pr': `Make sure all changes are committed — if there are uncommitted changes, stage them with \`git add -A\`, write a commit message, and commit. Push the branch with \`git push -u origin ${featureBranch}\`. Then review all commits on branch ${featureBranch} compared to ${branch} and create a pull request using \`gh pr create\` with a clear title and detailed description. If a PR already exists, update it instead. If anything fails, diagnose the issue and fix it.`,
|
|
724
|
+
'pull': `Fetch from origin with \`git fetch origin\` and rebase this branch onto \`origin/${branch}\` with \`git rebase origin/${branch}\`. If there are merge conflicts, resolve them: read each conflicting file, understand both sides, resolve correctly, \`git add\` the file, then run \`git rebase --continue\`. Repeat if new conflicts appear. If anything fails, diagnose the issue and fix it.`,
|
|
725
725
|
};
|
|
726
726
|
const prompt = prompts[command] || null;
|
|
727
727
|
|
|
@@ -747,7 +747,7 @@ export async function launchWorkspaceCommand(id, command) {
|
|
|
747
747
|
* Waits for the container to finish and returns its output.
|
|
748
748
|
* @deprecated Use launchWorkspaceCommand + SSE streaming instead.
|
|
749
749
|
* @param {string} id - Workspace ID
|
|
750
|
-
* @param {string} command - 'commit
|
|
750
|
+
* @param {string} command - 'commit' | 'push' | 'create-pr' | 'pull'
|
|
751
751
|
* @returns {Promise<{success: boolean, output?: string, exitCode?: number, message?: string}>}
|
|
752
752
|
*/
|
|
753
753
|
export async function runWorkspaceCommand(id, command) {
|
|
@@ -772,10 +772,10 @@ export async function runWorkspaceCommand(id, command) {
|
|
|
772
772
|
const branch = workspace.branch || 'main';
|
|
773
773
|
const featureBranch = workspace.featureBranch || '';
|
|
774
774
|
const prompts = {
|
|
775
|
-
'commit
|
|
776
|
-
'push
|
|
777
|
-
'create-pr': `
|
|
778
|
-
'
|
|
775
|
+
'commit': 'Stage all changes with `git add -A`. Review the staged diff with `git diff --cached`. Write a clear conventional commit message and run `git commit`. If anything fails, diagnose the issue and fix it. Do not modify any source files.',
|
|
776
|
+
'push': `Stage all changes with \`git add -A\`. Review the staged diff with \`git diff --cached\`. Write a clear conventional commit message and run \`git commit\`. Then run \`git push origin ${featureBranch || branch}\`. If anything fails, diagnose the issue and fix it. Do not modify any source files.`,
|
|
777
|
+
'create-pr': `Make sure all changes are committed — if there are uncommitted changes, stage them with \`git add -A\`, write a commit message, and commit. Push the branch with \`git push -u origin ${featureBranch}\`. Then review all commits on branch ${featureBranch} compared to ${branch} and create a pull request using \`gh pr create\` with a clear title and detailed description. If a PR already exists, update it instead. If anything fails, diagnose the issue and fix it.`,
|
|
778
|
+
'pull': `Fetch from origin with \`git fetch origin\` and rebase this branch onto \`origin/${branch}\` with \`git rebase origin/${branch}\`. If there are merge conflicts, resolve them: read each conflicting file, understand both sides, resolve correctly, \`git add\` the file, then run \`git rebase --continue\`. Repeat if new conflicts appear. If anything fails, diagnose the issue and fix it.`,
|
|
779
779
|
};
|
|
780
780
|
const prompt = prompts[command] || null;
|
|
781
781
|
|
package/lib/code/code-page.js
CHANGED
|
@@ -299,6 +299,45 @@ function CodePage({ session, codeWorkspaceId }) {
|
|
|
299
299
|
/* @__PURE__ */ jsx(SpinnerIcon, { size: 12 }),
|
|
300
300
|
/* @__PURE__ */ jsx("span", { children: "Editor..." })
|
|
301
301
|
] }),
|
|
302
|
+
portForwards.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: portForwards.map((pf) => /* @__PURE__ */ jsxs(
|
|
303
|
+
"div",
|
|
304
|
+
{
|
|
305
|
+
className: "flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium font-mono text-muted-foreground shrink-0 whitespace-nowrap rounded-t-md border border-b-0 border-emerald-500/30 bg-emerald-500/5",
|
|
306
|
+
children: [
|
|
307
|
+
/* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500" }),
|
|
308
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
309
|
+
":",
|
|
310
|
+
pf.port
|
|
311
|
+
] }),
|
|
312
|
+
/* @__PURE__ */ jsx(
|
|
313
|
+
"button",
|
|
314
|
+
{
|
|
315
|
+
className: "hover:text-emerald-400 transition-colors",
|
|
316
|
+
onClick: () => window.open(pf.url, "_blank"),
|
|
317
|
+
title: `Open ${pf.url}`,
|
|
318
|
+
children: /* @__PURE__ */ jsxs("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
319
|
+
/* @__PURE__ */ jsx("path", { d: "M7 3H3v10h10V9" }),
|
|
320
|
+
/* @__PURE__ */ jsx("path", { d: "M10 2h4v4" }),
|
|
321
|
+
/* @__PURE__ */ jsx("path", { d: "M14 2L7 9" })
|
|
322
|
+
] })
|
|
323
|
+
}
|
|
324
|
+
),
|
|
325
|
+
/* @__PURE__ */ jsx(
|
|
326
|
+
"button",
|
|
327
|
+
{
|
|
328
|
+
className: "hover:text-destructive transition-colors",
|
|
329
|
+
onClick: () => handleStopPort(pf.port),
|
|
330
|
+
title: "Stop forwarding",
|
|
331
|
+
children: /* @__PURE__ */ jsxs("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: [
|
|
332
|
+
/* @__PURE__ */ jsx("line", { x1: "4", y1: "4", x2: "12", y2: "12" }),
|
|
333
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "4", x2: "4", y2: "12" })
|
|
334
|
+
] })
|
|
335
|
+
}
|
|
336
|
+
)
|
|
337
|
+
]
|
|
338
|
+
},
|
|
339
|
+
pf.port
|
|
340
|
+
)) }),
|
|
302
341
|
/* @__PURE__ */ jsx("div", { className: "self-stretch my-1.5 mx-1 md:mx-4 w-px bg-border shrink-0" }),
|
|
303
342
|
/* @__PURE__ */ jsx(
|
|
304
343
|
"button",
|
|
@@ -341,46 +380,7 @@ function CodePage({ session, codeWorkspaceId }) {
|
|
|
341
380
|
title: "Forward a port",
|
|
342
381
|
children: "+ Port"
|
|
343
382
|
}
|
|
344
|
-
)
|
|
345
|
-
portForwards.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 ml-auto", children: portForwards.map((pf) => /* @__PURE__ */ jsxs(
|
|
346
|
-
"div",
|
|
347
|
-
{
|
|
348
|
-
className: "flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium font-mono text-muted-foreground shrink-0 whitespace-nowrap rounded-t-md border border-b-0 border-emerald-500/30 bg-emerald-500/5",
|
|
349
|
-
children: [
|
|
350
|
-
/* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500" }),
|
|
351
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
352
|
-
":",
|
|
353
|
-
pf.port
|
|
354
|
-
] }),
|
|
355
|
-
/* @__PURE__ */ jsx(
|
|
356
|
-
"button",
|
|
357
|
-
{
|
|
358
|
-
className: "hover:text-emerald-400 transition-colors",
|
|
359
|
-
onClick: () => window.open(pf.url, "_blank"),
|
|
360
|
-
title: `Open ${pf.url}`,
|
|
361
|
-
children: /* @__PURE__ */ jsxs("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
362
|
-
/* @__PURE__ */ jsx("path", { d: "M7 3H3v10h10V9" }),
|
|
363
|
-
/* @__PURE__ */ jsx("path", { d: "M10 2h4v4" }),
|
|
364
|
-
/* @__PURE__ */ jsx("path", { d: "M14 2L7 9" })
|
|
365
|
-
] })
|
|
366
|
-
}
|
|
367
|
-
),
|
|
368
|
-
/* @__PURE__ */ jsx(
|
|
369
|
-
"button",
|
|
370
|
-
{
|
|
371
|
-
className: "hover:text-destructive transition-colors",
|
|
372
|
-
onClick: () => handleStopPort(pf.port),
|
|
373
|
-
title: "Stop forwarding",
|
|
374
|
-
children: /* @__PURE__ */ jsxs("svg", { width: "10", height: "10", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", children: [
|
|
375
|
-
/* @__PURE__ */ jsx("line", { x1: "4", y1: "4", x2: "12", y2: "12" }),
|
|
376
|
-
/* @__PURE__ */ jsx("line", { x1: "12", y1: "4", x2: "4", y2: "12" })
|
|
377
|
-
] })
|
|
378
|
-
}
|
|
379
|
-
)
|
|
380
|
-
]
|
|
381
|
-
},
|
|
382
|
-
pf.port
|
|
383
|
-
)) })
|
|
383
|
+
)
|
|
384
384
|
] }),
|
|
385
385
|
/* @__PURE__ */ jsxs("div", { style: { position: "relative", flex: 1, minHeight: 0, display: "flex", flexDirection: "column" }, children: [
|
|
386
386
|
showDiff && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, zIndex: 20, display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ jsx(DiffViewer, { workspaceId: codeWorkspaceId, diffStats, onClose: () => setShowDiff(false) }) }),
|
package/lib/code/code-page.jsx
CHANGED
|
@@ -356,6 +356,42 @@ export default function CodePage({ session, codeWorkspaceId }) {
|
|
|
356
356
|
</div>
|
|
357
357
|
)}
|
|
358
358
|
|
|
359
|
+
{/* Active port forwards */}
|
|
360
|
+
{portForwards.length > 0 && (
|
|
361
|
+
<div className="flex items-center gap-1">
|
|
362
|
+
{portForwards.map((pf) => (
|
|
363
|
+
<div
|
|
364
|
+
key={pf.port}
|
|
365
|
+
className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium font-mono text-muted-foreground shrink-0 whitespace-nowrap rounded-t-md border border-b-0 border-emerald-500/30 bg-emerald-500/5"
|
|
366
|
+
>
|
|
367
|
+
<div className="w-1.5 h-1.5 rounded-full bg-emerald-500" />
|
|
368
|
+
<span>:{pf.port}</span>
|
|
369
|
+
<button
|
|
370
|
+
className="hover:text-emerald-400 transition-colors"
|
|
371
|
+
onClick={() => window.open(pf.url, '_blank')}
|
|
372
|
+
title={`Open ${pf.url}`}
|
|
373
|
+
>
|
|
374
|
+
<svg width="10" height="10" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
375
|
+
<path d="M7 3H3v10h10V9" />
|
|
376
|
+
<path d="M10 2h4v4" />
|
|
377
|
+
<path d="M14 2L7 9" />
|
|
378
|
+
</svg>
|
|
379
|
+
</button>
|
|
380
|
+
<button
|
|
381
|
+
className="hover:text-destructive transition-colors"
|
|
382
|
+
onClick={() => handleStopPort(pf.port)}
|
|
383
|
+
title="Stop forwarding"
|
|
384
|
+
>
|
|
385
|
+
<svg width="10" height="10" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
|
|
386
|
+
<line x1="4" y1="4" x2="12" y2="12" />
|
|
387
|
+
<line x1="12" y1="4" x2="4" y2="12" />
|
|
388
|
+
</svg>
|
|
389
|
+
</button>
|
|
390
|
+
</div>
|
|
391
|
+
))}
|
|
392
|
+
</div>
|
|
393
|
+
)}
|
|
394
|
+
|
|
359
395
|
{/* Divider between real tabs and + buttons */}
|
|
360
396
|
<div className="self-stretch my-1.5 mx-1 md:mx-4 w-px bg-border shrink-0" />
|
|
361
397
|
|
|
@@ -392,42 +428,6 @@ export default function CodePage({ session, codeWorkspaceId }) {
|
|
|
392
428
|
>
|
|
393
429
|
+ Port
|
|
394
430
|
</button>
|
|
395
|
-
|
|
396
|
-
{/* Active port forwards */}
|
|
397
|
-
{portForwards.length > 0 && (
|
|
398
|
-
<div className="flex items-center gap-1 ml-auto">
|
|
399
|
-
{portForwards.map((pf) => (
|
|
400
|
-
<div
|
|
401
|
-
key={pf.port}
|
|
402
|
-
className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium font-mono text-muted-foreground shrink-0 whitespace-nowrap rounded-t-md border border-b-0 border-emerald-500/30 bg-emerald-500/5"
|
|
403
|
-
>
|
|
404
|
-
<div className="w-1.5 h-1.5 rounded-full bg-emerald-500" />
|
|
405
|
-
<span>:{pf.port}</span>
|
|
406
|
-
<button
|
|
407
|
-
className="hover:text-emerald-400 transition-colors"
|
|
408
|
-
onClick={() => window.open(pf.url, '_blank')}
|
|
409
|
-
title={`Open ${pf.url}`}
|
|
410
|
-
>
|
|
411
|
-
<svg width="10" height="10" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
412
|
-
<path d="M7 3H3v10h10V9" />
|
|
413
|
-
<path d="M10 2h4v4" />
|
|
414
|
-
<path d="M14 2L7 9" />
|
|
415
|
-
</svg>
|
|
416
|
-
</button>
|
|
417
|
-
<button
|
|
418
|
-
className="hover:text-destructive transition-colors"
|
|
419
|
-
onClick={() => handleStopPort(pf.port)}
|
|
420
|
-
title="Stop forwarding"
|
|
421
|
-
>
|
|
422
|
-
<svg width="10" height="10" viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
|
|
423
|
-
<line x1="4" y1="4" x2="12" y2="12" />
|
|
424
|
-
<line x1="12" y1="4" x2="4" y2="12" />
|
|
425
|
-
</svg>
|
|
426
|
-
</button>
|
|
427
|
-
</div>
|
|
428
|
-
))}
|
|
429
|
-
</div>
|
|
430
|
-
)}
|
|
431
431
|
</div>
|
|
432
432
|
|
|
433
433
|
{/* Tab content panels — all mounted, hidden via display */}
|
|
@@ -8,7 +8,7 @@ import { WebLinksAddon } from "@xterm/addon-web-links";
|
|
|
8
8
|
import { SerializeAddon } from "@xterm/addon-serialize";
|
|
9
9
|
import "@xterm/xterm/css/xterm.css";
|
|
10
10
|
import { SpinnerIcon, MicIcon } from "../chat/components/icons.js";
|
|
11
|
-
import {
|
|
11
|
+
import { getCommandLabel, CommandOutputDialog } from "../chat/components/code-mode-toggle.js";
|
|
12
12
|
import { useVoiceInput } from "../voice/use-voice-input.js";
|
|
13
13
|
import { VoiceBars } from "../chat/components/voice-bars.js";
|
|
14
14
|
const getVoiceToken = () => fetch("/chat/voice-token").then((r) => r.json()).catch(() => ({ error: "Failed to get voice token" }));
|
|
@@ -835,7 +835,7 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
835
835
|
children: commandRunning ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
836
836
|
/* @__PURE__ */ jsx(SpinnerIcon, { size: 12 }),
|
|
837
837
|
" Running..."
|
|
838
|
-
] }) :
|
|
838
|
+
] }) : getCommandLabel(selectedCommand)
|
|
839
839
|
}
|
|
840
840
|
),
|
|
841
841
|
/* @__PURE__ */ jsx(
|
|
@@ -849,7 +849,7 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
849
849
|
)
|
|
850
850
|
] }),
|
|
851
851
|
dropupOpen && /* @__PURE__ */ jsxs("div", { className: "code-toolbar-dropup", children: [
|
|
852
|
-
["commit
|
|
852
|
+
["commit", "push", "create-pr"].map((cmd) => /* @__PURE__ */ jsx(
|
|
853
853
|
"button",
|
|
854
854
|
{
|
|
855
855
|
className: "code-toolbar-dropup-item",
|
|
@@ -857,12 +857,12 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
857
857
|
setSelectedCommand(cmd);
|
|
858
858
|
setDropupOpen(false);
|
|
859
859
|
},
|
|
860
|
-
children:
|
|
860
|
+
children: getCommandLabel(cmd)
|
|
861
861
|
},
|
|
862
862
|
cmd
|
|
863
863
|
)),
|
|
864
864
|
/* @__PURE__ */ jsx("div", { className: "code-toolbar-dropup-separator" }),
|
|
865
|
-
["
|
|
865
|
+
["pull"].map((cmd) => /* @__PURE__ */ jsx(
|
|
866
866
|
"button",
|
|
867
867
|
{
|
|
868
868
|
className: "code-toolbar-dropup-item",
|
|
@@ -870,7 +870,7 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
870
870
|
setSelectedCommand(cmd);
|
|
871
871
|
setDropupOpen(false);
|
|
872
872
|
},
|
|
873
|
-
children:
|
|
873
|
+
children: getCommandLabel(cmd)
|
|
874
874
|
},
|
|
875
875
|
cmd
|
|
876
876
|
))
|
|
@@ -879,7 +879,7 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
879
879
|
dialogOpen && /* @__PURE__ */ jsx(
|
|
880
880
|
CommandOutputDialog,
|
|
881
881
|
{
|
|
882
|
-
title:
|
|
882
|
+
title: getCommandLabel(selectedCommand),
|
|
883
883
|
output: commandOutput,
|
|
884
884
|
exitCode: commandExitCode,
|
|
885
885
|
running: commandRunning,
|
|
@@ -8,7 +8,7 @@ import { WebLinksAddon } from '@xterm/addon-web-links';
|
|
|
8
8
|
import { SerializeAddon } from '@xterm/addon-serialize';
|
|
9
9
|
import '@xterm/xterm/css/xterm.css';
|
|
10
10
|
import { SpinnerIcon, MicIcon } from '../chat/components/icons.js';
|
|
11
|
-
import {
|
|
11
|
+
import { getCommandLabel, CommandOutputDialog } from '../chat/components/code-mode-toggle.js';
|
|
12
12
|
import { useVoiceInput } from '../voice/use-voice-input.js';
|
|
13
13
|
import { VoiceBars } from '../chat/components/voice-bars.js';
|
|
14
14
|
|
|
@@ -882,7 +882,7 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
882
882
|
{commandRunning ? (
|
|
883
883
|
<><SpinnerIcon size={12} /> Running...</>
|
|
884
884
|
) : (
|
|
885
|
-
|
|
885
|
+
getCommandLabel(selectedCommand)
|
|
886
886
|
)}
|
|
887
887
|
</button>
|
|
888
888
|
<button
|
|
@@ -897,23 +897,23 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
897
897
|
</div>
|
|
898
898
|
{dropupOpen && (
|
|
899
899
|
<div className="code-toolbar-dropup">
|
|
900
|
-
{['commit
|
|
900
|
+
{['commit', 'push', 'create-pr'].map((cmd) => (
|
|
901
901
|
<button
|
|
902
902
|
key={cmd}
|
|
903
903
|
className="code-toolbar-dropup-item"
|
|
904
904
|
onClick={() => { setSelectedCommand(cmd); setDropupOpen(false); }}
|
|
905
905
|
>
|
|
906
|
-
{
|
|
906
|
+
{getCommandLabel(cmd)}
|
|
907
907
|
</button>
|
|
908
908
|
))}
|
|
909
909
|
<div className="code-toolbar-dropup-separator" />
|
|
910
|
-
{['
|
|
910
|
+
{['pull'].map((cmd) => (
|
|
911
911
|
<button
|
|
912
912
|
key={cmd}
|
|
913
913
|
className="code-toolbar-dropup-item"
|
|
914
914
|
onClick={() => { setSelectedCommand(cmd); setDropupOpen(false); }}
|
|
915
915
|
>
|
|
916
|
-
{
|
|
916
|
+
{getCommandLabel(cmd)}
|
|
917
917
|
</button>
|
|
918
918
|
))}
|
|
919
919
|
</div>
|
|
@@ -922,7 +922,7 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
922
922
|
|
|
923
923
|
{dialogOpen && (
|
|
924
924
|
<CommandOutputDialog
|
|
925
|
-
title={
|
|
925
|
+
title={getCommandLabel(selectedCommand)}
|
|
926
926
|
output={commandOutput}
|
|
927
927
|
exitCode={commandExitCode}
|
|
928
928
|
running={commandRunning}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thepopebot",
|
|
3
|
-
"version": "1.2.75-beta.
|
|
3
|
+
"version": "1.2.75-beta.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Create autonomous AI agents with a two-layer architecture: Next.js Event Handler + Docker Agent.",
|
|
6
6
|
"bin": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"./auth/actions": "./lib/auth/actions.js",
|
|
16
16
|
"./chat/api": "./lib/chat/api.js",
|
|
17
17
|
"./db": "./lib/db/index.js",
|
|
18
|
+
"./db/chats": "./lib/db/chats.js",
|
|
18
19
|
"./db/oauth-tokens": "./lib/db/oauth-tokens.js",
|
|
19
20
|
"./chat": "./lib/chat/components/index.js",
|
|
20
21
|
"./chat/actions": "./lib/chat/actions.js",
|