@kw-yeh/vibeflow 4.11.14 → 4.11.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/vibeflow.mjs +146 -299
- package/dist/web/404/index.html +1 -1
- package/dist/web/404.html +1 -1
- package/dist/web/_next/static/{1gu-Md_jBIHwDpsGMC8AV → TTJDd4vO-NmQBjEis26sl}/_buildManifest.js +1 -1
- package/dist/web/_next/static/chunks/pages/home-a17a5a665f0aa6bd.js +13 -0
- package/dist/web/_next/static/css/3cafb8bddc730b60.css +2 -0
- package/dist/web/home/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/_next/static/chunks/pages/home-029b95a2ac77e4bc.js +0 -13
- package/dist/web/_next/static/css/60e89d492b3b3ef3.css +0 -2
- /package/dist/web/_next/static/{1gu-Md_jBIHwDpsGMC8AV → TTJDd4vO-NmQBjEis26sl}/_ssgManifest.js +0 -0
package/dist/vibeflow.mjs
CHANGED
|
@@ -514,16 +514,6 @@ function agentArtifactsDir(worktreePath, workspacePath) {
|
|
|
514
514
|
const ws = pathBasename(worktreePath);
|
|
515
515
|
return `${dir}/${ws}${ARTIFACTS_DIR_SUFFIX}`;
|
|
516
516
|
}
|
|
517
|
-
function buildArtifactPrompt(artifactsDir = ARTIFACTS_FALLBACK_DIR) {
|
|
518
|
-
return [
|
|
519
|
-
"Artifact \u8A2D\u5B9A\uFF08\u672C\u6B21 session \u5168\u7A0B\u9069\u7528\uFF09\uFF1A",
|
|
520
|
-
`1. \u672C\u4EFB\u52D9\u7684 Artifact \u8CC7\u6599\u593E\u662F ${artifactsDir}/\uFF1B\u9700\u8981\u4FDD\u5B58\u7D66\u4F7F\u7528\u8005\u7684\u9A57\u8B49\u8B49\u64DA\u6216\u5831\u544A\u6642\uFF0C\u8ACB\u5BEB\u5165\u6B64\u8CC7\u6599\u593E\uFF08\u4E0D\u5B58\u5728\u8ACB\u5EFA\u7ACB\uFF09\u3002`,
|
|
521
|
-
`2. \u4F7F\u7528\u8005\u6703\u5728 VibeFlow \u7684 Artifacts \u5206\u9801\u6AA2\u8996\u6839\u76EE\u9304\u5167\u5BB9\uFF1B\u53EA\u653E\u4F60\u6703\u4E3B\u52D5\u8ACB\u4F7F\u7528\u8005\u904E\u76EE\u7684\u6A94\u6848\u3002`,
|
|
522
|
-
`3. \u4F60\u81EA\u5DF1\u7684\u5DE5\u4F5C\u66AB\u5B58\uFF08\u4E00\u6B21\u6027 script\u3001log\u3001\u4E2D\u9593\u8F38\u51FA\u3001debug \u6A94\uFF09\u653E\u5728 ${artifactsDir}/${SCRATCH_DIR_NAME}/\u3002`,
|
|
523
|
-
`4. \u82E5\u5DE5\u5177\u5148\u8F38\u51FA\u5230 /tmp\u3001/private/tmp\u3001$TMPDIR \u6216 ~/Downloads\uFF0C\u8ACB\u628A\u6700\u7D42\u8981\u5448\u73FE\u7684\u6A94\u6848\u8907\u88FD\u5230 ${artifactsDir}/ \u4E26\u78BA\u8A8D\u5B58\u5728\u3002`,
|
|
524
|
-
"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"
|
|
525
|
-
].join("\n");
|
|
526
|
-
}
|
|
527
517
|
function claudePermissionFlag(autoMode) {
|
|
528
518
|
return autoMode ? ` --permission-mode ${AUTO_PERMISSION_MODE}` : "";
|
|
529
519
|
}
|
|
@@ -533,8 +523,9 @@ function shellQuote(s) {
|
|
|
533
523
|
function toShellPath(p) {
|
|
534
524
|
return p.replace(/\\/g, "/");
|
|
535
525
|
}
|
|
536
|
-
function boardEnvPrefix(task, opts) {
|
|
526
|
+
function boardEnvPrefix(task, opts, workspacePath) {
|
|
537
527
|
const board = opts?.boardCli;
|
|
528
|
+
const artifactsDir = agentArtifactsDir(task.worktreePath, workspacePath) ?? (task.worktreePath ? `${toShellPath(task.worktreePath)}/${ARTIFACTS_FALLBACK_DIR}` : void 0);
|
|
538
529
|
if (!board) return "";
|
|
539
530
|
const entries = [
|
|
540
531
|
["VIBEFLOW_TASK_ID", task.id],
|
|
@@ -544,7 +535,9 @@ function boardEnvPrefix(task, opts) {
|
|
|
544
535
|
["VIBEFLOW_STORE_DIR", board?.storeDir],
|
|
545
536
|
["VIBEFLOW_CLI", board?.cliPath],
|
|
546
537
|
["VIBEFLOW_CLI_LOADER", board?.loaderPath],
|
|
547
|
-
["VIBEFLOW_AUTO_MODE", opts?.autoMode ? "1" : "0"]
|
|
538
|
+
["VIBEFLOW_AUTO_MODE", opts?.autoMode ? "1" : "0"],
|
|
539
|
+
["VIBEFLOW_ARTIFACTS_DIR", artifactsDir],
|
|
540
|
+
["VIBEFLOW_SCRATCH_DIR", artifactsDir ? `${artifactsDir}/${SCRATCH_DIR_NAME}` : void 0]
|
|
548
541
|
];
|
|
549
542
|
const exports = entries.filter((entry) => Boolean(entry[1])).map(([key, value]) => `${key}=${shellQuote(toShellPath(value))}`);
|
|
550
543
|
return exports.length ? `export ${exports.join(" ")}; ` : "";
|
|
@@ -612,25 +605,22 @@ function assembleCommand(agent, systemPrompt, prompt, model, effort, opts, workt
|
|
|
612
605
|
const settings = ` --settings ${shellQuote(buildClaudeSettings(worktreePath))}`;
|
|
613
606
|
const addDir = workspacePath ? ` --add-dir ${shellQuote(toShellPath(workspacePath))}` : "";
|
|
614
607
|
const modelFlag = model ? ` --model ${model}` : "";
|
|
615
|
-
const effortFlag = effort ? ` --effort ${effort}` : "";
|
|
616
|
-
const
|
|
617
|
-
const libraryFlags = library ? ` --plugin-dir ${shellQuote(toShellPath(library.pluginDir))} --add-dir ${shellQuote(toShellPath(library.libraryDir))}` : "";
|
|
618
|
-
const flags = `--chrome${claudePermissionFlag(opts?.autoMode)}${modelFlag}${effortFlag}${settings}${addDir}${libraryFlags}`;
|
|
608
|
+
const effortFlag = effort && effort !== "auto" ? ` --effort ${effort}` : "";
|
|
609
|
+
const flags = `--chrome${claudePermissionFlag(opts?.autoMode)}${modelFlag}${effortFlag}${settings}${addDir}`;
|
|
619
610
|
const sysFlag = systemPrompt ? ` --append-system-prompt ${shellQuote(systemPrompt)}` : "";
|
|
620
611
|
const promptArg = prompt ? ` ${shellQuote(prompt)}` : "";
|
|
621
612
|
const tail = `${flags}${sysFlag}${promptArg}`;
|
|
622
613
|
cmd = sessionId && opts?.resume ? claudeResumeOrFresh(sessionId, worktreePath, tail) : `claude ${sessionId ? `--session-id ${sessionId} ` : opts?.resume ? "--continue " : ""}${tail}\r`;
|
|
623
614
|
} else {
|
|
624
615
|
const combined = [systemPrompt, prompt].filter(Boolean).join("\n\n");
|
|
625
|
-
const codexEffortFlag = effort ? `-c ${shellQuote(`model_reasoning_effort="${effort}"`)} ` : "";
|
|
626
|
-
const codexHome = opts?.library ? `CODEX_HOME=${shellQuote(toShellPath(opts.library.codexHome))} ` : "";
|
|
616
|
+
const codexEffortFlag = effort && effort !== "auto" ? `-c ${shellQuote(`model_reasoning_effort="${effort}"`)} ` : "";
|
|
627
617
|
const args = [
|
|
628
618
|
codexAutoFlag(opts?.autoMode).trim(),
|
|
629
619
|
codexEffortFlag.trim(),
|
|
630
620
|
model ? `--model ${model}` : "",
|
|
631
621
|
combined ? shellQuote(combined) : ""
|
|
632
622
|
].filter(Boolean);
|
|
633
|
-
cmd = `${
|
|
623
|
+
cmd = `${["codex", ...args].join(" ")}\r`;
|
|
634
624
|
}
|
|
635
625
|
if (cmd.length > 2e5) console.warn(`[VibeFlow] launch command is ${cmd.length} bytes \u2014 approaching ARG_MAX`);
|
|
636
626
|
return cmd;
|
|
@@ -647,16 +637,11 @@ function taskModel(task) {
|
|
|
647
637
|
function buildAgentCommand(task, systemPrompt, opts, workspacePath) {
|
|
648
638
|
const agent = taskAgent(task);
|
|
649
639
|
const model = taskModel(task);
|
|
650
|
-
const
|
|
651
|
-
const builtInPrompt = buildArtifactPrompt(artifactsDir);
|
|
652
|
-
const libraryPrompt = opts?.library?.promptText?.trim();
|
|
653
|
-
const customPrompt = resolveSystemPrompt(systemPrompt);
|
|
654
|
-
const sys = [builtInPrompt, libraryPrompt, customPrompt].filter(Boolean).join("\n\n");
|
|
640
|
+
const sys = resolveSystemPrompt(systemPrompt);
|
|
655
641
|
const includeTaskPrompt = opts?.includeTaskPrompt !== false;
|
|
656
|
-
const prompt = includeTaskPrompt && !opts?.resume ?
|
|
657
|
-
${opts.preflightPlan}` : ""].filter(Boolean).join("\n\n") : "";
|
|
642
|
+
const prompt = includeTaskPrompt && !opts?.resume ? buildPrompt(task) : "";
|
|
658
643
|
const sessionId = agent === "claude" && includeTaskPrompt ? executorSessionId(task.id, task.runId) : void 0;
|
|
659
|
-
return boardEnvPrefix(task, opts) + assembleCommand(
|
|
644
|
+
return boardEnvPrefix(task, opts, workspacePath) + assembleCommand(
|
|
660
645
|
agent,
|
|
661
646
|
sys,
|
|
662
647
|
prompt,
|
|
@@ -793,8 +778,8 @@ var init_attachments = __esm({
|
|
|
793
778
|
function modelFor(models, modelId) {
|
|
794
779
|
return modelId ? models?.find((m) => m.id === modelId) : models?.find((m) => m.isDefault);
|
|
795
780
|
}
|
|
796
|
-
function
|
|
797
|
-
return typeof value === "string" &&
|
|
781
|
+
function isManualEffort(value) {
|
|
782
|
+
return typeof value === "string" && MANUAL_EFFORTS.includes(value);
|
|
798
783
|
}
|
|
799
784
|
function allowedEfforts(model) {
|
|
800
785
|
return model?.efforts ?? null;
|
|
@@ -804,17 +789,19 @@ function selectableEfforts(model) {
|
|
|
804
789
|
}
|
|
805
790
|
function clampEffort(effort, allowed) {
|
|
806
791
|
if (allowed.length === 0) return void 0;
|
|
807
|
-
if (effort === void 0 ||
|
|
808
|
-
|
|
809
|
-
const
|
|
810
|
-
const
|
|
792
|
+
if (effort === void 0 || effort === "auto") return void 0;
|
|
793
|
+
if (allowed.includes(effort)) return effort;
|
|
794
|
+
const rank = MANUAL_EFFORTS.indexOf(effort);
|
|
795
|
+
const ordered = MANUAL_EFFORTS.filter((level) => allowed.includes(level));
|
|
796
|
+
const notDeeper = ordered.filter((level) => MANUAL_EFFORTS.indexOf(level) <= rank);
|
|
811
797
|
return notDeeper.length > 0 ? notDeeper[notDeeper.length - 1] : ordered[0];
|
|
812
798
|
}
|
|
813
|
-
var AGENT_EFFORTS, UNKNOWN_MODEL_EFFORTS;
|
|
799
|
+
var MANUAL_EFFORTS, AGENT_EFFORTS, UNKNOWN_MODEL_EFFORTS;
|
|
814
800
|
var init_effort = __esm({
|
|
815
801
|
"packages/core/src/effort.ts"() {
|
|
816
802
|
"use strict";
|
|
817
|
-
|
|
803
|
+
MANUAL_EFFORTS = ["low", "medium", "high", "xhigh", "max", "ultra"];
|
|
804
|
+
AGENT_EFFORTS = ["auto", ...MANUAL_EFFORTS];
|
|
818
805
|
UNKNOWN_MODEL_EFFORTS = ["low", "medium", "high", "xhigh"];
|
|
819
806
|
}
|
|
820
807
|
});
|
|
@@ -1104,7 +1091,7 @@ var init_progress = __esm({
|
|
|
1104
1091
|
// packages/tui/src/task-form.ts
|
|
1105
1092
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
1106
1093
|
import fs24 from "fs";
|
|
1107
|
-
import
|
|
1094
|
+
import os8 from "os";
|
|
1108
1095
|
import path28 from "path";
|
|
1109
1096
|
import React, { useEffect, useRef, useState } from "react";
|
|
1110
1097
|
import { Box, Text, render as render2, useApp, useInput } from "ink";
|
|
@@ -1177,10 +1164,10 @@ function modelOptions(ctx, agentCli, current) {
|
|
|
1177
1164
|
return options;
|
|
1178
1165
|
}
|
|
1179
1166
|
function effortOptions(ctx, agentCli, model) {
|
|
1180
|
-
return selectableEfforts(modelFor(ctx.models[agentCli], taskModel({ agentCli, model })));
|
|
1167
|
+
return ["auto", ...selectableEfforts(modelFor(ctx.models[agentCli], taskModel({ agentCli, model })))];
|
|
1181
1168
|
}
|
|
1182
1169
|
function fitEffort(ctx, s) {
|
|
1183
|
-
const effort = clampEffort(s.effort, effortOptions(ctx, s.agentCli, s.model)) ?? s.effort;
|
|
1170
|
+
const effort = s.effort === "auto" ? "auto" : clampEffort(s.effort, effortOptions(ctx, s.agentCli, s.model).filter(isManualEffort)) ?? s.effort;
|
|
1184
1171
|
return effort === s.effort ? s : { ...s, effort };
|
|
1185
1172
|
}
|
|
1186
1173
|
function blockReason(s, ctx, loadingGit) {
|
|
@@ -1231,7 +1218,7 @@ function editorCommand(env, platform) {
|
|
|
1231
1218
|
return env.VISUAL?.trim() || env.EDITOR?.trim() || (platform === "win32" ? "notepad" : "vi");
|
|
1232
1219
|
}
|
|
1233
1220
|
function editInEditor(text) {
|
|
1234
|
-
const dir = fs24.mkdtempSync(path28.join(
|
|
1221
|
+
const dir = fs24.mkdtempSync(path28.join(os8.tmpdir(), "vibeflow-"));
|
|
1235
1222
|
const file = path28.join(dir, "description.md");
|
|
1236
1223
|
try {
|
|
1237
1224
|
fs24.writeFileSync(file, text);
|
|
@@ -1312,9 +1299,9 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
1312
1299
|
if (editing === "title") setS((prev) => ({ ...prev, title: draft }));
|
|
1313
1300
|
else if (editing === "branch") setS((prev) => ({ ...prev, branch: value2 }));
|
|
1314
1301
|
else if (editing === "project") {
|
|
1315
|
-
if (value2) setProject(path28.resolve(value2.replace(/^~(?=$|\/)/,
|
|
1302
|
+
if (value2) setProject(path28.resolve(value2.replace(/^~(?=$|\/)/, os8.homedir())));
|
|
1316
1303
|
} else if (editing === "attachments" && value2) {
|
|
1317
|
-
const file = path28.resolve(value2.replace(/^~(?=$|\/)/,
|
|
1304
|
+
const file = path28.resolve(value2.replace(/^~(?=$|\/)/, os8.homedir()));
|
|
1318
1305
|
if (!fs24.existsSync(file) || !fs24.statSync(file).isFile()) {
|
|
1319
1306
|
setMessage(`\u627E\u4E0D\u5230\u6A94\u6848\uFF1A${file}`);
|
|
1320
1307
|
return;
|
|
@@ -1405,7 +1392,6 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
1405
1392
|
return lines.length > 1 ? `${lines[0]} \u2026\uFF08\u5171 ${lines.length} \u884C\uFF09` : lines[0];
|
|
1406
1393
|
}
|
|
1407
1394
|
case "effort": {
|
|
1408
|
-
if (effortOptions(ctx, s.agentCli, s.model).length === 0) return "\u4E0D\u9069\u7528";
|
|
1409
1395
|
const e = EFFORTS.find((x) => x.value === s.effort) ?? EFFORTS[0];
|
|
1410
1396
|
return `\u2039 ${e.label} \xB7 ${e.value} \u203A`;
|
|
1411
1397
|
}
|
|
@@ -1441,7 +1427,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
1441
1427
|
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;
|
|
1442
1428
|
}
|
|
1443
1429
|
if (field === "effort") {
|
|
1444
|
-
if (effortOptions(ctx, s.agentCli, s.model).length ===
|
|
1430
|
+
if (effortOptions(ctx, s.agentCli, s.model).length === 1) return "\u9019\u500B model \u4E0D\u652F\u63F4\u8ABF\u6574\u63A8\u7406\u5F37\u5EA6\uFF0C\u555F\u52D5\u6642\u4F7F\u7528\u6A21\u578B\u9810\u8A2D\u503C\u3002";
|
|
1445
1431
|
const e = EFFORTS.find((x) => x.value === s.effort) ?? EFFORTS[0];
|
|
1446
1432
|
return `${e.description} Claude Code \u8207 Codex \u6703\u5728\u555F\u52D5\u6B64\u4EFB\u52D9\u6642\u5957\u7528\uFF1B\u53EF\u9078\u7684\u7D1A\u8DDD\u4F9D model \u800C\u5B9A\u3002`;
|
|
1447
1433
|
}
|
|
@@ -1521,6 +1507,7 @@ var init_task_form = __esm({
|
|
|
1521
1507
|
init_attachments();
|
|
1522
1508
|
h = React.createElement;
|
|
1523
1509
|
EFFORTS = [
|
|
1510
|
+
{ value: "auto", label: "\u81EA\u52D5", description: "Jev \u4F9D\u4EFB\u52D9\u8207\u76EE\u524D\u6A21\u578B\u9078\u64C7\u63A8\u7406\u5F37\u5EA6\u3002" },
|
|
1524
1511
|
{ value: "low", label: "\u5FEB\u901F", description: "\u9069\u5408\u7BC4\u570D\u660E\u78BA\u3001\u4F4E\u98A8\u96AA\u7684\u5C0F\u4EFB\u52D9\u3002" },
|
|
1525
1512
|
{ value: "medium", label: "\u6A19\u6E96", description: "\u517C\u9867\u901F\u5EA6\u8207\u63A8\u7406\u6DF1\u5EA6\uFF0C\u9069\u5408\u4E00\u822C\u958B\u767C\u4EFB\u52D9\u3002" },
|
|
1526
1513
|
{ value: "high", label: "\u6DF1\u5165", description: "\u9069\u5408\u8DE8\u6A94\u6848\u3001\u9664\u932F\u6216\u9700\u8981\u8F03\u591A\u5224\u65B7\u7684\u4EFB\u52D9\u3002" },
|
|
@@ -1528,7 +1515,7 @@ var init_task_form = __esm({
|
|
|
1528
1515
|
{ value: "max", label: "\u6700\u5927", description: "\u6700\u6DF1\u7684\u63A8\u7406\uFF0C\u9069\u5408\u6700\u56F0\u96E3\u7684\u554F\u984C\u3002" },
|
|
1529
1516
|
{ value: "ultra", label: "\u59D4\u6D3E", description: "\u6700\u6DF1\u63A8\u7406\u4E26\u81EA\u52D5\u59D4\u6D3E\u5B50\u4EFB\u52D9\uFF0C\u8017\u6642\u8207\u7528\u91CF\u53EF\u80FD\u660E\u986F\u589E\u52A0\u3002" }
|
|
1530
1517
|
];
|
|
1531
|
-
DEFAULT_EFFORT = "
|
|
1518
|
+
DEFAULT_EFFORT = "auto";
|
|
1532
1519
|
LABELS = {
|
|
1533
1520
|
title: "\u4EFB\u52D9\u6A19\u984C",
|
|
1534
1521
|
project: "\u5C08\u6848\u8CC7\u6599\u593E",
|
|
@@ -3337,6 +3324,30 @@ var SNIFF_BYTES = 8 * 1024;
|
|
|
3337
3324
|
function agentArtifactsPath(baseDir, worktreePath) {
|
|
3338
3325
|
return path11.join(baseDir, `${path11.basename(worktreePath)}${ARTIFACTS_DIR_SUFFIX2}`);
|
|
3339
3326
|
}
|
|
3327
|
+
function ensureTaskArtifactDirs(task) {
|
|
3328
|
+
if (!task.worktreePath) throw new Error("\u4EFB\u52D9\u5C1A\u672A\u5EFA\u7ACB worktree");
|
|
3329
|
+
const dir = task.workspacePath ? agentArtifactsPath(task.workspacePath, task.worktreePath) : path11.join(task.worktreePath, ARTIFACTS_FALLBACK_DIR2);
|
|
3330
|
+
fs7.mkdirSync(path11.join(dir, SCRATCH_DIR_NAME2), { recursive: true });
|
|
3331
|
+
return dir;
|
|
3332
|
+
}
|
|
3333
|
+
function addTaskArtifact(task, filePath) {
|
|
3334
|
+
const source = path11.resolve(filePath);
|
|
3335
|
+
const stat = fs7.lstatSync(source);
|
|
3336
|
+
if (!stat.isFile()) throw new Error("Artifact \u4F86\u6E90\u5FC5\u9808\u662F\u4E00\u822C\u6A94\u6848");
|
|
3337
|
+
const dir = ensureTaskArtifactDirs(task);
|
|
3338
|
+
if (path11.dirname(source) === dir) return source;
|
|
3339
|
+
const { name, ext } = path11.parse(source);
|
|
3340
|
+
for (let index = 0; index < 1e3; index += 1) {
|
|
3341
|
+
const destination = path11.join(dir, index === 0 ? `${name}${ext}` : `${name}-${index}${ext}`);
|
|
3342
|
+
try {
|
|
3343
|
+
fs7.copyFileSync(source, destination, fs7.constants.COPYFILE_EXCL);
|
|
3344
|
+
return destination;
|
|
3345
|
+
} catch (error) {
|
|
3346
|
+
if (error.code !== "EEXIST") throw error;
|
|
3347
|
+
}
|
|
3348
|
+
}
|
|
3349
|
+
throw new Error("Artifact \u8CC7\u6599\u593E\u6709\u592A\u591A\u540C\u540D\u6A94\u6848");
|
|
3350
|
+
}
|
|
3340
3351
|
function mediaKind(filePath, size) {
|
|
3341
3352
|
const extension = path11.extname(filePath).toLowerCase();
|
|
3342
3353
|
const imageMime = IMAGE_MIME[extension];
|
|
@@ -4272,7 +4283,7 @@ init_effort();
|
|
|
4272
4283
|
import { execFile as execFile6 } from "child_process";
|
|
4273
4284
|
import { promisify as promisify3 } from "util";
|
|
4274
4285
|
var pexec3 = promisify3(execFile6);
|
|
4275
|
-
var DEFAULT_TASK_EFFORT = "
|
|
4286
|
+
var DEFAULT_TASK_EFFORT = "auto";
|
|
4276
4287
|
var AGENT_CLIS = [
|
|
4277
4288
|
{
|
|
4278
4289
|
id: "claude",
|
|
@@ -4463,7 +4474,7 @@ function updateTaskFromInput(input) {
|
|
|
4463
4474
|
init_attachments();
|
|
4464
4475
|
var AGENT_IDS = AGENT_CLIS.map((agent) => agent.id);
|
|
4465
4476
|
var STATUSES = ["backlog", "in_progress", "done"];
|
|
4466
|
-
var SUBCOMMANDS = ["create", "update"];
|
|
4477
|
+
var SUBCOMMANDS = ["create", "update", "artifact"];
|
|
4467
4478
|
var MODES = ["existing", "new"];
|
|
4468
4479
|
var AUTO_MODES = ["on", "off"];
|
|
4469
4480
|
var TASK_USAGE = `
|
|
@@ -4472,6 +4483,7 @@ VibeFlow task commands
|
|
|
4472
4483
|
Usage:
|
|
4473
4484
|
vibeflow task create [options]
|
|
4474
4485
|
vibeflow task update [options]
|
|
4486
|
+
vibeflow task artifact add --file <path> [options]
|
|
4475
4487
|
|
|
4476
4488
|
task create options:
|
|
4477
4489
|
--project <path> Target project directory (required)
|
|
@@ -4485,7 +4497,7 @@ task create options:
|
|
|
4485
4497
|
--mode <mode> ${MODES.join(" | ")} (default: existing; "new" runs git init first)
|
|
4486
4498
|
--agent <id> Task agent: ${AGENT_IDS.join(" | ")} (default: claude)
|
|
4487
4499
|
--model <id> Task model (default: the agent's own default)
|
|
4488
|
-
--effort <level> ${AGENT_EFFORTS.join(" | ")} (default:
|
|
4500
|
+
--effort <level> ${AGENT_EFFORTS.join(" | ")} (default: auto, same as the UI)
|
|
4489
4501
|
--auto-mode <on|off> Let the agent act without asking for approval
|
|
4490
4502
|
(default: the board-wide setting, same as the UI)
|
|
4491
4503
|
--attach <path> Attach a file; repeat the flag for several files
|
|
@@ -4504,6 +4516,12 @@ task update options:
|
|
|
4504
4516
|
At least one of --title / --prompt / --status is required. Branch, worktree
|
|
4505
4517
|
and project path are provisioned on disk and cannot be changed here.
|
|
4506
4518
|
|
|
4519
|
+
task artifact add options:
|
|
4520
|
+
--file <path> Copy a file into the card's user-facing Artifacts folder
|
|
4521
|
+
--task <id> Card ID (defaults to VIBEFLOW_TASK_ID in a task shell)
|
|
4522
|
+
--store-path <dir> Store directory (defaults to VIBEFLOW_STORE_DIR in a task shell)
|
|
4523
|
+
--profile <name> dev | prod \u2014 when no store path is given
|
|
4524
|
+
|
|
4507
4525
|
Notes:
|
|
4508
4526
|
A card created with --status in_progress does NOT start running by itself.
|
|
4509
4527
|
Every launch is started by hand from the app.
|
|
@@ -4571,6 +4589,7 @@ async function taskCommand(argv) {
|
|
|
4571
4589
|
effort: { type: "string" },
|
|
4572
4590
|
"auto-mode": { type: "string" },
|
|
4573
4591
|
attach: { type: "string", multiple: true },
|
|
4592
|
+
file: { type: "string" },
|
|
4574
4593
|
"store-path": { type: "string" },
|
|
4575
4594
|
profile: { type: "string" },
|
|
4576
4595
|
help: { type: "boolean", short: "h" }
|
|
@@ -4582,13 +4601,24 @@ async function taskCommand(argv) {
|
|
|
4582
4601
|
fail("INVALID_ARGUMENT", err.message);
|
|
4583
4602
|
}
|
|
4584
4603
|
const { values, positionals } = parsed;
|
|
4585
|
-
const [sub] = positionals;
|
|
4604
|
+
const [sub, action] = positionals;
|
|
4586
4605
|
if (values.help || !sub) return null;
|
|
4587
|
-
const storePath = resolveStorePath(
|
|
4606
|
+
const storePath = resolveStorePath(
|
|
4607
|
+
values["store-path"] ?? (sub === "artifact" ? process.env.VIBEFLOW_STORE_DIR : void 0),
|
|
4608
|
+
values.profile
|
|
4609
|
+
);
|
|
4588
4610
|
setPlatform(createNodePlatform({ userDataDir: storePath }));
|
|
4589
4611
|
if (!SUBCOMMANDS.includes(sub)) {
|
|
4590
4612
|
fail("UNKNOWN_COMMAND", `Unknown command: "task ${sub}". Use: ${SUBCOMMANDS.map((s) => `task ${s}`).join(" | ")}`);
|
|
4591
4613
|
}
|
|
4614
|
+
if (sub === "artifact") {
|
|
4615
|
+
if (action !== "add") fail("UNKNOWN_COMMAND", "Use: task artifact add --file <path>");
|
|
4616
|
+
const taskId = values.task ?? process.env.VIBEFLOW_TASK_ID;
|
|
4617
|
+
if (!taskId || !values.file) fail("MISSING_ARGUMENT", "task artifact add needs --file and --task (or VIBEFLOW_TASK_ID)");
|
|
4618
|
+
const task2 = findTask(taskId);
|
|
4619
|
+
if (!task2) fail("TASK_NOT_FOUND", `Task not found: ${taskId}`);
|
|
4620
|
+
return { taskId, path: addTaskArtifact(task2, values.file) };
|
|
4621
|
+
}
|
|
4592
4622
|
if (sub === "update") {
|
|
4593
4623
|
if (!values.task) fail("MISSING_ARGUMENT", "Missing required arguments: --task");
|
|
4594
4624
|
requireOneOf("--status", values.status, STATUSES);
|
|
@@ -4696,7 +4726,6 @@ import path15 from "path";
|
|
|
4696
4726
|
// packages/core/src/library.ts
|
|
4697
4727
|
import { createHash } from "crypto";
|
|
4698
4728
|
import fs10 from "fs";
|
|
4699
|
-
import os3 from "os";
|
|
4700
4729
|
import path14 from "path";
|
|
4701
4730
|
var LIBRARY_DIR = "library";
|
|
4702
4731
|
var LIBRARY_KINDS = ["skill", "prompt", "script"];
|
|
@@ -4713,7 +4742,6 @@ function libraryPaths(root) {
|
|
|
4713
4742
|
skills: path14.join(root, KIND_DIR.skill),
|
|
4714
4743
|
prompts: path14.join(root, KIND_DIR.prompt),
|
|
4715
4744
|
scripts: path14.join(root, KIND_DIR.script),
|
|
4716
|
-
plugin: path14.join(root, "plugin"),
|
|
4717
4745
|
codexHome: path14.join(root, "codex-home")
|
|
4718
4746
|
};
|
|
4719
4747
|
}
|
|
@@ -4961,9 +4989,6 @@ function requireEntry(root, kind, name) {
|
|
|
4961
4989
|
if (!found2) throw new Error(`\u9805\u76EE\u5BEB\u5165\u5F8C\u8B80\u4E0D\u56DE\u4F86\uFF1A${kind}/${name}`);
|
|
4962
4990
|
return found2;
|
|
4963
4991
|
}
|
|
4964
|
-
function projectSkillsDir(worktreePath) {
|
|
4965
|
-
return path14.join(worktreePath, ".claude", "skills");
|
|
4966
|
-
}
|
|
4967
4992
|
function skillNamesIn(dir) {
|
|
4968
4993
|
try {
|
|
4969
4994
|
return fs10.readdirSync(dir, { withFileTypes: true }).filter((d) => !d.name.startsWith(".")).map((d) => d.name).filter((name) => fs10.existsSync(path14.join(dir, name, "SKILL.md"))).sort();
|
|
@@ -4971,132 +4996,6 @@ function skillNamesIn(dir) {
|
|
|
4971
4996
|
return [];
|
|
4972
4997
|
}
|
|
4973
4998
|
}
|
|
4974
|
-
var PLUGIN_MANIFEST_DIR = ".claude-plugin";
|
|
4975
|
-
function buildPluginDir(root) {
|
|
4976
|
-
const paths = libraryPaths(root);
|
|
4977
|
-
const enabled = listLibrary(root).filter((e) => e.kind === "skill" && e.enabled);
|
|
4978
|
-
fs10.rmSync(path14.join(paths.plugin, "skills"), { recursive: true, force: true });
|
|
4979
|
-
fs10.mkdirSync(path14.join(paths.plugin, PLUGIN_MANIFEST_DIR), { recursive: true });
|
|
4980
|
-
fs10.mkdirSync(path14.join(paths.plugin, "skills"), { recursive: true });
|
|
4981
|
-
fs10.writeFileSync(
|
|
4982
|
-
path14.join(paths.plugin, PLUGIN_MANIFEST_DIR, "plugin.json"),
|
|
4983
|
-
`${JSON.stringify(
|
|
4984
|
-
{
|
|
4985
|
-
name: "vibeflow-library",
|
|
4986
|
-
version: "1.0.0",
|
|
4987
|
-
description: "Skills delivered by VibeFlow for this task."
|
|
4988
|
-
},
|
|
4989
|
-
null,
|
|
4990
|
-
2
|
|
4991
|
-
)}
|
|
4992
|
-
`
|
|
4993
|
-
);
|
|
4994
|
-
for (const entry of enabled) {
|
|
4995
|
-
fs10.cpSync(entry.path, path14.join(paths.plugin, "skills", entry.name), {
|
|
4996
|
-
recursive: true,
|
|
4997
|
-
dereference: true
|
|
4998
|
-
});
|
|
4999
|
-
}
|
|
5000
|
-
return { pluginDir: paths.plugin, skills: enabled.map((e) => e.name) };
|
|
5001
|
-
}
|
|
5002
|
-
function linkOrSkip(target, linkPath) {
|
|
5003
|
-
if (!fs10.existsSync(target)) return false;
|
|
5004
|
-
const source = path14.resolve(target);
|
|
5005
|
-
const attempts = fs10.statSync(source).isDirectory() ? [
|
|
5006
|
-
() => fs10.symlinkSync(source, linkPath, "junction"),
|
|
5007
|
-
() => fs10.cpSync(source, linkPath, { recursive: true, dereference: true })
|
|
5008
|
-
] : [
|
|
5009
|
-
() => fs10.symlinkSync(source, linkPath),
|
|
5010
|
-
() => fs10.linkSync(source, linkPath),
|
|
5011
|
-
() => fs10.copyFileSync(source, linkPath)
|
|
5012
|
-
];
|
|
5013
|
-
for (const attempt of attempts) {
|
|
5014
|
-
try {
|
|
5015
|
-
fs10.rmSync(linkPath, { recursive: true, force: true });
|
|
5016
|
-
attempt();
|
|
5017
|
-
return true;
|
|
5018
|
-
} catch {
|
|
5019
|
-
}
|
|
5020
|
-
}
|
|
5021
|
-
return false;
|
|
5022
|
-
}
|
|
5023
|
-
function buildCodexHome(root, worktreePath, userCodexHome = path14.join(os3.homedir(), ".codex")) {
|
|
5024
|
-
const paths = libraryPaths(root);
|
|
5025
|
-
const skillsDir = path14.join(paths.codexHome, "skills");
|
|
5026
|
-
fs10.rmSync(skillsDir, { recursive: true, force: true });
|
|
5027
|
-
fs10.mkdirSync(skillsDir, { recursive: true });
|
|
5028
|
-
for (const file of ["auth.json", "config.toml"]) {
|
|
5029
|
-
linkOrSkip(path14.join(userCodexHome, file), path14.join(paths.codexHome, file));
|
|
5030
|
-
}
|
|
5031
|
-
const result = {
|
|
5032
|
-
codexHome: paths.codexHome,
|
|
5033
|
-
project: [],
|
|
5034
|
-
user: [],
|
|
5035
|
-
library: [],
|
|
5036
|
-
shadowed: []
|
|
5037
|
-
};
|
|
5038
|
-
const claimed = /* @__PURE__ */ new Map();
|
|
5039
|
-
const projectDir = worktreePath ? projectSkillsDir(worktreePath) : void 0;
|
|
5040
|
-
if (projectDir) {
|
|
5041
|
-
for (const name of skillNamesIn(projectDir)) {
|
|
5042
|
-
if (linkOrSkip(path14.join(projectDir, name), path14.join(skillsDir, name))) {
|
|
5043
|
-
result.project.push(name);
|
|
5044
|
-
claimed.set(name, "project");
|
|
5045
|
-
}
|
|
5046
|
-
}
|
|
5047
|
-
}
|
|
5048
|
-
const userDir = path14.join(userCodexHome, "skills");
|
|
5049
|
-
for (const name of skillNamesIn(userDir)) {
|
|
5050
|
-
const owner = claimed.get(name);
|
|
5051
|
-
if (owner) {
|
|
5052
|
-
result.shadowed.push({ name, keptFrom: owner, dropped: "user" });
|
|
5053
|
-
continue;
|
|
5054
|
-
}
|
|
5055
|
-
if (linkOrSkip(path14.join(userDir, name), path14.join(skillsDir, name))) {
|
|
5056
|
-
result.user.push(name);
|
|
5057
|
-
claimed.set(name, "user");
|
|
5058
|
-
}
|
|
5059
|
-
}
|
|
5060
|
-
for (const entry of listLibrary(root)) {
|
|
5061
|
-
if (entry.kind !== "skill" || !entry.enabled) continue;
|
|
5062
|
-
const owner = claimed.get(entry.name);
|
|
5063
|
-
if (owner) {
|
|
5064
|
-
result.shadowed.push({ name: entry.name, keptFrom: owner, dropped: "library" });
|
|
5065
|
-
continue;
|
|
5066
|
-
}
|
|
5067
|
-
fs10.cpSync(entry.path, path14.join(skillsDir, entry.name), {
|
|
5068
|
-
recursive: true,
|
|
5069
|
-
dereference: true
|
|
5070
|
-
});
|
|
5071
|
-
result.library.push(entry.name);
|
|
5072
|
-
}
|
|
5073
|
-
return result;
|
|
5074
|
-
}
|
|
5075
|
-
function libraryLaunchInfoAt(root, worktreePath, userCodexHome) {
|
|
5076
|
-
const entries = listLibrary(root).filter((e) => e.enabled);
|
|
5077
|
-
if (entries.length === 0) return null;
|
|
5078
|
-
const { pluginDir } = buildPluginDir(root);
|
|
5079
|
-
const { codexHome } = buildCodexHome(root, worktreePath, userCodexHome);
|
|
5080
|
-
const scripts = entries.filter((e) => e.kind === "script").map((e) => ({ name: e.name, path: e.path, description: e.description }));
|
|
5081
|
-
const promptBodies = entries.filter((e) => e.kind === "prompt").map((e) => readEntryContent(root, "prompt", e.name).trim()).filter(Boolean);
|
|
5082
|
-
const lines = [...promptBodies];
|
|
5083
|
-
if (scripts.length > 0) {
|
|
5084
|
-
lines.push(
|
|
5085
|
-
"\u53EF\u7528\u7684\u5DE5\u5177\u8173\u672C\uFF08\u9700\u8981\u6642\u81EA\u884C\u57F7\u884C\uFF0C\u4E0D\u9700\u8981\u5C31\u5225\u8DD1\uFF09\uFF1A",
|
|
5086
|
-
...scripts.map((s) => `- ${s.path}${s.description ? ` \u2014 ${s.description}` : ""}`)
|
|
5087
|
-
);
|
|
5088
|
-
}
|
|
5089
|
-
return {
|
|
5090
|
-
pluginDir,
|
|
5091
|
-
codexHome,
|
|
5092
|
-
libraryDir: root,
|
|
5093
|
-
scripts,
|
|
5094
|
-
promptText: lines.join("\n\n")
|
|
5095
|
-
};
|
|
5096
|
-
}
|
|
5097
|
-
async function libraryLaunchInfo(worktreePath) {
|
|
5098
|
-
return libraryLaunchInfoAt(await libraryRoot(), worktreePath);
|
|
5099
|
-
}
|
|
5100
4999
|
|
|
5101
5000
|
// packages/core/src/library-builtins.ts
|
|
5102
5001
|
function builtinSkillsDir() {
|
|
@@ -5202,19 +5101,19 @@ async function syncBuiltinsAtStartup() {
|
|
|
5202
5101
|
|
|
5203
5102
|
// packages/core/src/service.ts
|
|
5204
5103
|
import fs19 from "fs";
|
|
5205
|
-
import
|
|
5104
|
+
import os7 from "os";
|
|
5206
5105
|
import path23 from "path";
|
|
5207
5106
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
5208
5107
|
|
|
5209
5108
|
// packages/core/src/agent-models.ts
|
|
5210
5109
|
import fs13 from "fs";
|
|
5211
|
-
import
|
|
5110
|
+
import os5 from "os";
|
|
5212
5111
|
import path17 from "path";
|
|
5213
5112
|
|
|
5214
5113
|
// packages/core/src/claude-models.ts
|
|
5215
5114
|
init_effort();
|
|
5216
5115
|
import fs12 from "fs";
|
|
5217
|
-
import
|
|
5116
|
+
import os3 from "os";
|
|
5218
5117
|
import path16 from "path";
|
|
5219
5118
|
|
|
5220
5119
|
// packages/core/src/json-lines-process.ts
|
|
@@ -5319,7 +5218,7 @@ var CLAUDE_MODELS_TIMEOUT_MS = 15e3;
|
|
|
5319
5218
|
var REQUEST_ID = "vibeflow-models";
|
|
5320
5219
|
var CLAUDE_ARGS = ["-p", "--input-format", "stream-json", "--output-format", "stream-json", "--verbose"];
|
|
5321
5220
|
function openClaude() {
|
|
5322
|
-
const cwd = fs12.mkdtempSync(path16.join(
|
|
5221
|
+
const cwd = fs12.mkdtempSync(path16.join(os3.tmpdir(), "vf-claude-models-"));
|
|
5323
5222
|
return spawnJsonLines("claude", CLAUDE_ARGS, {
|
|
5324
5223
|
cwd,
|
|
5325
5224
|
timeoutMs: CLAUDE_MODELS_TIMEOUT_MS,
|
|
@@ -5349,7 +5248,7 @@ function parseClaudeInitialize(message) {
|
|
|
5349
5248
|
seen.add(id);
|
|
5350
5249
|
const label = typeof entry.displayName === "string" && entry.displayName.trim() ? entry.displayName.trim() : id;
|
|
5351
5250
|
const description = typeof entry.description === "string" && entry.description.trim() ? entry.description.trim() : void 0;
|
|
5352
|
-
const levels = entry.supportsEffort === true && Array.isArray(entry.supportedEffortLevels) ? entry.supportedEffortLevels.filter(
|
|
5251
|
+
const levels = entry.supportsEffort === true && Array.isArray(entry.supportedEffortLevels) ? entry.supportedEffortLevels.filter(isManualEffort) : [];
|
|
5353
5252
|
const isDefault = !defaultMarked && defaultResolved !== void 0 && entry.resolvedModel === defaultResolved;
|
|
5354
5253
|
if (isDefault) defaultMarked = true;
|
|
5355
5254
|
models.push({ id, label, ...description ? { description } : {}, efforts: levels, ...isDefault ? { isDefault } : {} });
|
|
@@ -5370,7 +5269,7 @@ async function fetchClaudeModels(open = openClaude) {
|
|
|
5370
5269
|
// packages/core/src/codex-models.ts
|
|
5371
5270
|
init_effort();
|
|
5372
5271
|
init_env();
|
|
5373
|
-
import
|
|
5272
|
+
import os4 from "os";
|
|
5374
5273
|
var CODEX_MODELS_TIMEOUT_MS = 2e4;
|
|
5375
5274
|
var MAX_PAGES = 20;
|
|
5376
5275
|
var CodexLoginRequiredError = class extends Error {
|
|
@@ -5383,7 +5282,7 @@ function codexAppServerCommand() {
|
|
|
5383
5282
|
return {
|
|
5384
5283
|
bin: "codex",
|
|
5385
5284
|
args: ["app-server", "--listen", "stdio://"],
|
|
5386
|
-
cwd:
|
|
5285
|
+
cwd: os4.homedir(),
|
|
5387
5286
|
env: execEnv()
|
|
5388
5287
|
};
|
|
5389
5288
|
}
|
|
@@ -5412,7 +5311,7 @@ function parseCodexModelPage(result) {
|
|
|
5412
5311
|
const id = entry.id.trim();
|
|
5413
5312
|
const label = typeof entry.displayName === "string" && entry.displayName.trim() ? entry.displayName.trim() : id;
|
|
5414
5313
|
const description = typeof entry.description === "string" && entry.description.trim() ? entry.description.trim() : void 0;
|
|
5415
|
-
const efforts = Array.isArray(entry.supportedReasoningEfforts) ? entry.supportedReasoningEfforts.map((e) => isRecord2(e) ? e.reasoningEffort : void 0).filter(
|
|
5314
|
+
const efforts = Array.isArray(entry.supportedReasoningEfforts) ? entry.supportedReasoningEfforts.map((e) => isRecord2(e) ? e.reasoningEffort : void 0).filter(isManualEffort) : void 0;
|
|
5416
5315
|
models.push({
|
|
5417
5316
|
id,
|
|
5418
5317
|
label,
|
|
@@ -5472,7 +5371,7 @@ function builtinModels(id) {
|
|
|
5472
5371
|
}
|
|
5473
5372
|
function defaultCodexHome() {
|
|
5474
5373
|
const configured = process.env.CODEX_HOME?.trim();
|
|
5475
|
-
return configured ? configured : path17.join(
|
|
5374
|
+
return configured ? configured : path17.join(os5.homedir(), ".codex");
|
|
5476
5375
|
}
|
|
5477
5376
|
function parseCodexCatalog(raw) {
|
|
5478
5377
|
const body = JSON.parse(raw);
|
|
@@ -5558,118 +5457,68 @@ function createModelCatalog(opts) {
|
|
|
5558
5457
|
}
|
|
5559
5458
|
|
|
5560
5459
|
// packages/core/src/jev-router.ts
|
|
5460
|
+
init_effort();
|
|
5561
5461
|
init_launch();
|
|
5562
5462
|
var API_URL = "https://api.typesafe.ai/v1/systemone";
|
|
5563
5463
|
var MAX_TASK_CHARS = 12e3;
|
|
5564
|
-
var MAX_PLAN_CHARS = 8e3;
|
|
5565
|
-
function tier(model, agent) {
|
|
5566
|
-
const name = `${model.id} ${model.label}`.toLowerCase();
|
|
5567
|
-
if (/haiku|mini|nano|luna|flash/.test(name)) return 0;
|
|
5568
|
-
if (/opus|astra|pro\b/.test(name)) return 2;
|
|
5569
|
-
if (agent === "codex" && /gpt-5\.5|gpt-5\.4(?!-mini)/.test(name)) return 2;
|
|
5570
|
-
return 1;
|
|
5571
|
-
}
|
|
5572
|
-
function routeCandidates(agent, models) {
|
|
5573
|
-
const valid = models.filter((m) => /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(m.id));
|
|
5574
|
-
const byTier = /* @__PURE__ */ new Map();
|
|
5575
|
-
for (const model of valid) {
|
|
5576
|
-
const rank = tier(model, agent);
|
|
5577
|
-
if (!byTier.has(rank)) byTier.set(rank, model);
|
|
5578
|
-
}
|
|
5579
|
-
return [...byTier.entries()].sort(([a], [b]) => a - b).map(([, model]) => model);
|
|
5580
|
-
}
|
|
5581
|
-
function isChoice(value) {
|
|
5582
|
-
return !!value && typeof value === "object" && value.type === "choice" && typeof value.choice === "string";
|
|
5583
|
-
}
|
|
5584
5464
|
function createJevRouter(opts = {}) {
|
|
5585
5465
|
const getApiKey = opts.getApiKey ?? (() => opts.apiKey ?? process.env.TYPESAFE_API_KEY?.trim());
|
|
5586
5466
|
const fetcher = opts.fetcher ?? fetch;
|
|
5587
|
-
const planner = opts.planner ?? (async (agent, model, prompt, cwd) => {
|
|
5588
|
-
const args = agent === "claude" ? ["-p", "--model", model, "--permission-mode", "plan"] : ["exec", "--model", model, "--sandbox", "read-only", "--skip-git-repo-check", "-"];
|
|
5589
|
-
return (opts.printAgent ?? runAgentPrint)(agent, args, prompt, { cwd, timeout: 12e4, maxBuffer: 128 * 1024 });
|
|
5590
|
-
});
|
|
5591
|
-
async function ask(state, questions) {
|
|
5592
|
-
const apiKey = getApiKey();
|
|
5593
|
-
if (!apiKey) throw new Error("\u672A\u8A2D\u5B9A Jev API key\uFF08\u53EF\u5728\u8A2D\u5B9A\u4E2D\u8F38\u5165\u6216\u63D0\u4F9B TYPESAFE_API_KEY\uFF09");
|
|
5594
|
-
const response = await fetcher(API_URL, {
|
|
5595
|
-
method: "POST",
|
|
5596
|
-
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
5597
|
-
body: JSON.stringify({ model: "jev-latest", state, questions }),
|
|
5598
|
-
signal: AbortSignal.timeout(15e3)
|
|
5599
|
-
});
|
|
5600
|
-
if (!response.ok) throw new Error(`Jev API \u56DE\u61C9 ${response.status}`);
|
|
5601
|
-
const body = await response.json();
|
|
5602
|
-
if (!body.answers) throw new Error("Jev API \u6C92\u6709\u56DE\u50B3\u5224\u65B7");
|
|
5603
|
-
return body.answers;
|
|
5604
|
-
}
|
|
5605
5467
|
return {
|
|
5606
5468
|
get enabled() {
|
|
5607
5469
|
return Boolean(getApiKey());
|
|
5608
5470
|
},
|
|
5609
|
-
async route(task, catalog
|
|
5610
|
-
const
|
|
5611
|
-
const
|
|
5612
|
-
if (
|
|
5613
|
-
const expensive = candidates[candidates.length - 1];
|
|
5614
|
-
const taskText = buildPrompt(task).slice(0, MAX_TASK_CHARS);
|
|
5471
|
+
async route(task, catalog) {
|
|
5472
|
+
const model = modelFor(catalog, taskModel(task));
|
|
5473
|
+
const levels = selectableEfforts(model);
|
|
5474
|
+
if (levels.length === 0) return { status: "fallback", reason: "\u76EE\u524D\u6A21\u578B\u4E0D\u652F\u63F4\u8ABF\u6574 effort" };
|
|
5615
5475
|
try {
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
|
|
5629
|
-
|
|
5630
|
-
|
|
5631
|
-
|
|
5632
|
-
|
|
5476
|
+
const apiKey = getApiKey();
|
|
5477
|
+
if (!apiKey) throw new Error("\u672A\u8A2D\u5B9A Jev API key\uFF08\u53EF\u5728\u8A2D\u5B9A\u4E2D\u8F38\u5165\u6216\u63D0\u4F9B TYPESAFE_API_KEY\uFF09");
|
|
5478
|
+
const response = await fetcher(API_URL, {
|
|
5479
|
+
method: "POST",
|
|
5480
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
5481
|
+
body: JSON.stringify({
|
|
5482
|
+
model: "jev-latest",
|
|
5483
|
+
state: {
|
|
5484
|
+
task: buildPrompt(task).slice(0, MAX_TASK_CHARS),
|
|
5485
|
+
agent: task.agentCli === "codex" ? "codex" : "claude",
|
|
5486
|
+
currentModel: model?.id ?? taskModel(task) ?? "CLI default (catalog unavailable)"
|
|
5487
|
+
},
|
|
5488
|
+
questions: {
|
|
5489
|
+
effort: {
|
|
5490
|
+
type: "choice",
|
|
5491
|
+
instructions: "Choose the lowest reasoning effort likely to complete this software task correctly on the current model. Increase effort for complexity, ambiguity, or risk.",
|
|
5492
|
+
criteria: Object.fromEntries(levels.map((level) => [level, effortDescription(level)]))
|
|
5493
|
+
}
|
|
5633
5494
|
}
|
|
5634
|
-
}
|
|
5495
|
+
}),
|
|
5496
|
+
signal: AbortSignal.timeout(15e3)
|
|
5635
5497
|
});
|
|
5636
|
-
if (!
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
5640
|
-
|
|
5641
|
-
const instruction = `Read the repository and make a concise implementation plan for the following task. Do not edit files. Identify unclear requirements, affected areas, and verification. Return only the plan.
|
|
5642
|
-
|
|
5643
|
-
${taskText}`;
|
|
5644
|
-
plan = (await planner(agent, expensive.id, instruction, task.worktreePath)).trim().slice(0, MAX_PLAN_CHARS);
|
|
5645
|
-
if (!plan) throw new Error("\u898F\u5283\u6A21\u578B\u6C92\u6709\u56DE\u50B3\u8A08\u756B");
|
|
5498
|
+
if (!response.ok) throw new Error(`Jev API \u56DE\u61C9 ${response.status}`);
|
|
5499
|
+
const body = await response.json();
|
|
5500
|
+
const choice = body.answers?.effort;
|
|
5501
|
+
if (choice?.type !== "choice" || !levels.includes(choice.choice)) {
|
|
5502
|
+
throw new Error("Jev \u9078\u4E86\u76EE\u524D\u6A21\u578B\u4E0D\u652F\u63F4\u7684 effort");
|
|
5646
5503
|
}
|
|
5647
|
-
|
|
5648
|
-
const options = Object.fromEntries(candidates.map((m) => [
|
|
5649
|
-
m.id,
|
|
5650
|
-
`${m.label}; relative cost tier ${tier(m, agent) + 1}/3 (${tier(m, agent) === 2 ? "highest capability" : tier(m, agent) === 0 ? "lowest cost" : "balanced"})`
|
|
5651
|
-
]));
|
|
5652
|
-
const second = await ask({ task: taskText, complexity: first.complexity.choice, plan }, {
|
|
5653
|
-
model: {
|
|
5654
|
-
type: "choice",
|
|
5655
|
-
instructions: "Choose the lowest-cost available model likely to implement this task correctly. Prefer more capable models as complexity or uncertainty rises.",
|
|
5656
|
-
criteria: options
|
|
5657
|
-
}
|
|
5658
|
-
});
|
|
5659
|
-
if (!isChoice(second.model) || !candidates.some((m) => m.id === second.model.choice)) {
|
|
5660
|
-
throw new Error("Jev \u9078\u4E86\u4E0D\u5728\u6A21\u578B\u6E05\u55AE\u4E2D\u7684\u6A21\u578B");
|
|
5661
|
-
}
|
|
5662
|
-
return {
|
|
5663
|
-
status: "routed",
|
|
5664
|
-
model: second.model.choice,
|
|
5665
|
-
...plan ? { plannerModel: expensive.id, plan } : {}
|
|
5666
|
-
};
|
|
5504
|
+
return { status: "routed", effort: choice.choice };
|
|
5667
5505
|
} catch (err) {
|
|
5668
5506
|
return { status: "fallback", reason: err instanceof Error ? err.message : String(err) };
|
|
5669
5507
|
}
|
|
5670
5508
|
}
|
|
5671
5509
|
};
|
|
5672
5510
|
}
|
|
5511
|
+
function effortDescription(level) {
|
|
5512
|
+
const descriptions = {
|
|
5513
|
+
low: "Routine, small and well scoped work",
|
|
5514
|
+
medium: "Typical development with limited uncertainty",
|
|
5515
|
+
high: "Complex debugging or several interacting files",
|
|
5516
|
+
xhigh: "Difficult design or extensive reasoning",
|
|
5517
|
+
max: "The hardest, highest risk tasks",
|
|
5518
|
+
ultra: "Deepest reasoning with automatic delegation"
|
|
5519
|
+
};
|
|
5520
|
+
return descriptions[level];
|
|
5521
|
+
}
|
|
5673
5522
|
|
|
5674
5523
|
// packages/core/src/jev-credentials.ts
|
|
5675
5524
|
import fs14 from "fs";
|
|
@@ -6635,7 +6484,7 @@ init_launch();
|
|
|
6635
6484
|
init_progress();
|
|
6636
6485
|
init_launch();
|
|
6637
6486
|
import fs18 from "fs";
|
|
6638
|
-
import
|
|
6487
|
+
import os6 from "os";
|
|
6639
6488
|
import path22 from "path";
|
|
6640
6489
|
var SINCE_SLACK_MS = 5e3;
|
|
6641
6490
|
function claudeProjectDir(home, cwd) {
|
|
@@ -6736,7 +6585,7 @@ function codexDayDirs(sessionsRoot, since) {
|
|
|
6736
6585
|
return days;
|
|
6737
6586
|
}
|
|
6738
6587
|
function createProgressTracker(opts) {
|
|
6739
|
-
const home = opts.homeDir ??
|
|
6588
|
+
const home = opts.homeDir ?? os6.homedir();
|
|
6740
6589
|
const codexHomes = opts.codexHomes ?? (() => [path22.join(home, ".codex")]);
|
|
6741
6590
|
const pollMs = opts.pollMs ?? 2e3;
|
|
6742
6591
|
const entries = /* @__PURE__ */ new Map();
|
|
@@ -6990,7 +6839,7 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
6990
6839
|
libraryCodexHome = libraryPaths(root).codexHome;
|
|
6991
6840
|
}).catch(() => {
|
|
6992
6841
|
});
|
|
6993
|
-
const home = homeDir ??
|
|
6842
|
+
const home = homeDir ?? os7.homedir();
|
|
6994
6843
|
const progress = createProgressTracker({
|
|
6995
6844
|
homeDir: home,
|
|
6996
6845
|
codexHomes: () => [path23.join(home, ".codex"), ...libraryCodexHome ? [libraryCodexHome] : []],
|
|
@@ -7067,16 +6916,16 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
7067
6916
|
requireTask(key.split(":")[0]);
|
|
7068
6917
|
return key;
|
|
7069
6918
|
}
|
|
7070
|
-
function launchEffort(task,
|
|
7071
|
-
const
|
|
7072
|
-
|
|
6919
|
+
function launchEffort(task, route) {
|
|
6920
|
+
const effort = task.effort === "auto" ? route?.effort : task.effort;
|
|
6921
|
+
const model = models.findModel(taskAgent(task), taskModel(task));
|
|
6922
|
+
return model?.efforts ? clampEffort(effort, model.efforts) : effort;
|
|
7073
6923
|
}
|
|
7074
6924
|
async function launchCommand(task, intent) {
|
|
7075
6925
|
const settings = getSettings();
|
|
7076
|
-
const library = await libraryLaunchInfo(task.worktreePath);
|
|
7077
6926
|
const boardCli = await boardCliLaunchInfo();
|
|
7078
|
-
let route = task.
|
|
7079
|
-
if (
|
|
6927
|
+
let route = task.jevRoute?.status === "routing" ? void 0 : task.jevRoute;
|
|
6928
|
+
if (task.effort === "auto" && !intent.resume && intent.includeTaskPrompt !== false) {
|
|
7080
6929
|
let pending = routing.get(task.id);
|
|
7081
6930
|
if (!pending) {
|
|
7082
6931
|
const setRoute = (jevRoute) => {
|
|
@@ -7084,9 +6933,9 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
7084
6933
|
bus.emit("state:changed", getState());
|
|
7085
6934
|
};
|
|
7086
6935
|
pending = (async () => {
|
|
7087
|
-
setRoute({ status: "routing"
|
|
6936
|
+
setRoute({ status: "routing" });
|
|
7088
6937
|
const candidateModels = (await (router.enabled === false ? models.get(taskAgent(task)) : models.refresh(taskAgent(task)))).models;
|
|
7089
|
-
const selected = await router.route(task, candidateModels
|
|
6938
|
+
const selected = await router.route(task, candidateModels);
|
|
7090
6939
|
setRoute(selected);
|
|
7091
6940
|
return selected;
|
|
7092
6941
|
})().catch((err) => {
|
|
@@ -7097,24 +6946,21 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
7097
6946
|
}
|
|
7098
6947
|
route = await pending;
|
|
7099
6948
|
}
|
|
7100
|
-
const selectedModel = task.model?.trim() ? taskModel(task) : route?.model;
|
|
7101
6949
|
return buildAgentCommand(
|
|
7102
|
-
{ ...task, model:
|
|
6950
|
+
{ ...task, model: taskModel(task), effort: launchEffort(task, route) },
|
|
7103
6951
|
settings.systemPrompt ?? "",
|
|
7104
6952
|
{
|
|
7105
6953
|
resume: intent.resume === true,
|
|
7106
6954
|
includeTaskPrompt: intent.includeTaskPrompt !== false,
|
|
7107
|
-
library: library ?? void 0,
|
|
7108
6955
|
boardCli,
|
|
7109
|
-
autoMode: task.autoMode ?? settings.autoMode
|
|
7110
|
-
preflightPlan: !intent.resume ? route?.plan : void 0
|
|
6956
|
+
autoMode: task.autoMode ?? settings.autoMode
|
|
7111
6957
|
},
|
|
7112
6958
|
task.workspacePath
|
|
7113
6959
|
);
|
|
7114
6960
|
}
|
|
7115
6961
|
function claudeSessionFile(cwd, sessionId) {
|
|
7116
6962
|
const munged = cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
7117
|
-
return path23.join(
|
|
6963
|
+
return path23.join(os7.homedir(), ".claude", "projects", munged, `${sessionId}.jsonl`);
|
|
7118
6964
|
}
|
|
7119
6965
|
async function removeTaskWorktree(task) {
|
|
7120
6966
|
if (!task.projectPath || !task.worktreePath) return;
|
|
@@ -7412,6 +7258,7 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
7412
7258
|
command = (await launchCommand(task, intent)).replace(/\r$/, "");
|
|
7413
7259
|
}
|
|
7414
7260
|
}
|
|
7261
|
+
if (p.launch) ensureTaskArtifactDirs(task);
|
|
7415
7262
|
const result = await sessions.start(key, {
|
|
7416
7263
|
cwd,
|
|
7417
7264
|
command,
|
|
@@ -8579,7 +8426,7 @@ Usage:
|
|
|
8579
8426
|
vibeflow doctor Check Node, git, tmux, node-pty and the agent CLIs
|
|
8580
8427
|
(--skip agents,web,\u2026 leaves checks out, e.g. on CI)
|
|
8581
8428
|
vibeflow update Install the latest global npm release (restart the host afterward)
|
|
8582
|
-
vibeflow task \u2026 Create / update cards (vibeflow task --help)
|
|
8429
|
+
vibeflow task \u2026 Create / update cards; add artifacts (vibeflow task --help)
|
|
8583
8430
|
|
|
8584
8431
|
Options:
|
|
8585
8432
|
--profile dev|prod Store profile (dev = the "(development)" store npm run dev uses)
|