@kw-yeh/vibeflow 4.1.0 → 4.2.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/dist/vibeflow.mjs +131 -99
- package/dist/web/404/index.html +1 -1
- package/dist/web/404.html +1 -1
- package/dist/web/_next/static/chunks/pages/{_app-66261c34aef6a4cb.js → _app-014e95fe86cd1d39.js} +1 -1
- package/dist/web/_next/static/chunks/pages/home-e692e9e0783d2fdf.js +11 -0
- package/dist/web/_next/static/{E9h3ANqgTHA4it6NLyDv5 → lyOZoF78HzRwmQ3DYf88f}/_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-e16a7b49ece28424.js +0 -11
- /package/dist/web/_next/static/{E9h3ANqgTHA4it6NLyDv5 → lyOZoF78HzRwmQ3DYf88f}/_ssgManifest.js +0 -0
package/dist/vibeflow.mjs
CHANGED
|
@@ -598,9 +598,9 @@ var init_attachments = __esm({
|
|
|
598
598
|
|
|
599
599
|
// packages/tui/src/task-form.ts
|
|
600
600
|
import { spawnSync } from "child_process";
|
|
601
|
-
import
|
|
601
|
+
import fs20 from "fs";
|
|
602
602
|
import os6 from "os";
|
|
603
|
-
import
|
|
603
|
+
import path24 from "path";
|
|
604
604
|
import React, { useEffect, useRef, useState } from "react";
|
|
605
605
|
import { Box, Text, render, useApp, useInput } from "ink";
|
|
606
606
|
function newFormState(defaultAutoMode, agents) {
|
|
@@ -719,17 +719,17 @@ function editorCommand(env, platform) {
|
|
|
719
719
|
return env.VISUAL?.trim() || env.EDITOR?.trim() || (platform === "win32" ? "notepad" : "vi");
|
|
720
720
|
}
|
|
721
721
|
function editInEditor(text) {
|
|
722
|
-
const dir =
|
|
723
|
-
const file =
|
|
722
|
+
const dir = fs20.mkdtempSync(path24.join(os6.tmpdir(), "vibeflow-"));
|
|
723
|
+
const file = path24.join(dir, "description.md");
|
|
724
724
|
try {
|
|
725
|
-
|
|
725
|
+
fs20.writeFileSync(file, text);
|
|
726
726
|
const cmd = editorCommand(process.env, process.platform);
|
|
727
727
|
const r = spawnSync(`${cmd} "${file}"`, { stdio: "inherit", shell: true });
|
|
728
728
|
if (r.error) return { error: `\u7121\u6CD5\u555F\u52D5\u7DE8\u8F2F\u5668\uFF08${cmd}\uFF09\uFF1A${r.error.message}` };
|
|
729
729
|
if (r.status !== 0) return { error: `\u7DE8\u8F2F\u5668\uFF08${cmd}\uFF09\u7D50\u675F\u78BC ${r.status}\uFF0C\u63CF\u8FF0\u672A\u8B8A\u66F4` };
|
|
730
|
-
return { text:
|
|
730
|
+
return { text: fs20.readFileSync(file, "utf8").replace(/\r?\n$/, "") };
|
|
731
731
|
} finally {
|
|
732
|
-
|
|
732
|
+
fs20.rmSync(dir, { recursive: true, force: true });
|
|
733
733
|
}
|
|
734
734
|
}
|
|
735
735
|
function cycle(list, current, step) {
|
|
@@ -797,10 +797,10 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
797
797
|
if (editing === "title") setS((prev) => ({ ...prev, title: draft }));
|
|
798
798
|
else if (editing === "branch") setS((prev) => ({ ...prev, branch: value2 }));
|
|
799
799
|
else if (editing === "project") {
|
|
800
|
-
if (value2) setProject(
|
|
800
|
+
if (value2) setProject(path24.resolve(value2.replace(/^~(?=$|\/)/, os6.homedir())));
|
|
801
801
|
} else if (editing === "attachments" && value2) {
|
|
802
|
-
const file =
|
|
803
|
-
if (!
|
|
802
|
+
const file = path24.resolve(value2.replace(/^~(?=$|\/)/, os6.homedir()));
|
|
803
|
+
if (!fs20.existsSync(file) || !fs20.statSync(file).isFile()) {
|
|
804
804
|
setMessage(`\u627E\u4E0D\u5230\u6A94\u6848\uFF1A${file}`);
|
|
805
805
|
return;
|
|
806
806
|
}
|
|
@@ -870,7 +870,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
870
870
|
case "title":
|
|
871
871
|
return s.title || "\uFF08\u4F8B\u5982\uFF1A\u5BE6\u4F5C\u767B\u5165\u9801\u9762\uFF09";
|
|
872
872
|
case "project": {
|
|
873
|
-
if (projectLocked) return `${s.projectPath ?
|
|
873
|
+
if (projectLocked) return `${s.projectPath ? path24.basename(s.projectPath) : "\u2014"}\uFF08\u4EFB\u52D9\u5DF2\u958B\u59CB\uFF0C\u9396\u5B9A\uFF09`;
|
|
874
874
|
if (!s.projectPath) return ctx.recent.length ? "\u2190/\u2192 \u9078\u64C7\u4F7F\u7528\u904E\u7684\u5C08\u6848\uFF0C\u6216 Enter \u8F38\u5165\u8DEF\u5F91" : "Enter \u8F38\u5165\u5C08\u6848\u8CC7\u6599\u593E\u7684\u7D55\u5C0D\u8DEF\u5F91";
|
|
875
875
|
return `${s.projectPath}${missing ? "\uFF08\u8DEF\u5F91\u907A\u5931\uFF09" : ""}`;
|
|
876
876
|
}
|
|
@@ -881,7 +881,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
881
881
|
case "branch":
|
|
882
882
|
return s.branch || "\uFF08\u7559\u7A7A\u5247\u81EA\u52D5\u547D\u540D\uFF0C\u4F8B\u5982 feature/login-fix\uFF09";
|
|
883
883
|
case "attachments":
|
|
884
|
-
return s.attachments.length ? s.attachments.map((a) =>
|
|
884
|
+
return s.attachments.length ? s.attachments.map((a) => path24.basename(a)).join("\u3001") : "\uFF08Enter \u8F38\u5165\u6A94\u6848\u8DEF\u5F91\u52A0\u5165\uFF09";
|
|
885
885
|
case "description": {
|
|
886
886
|
if (!s.description) return "\uFF08Enter \u7528\u7DE8\u8F2F\u5668\u64B0\u5BEB\uFF09";
|
|
887
887
|
const lines = s.description.split("\n");
|
|
@@ -912,7 +912,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
912
912
|
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";
|
|
913
913
|
if (s.mode === "edit" && projectChanged(s)) return "\u66F4\u63DB\u5C08\u6848\u6703\u5728\u65B0\u5C08\u6848\u91CD\u5EFA worktree\uFF08\u6B64\u4EFB\u52D9\u5C1A\u672A\u958B\u59CB\uFF0C\u7121\u8B8A\u66F4\u6703\u907A\u5931\uFF09\u3002";
|
|
914
914
|
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`;
|
|
915
|
-
if (info?.isRepo && s.projectPath) return `worktree \u6703\u5EFA\u5728 ${ctx.workstationPath || "~/Desktop"}/${
|
|
915
|
+
if (info?.isRepo && s.projectPath) return `worktree \u6703\u5EFA\u5728 ${ctx.workstationPath || "~/Desktop"}/${path24.basename(s.projectPath)}`;
|
|
916
916
|
}
|
|
917
917
|
if (field === "branch") return info?.hasRemote ? "\u586B\u5BEB\u5F8C\u6703\u5EFA\u7ACB\u540C\u540D\u5206\u652F\uFF1B\u82E5 remote \u5DF2\u6709\u9019\u500B\u5206\u652F\uFF0C\u5247\u76F4\u63A5\u53D6\u56DE\u4E26\u63A5\u7E8C\u4E0A\u9762\u7684\u5DE5\u4F5C\u3002" : "\u586B\u5BEB\u5F8C\u6703\u5EFA\u7ACB\u540C\u540D\u5206\u652F\u3002";
|
|
918
918
|
if (field === "effort") return `${EFFORTS.find((x) => x.value === s.effort).description} Claude Code \u8207 Codex \u6703\u5728\u555F\u52D5\u6B64\u4EFB\u52D9\u6642\u5957\u7528\uFF1B\u5BE6\u969B\u53EF\u7528\u7D1A\u8DDD\u4F9D model \u800C\u5B9A\u3002`;
|
|
@@ -1029,7 +1029,7 @@ __export(src_exports, {
|
|
|
1029
1029
|
showDiff: () => showDiff
|
|
1030
1030
|
});
|
|
1031
1031
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
1032
|
-
import
|
|
1032
|
+
import path25 from "path";
|
|
1033
1033
|
import React2, { useEffect as useEffect2, useState as useState2 } from "react";
|
|
1034
1034
|
import { Box as Box2, Text as Text2, render as render2, useApp as useApp2, useInput as useInput2, useStdout } from "ink";
|
|
1035
1035
|
function findDetachKey(text) {
|
|
@@ -1291,7 +1291,7 @@ function showDiff(task) {
|
|
|
1291
1291
|
});
|
|
1292
1292
|
}
|
|
1293
1293
|
function tmuxAttach(opts, sessionName) {
|
|
1294
|
-
const conf =
|
|
1294
|
+
const conf = path25.join(opts.userDataDir, "tmux.conf");
|
|
1295
1295
|
const inOurServer = (process.env.TMUX ?? "").split(",")[0].endsWith(`/${TMUX_SOCKET}`);
|
|
1296
1296
|
const args = inOurServer ? ["-L", TMUX_SOCKET, "-f", conf, "switch-client", "-t", `=${sessionName}`] : ["-L", TMUX_SOCKET, "-f", conf, "attach-session", "-t", `=${sessionName}`];
|
|
1297
1297
|
spawnSync2("tmux", args, { stdio: "inherit", env: { ...process.env, TMUX: inOurServer ? process.env.TMUX : "" } });
|
|
@@ -1421,8 +1421,8 @@ var init_src = __esm({
|
|
|
1421
1421
|
});
|
|
1422
1422
|
|
|
1423
1423
|
// packages/cli/src/main.ts
|
|
1424
|
-
import
|
|
1425
|
-
import
|
|
1424
|
+
import fs21 from "fs";
|
|
1425
|
+
import path26 from "path";
|
|
1426
1426
|
import { fileURLToPath } from "url";
|
|
1427
1427
|
import { parseArgs as parseArgs2 } from "node:util";
|
|
1428
1428
|
|
|
@@ -1814,8 +1814,8 @@ function createBridge(t) {
|
|
|
1814
1814
|
* in-app preview will not inline. Resolves to '' on success, else a reason.
|
|
1815
1815
|
*/
|
|
1816
1816
|
openArtifactsDir: (taskId) => t.invoke("task:openArtifactsDir", taskId),
|
|
1817
|
-
/**
|
|
1818
|
-
|
|
1817
|
+
/** Every spec.md the task's branch added or changed; empty when there is none. */
|
|
1818
|
+
getSpecs: (taskId) => t.invoke("task:getSpecs", taskId),
|
|
1819
1819
|
/** Store dir + CLI paths for launch injection, so an agent can write cards. */
|
|
1820
1820
|
getBoardCliLaunchInfo: () => t.invoke("board:getCliLaunchInfo"),
|
|
1821
1821
|
/** VibeFlow's own skill / prompt / script store. */
|
|
@@ -3574,8 +3574,8 @@ async function taskCommand(argv) {
|
|
|
3574
3574
|
}
|
|
3575
3575
|
|
|
3576
3576
|
// packages/cli/src/host.ts
|
|
3577
|
-
import
|
|
3578
|
-
import
|
|
3577
|
+
import fs18 from "fs";
|
|
3578
|
+
import path22 from "path";
|
|
3579
3579
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
3580
3580
|
|
|
3581
3581
|
// packages/core/src/events.ts
|
|
@@ -4113,9 +4113,9 @@ async function syncBuiltinsAtStartup() {
|
|
|
4113
4113
|
}
|
|
4114
4114
|
|
|
4115
4115
|
// packages/core/src/service.ts
|
|
4116
|
-
import
|
|
4116
|
+
import fs16 from "fs";
|
|
4117
4117
|
import os5 from "os";
|
|
4118
|
-
import
|
|
4118
|
+
import path20 from "path";
|
|
4119
4119
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
4120
4120
|
|
|
4121
4121
|
// packages/core/src/agent-models.ts
|
|
@@ -4364,34 +4364,81 @@ async function boardCliLaunchInfo() {
|
|
|
4364
4364
|
import fs14 from "fs";
|
|
4365
4365
|
import path18 from "path";
|
|
4366
4366
|
var DECISIONS_FILE_SUFFIX = ".DECISIONS.md";
|
|
4367
|
-
var MAX_DECISION_BYTES = 256 * 1024;
|
|
4368
4367
|
function decisionsKey(worktreePath, branch) {
|
|
4369
4368
|
return worktreePath ? path18.basename(worktreePath) : branch.replace(/\//g, "-");
|
|
4370
4369
|
}
|
|
4371
4370
|
function decisionsPath(workspacePath, key) {
|
|
4372
4371
|
return path18.join(workspacePath, `${key}${DECISIONS_FILE_SUFFIX}`);
|
|
4373
4372
|
}
|
|
4374
|
-
function
|
|
4375
|
-
const target = decisionsPath(workspacePath, key);
|
|
4373
|
+
function deleteDecisions(workspacePath, key) {
|
|
4376
4374
|
try {
|
|
4377
|
-
|
|
4378
|
-
if (!stat.isFile()) return { path: target, markdown: null };
|
|
4379
|
-
const buf = fs14.readFileSync(target);
|
|
4380
|
-
return {
|
|
4381
|
-
path: target,
|
|
4382
|
-
markdown: buf.subarray(0, MAX_DECISION_BYTES).toString("utf8"),
|
|
4383
|
-
updatedAt: stat.mtimeMs,
|
|
4384
|
-
...buf.byteLength > MAX_DECISION_BYTES ? { truncated: true } : {}
|
|
4385
|
-
};
|
|
4375
|
+
fs14.rmSync(decisionsPath(workspacePath, key), { force: true });
|
|
4386
4376
|
} catch {
|
|
4387
|
-
return { path: target, markdown: null };
|
|
4388
4377
|
}
|
|
4389
4378
|
}
|
|
4390
|
-
|
|
4379
|
+
|
|
4380
|
+
// packages/core/src/specs.ts
|
|
4381
|
+
import fs15 from "fs";
|
|
4382
|
+
import path19 from "path";
|
|
4383
|
+
var SPEC_FILE_NAME = "spec.md";
|
|
4384
|
+
var MAX_SPEC_BYTES = 256 * 1024;
|
|
4385
|
+
function isSpecPath(p) {
|
|
4386
|
+
return path19.posix.basename(p) === SPEC_FILE_NAME;
|
|
4387
|
+
}
|
|
4388
|
+
function clip2(buf) {
|
|
4389
|
+
return {
|
|
4390
|
+
markdown: buf.subarray(0, MAX_SPEC_BYTES).toString("utf8"),
|
|
4391
|
+
...buf.byteLength > MAX_SPEC_BYTES ? { truncated: true } : {}
|
|
4392
|
+
};
|
|
4393
|
+
}
|
|
4394
|
+
async function readWorktreeSpecs(worktreePath, baseBranch) {
|
|
4395
|
+
const baseRef = await resolveBaseRef(worktreePath, baseBranch);
|
|
4396
|
+
const entries = await collectDiffEntries(worktreePath, baseRef);
|
|
4397
|
+
const specs = [];
|
|
4398
|
+
for (const entry of entries) {
|
|
4399
|
+
if (entry.status === "D" || !isSpecPath(entry.path)) continue;
|
|
4400
|
+
try {
|
|
4401
|
+
const full = path19.join(worktreePath, entry.path);
|
|
4402
|
+
const stat = fs15.statSync(full);
|
|
4403
|
+
if (!stat.isFile()) continue;
|
|
4404
|
+
specs.push({ path: entry.path, ...clip2(fs15.readFileSync(full)), updatedAt: stat.mtimeMs });
|
|
4405
|
+
} catch {
|
|
4406
|
+
}
|
|
4407
|
+
}
|
|
4408
|
+
return specs.sort((a, b) => a.path.localeCompare(b.path));
|
|
4409
|
+
}
|
|
4410
|
+
async function readBranchSpecs(projectPath, branch, baseBranch, changedPaths) {
|
|
4411
|
+
const ref = `refs/heads/${branch}`;
|
|
4391
4412
|
try {
|
|
4392
|
-
|
|
4413
|
+
await git(projectPath, ["rev-parse", "--verify", ref]);
|
|
4393
4414
|
} catch {
|
|
4415
|
+
return [];
|
|
4416
|
+
}
|
|
4417
|
+
let paths = changedPaths;
|
|
4418
|
+
if (!paths) {
|
|
4419
|
+
const baseRef = await resolveBaseRef(projectPath, baseBranch);
|
|
4420
|
+
const names = await git(projectPath, [
|
|
4421
|
+
"diff",
|
|
4422
|
+
"--name-only",
|
|
4423
|
+
"--diff-filter=d",
|
|
4424
|
+
`${baseRef}...${ref}`
|
|
4425
|
+
]).catch(() => "");
|
|
4426
|
+
paths = names.split("\n").map((l) => l.trim());
|
|
4427
|
+
}
|
|
4428
|
+
const specs = [];
|
|
4429
|
+
for (const p of paths.filter(isSpecPath)) {
|
|
4430
|
+
try {
|
|
4431
|
+
const content = await git(projectPath, ["show", `${ref}:${p}`]);
|
|
4432
|
+
const ct = await git(projectPath, ["log", "-1", "--format=%ct", ref, "--", p]);
|
|
4433
|
+
specs.push({
|
|
4434
|
+
path: p,
|
|
4435
|
+
...clip2(Buffer.from(content, "utf8")),
|
|
4436
|
+
...ct ? { updatedAt: Number(ct) * 1e3 } : {}
|
|
4437
|
+
});
|
|
4438
|
+
} catch {
|
|
4439
|
+
}
|
|
4394
4440
|
}
|
|
4441
|
+
return specs.sort((a, b) => a.path.localeCompare(b.path));
|
|
4395
4442
|
}
|
|
4396
4443
|
|
|
4397
4444
|
// packages/core/src/chat-session.ts
|
|
@@ -4705,22 +4752,6 @@ function buildArtifactPrompt(artifactsDir = ARTIFACTS_FALLBACK_DIR2) {
|
|
|
4705
4752
|
"5. Artifact \u8CC7\u6599\u593E\u4F4D\u65BC worktree \u4E4B\u5916\uFF1B\u4E0D\u8981\u628A\u5176\u4E2D\u5167\u5BB9\u52A0\u5165 git commit\uFF0C\u4E5F\u4E0D\u8981\u628A\u6700\u7D42\u4EA4\u4ED8\u7269\u53EA\u7559\u5728\u9019\u88E1\u3002"
|
|
4706
4753
|
].join("\n");
|
|
4707
4754
|
}
|
|
4708
|
-
var DECISIONS_FILE_SUFFIX2 = ".DECISIONS.md";
|
|
4709
|
-
function taskDecisionsPath(worktreePath, workspacePath) {
|
|
4710
|
-
if (!worktreePath || !workspacePath) return null;
|
|
4711
|
-
return `${toShellPath(workspacePath)}/${pathBasename(worktreePath)}${DECISIONS_FILE_SUFFIX2}`;
|
|
4712
|
-
}
|
|
4713
|
-
function buildDecisionPrompt(decisionsPath2) {
|
|
4714
|
-
return [
|
|
4715
|
-
"\u6C7A\u7B56\u66F8\uFF08\u672C\u6B21 session \u5168\u7A0B\u9069\u7528\uFF09\uFF1A",
|
|
4716
|
-
`1. \u672C\u4EFB\u52D9\u7684\u6C7A\u7B56\u66F8\u662F ${decisionsPath2}\uFF1B\u505A\u51FA\u65B0\u6C7A\u7B56\u3001\u6216\u8ABF\u6574\u65E2\u6709\u6C7A\u7B56\u6642\uFF0C\u7576\u4E0B\u5C31\u66F4\u65B0\u5B83\uFF08\u4E0D\u5B58\u5728\u8ACB\u5EFA\u7ACB\uFF09\u3002`,
|
|
4717
|
-
"2. \u53EA\u5BEB\u300C\u9019\u6B21\u65B0\u589E\u4E86\u4EC0\u9EBC\u6C7A\u7B56\u3001\u8ABF\u6574\u4E86\u4EC0\u9EBC\u65E2\u6709\u6C7A\u7B56\u300D\u8207\u7406\u7531\u3002\u9700\u6C42\u8986\u8FF0\u3001\u9032\u5EA6\u56DE\u5831\u3001\u5BE6\u4F5C\u6D41\u6C34\u5E33\u3001\u672C\u4F86\u5C31\u6210\u7ACB\u7684\u6163\u4F8B\u90FD\u4E0D\u8981\u5BEB\u3002",
|
|
4718
|
-
"3. \u6BCF\u5247\u6C7A\u7B56\u4E00\u500B `## <\u4E00\u53E5\u8A71\u8B1B\u5B8C\u7684\u6C7A\u7B56>` \u6BB5\u843D\uFF0C\u5E95\u4E0B 2-4 \u884C\u4EA4\u4EE3\uFF1A\u70BA\u4EC0\u9EBC\u9019\u6A23\u9078\u3001\u5426\u6C7A\u4E86\u4EC0\u9EBC\u66FF\u4EE3\u65B9\u6848\u3001\u8AB0\u4E4B\u5F8C\u6703\u88AB\u9019\u500B\u6C7A\u7B56\u7D81\u4F4F\u3002",
|
|
4719
|
-
"4. \u8981\u8AAA\u660E\u6D41\u7A0B\u3001\u72C0\u614B\u8F49\u63DB\u6216\u6A21\u7D44\u95DC\u4FC2\u6642\uFF0C\u7528 mermaid fence \u756B\u5716\uFF0CVibeFlow \u6703\u76F4\u63A5\u6E32\u67D3\u3002",
|
|
4720
|
-
"5. \u9019\u6B21\u6C92\u6709\u4EFB\u4F55\u6C7A\u7B56\u5C31\u4E0D\u8981\u5EFA\u7ACB\u9019\u500B\u6A94\u6848\uFF1B\u5BE7\u53EF\u7559\u767D\uFF0C\u4E0D\u8981\u6E4A\u5167\u5BB9\u3002",
|
|
4721
|
-
"6. \u7528\u7E41\u9AD4\u4E2D\u6587\u66F8\u5BEB\uFF0C\u7A0B\u5F0F\u8B58\u5225\u5B57\u4FDD\u7559\u82F1\u6587\u3002"
|
|
4722
|
-
].join("\n");
|
|
4723
|
-
}
|
|
4724
4755
|
var AUTO_PERMISSION_MODE = "auto";
|
|
4725
4756
|
function claudePermissionFlag(autoMode) {
|
|
4726
4757
|
return autoMode ? ` --permission-mode ${AUTO_PERMISSION_MODE}` : "";
|
|
@@ -4849,11 +4880,9 @@ function buildAgentCommand(task, systemPrompt, opts, workspacePath) {
|
|
|
4849
4880
|
const model = taskModel(task);
|
|
4850
4881
|
const artifactsDir = agentArtifactsDir(task.worktreePath, workspacePath) ?? ARTIFACTS_FALLBACK_DIR2;
|
|
4851
4882
|
const builtInPrompt = buildArtifactPrompt(artifactsDir);
|
|
4852
|
-
const decisionsPath2 = taskDecisionsPath(task.worktreePath, workspacePath);
|
|
4853
|
-
const decisionPrompt = decisionsPath2 ? buildDecisionPrompt(decisionsPath2) : "";
|
|
4854
4883
|
const libraryPrompt = opts?.library?.promptText?.trim();
|
|
4855
4884
|
const customPrompt = resolveSystemPrompt(systemPrompt);
|
|
4856
|
-
const sys = [builtInPrompt,
|
|
4885
|
+
const sys = [builtInPrompt, libraryPrompt, customPrompt].filter(Boolean).join("\n\n");
|
|
4857
4886
|
const includeTaskPrompt = opts?.includeTaskPrompt !== false;
|
|
4858
4887
|
const prompt = includeTaskPrompt && !opts?.resume ? buildPrompt(task) : "";
|
|
4859
4888
|
const sessionId = agent === "claude" && includeTaskPrompt ? executorSessionId(task.id, task.runId) : void 0;
|
|
@@ -4962,13 +4991,13 @@ function createCore({ sessions, bus, version }) {
|
|
|
4962
4991
|
}
|
|
4963
4992
|
function claudeSessionFile(cwd, sessionId) {
|
|
4964
4993
|
const munged = cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
4965
|
-
return
|
|
4994
|
+
return path20.join(os5.homedir(), ".claude", "projects", munged, `${sessionId}.jsonl`);
|
|
4966
4995
|
}
|
|
4967
4996
|
async function removeTaskWorktree(task) {
|
|
4968
4997
|
if (!task.projectPath || !task.worktreePath) return;
|
|
4969
4998
|
const branch = task.branch || fallbackBranchName(task.id);
|
|
4970
4999
|
await removeWorktree(task.projectPath, task.worktreePath);
|
|
4971
|
-
deleteArtifacts(task.workspacePath ??
|
|
5000
|
+
deleteArtifacts(task.workspacePath ?? path20.dirname(task.worktreePath), task.worktreePath);
|
|
4972
5001
|
await deleteBranch(task.projectPath, branch);
|
|
4973
5002
|
}
|
|
4974
5003
|
const handlers = {
|
|
@@ -5007,8 +5036,8 @@ function createCore({ sessions, bus, version }) {
|
|
|
5007
5036
|
"projects:listRecent": () => listRecentProjects(getStore()),
|
|
5008
5037
|
// `vibeflow open <path>` while a host runs: only the host writes the store.
|
|
5009
5038
|
"projects:record": (projectPath) => {
|
|
5010
|
-
const p =
|
|
5011
|
-
if (!
|
|
5039
|
+
const p = path20.resolve(str(projectPath, "projectPath"));
|
|
5040
|
+
if (!fs16.existsSync(p) || !fs16.statSync(p).isDirectory()) invalid(`not a directory: ${p}`);
|
|
5012
5041
|
recordRecentProject(getStore(), p);
|
|
5013
5042
|
return listRecentProjects(getStore());
|
|
5014
5043
|
},
|
|
@@ -5040,7 +5069,7 @@ function createCore({ sessions, bus, version }) {
|
|
|
5040
5069
|
},
|
|
5041
5070
|
// Discard everything the last run left behind — the PTY session, the
|
|
5042
5071
|
// sub-agent timeline, the conversation id, the code it changed, its artifacts
|
|
5043
|
-
// and its decision record — so the next launch starts over as if the card
|
|
5072
|
+
// and its legacy decision record — so the next launch starts over as if the card
|
|
5044
5073
|
// were new. Launching again is the caller's decision.
|
|
5045
5074
|
"vibeflow:resetTaskRun": async (taskId) => {
|
|
5046
5075
|
const task = requireTask(taskId);
|
|
@@ -5048,7 +5077,7 @@ function createCore({ sessions, bus, version }) {
|
|
|
5048
5077
|
if (!task.baseBranch) throw new Error("\u4EFB\u52D9\u6C92\u6709\u8A18\u9304 base branch\uFF0C\u7121\u6CD5\u9084\u539F worktree");
|
|
5049
5078
|
await teardownTask(task.id);
|
|
5050
5079
|
await resetWorktreeToBase(task.worktreePath, task.baseBranch);
|
|
5051
|
-
const workspacePath = task.workspacePath ??
|
|
5080
|
+
const workspacePath = task.workspacePath ?? path20.dirname(task.worktreePath);
|
|
5052
5081
|
deleteArtifacts(workspacePath, task.worktreePath);
|
|
5053
5082
|
deleteDecisions(workspacePath, decisionsKey(task.worktreePath, task.branch));
|
|
5054
5083
|
resetSubAgents(task.worktreePath);
|
|
@@ -5087,9 +5116,9 @@ function createCore({ sessions, bus, version }) {
|
|
|
5087
5116
|
if (!info.isRepo) throw new Error("\u76EE\u6A19\u8CC7\u6599\u593E\u4E0D\u662F git repository");
|
|
5088
5117
|
await teardownTask(existing.id);
|
|
5089
5118
|
await removeTaskWorktree(existing);
|
|
5090
|
-
const projectName =
|
|
5119
|
+
const projectName = path20.basename(nextProject);
|
|
5091
5120
|
const workspacePath = projectWorkstationPath(resolveWorkstationPath(getSettings()), projectName);
|
|
5092
|
-
await
|
|
5121
|
+
await fs16.promises.mkdir(workspacePath, { recursive: true });
|
|
5093
5122
|
const result = await provisionWorktree(
|
|
5094
5123
|
nextProject,
|
|
5095
5124
|
workspacePath,
|
|
@@ -5177,7 +5206,7 @@ function createCore({ sessions, bus, version }) {
|
|
|
5177
5206
|
"claude:sessionExists": (taskId) => {
|
|
5178
5207
|
const task = requireTask(taskId);
|
|
5179
5208
|
if (!task.worktreePath) return false;
|
|
5180
|
-
return
|
|
5209
|
+
return fs16.existsSync(claudeSessionFile(task.worktreePath, executorSessionId(task.id, task.runId)));
|
|
5181
5210
|
},
|
|
5182
5211
|
"sessions:list": async () => {
|
|
5183
5212
|
const keys = await sessions.list();
|
|
@@ -5224,13 +5253,16 @@ function createCore({ sessions, bus, version }) {
|
|
|
5224
5253
|
const task = requireTask(taskId);
|
|
5225
5254
|
if (!task.worktreePath || !task.workspacePath) return "task has no worktree";
|
|
5226
5255
|
const dir = agentArtifactsPath(task.workspacePath, task.worktreePath);
|
|
5227
|
-
if (!
|
|
5256
|
+
if (!fs16.existsSync(dir)) return "artifacts directory does not exist yet";
|
|
5228
5257
|
return getPlatform().openPath(dir);
|
|
5229
5258
|
},
|
|
5230
|
-
"task:
|
|
5259
|
+
"task:getSpecs": async (taskId) => {
|
|
5231
5260
|
const task = requireTask(taskId);
|
|
5232
|
-
|
|
5233
|
-
|
|
5261
|
+
const base = task.baseBranch ?? "main";
|
|
5262
|
+
if (task.worktreePath) return readWorktreeSpecs(task.worktreePath, base);
|
|
5263
|
+
if (!task.projectPath) return [];
|
|
5264
|
+
const changed = task.outcome?.files.filter((f) => f.status !== "D").map((f) => f.path);
|
|
5265
|
+
return readBranchSpecs(task.projectPath, task.branch, base, changed);
|
|
5234
5266
|
},
|
|
5235
5267
|
"board:getCliLaunchInfo": () => boardCliLaunchInfo(),
|
|
5236
5268
|
"library:list": async () => listLibrary(await libraryRoot(), builtinSkillsDir()),
|
|
@@ -5382,9 +5414,9 @@ function createCore({ sessions, bus, version }) {
|
|
|
5382
5414
|
// Watch the containing directory, not the file: JsonStore renames a temp
|
|
5383
5415
|
// file over the target and so replaces the inode on every save.
|
|
5384
5416
|
watchStore() {
|
|
5385
|
-
const file =
|
|
5417
|
+
const file = path20.basename(getStorePath());
|
|
5386
5418
|
let debounce = null;
|
|
5387
|
-
storeWatcher =
|
|
5419
|
+
storeWatcher = fs16.watch(path20.dirname(getStorePath()), (_event, filename) => {
|
|
5388
5420
|
if (filename !== file) return;
|
|
5389
5421
|
if (debounce) clearTimeout(debounce);
|
|
5390
5422
|
debounce = setTimeout(() => {
|
|
@@ -5416,9 +5448,9 @@ function createSessionBackend(sink, choice) {
|
|
|
5416
5448
|
}
|
|
5417
5449
|
|
|
5418
5450
|
// packages/core/src/web-server.ts
|
|
5419
|
-
import
|
|
5451
|
+
import fs17 from "fs";
|
|
5420
5452
|
import http from "http";
|
|
5421
|
-
import
|
|
5453
|
+
import path21 from "path";
|
|
5422
5454
|
import { timingSafeEqual } from "crypto";
|
|
5423
5455
|
import { WebSocketServer } from "ws";
|
|
5424
5456
|
var TOKEN_COOKIE = "vf_token";
|
|
@@ -5471,14 +5503,14 @@ function resolveStatic(root, urlPath) {
|
|
|
5471
5503
|
return null;
|
|
5472
5504
|
}
|
|
5473
5505
|
if (decoded.includes("\0")) return null;
|
|
5474
|
-
const rel =
|
|
5475
|
-
const base =
|
|
5476
|
-
const candidates = [rel,
|
|
5506
|
+
const rel = path21.posix.normalize(decoded).replace(/^\/+/, "");
|
|
5507
|
+
const base = path21.resolve(root);
|
|
5508
|
+
const candidates = [rel, path21.posix.join(rel, "index.html"), `${rel}.html`];
|
|
5477
5509
|
for (const c of candidates) {
|
|
5478
|
-
const full =
|
|
5479
|
-
if (full !== base && !full.startsWith(base +
|
|
5510
|
+
const full = path21.resolve(base, c);
|
|
5511
|
+
if (full !== base && !full.startsWith(base + path21.sep)) return null;
|
|
5480
5512
|
try {
|
|
5481
|
-
if (
|
|
5513
|
+
if (fs17.statSync(full).isFile()) return full;
|
|
5482
5514
|
} catch {
|
|
5483
5515
|
}
|
|
5484
5516
|
}
|
|
@@ -5539,7 +5571,7 @@ async function startWebServer(options) {
|
|
|
5539
5571
|
send(res, 404, "Not found");
|
|
5540
5572
|
return;
|
|
5541
5573
|
}
|
|
5542
|
-
const ext =
|
|
5574
|
+
const ext = path21.extname(file).toLowerCase();
|
|
5543
5575
|
const immutable = url.pathname.startsWith("/_next/static/");
|
|
5544
5576
|
res.writeHead(200, {
|
|
5545
5577
|
"Content-Type": CONTENT_TYPES[ext] ?? "application/octet-stream",
|
|
@@ -5552,7 +5584,7 @@ async function startWebServer(options) {
|
|
|
5552
5584
|
res.end();
|
|
5553
5585
|
return;
|
|
5554
5586
|
}
|
|
5555
|
-
|
|
5587
|
+
fs17.createReadStream(file).pipe(res);
|
|
5556
5588
|
}
|
|
5557
5589
|
const wss = new WebSocketServer({ noServer: true, maxPayload: MAX_PAYLOAD });
|
|
5558
5590
|
function reject(socket, status, reason) {
|
|
@@ -5724,7 +5756,7 @@ function loginUrl(lock, pathname = "/home/") {
|
|
|
5724
5756
|
return `http://127.0.0.1:${lock.port}${pathname}?token=${encodeURIComponent(lock.token)}`;
|
|
5725
5757
|
}
|
|
5726
5758
|
function isWebDir(dir) {
|
|
5727
|
-
return
|
|
5759
|
+
return fs18.existsSync(path22.join(dir, "home", "index.html"));
|
|
5728
5760
|
}
|
|
5729
5761
|
|
|
5730
5762
|
// packages/cli/src/remote.ts
|
|
@@ -5841,8 +5873,8 @@ function connectToHost(lock) {
|
|
|
5841
5873
|
}
|
|
5842
5874
|
|
|
5843
5875
|
// packages/cli/src/doctor.ts
|
|
5844
|
-
import
|
|
5845
|
-
import
|
|
5876
|
+
import fs19 from "fs";
|
|
5877
|
+
import path23 from "path";
|
|
5846
5878
|
import { execFile as execFile7 } from "child_process";
|
|
5847
5879
|
import { promisify as promisify5 } from "util";
|
|
5848
5880
|
init_env();
|
|
@@ -5982,10 +6014,10 @@ async function runDoctor(options) {
|
|
|
5982
6014
|
});
|
|
5983
6015
|
}
|
|
5984
6016
|
try {
|
|
5985
|
-
|
|
5986
|
-
const probe =
|
|
5987
|
-
|
|
5988
|
-
|
|
6017
|
+
fs19.mkdirSync(options.userDataDir, { recursive: true });
|
|
6018
|
+
const probe = path23.join(options.userDataDir, `.doctor-${process.pid}`);
|
|
6019
|
+
fs19.writeFileSync(probe, "");
|
|
6020
|
+
fs19.rmSync(probe);
|
|
5989
6021
|
checks.push({ id: "data", name: "\u8CC7\u6599\u76EE\u9304", level: "ok", detail: options.userDataDir });
|
|
5990
6022
|
} catch (err) {
|
|
5991
6023
|
checks.push({
|
|
@@ -6039,24 +6071,24 @@ Options:
|
|
|
6039
6071
|
`.trim();
|
|
6040
6072
|
function detectLayout() {
|
|
6041
6073
|
const file = fileURLToPath(import.meta.url);
|
|
6042
|
-
const here =
|
|
6043
|
-
const bundledWeb =
|
|
6044
|
-
if (isWebDir(bundledWeb) ||
|
|
6074
|
+
const here = path26.dirname(file);
|
|
6075
|
+
const bundledWeb = path26.join(here, "web");
|
|
6076
|
+
if (isWebDir(bundledWeb) || path26.basename(here) === "dist") {
|
|
6045
6077
|
return {
|
|
6046
|
-
version: readVersion(
|
|
6078
|
+
version: readVersion(path26.join(here, "..", "package.json")),
|
|
6047
6079
|
webDir: isWebDir(bundledWeb) ? bundledWeb : null,
|
|
6048
6080
|
sourceRoot: null,
|
|
6049
6081
|
cliEntry: file
|
|
6050
6082
|
};
|
|
6051
6083
|
}
|
|
6052
|
-
const root =
|
|
6084
|
+
const root = path26.resolve(here, "..", "..", "..");
|
|
6053
6085
|
const override = process.env.VIBEFLOW_WEB_DIR;
|
|
6054
|
-
const webDir = override && isWebDir(override) ? override : isWebDir(
|
|
6055
|
-
return { version: readVersion(
|
|
6086
|
+
const webDir = override && isWebDir(override) ? override : isWebDir(path26.join(root, "app")) ? path26.join(root, "app") : null;
|
|
6087
|
+
return { version: readVersion(path26.join(root, "package.json")), webDir, sourceRoot: root, cliEntry: null };
|
|
6056
6088
|
}
|
|
6057
6089
|
function readVersion(pkgPath) {
|
|
6058
6090
|
try {
|
|
6059
|
-
return JSON.parse(
|
|
6091
|
+
return JSON.parse(fs21.readFileSync(pkgPath, "utf8")).version;
|
|
6060
6092
|
} catch {
|
|
6061
6093
|
return "0.0.0";
|
|
6062
6094
|
}
|
|
@@ -6262,8 +6294,8 @@ async function cmdOpen(values, target, layout, userDataDir) {
|
|
|
6262
6294
|
console.error("\u7528\u6CD5\uFF1Avibeflow open <path>");
|
|
6263
6295
|
return 1;
|
|
6264
6296
|
}
|
|
6265
|
-
const dir =
|
|
6266
|
-
if (!
|
|
6297
|
+
const dir = path26.resolve(target);
|
|
6298
|
+
if (!fs21.existsSync(dir) || !fs21.statSync(dir).isDirectory()) {
|
|
6267
6299
|
console.error(`\u4E0D\u662F\u8CC7\u6599\u593E\uFF1A${dir}`);
|
|
6268
6300
|
return 1;
|
|
6269
6301
|
}
|
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/c380333c2873a2b8.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c380333c2873a2b8.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-c8aa5df0425f6b7b.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/c380333c2873a2b8.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c380333c2873a2b8.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-c8aa5df0425f6b7b.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-014e95fe86cd1d39.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/lyOZoF78HzRwmQ3DYf88f/_buildManifest.js" defer=""></script><script src="/_next/static/lyOZoF78HzRwmQ3DYf88f/_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":"lyOZoF78HzRwmQ3DYf88f","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/c380333c2873a2b8.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c380333c2873a2b8.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-c8aa5df0425f6b7b.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/c380333c2873a2b8.css" as="style"/><link rel="stylesheet" href="/_next/static/css/c380333c2873a2b8.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-c8aa5df0425f6b7b.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-014e95fe86cd1d39.js" defer=""></script><script src="/_next/static/chunks/pages/_error-8f65b0f8749f42d2.js" defer=""></script><script src="/_next/static/lyOZoF78HzRwmQ3DYf88f/_buildManifest.js" defer=""></script><script src="/_next/static/lyOZoF78HzRwmQ3DYf88f/_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":"lyOZoF78HzRwmQ3DYf88f","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|