harness-wingman 0.6.1 → 0.8.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/apps/cli/dist/main.js +300 -26
- package/apps/panel/dist/assets/index-BquIYTp8.js +231 -0
- package/apps/panel/dist/assets/index-WYPdL-aq.css +1 -0
- package/apps/panel/dist/index.html +2 -2
- package/package.json +2 -2
- package/apps/panel/dist/assets/index-CEZ7rZoR.css +0 -1
- package/apps/panel/dist/assets/index-DaL6yKlh.js +0 -225
package/apps/cli/dist/main.js
CHANGED
|
@@ -13243,9 +13243,9 @@ var init_dist5 = __esm({
|
|
|
13243
13243
|
// apps/cli/dist/main.js
|
|
13244
13244
|
init_dist2();
|
|
13245
13245
|
init_dist();
|
|
13246
|
-
import { readFileSync as
|
|
13246
|
+
import { readFileSync as readFileSync18 } from "node:fs";
|
|
13247
13247
|
import { homedir as homedir13 } from "node:os";
|
|
13248
|
-
import { dirname as
|
|
13248
|
+
import { dirname as dirname19, resolve as resolve12 } from "node:path";
|
|
13249
13249
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
13250
13250
|
|
|
13251
13251
|
// packages/fixtures/dist/index.js
|
|
@@ -13373,7 +13373,7 @@ function isHookPayload(value) {
|
|
|
13373
13373
|
}
|
|
13374
13374
|
var HOOK_BODY_LIMIT = 1024 * 1024;
|
|
13375
13375
|
function readBody(req) {
|
|
13376
|
-
return new Promise((
|
|
13376
|
+
return new Promise((resolve13, reject) => {
|
|
13377
13377
|
const chunks = [];
|
|
13378
13378
|
let size = 0;
|
|
13379
13379
|
req.on("data", (chunk) => {
|
|
@@ -13385,7 +13385,7 @@ function readBody(req) {
|
|
|
13385
13385
|
}
|
|
13386
13386
|
chunks.push(chunk);
|
|
13387
13387
|
});
|
|
13388
|
-
req.on("end", () =>
|
|
13388
|
+
req.on("end", () => resolve13(Buffer.concat(chunks).toString("utf8")));
|
|
13389
13389
|
req.on("error", reject);
|
|
13390
13390
|
});
|
|
13391
13391
|
}
|
|
@@ -13980,7 +13980,7 @@ function isRecord2(value) {
|
|
|
13980
13980
|
|
|
13981
13981
|
// packages/narrative/dist/parse.js
|
|
13982
13982
|
function isHarnessSystemNotice(text) {
|
|
13983
|
-
return /^\s*<(task-notification|system-reminder)\b/u.test(text);
|
|
13983
|
+
return /^\s*<(task-notification|system-reminder|in-app-browser-context)\b/u.test(text);
|
|
13984
13984
|
}
|
|
13985
13985
|
function parseTranscriptLine(line) {
|
|
13986
13986
|
const trimmed = line.trim();
|
|
@@ -15606,7 +15606,7 @@ function resolveWingmanVersion({ defined, moduleUrl = import.meta.url, readPacka
|
|
|
15606
15606
|
return void 0;
|
|
15607
15607
|
}
|
|
15608
15608
|
function wingmanVersion() {
|
|
15609
|
-
const defined = false ? void 0 : "0.
|
|
15609
|
+
const defined = false ? void 0 : "0.8.0";
|
|
15610
15610
|
return resolveWingmanVersion({
|
|
15611
15611
|
defined,
|
|
15612
15612
|
readPackage: (url) => JSON.parse(readFileSync15(url, "utf8"))
|
|
@@ -16014,10 +16014,23 @@ function createNarrativeService(options = {}) {
|
|
|
16014
16014
|
session.follows.set(path, followTranscript(path, (line) => {
|
|
16015
16015
|
if (closed || generation !== session.generation)
|
|
16016
16016
|
return;
|
|
16017
|
-
|
|
16018
|
-
|
|
16019
|
-
|
|
16020
|
-
session.
|
|
16017
|
+
let timestamp;
|
|
16018
|
+
if (harness === "codex") {
|
|
16019
|
+
const parsed = parseCodexRolloutLine(line);
|
|
16020
|
+
session.codexLines.push(parsed);
|
|
16021
|
+
if (parsed.kind !== "unknown")
|
|
16022
|
+
timestamp = parsed.timestamp;
|
|
16023
|
+
} else {
|
|
16024
|
+
const parsed = parseTranscriptLine(line);
|
|
16025
|
+
session.lines.push(parsed);
|
|
16026
|
+
if (parsed.kind !== "unknown")
|
|
16027
|
+
timestamp = parsed.timestamp;
|
|
16028
|
+
}
|
|
16029
|
+
const endedAt = session.endedAt ?? session.stopAt;
|
|
16030
|
+
if (timestamp !== void 0 && endedAt !== void 0 && Date.parse(timestamp) > Date.parse(endedAt)) {
|
|
16031
|
+
session.endedAt = void 0;
|
|
16032
|
+
session.stopAt = void 0;
|
|
16033
|
+
}
|
|
16021
16034
|
recordToolObservations(harness, session, extractRawToolObservations(harness, line));
|
|
16022
16035
|
session.dirty = true;
|
|
16023
16036
|
notify(harness);
|
|
@@ -16138,13 +16151,8 @@ function createNarrativeService(options = {}) {
|
|
|
16138
16151
|
};
|
|
16139
16152
|
}
|
|
16140
16153
|
}
|
|
16141
|
-
|
|
16142
|
-
|
|
16143
|
-
} else if (name === "Stop") {
|
|
16144
|
-
session.stopAt = event.received_at;
|
|
16145
|
-
} else {
|
|
16146
|
-
session.stopAt = void 0;
|
|
16147
|
-
}
|
|
16154
|
+
session.endedAt = name === "SessionEnd" ? event.received_at : void 0;
|
|
16155
|
+
session.stopAt = name === "Stop" ? event.received_at : void 0;
|
|
16148
16156
|
session.lastEvent = { name, at: event.received_at };
|
|
16149
16157
|
session.dirty = true;
|
|
16150
16158
|
notify(event.harness);
|
|
@@ -16457,6 +16465,7 @@ function createNarrativeService(options = {}) {
|
|
|
16457
16465
|
};
|
|
16458
16466
|
}
|
|
16459
16467
|
projects.push({
|
|
16468
|
+
firstScreen: deriveProjectFirstScreen(plan, parsed?.availability === "available" ? parsed.goal : void 0, summary.currentPoints, sessionViews),
|
|
16460
16469
|
root,
|
|
16461
16470
|
presence: members.length === 0 ? "remembered" : "active",
|
|
16462
16471
|
seenSinceStart: seenProjectRoots.has(rootIdentity),
|
|
@@ -16479,7 +16488,11 @@ function createNarrativeService(options = {}) {
|
|
|
16479
16488
|
sessions: sessionViews
|
|
16480
16489
|
});
|
|
16481
16490
|
}
|
|
16482
|
-
projects.sort((left, right) =>
|
|
16491
|
+
projects.sort((left, right) => {
|
|
16492
|
+
const decisionOrder = Number(right.firstScreen.action.kind === "decision") - Number(left.firstScreen.action.kind === "decision");
|
|
16493
|
+
const activityOrder = (right.firstScreen.lastActivity === void 0 ? 0 : Date.parse(right.firstScreen.lastActivity.at)) - (left.firstScreen.lastActivity === void 0 ? 0 : Date.parse(left.firstScreen.lastActivity.at));
|
|
16494
|
+
return decisionOrder || activityOrder || left.root.localeCompare(right.root);
|
|
16495
|
+
});
|
|
16483
16496
|
return {
|
|
16484
16497
|
projects,
|
|
16485
16498
|
...projectMemoryUnavailable === void 0 ? {} : { memory: { unavailable: projectMemoryUnavailable } }
|
|
@@ -16507,6 +16520,107 @@ function createNarrativeService(options = {}) {
|
|
|
16507
16520
|
loadRememberedProjectRoots();
|
|
16508
16521
|
return { handleEvent, getState, getOverview, getProjects, seedFixture, subscribe, close };
|
|
16509
16522
|
}
|
|
16523
|
+
function deriveProjectFirstScreen(plan, goal, points, sessions) {
|
|
16524
|
+
const source = ".wingman/plan.md nodes(status, children)";
|
|
16525
|
+
const currentPoints = points.map((point) => ({ ...point, source }));
|
|
16526
|
+
const branch = [];
|
|
16527
|
+
const checkpoints = [];
|
|
16528
|
+
function visit(node, ancestors) {
|
|
16529
|
+
const path = [...ancestors, node];
|
|
16530
|
+
const childCurrent = node.children.map((child) => visit(child, path)).some(Boolean);
|
|
16531
|
+
const onCurrentPath = node.status === "in_progress" || childCurrent;
|
|
16532
|
+
if (onCurrentPath && (node.status === "checkpoint" || node.verification !== void 0)) {
|
|
16533
|
+
checkpoints.push({
|
|
16534
|
+
key: node.key,
|
|
16535
|
+
path: path.map((ancestor) => ancestor.text),
|
|
16536
|
+
text: node.text,
|
|
16537
|
+
source: `.wingman/plan.md:${node.line} status / verification`,
|
|
16538
|
+
...node.verification === void 0 ? {} : { verification: node.verification }
|
|
16539
|
+
});
|
|
16540
|
+
}
|
|
16541
|
+
return onCurrentPath;
|
|
16542
|
+
}
|
|
16543
|
+
if (plan.availability === "available") {
|
|
16544
|
+
for (const node of plan.nodes) {
|
|
16545
|
+
if (visit(node, []))
|
|
16546
|
+
branch.push({
|
|
16547
|
+
key: node.key,
|
|
16548
|
+
path: [node.text],
|
|
16549
|
+
text: node.text,
|
|
16550
|
+
source: `.wingman/plan.md:${node.line} \u5F53\u524D\u70B9\u9876\u5C42\u7956\u5148`
|
|
16551
|
+
});
|
|
16552
|
+
}
|
|
16553
|
+
}
|
|
16554
|
+
const requests = [];
|
|
16555
|
+
for (const session of sessions) {
|
|
16556
|
+
if (session.feedback?.state !== "needs_user")
|
|
16557
|
+
continue;
|
|
16558
|
+
requests.push({
|
|
16559
|
+
harness: session.harness,
|
|
16560
|
+
sessionId: session.id,
|
|
16561
|
+
label: session.label,
|
|
16562
|
+
since: session.feedback.since,
|
|
16563
|
+
source: session.feedback.source,
|
|
16564
|
+
...session.feedback.message === void 0 ? {} : { text: session.feedback.message }
|
|
16565
|
+
});
|
|
16566
|
+
}
|
|
16567
|
+
let action;
|
|
16568
|
+
if (requests.length > 0)
|
|
16569
|
+
action = { kind: "decision", items: requests, source: "sessions.feedback(state=needs_user)" };
|
|
16570
|
+
else if (checkpoints.length > 0)
|
|
16571
|
+
action = {
|
|
16572
|
+
kind: "checkpoint",
|
|
16573
|
+
items: checkpoints,
|
|
16574
|
+
source: ".wingman/plan.md \u5F53\u524D\u70B9\u7956\u5148\u8DEF\u5F84 status / verification"
|
|
16575
|
+
};
|
|
16576
|
+
else if (plan.availability === "missing")
|
|
16577
|
+
action = {
|
|
16578
|
+
kind: "insufficient",
|
|
16579
|
+
reason: "no_plan",
|
|
16580
|
+
source: "plan.availability=missing; plan.lookedUp"
|
|
16581
|
+
};
|
|
16582
|
+
else if (plan.availability === "unavailable")
|
|
16583
|
+
action = {
|
|
16584
|
+
kind: "insufficient",
|
|
16585
|
+
reason: "plan_unavailable",
|
|
16586
|
+
source: `plan.availability=unavailable; plan.reason: ${plan.reason}`
|
|
16587
|
+
};
|
|
16588
|
+
else if (sessions.length > 0 && sessions.every((session) => session.feedback === void 0 || session.feedback.state === "unavailable"))
|
|
16589
|
+
action = {
|
|
16590
|
+
kind: "insufficient",
|
|
16591
|
+
reason: "feedback_unavailable",
|
|
16592
|
+
source: "sessions.feedback.state=unavailable / feedback \u672A\u63D0\u4F9B"
|
|
16593
|
+
};
|
|
16594
|
+
else if (currentPoints.length > 0 && sessions.some((session) => !session.ended))
|
|
16595
|
+
action = {
|
|
16596
|
+
kind: "in_progress",
|
|
16597
|
+
source: ".wingman/plan.md currentPoints; sessions.ended=false"
|
|
16598
|
+
};
|
|
16599
|
+
else
|
|
16600
|
+
action = {
|
|
16601
|
+
kind: "insufficient",
|
|
16602
|
+
reason: "no_session",
|
|
16603
|
+
source: `currentPoints.length=${currentPoints.length}; sessions(ended=false).length=${sessions.filter((session) => !session.ended).length}`
|
|
16604
|
+
};
|
|
16605
|
+
const latest = sessions.filter((session) => session.lastActivity !== void 0 && Number.isFinite(Date.parse(session.lastActivity))).sort((left, right) => Date.parse(right.lastActivity) - Date.parse(left.lastActivity))[0];
|
|
16606
|
+
return {
|
|
16607
|
+
source,
|
|
16608
|
+
branch,
|
|
16609
|
+
currentPoints,
|
|
16610
|
+
action,
|
|
16611
|
+
...goal === void 0 ? {} : { goal: { text: goal, source: ".wingman/plan.md \u76EE\u6807: / Goal:" } },
|
|
16612
|
+
...latest === void 0 ? {} : {
|
|
16613
|
+
lastActivity: {
|
|
16614
|
+
at: latest.lastActivity,
|
|
16615
|
+
harness: latest.harness,
|
|
16616
|
+
sessionId: latest.id,
|
|
16617
|
+
label: latest.user.title ?? (latest.title.source === "plan.md \u6B65\u9AA4" ? latest.title.text : latest.label),
|
|
16618
|
+
source: "sessions.lastActivity\uFF08\u6700\u8FD1 hook received_at / transcript timestamp\uFF09\u6700\u5927\u503C",
|
|
16619
|
+
labelSource: latest.user.title !== void 0 ? "sessions.user.title" : latest.title.source === "plan.md \u6B65\u9AA4" ? "sessions.title\uFF08plan.md \u6B65\u9AA4\uFF09" : "sessions.label\uFF08\u4F1A\u8BDD\u5DE5\u4F5C\u76EE\u5F55\u540D / sessionId\uFF09"
|
|
16620
|
+
}
|
|
16621
|
+
}
|
|
16622
|
+
};
|
|
16623
|
+
}
|
|
16510
16624
|
function lastActivityOf(session) {
|
|
16511
16625
|
if (session.lastActivity !== void 0)
|
|
16512
16626
|
return session.lastActivity;
|
|
@@ -17510,10 +17624,108 @@ async function scanValidated(adapter, options) {
|
|
|
17510
17624
|
|
|
17511
17625
|
// apps/cli/dist/server.js
|
|
17512
17626
|
init_dist();
|
|
17627
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
17513
17628
|
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
17514
17629
|
import { readFile as readFile4 } from "node:fs/promises";
|
|
17515
17630
|
import { createServer } from "node:http";
|
|
17516
|
-
import { extname, resolve as
|
|
17631
|
+
import { extname, resolve as resolve11, sep as sep2 } from "node:path";
|
|
17632
|
+
|
|
17633
|
+
// apps/cli/dist/return-target.js
|
|
17634
|
+
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
17635
|
+
import { closeSync as closeSync4, copyFileSync as copyFileSync2, mkdirSync as mkdirSync12, openSync as openSync4, readFileSync as readFileSync17, renameSync as renameSync6, rmSync as rmSync10, statSync as statSync6, writeFileSync as writeFileSync13 } from "node:fs";
|
|
17636
|
+
import { dirname as dirname18, join as join24, resolve as resolve10 } from "node:path";
|
|
17637
|
+
var BUNDLES = [
|
|
17638
|
+
["Terminal", "Terminal.app"],
|
|
17639
|
+
["iTerm", "iTerm.app"],
|
|
17640
|
+
["Ghostty", "Ghostty.app"],
|
|
17641
|
+
["WezTerm", "WezTerm.app"],
|
|
17642
|
+
["Warp", "Warp.app"],
|
|
17643
|
+
["Alacritty", "Alacritty.app"],
|
|
17644
|
+
["kitty", "kitty.app"],
|
|
17645
|
+
["VS Code", "Visual Studio Code.app"]
|
|
17646
|
+
];
|
|
17647
|
+
function detectReturnTargets(homeDir, roots = ["/Applications", join24(homeDir, "Applications")]) {
|
|
17648
|
+
const available = [];
|
|
17649
|
+
for (const [name, bundle] of BUNDLES) {
|
|
17650
|
+
for (const root of new Set(roots.map((root2) => resolve10(root2)))) {
|
|
17651
|
+
const bundlePath = join24(root, bundle);
|
|
17652
|
+
try {
|
|
17653
|
+
if (statSync6(bundlePath).isDirectory())
|
|
17654
|
+
available.push({ name, bundlePath });
|
|
17655
|
+
} catch {
|
|
17656
|
+
}
|
|
17657
|
+
}
|
|
17658
|
+
}
|
|
17659
|
+
return available;
|
|
17660
|
+
}
|
|
17661
|
+
function settingsPath(homeDir) {
|
|
17662
|
+
return join24(homeDir, ".wingman", "state", "settings.json");
|
|
17663
|
+
}
|
|
17664
|
+
function readReturnTargetSettings(homeDir) {
|
|
17665
|
+
let raw;
|
|
17666
|
+
try {
|
|
17667
|
+
raw = readFileSync17(settingsPath(homeDir), "utf8");
|
|
17668
|
+
} catch (error) {
|
|
17669
|
+
if (isRecord8(error) && error.code === "ENOENT")
|
|
17670
|
+
return { version: 1 };
|
|
17671
|
+
return { unavailable: "\u56DE\u8DF3\u8BBE\u7F6E\u65E0\u6CD5\u8BFB\u53D6;\u8BF7\u4EBA\u5DE5\u68C0\u67E5 settings.json" };
|
|
17672
|
+
}
|
|
17673
|
+
try {
|
|
17674
|
+
const value = JSON.parse(raw);
|
|
17675
|
+
if (!isSettings(value))
|
|
17676
|
+
throw new Error("\u4E0D\u662F\u5408\u6CD5 v1 \u7ED3\u6784");
|
|
17677
|
+
return value;
|
|
17678
|
+
} catch {
|
|
17679
|
+
return { unavailable: "\u56DE\u8DF3\u8BBE\u7F6E\u65E0\u6CD5\u89E3\u6790\u6216\u7248\u672C\u672A\u77E5,\u62D2\u7EDD\u8986\u76D6;\u8BF7\u4EBA\u5DE5\u68C0\u67E5 settings.json" };
|
|
17680
|
+
}
|
|
17681
|
+
}
|
|
17682
|
+
function saveReturnTarget(homeDir, bundlePath) {
|
|
17683
|
+
const current = readReturnTargetSettings(homeDir);
|
|
17684
|
+
if ("unavailable" in current)
|
|
17685
|
+
return current;
|
|
17686
|
+
const settings = { version: 1, returnTarget: { bundlePath } };
|
|
17687
|
+
const path = settingsPath(homeDir);
|
|
17688
|
+
const tempPath = join24(dirname18(path), `.settings-${randomBytes5(8).toString("hex")}.tmp`);
|
|
17689
|
+
let fd;
|
|
17690
|
+
try {
|
|
17691
|
+
mkdirSync12(dirname18(path), { recursive: true, mode: 448 });
|
|
17692
|
+
try {
|
|
17693
|
+
copyFileSync2(path, `${path}.bak`);
|
|
17694
|
+
} catch (error) {
|
|
17695
|
+
if (!isRecord8(error) || error.code !== "ENOENT")
|
|
17696
|
+
throw error;
|
|
17697
|
+
}
|
|
17698
|
+
fd = openSync4(tempPath, "wx", 384);
|
|
17699
|
+
writeFileSync13(fd, `${JSON.stringify(settings)}
|
|
17700
|
+
`, "utf8");
|
|
17701
|
+
closeSync4(fd);
|
|
17702
|
+
fd = void 0;
|
|
17703
|
+
renameSync6(tempPath, path);
|
|
17704
|
+
return settings;
|
|
17705
|
+
} catch {
|
|
17706
|
+
return { unavailable: "\u56DE\u8DF3\u8BBE\u7F6E\u5907\u4EFD\u6216\u5199\u5165\u5931\u8D25,\u672A\u8986\u76D6\u8BBE\u7F6E;\u8BF7\u4EBA\u5DE5\u68C0\u67E5 settings.json" };
|
|
17707
|
+
} finally {
|
|
17708
|
+
if (fd !== void 0) {
|
|
17709
|
+
try {
|
|
17710
|
+
closeSync4(fd);
|
|
17711
|
+
} catch {
|
|
17712
|
+
}
|
|
17713
|
+
}
|
|
17714
|
+
try {
|
|
17715
|
+
rmSync10(tempPath, { force: true });
|
|
17716
|
+
} catch {
|
|
17717
|
+
}
|
|
17718
|
+
}
|
|
17719
|
+
}
|
|
17720
|
+
function isSettings(value) {
|
|
17721
|
+
if (!isRecord8(value) || value.version !== 1 || !Object.keys(value).every((key) => key === "version" || key === "returnTarget")) {
|
|
17722
|
+
return false;
|
|
17723
|
+
}
|
|
17724
|
+
return value.returnTarget === void 0 || isRecord8(value.returnTarget) && Object.keys(value.returnTarget).every((key) => key === "bundlePath") && typeof value.returnTarget.bundlePath === "string" && value.returnTarget.bundlePath.startsWith("/");
|
|
17725
|
+
}
|
|
17726
|
+
function isRecord8(value) {
|
|
17727
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17728
|
+
}
|
|
17517
17729
|
|
|
17518
17730
|
// apps/cli/dist/suggest.js
|
|
17519
17731
|
init_dist();
|
|
@@ -17761,6 +17973,10 @@ async function handle(req, res, options, warn, runtime) {
|
|
|
17761
17973
|
await handleTaskOverlay(req, res, options);
|
|
17762
17974
|
return;
|
|
17763
17975
|
}
|
|
17976
|
+
if (url.pathname === "/api/return-target" || url.pathname === "/api/return") {
|
|
17977
|
+
await handleReturn(req, res, options, url.pathname === "/api/return");
|
|
17978
|
+
return;
|
|
17979
|
+
}
|
|
17764
17980
|
if (url.pathname === "/api/license/install" && req.method === "POST") {
|
|
17765
17981
|
await handleLicenseInstall(req, res, options);
|
|
17766
17982
|
return;
|
|
@@ -17992,6 +18208,64 @@ async function handleActionApply(req, res, options, runtime) {
|
|
|
17992
18208
|
sendJson2(res, 400, { error: errorMessage3(error) });
|
|
17993
18209
|
}
|
|
17994
18210
|
}
|
|
18211
|
+
async function handleReturn(req, res, options, activate) {
|
|
18212
|
+
if (req.method !== "POST" && (activate || req.method !== "GET")) {
|
|
18213
|
+
sendText2(res, 405, "method not allowed");
|
|
18214
|
+
return;
|
|
18215
|
+
}
|
|
18216
|
+
if (req.method === "POST" && options.readonlyActions) {
|
|
18217
|
+
sendJson2(res, 403, { error: "fixtures \u6A21\u5F0F\u53EA\u8BFB:\u4E0D\u4FDD\u5B58\u56DE\u8DF3\u8BBE\u7F6E\u6216\u6FC0\u6D3B\u5E94\u7528" });
|
|
18218
|
+
return;
|
|
18219
|
+
}
|
|
18220
|
+
if (options.homeDir === void 0) {
|
|
18221
|
+
sendJson2(res, 500, { error: "\u56DE\u8DF3\u8BBE\u7F6E\u7F3A\u5C11 homeDir" });
|
|
18222
|
+
return;
|
|
18223
|
+
}
|
|
18224
|
+
const available = detectReturnTargets(options.homeDir, options.returnTargetRoots);
|
|
18225
|
+
if (req.method === "GET") {
|
|
18226
|
+
const settings = readReturnTargetSettings(options.homeDir);
|
|
18227
|
+
sendJson2(res, 200, {
|
|
18228
|
+
available,
|
|
18229
|
+
..."unavailable" in settings ? { settings } : settings.returnTarget === void 0 ? {} : { selected: settings.returnTarget }
|
|
18230
|
+
});
|
|
18231
|
+
return;
|
|
18232
|
+
}
|
|
18233
|
+
const body = await readJsonBody(req);
|
|
18234
|
+
if (!isRecord9(body) || Object.keys(body).some((key) => key !== "bundlePath") || typeof body.bundlePath !== "string") {
|
|
18235
|
+
sendJson2(res, 400, { error: "\u8BF7\u6C42\u53EA\u63A5\u53D7 bundlePath \u5B57\u7B26\u4E32" });
|
|
18236
|
+
return;
|
|
18237
|
+
}
|
|
18238
|
+
const target = available.find((target2) => target2.bundlePath === body.bundlePath);
|
|
18239
|
+
if (!target) {
|
|
18240
|
+
sendJson2(res, 400, { error: "\u672A\u68C0\u6D4B\u5230\u8BE5\u56DE\u8DF3\u5E94\u7528" });
|
|
18241
|
+
return;
|
|
18242
|
+
}
|
|
18243
|
+
if (!activate) {
|
|
18244
|
+
const settings = saveReturnTarget(options.homeDir, target.bundlePath);
|
|
18245
|
+
if ("unavailable" in settings)
|
|
18246
|
+
sendJson2(res, 409, { error: settings.unavailable });
|
|
18247
|
+
else
|
|
18248
|
+
sendJson2(res, 200, { selected: settings.returnTarget });
|
|
18249
|
+
return;
|
|
18250
|
+
}
|
|
18251
|
+
try {
|
|
18252
|
+
await (options.opener ?? openReturnTarget)(target.bundlePath);
|
|
18253
|
+
sendJson2(res, 200, { activated: true, name: target.name });
|
|
18254
|
+
} catch (error) {
|
|
18255
|
+
const timedOut = isRecord9(error) && (error.killed === true || error.code === "ETIMEDOUT");
|
|
18256
|
+
sendJson2(res, 200, { activated: false, reason: timedOut ? "\u5E94\u7528\u6FC0\u6D3B\u8D85\u65F6" : "\u5E94\u7528\u6FC0\u6D3B\u5931\u8D25" });
|
|
18257
|
+
}
|
|
18258
|
+
}
|
|
18259
|
+
function openReturnTarget(bundlePath) {
|
|
18260
|
+
return new Promise((resolveOpen, reject) => {
|
|
18261
|
+
execFile2("open", ["-a", bundlePath], { timeout: 5e3 }, (error) => {
|
|
18262
|
+
if (error)
|
|
18263
|
+
reject(error);
|
|
18264
|
+
else
|
|
18265
|
+
resolveOpen();
|
|
18266
|
+
});
|
|
18267
|
+
});
|
|
18268
|
+
}
|
|
17995
18269
|
async function handleTaskOverlay(req, res, options) {
|
|
17996
18270
|
if (options.readonlyActions) {
|
|
17997
18271
|
sendJson2(res, 403, { error: "fixtures \u6A21\u5F0F\u53EA\u8BFB:\u4E0D\u5199\u4EFB\u52A1\u5361 overlay" });
|
|
@@ -18097,11 +18371,11 @@ function isToggleRequest(value) {
|
|
|
18097
18371
|
return o.kind === "toggle" && typeof o.itemId === "string" && typeof o.enable === "boolean";
|
|
18098
18372
|
}
|
|
18099
18373
|
function isTaskOverlayRequest(value) {
|
|
18100
|
-
if (!
|
|
18374
|
+
if (!isRecord9(value) || !isHarnessId3(value.harness))
|
|
18101
18375
|
return false;
|
|
18102
18376
|
if (typeof value.sessionId !== "string" || value.sessionId.trim() === "")
|
|
18103
18377
|
return false;
|
|
18104
|
-
if (!
|
|
18378
|
+
if (!isRecord9(value.patch))
|
|
18105
18379
|
return false;
|
|
18106
18380
|
const keys = Object.keys(value.patch);
|
|
18107
18381
|
if (keys.length === 0 || keys.some((key) => !["title", "pinned", "hidden", "accepted"].includes(key))) {
|
|
@@ -18112,7 +18386,7 @@ function isTaskOverlayRequest(value) {
|
|
|
18112
18386
|
function isHarnessId3(value) {
|
|
18113
18387
|
return typeof value === "string" && HARNESS_IDS.includes(value);
|
|
18114
18388
|
}
|
|
18115
|
-
function
|
|
18389
|
+
function isRecord9(value) {
|
|
18116
18390
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18117
18391
|
}
|
|
18118
18392
|
function readJsonBody(req) {
|
|
@@ -18151,8 +18425,8 @@ async function serveStatic(pathname, res, panelDistDir) {
|
|
|
18151
18425
|
return;
|
|
18152
18426
|
}
|
|
18153
18427
|
const rel = decoded === "/" ? "/index.html" : decoded;
|
|
18154
|
-
const distDir =
|
|
18155
|
-
const filePath =
|
|
18428
|
+
const distDir = resolve11(panelDistDir);
|
|
18429
|
+
const filePath = resolve11(distDir, `.${rel}`);
|
|
18156
18430
|
if (filePath !== distDir && !filePath.startsWith(distDir + sep2)) {
|
|
18157
18431
|
sendText2(res, 403, "forbidden");
|
|
18158
18432
|
return;
|
|
@@ -18305,7 +18579,7 @@ async function runServe(args) {
|
|
|
18305
18579
|
`);
|
|
18306
18580
|
}
|
|
18307
18581
|
}
|
|
18308
|
-
const panelDistDir = panelDist === void 0 ?
|
|
18582
|
+
const panelDistDir = panelDist === void 0 ? resolve12(dirname19(fileURLToPath2(import.meta.url)), "../../panel/dist") : resolve12(panelDist);
|
|
18309
18583
|
const narrative = createNarrativeService({
|
|
18310
18584
|
followTranscripts: !fixtures,
|
|
18311
18585
|
homeDir,
|
|
@@ -18318,7 +18592,7 @@ async function runServe(args) {
|
|
|
18318
18592
|
});
|
|
18319
18593
|
if (fixtures) {
|
|
18320
18594
|
try {
|
|
18321
|
-
const raw =
|
|
18595
|
+
const raw = readFileSync18(fixturePath("cc", "sessions", "session-todos.jsonl"), "utf8");
|
|
18322
18596
|
narrative.seedFixture("cc", raw.split("\n"), "MOCK \u2014 fixtures \u6F14\u793A:\u53D9\u4E8B\u6570\u636E\u6765\u81EA packages/fixtures \u7684 session-todos.jsonl \u6837\u4F8B\u4F1A\u8BDD,\u975E\u672C\u673A\u771F\u5B9E transcript\u3002");
|
|
18323
18597
|
} catch (error) {
|
|
18324
18598
|
const message = error instanceof Error ? error.message : String(error);
|