@kw-yeh/vibeflow 4.2.0 → 4.3.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 +171 -80
- package/dist/web/404/index.html +1 -1
- package/dist/web/404.html +1 -1
- package/dist/web/_next/static/{lyOZoF78HzRwmQ3DYf88f → _pjqayPqD9pDyPeTbc6L2}/_buildManifest.js +1 -1
- package/dist/web/_next/static/chunks/{8833-76c31db372a29bb8.js → 2524-abaf3a55023f6066.js} +2 -2
- package/dist/web/_next/static/chunks/pages/home-1fb1d1a49d28f6dd.js +12 -0
- package/dist/web/_next/static/css/{c380333c2873a2b8.css → 24b804d01aa3af3c.css} +1 -1
- package/dist/web/home/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/_next/static/chunks/pages/home-e692e9e0783d2fdf.js +0 -11
- /package/dist/web/_next/static/{lyOZoF78HzRwmQ3DYf88f → _pjqayPqD9pDyPeTbc6L2}/_ssgManifest.js +0 -0
package/dist/vibeflow.mjs
CHANGED
|
@@ -555,14 +555,17 @@ ${entry}
|
|
|
555
555
|
}
|
|
556
556
|
}
|
|
557
557
|
function writeAttachments(worktreePath, inputs) {
|
|
558
|
+
if (inputs.length === 0) return [];
|
|
559
|
+
ensureAttachmentExclude(worktreePath);
|
|
560
|
+
return writeAttachmentsTo(path10.join(worktreePath, ATTACHMENTS_DIR), inputs);
|
|
561
|
+
}
|
|
562
|
+
function writeAttachmentsTo(attachmentDir, inputs) {
|
|
558
563
|
if (inputs.length === 0) return [];
|
|
559
564
|
const decodedInputs = inputs.map((input) => ({
|
|
560
565
|
input,
|
|
561
566
|
name: safeAttachmentName(input.name),
|
|
562
567
|
bytes: decodeAttachment(input)
|
|
563
568
|
}));
|
|
564
|
-
ensureAttachmentExclude(worktreePath);
|
|
565
|
-
const attachmentDir = path10.join(worktreePath, ATTACHMENTS_DIR);
|
|
566
569
|
fs6.mkdirSync(attachmentDir, { recursive: true });
|
|
567
570
|
return decodedInputs.map(({ input, name, bytes }) => {
|
|
568
571
|
const id = randomUUID().slice(0, 8);
|
|
@@ -607,7 +610,6 @@ function newFormState(defaultAutoMode, agents) {
|
|
|
607
610
|
const agentCli = agents && agents.length > 0 && !agents.some((a) => a.id === "claude") ? agents[0].id : "claude";
|
|
608
611
|
return {
|
|
609
612
|
mode: "new",
|
|
610
|
-
launched: false,
|
|
611
613
|
title: "",
|
|
612
614
|
description: "",
|
|
613
615
|
projectPath: null,
|
|
@@ -627,11 +629,11 @@ function editFormState(task, defaultAutoMode) {
|
|
|
627
629
|
return {
|
|
628
630
|
mode: "edit",
|
|
629
631
|
taskId: task.id,
|
|
630
|
-
launched: Boolean(task.launchedAt),
|
|
631
632
|
title: task.title,
|
|
632
633
|
description: task.description ?? "",
|
|
633
634
|
projectPath: task.projectPath ?? null,
|
|
634
635
|
originalProjectPath: task.projectPath ?? null,
|
|
636
|
+
worktreePath: task.worktreePath,
|
|
635
637
|
gitInfo: null,
|
|
636
638
|
gitInfoPath: null,
|
|
637
639
|
baseBranch: task.baseBranch ?? "",
|
|
@@ -662,8 +664,8 @@ function visibleFields(s, ctx) {
|
|
|
662
664
|
return fields2;
|
|
663
665
|
}
|
|
664
666
|
const fields = ["title", "description", "effort", "autoMode", "project"];
|
|
665
|
-
if (
|
|
666
|
-
fields.push("agent", "model", "submit");
|
|
667
|
+
if (isRepo && hasRemote) fields.push("baseBranch");
|
|
668
|
+
fields.push("branch", "agent", "model", "submit");
|
|
667
669
|
return fields;
|
|
668
670
|
}
|
|
669
671
|
function modelOptions(ctx, agentCli, current) {
|
|
@@ -712,7 +714,8 @@ function updatePayload(s) {
|
|
|
712
714
|
model: s.model || void 0,
|
|
713
715
|
effort: s.effort,
|
|
714
716
|
autoMode: s.autoMode,
|
|
715
|
-
|
|
717
|
+
...s.projectPath ? { projectPath: s.projectPath, baseBranch: s.baseBranch || null } : {},
|
|
718
|
+
branch: s.branch.trim()
|
|
716
719
|
};
|
|
717
720
|
}
|
|
718
721
|
function editorCommand(env, platform) {
|
|
@@ -754,16 +757,20 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
754
757
|
const lookup = useRef(0);
|
|
755
758
|
const fields = visibleFields(s, ctx);
|
|
756
759
|
const field = fields[Math.min(focus, fields.length - 1)];
|
|
757
|
-
const projectLocked = s.mode === "edit" && s.launched;
|
|
758
760
|
const missing = isProjectMissing(ctx.recent, s.projectPath);
|
|
759
761
|
useEffect(() => {
|
|
760
|
-
if (!s.projectPath || missing || s.gitInfoPath === s.projectPath
|
|
762
|
+
if (!s.projectPath || missing || s.gitInfoPath === s.projectPath) return;
|
|
761
763
|
const target = s.projectPath;
|
|
762
764
|
const id = ++lookup.current;
|
|
763
765
|
setLoadingGit(true);
|
|
764
766
|
void api.getGitInfo(target).then((info) => {
|
|
765
767
|
if (id !== lookup.current) return;
|
|
766
|
-
setS((prev) => ({
|
|
768
|
+
setS((prev) => ({
|
|
769
|
+
...prev,
|
|
770
|
+
gitInfo: info,
|
|
771
|
+
gitInfoPath: target,
|
|
772
|
+
baseBranch: prev.mode === "edit" && target === prev.originalProjectPath && prev.baseBranch ? prev.baseBranch : info.defaultBase ?? ""
|
|
773
|
+
}));
|
|
767
774
|
}).catch((err) => id === lookup.current && setMessage(`\u5075\u6E2C Git \u5931\u6557\uFF1A${err.message}`)).finally(() => id === lookup.current && setLoadingGit(false));
|
|
768
775
|
}, [s.projectPath]);
|
|
769
776
|
const leave = (result) => {
|
|
@@ -771,7 +778,6 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
771
778
|
exit();
|
|
772
779
|
};
|
|
773
780
|
const setProject = (projectPath) => {
|
|
774
|
-
if (projectLocked) return;
|
|
775
781
|
setS((prev) => ({ ...prev, projectPath, gitInfo: null, gitInfoPath: null, baseBranch: "" }));
|
|
776
782
|
};
|
|
777
783
|
const submit = async () => {
|
|
@@ -833,7 +839,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
833
839
|
if (key.downArrow || key.tab) return setFocus((f) => Math.min(fields.length - 1, f + 1));
|
|
834
840
|
const step = key.leftArrow ? -1 : key.rightArrow ? 1 : 0;
|
|
835
841
|
if (step) {
|
|
836
|
-
if (field === "project"
|
|
842
|
+
if (field === "project") {
|
|
837
843
|
const paths = ctx.recent.map((p) => p.path);
|
|
838
844
|
if (paths.length) setProject(cycle(paths, s.projectPath ?? paths[paths.length - 1], step));
|
|
839
845
|
} else if (field === "baseBranch") {
|
|
@@ -859,7 +865,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
859
865
|
void api.initRepository(s.projectPath).then((info) => setS((prev) => ({ ...prev, gitInfo: info, gitInfoPath: prev.projectPath, baseBranch: info.defaultBase ?? "" }))).catch((err) => setMessage(err.message)).finally(() => setBusy(null));
|
|
860
866
|
return;
|
|
861
867
|
}
|
|
862
|
-
if (TEXT_FIELDS.includes(field)
|
|
868
|
+
if (TEXT_FIELDS.includes(field)) {
|
|
863
869
|
setEditing(field);
|
|
864
870
|
setDraft(field === "title" ? s.title : field === "branch" ? s.branch : field === "project" ? s.projectPath ?? "" : "");
|
|
865
871
|
}
|
|
@@ -870,7 +876,6 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
870
876
|
case "title":
|
|
871
877
|
return s.title || "\uFF08\u4F8B\u5982\uFF1A\u5BE6\u4F5C\u767B\u5165\u9801\u9762\uFF09";
|
|
872
878
|
case "project": {
|
|
873
|
-
if (projectLocked) return `${s.projectPath ? path24.basename(s.projectPath) : "\u2014"}\uFF08\u4EFB\u52D9\u5DF2\u958B\u59CB\uFF0C\u9396\u5B9A\uFF09`;
|
|
874
879
|
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
880
|
return `${s.projectPath}${missing ? "\uFF08\u8DEF\u5F91\u907A\u5931\uFF09" : ""}`;
|
|
876
881
|
}
|
|
@@ -906,15 +911,18 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
906
911
|
};
|
|
907
912
|
const note = () => {
|
|
908
913
|
const info = s.gitInfo;
|
|
909
|
-
if (field === "project"
|
|
914
|
+
if (field === "project") {
|
|
910
915
|
if (loadingGit) return "\u5075\u6E2C Git \u72C0\u614B\u4E2D\u2026";
|
|
911
916
|
if (missing) return `\u627E\u4E0D\u5230 ${s.projectPath}\uFF0C\u5C08\u6848\u53EF\u80FD\u5DF2\u88AB\u79FB\u52D5\u6216\u522A\u9664\u3002`;
|
|
912
917
|
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
|
-
if (s.mode === "edit" && projectChanged(s)) return "\
|
|
918
|
+
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";
|
|
914
919
|
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
920
|
if (info?.isRepo && s.projectPath) return `worktree \u6703\u5EFA\u5728 ${ctx.workstationPath || "~/Desktop"}/${path24.basename(s.projectPath)}`;
|
|
916
921
|
}
|
|
917
|
-
if (field === "branch")
|
|
922
|
+
if (field === "branch") {
|
|
923
|
+
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";
|
|
924
|
+
return s.mode === "edit" && s.worktreePath ? `${when} \u9019\u5F35\u5361\u5DF2\u6709 worktree\uFF1A\u66F4\u6539\u5206\u652F\u3001\u5C08\u6848\u6216\u57FA\u6E96\u5206\u652F\u6703\u79FB\u9664\u5B83\uFF08\u6709\u672A\u5B8C\u6210\u8B8A\u66F4\u6642\u7121\u6CD5\u5132\u5B58\uFF09\u3002` : when;
|
|
925
|
+
}
|
|
918
926
|
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`;
|
|
919
927
|
if (field === "autoMode") return s.autoMode ? "\u958B\u555F\uFF1AAgent \u6703\u76F4\u63A5\u4FEE\u6539\u6A94\u6848\u3001\u57F7\u884C\u6307\u4EE4\uFF0C\u4E0D\u6703\u9010\u6B21\u5411\u4F60\u78BA\u8A8D\u3002" : "\u95DC\u9589\uFF1AAgent \u6BCF\u6B21\u8981\u52D5\u4F5C\u524D\uFF0C\u90FD\u6703\u5728\u7D42\u7AEF\u6A5F\u88E1\u7B49\u4F60\u5141\u8A31\u3002";
|
|
920
928
|
if (field === "submit") return blockReason(s, ctx, loadingGit);
|
|
@@ -1130,6 +1138,9 @@ function BoardView({ opts, initial, initialMessage, onAction }) {
|
|
|
1130
1138
|
}
|
|
1131
1139
|
setSel({ column: sel.column + direction, index: 0 });
|
|
1132
1140
|
if (move.effect === "launch") {
|
|
1141
|
+
if (!move.task.worktreePath) {
|
|
1142
|
+
setMessage(`\u6B63\u5728\u70BA\u300C${move.task.title}\u300D\u5F9E\u6700\u65B0\u7684 ${move.task.baseBranch ?? "\u57FA\u6E96\u5206\u652F"} \u5EFA\u7ACB\u5206\u652F ${move.task.branch} \u8207 worktree\uFF0C\u9700\u8981\u5E7E\u79D2\u9418\u2026`);
|
|
1143
|
+
}
|
|
1133
1144
|
await api.term.start({ taskId: move.task.id, launch: {} });
|
|
1134
1145
|
setMessage(`\u5DF2\u555F\u52D5\u300C${move.task.title}\u300D\u7684 agent\u3002Enter \u53EF\u9032\u5165\u7D42\u7AEF\u3002`);
|
|
1135
1146
|
} else if (move.effect === "cleanup") {
|
|
@@ -1189,8 +1200,14 @@ function BoardView({ opts, initial, initialMessage, onAction }) {
|
|
|
1189
1200
|
return;
|
|
1190
1201
|
}
|
|
1191
1202
|
if (!selected) return;
|
|
1192
|
-
if (input === "e")
|
|
1203
|
+
if (input === "e") {
|
|
1204
|
+
if (COLUMNS2[sel.column] !== "backlog") return setMessage("\u57F7\u884C\u4E2D\u8207\u5DF2\u5B8C\u6210\u7684\u5361\u7247\u53EA\u80FD\u67E5\u770B\uFF0C\u7121\u6CD5\u7DE8\u8F2F");
|
|
1205
|
+
return leave({ type: "edit", task: selected });
|
|
1206
|
+
}
|
|
1193
1207
|
if (key.return) {
|
|
1208
|
+
if (!selected.worktreePath && COLUMNS2[sel.column] === "backlog") {
|
|
1209
|
+
return setMessage("\u9019\u5F35\u5361\u5C1A\u672A\u958B\u59CB\u57F7\u884C\uFF0C\u5206\u652F\u8207 worktree \u6703\u5728\u958B\u59CB\u6642\u5EFA\u7ACB");
|
|
1210
|
+
}
|
|
1194
1211
|
if (!selected.worktreePath && !selected.projectPath) return setMessage("\u9019\u5F35\u5361\u6C92\u6709\u5DE5\u4F5C\u76EE\u9304");
|
|
1195
1212
|
if (COLUMNS2[sel.column] === "done") return setMessage("\u5DF2\u5B8C\u6210\u7684\u5361\u7247\u6C92\u6709\u7D42\u7AEF");
|
|
1196
1213
|
return leave({ type: "attach", task: selected });
|
|
@@ -3200,6 +3217,9 @@ import { join as join2 } from "path";
|
|
|
3200
3217
|
function projectWorkstationPath(workstationRoot, projectName) {
|
|
3201
3218
|
return join2(workstationRoot, projectName);
|
|
3202
3219
|
}
|
|
3220
|
+
function taskAttachmentStagingPath(workspacePath, taskId) {
|
|
3221
|
+
return join2(workspacePath, ".attachments", taskId);
|
|
3222
|
+
}
|
|
3203
3223
|
|
|
3204
3224
|
// packages/core/src/agents.ts
|
|
3205
3225
|
init_env();
|
|
@@ -3278,25 +3298,21 @@ async function createTaskFromInput(input) {
|
|
|
3278
3298
|
if (explicitBranch) {
|
|
3279
3299
|
await assertBranchAvailable(projectPath, workspacePath, explicitBranch);
|
|
3280
3300
|
}
|
|
3281
|
-
const
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
);
|
|
3297
|
-
}
|
|
3298
|
-
const attachments = writeAttachments(
|
|
3299
|
-
provisionResult.worktreePath,
|
|
3301
|
+
const branch = explicitBranch ?? await generateBranchName(input.title, input.description);
|
|
3302
|
+
const draft = {
|
|
3303
|
+
id: taskId,
|
|
3304
|
+
title: input.title.trim() || `Task ${taskId}`,
|
|
3305
|
+
branch: branch ?? fallbackBranchName(taskId),
|
|
3306
|
+
branchExplicit: explicitBranch ? true : void 0,
|
|
3307
|
+
projectPath,
|
|
3308
|
+
projectName,
|
|
3309
|
+
workspacePath,
|
|
3310
|
+
baseBranch: input.baseBranch || info.defaultBase || info.currentBranch || void 0
|
|
3311
|
+
};
|
|
3312
|
+
const col = input.status ?? "backlog";
|
|
3313
|
+
const provisioned = col === "backlog" ? null : await provisionTaskWorktree(draft);
|
|
3314
|
+
const attachments = provisioned?.worktreePath ? writeAttachments(provisioned.worktreePath, input.attachments ?? []) : writeAttachmentsTo(
|
|
3315
|
+
taskAttachmentStagingPath(workspacePath, taskId),
|
|
3300
3316
|
input.attachments ?? []
|
|
3301
3317
|
);
|
|
3302
3318
|
const attachmentLines = attachments.map(
|
|
@@ -3305,16 +3321,9 @@ async function createTaskFromInput(input) {
|
|
|
3305
3321
|
const baseDescription = input.description?.trim();
|
|
3306
3322
|
const description = attachmentLines.length ? [baseDescription, attachmentLines.join("\n")].filter(Boolean).join("\n\n") : baseDescription || void 0;
|
|
3307
3323
|
const task = {
|
|
3308
|
-
|
|
3309
|
-
|
|
3324
|
+
...draft,
|
|
3325
|
+
...provisioned,
|
|
3310
3326
|
description,
|
|
3311
|
-
branch: provisionResult.branch,
|
|
3312
|
-
projectPath,
|
|
3313
|
-
projectName,
|
|
3314
|
-
worktreePath: provisionResult.worktreePath,
|
|
3315
|
-
workspacePath,
|
|
3316
|
-
baseBranch: provisionResult.baseBranch,
|
|
3317
|
-
pushed: provisionResult.pushed,
|
|
3318
3327
|
createdAt: Date.now(),
|
|
3319
3328
|
agentCli: input.agentCli ?? "claude",
|
|
3320
3329
|
model: input.model || void 0,
|
|
@@ -3323,7 +3332,6 @@ async function createTaskFromInput(input) {
|
|
|
3323
3332
|
};
|
|
3324
3333
|
try {
|
|
3325
3334
|
const board = store.get("board");
|
|
3326
|
-
const col = input.status ?? "backlog";
|
|
3327
3335
|
board[col] = [task, ...board[col]];
|
|
3328
3336
|
store.set("board", board);
|
|
3329
3337
|
recordRecentProject(store, projectPath);
|
|
@@ -3335,6 +3343,38 @@ async function createTaskFromInput(input) {
|
|
|
3335
3343
|
}
|
|
3336
3344
|
return { task, storePath: store.path };
|
|
3337
3345
|
}
|
|
3346
|
+
async function provisionTaskWorktree(task) {
|
|
3347
|
+
if (!task.projectPath || !task.workspacePath) {
|
|
3348
|
+
throw Object.assign(new Error("\u4EFB\u52D9\u6C92\u6709\u5C08\u6848\u8CC7\u6599\u593E\uFF0C\u7121\u6CD5\u5EFA\u7ACB worktree"), {
|
|
3349
|
+
code: "WORKTREE_CREATE_FAILED"
|
|
3350
|
+
});
|
|
3351
|
+
}
|
|
3352
|
+
await fs9.mkdir(task.workspacePath, { recursive: true });
|
|
3353
|
+
if (task.branchExplicit) {
|
|
3354
|
+
await assertBranchAvailable(task.projectPath, task.workspacePath, task.branch);
|
|
3355
|
+
}
|
|
3356
|
+
try {
|
|
3357
|
+
const result = await provisionWorktree(
|
|
3358
|
+
task.projectPath,
|
|
3359
|
+
task.workspacePath,
|
|
3360
|
+
task.id,
|
|
3361
|
+
task.baseBranch ?? null,
|
|
3362
|
+
task.branch,
|
|
3363
|
+
{ explicitBranch: task.branchExplicit === true }
|
|
3364
|
+
);
|
|
3365
|
+
return {
|
|
3366
|
+
branch: result.branch,
|
|
3367
|
+
worktreePath: result.worktreePath,
|
|
3368
|
+
baseBranch: result.baseBranch,
|
|
3369
|
+
pushed: result.pushed
|
|
3370
|
+
};
|
|
3371
|
+
} catch (err) {
|
|
3372
|
+
throw Object.assign(
|
|
3373
|
+
new Error(`Worktree \u5EFA\u7ACB\u5931\u6557\uFF1A${err.message}`),
|
|
3374
|
+
{ code: "WORKTREE_CREATE_FAILED" }
|
|
3375
|
+
);
|
|
3376
|
+
}
|
|
3377
|
+
}
|
|
3338
3378
|
function updateTaskFromInput(input) {
|
|
3339
3379
|
const store = input.storePath ? getStoreAtPath(input.storePath) : getStore();
|
|
3340
3380
|
const board = store.get("board");
|
|
@@ -3521,7 +3561,7 @@ async function taskCommand(argv) {
|
|
|
3521
3561
|
title: task2.title,
|
|
3522
3562
|
description: task2.description,
|
|
3523
3563
|
branch: task2.branch,
|
|
3524
|
-
worktreePath: task2.worktreePath
|
|
3564
|
+
worktreePath: task2.worktreePath ?? null
|
|
3525
3565
|
}
|
|
3526
3566
|
};
|
|
3527
3567
|
}
|
|
@@ -3563,7 +3603,7 @@ async function taskCommand(argv) {
|
|
|
3563
3603
|
title: task.title,
|
|
3564
3604
|
projectPath: task.projectPath,
|
|
3565
3605
|
branch: task.branch,
|
|
3566
|
-
worktreePath: task.worktreePath,
|
|
3606
|
+
worktreePath: task.worktreePath ?? null,
|
|
3567
3607
|
baseBranch: task.baseBranch,
|
|
3568
3608
|
agentCli: task.agentCli,
|
|
3569
3609
|
model: task.model,
|
|
@@ -5000,6 +5040,45 @@ function createCore({ sessions, bus, version }) {
|
|
|
5000
5040
|
deleteArtifacts(task.workspacePath ?? path20.dirname(task.worktreePath), task.worktreePath);
|
|
5001
5041
|
await deleteBranch(task.projectPath, branch);
|
|
5002
5042
|
}
|
|
5043
|
+
function columnOf(taskId) {
|
|
5044
|
+
const board = getState().board;
|
|
5045
|
+
return COLUMNS.find((col) => board[col].some((t) => t.id === taskId)) ?? null;
|
|
5046
|
+
}
|
|
5047
|
+
const provisioning = /* @__PURE__ */ new Map();
|
|
5048
|
+
function ensureProvisioned(task) {
|
|
5049
|
+
if (task.worktreePath) return Promise.resolve(task);
|
|
5050
|
+
const pending = provisioning.get(task.id);
|
|
5051
|
+
if (pending) return pending;
|
|
5052
|
+
const run2 = (async () => {
|
|
5053
|
+
try {
|
|
5054
|
+
updateTask(task.id, { ...await provisionTaskWorktree(task), launchError: void 0 });
|
|
5055
|
+
bus.emit("state:changed", getState());
|
|
5056
|
+
} catch (err) {
|
|
5057
|
+
returnUnstarted(task.id, err.message);
|
|
5058
|
+
throw err;
|
|
5059
|
+
}
|
|
5060
|
+
const provisioned = findTask(task.id);
|
|
5061
|
+
if (!provisioned) throw new Error("\u627E\u4E0D\u5230\u8981\u57F7\u884C\u7684\u4EFB\u52D9");
|
|
5062
|
+
return provisioned;
|
|
5063
|
+
})().finally(() => provisioning.delete(task.id));
|
|
5064
|
+
provisioning.set(task.id, run2);
|
|
5065
|
+
return run2;
|
|
5066
|
+
}
|
|
5067
|
+
function returnUnstarted(taskId, launchError) {
|
|
5068
|
+
const current = findTask(taskId);
|
|
5069
|
+
if (!current) return;
|
|
5070
|
+
const board = getState().board;
|
|
5071
|
+
const next = {
|
|
5072
|
+
backlog: [
|
|
5073
|
+
{ ...current, launchedAt: void 0, launchError },
|
|
5074
|
+
...board.backlog.filter((t) => t.id !== taskId)
|
|
5075
|
+
],
|
|
5076
|
+
in_progress: board.in_progress.filter((t) => t.id !== taskId),
|
|
5077
|
+
done: board.done.filter((t) => t.id !== taskId)
|
|
5078
|
+
};
|
|
5079
|
+
setBoard(next);
|
|
5080
|
+
bus.emit("state:changed", getState());
|
|
5081
|
+
}
|
|
5003
5082
|
const handlers = {
|
|
5004
5083
|
"vibeflow:getState": () => getState(),
|
|
5005
5084
|
"app:getVersion": () => version,
|
|
@@ -5073,7 +5152,13 @@ function createCore({ sessions, bus, version }) {
|
|
|
5073
5152
|
// were new. Launching again is the caller's decision.
|
|
5074
5153
|
"vibeflow:resetTaskRun": async (taskId) => {
|
|
5075
5154
|
const task = requireTask(taskId);
|
|
5076
|
-
if (!task.worktreePath)
|
|
5155
|
+
if (!task.worktreePath) {
|
|
5156
|
+
await teardownTask(task.id);
|
|
5157
|
+
updateTask(task.id, { launchedAt: Date.now(), runId: randomUUID4() });
|
|
5158
|
+
const reset2 = findTask(task.id);
|
|
5159
|
+
if (!reset2) throw new Error("\u627E\u4E0D\u5230\u8981\u91CD\u7F6E\u7684\u4EFB\u52D9");
|
|
5160
|
+
return { state: getState(), task: reset2 };
|
|
5161
|
+
}
|
|
5077
5162
|
if (!task.baseBranch) throw new Error("\u4EFB\u52D9\u6C92\u6709\u8A18\u9304 base branch\uFF0C\u7121\u6CD5\u9084\u539F worktree");
|
|
5078
5163
|
await teardownTask(task.id);
|
|
5079
5164
|
await resetWorktreeToBase(task.worktreePath, task.baseBranch);
|
|
@@ -5087,21 +5172,25 @@ function createCore({ sessions, bus, version }) {
|
|
|
5087
5172
|
bus.emit("subagents:update", { taskId: task.id, subAgents: [] });
|
|
5088
5173
|
return { state: getState(), task: reset };
|
|
5089
5174
|
},
|
|
5090
|
-
// Edit an existing card's fields.
|
|
5091
|
-
//
|
|
5092
|
-
//
|
|
5093
|
-
//
|
|
5175
|
+
// Edit an existing card's fields. Only a Backlog card is editable: once it
|
|
5176
|
+
// runs, what it was asked to do and where it does it are history. The
|
|
5177
|
+
// git-bound fields (project, base, branch) are just stored — the worktree is
|
|
5178
|
+
// built when the card starts. A Backlog card that already has one (made
|
|
5179
|
+
// before provisioning moved to launch, or returned from a run) gives it up,
|
|
5180
|
+
// but only while it holds no changes.
|
|
5094
5181
|
"vibeflow:updateTask": async (payload) => {
|
|
5095
5182
|
const p = obj(payload, "payload");
|
|
5096
5183
|
const existing = requireTask(p.taskId);
|
|
5184
|
+
if (columnOf(existing.id) !== "backlog") {
|
|
5185
|
+
throw new Error("\u53EA\u6709 Backlog \u7684\u4EFB\u52D9\u53EF\u4EE5\u7DE8\u8F2F");
|
|
5186
|
+
}
|
|
5097
5187
|
let gitPatch = {};
|
|
5098
5188
|
const nextProject = p.projectPath || existing.projectPath;
|
|
5189
|
+
const nextBranch = p.branch === void 0 ? "" : str(p.branch, "branch").trim();
|
|
5099
5190
|
const projectChanged2 = Boolean(p.projectPath && p.projectPath !== existing.projectPath);
|
|
5100
5191
|
const baseChanged = p.baseBranch != null && p.baseBranch !== (existing.baseBranch ?? null);
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
throw new Error("\u4EFB\u52D9\u5DF2\u958B\u59CB\u57F7\u884C\uFF0C\u7121\u6CD5\u66F4\u63DB\u5C08\u6848\u8CC7\u6599\u593E\u6216\u57FA\u6E96\u5206\u652F");
|
|
5104
|
-
}
|
|
5192
|
+
const branchChanged = Boolean(nextBranch && nextBranch !== existing.branch);
|
|
5193
|
+
if (nextProject && (projectChanged2 || baseChanged || branchChanged)) {
|
|
5105
5194
|
if (existing.worktreePath) {
|
|
5106
5195
|
const diff = await getWorktreeDiffEntries(
|
|
5107
5196
|
existing.worktreePath,
|
|
@@ -5109,35 +5198,30 @@ function createCore({ sessions, bus, version }) {
|
|
|
5109
5198
|
{ fetch: false }
|
|
5110
5199
|
);
|
|
5111
5200
|
if (diff.length > 0) {
|
|
5112
|
-
throw new Error("\u76EE\u524D worktree \u5DF2\u6709\u8B8A\u66F4\uFF0C\u7121\u6CD5\u66F4\u63DB\u5C08\u6848\u8CC7\u6599\u593E\
|
|
5201
|
+
throw new Error("\u76EE\u524D worktree \u5DF2\u6709\u8B8A\u66F4\uFF0C\u7121\u6CD5\u66F4\u63DB\u5C08\u6848\u8CC7\u6599\u593E\u3001\u57FA\u6E96\u5206\u652F\u6216\u5206\u652F\u540D\u7A31");
|
|
5113
5202
|
}
|
|
5114
5203
|
}
|
|
5115
5204
|
const info = await getGitInfo(nextProject);
|
|
5116
5205
|
if (!info.isRepo) throw new Error("\u76EE\u6A19\u8CC7\u6599\u593E\u4E0D\u662F git repository");
|
|
5117
|
-
await teardownTask(existing.id);
|
|
5118
|
-
await removeTaskWorktree(existing);
|
|
5119
5206
|
const projectName = path20.basename(nextProject);
|
|
5120
5207
|
const workspacePath = projectWorkstationPath(resolveWorkstationPath(getSettings()), projectName);
|
|
5121
|
-
await
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
workspacePath,
|
|
5125
|
-
existing.id,
|
|
5126
|
-
p.baseBranch ?? existing.baseBranch ?? null,
|
|
5127
|
-
existing.branch
|
|
5128
|
-
);
|
|
5208
|
+
await teardownTask(existing.id);
|
|
5209
|
+
await removeTaskWorktree(existing);
|
|
5210
|
+
if (branchChanged) await assertBranchAvailable(nextProject, workspacePath, nextBranch);
|
|
5129
5211
|
recordRecentProject(getStore(), nextProject);
|
|
5130
5212
|
gitPatch = {
|
|
5131
5213
|
projectPath: nextProject,
|
|
5132
5214
|
projectName,
|
|
5133
|
-
branch: result.branch,
|
|
5134
|
-
worktreePath: result.worktreePath,
|
|
5135
5215
|
workspacePath,
|
|
5136
|
-
baseBranch:
|
|
5137
|
-
|
|
5216
|
+
baseBranch: (p.baseBranch ?? (projectChanged2 ? null : existing.baseBranch)) || info.defaultBase || info.currentBranch || void 0,
|
|
5217
|
+
...branchChanged ? { branch: nextBranch, branchExplicit: true } : {},
|
|
5218
|
+
worktreePath: void 0,
|
|
5219
|
+
pushed: void 0,
|
|
5220
|
+
launchedAt: void 0
|
|
5138
5221
|
};
|
|
5139
5222
|
}
|
|
5140
5223
|
updateTask(existing.id, {
|
|
5224
|
+
launchError: void 0,
|
|
5141
5225
|
title: (p.title ?? "").trim() || `Task ${existing.id}`,
|
|
5142
5226
|
description: p.description?.trim() || void 0,
|
|
5143
5227
|
agentCli: p.agentCli,
|
|
@@ -5153,10 +5237,12 @@ function createCore({ sessions, bus, version }) {
|
|
|
5153
5237
|
// string or a cwd, so a connected client cannot run anything else.
|
|
5154
5238
|
"pty:start": async (payload) => {
|
|
5155
5239
|
const p = obj(payload, "payload");
|
|
5156
|
-
const
|
|
5157
|
-
const key = sessionKeyFor(
|
|
5158
|
-
const
|
|
5159
|
-
|
|
5240
|
+
const requested = requireTask(p.taskId);
|
|
5241
|
+
const key = sessionKeyFor(requested.id, p.sessionKey);
|
|
5242
|
+
const pending = provisioning.get(requested.id);
|
|
5243
|
+
const task = p.launch ? await ensureProvisioned(requested) : pending ? await pending : requested;
|
|
5244
|
+
const cwd = task.worktreePath;
|
|
5245
|
+
if (!cwd) throw new Error("\u4EFB\u52D9\u5C1A\u672A\u958B\u59CB\u57F7\u884C\uFF0C\u9084\u6C92\u6709 worktree");
|
|
5160
5246
|
let command;
|
|
5161
5247
|
let fresh = p.fresh === true;
|
|
5162
5248
|
if (p.launch) {
|
|
@@ -5260,7 +5346,7 @@ function createCore({ sessions, bus, version }) {
|
|
|
5260
5346
|
const task = requireTask(taskId);
|
|
5261
5347
|
const base = task.baseBranch ?? "main";
|
|
5262
5348
|
if (task.worktreePath) return readWorktreeSpecs(task.worktreePath, base);
|
|
5263
|
-
if (!task.projectPath) return [];
|
|
5349
|
+
if (!task.projectPath || !task.launchedAt) return [];
|
|
5264
5350
|
const changed = task.outcome?.files.filter((f) => f.status !== "D").map((f) => f.path);
|
|
5265
5351
|
return readBranchSpecs(task.projectPath, task.branch, base, changed);
|
|
5266
5352
|
},
|
|
@@ -5365,6 +5451,9 @@ function createCore({ sessions, bus, version }) {
|
|
|
5365
5451
|
deleteDecisions(task.workspacePath, decisionsKey(task.worktreePath, task.branch));
|
|
5366
5452
|
}
|
|
5367
5453
|
await removeTaskWorktree(task);
|
|
5454
|
+
if (task.workspacePath) {
|
|
5455
|
+
fs16.rmSync(taskAttachmentStagingPath(task.workspacePath, task.id), { recursive: true, force: true });
|
|
5456
|
+
}
|
|
5368
5457
|
clearConversation(task.id);
|
|
5369
5458
|
removeTask(task.id);
|
|
5370
5459
|
return getState();
|
|
@@ -5372,9 +5461,11 @@ function createCore({ sessions, bus, version }) {
|
|
|
5372
5461
|
"attachments:write": (payload) => {
|
|
5373
5462
|
const p = obj(payload, "payload");
|
|
5374
5463
|
const task = requireTask(p.taskId);
|
|
5375
|
-
if (!task.worktreePath) throw new Error("\u627E\u4E0D\u5230\u4EFB\u52D9 worktree");
|
|
5376
5464
|
if (!Array.isArray(p.attachments)) invalid("attachments must be an array");
|
|
5377
|
-
|
|
5465
|
+
const inputs = p.attachments;
|
|
5466
|
+
if (task.worktreePath) return writeAttachments(task.worktreePath, inputs);
|
|
5467
|
+
if (!task.workspacePath) throw new Error("\u627E\u4E0D\u5230\u4EFB\u52D9 worktree");
|
|
5468
|
+
return writeAttachmentsTo(taskAttachmentStagingPath(task.workspacePath, task.id), inputs);
|
|
5378
5469
|
},
|
|
5379
5470
|
"chat:load": (taskId) => loadConversation(requireTask(taskId).id),
|
|
5380
5471
|
"chat:cancel": (taskId) => {
|
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/
|
|
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/24b804d01aa3af3c.css" as="style"/><link rel="stylesheet" href="/_next/static/css/24b804d01aa3af3c.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/_pjqayPqD9pDyPeTbc6L2/_buildManifest.js" defer=""></script><script src="/_next/static/_pjqayPqD9pDyPeTbc6L2/_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":"_pjqayPqD9pDyPeTbc6L2","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/
|
|
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/24b804d01aa3af3c.css" as="style"/><link rel="stylesheet" href="/_next/static/css/24b804d01aa3af3c.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/_pjqayPqD9pDyPeTbc6L2/_buildManifest.js" defer=""></script><script src="/_next/static/_pjqayPqD9pDyPeTbc6L2/_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":"_pjqayPqD9pDyPeTbc6L2","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|
package/dist/web/_next/static/{lyOZoF78HzRwmQ3DYf88f → _pjqayPqD9pDyPeTbc6L2}/_buildManifest.js
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:0,errorRate:1e-4,numBits:0,numHashes:null,bitArray:[]},__routerFilterDynamic:{numItems:0,errorRate:1e-4,numBits:0,numHashes:null,bitArray:[]},"/_error":["static/chunks/pages/_error-8f65b0f8749f42d2.js"],"/home":["static/chunks/
|
|
1
|
+
self.__BUILD_MANIFEST={__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:0,errorRate:1e-4,numBits:0,numHashes:null,bitArray:[]},__routerFilterDynamic:{numItems:0,errorRate:1e-4,numBits:0,numHashes:null,bitArray:[]},"/_error":["static/chunks/pages/_error-8f65b0f8749f42d2.js"],"/home":["static/chunks/2524-abaf3a55023f6066.js","static/chunks/pages/home-1fb1d1a49d28f6dd.js"],sortedPages:["/_app","/_error","/home"]},self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|