webmux 0.10.1 → 0.11.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/bin/webmux.js
CHANGED
|
@@ -1768,7 +1768,7 @@ Description=webmux dashboard \u2014 ${config.projectName}
|
|
|
1768
1768
|
|
|
1769
1769
|
[Service]
|
|
1770
1770
|
Type=simple
|
|
1771
|
-
ExecStart=${config.webmuxPath} --port ${config.port}
|
|
1771
|
+
ExecStart=${config.webmuxPath} serve --port ${config.port}
|
|
1772
1772
|
WorkingDirectory=${config.projectDir}
|
|
1773
1773
|
Restart=on-failure
|
|
1774
1774
|
RestartSec=5
|
|
@@ -1791,6 +1791,7 @@ function generateLaunchdPlist(config) {
|
|
|
1791
1791
|
<key>ProgramArguments</key>
|
|
1792
1792
|
<array>
|
|
1793
1793
|
<string>${config.webmuxPath}</string>
|
|
1794
|
+
<string>serve</string>
|
|
1794
1795
|
<string>--port</string>
|
|
1795
1796
|
<string>${config.port}</string>
|
|
1796
1797
|
</array>
|
|
@@ -9416,10 +9417,12 @@ function parseLifecycleHooks(raw) {
|
|
|
9416
9417
|
function parseAutoName(raw) {
|
|
9417
9418
|
if (!isRecord3(raw))
|
|
9418
9419
|
return null;
|
|
9419
|
-
|
|
9420
|
+
const provider = raw.provider;
|
|
9421
|
+
if (provider !== "claude" && provider !== "codex")
|
|
9420
9422
|
return null;
|
|
9421
9423
|
return {
|
|
9422
|
-
|
|
9424
|
+
provider,
|
|
9425
|
+
...typeof raw.model === "string" && raw.model.trim() ? { model: raw.model.trim() } : {},
|
|
9423
9426
|
...typeof raw.system_prompt === "string" && raw.system_prompt.trim() ? { systemPrompt: raw.system_prompt.trim() } : {}
|
|
9424
9427
|
};
|
|
9425
9428
|
}
|
|
@@ -10146,26 +10149,10 @@ class BunPortProbe {
|
|
|
10146
10149
|
}
|
|
10147
10150
|
|
|
10148
10151
|
// backend/src/services/auto-name-service.ts
|
|
10149
|
-
function isRecord4(value) {
|
|
10150
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10151
|
-
}
|
|
10152
10152
|
function buildPrompt(task) {
|
|
10153
10153
|
return `Task description:
|
|
10154
10154
|
${task.trim()}`;
|
|
10155
10155
|
}
|
|
10156
|
-
function parseBranchNamePayload(raw) {
|
|
10157
|
-
if (!isRecord4(raw) || typeof raw.branch_name !== "string") {
|
|
10158
|
-
throw new Error("Auto-name response did not include branch_name");
|
|
10159
|
-
}
|
|
10160
|
-
return raw.branch_name;
|
|
10161
|
-
}
|
|
10162
|
-
function parseJsonText(text) {
|
|
10163
|
-
try {
|
|
10164
|
-
return JSON.parse(text);
|
|
10165
|
-
} catch {
|
|
10166
|
-
throw new Error(`Auto-name response was not valid JSON: ${text}`);
|
|
10167
|
-
}
|
|
10168
|
-
}
|
|
10169
10156
|
function normalizeGeneratedBranchName(raw) {
|
|
10170
10157
|
let branch = raw.trim();
|
|
10171
10158
|
branch = branch.replace(/^```[\w-]*\s*/, "").replace(/\s*```$/, "");
|
|
@@ -10185,251 +10172,89 @@ function normalizeGeneratedBranchName(raw) {
|
|
|
10185
10172
|
}
|
|
10186
10173
|
return branch;
|
|
10187
10174
|
}
|
|
10188
|
-
function resolveAutoNameModel(modelSpec) {
|
|
10189
|
-
const trimmed = modelSpec.trim();
|
|
10190
|
-
const slashIndex = trimmed.indexOf("/");
|
|
10191
|
-
if (slashIndex > 0) {
|
|
10192
|
-
const provider = trimmed.slice(0, slashIndex);
|
|
10193
|
-
const model = trimmed.slice(slashIndex + 1).trim().replace(/^models\//, "");
|
|
10194
|
-
if (!model) {
|
|
10195
|
-
throw new Error(`Invalid auto_name model: ${modelSpec}`);
|
|
10196
|
-
}
|
|
10197
|
-
if (provider === "anthropic" || provider === "google" || provider === "openai") {
|
|
10198
|
-
return { provider, model };
|
|
10199
|
-
}
|
|
10200
|
-
if (provider === "gemini") {
|
|
10201
|
-
return { provider: "google", model };
|
|
10202
|
-
}
|
|
10203
|
-
}
|
|
10204
|
-
if (trimmed.startsWith("claude-")) {
|
|
10205
|
-
return { provider: "anthropic", model: trimmed };
|
|
10206
|
-
}
|
|
10207
|
-
if (trimmed.startsWith("gemini-") || trimmed.startsWith("models/gemini-")) {
|
|
10208
|
-
return { provider: "google", model: trimmed.replace(/^models\//, "") };
|
|
10209
|
-
}
|
|
10210
|
-
if (/^(gpt-|chatgpt-|o\d)/.test(trimmed)) {
|
|
10211
|
-
return { provider: "openai", model: trimmed };
|
|
10212
|
-
}
|
|
10213
|
-
throw new Error(`Unsupported auto_name model provider for ${modelSpec}. Use an anthropic/, gemini/, google/, or openai/ prefix, or a known model name.`);
|
|
10214
|
-
}
|
|
10215
10175
|
function getSystemPrompt(config) {
|
|
10216
10176
|
return config.systemPrompt?.trim() || DEFAULT_SYSTEM_PROMPT;
|
|
10217
10177
|
}
|
|
10218
|
-
function
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10222
|
-
|
|
10223
|
-
|
|
10224
|
-
|
|
10225
|
-
|
|
10226
|
-
|
|
10227
|
-
|
|
10228
|
-
return
|
|
10178
|
+
async function defaultSpawn(args) {
|
|
10179
|
+
const proc = Bun.spawn(args, {
|
|
10180
|
+
stdout: "pipe",
|
|
10181
|
+
stderr: "pipe"
|
|
10182
|
+
});
|
|
10183
|
+
const [stdout, stderr, exitCode] = await Promise.all([
|
|
10184
|
+
new Response(proc.stdout).text(),
|
|
10185
|
+
new Response(proc.stderr).text(),
|
|
10186
|
+
proc.exited
|
|
10187
|
+
]);
|
|
10188
|
+
return { exitCode, stdout, stderr };
|
|
10229
10189
|
}
|
|
10230
|
-
function
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
10236
|
-
|
|
10237
|
-
|
|
10238
|
-
|
|
10239
|
-
|
|
10240
|
-
|
|
10190
|
+
function buildClaudeArgs(model, systemPrompt, prompt) {
|
|
10191
|
+
const args = [
|
|
10192
|
+
"claude",
|
|
10193
|
+
"-p",
|
|
10194
|
+
"--system-prompt",
|
|
10195
|
+
systemPrompt,
|
|
10196
|
+
"--output-format",
|
|
10197
|
+
"text",
|
|
10198
|
+
"--no-session-persistence"
|
|
10199
|
+
];
|
|
10200
|
+
if (model) {
|
|
10201
|
+
args.push("--model", model);
|
|
10241
10202
|
}
|
|
10242
|
-
|
|
10203
|
+
args.push(prompt);
|
|
10204
|
+
return args;
|
|
10243
10205
|
}
|
|
10244
|
-
function
|
|
10245
|
-
|
|
10246
|
-
return null;
|
|
10247
|
-
if (typeof raw.output_text === "string" && raw.output_text.trim()) {
|
|
10248
|
-
return raw.output_text;
|
|
10249
|
-
}
|
|
10250
|
-
if (!Array.isArray(raw.output))
|
|
10251
|
-
return null;
|
|
10252
|
-
for (const item of raw.output) {
|
|
10253
|
-
if (!isRecord4(item) || !Array.isArray(item.content))
|
|
10254
|
-
continue;
|
|
10255
|
-
for (const content of item.content) {
|
|
10256
|
-
if (!isRecord4(content))
|
|
10257
|
-
continue;
|
|
10258
|
-
if (typeof content.text === "string" && content.text.trim()) {
|
|
10259
|
-
return content.text;
|
|
10260
|
-
}
|
|
10261
|
-
}
|
|
10262
|
-
}
|
|
10263
|
-
return null;
|
|
10206
|
+
function escapeTomlString(s) {
|
|
10207
|
+
return s.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n");
|
|
10264
10208
|
}
|
|
10265
|
-
|
|
10266
|
-
const
|
|
10267
|
-
|
|
10209
|
+
function buildCodexArgs(model, systemPrompt, prompt) {
|
|
10210
|
+
const args = [
|
|
10211
|
+
"codex",
|
|
10212
|
+
"-c",
|
|
10213
|
+
`developer_instructions="${escapeTomlString(systemPrompt)}"`,
|
|
10214
|
+
"exec",
|
|
10215
|
+
"--ephemeral"
|
|
10216
|
+
];
|
|
10217
|
+
if (model) {
|
|
10218
|
+
args.push("-m", model);
|
|
10219
|
+
}
|
|
10220
|
+
args.push(prompt);
|
|
10221
|
+
return args;
|
|
10268
10222
|
}
|
|
10269
10223
|
|
|
10270
10224
|
class AutoNameService {
|
|
10271
|
-
|
|
10272
|
-
anthropicApiKey;
|
|
10273
|
-
geminiApiKey;
|
|
10274
|
-
openaiApiKey;
|
|
10225
|
+
spawnImpl;
|
|
10275
10226
|
constructor(deps2 = {}) {
|
|
10276
|
-
this.
|
|
10277
|
-
this.anthropicApiKey = deps2.anthropicApiKey ?? Bun.env.ANTHROPIC_API_KEY;
|
|
10278
|
-
this.geminiApiKey = deps2.geminiApiKey ?? Bun.env.GEMINI_API_KEY;
|
|
10279
|
-
this.openaiApiKey = deps2.openaiApiKey ?? Bun.env.OPENAI_API_KEY;
|
|
10227
|
+
this.spawnImpl = deps2.spawnImpl ?? defaultSpawn;
|
|
10280
10228
|
}
|
|
10281
10229
|
async generateBranchName(config, task) {
|
|
10282
10230
|
const prompt = task.trim();
|
|
10283
10231
|
if (!prompt) {
|
|
10284
10232
|
throw new Error("Auto-name requires a prompt");
|
|
10285
10233
|
}
|
|
10286
|
-
const
|
|
10287
|
-
const
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
|
|
10292
|
-
|
|
10293
|
-
}
|
|
10294
|
-
|
|
10295
|
-
method: "POST",
|
|
10296
|
-
headers: {
|
|
10297
|
-
"content-type": "application/json",
|
|
10298
|
-
"x-api-key": this.anthropicApiKey,
|
|
10299
|
-
"anthropic-version": "2023-06-01"
|
|
10300
|
-
},
|
|
10301
|
-
body: JSON.stringify({
|
|
10302
|
-
model,
|
|
10303
|
-
system: systemPrompt,
|
|
10304
|
-
max_tokens: 64,
|
|
10305
|
-
messages: [{ role: "user", content: buildPrompt(task) }],
|
|
10306
|
-
output_config: {
|
|
10307
|
-
format: {
|
|
10308
|
-
type: "json_schema",
|
|
10309
|
-
schema: BRANCH_NAME_SCHEMA
|
|
10310
|
-
}
|
|
10311
|
-
}
|
|
10312
|
-
})
|
|
10313
|
-
});
|
|
10314
|
-
if (!response.ok) {
|
|
10315
|
-
throw new Error(`Anthropic auto-name request failed: ${await readErrorBody(response)}`);
|
|
10316
|
-
}
|
|
10317
|
-
const json = await response.json();
|
|
10318
|
-
if (isRecord4(json) && json.stop_reason === "refusal") {
|
|
10319
|
-
throw new Error("Anthropic auto-name request was refused");
|
|
10320
|
-
}
|
|
10321
|
-
if (isRecord4(json) && json.stop_reason === "max_tokens") {
|
|
10322
|
-
throw new Error("Anthropic auto-name response hit max_tokens before completing");
|
|
10323
|
-
}
|
|
10324
|
-
const text = extractAnthropicText(json);
|
|
10325
|
-
if (!text) {
|
|
10326
|
-
throw new Error("Anthropic auto-name response did not include text");
|
|
10327
|
-
}
|
|
10328
|
-
return parseBranchNamePayload(parseJsonText(text));
|
|
10329
|
-
}
|
|
10330
|
-
async generateWithGoogle(model, systemPrompt, task) {
|
|
10331
|
-
if (!this.geminiApiKey) {
|
|
10332
|
-
throw new Error("GEMINI_API_KEY is required for auto_name with Gemini models");
|
|
10333
|
-
}
|
|
10334
|
-
const response = await this.fetchImpl(`https://generativelanguage.googleapis.com/v1beta/models/${encodeURIComponent(model)}:generateContent`, {
|
|
10335
|
-
method: "POST",
|
|
10336
|
-
headers: {
|
|
10337
|
-
"content-type": "application/json",
|
|
10338
|
-
"x-goog-api-key": this.geminiApiKey
|
|
10339
|
-
},
|
|
10340
|
-
body: JSON.stringify({
|
|
10341
|
-
systemInstruction: {
|
|
10342
|
-
parts: [{ text: systemPrompt }]
|
|
10343
|
-
},
|
|
10344
|
-
contents: [
|
|
10345
|
-
{
|
|
10346
|
-
role: "user",
|
|
10347
|
-
parts: [{ text: buildPrompt(task) }]
|
|
10348
|
-
}
|
|
10349
|
-
],
|
|
10350
|
-
generationConfig: {
|
|
10351
|
-
responseMimeType: "application/json",
|
|
10352
|
-
responseJsonSchema: GEMINI_BRANCH_NAME_SCHEMA
|
|
10353
|
-
}
|
|
10354
|
-
})
|
|
10355
|
-
});
|
|
10356
|
-
if (!response.ok) {
|
|
10357
|
-
throw new Error(`Google auto-name request failed: ${await readErrorBody(response)}`);
|
|
10358
|
-
}
|
|
10359
|
-
const json = await response.json();
|
|
10360
|
-
const text = extractGoogleText(json);
|
|
10361
|
-
if (!text) {
|
|
10362
|
-
throw new Error("Google auto-name response did not include text");
|
|
10363
|
-
}
|
|
10364
|
-
return parseBranchNamePayload(parseJsonText(text));
|
|
10365
|
-
}
|
|
10366
|
-
async generateWithOpenAI(model, systemPrompt, task) {
|
|
10367
|
-
if (!this.openaiApiKey) {
|
|
10368
|
-
throw new Error("OPENAI_API_KEY is required for auto_name with OpenAI models");
|
|
10369
|
-
}
|
|
10370
|
-
const response = await this.fetchImpl("https://api.openai.com/v1/responses", {
|
|
10371
|
-
method: "POST",
|
|
10372
|
-
headers: {
|
|
10373
|
-
"content-type": "application/json",
|
|
10374
|
-
authorization: `Bearer ${this.openaiApiKey}`
|
|
10375
|
-
},
|
|
10376
|
-
body: JSON.stringify({
|
|
10377
|
-
model,
|
|
10378
|
-
input: [
|
|
10379
|
-
{ role: "system", content: systemPrompt },
|
|
10380
|
-
{ role: "user", content: buildPrompt(task) }
|
|
10381
|
-
],
|
|
10382
|
-
max_output_tokens: 64,
|
|
10383
|
-
text: {
|
|
10384
|
-
format: {
|
|
10385
|
-
type: "json_schema",
|
|
10386
|
-
name: "branch_name_response",
|
|
10387
|
-
strict: true,
|
|
10388
|
-
schema: BRANCH_NAME_SCHEMA
|
|
10389
|
-
}
|
|
10390
|
-
}
|
|
10391
|
-
})
|
|
10392
|
-
});
|
|
10393
|
-
if (!response.ok) {
|
|
10394
|
-
throw new Error(`OpenAI auto-name request failed: ${await readErrorBody(response)}`);
|
|
10234
|
+
const systemPrompt = getSystemPrompt(config);
|
|
10235
|
+
const userPrompt = buildPrompt(prompt);
|
|
10236
|
+
const args = config.provider === "claude" ? buildClaudeArgs(config.model, systemPrompt, userPrompt) : buildCodexArgs(config.model, systemPrompt, userPrompt);
|
|
10237
|
+
const cli = config.provider === "claude" ? "claude" : "codex";
|
|
10238
|
+
let result;
|
|
10239
|
+
try {
|
|
10240
|
+
result = await this.spawnImpl(args);
|
|
10241
|
+
} catch {
|
|
10242
|
+
throw new Error(`'${cli}' CLI not found. Install it or check your PATH.`);
|
|
10395
10243
|
}
|
|
10396
|
-
|
|
10397
|
-
|
|
10398
|
-
|
|
10399
|
-
if (!isRecord4(item) || !Array.isArray(item.content))
|
|
10400
|
-
continue;
|
|
10401
|
-
for (const content of item.content) {
|
|
10402
|
-
if (isRecord4(content) && content.type === "refusal" && typeof content.refusal === "string") {
|
|
10403
|
-
throw new Error(`OpenAI auto-name request was refused: ${content.refusal}`);
|
|
10404
|
-
}
|
|
10405
|
-
}
|
|
10406
|
-
}
|
|
10244
|
+
if (result.exitCode !== 0) {
|
|
10245
|
+
const detail = result.stderr.trim() || `exit ${result.exitCode}`;
|
|
10246
|
+
throw new Error(`${cli} failed: ${detail}`);
|
|
10407
10247
|
}
|
|
10408
|
-
const
|
|
10409
|
-
if (!
|
|
10410
|
-
throw new Error(
|
|
10248
|
+
const output = result.stdout.trim();
|
|
10249
|
+
if (!output) {
|
|
10250
|
+
throw new Error(`${cli} returned empty output`);
|
|
10411
10251
|
}
|
|
10412
|
-
return
|
|
10252
|
+
return normalizeGeneratedBranchName(output);
|
|
10413
10253
|
}
|
|
10414
10254
|
}
|
|
10415
|
-
var
|
|
10255
|
+
var DEFAULT_SYSTEM_PROMPT;
|
|
10416
10256
|
var init_auto_name_service = __esm(() => {
|
|
10417
10257
|
init_policies();
|
|
10418
|
-
BRANCH_NAME_SCHEMA = {
|
|
10419
|
-
type: "object",
|
|
10420
|
-
properties: {
|
|
10421
|
-
branch_name: {
|
|
10422
|
-
type: "string",
|
|
10423
|
-
description: "A lowercase kebab-case git branch name with no prefix"
|
|
10424
|
-
}
|
|
10425
|
-
},
|
|
10426
|
-
required: ["branch_name"],
|
|
10427
|
-
additionalProperties: false
|
|
10428
|
-
};
|
|
10429
|
-
GEMINI_BRANCH_NAME_SCHEMA = {
|
|
10430
|
-
...BRANCH_NAME_SCHEMA,
|
|
10431
|
-
propertyOrdering: ["branch_name"]
|
|
10432
|
-
};
|
|
10433
10258
|
DEFAULT_SYSTEM_PROMPT = [
|
|
10434
10259
|
"Generate a concise git branch name from the task description.",
|
|
10435
10260
|
"Return only the branch name.",
|
|
@@ -10444,7 +10269,7 @@ import { dirname as dirname2, join as join8 } from "path";
|
|
|
10444
10269
|
function shellQuote(value) {
|
|
10445
10270
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
10446
10271
|
}
|
|
10447
|
-
function
|
|
10272
|
+
function isRecord4(value) {
|
|
10448
10273
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
10449
10274
|
}
|
|
10450
10275
|
function buildAgentCtlScript() {
|
|
@@ -10712,7 +10537,7 @@ async function ensureAgentRuntimeArtifacts(input) {
|
|
|
10712
10537
|
await chmod2(artifacts.agentCtlPath, 493);
|
|
10713
10538
|
const hookSettings = buildClaudeHookSettings(artifacts);
|
|
10714
10539
|
const hooks = hookSettings.hooks;
|
|
10715
|
-
if (!
|
|
10540
|
+
if (!isRecord4(hooks)) {
|
|
10716
10541
|
throw new Error("Invalid Claude hook settings");
|
|
10717
10542
|
}
|
|
10718
10543
|
await mergeClaudeSettings(artifacts.claudeSettingsPath, hooks);
|
|
@@ -12146,25 +11971,28 @@ function usage2() {
|
|
|
12146
11971
|
webmux \u2014 Dev dashboard for managing Git worktrees
|
|
12147
11972
|
|
|
12148
11973
|
Usage:
|
|
12149
|
-
webmux
|
|
11974
|
+
webmux serve Start the dashboard server
|
|
12150
11975
|
webmux init Interactive project setup
|
|
12151
11976
|
webmux service Manage webmux as a system service
|
|
11977
|
+
webmux update Update webmux to the latest version
|
|
12152
11978
|
webmux add Create a worktree using the dashboard lifecycle
|
|
12153
11979
|
webmux list List worktrees and their status
|
|
12154
11980
|
webmux open Open an existing worktree session
|
|
12155
11981
|
webmux close Close a worktree session without removing it
|
|
12156
11982
|
webmux remove Remove a worktree
|
|
12157
11983
|
webmux merge Merge a worktree into the main branch and remove it
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
11984
|
+
|
|
11985
|
+
Options:
|
|
11986
|
+
--port N Set port (default: 5111)
|
|
11987
|
+
--debug Show debug-level logs
|
|
11988
|
+
--help Show this help message
|
|
12161
11989
|
|
|
12162
11990
|
Environment:
|
|
12163
11991
|
BACKEND_PORT Same as --port (flag takes precedence)
|
|
12164
11992
|
`);
|
|
12165
11993
|
}
|
|
12166
11994
|
function isRootCommand(value) {
|
|
12167
|
-
return value === "init" || value === "service" || value === "add" || value === "list" || value === "open" || value === "close" || value === "remove" || value === "merge";
|
|
11995
|
+
return value === "serve" || value === "init" || value === "service" || value === "update" || value === "add" || value === "list" || value === "open" || value === "close" || value === "remove" || value === "merge";
|
|
12168
11996
|
}
|
|
12169
11997
|
function parseRootArgs(args) {
|
|
12170
11998
|
let port = parseInt(process.env.BACKEND_PORT || "5111", 10);
|
|
@@ -12234,6 +12062,16 @@ if (parsed.command === "service") {
|
|
|
12234
12062
|
await service2(parsed.commandArgs);
|
|
12235
12063
|
process.exit(0);
|
|
12236
12064
|
}
|
|
12065
|
+
if (parsed.command === "update") {
|
|
12066
|
+
console.log("Updating webmux to the latest version...");
|
|
12067
|
+
const proc = Bun.spawn(["bun", "install", "--global", "webmux@latest"], {
|
|
12068
|
+
stdin: "inherit",
|
|
12069
|
+
stdout: "inherit",
|
|
12070
|
+
stderr: "inherit"
|
|
12071
|
+
});
|
|
12072
|
+
const code = await proc.exited;
|
|
12073
|
+
process.exit(code);
|
|
12074
|
+
}
|
|
12237
12075
|
async function loadEnvFile(path) {
|
|
12238
12076
|
if (!existsSync5(path))
|
|
12239
12077
|
return;
|
|
@@ -12265,6 +12103,10 @@ if (isWorktreeCommand(parsed.command)) {
|
|
|
12265
12103
|
});
|
|
12266
12104
|
process.exit(exitCode);
|
|
12267
12105
|
}
|
|
12106
|
+
if (parsed.command === null) {
|
|
12107
|
+
usage2();
|
|
12108
|
+
process.exit(0);
|
|
12109
|
+
}
|
|
12268
12110
|
if (!existsSync5(resolve6(process.cwd(), ".webmux.yaml"))) {
|
|
12269
12111
|
console.error("No .webmux.yaml found in this directory.\nRun `webmux init` to set up your project.");
|
|
12270
12112
|
process.exit(1);
|