@kw-yeh/vibeflow 4.11.38 → 4.11.39
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 +1 -1
- package/dist/vibeflow.mjs +261 -111
- package/dist/web/404/index.html +1 -1
- package/dist/web/404.html +1 -1
- package/dist/web/_next/static/{3LDsWmgCIL5P63CLLw9Ph → 7PoSgDqLcXreA4Amg4KCd}/_buildManifest.js +1 -1
- package/dist/web/_next/static/chunks/pages/home-e9b4955fe2fcbdc3.js +13 -0
- package/dist/web/home/index.html +1 -1
- package/package.json +1 -1
- package/dist/web/_next/static/chunks/pages/home-bae9ffb64fa6efa3.js +0 -13
- /package/dist/web/_next/static/{3LDsWmgCIL5P63CLLw9Ph → 7PoSgDqLcXreA4Amg4KCd}/_ssgManifest.js +0 -0
package/dist/vibeflow.mjs
CHANGED
|
@@ -168,8 +168,8 @@ function shellArgs(shell, command) {
|
|
|
168
168
|
const isPosixShell = process.platform !== "win32" || shell.toLowerCase().endsWith("bash.exe");
|
|
169
169
|
if (isPosixShell) return command ? ["-lic", command] : ["-l"];
|
|
170
170
|
if (command) {
|
|
171
|
-
const
|
|
172
|
-
return ["-NoProfile", "-NonInteractive", "-Command", `Write-Host '${
|
|
171
|
+
const message2 = GIT_BASH_MISSING_MESSAGE.replace(/'/g, "''");
|
|
172
|
+
return ["-NoProfile", "-NonInteractive", "-Command", `Write-Host '${message2}' -ForegroundColor Yellow; exit 1`];
|
|
173
173
|
}
|
|
174
174
|
return ["-NoProfile"];
|
|
175
175
|
}
|
|
@@ -638,7 +638,7 @@ function masterSystemPrompt(opts) {
|
|
|
638
638
|
'2. \u6D3E\u5DE5\uFF1AVF task create --store-path "$VIBEFLOW_STORE_DIR" --master "$VIBEFLOW_TASK_ID" --project <repo \u7D55\u5C0D\u8DEF\u5F91> --title <\u6A19\u984C> --prompt <\u5167\u5BB9>',
|
|
639
639
|
" prompt \u5FC5\u9808\u81EA\u5305\u542B\uFF1A\u80CC\u666F\u3001\u7BC4\u570D\u3001\u9A57\u6536\u689D\u4EF6\u3001\u8207\u5176\u4ED6\u5361\u7684\u4ECB\u9762\u7D04\u5B9A\u2014\u2014slave \u770B\u4E0D\u5230\u4F60\u7684\u5C0D\u8A71\u3002",
|
|
640
640
|
" \u6A19\u984C\u8981\u77ED\u3001\u5F7C\u6B64\u4E00\u773C\u5206\u5F97\u51FA\u4F86\uFF1A\u4EE5\u9019\u5F35\u5361\u8CA0\u8CAC\u7684\u90E8\u5206\u958B\u982D\uFF08\u4F8B\u5982\u300C\u5F8C\u7AEF\uFF1A\u2026\u300D\u300C\u9A57\u6536\uFF1A\u2026\u300D\uFF09\uFF0C\u4E0D\u8981\u8B93\u591A\u5F35\u5361\u5171\u7528\u540C\u4E00\u6BB5\u958B\u982D\u3002",
|
|
641
|
-
" \
|
|
641
|
+
" \u9810\u8A2D\u4E0D\u8981\u52A0 --model / --effort\uFF1A\u6C92\u6307\u5B9A\u6642 Jev \u6703\u4F9D\u4EFB\u52D9\u8907\u96DC\u5EA6\u6311\u6A21\u578B\u8207 effort\uFF1B\u53EA\u6709\u4EFB\u52D9\u660E\u78BA\u9700\u8981\u7279\u5B9A\u6A21\u578B\u6216 effort \u6642\u624D\u6307\u5B9A\u3002\u9700\u8981\u6642\u53EF\u52A0 --agent / --base-branch\u3002"
|
|
642
642
|
);
|
|
643
643
|
lines.push(
|
|
644
644
|
opts.autoMode ? '3. \u555F\u52D5\uFF1A\u6C92\u6709\u524D\u7F6E\u4F9D\u8CF4\u7684\u5361\u76F4\u63A5 VF task start --store-path "$VIBEFLOW_STORE_DIR" --task <id>\uFF1B\u6709\u4F9D\u8CF4\u7684\u5148\u7559\u5728 Backlog\uFF0C\u524D\u7F6E\u5361\u5B8C\u6210\u5F8C\u518D\u555F\u52D5\u3002' : "3. \u555F\u52D5\uFF1A\u4E0D\u8981\u81EA\u5DF1\u555F\u52D5\u5361\u7247\u3002\u5217\u51FA\u4F60\u5EFA\u4E86\u54EA\u4E9B\u5361\u3001\u5EFA\u8B70\u7684\u555F\u52D5\u9806\u5E8F\uFF0C\u7B49\u4F7F\u7528\u8005\u5728 VibeFlow \u6309\u958B\u59CB\u3002"
|
|
@@ -655,12 +655,16 @@ function masterSystemPrompt(opts) {
|
|
|
655
655
|
);
|
|
656
656
|
return lines.join("\n");
|
|
657
657
|
}
|
|
658
|
-
function buildPrompt(task) {
|
|
658
|
+
function buildPrompt(task, preface) {
|
|
659
659
|
const lines = [`\u4EFB\u52D9\u6A19\u984C\uFF1A${task.title}`];
|
|
660
660
|
const description = task.description?.trim();
|
|
661
661
|
if (description) {
|
|
662
662
|
lines.push("", "\u4EFB\u52D9\u63CF\u8FF0\uFF1A", description);
|
|
663
663
|
}
|
|
664
|
+
const context = preface?.context.trim();
|
|
665
|
+
if (preface && context) {
|
|
666
|
+
lines.push("", `\u524D\u7F6E\u5206\u6790\uFF08${preface.model}\uFF0C\u50C5\u4F9B\u53C3\u8003\uFF09\uFF1A`, context);
|
|
667
|
+
}
|
|
664
668
|
return lines.join("\n");
|
|
665
669
|
}
|
|
666
670
|
function executorSessionId(taskId, runId) {
|
|
@@ -718,9 +722,9 @@ function buildAgentCommand(task, systemPrompt, opts, workspacePath) {
|
|
|
718
722
|
const custom = resolveSystemPrompt(systemPrompt);
|
|
719
723
|
const canWrite = Boolean(opts?.boardCli?.cliPath);
|
|
720
724
|
const role = task.role === "master" ? masterSystemPrompt({ canWrite, autoMode: opts?.autoMode === true }) : task.masterId ? slaveSystemPrompt({ canWrite }) : null;
|
|
721
|
-
const sys = role ? [custom, role].filter(Boolean).join("\n\n") : custom;
|
|
725
|
+
const sys = task.masterId && task.role !== "master" ? role ?? "" : role ? [custom, role].filter(Boolean).join("\n\n") : custom;
|
|
722
726
|
const includeTaskPrompt = opts?.includeTaskPrompt !== false;
|
|
723
|
-
const prompt = includeTaskPrompt && !opts?.resume ? buildPrompt(task) : "";
|
|
727
|
+
const prompt = includeTaskPrompt && !opts?.resume ? buildPrompt(task, opts?.preface) : "";
|
|
724
728
|
const sessionId = agent === "claude" && includeTaskPrompt ? executorSessionId(task.id, task.runId) : void 0;
|
|
725
729
|
return boardEnvPrefix(task, opts, workspacePath) + assembleCommand(
|
|
726
730
|
agent,
|
|
@@ -986,13 +990,13 @@ function reduceClaudeLine(state, line) {
|
|
|
986
990
|
if (!entry) return state;
|
|
987
991
|
const at = parseTime(entry.timestamp);
|
|
988
992
|
const next = { ...state, startedAt: state.startedAt ?? at };
|
|
989
|
-
const
|
|
990
|
-
const content = Array.isArray(
|
|
991
|
-
if (entry.type === "assistant" &&
|
|
992
|
-
const usage =
|
|
993
|
-
if (usage && typeof
|
|
993
|
+
const message2 = entry.message;
|
|
994
|
+
const content = Array.isArray(message2?.content) ? message2.content : [];
|
|
995
|
+
if (entry.type === "assistant" && message2) {
|
|
996
|
+
const usage = message2.usage;
|
|
997
|
+
if (usage && typeof message2.id === "string") {
|
|
994
998
|
const u = claudeUsage(usage);
|
|
995
|
-
next.usageById = { ...state.usageById, [
|
|
999
|
+
next.usageById = { ...state.usageById, [message2.id]: u };
|
|
996
1000
|
next.contextTokens = u.input + u.cacheRead + u.cacheWrite;
|
|
997
1001
|
}
|
|
998
1002
|
let tool;
|
|
@@ -1008,11 +1012,11 @@ function reduceClaudeLine(state, line) {
|
|
|
1008
1012
|
}
|
|
1009
1013
|
}
|
|
1010
1014
|
if (tool) next.activity = { state: "working", tool, at };
|
|
1011
|
-
else if (
|
|
1015
|
+
else if (message2.stop_reason === "end_turn") next.activity = { state: "waiting", waitingFor: "input", at };
|
|
1012
1016
|
else next.activity = { state: "working", at };
|
|
1013
1017
|
return next;
|
|
1014
1018
|
}
|
|
1015
|
-
if (entry.type === "user" &&
|
|
1019
|
+
if (entry.type === "user" && message2) {
|
|
1016
1020
|
const result = entry.toolUseResult && typeof entry.toolUseResult === "object" ? entry.toolUseResult : void 0;
|
|
1017
1021
|
let pending = next.pendingTasks;
|
|
1018
1022
|
for (const block of content) {
|
|
@@ -1342,7 +1346,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
1342
1346
|
const [focus, setFocus] = useState(initialFocus);
|
|
1343
1347
|
const [editing, setEditing] = useState(null);
|
|
1344
1348
|
const [draft, setDraft] = useState("");
|
|
1345
|
-
const [
|
|
1349
|
+
const [message2, setMessage] = useState(initialMessage ?? "");
|
|
1346
1350
|
const [busy, setBusy] = useState(null);
|
|
1347
1351
|
const [loadingGit, setLoadingGit] = useState(false);
|
|
1348
1352
|
const [confirmLeave, setConfirmLeave] = useState(false);
|
|
@@ -1561,7 +1565,7 @@ function FormView({ api, ctx, initial, initialFocus, initialMessage, pristine, o
|
|
|
1561
1565
|
)
|
|
1562
1566
|
),
|
|
1563
1567
|
extra ? h(Text, { dimColor: true }, ` ${extra}`) : null,
|
|
1564
|
-
confirmLeave ? h(Text, { color: "yellow" }, "\u6709\u672A\u5132\u5B58\u7684\u8B8A\u66F4\uFF0C\u78BA\u5B9A\u8981\u96E2\u958B\uFF1F\uFF08y/n\uFF09") :
|
|
1568
|
+
confirmLeave ? h(Text, { color: "yellow" }, "\u6709\u672A\u5132\u5B58\u7684\u8B8A\u66F4\uFF0C\u78BA\u5B9A\u8981\u96E2\u958B\uFF1F\uFF08y/n\uFF09") : message2 ? h(Text, { color: "yellow" }, message2) : h(Text, { dimColor: true }, hint)
|
|
1565
1569
|
);
|
|
1566
1570
|
}
|
|
1567
1571
|
function showForm(api, ctx, initial, pristine, initialFocus = 0, initialMessage) {
|
|
@@ -1702,7 +1706,7 @@ function BoardView({ opts, initial, initialMessage, onAction }) {
|
|
|
1702
1706
|
const [sel, setSel] = useState2(initial);
|
|
1703
1707
|
const [running, setRunning] = useState2(/* @__PURE__ */ new Set());
|
|
1704
1708
|
const [backend, setBackend] = useState2("pty");
|
|
1705
|
-
const [
|
|
1709
|
+
const [message2, setMessage] = useState2(initialMessage ?? "");
|
|
1706
1710
|
const [confirm, setConfirm] = useState2(null);
|
|
1707
1711
|
const [help, setHelp] = useState2(false);
|
|
1708
1712
|
const [progress, setProgress] = useState2({});
|
|
@@ -1913,7 +1917,7 @@ function BoardView({ opts, initial, initialMessage, onAction }) {
|
|
|
1913
1917
|
Box2,
|
|
1914
1918
|
{ flexDirection: "column" },
|
|
1915
1919
|
h2(Box2, { flexDirection: "row" }, ...columns),
|
|
1916
|
-
confirm ? h2(Text2, { color: "yellow" }, confirm.prompt) :
|
|
1920
|
+
confirm ? h2(Text2, { color: "yellow" }, confirm.prompt) : message2 ? h2(Text2, { color: "yellow" }, message2) : h2(
|
|
1917
1921
|
Text2,
|
|
1918
1922
|
{ dimColor: true },
|
|
1919
1923
|
`h/l \u5207\u6B04 \xB7 j/k \u9078\u5361 \xB7 H/L \u79FB\u52D5 \xB7 Enter \u7D42\u7AEF \xB7 n \u65B0\u589E \xB7 e \u7DE8\u8F2F \xB7 d diff \xB7 w Web \xB7 ? \u8AAA\u660E \xB7 q \u96E2\u958B [${backend}]`
|
|
@@ -2037,24 +2041,24 @@ async function runForm(opts, action) {
|
|
|
2037
2041
|
}
|
|
2038
2042
|
async function runTui(opts) {
|
|
2039
2043
|
let sel = { column: 1, index: 0 };
|
|
2040
|
-
let
|
|
2044
|
+
let message2;
|
|
2041
2045
|
for (; ; ) {
|
|
2042
|
-
const result = await showBoard(opts, sel,
|
|
2046
|
+
const result = await showBoard(opts, sel, message2);
|
|
2043
2047
|
sel = result.sel;
|
|
2044
|
-
|
|
2048
|
+
message2 = void 0;
|
|
2045
2049
|
const { action } = result;
|
|
2046
2050
|
if (action.type === "quit") return;
|
|
2047
2051
|
try {
|
|
2048
|
-
if (action.type === "attach")
|
|
2052
|
+
if (action.type === "attach") message2 = await openTerminal(opts, action.task);
|
|
2049
2053
|
else if (action.type === "diff") showDiff(action.task);
|
|
2050
2054
|
else {
|
|
2051
2055
|
process.stdout.write(CLEAR_SCREEN);
|
|
2052
2056
|
const done = await runForm(opts, action);
|
|
2053
|
-
|
|
2057
|
+
message2 = done.message;
|
|
2054
2058
|
if (done.sel) sel = done.sel;
|
|
2055
2059
|
}
|
|
2056
2060
|
} catch (err) {
|
|
2057
|
-
|
|
2061
|
+
message2 = `\u5931\u6557\uFF1A${err.message}`;
|
|
2058
2062
|
}
|
|
2059
2063
|
process.stdout.write(CLEAR_SCREEN);
|
|
2060
2064
|
}
|
|
@@ -2652,7 +2656,7 @@ function createBridge(t) {
|
|
|
2652
2656
|
restoreBuiltinSkill: (payload) => t.invoke("library:restoreBuiltin", payload),
|
|
2653
2657
|
/** Shipped skills the user deleted, offered for restore. */
|
|
2654
2658
|
listRemovedBuiltinSkills: () => t.invoke("library:removedBuiltins"),
|
|
2655
|
-
approve: (taskId,
|
|
2659
|
+
approve: (taskId, message2) => t.invoke("git:approve", { taskId, message: message2 }),
|
|
2656
2660
|
/** Use the task's agent CLI to generate a commit message for branch changes. */
|
|
2657
2661
|
generateCommitMessage: (taskId) => t.invoke("git:generateCommitMessage", taskId),
|
|
2658
2662
|
/** Check whether a PR exists for the task's branch. */
|
|
@@ -4233,11 +4237,11 @@ async function getWorktreeDiff(worktreePath, baseBranch) {
|
|
|
4233
4237
|
}
|
|
4234
4238
|
return files;
|
|
4235
4239
|
}
|
|
4236
|
-
async function commitAndPush(worktreePath,
|
|
4240
|
+
async function commitAndPush(worktreePath, message2) {
|
|
4237
4241
|
await git(worktreePath, ["add", "-A"]);
|
|
4238
4242
|
let committed = false;
|
|
4239
4243
|
try {
|
|
4240
|
-
await git(worktreePath, ["commit", "-m",
|
|
4244
|
+
await git(worktreePath, ["commit", "-m", message2]);
|
|
4241
4245
|
committed = true;
|
|
4242
4246
|
} catch {
|
|
4243
4247
|
committed = false;
|
|
@@ -4249,7 +4253,7 @@ async function commitAndPush(worktreePath, message) {
|
|
|
4249
4253
|
} catch {
|
|
4250
4254
|
pushed = false;
|
|
4251
4255
|
}
|
|
4252
|
-
return { committed, pushed, message };
|
|
4256
|
+
return { committed, pushed, message: message2 };
|
|
4253
4257
|
}
|
|
4254
4258
|
var MAX_OUTCOME_COMMITS = 50;
|
|
4255
4259
|
var OUTCOME_LOG_FORMAT = "%h%x00%s";
|
|
@@ -4453,8 +4457,8 @@ init_attachments();
|
|
|
4453
4457
|
function mastersRoot(storeFile) {
|
|
4454
4458
|
return path13.join(path13.dirname(storeFile), "masters");
|
|
4455
4459
|
}
|
|
4456
|
-
function taskError(
|
|
4457
|
-
return Object.assign(new Error(
|
|
4460
|
+
function taskError(message2, code2) {
|
|
4461
|
+
return Object.assign(new Error(message2), { code: code2 });
|
|
4458
4462
|
}
|
|
4459
4463
|
function assertMasterRef(board, masterId, taskId) {
|
|
4460
4464
|
const master = Object.values(board).flat().find((t) => t.id === masterId);
|
|
@@ -4733,8 +4737,8 @@ function createWsTransport(options) {
|
|
|
4733
4737
|
function dispatch(channel, payload) {
|
|
4734
4738
|
for (const cb of Array.from(listeners.get(channel) ?? [])) cb(payload);
|
|
4735
4739
|
}
|
|
4736
|
-
function post(
|
|
4737
|
-
const data = JSON.stringify(
|
|
4740
|
+
function post(message2) {
|
|
4741
|
+
const data = JSON.stringify(message2);
|
|
4738
4742
|
if (socket && socket.readyState === OPEN) socket.send(data);
|
|
4739
4743
|
else queue.push(data);
|
|
4740
4744
|
}
|
|
@@ -4872,13 +4876,13 @@ Examples:
|
|
|
4872
4876
|
`.trim();
|
|
4873
4877
|
var CliFailure = class extends Error {
|
|
4874
4878
|
code;
|
|
4875
|
-
constructor(code2,
|
|
4876
|
-
super(
|
|
4879
|
+
constructor(code2, message2) {
|
|
4880
|
+
super(message2);
|
|
4877
4881
|
this.code = code2;
|
|
4878
4882
|
}
|
|
4879
4883
|
};
|
|
4880
|
-
function fail(code2,
|
|
4881
|
-
throw new CliFailure(code2,
|
|
4884
|
+
function fail(code2, message2) {
|
|
4885
|
+
throw new CliFailure(code2, message2);
|
|
4882
4886
|
}
|
|
4883
4887
|
function requireOneOf(flag, value, allowed) {
|
|
4884
4888
|
if (value !== void 0 && !allowed.includes(value)) {
|
|
@@ -5617,10 +5621,10 @@ function spawnJsonLines(bin, args, opts) {
|
|
|
5617
5621
|
failure = err;
|
|
5618
5622
|
for (const w of waiters.splice(0)) w.reject(err);
|
|
5619
5623
|
};
|
|
5620
|
-
const deliver = (
|
|
5621
|
-
const i = waiters.findIndex((w) => w.match(
|
|
5622
|
-
if (i === -1) inbox.push(
|
|
5623
|
-
else waiters.splice(i, 1)[0].resolve(
|
|
5624
|
+
const deliver = (message2) => {
|
|
5625
|
+
const i = waiters.findIndex((w) => w.match(message2));
|
|
5626
|
+
if (i === -1) inbox.push(message2);
|
|
5627
|
+
else waiters.splice(i, 1)[0].resolve(message2);
|
|
5624
5628
|
};
|
|
5625
5629
|
let buffered = "";
|
|
5626
5630
|
proc.stdout.setEncoding("utf8");
|
|
@@ -5631,13 +5635,13 @@ function spawnJsonLines(bin, args, opts) {
|
|
|
5631
5635
|
const line = buffered.slice(0, nl).trim();
|
|
5632
5636
|
buffered = buffered.slice(nl + 1);
|
|
5633
5637
|
if (!line) continue;
|
|
5634
|
-
let
|
|
5638
|
+
let message2;
|
|
5635
5639
|
try {
|
|
5636
|
-
|
|
5640
|
+
message2 = JSON.parse(line);
|
|
5637
5641
|
} catch {
|
|
5638
5642
|
continue;
|
|
5639
5643
|
}
|
|
5640
|
-
deliver(
|
|
5644
|
+
deliver(message2);
|
|
5641
5645
|
}
|
|
5642
5646
|
});
|
|
5643
5647
|
proc.stderr.setEncoding("utf8");
|
|
@@ -5674,8 +5678,8 @@ function spawnJsonLines(bin, args, opts) {
|
|
|
5674
5678
|
}, opts.timeoutMs);
|
|
5675
5679
|
let graceTimer;
|
|
5676
5680
|
return {
|
|
5677
|
-
send(
|
|
5678
|
-
if (!failure) proc.stdin.write(`${JSON.stringify(
|
|
5681
|
+
send(message2) {
|
|
5682
|
+
if (!failure) proc.stdin.write(`${JSON.stringify(message2)}
|
|
5679
5683
|
`);
|
|
5680
5684
|
},
|
|
5681
5685
|
next(match) {
|
|
@@ -5708,11 +5712,11 @@ function openClaude() {
|
|
|
5708
5712
|
function isRecord(value) {
|
|
5709
5713
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5710
5714
|
}
|
|
5711
|
-
function isOurResponse(
|
|
5712
|
-
return isRecord(
|
|
5715
|
+
function isOurResponse(message2) {
|
|
5716
|
+
return isRecord(message2) && message2.type === "control_response" && isRecord(message2.response) && message2.response.request_id === REQUEST_ID;
|
|
5713
5717
|
}
|
|
5714
|
-
function parseClaudeInitialize(
|
|
5715
|
-
const outer = isRecord(
|
|
5718
|
+
function parseClaudeInitialize(message2) {
|
|
5719
|
+
const outer = isRecord(message2) && isRecord(message2.response) ? message2.response : null;
|
|
5716
5720
|
if (outer?.subtype === "error") throw new Error(`claude refused the handshake: ${String(outer.error ?? "unknown error")}`);
|
|
5717
5721
|
const body = outer && isRecord(outer.response) ? outer.response : null;
|
|
5718
5722
|
if (!body || !Array.isArray(body.models)) throw new Error("claude handshake has no models array");
|
|
@@ -5773,12 +5777,12 @@ function openCodex() {
|
|
|
5773
5777
|
function isRecord2(value) {
|
|
5774
5778
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5775
5779
|
}
|
|
5776
|
-
var responseTo = (id) => (
|
|
5777
|
-
function resultOf(
|
|
5778
|
-
if (!isRecord2(
|
|
5779
|
-
if (isRecord2(
|
|
5780
|
-
if (!isRecord2(
|
|
5781
|
-
return
|
|
5780
|
+
var responseTo = (id) => (message2) => isRecord2(message2) && message2.id === id && ("result" in message2 || "error" in message2);
|
|
5781
|
+
function resultOf(message2, method) {
|
|
5782
|
+
if (!isRecord2(message2)) throw new Error(`codex ${method}: malformed response`);
|
|
5783
|
+
if (isRecord2(message2.error)) throw new Error(`codex ${method}: ${String(message2.error.message ?? "request failed")}`);
|
|
5784
|
+
if (!isRecord2(message2.result)) throw new Error(`codex ${method}: response has no result`);
|
|
5785
|
+
return message2.result;
|
|
5782
5786
|
}
|
|
5783
5787
|
function isCodexSignedIn(result) {
|
|
5784
5788
|
return result.account != null || result.requiresOpenaiAuth === false;
|
|
@@ -5941,53 +5945,175 @@ init_effort();
|
|
|
5941
5945
|
init_launch();
|
|
5942
5946
|
var API_URL = "https://api.typesafe.ai/v1/systemone";
|
|
5943
5947
|
var MAX_TASK_CHARS = 12e3;
|
|
5948
|
+
var MAX_CONTEXT_CHARS = 8e3;
|
|
5949
|
+
var SCOUT_TIMEOUT_MS = 5 * 6e4;
|
|
5950
|
+
var SAFE_MODEL_ID = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/;
|
|
5951
|
+
function tier(model, agent) {
|
|
5952
|
+
const name = `${model.id} ${model.label}`.toLowerCase();
|
|
5953
|
+
if (/haiku|mini|nano|luna|flash/.test(name)) return 0;
|
|
5954
|
+
if (/opus|fable|astra|pro\b/.test(name)) return 2;
|
|
5955
|
+
if (agent === "codex" && /gpt-5\.5|gpt-5\.4(?!-mini)/.test(name)) return 2;
|
|
5956
|
+
return 1;
|
|
5957
|
+
}
|
|
5958
|
+
var TIER_LABELS = ["lowest cost", "balanced", "highest capability"];
|
|
5959
|
+
function routeCandidates(agent, models) {
|
|
5960
|
+
const byTier = /* @__PURE__ */ new Map();
|
|
5961
|
+
for (const model of models) {
|
|
5962
|
+
if (!SAFE_MODEL_ID.test(model.id) || model.id === "default") continue;
|
|
5963
|
+
const rank = tier(model, agent);
|
|
5964
|
+
if (!byTier.has(rank)) byTier.set(rank, model);
|
|
5965
|
+
}
|
|
5966
|
+
return [...byTier.entries()].sort(([a], [b]) => a - b).map(([, model]) => model);
|
|
5967
|
+
}
|
|
5968
|
+
function isChoice(value) {
|
|
5969
|
+
return !!value && typeof value === "object" && value.type === "choice" && typeof value.choice === "string";
|
|
5970
|
+
}
|
|
5971
|
+
var defaultScout = (agent, model, effort, prompt, cwd) => {
|
|
5972
|
+
const args = agent === "claude" ? ["-p", "--model", model, "--permission-mode", "plan", ...effort ? ["--effort", effort] : []] : [
|
|
5973
|
+
"exec",
|
|
5974
|
+
"--model",
|
|
5975
|
+
model,
|
|
5976
|
+
...effort ? ["-c", `model_reasoning_effort=${effort}`] : [],
|
|
5977
|
+
"--sandbox",
|
|
5978
|
+
"read-only",
|
|
5979
|
+
"--skip-git-repo-check",
|
|
5980
|
+
"-"
|
|
5981
|
+
];
|
|
5982
|
+
return runAgentPrint(agent, args, prompt, { cwd, timeout: SCOUT_TIMEOUT_MS, maxBuffer: 128 * 1024 });
|
|
5983
|
+
};
|
|
5944
5984
|
function createJevRouter(opts = {}) {
|
|
5945
5985
|
const getApiKey = opts.getApiKey ?? (() => opts.apiKey ?? process.env.TYPESAFE_API_KEY?.trim());
|
|
5946
5986
|
const fetcher = opts.fetcher ?? fetch;
|
|
5987
|
+
const scout = opts.scout ?? defaultScout;
|
|
5988
|
+
async function ask(state, questions) {
|
|
5989
|
+
const apiKey = getApiKey();
|
|
5990
|
+
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");
|
|
5991
|
+
const response = await fetcher(API_URL, {
|
|
5992
|
+
method: "POST",
|
|
5993
|
+
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
5994
|
+
body: JSON.stringify({ model: "jev-latest", state, questions }),
|
|
5995
|
+
signal: AbortSignal.timeout(15e3)
|
|
5996
|
+
});
|
|
5997
|
+
if (response.status === 402 || response.status === 429) {
|
|
5998
|
+
throw new Error(`Jev \u984D\u5EA6\u5DF2\u7528\u5B8C\u6216\u8ACB\u6C42\u904E\u591A\uFF08HTTP ${response.status}\uFF09\uFF0C\u6539\u7528 CLI \u76EE\u524D\u7684\u6A21\u578B`);
|
|
5999
|
+
}
|
|
6000
|
+
if (!response.ok) throw new Error(`Jev API \u56DE\u61C9 ${response.status}`);
|
|
6001
|
+
const body = await response.json();
|
|
6002
|
+
if (!body.answers) throw new Error("Jev API \u6C92\u6709\u56DE\u50B3\u5224\u65B7");
|
|
6003
|
+
return body.answers;
|
|
6004
|
+
}
|
|
6005
|
+
async function routeEffort(task, catalog) {
|
|
6006
|
+
const model = modelFor(catalog, taskModel(task));
|
|
6007
|
+
const levels = selectableEfforts(model);
|
|
6008
|
+
if (levels.length === 0) return { status: "fallback", reason: "\u76EE\u524D\u6A21\u578B\u4E0D\u652F\u63F4\u8ABF\u6574 effort" };
|
|
6009
|
+
try {
|
|
6010
|
+
const answers = await ask({
|
|
6011
|
+
task: buildPrompt(task).slice(0, MAX_TASK_CHARS),
|
|
6012
|
+
agent: taskAgent(task),
|
|
6013
|
+
currentModel: model?.id ?? taskModel(task) ?? "CLI default (catalog unavailable)"
|
|
6014
|
+
}, { effort: effortQuestion(levels) });
|
|
6015
|
+
const choice = answers.effort;
|
|
6016
|
+
if (!isChoice(choice) || !levels.includes(choice.choice)) {
|
|
6017
|
+
throw new Error("Jev \u9078\u4E86\u76EE\u524D\u6A21\u578B\u4E0D\u652F\u63F4\u7684 effort");
|
|
6018
|
+
}
|
|
6019
|
+
return { status: "routed", effort: choice.choice };
|
|
6020
|
+
} catch (err) {
|
|
6021
|
+
return { status: "fallback", reason: message(err) };
|
|
6022
|
+
}
|
|
6023
|
+
}
|
|
6024
|
+
async function routeModel(task, catalog, ro) {
|
|
6025
|
+
const agent = taskAgent(task);
|
|
6026
|
+
const candidates = routeCandidates(agent, catalog);
|
|
6027
|
+
if (candidates.length === 0) return { status: "fallback", reason: "\u6A21\u578B\u6E05\u55AE\u6C92\u6709\u53EF\u7528\u7684\u6A21\u578B" };
|
|
6028
|
+
const chooseEffort = task.effort === "auto";
|
|
6029
|
+
const strongest = candidates[candidates.length - 1];
|
|
6030
|
+
const levels = MANUAL_EFFORTS.filter((level) => candidates.some((m) => selectableEfforts(m).includes(level)));
|
|
6031
|
+
const taskText = buildPrompt(task).slice(0, MAX_TASK_CHARS);
|
|
6032
|
+
const modelQuestion = {
|
|
6033
|
+
type: "choice",
|
|
6034
|
+
instructions: "Choose the lowest-cost available model likely to implement this software task correctly. Prefer more capable models as complexity, ambiguity or risk rises.",
|
|
6035
|
+
criteria: Object.fromEntries(candidates.map((m) => [m.id, `${m.label}; ${TIER_LABELS[tier(m, agent)]}`]))
|
|
6036
|
+
};
|
|
6037
|
+
const questions = (withUnclear) => ({
|
|
6038
|
+
complexity: {
|
|
6039
|
+
type: "choice",
|
|
6040
|
+
instructions: "How difficult is this software task to implement correctly?",
|
|
6041
|
+
criteria: {
|
|
6042
|
+
simple: "Small, well scoped and routine",
|
|
6043
|
+
moderate: "Some design choices or multiple files",
|
|
6044
|
+
complex: "Architecture, ambiguous requirements, high risk, or many interacting parts",
|
|
6045
|
+
...withUnclear ? { unclear: "Cannot be judged from the description alone; the repository must be read first" } : {}
|
|
6046
|
+
}
|
|
6047
|
+
},
|
|
6048
|
+
model: modelQuestion,
|
|
6049
|
+
...chooseEffort && levels.length > 0 ? { effort: effortQuestion(levels) } : {}
|
|
6050
|
+
});
|
|
6051
|
+
const decide = (answers, extra) => {
|
|
6052
|
+
const model = candidates.find((m) => isChoice(answers.model) && m.id === answers.model.choice);
|
|
6053
|
+
if (!model) throw new Error("Jev \u9078\u4E86\u4E0D\u5728\u6A21\u578B\u6E05\u55AE\u4E2D\u7684\u6A21\u578B");
|
|
6054
|
+
let effort;
|
|
6055
|
+
if (chooseEffort && levels.length > 0) {
|
|
6056
|
+
const choice = answers.effort;
|
|
6057
|
+
if (!isChoice(choice) || !levels.includes(choice.choice)) throw new Error("Jev \u56DE\u50B3\u4E0D\u53D7\u652F\u63F4\u7684 effort");
|
|
6058
|
+
effort = clampEffort(choice.choice, selectableEfforts(model));
|
|
6059
|
+
}
|
|
6060
|
+
return { status: "routed", model: model.id, ...effort ? { effort } : {}, ...extra };
|
|
6061
|
+
};
|
|
6062
|
+
const conservative = (extra) => {
|
|
6063
|
+
const effort = chooseEffort ? clampEffort("high", selectableEfforts(strongest)) : void 0;
|
|
6064
|
+
return { model: strongest.id, ...effort ? { effort } : {}, ...extra };
|
|
6065
|
+
};
|
|
6066
|
+
let first;
|
|
6067
|
+
let complexity;
|
|
6068
|
+
try {
|
|
6069
|
+
ro.onPhase?.("judging");
|
|
6070
|
+
first = await ask({ task: taskText, agent }, questions(true));
|
|
6071
|
+
const c = first.complexity;
|
|
6072
|
+
if (!isChoice(c) || !["simple", "moderate", "complex", "unclear"].includes(c.choice)) throw new Error("Jev \u56DE\u50B3\u4E0D\u53D7\u652F\u63F4\u7684\u8907\u96DC\u5EA6");
|
|
6073
|
+
complexity = c.choice;
|
|
6074
|
+
if (complexity !== "unclear") return decide(first, { complexity });
|
|
6075
|
+
} catch (err) {
|
|
6076
|
+
return { status: "fallback", reason: message(err) };
|
|
6077
|
+
}
|
|
6078
|
+
if (ro.scout === false) return conservative({ status: "routed", complexity });
|
|
6079
|
+
let context;
|
|
6080
|
+
try {
|
|
6081
|
+
if (!ro.cwd) throw new Error("\u88DC\u5145 context \u6642\u627E\u4E0D\u5230 worktree");
|
|
6082
|
+
ro.onPhase?.("scouting");
|
|
6083
|
+
const scoutEffort = clampEffort("high", selectableEfforts(strongest));
|
|
6084
|
+
const instruction = "Read the repository to prepare the following software task. Do not edit any file. Report concisely: the affected areas and files, requirements that are unclear, the main risks, and how to verify the work. Return only the analysis.\n\n" + taskText;
|
|
6085
|
+
context = (await scout(agent, strongest.id, scoutEffort, instruction, ro.cwd)).trim().slice(0, MAX_CONTEXT_CHARS);
|
|
6086
|
+
if (!context) throw new Error("\u88DC\u5145 context \u7684\u6A21\u578B\u6C92\u6709\u56DE\u50B3\u5206\u6790");
|
|
6087
|
+
} catch (err) {
|
|
6088
|
+
return conservative({ status: "fallback", complexity, reason: message(err) });
|
|
6089
|
+
}
|
|
6090
|
+
try {
|
|
6091
|
+
ro.onPhase?.("selecting");
|
|
6092
|
+
const second = await ask({ task: taskText, agent, context }, questions(false));
|
|
6093
|
+
return decide(second, { complexity, scoutModel: strongest.id, context });
|
|
6094
|
+
} catch (err) {
|
|
6095
|
+
return { status: "fallback", complexity, reason: message(err), scoutModel: strongest.id, context };
|
|
6096
|
+
}
|
|
6097
|
+
}
|
|
5947
6098
|
return {
|
|
5948
6099
|
get enabled() {
|
|
5949
6100
|
return Boolean(getApiKey());
|
|
5950
6101
|
},
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
const levels = selectableEfforts(model);
|
|
5954
|
-
if (levels.length === 0) return { status: "fallback", reason: "\u76EE\u524D\u6A21\u578B\u4E0D\u652F\u63F4\u8ABF\u6574 effort" };
|
|
5955
|
-
try {
|
|
5956
|
-
const apiKey = getApiKey();
|
|
5957
|
-
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");
|
|
5958
|
-
const response = await fetcher(API_URL, {
|
|
5959
|
-
method: "POST",
|
|
5960
|
-
headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
|
|
5961
|
-
body: JSON.stringify({
|
|
5962
|
-
model: "jev-latest",
|
|
5963
|
-
state: {
|
|
5964
|
-
task: buildPrompt(task).slice(0, MAX_TASK_CHARS),
|
|
5965
|
-
agent: task.agentCli === "codex" ? "codex" : "claude",
|
|
5966
|
-
currentModel: model?.id ?? taskModel(task) ?? "CLI default (catalog unavailable)"
|
|
5967
|
-
},
|
|
5968
|
-
questions: {
|
|
5969
|
-
effort: {
|
|
5970
|
-
type: "choice",
|
|
5971
|
-
instructions: "Choose the lowest reasoning effort likely to complete this software task correctly on the current model. Increase effort for complexity, ambiguity, or risk.",
|
|
5972
|
-
criteria: Object.fromEntries(levels.map((level) => [level, effortDescription(level)]))
|
|
5973
|
-
}
|
|
5974
|
-
}
|
|
5975
|
-
}),
|
|
5976
|
-
signal: AbortSignal.timeout(15e3)
|
|
5977
|
-
});
|
|
5978
|
-
if (!response.ok) throw new Error(`Jev API \u56DE\u61C9 ${response.status}`);
|
|
5979
|
-
const body = await response.json();
|
|
5980
|
-
const choice = body.answers?.effort;
|
|
5981
|
-
if (choice?.type !== "choice" || !levels.includes(choice.choice)) {
|
|
5982
|
-
throw new Error("Jev \u9078\u4E86\u76EE\u524D\u6A21\u578B\u4E0D\u652F\u63F4\u7684 effort");
|
|
5983
|
-
}
|
|
5984
|
-
return { status: "routed", effort: choice.choice };
|
|
5985
|
-
} catch (err) {
|
|
5986
|
-
return { status: "fallback", reason: err instanceof Error ? err.message : String(err) };
|
|
5987
|
-
}
|
|
6102
|
+
route(task, catalog, ro = {}) {
|
|
6103
|
+
return taskModel(task) ? routeEffort(task, catalog) : routeModel(task, catalog, ro);
|
|
5988
6104
|
}
|
|
5989
6105
|
};
|
|
5990
6106
|
}
|
|
6107
|
+
function effortQuestion(levels) {
|
|
6108
|
+
return {
|
|
6109
|
+
type: "choice",
|
|
6110
|
+
instructions: "Choose the lowest reasoning effort likely to complete this software task correctly on the chosen model. Increase effort for complexity, ambiguity, or risk.",
|
|
6111
|
+
criteria: Object.fromEntries(levels.map((level) => [level, effortDescription(level)]))
|
|
6112
|
+
};
|
|
6113
|
+
}
|
|
6114
|
+
function message(err) {
|
|
6115
|
+
return err instanceof Error ? err.message : String(err);
|
|
6116
|
+
}
|
|
5991
6117
|
function effortDescription(level) {
|
|
5992
6118
|
const descriptions = {
|
|
5993
6119
|
low: "Routine, small and well scoped work",
|
|
@@ -6116,11 +6242,11 @@ async function getGitHubCliAuthStatus() {
|
|
|
6116
6242
|
} catch {
|
|
6117
6243
|
}
|
|
6118
6244
|
}
|
|
6119
|
-
const
|
|
6245
|
+
const message2 = errorMessage2(err);
|
|
6120
6246
|
return {
|
|
6121
|
-
installed: !/ENOENT|not found/i.test(
|
|
6247
|
+
installed: !/ENOENT|not found/i.test(message2),
|
|
6122
6248
|
authenticated: false,
|
|
6123
|
-
error:
|
|
6249
|
+
error: message2
|
|
6124
6250
|
};
|
|
6125
6251
|
}
|
|
6126
6252
|
}
|
|
@@ -6706,13 +6832,13 @@ function setConversation(taskId, conversation) {
|
|
|
6706
6832
|
function loadConversation(taskId) {
|
|
6707
6833
|
return getChatStore().get("conversations")[taskId] ?? null;
|
|
6708
6834
|
}
|
|
6709
|
-
function appendMessage(taskId,
|
|
6835
|
+
function appendMessage(taskId, message2) {
|
|
6710
6836
|
const existing = loadConversation(taskId) ?? {
|
|
6711
6837
|
taskId,
|
|
6712
6838
|
messages: [],
|
|
6713
6839
|
updatedAt: 0
|
|
6714
6840
|
};
|
|
6715
|
-
existing.messages.push(
|
|
6841
|
+
existing.messages.push(message2);
|
|
6716
6842
|
existing.updatedAt = Date.now();
|
|
6717
6843
|
setConversation(taskId, existing);
|
|
6718
6844
|
}
|
|
@@ -7267,8 +7393,8 @@ var PASTE_END = "\x1B[201~";
|
|
|
7267
7393
|
var PASTE_GAP_MS = 200;
|
|
7268
7394
|
var DEFAULT_QUIET_MS = 3e3;
|
|
7269
7395
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
7270
|
-
function coded(code2,
|
|
7271
|
-
return Object.assign(new Error(
|
|
7396
|
+
function coded(code2, message2) {
|
|
7397
|
+
return Object.assign(new Error(message2), { code: code2 });
|
|
7272
7398
|
}
|
|
7273
7399
|
function isBlocked(activity) {
|
|
7274
7400
|
return activity?.state === "waiting" && activity.waitingFor === "permission";
|
|
@@ -7453,11 +7579,11 @@ var InvalidRequestError = class extends Error {
|
|
|
7453
7579
|
};
|
|
7454
7580
|
var STANDALONE_KEY = /^terminal_[0-9a-f-]{36}$/;
|
|
7455
7581
|
var MAX_MESSAGE_LENGTH = 2e4;
|
|
7456
|
-
function coded2(code2,
|
|
7457
|
-
return Object.assign(new Error(
|
|
7582
|
+
function coded2(code2, message2) {
|
|
7583
|
+
return Object.assign(new Error(message2), { code: code2 });
|
|
7458
7584
|
}
|
|
7459
|
-
function invalid(
|
|
7460
|
-
throw new InvalidRequestError(
|
|
7585
|
+
function invalid(message2) {
|
|
7586
|
+
throw new InvalidRequestError(message2);
|
|
7461
7587
|
}
|
|
7462
7588
|
function str(value, name) {
|
|
7463
7589
|
if (typeof value !== "string") invalid(`${name} must be a string`);
|
|
@@ -7638,16 +7764,23 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
7638
7764
|
const task = requireTask(key.split(":")[0]);
|
|
7639
7765
|
return str(task.worktreePath ?? task.projectPath, "directory");
|
|
7640
7766
|
}
|
|
7767
|
+
function launchModel(task, route) {
|
|
7768
|
+
return taskModel(task) ?? route?.model;
|
|
7769
|
+
}
|
|
7641
7770
|
function launchEffort(task, route) {
|
|
7642
7771
|
const effort = task.effort === "auto" ? route?.effort : task.effort;
|
|
7643
|
-
const model = models.findModel(taskAgent(task),
|
|
7772
|
+
const model = models.findModel(taskAgent(task), launchModel(task, route));
|
|
7644
7773
|
return model?.efforts ? clampEffort(effort, model.efforts) : effort;
|
|
7645
7774
|
}
|
|
7775
|
+
function settledRoute(task) {
|
|
7776
|
+
return task.jevRoute?.status === "routing" ? void 0 : task.jevRoute;
|
|
7777
|
+
}
|
|
7646
7778
|
async function launchCommand(task, intent) {
|
|
7647
7779
|
const settings = getSettings();
|
|
7648
7780
|
const boardCli = await boardCliLaunchInfo();
|
|
7649
|
-
let route = task
|
|
7650
|
-
|
|
7781
|
+
let route = settledRoute(task);
|
|
7782
|
+
const needsRoute = !taskModel(task) || task.effort === "auto";
|
|
7783
|
+
if (needsRoute && !intent.resume && intent.includeTaskPrompt !== false) {
|
|
7651
7784
|
let pending = routing.get(task.id);
|
|
7652
7785
|
if (!pending) {
|
|
7653
7786
|
const setRoute = (jevRoute) => {
|
|
@@ -7657,7 +7790,12 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
7657
7790
|
pending = (async () => {
|
|
7658
7791
|
setRoute({ status: "routing" });
|
|
7659
7792
|
const candidateModels = (await (router.enabled === false ? models.get(taskAgent(task)) : models.refresh(taskAgent(task)))).models;
|
|
7660
|
-
const selected = await router.route(task, candidateModels
|
|
7793
|
+
const selected = await router.route(task, candidateModels, {
|
|
7794
|
+
// A master has no repo to read, only its notes folder.
|
|
7795
|
+
scout: !isMasterTask(task),
|
|
7796
|
+
cwd: task.worktreePath,
|
|
7797
|
+
onPhase: (phase) => setRoute({ status: "routing", phase })
|
|
7798
|
+
});
|
|
7661
7799
|
setRoute(selected);
|
|
7662
7800
|
return selected;
|
|
7663
7801
|
})().catch((err) => {
|
|
@@ -7668,14 +7806,16 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
7668
7806
|
}
|
|
7669
7807
|
route = await pending;
|
|
7670
7808
|
}
|
|
7809
|
+
const preface = route?.context && route.scoutModel ? { model: route.scoutModel, context: route.context } : void 0;
|
|
7671
7810
|
return buildAgentCommand(
|
|
7672
|
-
{ ...task, model:
|
|
7811
|
+
{ ...task, model: launchModel(task, route), effort: launchEffort(task, route) },
|
|
7673
7812
|
settings.systemPrompt ?? "",
|
|
7674
7813
|
{
|
|
7675
7814
|
resume: intent.resume === true,
|
|
7676
7815
|
includeTaskPrompt: intent.includeTaskPrompt !== false,
|
|
7677
7816
|
boardCli,
|
|
7678
|
-
autoMode: task.autoMode ?? settings.autoMode
|
|
7817
|
+
autoMode: task.autoMode ?? settings.autoMode,
|
|
7818
|
+
preface
|
|
7679
7819
|
},
|
|
7680
7820
|
task.workspacePath
|
|
7681
7821
|
);
|
|
@@ -7784,6 +7924,15 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
7784
7924
|
const task = findTask(taskId);
|
|
7785
7925
|
if (task && sessions.isAttached?.(taskId) === false) await startTaskSession(task, taskId, { taskId });
|
|
7786
7926
|
}
|
|
7927
|
+
function launchChoice(task) {
|
|
7928
|
+
const route = settledRoute(task);
|
|
7929
|
+
const model = launchModel(task, route);
|
|
7930
|
+
const effort = launchEffort(task, route);
|
|
7931
|
+
return {
|
|
7932
|
+
...model ? { model } : {},
|
|
7933
|
+
...effort && effort !== "auto" ? { effort } : {}
|
|
7934
|
+
};
|
|
7935
|
+
}
|
|
7787
7936
|
async function summarizeTasks(filter) {
|
|
7788
7937
|
const board = getState().board;
|
|
7789
7938
|
const alive = new Set(await sessions.list());
|
|
@@ -7805,6 +7954,7 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
7805
7954
|
...task.masterId ? { masterId: task.masterId } : {},
|
|
7806
7955
|
...task.projectName ? { projectName: task.projectName } : {},
|
|
7807
7956
|
...task.branch ? { branch: task.branch } : {},
|
|
7957
|
+
...launchChoice(task),
|
|
7808
7958
|
running: alive.has(task.id),
|
|
7809
7959
|
...task.launchedAt ? { launchedAt: task.launchedAt } : {},
|
|
7810
7960
|
...task.launchError ? { launchError: task.launchError } : {},
|
|
@@ -8194,8 +8344,8 @@ function createCore({ sessions, bus, version, homeDir, ghRunner, githubAuthStatu
|
|
|
8194
8344
|
const file = await readTerminalFile(terminalDirectory(p.sessionKey), str(p.path, "path"), true);
|
|
8195
8345
|
if (!file.ok) return { ok: false, message: file.message };
|
|
8196
8346
|
try {
|
|
8197
|
-
const
|
|
8198
|
-
return
|
|
8347
|
+
const message2 = await getPlatform().openPath(file.path);
|
|
8348
|
+
return message2 ? { ok: false, message: message2 } : { ok: true };
|
|
8199
8349
|
} catch (error) {
|
|
8200
8350
|
return { ok: false, message: error instanceof Error ? error.message : "\u7121\u6CD5\u958B\u555F\u6A94\u6848\u3002" };
|
|
8201
8351
|
}
|