@kw-yeh/vibeflow 4.11.16 → 4.11.18
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/dist/vibeflow.mjs +219 -67
- package/dist/web/404/index.html +1 -1
- package/dist/web/404.html +1 -1
- package/dist/web/_next/static/chunks/pages/{_app-0c60752b4c05d52e.js → _app-2571a2564f593899.js} +1 -1
- package/dist/web/_next/static/chunks/pages/home-5e349dff04afe2eb.js +13 -0
- package/dist/web/_next/static/{TTJDd4vO-NmQBjEis26sl → wiyRNf4HeW4AW-LhhYSsf}/_buildManifest.js +1 -1
- package/dist/web/home/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/_next/static/chunks/pages/home-a17a5a665f0aa6bd.js +0 -13
- /package/dist/web/_next/static/{TTJDd4vO-NmQBjEis26sl → wiyRNf4HeW4AW-LhhYSsf}/_ssgManifest.js +0 -0
package/dist/vibeflow.mjs
CHANGED
|
@@ -1090,9 +1090,9 @@ var init_progress = __esm({
|
|
|
1090
1090
|
|
|
1091
1091
|
// packages/tui/src/task-form.ts
|
|
1092
1092
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
1093
|
-
import
|
|
1093
|
+
import fs25 from "fs";
|
|
1094
1094
|
import os8 from "os";
|
|
1095
|
-
import
|
|
1095
|
+
import path29 from "path";
|
|
1096
1096
|
import React, { useEffect, useRef, useState } from "react";
|
|
1097
1097
|
import { Box, Text, render as render2, useApp, useInput } from "ink";
|
|
1098
1098
|
function newFormState(defaultAutoMode, agents) {
|
|
@@ -1218,17 +1218,17 @@ function editorCommand(env, platform) {
|
|
|
1218
1218
|
return env.VISUAL?.trim() || env.EDITOR?.trim() || (platform === "win32" ? "notepad" : "vi");
|
|
1219
1219
|
}
|
|
1220
1220
|
function editInEditor(text) {
|
|
1221
|
-
const dir =
|
|
1222
|
-
const file =
|
|
1221
|
+
const dir = fs25.mkdtempSync(path29.join(os8.tmpdir(), "vibeflow-"));
|
|
1222
|
+
const file = path29.join(dir, "description.md");
|
|
1223
1223
|
try {
|
|
1224
|
-
|
|
1224
|
+
fs25.writeFileSync(file, text);
|
|
1225
1225
|
const cmd = editorCommand(process.env, process.platform);
|
|
1226
1226
|
const r = spawnSync2(`${cmd} "${file}"`, { stdio: "inherit", shell: true });
|
|
1227
1227
|
if (r.error) return { error: `\u7121\u6CD5\u555F\u52D5\u7DE8\u8F2F\u5668\uFF08${cmd}\uFF09\uFF1A${r.error.message}` };
|
|
1228
1228
|
if (r.status !== 0) return { error: `\u7DE8\u8F2F\u5668\uFF08${cmd}\uFF09\u7D50\u675F\u78BC ${r.status}\uFF0C\u63CF\u8FF0\u672A\u8B8A\u66F4` };
|
|
1229
|
-
return { text:
|
|
1229
|
+
return { text: fs25.readFileSync(file, "utf8").replace(/\r?\n$/, "") };
|
|
1230
1230
|
} finally {
|
|
1231
|
-
|
|
1231
|
+
fs25.rmSync(dir, { recursive: true, force: true });
|
|
1232
1232
|
}
|
|
1233
1233
|
}
|
|
1234
1234
|
function cycle(list, current, step) {
|
|
@@ -1299,10 +1299,10 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
1299
1299
|
if (editing === "title") setS((prev) => ({ ...prev, title: draft }));
|
|
1300
1300
|
else if (editing === "branch") setS((prev) => ({ ...prev, branch: value2 }));
|
|
1301
1301
|
else if (editing === "project") {
|
|
1302
|
-
if (value2) setProject(
|
|
1302
|
+
if (value2) setProject(path29.resolve(value2.replace(/^~(?=$|\/)/, os8.homedir())));
|
|
1303
1303
|
} else if (editing === "attachments" && value2) {
|
|
1304
|
-
const file =
|
|
1305
|
-
if (!
|
|
1304
|
+
const file = path29.resolve(value2.replace(/^~(?=$|\/)/, os8.homedir()));
|
|
1305
|
+
if (!fs25.existsSync(file) || !fs25.statSync(file).isFile()) {
|
|
1306
1306
|
setMessage(`\u627E\u4E0D\u5230\u6A94\u6848\uFF1A${file}`);
|
|
1307
1307
|
return;
|
|
1308
1308
|
}
|
|
@@ -1385,7 +1385,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
1385
1385
|
case "branch":
|
|
1386
1386
|
return s.branch || "\uFF08\u7559\u7A7A\u5247\u81EA\u52D5\u547D\u540D\uFF0C\u4F8B\u5982 feature/login-fix\uFF09";
|
|
1387
1387
|
case "attachments":
|
|
1388
|
-
return s.attachments.length ? s.attachments.map((a) =>
|
|
1388
|
+
return s.attachments.length ? s.attachments.map((a) => path29.basename(a)).join("\u3001") : "\uFF08Enter \u8F38\u5165\u6A94\u6848\u8DEF\u5F91\u52A0\u5165\uFF09";
|
|
1389
1389
|
case "description": {
|
|
1390
1390
|
if (!s.description) return "\uFF08Enter \u7528\u7DE8\u8F2F\u5668\u64B0\u5BEB\uFF09";
|
|
1391
1391
|
const lines = s.description.split("\n");
|
|
@@ -1420,7 +1420,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
1420
1420
|
if (info && !info.isRepo) return "\u9019\u500B\u8CC7\u6599\u593E\u4E0D\u662F Git repository\u3002\u8ACB\u6539\u9078\u4E00\u500B Git \u5C08\u6848\uFF0C\u6216\u5728\u4E0B\u65B9\u521D\u59CB\u5316\u3002";
|
|
1421
1421
|
if (s.mode === "edit" && projectChanged(s)) return "\u5206\u652F\u6703\u5728\u65B0\u5C08\u6848\u3001\u5361\u7247\u958B\u59CB\u57F7\u884C\u6642\u624D\u5EFA\u7ACB\u3002";
|
|
1422
1422
|
if (info?.isRepo && !info.hasRemote) return `\u6B64 repository \u6C92\u6709 remote\uFF0C\u5C07\u4EE5\u76EE\u524D\u5206\u652F (${info.currentBranch ?? "HEAD"}) \u70BA\u57FA\u6E96\u5EFA\u7ACB\u672C\u5730 worktree\u3002`;
|
|
1423
|
-
if (info?.isRepo && s.projectPath) return `worktree \u6703\u5EFA\u5728 ${ctx.workstationPath || "~/Desktop"}/${
|
|
1423
|
+
if (info?.isRepo && s.projectPath) return `worktree \u6703\u5EFA\u5728 ${ctx.workstationPath || "~/Desktop"}/${path29.basename(s.projectPath)}`;
|
|
1424
1424
|
}
|
|
1425
1425
|
if (field === "branch") {
|
|
1426
1426
|
const when = info?.hasRemote ? "\u958B\u59CB\u57F7\u884C\u6642\u6703\u5EFA\u7ACB\u540C\u540D\u5206\u652F\u4E26\u63A8\u5230 origin\uFF1B\u82E5 remote \u5DF2\u6709\u9019\u500B\u5206\u652F\uFF0C\u5247\u76F4\u63A5\u53D6\u56DE\u4E26\u63A5\u7E8C\u4E0A\u9762\u7684\u5DE5\u4F5C\u3002" : "\u958B\u59CB\u57F7\u884C\u6642\u6703\u5EFA\u7ACB\u540C\u540D\u5206\u652F\u3002";
|
|
@@ -1549,7 +1549,7 @@ __export(src_exports, {
|
|
|
1549
1549
|
showDiff: () => showDiff
|
|
1550
1550
|
});
|
|
1551
1551
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
1552
|
-
import
|
|
1552
|
+
import path30 from "path";
|
|
1553
1553
|
import React2, { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1554
1554
|
import { Box as Box2, Text as Text2, render as render3, useApp as useApp2, useInput as useInput2, useStdout } from "ink";
|
|
1555
1555
|
function findDetachKey(text) {
|
|
@@ -1845,7 +1845,7 @@ function showDiff(task) {
|
|
|
1845
1845
|
});
|
|
1846
1846
|
}
|
|
1847
1847
|
function tmuxAttach(opts, sessionName) {
|
|
1848
|
-
const conf =
|
|
1848
|
+
const conf = path30.join(opts.userDataDir, "tmux.conf");
|
|
1849
1849
|
const inOurServer = (process.env.TMUX ?? "").split(",")[0].endsWith(`/${TMUX_SOCKET}`);
|
|
1850
1850
|
const args = inOurServer ? ["-L", TMUX_SOCKET, "-f", conf, "switch-client", "-t", `=${sessionName}`] : ["-L", TMUX_SOCKET, "-f", conf, "attach-session", "-t", `=${sessionName}`];
|
|
1851
1851
|
spawnSync3("tmux", args, { stdio: "inherit", env: { ...process.env, TMUX: inOurServer ? process.env.TMUX : "" } });
|
|
@@ -1976,10 +1976,11 @@ var init_src = __esm({
|
|
|
1976
1976
|
});
|
|
1977
1977
|
|
|
1978
1978
|
// packages/cli/src/main.ts
|
|
1979
|
-
import
|
|
1980
|
-
import
|
|
1979
|
+
import fs26 from "fs";
|
|
1980
|
+
import path31 from "path";
|
|
1981
1981
|
import { fileURLToPath } from "url";
|
|
1982
1982
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
1983
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
1983
1984
|
|
|
1984
1985
|
// packages/core/src/lock.ts
|
|
1985
1986
|
import fs from "fs";
|
|
@@ -2457,6 +2458,7 @@ function createBridge(t) {
|
|
|
2457
2458
|
/** Running app version (package.json version baked into the build). */
|
|
2458
2459
|
getVersion: () => t.invoke("app:getVersion"),
|
|
2459
2460
|
getUpdateStatus: () => t.invoke("host:updateStatus"),
|
|
2461
|
+
checkForUpdate: () => t.invoke("host:checkUpdate"),
|
|
2460
2462
|
openUpdateTerminal: () => t.invoke("host:openUpdateTerminal"),
|
|
2461
2463
|
onUpdateAvailable: (callback) => t.on("update:available", (payload) => callback(payload)),
|
|
2462
2464
|
/**
|
|
@@ -4692,8 +4694,8 @@ async function taskCommand(argv) {
|
|
|
4692
4694
|
}
|
|
4693
4695
|
|
|
4694
4696
|
// packages/cli/src/host.ts
|
|
4695
|
-
import
|
|
4696
|
-
import
|
|
4697
|
+
import fs23 from "fs";
|
|
4698
|
+
import path27 from "path";
|
|
4697
4699
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
4698
4700
|
|
|
4699
4701
|
// packages/core/src/events.ts
|
|
@@ -7916,7 +7918,7 @@ function runUpdate(options) {
|
|
|
7916
7918
|
error(`\u66F4\u65B0\u5931\u6557\uFF1A${result.error?.message ?? `npm \u7D50\u675F\u78BC ${result.status ?? "unknown"}`}`);
|
|
7917
7919
|
return result.status && result.status > 0 ? result.status : 1;
|
|
7918
7920
|
}
|
|
7919
|
-
log("\u66F4\u65B0\u5B8C\u6210\u3002\
|
|
7921
|
+
log("\u66F4\u65B0\u5B8C\u6210\u3002\u57F7\u884C\u4E2D\u7684 Web UI host \u6703\u5728\u6578\u79D2\u5167\u81EA\u52D5\u91CD\u65B0\u555F\u52D5\u6210\u65B0\u7248\u672C\uFF1BTUI host \u6216\u6709\u57F7\u884C\u4E2D session \u7684 pty host \u8ACB\u81EA\u884C\u91CD\u65B0\u555F\u52D5\u3002");
|
|
7920
7922
|
return 0;
|
|
7921
7923
|
}
|
|
7922
7924
|
|
|
@@ -7953,6 +7955,39 @@ async function checkForUpdate(packageName2, currentVersion, query = async (name)
|
|
|
7953
7955
|
if (typeof latest !== "string" || !isNewerVersion(latest, currentVersion)) return null;
|
|
7954
7956
|
return { currentVersion, latestVersion: latest };
|
|
7955
7957
|
}
|
|
7958
|
+
function createUpdateMonitor(options) {
|
|
7959
|
+
const check = options.check ?? ((name, version) => checkForUpdate(name, version));
|
|
7960
|
+
let available = null;
|
|
7961
|
+
let stopped = false;
|
|
7962
|
+
return {
|
|
7963
|
+
supported: options.packageName !== null,
|
|
7964
|
+
status: () => available,
|
|
7965
|
+
/** Rejects when the registry cannot be reached; the last answer is kept. */
|
|
7966
|
+
async refresh() {
|
|
7967
|
+
if (!options.packageName) return { status: "unsupported", currentVersion: options.currentVersion };
|
|
7968
|
+
const next = await check(options.packageName, options.currentVersion);
|
|
7969
|
+
if (!stopped && next?.latestVersion !== available?.latestVersion) {
|
|
7970
|
+
available = next;
|
|
7971
|
+
options.onChange(next);
|
|
7972
|
+
}
|
|
7973
|
+
return next ? { status: "available", ...next } : { status: "current", currentVersion: options.currentVersion };
|
|
7974
|
+
},
|
|
7975
|
+
/** A newer version is on disk but the host must be restarted by hand to run it. */
|
|
7976
|
+
markInstalled(version, reason) {
|
|
7977
|
+
if (stopped || available?.installedVersion === version && available.restartBlocked === reason) return;
|
|
7978
|
+
available = {
|
|
7979
|
+
currentVersion: options.currentVersion,
|
|
7980
|
+
latestVersion: available && isNewerVersion(available.latestVersion, version) ? available.latestVersion : version,
|
|
7981
|
+
installedVersion: version,
|
|
7982
|
+
restartBlocked: reason
|
|
7983
|
+
};
|
|
7984
|
+
options.onChange(available);
|
|
7985
|
+
},
|
|
7986
|
+
stop() {
|
|
7987
|
+
stopped = true;
|
|
7988
|
+
}
|
|
7989
|
+
};
|
|
7990
|
+
}
|
|
7956
7991
|
|
|
7957
7992
|
// packages/cli/src/update-terminal.ts
|
|
7958
7993
|
import { spawn as spawn8 } from "node:child_process";
|
|
@@ -8014,6 +8049,70 @@ async function openUpdateTerminal(platform = process.platform, run3 = launch) {
|
|
|
8014
8049
|
throw new Error("\u627E\u4E0D\u5230\u53EF\u7528\u7684\u7D42\u7AEF\u6A5F\uFF0C\u8ACB\u624B\u52D5\u57F7\u884C\u66F4\u65B0\u6307\u4EE4\u3002");
|
|
8015
8050
|
}
|
|
8016
8051
|
|
|
8052
|
+
// packages/cli/src/self-update.ts
|
|
8053
|
+
import fs22 from "node:fs";
|
|
8054
|
+
import path26 from "node:path";
|
|
8055
|
+
import { execFile as execFile10 } from "node:child_process";
|
|
8056
|
+
import { promisify as promisify7 } from "node:util";
|
|
8057
|
+
var execFileAsync2 = promisify7(execFile10);
|
|
8058
|
+
var INSTALL_POLL_INTERVAL_MS = 3e3;
|
|
8059
|
+
var PROBE_RETRY_MS = 3e4;
|
|
8060
|
+
var HOST_TOKEN_ENV = "VIBEFLOW_HOST_TOKEN";
|
|
8061
|
+
function readInstalledVersion(packageRoot) {
|
|
8062
|
+
try {
|
|
8063
|
+
const pkg = JSON.parse(fs22.readFileSync(path26.join(packageRoot, "package.json"), "utf8"));
|
|
8064
|
+
return typeof pkg.version === "string" ? pkg.version : null;
|
|
8065
|
+
} catch {
|
|
8066
|
+
return null;
|
|
8067
|
+
}
|
|
8068
|
+
}
|
|
8069
|
+
async function probeCli(cliEntry) {
|
|
8070
|
+
try {
|
|
8071
|
+
const { stdout } = await execFileAsync2(process.execPath, [cliEntry, "--version"], { timeout: 15e3, windowsHide: true });
|
|
8072
|
+
return stdout.trim();
|
|
8073
|
+
} catch {
|
|
8074
|
+
return null;
|
|
8075
|
+
}
|
|
8076
|
+
}
|
|
8077
|
+
function watchInstalledVersion(options) {
|
|
8078
|
+
const readVersion2 = options.readVersion ?? readInstalledVersion;
|
|
8079
|
+
const probe = options.probe ?? probeCli;
|
|
8080
|
+
const now = options.now ?? Date.now;
|
|
8081
|
+
let previous = null;
|
|
8082
|
+
let installed = null;
|
|
8083
|
+
const probedAt = /* @__PURE__ */ new Map();
|
|
8084
|
+
let busy = false;
|
|
8085
|
+
const tick = async () => {
|
|
8086
|
+
if (busy) return;
|
|
8087
|
+
busy = true;
|
|
8088
|
+
try {
|
|
8089
|
+
const version = readVersion2(options.packageRoot);
|
|
8090
|
+
const seenTwice = version !== null && version === previous;
|
|
8091
|
+
previous = version;
|
|
8092
|
+
if (!version || !isNewerVersion(version, options.currentVersion)) return;
|
|
8093
|
+
if (installed !== version) {
|
|
8094
|
+
const last = probedAt.get(version);
|
|
8095
|
+
if (!seenTwice || last !== void 0 && now() - last < PROBE_RETRY_MS) return;
|
|
8096
|
+
probedAt.set(version, now());
|
|
8097
|
+
if (await probe(options.cliEntry) !== version) return;
|
|
8098
|
+
installed = version;
|
|
8099
|
+
}
|
|
8100
|
+
options.onInstalled(version);
|
|
8101
|
+
} finally {
|
|
8102
|
+
busy = false;
|
|
8103
|
+
}
|
|
8104
|
+
};
|
|
8105
|
+
return { tick };
|
|
8106
|
+
}
|
|
8107
|
+
function relaunchArgs(cliEntry, options) {
|
|
8108
|
+
return [cliEntry, "web", "--no-open", "--store-path", options.userDataDir, "--port", String(options.port), "--backend", options.backend];
|
|
8109
|
+
}
|
|
8110
|
+
function takeHandedOverToken(env = process.env) {
|
|
8111
|
+
const token = env[HOST_TOKEN_ENV];
|
|
8112
|
+
delete env[HOST_TOKEN_ENV];
|
|
8113
|
+
return token && /^[A-Za-z0-9_-]{43}$/.test(token) ? token : void 0;
|
|
8114
|
+
}
|
|
8115
|
+
|
|
8017
8116
|
// packages/cli/src/host.ts
|
|
8018
8117
|
var DEFAULT_HOST_PORT = 47820;
|
|
8019
8118
|
async function waitForPort(userDataDir, timeoutMs = 1e4) {
|
|
@@ -8037,7 +8136,7 @@ async function startHost(options) {
|
|
|
8037
8136
|
const lock = {
|
|
8038
8137
|
pid: process.pid,
|
|
8039
8138
|
port: 0,
|
|
8040
|
-
token: randomBytes2(32).toString("base64url"),
|
|
8139
|
+
token: options.token ?? randomBytes2(32).toString("base64url"),
|
|
8041
8140
|
version: options.version,
|
|
8042
8141
|
startedAt: Date.now()
|
|
8043
8142
|
};
|
|
@@ -8055,22 +8154,16 @@ async function startHost(options) {
|
|
|
8055
8154
|
stateDir: options.userDataDir
|
|
8056
8155
|
});
|
|
8057
8156
|
const core = createCore({ sessions, bus, version: options.version });
|
|
8058
|
-
let availableUpdate = null;
|
|
8059
8157
|
let updateTimer = null;
|
|
8060
|
-
let
|
|
8061
|
-
const
|
|
8062
|
-
const
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
bus.emit("update:available", next);
|
|
8070
|
-
}
|
|
8071
|
-
} catch {
|
|
8072
|
-
}
|
|
8073
|
-
};
|
|
8158
|
+
let installTimer = null;
|
|
8159
|
+
const packageRoot = options.cliEntry ? path27.dirname(path27.dirname(options.cliEntry)) : null;
|
|
8160
|
+
const updates = createUpdateMonitor({
|
|
8161
|
+
packageName: options.sourceRoot || !packageRoot ? null : packageName(packageRoot),
|
|
8162
|
+
currentVersion: options.version,
|
|
8163
|
+
onChange: (update) => bus.emit("update:available", update)
|
|
8164
|
+
});
|
|
8165
|
+
const checkUpdates = () => void updates.refresh().catch(() => {
|
|
8166
|
+
});
|
|
8074
8167
|
let stopping = null;
|
|
8075
8168
|
const handlers = {
|
|
8076
8169
|
...core.handlers,
|
|
@@ -8084,9 +8177,10 @@ async function startHost(options) {
|
|
|
8084
8177
|
backend: sessions.kind,
|
|
8085
8178
|
startedAt: lock.startedAt
|
|
8086
8179
|
}),
|
|
8087
|
-
"host:updateStatus": () =>
|
|
8180
|
+
"host:updateStatus": () => updates.status(),
|
|
8181
|
+
"host:checkUpdate": () => updates.refresh(),
|
|
8088
8182
|
"host:openUpdateTerminal": () => {
|
|
8089
|
-
if (!
|
|
8183
|
+
if (!updates.status()) throw new Error("\u76EE\u524D\u6C92\u6709\u53EF\u5F9E\u5168\u57DF npm \u5B89\u88DD\u66F4\u65B0\u7684\u7248\u672C\u3002");
|
|
8090
8184
|
return openUpdateTerminal();
|
|
8091
8185
|
}
|
|
8092
8186
|
};
|
|
@@ -8102,19 +8196,45 @@ async function startHost(options) {
|
|
|
8102
8196
|
updateLock(options.userDataDir, lock);
|
|
8103
8197
|
const stopWatch = core.watchStore();
|
|
8104
8198
|
core.warmModelCatalog();
|
|
8105
|
-
|
|
8106
|
-
|
|
8107
|
-
|
|
8199
|
+
let requestRestart = () => {
|
|
8200
|
+
};
|
|
8201
|
+
const restartRequested = new Promise((resolve) => {
|
|
8202
|
+
requestRestart = resolve;
|
|
8203
|
+
});
|
|
8204
|
+
if (updates.supported && options.cliEntry && packageRoot) {
|
|
8205
|
+
checkUpdates();
|
|
8206
|
+
updateTimer = setInterval(checkUpdates, UPDATE_CHECK_INTERVAL_MS);
|
|
8207
|
+
const installs = watchInstalledVersion({
|
|
8208
|
+
packageRoot,
|
|
8209
|
+
cliEntry: options.cliEntry,
|
|
8210
|
+
currentVersion: options.version,
|
|
8211
|
+
onInstalled: (version) => {
|
|
8212
|
+
if (!options.autoRestart) {
|
|
8213
|
+
updates.markInstalled(version, "\u7D42\u7AEF\u6A5F\u4ECB\u9762\uFF08TUI\uFF09host \u4E0D\u6703\u81EA\u52D5\u91CD\u65B0\u555F\u52D5");
|
|
8214
|
+
return;
|
|
8215
|
+
}
|
|
8216
|
+
void (sessions.kind === "pty" ? sessions.list() : Promise.resolve([])).then((running) => {
|
|
8217
|
+
if (running.length > 0) {
|
|
8218
|
+
updates.markInstalled(version, `\u6709 ${running.length} \u500B\u57F7\u884C\u4E2D\u7684\u7D42\u7AEF\u6A5F session\uFF0C\u91CD\u65B0\u555F\u52D5\u6703\u4E2D\u65B7\u5B83\u5011\uFF1B\u5168\u90E8\u7D50\u675F\u5F8C\u6703\u81EA\u52D5\u91CD\u65B0\u555F\u52D5`);
|
|
8219
|
+
} else {
|
|
8220
|
+
requestRestart(version);
|
|
8221
|
+
}
|
|
8222
|
+
}).catch(() => {
|
|
8223
|
+
});
|
|
8224
|
+
}
|
|
8225
|
+
});
|
|
8226
|
+
installTimer = setInterval(() => void installs.tick(), INSTALL_POLL_INTERVAL_MS);
|
|
8108
8227
|
}
|
|
8109
8228
|
const stop = () => stopping ??= (async () => {
|
|
8110
|
-
|
|
8229
|
+
updates.stop();
|
|
8111
8230
|
if (updateTimer) clearInterval(updateTimer);
|
|
8231
|
+
if (installTimer) clearInterval(installTimer);
|
|
8112
8232
|
stopWatch();
|
|
8113
8233
|
core.shutdown();
|
|
8114
8234
|
await server.close();
|
|
8115
8235
|
releaseLock(options.userDataDir);
|
|
8116
8236
|
})();
|
|
8117
|
-
return { kind: "started", host: { core, server, lock, stop } };
|
|
8237
|
+
return { kind: "started", host: { core, server, lock, restartRequested, stop } };
|
|
8118
8238
|
} catch (err) {
|
|
8119
8239
|
releaseLock(options.userDataDir);
|
|
8120
8240
|
throw err;
|
|
@@ -8124,7 +8244,7 @@ function loginUrl(lock, pathname = "/home/") {
|
|
|
8124
8244
|
return `http://127.0.0.1:${lock.port}${pathname}?token=${encodeURIComponent(lock.token)}`;
|
|
8125
8245
|
}
|
|
8126
8246
|
function isWebDir(dir) {
|
|
8127
|
-
return
|
|
8247
|
+
return fs23.existsSync(path27.join(dir, "home", "index.html"));
|
|
8128
8248
|
}
|
|
8129
8249
|
|
|
8130
8250
|
// packages/cli/src/remote.ts
|
|
@@ -8241,14 +8361,14 @@ function connectToHost(lock) {
|
|
|
8241
8361
|
}
|
|
8242
8362
|
|
|
8243
8363
|
// packages/cli/src/doctor.ts
|
|
8244
|
-
import
|
|
8245
|
-
import
|
|
8246
|
-
import { execFile as
|
|
8247
|
-
import { promisify as
|
|
8364
|
+
import fs24 from "fs";
|
|
8365
|
+
import path28 from "path";
|
|
8366
|
+
import { execFile as execFile11 } from "child_process";
|
|
8367
|
+
import { promisify as promisify8 } from "util";
|
|
8248
8368
|
init_env();
|
|
8249
8369
|
init_git_bash();
|
|
8250
8370
|
init_tmux_backend();
|
|
8251
|
-
var pexec6 =
|
|
8371
|
+
var pexec6 = promisify8(execFile11);
|
|
8252
8372
|
function parseVersion(text) {
|
|
8253
8373
|
const m = /(\d+)\.(\d+)(?:\.(\d+))?/.exec(text);
|
|
8254
8374
|
return m ? [Number(m[1]), Number(m[2]), Number(m[3] ?? 0)] : [];
|
|
@@ -8382,10 +8502,10 @@ async function runDoctor(options) {
|
|
|
8382
8502
|
});
|
|
8383
8503
|
}
|
|
8384
8504
|
try {
|
|
8385
|
-
|
|
8386
|
-
const probe =
|
|
8387
|
-
|
|
8388
|
-
|
|
8505
|
+
fs24.mkdirSync(options.userDataDir, { recursive: true });
|
|
8506
|
+
const probe = path28.join(options.userDataDir, `.doctor-${process.pid}`);
|
|
8507
|
+
fs24.writeFileSync(probe, "");
|
|
8508
|
+
fs24.rmSync(probe);
|
|
8389
8509
|
checks.push({ id: "data", name: "\u8CC7\u6599\u76EE\u9304", level: "ok", detail: options.userDataDir });
|
|
8390
8510
|
} catch (err) {
|
|
8391
8511
|
checks.push({
|
|
@@ -8425,7 +8545,7 @@ Usage:
|
|
|
8425
8545
|
vibeflow open <path> Add a project folder to the recent list, then open the Web UI
|
|
8426
8546
|
vibeflow doctor Check Node, git, tmux, node-pty and the agent CLIs
|
|
8427
8547
|
(--skip agents,web,\u2026 leaves checks out, e.g. on CI)
|
|
8428
|
-
vibeflow update Install the latest global npm release (
|
|
8548
|
+
vibeflow update Install the latest global npm release (a running Web UI host restarts into it)
|
|
8429
8549
|
vibeflow task \u2026 Create / update cards; add artifacts (vibeflow task --help)
|
|
8430
8550
|
|
|
8431
8551
|
Options:
|
|
@@ -8440,24 +8560,24 @@ Options:
|
|
|
8440
8560
|
`.trim();
|
|
8441
8561
|
function detectLayout() {
|
|
8442
8562
|
const file = fileURLToPath(import.meta.url);
|
|
8443
|
-
const here =
|
|
8444
|
-
const bundledWeb =
|
|
8445
|
-
if (isWebDir(bundledWeb) ||
|
|
8563
|
+
const here = path31.dirname(file);
|
|
8564
|
+
const bundledWeb = path31.join(here, "web");
|
|
8565
|
+
if (isWebDir(bundledWeb) || path31.basename(here) === "dist") {
|
|
8446
8566
|
return {
|
|
8447
|
-
version: readVersion(
|
|
8567
|
+
version: readVersion(path31.join(here, "..", "package.json")),
|
|
8448
8568
|
webDir: isWebDir(bundledWeb) ? bundledWeb : null,
|
|
8449
8569
|
sourceRoot: null,
|
|
8450
8570
|
cliEntry: file
|
|
8451
8571
|
};
|
|
8452
8572
|
}
|
|
8453
|
-
const root =
|
|
8573
|
+
const root = path31.resolve(here, "..", "..", "..");
|
|
8454
8574
|
const override = process.env.VIBEFLOW_WEB_DIR;
|
|
8455
|
-
const webDir = override && isWebDir(override) ? override : isWebDir(
|
|
8456
|
-
return { version: readVersion(
|
|
8575
|
+
const webDir = override && isWebDir(override) ? override : isWebDir(path31.join(root, "app")) ? path31.join(root, "app") : null;
|
|
8576
|
+
return { version: readVersion(path31.join(root, "package.json")), webDir, sourceRoot: root, cliEntry: null };
|
|
8457
8577
|
}
|
|
8458
8578
|
function readVersion(pkgPath) {
|
|
8459
8579
|
try {
|
|
8460
|
-
return JSON.parse(
|
|
8580
|
+
return JSON.parse(fs26.readFileSync(pkgPath, "utf8")).version;
|
|
8461
8581
|
} catch {
|
|
8462
8582
|
return "0.0.0";
|
|
8463
8583
|
}
|
|
@@ -8481,6 +8601,7 @@ function parse(argv) {
|
|
|
8481
8601
|
strict: true
|
|
8482
8602
|
});
|
|
8483
8603
|
}
|
|
8604
|
+
var handedOverToken = takeHandedOverToken();
|
|
8484
8605
|
function hostOptions(values, layout, userDataDir, withWeb = true) {
|
|
8485
8606
|
const backend = values.backend ?? "auto";
|
|
8486
8607
|
if (!["auto", "tmux", "pty"].includes(backend)) throw new Error("--backend must be auto | tmux | pty");
|
|
@@ -8493,7 +8614,8 @@ function hostOptions(values, layout, userDataDir, withWeb = true) {
|
|
|
8493
8614
|
sourceRoot: layout.sourceRoot,
|
|
8494
8615
|
cliEntry: layout.cliEntry,
|
|
8495
8616
|
backend,
|
|
8496
|
-
port
|
|
8617
|
+
port,
|
|
8618
|
+
token: handedOverToken
|
|
8497
8619
|
};
|
|
8498
8620
|
}
|
|
8499
8621
|
async function openBrowser(url) {
|
|
@@ -8502,6 +8624,33 @@ async function openBrowser(url) {
|
|
|
8502
8624
|
} catch {
|
|
8503
8625
|
}
|
|
8504
8626
|
}
|
|
8627
|
+
async function relaunchHost(host, cliEntry, userDataDir, version) {
|
|
8628
|
+
const port = host.lock.port;
|
|
8629
|
+
const token = host.lock.token;
|
|
8630
|
+
const backend = host.core.sessions.kind;
|
|
8631
|
+
console.log(`
|
|
8632
|
+
\u5DF2\u5B89\u88DD VibeFlow ${version}\uFF0C\u6B63\u5728\u91CD\u65B0\u555F\u52D5 host\u2026`);
|
|
8633
|
+
await host.stop();
|
|
8634
|
+
const child = spawn9(process.execPath, relaunchArgs(cliEntry, { userDataDir, port, backend }), {
|
|
8635
|
+
stdio: "inherit",
|
|
8636
|
+
env: { ...process.env, [HOST_TOKEN_ENV]: token }
|
|
8637
|
+
});
|
|
8638
|
+
const forward = () => {
|
|
8639
|
+
child.kill("SIGTERM");
|
|
8640
|
+
};
|
|
8641
|
+
process.on("SIGINT", () => {
|
|
8642
|
+
});
|
|
8643
|
+
process.on("SIGHUP", () => {
|
|
8644
|
+
});
|
|
8645
|
+
process.on("SIGTERM", forward);
|
|
8646
|
+
return new Promise((resolve) => {
|
|
8647
|
+
child.once("error", (err) => {
|
|
8648
|
+
console.error(`\u7121\u6CD5\u555F\u52D5\u65B0\u7248 host\uFF1A${err.message}\u3002\u8ACB\u57F7\u884C vibeflow \u91CD\u65B0\u555F\u52D5\u3002`);
|
|
8649
|
+
resolve(1);
|
|
8650
|
+
});
|
|
8651
|
+
child.once("exit", (code2, signal) => resolve(code2 ?? (signal ? 1 : 0)));
|
|
8652
|
+
});
|
|
8653
|
+
}
|
|
8505
8654
|
function stopOnSignals(host) {
|
|
8506
8655
|
return new Promise((resolve) => {
|
|
8507
8656
|
const stop = () => {
|
|
@@ -8524,7 +8673,7 @@ async function cmdWeb(values, layout, userDataDir, pathname = "/home/") {
|
|
|
8524
8673
|
console.error("\u627E\u4E0D\u5230 Web UI \u7684\u975C\u614B\u6A94\u3002\u5F9E\u539F\u59CB\u78BC\u57F7\u884C\u6642\u8ACB\u5148\u57F7\u884C\uFF1Anpm run build:web");
|
|
8525
8674
|
return 1;
|
|
8526
8675
|
}
|
|
8527
|
-
const started = await startHost(hostOptions(values, layout, userDataDir));
|
|
8676
|
+
const started = await startHost({ ...hostOptions(values, layout, userDataDir), autoRestart: true });
|
|
8528
8677
|
if (started.kind === "running") return cmdWeb(values, layout, userDataDir, pathname);
|
|
8529
8678
|
const { host } = started;
|
|
8530
8679
|
const url = loginUrl(host.lock, pathname);
|
|
@@ -8537,8 +8686,11 @@ async function cmdWeb(values, layout, userDataDir, pathname = "/home/") {
|
|
|
8537
8686
|
${formatChecks(checks)}
|
|
8538
8687
|
`);
|
|
8539
8688
|
if (!values["no-open"]) await openBrowser(url);
|
|
8540
|
-
await
|
|
8541
|
-
|
|
8689
|
+
const ended = await Promise.race([
|
|
8690
|
+
stopOnSignals(host).then(() => null),
|
|
8691
|
+
host.restartRequested
|
|
8692
|
+
]);
|
|
8693
|
+
return ended === null || !layout.cliEntry ? 0 : relaunchHost(host, layout.cliEntry, userDataDir, ended);
|
|
8542
8694
|
}
|
|
8543
8695
|
async function cmdTui(values, layout, userDataDir) {
|
|
8544
8696
|
const { runTui: runTui2 } = await Promise.resolve().then(() => (init_src(), src_exports));
|
|
@@ -8663,8 +8815,8 @@ async function cmdOpen(values, target, layout, userDataDir) {
|
|
|
8663
8815
|
console.error("\u7528\u6CD5\uFF1Avibeflow open <path>");
|
|
8664
8816
|
return 1;
|
|
8665
8817
|
}
|
|
8666
|
-
const dir =
|
|
8667
|
-
if (!
|
|
8818
|
+
const dir = path31.resolve(target);
|
|
8819
|
+
if (!fs26.existsSync(dir) || !fs26.statSync(dir).isDirectory()) {
|
|
8668
8820
|
console.error(`\u4E0D\u662F\u8CC7\u6599\u593E\uFF1A${dir}`);
|
|
8669
8821
|
return 1;
|
|
8670
8822
|
}
|
package/dist/web/404/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">404: This page could not be found</title><link rel="preload" href="/_next/static/css/3cafb8bddc730b60.css" as="style"/><link rel="stylesheet" href="/_next/static/css/3cafb8bddc730b60.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-33344f7100190436.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-
|
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">404: This page could not be found</title><link rel="preload" href="/_next/static/css/3cafb8bddc730b60.css" as="style"/><link rel="stylesheet" href="/_next/static/css/3cafb8bddc730b60.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-33344f7100190436.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-2571a2564f593899.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/wiyRNf4HeW4AW-LhhYSsf/_buildManifest.js" defer=""></script><script src="/_next/static/wiyRNf4HeW4AW-LhhYSsf/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"wiyRNf4HeW4AW-LhhYSsf","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|
package/dist/web/404.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">404: This page could not be found</title><link rel="preload" href="/_next/static/css/3cafb8bddc730b60.css" as="style"/><link rel="stylesheet" href="/_next/static/css/3cafb8bddc730b60.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-33344f7100190436.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-
|
|
1
|
+
<!DOCTYPE html><html><head><meta charSet="utf-8" data-next-head=""/><meta name="viewport" content="width=device-width" data-next-head=""/><link rel="icon" href="/favicon.ico" sizes="any" data-next-head=""/><link rel="icon" href="/logo.svg" type="image/svg+xml" data-next-head=""/><link rel="apple-touch-icon" href="/apple-touch-icon.png" data-next-head=""/><title data-next-head="">404: This page could not be found</title><link rel="preload" href="/_next/static/css/3cafb8bddc730b60.css" as="style"/><link rel="stylesheet" href="/_next/static/css/3cafb8bddc730b60.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" noModule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-33344f7100190436.js" defer=""></script><script src="/_next/static/chunks/framework-b92a367cf1ad4bf7.js" defer=""></script><script src="/_next/static/chunks/main-ec7fd4c371d06729.js" defer=""></script><script src="/_next/static/chunks/pages/_app-2571a2564f593899.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/wiyRNf4HeW4AW-LhhYSsf/_buildManifest.js" defer=""></script><script src="/_next/static/wiyRNf4HeW4AW-LhhYSsf/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"wiyRNf4HeW4AW-LhhYSsf","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|