webmux 0.13.0 → 0.15.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/README.md +2 -1
- package/backend/dist/server.js +152 -71
- package/bin/webmux.js +147 -67
- package/frontend/dist/assets/index-Bt0UjBTn.css +32 -0
- package/frontend/dist/assets/index-C9lpouvy.js +35 -0
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/frontend/dist/assets/index-Bi9DHlpD.js +0 -34
- package/frontend/dist/assets/index-FwEUWC9Q.css +0 -32
package/bin/webmux.js
CHANGED
|
@@ -2604,6 +2604,9 @@ function assertTmuxOk(args, action) {
|
|
|
2604
2604
|
}
|
|
2605
2605
|
return result.stdout;
|
|
2606
2606
|
}
|
|
2607
|
+
function isIgnorableKillWindowError(stderr) {
|
|
2608
|
+
return stderr.includes("can't find window") || stderr.includes("can't find session") || stderr.includes("no server running") || stderr.includes("error connecting to") && stderr.includes("No such file or directory");
|
|
2609
|
+
}
|
|
2607
2610
|
function sanitizeTmuxNameSegment(value, maxLength = 24) {
|
|
2608
2611
|
const sanitized = value.toLowerCase().replace(/[^a-z0-9_.-]+/g, "-").replace(/-{2,}/g, "-").replace(/^[.-]+|[.-]+$/g, "");
|
|
2609
2612
|
const trimmed = sanitized.slice(0, maxLength);
|
|
@@ -2637,8 +2640,10 @@ class BunTmuxGateway {
|
|
|
2637
2640
|
ensureSession(sessionName, cwd) {
|
|
2638
2641
|
const check = runTmux(["has-session", "-t", sessionName]);
|
|
2639
2642
|
if (check.exitCode !== 0) {
|
|
2640
|
-
assertTmuxOk(["new-session", "-d", "-s", sessionName, "-c", cwd], `create tmux session ${sessionName}`);
|
|
2643
|
+
assertTmuxOk(["new-session", "-d", "-s", sessionName, "-c", cwd, ";", "set-option", "-t", sessionName, "destroy-unattached", "off"], `create tmux session ${sessionName}`);
|
|
2644
|
+
return;
|
|
2641
2645
|
}
|
|
2646
|
+
assertTmuxOk(["set-option", "-t", sessionName, "destroy-unattached", "off"], `set destroy-unattached off for ${sessionName}`);
|
|
2642
2647
|
}
|
|
2643
2648
|
hasWindow(sessionName, windowName) {
|
|
2644
2649
|
const result = runTmux(["list-windows", "-t", sessionName, "-F", "#{window_name}"]);
|
|
@@ -2649,7 +2654,7 @@ class BunTmuxGateway {
|
|
|
2649
2654
|
}
|
|
2650
2655
|
killWindow(sessionName, windowName) {
|
|
2651
2656
|
const result = runTmux(["kill-window", "-t", `${sessionName}:${windowName}`]);
|
|
2652
|
-
if (result.exitCode !== 0 && !result.stderr
|
|
2657
|
+
if (result.exitCode !== 0 && !isIgnorableKillWindowError(result.stderr)) {
|
|
2653
2658
|
throw new Error(`kill tmux window ${sessionName}:${windowName} failed: ${result.stderr}`);
|
|
2654
2659
|
}
|
|
2655
2660
|
}
|
|
@@ -9685,10 +9690,27 @@ var init_dist3 = __esm(() => {
|
|
|
9685
9690
|
|
|
9686
9691
|
// backend/src/adapters/config.ts
|
|
9687
9692
|
import { readFileSync as readFileSync3 } from "fs";
|
|
9688
|
-
import { join as join6 } from "path";
|
|
9693
|
+
import { dirname as dirname2, join as join6, resolve as resolve4 } from "path";
|
|
9689
9694
|
function clonePanes(panes) {
|
|
9690
9695
|
return panes.map((pane) => ({ ...pane }));
|
|
9691
9696
|
}
|
|
9697
|
+
function cloneMounts(mounts) {
|
|
9698
|
+
return mounts?.map((mount) => ({ ...mount }));
|
|
9699
|
+
}
|
|
9700
|
+
function cloneProfile(profile) {
|
|
9701
|
+
return {
|
|
9702
|
+
...profile,
|
|
9703
|
+
envPassthrough: [...profile.envPassthrough],
|
|
9704
|
+
panes: clonePanes(profile.panes),
|
|
9705
|
+
...profile.mounts ? { mounts: cloneMounts(profile.mounts) } : {}
|
|
9706
|
+
};
|
|
9707
|
+
}
|
|
9708
|
+
function cloneProfiles(profiles) {
|
|
9709
|
+
return Object.fromEntries(Object.entries(profiles).map(([name, profile]) => [name, cloneProfile(profile)]));
|
|
9710
|
+
}
|
|
9711
|
+
function defaultProfiles() {
|
|
9712
|
+
return { default: cloneProfile(DEFAULT_CONFIG.profiles.default) };
|
|
9713
|
+
}
|
|
9692
9714
|
function isRecord3(value) {
|
|
9693
9715
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
9694
9716
|
}
|
|
@@ -9761,16 +9783,16 @@ function parseProfile(raw, fallbackRuntime) {
|
|
|
9761
9783
|
...mounts ? { mounts } : {}
|
|
9762
9784
|
};
|
|
9763
9785
|
}
|
|
9764
|
-
function parseProfiles(raw) {
|
|
9786
|
+
function parseProfiles(raw, includeDefaultProfile) {
|
|
9765
9787
|
if (!isRecord3(raw))
|
|
9766
|
-
return
|
|
9788
|
+
return includeDefaultProfile ? defaultProfiles() : {};
|
|
9767
9789
|
const profiles = Object.entries(raw).reduce((acc, [name, value]) => {
|
|
9768
9790
|
const fallbackRuntime = name === "sandbox" ? "docker" : "host";
|
|
9769
9791
|
acc[name] = parseProfile(value, fallbackRuntime);
|
|
9770
9792
|
return acc;
|
|
9771
9793
|
}, {});
|
|
9772
9794
|
if (Object.keys(profiles).length === 0) {
|
|
9773
|
-
return
|
|
9795
|
+
return includeDefaultProfile ? defaultProfiles() : {};
|
|
9774
9796
|
}
|
|
9775
9797
|
return profiles;
|
|
9776
9798
|
}
|
|
@@ -9842,6 +9864,69 @@ function getDefaultProfileName(config) {
|
|
|
9842
9864
|
function readConfigFile(root) {
|
|
9843
9865
|
return readFileSync3(join6(root, ".webmux.yaml"), "utf8");
|
|
9844
9866
|
}
|
|
9867
|
+
function readLocalConfigFile(root) {
|
|
9868
|
+
return readFileSync3(join6(root, ".webmux.local.yaml"), "utf8");
|
|
9869
|
+
}
|
|
9870
|
+
function parseConfigDocument(text) {
|
|
9871
|
+
const parsed = $parse(text);
|
|
9872
|
+
return isRecord3(parsed) ? parsed : {};
|
|
9873
|
+
}
|
|
9874
|
+
function parseProjectConfig(parsed) {
|
|
9875
|
+
return {
|
|
9876
|
+
name: typeof parsed.name === "string" && parsed.name.trim() ? parsed.name.trim() : DEFAULT_CONFIG.name,
|
|
9877
|
+
workspace: {
|
|
9878
|
+
mainBranch: isRecord3(parsed.workspace) && typeof parsed.workspace.mainBranch === "string" ? parsed.workspace.mainBranch : DEFAULT_CONFIG.workspace.mainBranch,
|
|
9879
|
+
worktreeRoot: isRecord3(parsed.workspace) && typeof parsed.workspace.worktreeRoot === "string" ? parsed.workspace.worktreeRoot : DEFAULT_CONFIG.workspace.worktreeRoot,
|
|
9880
|
+
defaultAgent: isRecord3(parsed.workspace) ? parseAgentKind(parsed.workspace.defaultAgent) : DEFAULT_CONFIG.workspace.defaultAgent
|
|
9881
|
+
},
|
|
9882
|
+
profiles: parseProfiles(parsed.profiles, true),
|
|
9883
|
+
services: parseServices(parsed.services),
|
|
9884
|
+
startupEnvs: parseStartupEnvs(parsed.startupEnvs),
|
|
9885
|
+
integrations: {
|
|
9886
|
+
github: {
|
|
9887
|
+
linkedRepos: isRecord3(parsed.integrations) && isRecord3(parsed.integrations.github) ? parseLinkedRepos(parsed.integrations.github.linkedRepos) : isRecord3(parsed.integrations) && Array.isArray(parsed.integrations.github) ? parseLinkedRepos(parsed.integrations.github) : []
|
|
9888
|
+
},
|
|
9889
|
+
linear: {
|
|
9890
|
+
enabled: isRecord3(parsed.integrations) && isRecord3(parsed.integrations.linear) && typeof parsed.integrations.linear.enabled === "boolean" ? parsed.integrations.linear.enabled : DEFAULT_CONFIG.integrations.linear.enabled
|
|
9891
|
+
}
|
|
9892
|
+
},
|
|
9893
|
+
lifecycleHooks: parseLifecycleHooks(parsed.lifecycleHooks),
|
|
9894
|
+
autoName: parseAutoName(parsed.auto_name)
|
|
9895
|
+
};
|
|
9896
|
+
}
|
|
9897
|
+
function defaultConfig() {
|
|
9898
|
+
return parseProjectConfig({});
|
|
9899
|
+
}
|
|
9900
|
+
function loadLocalProjectConfigOverlay(root) {
|
|
9901
|
+
try {
|
|
9902
|
+
const text = readLocalConfigFile(root).trim();
|
|
9903
|
+
if (!text) {
|
|
9904
|
+
return { profiles: {}, lifecycleHooks: {} };
|
|
9905
|
+
}
|
|
9906
|
+
const parsed = parseConfigDocument(text);
|
|
9907
|
+
return {
|
|
9908
|
+
profiles: parseProfiles(parsed.profiles, false),
|
|
9909
|
+
lifecycleHooks: parseLifecycleHooks(parsed.lifecycleHooks)
|
|
9910
|
+
};
|
|
9911
|
+
} catch {
|
|
9912
|
+
return { profiles: {}, lifecycleHooks: {} };
|
|
9913
|
+
}
|
|
9914
|
+
}
|
|
9915
|
+
function mergeHookCommand(projectCommand, localCommand) {
|
|
9916
|
+
if (projectCommand && localCommand) {
|
|
9917
|
+
return ["set -e", projectCommand, localCommand].join(`
|
|
9918
|
+
`);
|
|
9919
|
+
}
|
|
9920
|
+
return localCommand ?? projectCommand;
|
|
9921
|
+
}
|
|
9922
|
+
function mergeLifecycleHooks(projectHooks, localHooks) {
|
|
9923
|
+
const postCreate = mergeHookCommand(projectHooks.postCreate, localHooks.postCreate);
|
|
9924
|
+
const preRemove = mergeHookCommand(projectHooks.preRemove, localHooks.preRemove);
|
|
9925
|
+
return {
|
|
9926
|
+
...postCreate ? { postCreate } : {},
|
|
9927
|
+
...preRemove ? { preRemove } : {}
|
|
9928
|
+
};
|
|
9929
|
+
}
|
|
9845
9930
|
function gitRoot2(dir) {
|
|
9846
9931
|
const result = Bun.spawnSync(["git", "rev-parse", "--show-toplevel"], { stdout: "pipe", stderr: "pipe", cwd: dir });
|
|
9847
9932
|
if (result.exitCode !== 0)
|
|
@@ -9849,37 +9934,31 @@ function gitRoot2(dir) {
|
|
|
9849
9934
|
const root = new TextDecoder().decode(result.stdout).trim();
|
|
9850
9935
|
return root || dir;
|
|
9851
9936
|
}
|
|
9852
|
-
function
|
|
9937
|
+
function projectRoot(dir) {
|
|
9938
|
+
const result = Bun.spawnSync(["git", "rev-parse", "--git-common-dir"], { stdout: "pipe", stderr: "pipe", cwd: dir });
|
|
9939
|
+
if (result.exitCode !== 0)
|
|
9940
|
+
return gitRoot2(dir);
|
|
9941
|
+
const commonDir = new TextDecoder().decode(result.stdout).trim();
|
|
9942
|
+
return commonDir ? dirname2(resolve4(dir, commonDir)) : gitRoot2(dir);
|
|
9943
|
+
}
|
|
9944
|
+
function loadConfig(dir, options = {}) {
|
|
9945
|
+
const root = options.resolvedRoot ? dir : projectRoot(dir);
|
|
9946
|
+
let projectConfig;
|
|
9853
9947
|
try {
|
|
9854
|
-
const root = gitRoot2(dir);
|
|
9855
9948
|
const text = readConfigFile(root).trim();
|
|
9856
|
-
|
|
9857
|
-
return DEFAULT_CONFIG;
|
|
9858
|
-
const parsed = $parse(text);
|
|
9859
|
-
return {
|
|
9860
|
-
name: typeof parsed.name === "string" && parsed.name.trim() ? parsed.name.trim() : DEFAULT_CONFIG.name,
|
|
9861
|
-
workspace: {
|
|
9862
|
-
mainBranch: isRecord3(parsed.workspace) && typeof parsed.workspace.mainBranch === "string" ? parsed.workspace.mainBranch : DEFAULT_CONFIG.workspace.mainBranch,
|
|
9863
|
-
worktreeRoot: isRecord3(parsed.workspace) && typeof parsed.workspace.worktreeRoot === "string" ? parsed.workspace.worktreeRoot : DEFAULT_CONFIG.workspace.worktreeRoot,
|
|
9864
|
-
defaultAgent: isRecord3(parsed.workspace) ? parseAgentKind(parsed.workspace.defaultAgent) : DEFAULT_CONFIG.workspace.defaultAgent
|
|
9865
|
-
},
|
|
9866
|
-
profiles: parseProfiles(parsed.profiles),
|
|
9867
|
-
services: parseServices(parsed.services),
|
|
9868
|
-
startupEnvs: parseStartupEnvs(parsed.startupEnvs),
|
|
9869
|
-
integrations: {
|
|
9870
|
-
github: {
|
|
9871
|
-
linkedRepos: isRecord3(parsed.integrations) && isRecord3(parsed.integrations.github) ? parseLinkedRepos(parsed.integrations.github.linkedRepos) : isRecord3(parsed.integrations) && Array.isArray(parsed.integrations.github) ? parseLinkedRepos(parsed.integrations.github) : []
|
|
9872
|
-
},
|
|
9873
|
-
linear: {
|
|
9874
|
-
enabled: isRecord3(parsed.integrations) && isRecord3(parsed.integrations.linear) && typeof parsed.integrations.linear.enabled === "boolean" ? parsed.integrations.linear.enabled : DEFAULT_CONFIG.integrations.linear.enabled
|
|
9875
|
-
}
|
|
9876
|
-
},
|
|
9877
|
-
lifecycleHooks: parseLifecycleHooks(parsed.lifecycleHooks),
|
|
9878
|
-
autoName: parseAutoName(parsed.auto_name)
|
|
9879
|
-
};
|
|
9949
|
+
projectConfig = text ? parseProjectConfig(parseConfigDocument(text)) : defaultConfig();
|
|
9880
9950
|
} catch {
|
|
9881
|
-
|
|
9951
|
+
projectConfig = defaultConfig();
|
|
9882
9952
|
}
|
|
9953
|
+
const localOverlay = loadLocalProjectConfigOverlay(root);
|
|
9954
|
+
return {
|
|
9955
|
+
...projectConfig,
|
|
9956
|
+
profiles: {
|
|
9957
|
+
...cloneProfiles(projectConfig.profiles),
|
|
9958
|
+
...cloneProfiles(localOverlay.profiles)
|
|
9959
|
+
},
|
|
9960
|
+
lifecycleHooks: mergeLifecycleHooks(projectConfig.lifecycleHooks, localOverlay.lifecycleHooks)
|
|
9961
|
+
};
|
|
9883
9962
|
}
|
|
9884
9963
|
function expandTemplate(template, env) {
|
|
9885
9964
|
return template.replace(/\$\{(\w+)\}/g, (_2, key) => env[key] ?? "");
|
|
@@ -9918,7 +9997,7 @@ var init_config = __esm(() => {
|
|
|
9918
9997
|
|
|
9919
9998
|
// backend/src/adapters/control-token.ts
|
|
9920
9999
|
import { chmod, mkdir as mkdir2 } from "fs/promises";
|
|
9921
|
-
import { dirname as
|
|
10000
|
+
import { dirname as dirname3 } from "path";
|
|
9922
10001
|
async function loadControlToken() {
|
|
9923
10002
|
if (cachedToken)
|
|
9924
10003
|
return cachedToken;
|
|
@@ -9928,7 +10007,7 @@ async function loadControlToken() {
|
|
|
9928
10007
|
return cachedToken;
|
|
9929
10008
|
}
|
|
9930
10009
|
const controlToken = crypto.randomUUID();
|
|
9931
|
-
await mkdir2(
|
|
10010
|
+
await mkdir2(dirname3(CONTROL_TOKEN_PATH), { recursive: true });
|
|
9932
10011
|
await Bun.write(CONTROL_TOKEN_PATH, controlToken);
|
|
9933
10012
|
await chmod(CONTROL_TOKEN_PATH, 384);
|
|
9934
10013
|
cachedToken = controlToken;
|
|
@@ -10290,7 +10369,7 @@ class BunPortProbe {
|
|
|
10290
10369
|
this.hostnames = hostnames;
|
|
10291
10370
|
}
|
|
10292
10371
|
isListening(port) {
|
|
10293
|
-
return new Promise((
|
|
10372
|
+
return new Promise((resolve5) => {
|
|
10294
10373
|
let settled = false;
|
|
10295
10374
|
let pending = this.hostnames.length;
|
|
10296
10375
|
const settle = (result) => {
|
|
@@ -10299,20 +10378,20 @@ class BunPortProbe {
|
|
|
10299
10378
|
if (result) {
|
|
10300
10379
|
settled = true;
|
|
10301
10380
|
clearTimeout(timer);
|
|
10302
|
-
|
|
10381
|
+
resolve5(true);
|
|
10303
10382
|
return;
|
|
10304
10383
|
}
|
|
10305
10384
|
pending--;
|
|
10306
10385
|
if (pending === 0) {
|
|
10307
10386
|
settled = true;
|
|
10308
10387
|
clearTimeout(timer);
|
|
10309
|
-
|
|
10388
|
+
resolve5(false);
|
|
10310
10389
|
}
|
|
10311
10390
|
};
|
|
10312
10391
|
const timer = setTimeout(() => {
|
|
10313
10392
|
if (!settled) {
|
|
10314
10393
|
settled = true;
|
|
10315
|
-
|
|
10394
|
+
resolve5(false);
|
|
10316
10395
|
}
|
|
10317
10396
|
}, this.timeoutMs);
|
|
10318
10397
|
for (const hostname of this.hostnames) {
|
|
@@ -10453,7 +10532,7 @@ var init_auto_name_service = __esm(() => {
|
|
|
10453
10532
|
|
|
10454
10533
|
// backend/src/adapters/agent-runtime.ts
|
|
10455
10534
|
import { chmod as chmod2, mkdir as mkdir3 } from "fs/promises";
|
|
10456
|
-
import { dirname as
|
|
10535
|
+
import { dirname as dirname4, join as join8 } from "path";
|
|
10457
10536
|
function shellQuote(value) {
|
|
10458
10537
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
10459
10538
|
}
|
|
@@ -10720,7 +10799,7 @@ async function ensureAgentRuntimeArtifacts(input) {
|
|
|
10720
10799
|
agentCtlPath: join8(storagePaths.webmuxDir, "webmux-agentctl"),
|
|
10721
10800
|
claudeSettingsPath: join8(input.worktreePath, ".claude", "settings.local.json")
|
|
10722
10801
|
};
|
|
10723
|
-
await mkdir3(
|
|
10802
|
+
await mkdir3(dirname4(artifacts.claudeSettingsPath), { recursive: true });
|
|
10724
10803
|
await Bun.write(artifacts.agentCtlPath, buildAgentCtlScript());
|
|
10725
10804
|
await chmod2(artifacts.agentCtlPath, 493);
|
|
10726
10805
|
const hookSettings = buildClaudeHookSettings(artifacts);
|
|
@@ -10800,7 +10879,7 @@ function resolvePaneStartupCommand(template, commands) {
|
|
|
10800
10879
|
return template.command;
|
|
10801
10880
|
}
|
|
10802
10881
|
}
|
|
10803
|
-
function planSessionLayout(
|
|
10882
|
+
function planSessionLayout(projectRoot2, branch, templates, ctx) {
|
|
10804
10883
|
if (templates.length === 0) {
|
|
10805
10884
|
throw new Error("At least one pane template is required");
|
|
10806
10885
|
}
|
|
@@ -10821,7 +10900,7 @@ function planSessionLayout(projectRoot, branch, templates, ctx) {
|
|
|
10821
10900
|
});
|
|
10822
10901
|
const focusPaneIndex = panes.find((pane) => pane.focus)?.index ?? 0;
|
|
10823
10902
|
return {
|
|
10824
|
-
sessionName: buildProjectSessionName(
|
|
10903
|
+
sessionName: buildProjectSessionName(projectRoot2),
|
|
10825
10904
|
windowName: buildWorktreeWindowName(branch),
|
|
10826
10905
|
shellCommand: ctx.paneCommands.shell,
|
|
10827
10906
|
panes,
|
|
@@ -11018,7 +11097,7 @@ var init_worktree_service = __esm(() => {
|
|
|
11018
11097
|
// backend/src/services/lifecycle-service.ts
|
|
11019
11098
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
11020
11099
|
import { mkdir as mkdir4 } from "fs/promises";
|
|
11021
|
-
import { dirname as
|
|
11100
|
+
import { dirname as dirname5, resolve as resolve5 } from "path";
|
|
11022
11101
|
function generateBranchName() {
|
|
11023
11102
|
return `change-${randomUUID2().slice(0, 8)}`;
|
|
11024
11103
|
}
|
|
@@ -11051,7 +11130,7 @@ class LifecycleService {
|
|
|
11051
11130
|
agent,
|
|
11052
11131
|
phase: "creating_worktree"
|
|
11053
11132
|
});
|
|
11054
|
-
await mkdir4(
|
|
11133
|
+
await mkdir4(dirname5(worktreePath), { recursive: true });
|
|
11055
11134
|
initialized = await createManagedWorktree({
|
|
11056
11135
|
repoRoot: this.deps.projectRoot,
|
|
11057
11136
|
worktreePath,
|
|
@@ -11286,17 +11365,17 @@ class LifecycleService {
|
|
|
11286
11365
|
return allocateServicePorts(metas, this.deps.config.services);
|
|
11287
11366
|
}
|
|
11288
11367
|
resolveWorktreePath(branch) {
|
|
11289
|
-
return
|
|
11368
|
+
return resolve5(this.deps.projectRoot, this.deps.config.workspace.worktreeRoot, branch);
|
|
11290
11369
|
}
|
|
11291
11370
|
listLocalBranches() {
|
|
11292
|
-
return this.deps.git.listLocalBranches(
|
|
11371
|
+
return this.deps.git.listLocalBranches(resolve5(this.deps.projectRoot));
|
|
11293
11372
|
}
|
|
11294
11373
|
listCheckedOutBranches() {
|
|
11295
|
-
return new Set(this.deps.git.listWorktrees(
|
|
11374
|
+
return new Set(this.deps.git.listWorktrees(resolve5(this.deps.projectRoot)).filter((entry) => !entry.bare && entry.branch !== null).map((entry) => entry.branch));
|
|
11296
11375
|
}
|
|
11297
11376
|
listProjectWorktrees() {
|
|
11298
|
-
const
|
|
11299
|
-
return this.deps.git.listWorktrees(
|
|
11377
|
+
const projectRoot2 = resolve5(this.deps.projectRoot);
|
|
11378
|
+
return this.deps.git.listWorktrees(projectRoot2).filter((entry) => !entry.bare && resolve5(entry.path) !== projectRoot2);
|
|
11300
11379
|
}
|
|
11301
11380
|
async readManagedMetas() {
|
|
11302
11381
|
const metas = await Promise.all(this.listProjectWorktrees().map(async (entry) => {
|
|
@@ -11819,9 +11898,9 @@ var init_project_runtime = __esm(() => {
|
|
|
11819
11898
|
});
|
|
11820
11899
|
|
|
11821
11900
|
// backend/src/services/reconciliation-service.ts
|
|
11822
|
-
import { basename as basename4, resolve as
|
|
11901
|
+
import { basename as basename4, resolve as resolve6 } from "path";
|
|
11823
11902
|
function makeUnmanagedWorktreeId(path) {
|
|
11824
|
-
return `unmanaged:${
|
|
11903
|
+
return `unmanaged:${resolve6(path)}`;
|
|
11825
11904
|
}
|
|
11826
11905
|
function isValidPort2(port) {
|
|
11827
11906
|
return port !== null && Number.isInteger(port) && port >= 1 && port <= 65535;
|
|
@@ -11864,7 +11943,7 @@ class ReconciliationService {
|
|
|
11864
11943
|
this.deps = deps2;
|
|
11865
11944
|
}
|
|
11866
11945
|
async reconcile(repoRoot) {
|
|
11867
|
-
const normalizedRepoRoot =
|
|
11946
|
+
const normalizedRepoRoot = resolve6(repoRoot);
|
|
11868
11947
|
const worktrees = this.deps.git.listWorktrees(normalizedRepoRoot);
|
|
11869
11948
|
const sessionName = buildProjectSessionName(normalizedRepoRoot);
|
|
11870
11949
|
let windows = [];
|
|
@@ -11877,7 +11956,7 @@ class ReconciliationService {
|
|
|
11877
11956
|
for (const entry of worktrees) {
|
|
11878
11957
|
if (entry.bare)
|
|
11879
11958
|
continue;
|
|
11880
|
-
if (
|
|
11959
|
+
if (resolve6(entry.path) === normalizedRepoRoot)
|
|
11881
11960
|
continue;
|
|
11882
11961
|
const gitDir = this.deps.git.resolveWorktreeGitDir(entry.path);
|
|
11883
11962
|
const meta = await readWorktreeMeta(gitDir);
|
|
@@ -11961,8 +12040,8 @@ class WorktreeCreationTracker {
|
|
|
11961
12040
|
// backend/src/runtime.ts
|
|
11962
12041
|
function createWebmuxRuntime(options = {}) {
|
|
11963
12042
|
const port = options.port ?? parseInt(Bun.env.PORT || "5111", 10);
|
|
11964
|
-
const projectDir =
|
|
11965
|
-
const config = loadConfig(projectDir);
|
|
12043
|
+
const projectDir = projectRoot(options.projectDir ?? Bun.env.WEBMUX_PROJECT_DIR ?? process.cwd());
|
|
12044
|
+
const config = loadConfig(projectDir, { resolvedRoot: true });
|
|
11966
12045
|
const git = new BunGitGateway;
|
|
11967
12046
|
const portProbe = new BunPortProbe;
|
|
11968
12047
|
const tmux = new BunTmuxGateway;
|
|
@@ -12035,7 +12114,7 @@ __export(exports_worktree_commands, {
|
|
|
12035
12114
|
parseAddCommandArgs: () => parseAddCommandArgs,
|
|
12036
12115
|
getWorktreeCommandUsage: () => getWorktreeCommandUsage
|
|
12037
12116
|
});
|
|
12038
|
-
import { basename as basename5, resolve as
|
|
12117
|
+
import { basename as basename5, resolve as resolve7 } from "path";
|
|
12039
12118
|
function getWorktreeCommandUsage(command) {
|
|
12040
12119
|
switch (command) {
|
|
12041
12120
|
case "add":
|
|
@@ -12184,8 +12263,8 @@ function parsePruneCommandArgs(args) {
|
|
|
12184
12263
|
return true;
|
|
12185
12264
|
}
|
|
12186
12265
|
function listProjectWorktrees(runtime) {
|
|
12187
|
-
const projectDir =
|
|
12188
|
-
return runtime.git.listWorktrees(projectDir).filter((entry) => !entry.bare &&
|
|
12266
|
+
const projectDir = resolve7(runtime.projectDir);
|
|
12267
|
+
return runtime.git.listWorktrees(projectDir).filter((entry) => !entry.bare && resolve7(entry.path) !== projectDir);
|
|
12189
12268
|
}
|
|
12190
12269
|
async function defaultConfirmPrune(worktreeCount) {
|
|
12191
12270
|
const response = await Rt({
|
|
@@ -12195,7 +12274,7 @@ async function defaultConfirmPrune(worktreeCount) {
|
|
|
12195
12274
|
return !Ct(response) && response;
|
|
12196
12275
|
}
|
|
12197
12276
|
function defaultSwitchToTmuxWindow(projectDir, branch) {
|
|
12198
|
-
const sessionName = buildProjectSessionName(
|
|
12277
|
+
const sessionName = buildProjectSessionName(resolve7(projectDir));
|
|
12199
12278
|
const windowName = buildWorktreeWindowName(branch);
|
|
12200
12279
|
const target = `${sessionName}:${windowName}`;
|
|
12201
12280
|
const selectResult = Bun.spawnSync(["tmux", "select-window", "-t", target], {
|
|
@@ -12224,7 +12303,7 @@ function defaultSwitchToTmuxWindow(projectDir, branch) {
|
|
|
12224
12303
|
}
|
|
12225
12304
|
}
|
|
12226
12305
|
async function listWorktrees(runtime, stdout) {
|
|
12227
|
-
const projectDir =
|
|
12306
|
+
const projectDir = resolve7(runtime.projectDir);
|
|
12228
12307
|
const entries = listProjectWorktrees(runtime);
|
|
12229
12308
|
if (entries.length === 0) {
|
|
12230
12309
|
stdout("No worktrees found.");
|
|
@@ -12327,6 +12406,7 @@ async function runWorktreeCommand(context, deps2 = {}) {
|
|
|
12327
12406
|
case "open":
|
|
12328
12407
|
await runtime.lifecycleService.openWorktree(branch);
|
|
12329
12408
|
stdout(`Opened worktree ${branch}`);
|
|
12409
|
+
switchToTmuxWindow(runtime.projectDir, branch);
|
|
12330
12410
|
return 0;
|
|
12331
12411
|
case "close":
|
|
12332
12412
|
await runtime.lifecycleService.closeWorktree(branch);
|
|
@@ -12358,13 +12438,13 @@ var init_worktree_commands = __esm(() => {
|
|
|
12358
12438
|
});
|
|
12359
12439
|
|
|
12360
12440
|
// bin/src/webmux.ts
|
|
12361
|
-
import { resolve as
|
|
12441
|
+
import { resolve as resolve8, dirname as dirname6, join as join10 } from "path";
|
|
12362
12442
|
import { existsSync as existsSync5 } from "fs";
|
|
12363
12443
|
import { fileURLToPath } from "url";
|
|
12364
12444
|
// package.json
|
|
12365
12445
|
var package_default = {
|
|
12366
12446
|
name: "webmux",
|
|
12367
|
-
version: "0.
|
|
12447
|
+
version: "0.15.0",
|
|
12368
12448
|
description: "Web dashboard for workmux \u2014 browser UI with embedded terminals, PR monitoring, and CI integration",
|
|
12369
12449
|
type: "module",
|
|
12370
12450
|
repository: {
|
|
@@ -12418,7 +12498,7 @@ var package_default = {
|
|
|
12418
12498
|
};
|
|
12419
12499
|
|
|
12420
12500
|
// bin/src/webmux.ts
|
|
12421
|
-
var PKG_ROOT =
|
|
12501
|
+
var PKG_ROOT = resolve8(dirname6(fileURLToPath(import.meta.url)), "..");
|
|
12422
12502
|
function usage2() {
|
|
12423
12503
|
console.log(`
|
|
12424
12504
|
webmux \u2014 Dev dashboard for managing Git worktrees
|
|
@@ -12586,8 +12666,8 @@ async function main(args = process.argv.slice(2)) {
|
|
|
12586
12666
|
const code = await proc.exited;
|
|
12587
12667
|
process.exit(code);
|
|
12588
12668
|
}
|
|
12589
|
-
await loadEnvFile(
|
|
12590
|
-
await loadEnvFile(
|
|
12669
|
+
await loadEnvFile(resolve8(process.cwd(), ".env.local"));
|
|
12670
|
+
await loadEnvFile(resolve8(process.cwd(), ".env"));
|
|
12591
12671
|
if (isWorktreeCommand(parsed.command)) {
|
|
12592
12672
|
const { runWorktreeCommand: runWorktreeCommand2 } = await Promise.resolve().then(() => (init_worktree_commands(), exports_worktree_commands));
|
|
12593
12673
|
const exitCode = await runWorktreeCommand2({
|
|
@@ -12602,7 +12682,7 @@ async function main(args = process.argv.slice(2)) {
|
|
|
12602
12682
|
usage2();
|
|
12603
12683
|
process.exit(0);
|
|
12604
12684
|
}
|
|
12605
|
-
if (!existsSync5(
|
|
12685
|
+
if (!existsSync5(resolve8(process.cwd(), ".webmux.yaml"))) {
|
|
12606
12686
|
console.error("No .webmux.yaml found in this directory.\nRun `webmux init` to set up your project.");
|
|
12607
12687
|
process.exit(1);
|
|
12608
12688
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-sans:ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-surface:#0d1117;--color-sidebar:#161b22;--color-topbar:#1c2128;--color-hover:#21262d;--color-active:#1f6feb33;--color-edge:#30363d;--color-primary:#e6edf3;--color-muted:#8b949e;--color-accent:#58a6ff;--color-merged:#a78bfa;--color-danger:#f85149;--color-success:#3fb950;--color-warning:#d29922}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing) * 0)}.-top-0\.5{top:calc(var(--spacing) * -.5)}.top-2{top:calc(var(--spacing) * 2)}.-right-0\.5{right:calc(var(--spacing) * -.5)}.right-2{right:calc(var(--spacing) * 2)}.right-4{right:calc(var(--spacing) * 4)}.bottom-4{bottom:calc(var(--spacing) * 4)}.z-40{z-index:40}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing) * 0)}.-mt-2{margin-top:calc(var(--spacing) * -2)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mb-0\.5{margin-bottom:calc(var(--spacing) * .5)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.-ml-1{margin-left:calc(var(--spacing) * -1)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-3{margin-left:calc(var(--spacing) * 3)}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-2\.5{height:calc(var(--spacing) * 2.5)}.h-3{height:calc(var(--spacing) * 3)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-dvh{height:100dvh}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-64{max-height:calc(var(--spacing) * 64)}.max-h-\[300px\]{max-height:300px}.max-h-\[400px\]{max-height:400px}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-12{min-height:calc(var(--spacing) * 12)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-2{width:calc(var(--spacing) * 2)}.w-2\.5{width:calc(var(--spacing) * 2.5)}.w-3{width:calc(var(--spacing) * 3)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-8{width:calc(var(--spacing) * 8)}.w-\[90\%\]{width:90%}.w-\[220px\]{width:220px}.w-full{width:100%}.max-w-\[90\%\]{max-width:90%}.max-w-\[380px\]{max-width:380px}.max-w-\[560px\]{max-width:560px}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-\[220px\]{min-width:220px}.flex-1{flex:1}.shrink-0{flex-shrink:0}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-y{resize:vertical}.list-none{list-style-type:none}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-none{--tw-border-style:none;border-style:none}.border-accent{border-color:var(--color-accent)}.border-accent\/40{border-color:#58a6ff66}@supports (color:color-mix(in lab,red,red)){.border-accent\/40{border-color:color-mix(in oklab,var(--color-accent) 40%,transparent)}}.border-danger{border-color:var(--color-danger)}.border-danger\/35{border-color:#f8514959}@supports (color:color-mix(in lab,red,red)){.border-danger\/35{border-color:color-mix(in oklab,var(--color-danger) 35%,transparent)}}.border-danger\/40{border-color:#f8514966}@supports (color:color-mix(in lab,red,red)){.border-danger\/40{border-color:color-mix(in oklab,var(--color-danger) 40%,transparent)}}.border-edge{border-color:var(--color-edge)}.border-merged\/35{border-color:#a78bfa59}@supports (color:color-mix(in lab,red,red)){.border-merged\/35{border-color:color-mix(in oklab,var(--color-merged) 35%,transparent)}}.border-success\/30{border-color:#3fb9504d}@supports (color:color-mix(in lab,red,red)){.border-success\/30{border-color:color-mix(in oklab,var(--color-success) 30%,transparent)}}.border-success\/40{border-color:#3fb95066}@supports (color:color-mix(in lab,red,red)){.border-success\/40{border-color:color-mix(in oklab,var(--color-success) 40%,transparent)}}.border-transparent{border-color:#0000}.border-warning\/40{border-color:#d2992266}@supports (color:color-mix(in lab,red,red)){.border-warning\/40{border-color:color-mix(in oklab,var(--color-warning) 40%,transparent)}}.bg-accent{background-color:var(--color-accent)}.bg-accent\/10{background-color:#58a6ff1a}@supports (color:color-mix(in lab,red,red)){.bg-accent\/10{background-color:color-mix(in oklab,var(--color-accent) 10%,transparent)}}.bg-active{background-color:var(--color-active)}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black) 50%,transparent)}}.bg-danger{background-color:var(--color-danger)}.bg-danger\/5{background-color:#f851490d}@supports (color:color-mix(in lab,red,red)){.bg-danger\/5{background-color:color-mix(in oklab,var(--color-danger) 5%,transparent)}}.bg-danger\/15{background-color:#f8514926}@supports (color:color-mix(in lab,red,red)){.bg-danger\/15{background-color:color-mix(in oklab,var(--color-danger) 15%,transparent)}}.bg-danger\/20{background-color:#f8514933}@supports (color:color-mix(in lab,red,red)){.bg-danger\/20{background-color:color-mix(in oklab,var(--color-danger) 20%,transparent)}}.bg-hover{background-color:var(--color-hover)}.bg-merged\/8{background-color:#a78bfa14}@supports (color:color-mix(in lab,red,red)){.bg-merged\/8{background-color:color-mix(in oklab,var(--color-merged) 8%,transparent)}}.bg-merged\/20{background-color:#a78bfa33}@supports (color:color-mix(in lab,red,red)){.bg-merged\/20{background-color:color-mix(in oklab,var(--color-merged) 20%,transparent)}}.bg-muted{background-color:var(--color-muted)}.bg-muted\/20{background-color:#8b949e33}@supports (color:color-mix(in lab,red,red)){.bg-muted\/20{background-color:color-mix(in oklab,var(--color-muted) 20%,transparent)}}.bg-sidebar{background-color:var(--color-sidebar)}.bg-success{background-color:var(--color-success)}.bg-success\/5{background-color:#3fb9500d}@supports (color:color-mix(in lab,red,red)){.bg-success\/5{background-color:color-mix(in oklab,var(--color-success) 5%,transparent)}}.bg-success\/15{background-color:#3fb95026}@supports (color:color-mix(in lab,red,red)){.bg-success\/15{background-color:color-mix(in oklab,var(--color-success) 15%,transparent)}}.bg-success\/20{background-color:#3fb95033}@supports (color:color-mix(in lab,red,red)){.bg-success\/20{background-color:color-mix(in oklab,var(--color-success) 20%,transparent)}}.bg-surface{background-color:var(--color-surface)}.bg-surface\/60{background-color:#0d111799}@supports (color:color-mix(in lab,red,red)){.bg-surface\/60{background-color:color-mix(in oklab,var(--color-surface) 60%,transparent)}}.bg-topbar{background-color:var(--color-topbar)}.bg-transparent{background-color:#0000}.bg-warning{background-color:var(--color-warning)}.bg-warning\/5{background-color:#d299220d}@supports (color:color-mix(in lab,red,red)){.bg-warning\/5{background-color:color-mix(in oklab,var(--color-warning) 5%,transparent)}}.bg-warning\/15{background-color:#d2992226}@supports (color:color-mix(in lab,red,red)){.bg-warning\/15{background-color:color-mix(in oklab,var(--color-warning) 15%,transparent)}}.p-0{padding:calc(var(--spacing) * 0)}.p-1{padding:calc(var(--spacing) * 1)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-6{padding:calc(var(--spacing) * 6)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.pr-5{padding-right:calc(var(--spacing) * 5)}.pb-1{padding-bottom:calc(var(--spacing) * 1)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pl-3{padding-left:calc(var(--spacing) * 3)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[9px\]{font-size:9px}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[0\.08em\]{--tw-tracking:.08em;letter-spacing:.08em}.whitespace-pre-wrap{white-space:pre-wrap}.text-accent{color:var(--color-accent)}.text-accent\/60{color:#58a6ff99}@supports (color:color-mix(in lab,red,red)){.text-accent\/60{color:color-mix(in oklab,var(--color-accent) 60%,transparent)}}.text-accent\/80{color:#58a6ffcc}@supports (color:color-mix(in lab,red,red)){.text-accent\/80{color:color-mix(in oklab,var(--color-accent) 80%,transparent)}}.text-danger{color:var(--color-danger)}.text-inherit{color:inherit}.text-merged{color:var(--color-merged)}.text-muted{color:var(--color-muted)}.text-muted\/50{color:#8b949e80}@supports (color:color-mix(in lab,red,red)){.text-muted\/50{color:color-mix(in oklab,var(--color-muted) 50%,transparent)}}.text-primary{color:var(--color-primary)}.text-primary\/80{color:#e6edf3cc}@supports (color:color-mix(in lab,red,red)){.text-primary\/80{color:color-mix(in oklab,var(--color-primary) 80%,transparent)}}.text-success{color:var(--color-success)}.text-warning{color:var(--color-warning)}.text-white{color:var(--color-white)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.no-underline{text-decoration-line:none}.accent-\[var\(--accent\)\]{accent-color:var(--accent)}.accent-accent{accent-color:var(--color-accent)}.opacity-0{opacity:0}.opacity-40{opacity:.4}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}@media(hover:hover){.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.placeholder\:text-muted::placeholder{color:var(--color-muted)}.placeholder\:text-muted\/50::placeholder{color:#8b949e80}@supports (color:color-mix(in lab,red,red)){.placeholder\:text-muted\/50::placeholder{color:color-mix(in oklab,var(--color-muted) 50%,transparent)}}@media(hover:hover){.hover\:border-edge:hover{border-color:var(--color-edge)}.hover\:bg-accent\/10:hover{background-color:#58a6ff1a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/10:hover{background-color:color-mix(in oklab,var(--color-accent) 10%,transparent)}}.hover\:bg-danger\/10:hover{background-color:#f851491a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-danger\/10:hover{background-color:color-mix(in oklab,var(--color-danger) 10%,transparent)}}.hover\:bg-hover:hover{background-color:var(--color-hover)}.hover\:text-danger:hover{color:var(--color-danger)}.hover\:text-primary:hover{color:var(--color-primary)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-80:hover{opacity:.8}.hover\:opacity-90:hover{opacity:.9}}.focus\:border-accent:focus{border-color:var(--color-accent)}.focus-visible\:z-10:focus-visible{z-index:10}.focus-visible\:bg-hover:focus-visible{background-color:var(--color-hover)}.focus-visible\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\:ring-accent:focus-visible{--tw-ring-color:var(--color-accent)}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.focus-visible\:ring-inset:focus-visible{--tw-ring-inset:inset}.active\:bg-active:active{background-color:var(--color-active)}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}@media(min-width:48rem){.md\:max-w-\[440px\]{max-width:440px}}}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif}dialog[open]{margin:auto}dialog::backdrop{background:#0009}dialog textarea{font-family:inherit}dialog textarea:focus{border-color:var(--color-accent);outline:none}@keyframes spin{to{transform:rotate(360deg)}}.spinner{border:1.5px solid;border-top-color:#0000;border-radius:50%;width:12px;height:12px;animation:.6s linear infinite spin;display:inline-block}.xterm{width:100%;height:100%}.xterm .xterm-viewport{overscroll-behavior-y:contain}@media(max-width:768px){html,body{width:100%;height:100dvh;position:fixed;overflow:hidden}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@keyframes pulse{50%{opacity:.5}}.more-dropdown.svelte-gwjq7z{position:absolute;top:100%;right:0;margin-top:.25rem;width:max-content;max-width:80vw;border-radius:.5rem;border:1px solid var(--color-edge);background:var(--color-topbar);box-shadow:0 4px 12px #0006;z-index:50}.bell-dropdown.svelte-gwjq7z{position:absolute;top:100%;right:0;margin-top:.25rem;width:18rem;border-radius:.5rem;border:1px solid var(--color-edge);background:var(--color-topbar);box-shadow:0 4px 12px #0006;z-index:50}/**
|
|
2
|
+
* Copyright (c) 2014 The xterm.js authors. All rights reserved.
|
|
3
|
+
* Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
|
|
4
|
+
* https://github.com/chjj/term.js
|
|
5
|
+
* @license MIT
|
|
6
|
+
*
|
|
7
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
* in the Software without restriction, including without limitation the rights
|
|
10
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
* furnished to do so, subject to the following conditions:
|
|
13
|
+
*
|
|
14
|
+
* The above copyright notice and this permission notice shall be included in
|
|
15
|
+
* all copies or substantial portions of the Software.
|
|
16
|
+
*
|
|
17
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
23
|
+
* THE SOFTWARE.
|
|
24
|
+
*
|
|
25
|
+
* Originally forked from (with the author's permission):
|
|
26
|
+
* Fabrice Bellard's javascript vt100 for jslinux:
|
|
27
|
+
* http://bellard.org/jslinux/
|
|
28
|
+
* Copyright (c) 2011 Fabrice Bellard
|
|
29
|
+
* The original design remains. The terminal itself
|
|
30
|
+
* has been extended to include xterm CSI codes, among
|
|
31
|
+
* other features.
|
|
32
|
+
*/.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;right:0;left:0;top:0;bottom:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm .xterm-scroll-area{visibility:hidden}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;left:0;top:0;bottom:0;right:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{-webkit-user-select:text;user-select:text;white-space:pre}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.pane-bar.svelte-19vlwaa{padding-bottom:env(safe-area-inset-bottom,0px)}.pane-active.svelte-19vlwaa{box-shadow:inset 0 2px 0 0 var(--color-accent)}.toast.svelte-1974bvt{display:flex;align-items:flex-start;gap:.5rem;padding:.75rem;border-radius:.5rem;border:1px solid var(--color-edge);background:var(--color-topbar);box-shadow:0 4px 12px #0006;animation:svelte-1974bvt-slide-in .2s ease-out}@keyframes svelte-1974bvt-slide-in{0%{opacity:0;transform:translate(1rem)}to{opacity:1;transform:translate(0)}}
|