webmux 0.12.0 → 0.14.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/backend/dist/server.js +124 -32
- package/bin/webmux.js +171 -36
- package/frontend/dist/assets/index-Bi9DHlpD.js +34 -0
- package/frontend/dist/assets/index-FwEUWC9Q.css +32 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/frontend/dist/assets/index-DIWwx16E.css +0 -32
- package/frontend/dist/assets/index-Pz_SK2_d.js +0 -32
package/backend/dist/server.js
CHANGED
|
@@ -8092,7 +8092,6 @@ class BunTmuxGateway {
|
|
|
8092
8092
|
if (check.exitCode !== 0) {
|
|
8093
8093
|
assertTmuxOk(["new-session", "-d", "-s", sessionName, "-c", cwd], `create tmux session ${sessionName}`);
|
|
8094
8094
|
}
|
|
8095
|
-
assertTmuxOk(["set-option", "-t", sessionName, "pane-base-index", "0"], `set pane-base-index on ${sessionName}`);
|
|
8096
8095
|
}
|
|
8097
8096
|
hasWindow(sessionName, windowName) {
|
|
8098
8097
|
const result = runTmux(["list-windows", "-t", sessionName, "-F", "#{window_name}"]);
|
|
@@ -8190,15 +8189,22 @@ function buildRuntimeBootstrap(runtimeEnvPath) {
|
|
|
8190
8189
|
return `set -a; . ${quoteShell(runtimeEnvPath)}; set +a`;
|
|
8191
8190
|
}
|
|
8192
8191
|
function buildAgentInvocation(input) {
|
|
8193
|
-
const promptSuffix = input.prompt ? ` ${quoteShell(input.prompt)}` : "";
|
|
8194
8192
|
if (input.agent === "codex") {
|
|
8195
8193
|
const yoloFlag2 = input.yolo ? " --yolo" : "";
|
|
8194
|
+
if (input.launchMode === "resume") {
|
|
8195
|
+
return `codex${yoloFlag2} resume --last`;
|
|
8196
|
+
}
|
|
8197
|
+
const promptSuffix2 = input.prompt ? ` ${quoteShell(input.prompt)}` : "";
|
|
8196
8198
|
if (input.systemPrompt) {
|
|
8197
|
-
return `codex${yoloFlag2} -c ${quoteShell(`developer_instructions=${input.systemPrompt}`)}${
|
|
8199
|
+
return `codex${yoloFlag2} -c ${quoteShell(`developer_instructions=${input.systemPrompt}`)}${promptSuffix2}`;
|
|
8198
8200
|
}
|
|
8199
|
-
return `codex${yoloFlag2}${
|
|
8201
|
+
return `codex${yoloFlag2}${promptSuffix2}`;
|
|
8200
8202
|
}
|
|
8201
8203
|
const yoloFlag = input.yolo ? " --dangerously-skip-permissions" : "";
|
|
8204
|
+
if (input.launchMode === "resume") {
|
|
8205
|
+
return `claude${yoloFlag} --continue`;
|
|
8206
|
+
}
|
|
8207
|
+
const promptSuffix = input.prompt ? ` ${quoteShell(input.prompt)}` : "";
|
|
8202
8208
|
if (input.systemPrompt) {
|
|
8203
8209
|
return `claude${yoloFlag} --append-system-prompt ${quoteShell(input.systemPrompt)}${promptSuffix}`;
|
|
8204
8210
|
}
|
|
@@ -8281,6 +8287,7 @@ function ensureSessionLayout(tmux, plan) {
|
|
|
8281
8287
|
cwd: rootPane.cwd,
|
|
8282
8288
|
command: plan.shellCommand
|
|
8283
8289
|
});
|
|
8290
|
+
tmux.setWindowOption(plan.sessionName, plan.windowName, "pane-base-index", "0");
|
|
8284
8291
|
tmux.setWindowOption(plan.sessionName, plan.windowName, "automatic-rename", "off");
|
|
8285
8292
|
tmux.setWindowOption(plan.sessionName, plan.windowName, "allow-rename", "off");
|
|
8286
8293
|
for (const pane of plan.panes.slice(1)) {
|
|
@@ -8421,6 +8428,11 @@ function listGitWorktrees(cwd) {
|
|
|
8421
8428
|
const output = runGit(["worktree", "list", "--porcelain"], cwd);
|
|
8422
8429
|
return parseGitWorktreePorcelain(output);
|
|
8423
8430
|
}
|
|
8431
|
+
function listLocalGitBranches(cwd) {
|
|
8432
|
+
const output = runGit(["for-each-ref", "--format=%(refname:short)", "refs/heads"], cwd);
|
|
8433
|
+
return output.split(`
|
|
8434
|
+
`).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
8435
|
+
}
|
|
8424
8436
|
function readGitWorktreeStatus(cwd) {
|
|
8425
8437
|
const dirtyOutput = runGit(["status", "--porcelain"], cwd);
|
|
8426
8438
|
const commit = tryRunGit(["rev-parse", "HEAD"], cwd);
|
|
@@ -8462,13 +8474,21 @@ class BunGitGateway {
|
|
|
8462
8474
|
listWorktrees(cwd) {
|
|
8463
8475
|
return listGitWorktrees(cwd);
|
|
8464
8476
|
}
|
|
8477
|
+
listLocalBranches(cwd) {
|
|
8478
|
+
return listLocalGitBranches(cwd);
|
|
8479
|
+
}
|
|
8465
8480
|
readWorktreeStatus(cwd) {
|
|
8466
8481
|
return readGitWorktreeStatus(cwd);
|
|
8467
8482
|
}
|
|
8468
8483
|
createWorktree(opts) {
|
|
8469
|
-
const args = ["worktree", "add"
|
|
8470
|
-
if (opts.
|
|
8471
|
-
args.push(opts.
|
|
8484
|
+
const args = ["worktree", "add"];
|
|
8485
|
+
if (opts.mode === "new") {
|
|
8486
|
+
args.push("-b", opts.branch, opts.worktreePath);
|
|
8487
|
+
if (opts.baseBranch)
|
|
8488
|
+
args.push(opts.baseBranch);
|
|
8489
|
+
} else {
|
|
8490
|
+
args.push(opts.worktreePath, opts.branch);
|
|
8491
|
+
}
|
|
8472
8492
|
runGit(args, opts.repoRoot);
|
|
8473
8493
|
}
|
|
8474
8494
|
removeWorktree(opts) {
|
|
@@ -8547,10 +8567,12 @@ function rollbackManagedWorktreeCreation(opts, sessionLayoutPlan, git, deps) {
|
|
|
8547
8567
|
} catch (error) {
|
|
8548
8568
|
cleanupErrors.push(`worktree rollback failed: ${toErrorMessage(error)}`);
|
|
8549
8569
|
}
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8570
|
+
if (opts.deleteBranchOnRollback ?? true) {
|
|
8571
|
+
try {
|
|
8572
|
+
git.deleteBranch(opts.repoRoot, opts.branch, true);
|
|
8573
|
+
} catch (error) {
|
|
8574
|
+
cleanupErrors.push(`branch rollback failed: ${toErrorMessage(error)}`);
|
|
8575
|
+
}
|
|
8554
8576
|
}
|
|
8555
8577
|
return cleanupErrors.length > 0 ? joinErrorMessages(cleanupErrors) : null;
|
|
8556
8578
|
}
|
|
@@ -8600,6 +8622,7 @@ async function createManagedWorktree(opts, deps = {}) {
|
|
|
8600
8622
|
repoRoot: opts.repoRoot,
|
|
8601
8623
|
worktreePath: opts.worktreePath,
|
|
8602
8624
|
branch: opts.branch,
|
|
8625
|
+
mode: opts.mode,
|
|
8603
8626
|
baseBranch: opts.baseBranch
|
|
8604
8627
|
});
|
|
8605
8628
|
worktreeCreated = true;
|
|
@@ -8679,11 +8702,13 @@ class LifecycleService {
|
|
|
8679
8702
|
this.deps = deps;
|
|
8680
8703
|
}
|
|
8681
8704
|
async createWorktree(input) {
|
|
8682
|
-
const
|
|
8683
|
-
this.
|
|
8705
|
+
const mode = input.mode ?? "new";
|
|
8706
|
+
const branch = await this.resolveBranch(input.branch, input.prompt, mode);
|
|
8707
|
+
this.ensureBranchAvailable(branch, mode);
|
|
8684
8708
|
const { profileName, profile } = this.resolveProfile(input.profile);
|
|
8685
8709
|
const agent = this.resolveAgent(input.agent);
|
|
8686
8710
|
const worktreePath = this.resolveWorktreePath(branch);
|
|
8711
|
+
const deleteBranchOnRollback = mode === "new";
|
|
8687
8712
|
let initialized = null;
|
|
8688
8713
|
try {
|
|
8689
8714
|
await this.reportCreateProgress({
|
|
@@ -8698,7 +8723,8 @@ class LifecycleService {
|
|
|
8698
8723
|
repoRoot: this.deps.projectRoot,
|
|
8699
8724
|
worktreePath,
|
|
8700
8725
|
branch,
|
|
8701
|
-
|
|
8726
|
+
mode,
|
|
8727
|
+
...mode === "new" ? { baseBranch: this.deps.config.workspace.mainBranch } : {},
|
|
8702
8728
|
profile: profileName,
|
|
8703
8729
|
agent,
|
|
8704
8730
|
runtime: profile.runtime,
|
|
@@ -8706,7 +8732,8 @@ class LifecycleService {
|
|
|
8706
8732
|
allocatedPorts: await this.allocatePorts(),
|
|
8707
8733
|
runtimeEnvExtras: { WEBMUX_WORKTREE_PATH: worktreePath },
|
|
8708
8734
|
controlUrl: this.controlUrl(),
|
|
8709
|
-
controlToken: await this.deps.getControlToken()
|
|
8735
|
+
controlToken: await this.deps.getControlToken(),
|
|
8736
|
+
deleteBranchOnRollback
|
|
8710
8737
|
}, {
|
|
8711
8738
|
git: this.deps.git
|
|
8712
8739
|
});
|
|
@@ -8752,7 +8779,8 @@ class LifecycleService {
|
|
|
8752
8779
|
agent,
|
|
8753
8780
|
initialized,
|
|
8754
8781
|
worktreePath,
|
|
8755
|
-
prompt: input.prompt
|
|
8782
|
+
prompt: input.prompt,
|
|
8783
|
+
launchMode: "fresh"
|
|
8756
8784
|
});
|
|
8757
8785
|
await this.reportCreateProgress({
|
|
8758
8786
|
branch,
|
|
@@ -8768,7 +8796,7 @@ class LifecycleService {
|
|
|
8768
8796
|
};
|
|
8769
8797
|
} catch (error) {
|
|
8770
8798
|
if (initialized) {
|
|
8771
|
-
const cleanupError = await this.cleanupFailedCreate(branch, worktreePath, profile.runtime);
|
|
8799
|
+
const cleanupError = await this.cleanupFailedCreate(branch, worktreePath, profile.runtime, deleteBranchOnRollback);
|
|
8772
8800
|
if (cleanupError) {
|
|
8773
8801
|
throw this.wrapOperationError(new Error(`${toErrorMessage2(error)}; ${cleanupError}`));
|
|
8774
8802
|
}
|
|
@@ -8781,6 +8809,7 @@ class LifecycleService {
|
|
|
8781
8809
|
async openWorktree(branch) {
|
|
8782
8810
|
try {
|
|
8783
8811
|
const resolved = await this.resolveExistingWorktree(branch);
|
|
8812
|
+
const launchMode = resolved.meta ? "resume" : "fresh";
|
|
8784
8813
|
const initialized = resolved.meta ? await this.refreshManagedArtifacts(resolved) : await this.initializeUnmanagedWorktree(resolved);
|
|
8785
8814
|
const { profile } = this.resolveProfile(initialized.meta.profile);
|
|
8786
8815
|
await ensureAgentRuntimeArtifacts({
|
|
@@ -8792,7 +8821,8 @@ class LifecycleService {
|
|
|
8792
8821
|
profile,
|
|
8793
8822
|
agent: initialized.meta.agent,
|
|
8794
8823
|
initialized,
|
|
8795
|
-
worktreePath: resolved.entry.path
|
|
8824
|
+
worktreePath: resolved.entry.path,
|
|
8825
|
+
launchMode
|
|
8796
8826
|
});
|
|
8797
8827
|
await this.deps.reconciliation.reconcile(this.deps.projectRoot);
|
|
8798
8828
|
return {
|
|
@@ -8820,6 +8850,20 @@ class LifecycleService {
|
|
|
8820
8850
|
throw this.wrapOperationError(error);
|
|
8821
8851
|
}
|
|
8822
8852
|
}
|
|
8853
|
+
async pruneWorktrees() {
|
|
8854
|
+
try {
|
|
8855
|
+
const resolvedWorktrees = await this.resolveAllWorktrees();
|
|
8856
|
+
const removedBranches = [];
|
|
8857
|
+
for (const resolved of resolvedWorktrees) {
|
|
8858
|
+
const branch = resolved.entry.branch ?? resolved.entry.path;
|
|
8859
|
+
await this.removeResolvedWorktree(resolved);
|
|
8860
|
+
removedBranches.push(branch);
|
|
8861
|
+
}
|
|
8862
|
+
return { removedBranches };
|
|
8863
|
+
} catch (error) {
|
|
8864
|
+
throw this.wrapOperationError(error);
|
|
8865
|
+
}
|
|
8866
|
+
}
|
|
8823
8867
|
async mergeWorktree(branch) {
|
|
8824
8868
|
try {
|
|
8825
8869
|
const resolved = await this.resolveExistingWorktree(branch);
|
|
@@ -8838,9 +8882,17 @@ class LifecycleService {
|
|
|
8838
8882
|
throw this.wrapOperationError(error);
|
|
8839
8883
|
}
|
|
8840
8884
|
}
|
|
8841
|
-
|
|
8885
|
+
listAvailableBranches() {
|
|
8886
|
+
const localBranches = this.listLocalBranches().filter((branch) => isValidBranchName(branch));
|
|
8887
|
+
const checkedOutBranches = this.listCheckedOutBranches();
|
|
8888
|
+
return localBranches.filter((branch) => !checkedOutBranches.has(branch)).sort((left, right) => left.localeCompare(right)).map((name) => ({ name }));
|
|
8889
|
+
}
|
|
8890
|
+
async resolveBranch(rawBranch, prompt, mode) {
|
|
8842
8891
|
const explicitBranch = rawBranch?.trim();
|
|
8843
|
-
const branch = explicitBranch || await this.generateAutoName(prompt) || generateBranchName();
|
|
8892
|
+
const branch = mode === "existing" ? explicitBranch : explicitBranch || await this.generateAutoName(prompt) || generateBranchName();
|
|
8893
|
+
if (!branch) {
|
|
8894
|
+
throw new LifecycleError("Existing branch is required", 400);
|
|
8895
|
+
}
|
|
8844
8896
|
if (!isValidBranchName(branch)) {
|
|
8845
8897
|
throw new LifecycleError(`Invalid branch name: ${branch}`, 400);
|
|
8846
8898
|
}
|
|
@@ -8852,10 +8904,19 @@ class LifecycleService {
|
|
|
8852
8904
|
}
|
|
8853
8905
|
return await this.deps.autoName.generateBranchName(this.deps.config.autoName, prompt);
|
|
8854
8906
|
}
|
|
8855
|
-
ensureBranchAvailable(branch) {
|
|
8856
|
-
const
|
|
8857
|
-
if (
|
|
8858
|
-
|
|
8907
|
+
ensureBranchAvailable(branch, mode) {
|
|
8908
|
+
const localBranches = new Set(this.listLocalBranches());
|
|
8909
|
+
if (mode === "new") {
|
|
8910
|
+
if (localBranches.has(branch)) {
|
|
8911
|
+
throw new LifecycleError(`Branch already exists: ${branch}`, 409);
|
|
8912
|
+
}
|
|
8913
|
+
return;
|
|
8914
|
+
}
|
|
8915
|
+
if (!localBranches.has(branch)) {
|
|
8916
|
+
throw new LifecycleError(`Branch not found: ${branch}`, 404);
|
|
8917
|
+
}
|
|
8918
|
+
if (this.listCheckedOutBranches().has(branch)) {
|
|
8919
|
+
throw new LifecycleError(`Branch already has a worktree: ${branch}`, 409);
|
|
8859
8920
|
}
|
|
8860
8921
|
}
|
|
8861
8922
|
resolveProfile(profileName) {
|
|
@@ -8894,6 +8955,12 @@ class LifecycleService {
|
|
|
8894
8955
|
resolveWorktreePath(branch) {
|
|
8895
8956
|
return resolve3(this.deps.projectRoot, this.deps.config.workspace.worktreeRoot, branch);
|
|
8896
8957
|
}
|
|
8958
|
+
listLocalBranches() {
|
|
8959
|
+
return this.deps.git.listLocalBranches(resolve3(this.deps.projectRoot));
|
|
8960
|
+
}
|
|
8961
|
+
listCheckedOutBranches() {
|
|
8962
|
+
return new Set(this.deps.git.listWorktrees(resolve3(this.deps.projectRoot)).filter((entry) => !entry.bare && entry.branch !== null).map((entry) => entry.branch));
|
|
8963
|
+
}
|
|
8897
8964
|
listProjectWorktrees() {
|
|
8898
8965
|
const projectRoot = resolve3(this.deps.projectRoot);
|
|
8899
8966
|
return this.deps.git.listWorktrees(projectRoot).filter((entry) => !entry.bare && resolve3(entry.path) !== projectRoot);
|
|
@@ -8914,6 +8981,14 @@ class LifecycleService {
|
|
|
8914
8981
|
const meta = await readWorktreeMeta(gitDir);
|
|
8915
8982
|
return { entry, gitDir, meta };
|
|
8916
8983
|
}
|
|
8984
|
+
async resolveAllWorktrees() {
|
|
8985
|
+
const entries = this.listProjectWorktrees().sort((left, right) => (left.branch ?? left.path).localeCompare(right.branch ?? right.path));
|
|
8986
|
+
return await Promise.all(entries.map(async (entry) => {
|
|
8987
|
+
const gitDir = this.deps.git.resolveWorktreeGitDir(entry.path);
|
|
8988
|
+
const meta = await readWorktreeMeta(gitDir);
|
|
8989
|
+
return { entry, gitDir, meta };
|
|
8990
|
+
}));
|
|
8991
|
+
}
|
|
8917
8992
|
async initializeUnmanagedWorktree(resolved) {
|
|
8918
8993
|
const { profileName, profile } = this.resolveProfile(undefined);
|
|
8919
8994
|
const dotenvValues = await loadDotenvLocal(resolved.entry.path);
|
|
@@ -8979,6 +9054,7 @@ class LifecycleService {
|
|
|
8979
9054
|
initialized: input.initialized,
|
|
8980
9055
|
worktreePath: input.worktreePath,
|
|
8981
9056
|
prompt: input.prompt,
|
|
9057
|
+
launchMode: input.launchMode,
|
|
8982
9058
|
containerName
|
|
8983
9059
|
}));
|
|
8984
9060
|
return;
|
|
@@ -8989,11 +9065,12 @@ class LifecycleService {
|
|
|
8989
9065
|
agent: input.agent,
|
|
8990
9066
|
initialized: input.initialized,
|
|
8991
9067
|
worktreePath: input.worktreePath,
|
|
8992
|
-
prompt: input.prompt
|
|
9068
|
+
prompt: input.prompt,
|
|
9069
|
+
launchMode: input.launchMode
|
|
8993
9070
|
}));
|
|
8994
9071
|
}
|
|
8995
9072
|
buildSessionLayout(input) {
|
|
8996
|
-
const systemPrompt = input.profile.systemPrompt ? expandTemplate(input.profile.systemPrompt, input.initialized.runtimeEnv) : undefined;
|
|
9073
|
+
const systemPrompt = input.launchMode === "fresh" && input.profile.systemPrompt ? expandTemplate(input.profile.systemPrompt, input.initialized.runtimeEnv) : undefined;
|
|
8997
9074
|
const containerName = input.containerName;
|
|
8998
9075
|
return planSessionLayout(this.deps.projectRoot, input.branch, input.profile.panes, {
|
|
8999
9076
|
repoRoot: this.deps.projectRoot,
|
|
@@ -9006,7 +9083,8 @@ class LifecycleService {
|
|
|
9006
9083
|
runtimeEnvPath: input.initialized.paths.runtimeEnvPath,
|
|
9007
9084
|
yolo: input.profile.yolo === true,
|
|
9008
9085
|
systemPrompt,
|
|
9009
|
-
prompt: input.prompt
|
|
9086
|
+
prompt: input.launchMode === "fresh" ? input.prompt : undefined,
|
|
9087
|
+
launchMode: input.launchMode
|
|
9010
9088
|
}),
|
|
9011
9089
|
shell: buildDockerShellCommand(containerName, input.worktreePath, input.initialized.paths.runtimeEnvPath)
|
|
9012
9090
|
} : {
|
|
@@ -9015,7 +9093,8 @@ class LifecycleService {
|
|
|
9015
9093
|
runtimeEnvPath: input.initialized.paths.runtimeEnvPath,
|
|
9016
9094
|
yolo: input.profile.yolo === true,
|
|
9017
9095
|
systemPrompt,
|
|
9018
|
-
prompt: input.prompt
|
|
9096
|
+
prompt: input.launchMode === "fresh" ? input.prompt : undefined,
|
|
9097
|
+
launchMode: input.launchMode
|
|
9019
9098
|
}),
|
|
9020
9099
|
shell: buildManagedShellCommand(input.initialized.paths.runtimeEnvPath)
|
|
9021
9100
|
}
|
|
@@ -9027,7 +9106,7 @@ class LifecycleService {
|
|
|
9027
9106
|
}
|
|
9028
9107
|
return profile;
|
|
9029
9108
|
}
|
|
9030
|
-
async cleanupFailedCreate(branch, worktreePath, runtime) {
|
|
9109
|
+
async cleanupFailedCreate(branch, worktreePath, runtime, deleteBranch) {
|
|
9031
9110
|
const cleanupErrors = [];
|
|
9032
9111
|
if (runtime === "docker") {
|
|
9033
9112
|
try {
|
|
@@ -9047,8 +9126,8 @@ class LifecycleService {
|
|
|
9047
9126
|
worktreePath,
|
|
9048
9127
|
branch,
|
|
9049
9128
|
force: true,
|
|
9050
|
-
deleteBranch
|
|
9051
|
-
deleteBranchForce:
|
|
9129
|
+
deleteBranch,
|
|
9130
|
+
deleteBranchForce: deleteBranch
|
|
9052
9131
|
}, this.deps.git);
|
|
9053
9132
|
} catch (error) {
|
|
9054
9133
|
cleanupErrors.push(`worktree cleanup failed: ${toErrorMessage2(error)}`);
|
|
@@ -10743,6 +10822,11 @@ async function apiRuntimeEvent(req) {
|
|
|
10743
10822
|
...notification ? { notification } : {}
|
|
10744
10823
|
});
|
|
10745
10824
|
}
|
|
10825
|
+
async function apiListBranches() {
|
|
10826
|
+
return jsonResponse({
|
|
10827
|
+
branches: lifecycleService.listAvailableBranches()
|
|
10828
|
+
});
|
|
10829
|
+
}
|
|
10746
10830
|
async function apiCreateWorktree(req) {
|
|
10747
10831
|
const raw = await req.json();
|
|
10748
10832
|
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
@@ -10764,11 +10848,16 @@ async function apiCreateWorktree(req) {
|
|
|
10764
10848
|
const prompt = typeof body.prompt === "string" ? body.prompt : undefined;
|
|
10765
10849
|
const profile = typeof body.profile === "string" ? body.profile : undefined;
|
|
10766
10850
|
const agent = body.agent === "claude" || body.agent === "codex" ? body.agent : undefined;
|
|
10851
|
+
const mode = body.mode;
|
|
10852
|
+
if (mode !== undefined && mode !== "new" && mode !== "existing") {
|
|
10853
|
+
return errorResponse("Invalid worktree create mode", 400);
|
|
10854
|
+
}
|
|
10767
10855
|
if (branch) {
|
|
10768
10856
|
ensureBranchNotCreating(branch);
|
|
10769
10857
|
}
|
|
10770
|
-
log.info(`[worktree:add]${branch ? ` branch=${branch}` : ""}${profile ? ` profile=${profile}` : ""}${agent ? ` agent=${agent}` : ""}${prompt ? ` prompt="${prompt.slice(0, 80)}"` : ""}`);
|
|
10858
|
+
log.info(`[worktree:add] mode=${mode ?? "new"}${branch ? ` branch=${branch}` : ""}${profile ? ` profile=${profile}` : ""}${agent ? ` agent=${agent}` : ""}${prompt ? ` prompt="${prompt.slice(0, 80)}"` : ""}`);
|
|
10771
10859
|
const result = await lifecycleService.createWorktree({
|
|
10860
|
+
mode,
|
|
10772
10861
|
branch,
|
|
10773
10862
|
prompt,
|
|
10774
10863
|
profile,
|
|
@@ -10857,6 +10946,9 @@ Bun.serve({
|
|
|
10857
10946
|
"/api/config": {
|
|
10858
10947
|
GET: () => jsonResponse(getFrontendConfig())
|
|
10859
10948
|
},
|
|
10949
|
+
"/api/branches": {
|
|
10950
|
+
GET: () => catching("GET /api/branches", () => apiListBranches())
|
|
10951
|
+
},
|
|
10860
10952
|
"/api/project": {
|
|
10861
10953
|
GET: () => catching("GET /api/project", () => apiGetProject())
|
|
10862
10954
|
},
|