thepopebot 1.2.76-beta.31 → 1.2.76-beta.32
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/ai/index.js +2 -7
- package/lib/chat/actions.js +2 -2
- package/lib/chat/components/code-mode-toggle.js +5 -10
- package/lib/chat/components/code-mode-toggle.jsx +5 -19
- package/lib/chat/components/settings-coding-agents-page.js +2 -6
- package/lib/chat/components/settings-coding-agents-page.jsx +2 -6
- package/lib/code/actions.js +5 -16
- package/lib/code/terminal-view.js +13 -33
- package/lib/code/terminal-view.jsx +3 -18
- package/lib/config.js +2 -2
- package/lib/git-commands.js +41 -0
- package/package.json +1 -1
package/lib/ai/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import { ensureWorkspaceRepo } from './workspace-setup.js';
|
|
|
13
13
|
import { resolveAgentScope } from './scope.js';
|
|
14
14
|
import { readSessionId, writeSessionId } from './session-manager.js';
|
|
15
15
|
import { workspaceDir as getWorkspaceDir } from '../tools/docker.js';
|
|
16
|
+
import { getCommandPrompt } from '../git-commands.js';
|
|
16
17
|
|
|
17
18
|
/**
|
|
18
19
|
* Ensure a chat exists in the DB and save a message.
|
|
@@ -239,13 +240,7 @@ async function maybeAutoRun({ workspaceId, isCodeMode, repoDir }) {
|
|
|
239
240
|
|
|
240
241
|
const branch = workspace.branch || 'main';
|
|
241
242
|
const featureBranch = workspace.featureBranch || '';
|
|
242
|
-
const
|
|
243
|
-
'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.',
|
|
244
|
-
'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.`,
|
|
245
|
-
'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.`,
|
|
246
|
-
'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.`,
|
|
247
|
-
};
|
|
248
|
-
const prompt = prompts[command] || null;
|
|
243
|
+
const prompt = getCommandPrompt(command, { branch, featureBranch });
|
|
249
244
|
|
|
250
245
|
// Random suffix prevents collisions with manual runs and other auto-runs.
|
|
251
246
|
const shortId = workspaceId.replace(/-/g, '').slice(0, 8);
|
package/lib/chat/actions.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
3
|
import { auth } from '../auth/index.js';
|
|
4
|
+
import { GIT_COMMAND_SET } from '../git-commands.js';
|
|
4
5
|
import {
|
|
5
6
|
createChat as dbCreateChat,
|
|
6
7
|
getChatById,
|
|
@@ -851,7 +852,6 @@ export async function setCodingAgentDefault(agent) {
|
|
|
851
852
|
}
|
|
852
853
|
|
|
853
854
|
const MODE_BRANCH_VALUES = new Set(['default', 'dynamic']);
|
|
854
|
-
const MODE_GIT_ACTION_VALUES = new Set(['commit', 'push', 'create-pr', 'pull']);
|
|
855
855
|
|
|
856
856
|
/**
|
|
857
857
|
* Get the admin-configured default git action for a chat mode.
|
|
@@ -876,7 +876,7 @@ export async function setModeDefault(mode, field, value) {
|
|
|
876
876
|
try {
|
|
877
877
|
if (mode !== 'agent' && mode !== 'code') return { error: 'Invalid mode' };
|
|
878
878
|
if (field === 'branch' && !MODE_BRANCH_VALUES.has(value)) return { error: 'Invalid branch value' };
|
|
879
|
-
if (field === 'gitAction' && !
|
|
879
|
+
if (field === 'gitAction' && !GIT_COMMAND_SET.has(value)) return { error: 'Invalid git action value' };
|
|
880
880
|
|
|
881
881
|
const keyMap = {
|
|
882
882
|
'agent.branch': 'AGENT_MODE_BRANCH',
|
|
@@ -4,12 +4,10 @@ import { useState, useEffect, useCallback, useRef } from "react";
|
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
5
|
import { GitBranchIcon, ChevronDownIcon, SpinnerIcon, XIcon, PlusIcon } from "./icons.js";
|
|
6
6
|
import { Combobox } from "./ui/combobox.js";
|
|
7
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem
|
|
7
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "./ui/dropdown-menu.js";
|
|
8
8
|
import { cn } from "../utils.js";
|
|
9
9
|
import { CodeLogView } from "./code-log-view.js";
|
|
10
|
-
|
|
11
|
-
return slug.split("-").map((word) => word.length <= 2 ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
12
|
-
}
|
|
10
|
+
import { GIT_COMMANDS, getCommandLabel, FALLBACK_BY_MODE } from "../../git-commands.js";
|
|
13
11
|
function RepoBranchPicker({
|
|
14
12
|
repo,
|
|
15
13
|
onRepoChange,
|
|
@@ -298,7 +296,6 @@ function CommandOutputDialog({ title, logs, exitCode, running, onClose }) {
|
|
|
298
296
|
);
|
|
299
297
|
}
|
|
300
298
|
const STORAGE_KEY = "thepopebot-workspace-command";
|
|
301
|
-
const FALLBACK_BY_MODE = { agent: "push", code: "create-pr" };
|
|
302
299
|
function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, onShowDiff, chatMode = "agent", autoRunInfo = null }) {
|
|
303
300
|
const storageKey = `${STORAGE_KEY}:${chatMode}`;
|
|
304
301
|
const [selectedCommand, setSelectedCommandState] = useState(() => {
|
|
@@ -476,11 +473,7 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
476
473
|
children: /* @__PURE__ */ jsx(ChevronDownIcon, { size: 14 })
|
|
477
474
|
}
|
|
478
475
|
) }),
|
|
479
|
-
/* @__PURE__ */
|
|
480
|
-
["commit", "push", "create-pr"].map((cmd) => /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: () => setSelectedCommand(cmd), children: getCommandLabel(cmd) }, cmd)),
|
|
481
|
-
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
482
|
-
["pull"].map((cmd) => /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: () => setSelectedCommand(cmd), children: getCommandLabel(cmd) }, cmd))
|
|
483
|
-
] })
|
|
476
|
+
/* @__PURE__ */ jsx(DropdownMenuContent, { side: "top", align: "end", className: "whitespace-nowrap", children: GIT_COMMANDS.map((cmd) => /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: () => setSelectedCommand(cmd), children: getCommandLabel(cmd) }, cmd)) })
|
|
484
477
|
] })
|
|
485
478
|
] })
|
|
486
479
|
] }),
|
|
@@ -498,6 +491,8 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
498
491
|
}
|
|
499
492
|
export {
|
|
500
493
|
CommandOutputDialog,
|
|
494
|
+
FALLBACK_BY_MODE,
|
|
495
|
+
GIT_COMMANDS,
|
|
501
496
|
RepoBranchPicker,
|
|
502
497
|
WorkspaceBar,
|
|
503
498
|
getCommandLabel
|
|
@@ -4,20 +4,13 @@ import { useState, useEffect, useCallback, useRef } from 'react';
|
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
5
|
import { GitBranchIcon, ChevronDownIcon, SpinnerIcon, XIcon, PlusIcon } from './icons.js';
|
|
6
6
|
import { Combobox } from './ui/combobox.js';
|
|
7
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem
|
|
7
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from './ui/dropdown-menu.js';
|
|
8
8
|
import { cn } from '../utils.js';
|
|
9
9
|
import { CodeLogView } from './code-log-view.js';
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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
|
-
}
|
|
11
|
+
import { GIT_COMMANDS, getCommandLabel, FALLBACK_BY_MODE } from '../../git-commands.js';
|
|
12
|
+
// Re-export so existing client imports (`from './code-mode-toggle.js'`) keep working.
|
|
13
|
+
export { GIT_COMMANDS, getCommandLabel, FALLBACK_BY_MODE };
|
|
21
14
|
|
|
22
15
|
/**
|
|
23
16
|
* Repo/branch picker dropdowns for the empty state (below chat input).
|
|
@@ -343,7 +336,6 @@ export function CommandOutputDialog({ title, logs, exitCode, running, onClose })
|
|
|
343
336
|
}
|
|
344
337
|
|
|
345
338
|
const STORAGE_KEY = 'thepopebot-workspace-command';
|
|
346
|
-
const FALLBACK_BY_MODE = { agent: 'push', code: 'create-pr' };
|
|
347
339
|
|
|
348
340
|
function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, onShowDiff, chatMode = 'agent', autoRunInfo = null }) {
|
|
349
341
|
const storageKey = `${STORAGE_KEY}:${chatMode}`;
|
|
@@ -512,13 +504,7 @@ function WorkspaceCommandButton({ workspaceId, diffStats, onDiffStatsRefresh, on
|
|
|
512
504
|
</button>
|
|
513
505
|
</DropdownMenuTrigger>
|
|
514
506
|
<DropdownMenuContent side="top" align="end" className="whitespace-nowrap">
|
|
515
|
-
{
|
|
516
|
-
<DropdownMenuItem key={cmd} onClick={() => setSelectedCommand(cmd)}>
|
|
517
|
-
{getCommandLabel(cmd)}
|
|
518
|
-
</DropdownMenuItem>
|
|
519
|
-
))}
|
|
520
|
-
<DropdownMenuSeparator />
|
|
521
|
-
{['pull'].map((cmd) => (
|
|
507
|
+
{GIT_COMMANDS.map((cmd) => (
|
|
522
508
|
<DropdownMenuItem key={cmd} onClick={() => setSelectedCommand(cmd)}>
|
|
523
509
|
{getCommandLabel(cmd)}
|
|
524
510
|
</DropdownMenuItem>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect } from "react";
|
|
4
4
|
import { CheckIcon } from "./icons.js";
|
|
5
|
+
import { GIT_COMMANDS, getCommandLabel } from "./code-mode-toggle.js";
|
|
5
6
|
import {
|
|
6
7
|
getCodingAgentSettings,
|
|
7
8
|
updateCodingAgentConfig,
|
|
@@ -192,12 +193,7 @@ const BRANCH_OPTIONS = [
|
|
|
192
193
|
{ value: "default", label: "Default branch" },
|
|
193
194
|
{ value: "dynamic", label: "Feature branch" }
|
|
194
195
|
];
|
|
195
|
-
const GIT_ACTION_OPTIONS =
|
|
196
|
-
{ value: "commit", label: "Commit" },
|
|
197
|
-
{ value: "push", label: "Push" },
|
|
198
|
-
{ value: "create-pr", label: "Create PR" },
|
|
199
|
-
{ value: "pull", label: "Pull" }
|
|
200
|
-
];
|
|
196
|
+
const GIT_ACTION_OPTIONS = GIT_COMMANDS.map((value) => ({ value, label: getCommandLabel(value) }));
|
|
201
197
|
function ModeDefaultRow({ label, mode, field, value, options, onSaved }) {
|
|
202
198
|
const [saving, setSaving] = useState(false);
|
|
203
199
|
const [saved, setSaved] = useState(false);
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect } from 'react';
|
|
4
4
|
import { CheckIcon } from './icons.js';
|
|
5
|
+
import { GIT_COMMANDS, getCommandLabel } from './code-mode-toggle.js';
|
|
5
6
|
import {
|
|
6
7
|
getCodingAgentSettings,
|
|
7
8
|
updateCodingAgentConfig,
|
|
@@ -203,12 +204,7 @@ const BRANCH_OPTIONS = [
|
|
|
203
204
|
{ value: 'dynamic', label: 'Feature branch' },
|
|
204
205
|
];
|
|
205
206
|
|
|
206
|
-
const GIT_ACTION_OPTIONS =
|
|
207
|
-
{ value: 'commit', label: 'Commit' },
|
|
208
|
-
{ value: 'push', label: 'Push' },
|
|
209
|
-
{ value: 'create-pr', label: 'Create PR' },
|
|
210
|
-
{ value: 'pull', label: 'Pull' },
|
|
211
|
-
];
|
|
207
|
+
const GIT_ACTION_OPTIONS = GIT_COMMANDS.map(value => ({ value, label: getCommandLabel(value) }));
|
|
212
208
|
|
|
213
209
|
function ModeDefaultRow({ label, mode, field, value, options, onSaved }) {
|
|
214
210
|
const [saving, setSaving] = useState(false);
|
package/lib/code/actions.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use server';
|
|
2
2
|
|
|
3
3
|
import { auth } from '../auth/index.js';
|
|
4
|
+
import { getCommandPrompt } from '../git-commands.js';
|
|
4
5
|
import {
|
|
5
6
|
createCodeWorkspace as dbCreateCodeWorkspace,
|
|
6
7
|
getCodeWorkspaceById,
|
|
@@ -733,7 +734,7 @@ export async function getWorkspaceDiffFull(id, authenticatedUser) {
|
|
|
733
734
|
* Launch a workspace command container and return immediately.
|
|
734
735
|
* The client connects to /stream/containers/logs?name=...&cleanup=true for live output.
|
|
735
736
|
* @param {string} id - Workspace ID
|
|
736
|
-
* @param {string} command - 'commit' | 'push' | 'create-pr' | 'pull'
|
|
737
|
+
* @param {string} command - 'commit' | 'push' | 'create-pr' | 'pull' | 'pull-push'
|
|
737
738
|
* @returns {Promise<{success: boolean, containerName?: string, message?: string}>}
|
|
738
739
|
*/
|
|
739
740
|
export async function launchWorkspaceCommand(id, command) {
|
|
@@ -756,13 +757,7 @@ export async function launchWorkspaceCommand(id, command) {
|
|
|
756
757
|
|
|
757
758
|
const branch = workspace.branch || 'main';
|
|
758
759
|
const featureBranch = workspace.featureBranch || '';
|
|
759
|
-
const
|
|
760
|
-
'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.',
|
|
761
|
-
'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.`,
|
|
762
|
-
'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.`,
|
|
763
|
-
'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.`,
|
|
764
|
-
};
|
|
765
|
-
const prompt = prompts[command] || null;
|
|
760
|
+
const prompt = getCommandPrompt(command, { branch, featureBranch });
|
|
766
761
|
|
|
767
762
|
await runCommandContainer({
|
|
768
763
|
containerName,
|
|
@@ -786,7 +781,7 @@ export async function launchWorkspaceCommand(id, command) {
|
|
|
786
781
|
* Waits for the container to finish and returns its output.
|
|
787
782
|
* @deprecated Use launchWorkspaceCommand + SSE streaming instead.
|
|
788
783
|
* @param {string} id - Workspace ID
|
|
789
|
-
* @param {string} command - 'commit' | 'push' | 'create-pr' | 'pull'
|
|
784
|
+
* @param {string} command - 'commit' | 'push' | 'create-pr' | 'pull' | 'pull-push'
|
|
790
785
|
* @returns {Promise<{success: boolean, output?: string, exitCode?: number, message?: string}>}
|
|
791
786
|
*/
|
|
792
787
|
export async function runWorkspaceCommand(id, command) {
|
|
@@ -810,13 +805,7 @@ export async function runWorkspaceCommand(id, command) {
|
|
|
810
805
|
// Build prompt based on command type
|
|
811
806
|
const branch = workspace.branch || 'main';
|
|
812
807
|
const featureBranch = workspace.featureBranch || '';
|
|
813
|
-
const
|
|
814
|
-
'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.',
|
|
815
|
-
'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.`,
|
|
816
|
-
'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.`,
|
|
817
|
-
'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.`,
|
|
818
|
-
};
|
|
819
|
-
const prompt = prompts[command] || null;
|
|
808
|
+
const prompt = getCommandPrompt(command, { branch, featureBranch });
|
|
820
809
|
|
|
821
810
|
await runCommandContainer({
|
|
822
811
|
containerName,
|
|
@@ -8,7 +8,8 @@ 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 { CommandOutputDialog } from "../chat/components/code-mode-toggle.js";
|
|
12
|
+
import { GIT_COMMANDS, getCommandLabel, FALLBACK_BY_MODE } from "../git-commands.js";
|
|
12
13
|
import { useVoiceInput } from "../voice/use-voice-input.js";
|
|
13
14
|
import { VoiceBars } from "../chat/components/voice-bars.js";
|
|
14
15
|
const getVoiceToken = () => fetch("/chat/voice-token").then((r) => r.json()).catch(() => ({ error: "Failed to get voice token" }));
|
|
@@ -464,11 +465,6 @@ function TerminalView({ codeWorkspaceId, wsPath, isActive = true, showToolbar =
|
|
|
464
465
|
color: #7aa2f7;
|
|
465
466
|
background: rgba(122,162,247,0.08);
|
|
466
467
|
}
|
|
467
|
-
.code-toolbar-dropup-separator {
|
|
468
|
-
height: 1px;
|
|
469
|
-
background: var(--tb-border, rgba(169,177,214,0.15));
|
|
470
|
-
margin: 4px 0;
|
|
471
|
-
}
|
|
472
468
|
.code-toolbar-btn--reconnect:hover {
|
|
473
469
|
color: var(--tb-hover, #a9b1d6);
|
|
474
470
|
}
|
|
@@ -781,7 +777,6 @@ function TerminalView({ codeWorkspaceId, wsPath, isActive = true, showToolbar =
|
|
|
781
777
|
] });
|
|
782
778
|
}
|
|
783
779
|
const STORAGE_KEY = "thepopebot-workspace-command";
|
|
784
|
-
const FALLBACK_BY_MODE = { agent: "push", code: "create-pr" };
|
|
785
780
|
function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh, onShowDiff }) {
|
|
786
781
|
const [chatMode, setChatMode] = useState("code");
|
|
787
782
|
useEffect(() => {
|
|
@@ -913,33 +908,18 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
913
908
|
}
|
|
914
909
|
)
|
|
915
910
|
] }),
|
|
916
|
-
dropupOpen && /* @__PURE__ */
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
setDropupOpen(false);
|
|
924
|
-
},
|
|
925
|
-
children: getCommandLabel(cmd)
|
|
926
|
-
},
|
|
927
|
-
cmd
|
|
928
|
-
)),
|
|
929
|
-
/* @__PURE__ */ jsx("div", { className: "code-toolbar-dropup-separator" }),
|
|
930
|
-
["pull"].map((cmd) => /* @__PURE__ */ jsx(
|
|
931
|
-
"button",
|
|
932
|
-
{
|
|
933
|
-
className: "code-toolbar-dropup-item",
|
|
934
|
-
onClick: () => {
|
|
935
|
-
setSelectedCommand(cmd);
|
|
936
|
-
setDropupOpen(false);
|
|
937
|
-
},
|
|
938
|
-
children: getCommandLabel(cmd)
|
|
911
|
+
dropupOpen && /* @__PURE__ */ jsx("div", { className: "code-toolbar-dropup", children: GIT_COMMANDS.map((cmd) => /* @__PURE__ */ jsx(
|
|
912
|
+
"button",
|
|
913
|
+
{
|
|
914
|
+
className: "code-toolbar-dropup-item",
|
|
915
|
+
onClick: () => {
|
|
916
|
+
setSelectedCommand(cmd);
|
|
917
|
+
setDropupOpen(false);
|
|
939
918
|
},
|
|
940
|
-
cmd
|
|
941
|
-
|
|
942
|
-
|
|
919
|
+
children: getCommandLabel(cmd)
|
|
920
|
+
},
|
|
921
|
+
cmd
|
|
922
|
+
)) })
|
|
943
923
|
] }),
|
|
944
924
|
dialogOpen && /* @__PURE__ */ jsx(
|
|
945
925
|
CommandOutputDialog,
|
|
@@ -8,7 +8,8 @@ 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 { CommandOutputDialog } from '../chat/components/code-mode-toggle.js';
|
|
12
|
+
import { GIT_COMMANDS, getCommandLabel, FALLBACK_BY_MODE } from '../git-commands.js';
|
|
12
13
|
import { useVoiceInput } from '../voice/use-voice-input.js';
|
|
13
14
|
import { VoiceBars } from '../chat/components/voice-bars.js';
|
|
14
15
|
|
|
@@ -543,11 +544,6 @@ export default function TerminalView({ codeWorkspaceId, wsPath, isActive = true,
|
|
|
543
544
|
color: #7aa2f7;
|
|
544
545
|
background: rgba(122,162,247,0.08);
|
|
545
546
|
}
|
|
546
|
-
.code-toolbar-dropup-separator {
|
|
547
|
-
height: 1px;
|
|
548
|
-
background: var(--tb-border, rgba(169,177,214,0.15));
|
|
549
|
-
margin: 4px 0;
|
|
550
|
-
}
|
|
551
547
|
.code-toolbar-btn--reconnect:hover {
|
|
552
548
|
color: var(--tb-hover, #a9b1d6);
|
|
553
549
|
}
|
|
@@ -843,7 +839,6 @@ export default function TerminalView({ codeWorkspaceId, wsPath, isActive = true,
|
|
|
843
839
|
}
|
|
844
840
|
|
|
845
841
|
const STORAGE_KEY = 'thepopebot-workspace-command';
|
|
846
|
-
const FALLBACK_BY_MODE = { agent: 'push', code: 'create-pr' };
|
|
847
842
|
|
|
848
843
|
function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh, onShowDiff }) {
|
|
849
844
|
// Resolve chatMode from the workspace's chat (matches code-mode-toggle's per-mode behavior).
|
|
@@ -967,17 +962,7 @@ function ToolbarCommandButton({ codeWorkspaceId, diffStats, onDiffStatsRefresh,
|
|
|
967
962
|
</div>
|
|
968
963
|
{dropupOpen && (
|
|
969
964
|
<div className="code-toolbar-dropup">
|
|
970
|
-
{
|
|
971
|
-
<button
|
|
972
|
-
key={cmd}
|
|
973
|
-
className="code-toolbar-dropup-item"
|
|
974
|
-
onClick={() => { setSelectedCommand(cmd); setDropupOpen(false); }}
|
|
975
|
-
>
|
|
976
|
-
{getCommandLabel(cmd)}
|
|
977
|
-
</button>
|
|
978
|
-
))}
|
|
979
|
-
<div className="code-toolbar-dropup-separator" />
|
|
980
|
-
{['pull'].map((cmd) => (
|
|
965
|
+
{GIT_COMMANDS.map((cmd) => (
|
|
981
966
|
<button
|
|
982
967
|
key={cmd}
|
|
983
968
|
className="code-toolbar-dropup-item"
|
package/lib/config.js
CHANGED
|
@@ -81,9 +81,9 @@ const DEFAULTS = {
|
|
|
81
81
|
CODING_AGENT_KIMI_CLI_ENABLED: 'false',
|
|
82
82
|
AGENT_MODE_BRANCH: 'default',
|
|
83
83
|
CODE_MODE_BRANCH: 'dynamic',
|
|
84
|
-
AGENT_MODE_GIT_ACTION: 'push',
|
|
84
|
+
AGENT_MODE_GIT_ACTION: 'pull-push',
|
|
85
85
|
CODE_MODE_GIT_ACTION: 'create-pr',
|
|
86
|
-
AGENT_MODE_AUTO_RUN: '
|
|
86
|
+
AGENT_MODE_AUTO_RUN: 'true',
|
|
87
87
|
CODE_MODE_AUTO_RUN: 'false',
|
|
88
88
|
};
|
|
89
89
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for the workspace git commands.
|
|
3
|
+
*
|
|
4
|
+
* Used by:
|
|
5
|
+
* - Chat dropdown (lib/chat/components/code-mode-toggle.jsx)
|
|
6
|
+
* - Workspace toolbar dropup (lib/code/terminal-view.jsx)
|
|
7
|
+
* - Admin defaults select (lib/chat/components/settings-coding-agents-page.jsx)
|
|
8
|
+
* - Manual launch (lib/code/actions.js — launchWorkspaceCommand, runWorkspaceCommand)
|
|
9
|
+
* - Auto-run on chat finish (lib/ai/index.js — maybeAutoRun)
|
|
10
|
+
* - Server-side validation (lib/chat/actions.js — setModeDefault)
|
|
11
|
+
*
|
|
12
|
+
* Plain ESM (no 'use client'), so both server and client code can import it.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export const GIT_COMMANDS = ['pull', 'commit', 'push', 'pull-push', 'create-pr'];
|
|
16
|
+
export const GIT_COMMAND_SET = new Set(GIT_COMMANDS);
|
|
17
|
+
export const FALLBACK_BY_MODE = { agent: 'pull-push', code: 'create-pr' };
|
|
18
|
+
|
|
19
|
+
export function getCommandLabel(slug) {
|
|
20
|
+
return slug
|
|
21
|
+
.split('-')
|
|
22
|
+
.map(word => word.length <= 2 ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1))
|
|
23
|
+
.join(' ');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function getCommandPrompt(command, { branch = '', featureBranch = '' } = {}) {
|
|
27
|
+
switch (command) {
|
|
28
|
+
case 'commit':
|
|
29
|
+
return '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.';
|
|
30
|
+
case 'push':
|
|
31
|
+
return `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.`;
|
|
32
|
+
case 'create-pr':
|
|
33
|
+
return `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.`;
|
|
34
|
+
case 'pull':
|
|
35
|
+
return `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.`;
|
|
36
|
+
case 'pull-push':
|
|
37
|
+
return `Stage all changes with \`git add -A\`. Review the staged diff with \`git diff --cached\`. If there are staged changes, write a clear conventional commit message and run \`git commit\`. Then fetch from origin with \`git fetch origin\`. If \`origin/${featureBranch || branch}\` exists, rebase onto it with \`git rebase origin/${featureBranch || branch}\` — resolve any conflicts by reading each conflicting file, choosing the correct resolution, \`git add\` the file, then run \`git rebase --continue\`. Finally, run \`git push origin ${featureBranch || branch}\`. If anything fails, diagnose the issue and fix it.`;
|
|
38
|
+
default:
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
}
|