frizz 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/claude-agent-broker.js +9 -3
- package/dist/dev-child.js +241 -158
- package/dist/frizz.js +24 -3
- package/package.json +1 -1
- package/web-dist/assets/{TerminalPane-DBmtdVkV.js → TerminalPane-K-DhxpCR.js} +1 -1
- package/web-dist/assets/{abnfDiagram-VRR7QNED-s9x3PTMx.js → abnfDiagram-VRR7QNED-D1qyMYic.js} +1 -1
- package/web-dist/assets/architecture-TIHT7OUA-DhCDPuB9.js +1 -0
- package/web-dist/assets/{architectureDiagram-ZJ3FMSHR-CIFfgliT.js → architectureDiagram-ZJ3FMSHR-B7OHBGs-.js} +1 -1
- package/web-dist/assets/{blockDiagram-677ZJIJ3-BC-TeFao.js → blockDiagram-677ZJIJ3-BOkbWfnO.js} +1 -1
- package/web-dist/assets/{c4Diagram-LMCZKHZV-DoJ_Bulk.js → c4Diagram-LMCZKHZV-DcfWo37Z.js} +1 -1
- package/web-dist/assets/channel-C0ssx150.js +1 -0
- package/web-dist/assets/{chunk-32BRIVSS-BgchlScG.js → chunk-32BRIVSS-DG_MDBh7.js} +1 -1
- package/web-dist/assets/{chunk-52WLFC77-D94nMfY5.js → chunk-52WLFC77-HgYoNFkS.js} +1 -1
- package/web-dist/assets/{chunk-C7G6YPKG-BNU4g2Rm.js → chunk-C7G6YPKG-Dfpg508V.js} +1 -1
- package/web-dist/assets/{chunk-EX3LRPZG-DooNeZ0v.js → chunk-EX3LRPZG-zaEux9Wm.js} +1 -1
- package/web-dist/assets/{chunk-FWX5IMBZ-DuXYfpte.js → chunk-FWX5IMBZ-CpSICFGT.js} +2 -2
- package/web-dist/assets/{chunk-HOUHSVGY-DDtc0Lod.js → chunk-HOUHSVGY-CSwYs-ck.js} +1 -1
- package/web-dist/assets/{chunk-ICXQ74PX-D1soMHlW.js → chunk-ICXQ74PX-CkRfiAJk.js} +1 -1
- package/web-dist/assets/{chunk-MOJQB5TN-BYZZoPrO.js → chunk-MOJQB5TN-DFtJBynx.js} +1 -1
- package/web-dist/assets/{chunk-OGEWGWER-CSI1op21.js → chunk-OGEWGWER-B1ST2fth.js} +1 -1
- package/web-dist/assets/{chunk-PUDLZKDR-B2_qeHID.js → chunk-PUDLZKDR-B7ABSn_A.js} +1 -1
- package/web-dist/assets/{chunk-Q4XR5HBZ-BNiafbsU.js → chunk-Q4XR5HBZ-CivO3j1P.js} +1 -1
- package/web-dist/assets/{chunk-V7JOEXUC-D9aOhGjB.js → chunk-V7JOEXUC-BaM6_dmG.js} +1 -1
- package/web-dist/assets/{chunk-VAUOI2AC-mt04_MVl.js → chunk-VAUOI2AC-BY3O_FOQ.js} +1 -1
- package/web-dist/assets/{chunk-VR4S4FIN-CTbhzN9l.js → chunk-VR4S4FIN-BIV_iEar.js} +1 -1
- package/web-dist/assets/{chunk-WYO6CB5R-t-QJiLir.js → chunk-WYO6CB5R-CUi65Li4.js} +1 -1
- package/web-dist/assets/{chunk-ZGVPDNZ5-BNBiwqoz.js → chunk-ZGVPDNZ5-Dg0vMfMN.js} +1 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-DGsI7bj0.js +1 -0
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-DGsI7bj0.js +1 -0
- package/web-dist/assets/{cynefin-VYW2F7L2-CJzDWQw9.js → cynefin-VYW2F7L2-DWJeaT_t.js} +1 -1
- package/web-dist/assets/{cynefinDiagram-TSTJHNR4-C_wWdWpO.js → cynefinDiagram-TSTJHNR4-ClaGZDTr.js} +1 -1
- package/web-dist/assets/{dagre-VKFMJZFB-JcoSMott.js → dagre-VKFMJZFB-C0pp3Xyc.js} +1 -1
- package/web-dist/assets/{diagram-FQU43EPY-DwPIrxvI.js → diagram-FQU43EPY-SSBAJs6v.js} +1 -1
- package/web-dist/assets/{diagram-G47NLZAW-Bs1Iyjn4.js → diagram-G47NLZAW-3GFBBF81.js} +1 -1
- package/web-dist/assets/{diagram-NH7WQ7WH-DFXMkDQZ.js → diagram-NH7WQ7WH-DqYwuzE7.js} +1 -1
- package/web-dist/assets/{diagram-OA4YK3LP-BdeEougN.js → diagram-OA4YK3LP-K6M4KioM.js} +1 -1
- package/web-dist/assets/{diagram-WEI45ONY-DOeCVBYO.js → diagram-WEI45ONY-ByTNMmJD.js} +1 -1
- package/web-dist/assets/{ebnfDiagram-CCIWWBDH-Dm5CrqN3.js → ebnfDiagram-CCIWWBDH-Bl6rAFTA.js} +1 -1
- package/web-dist/assets/{erDiagram-Q63AITRT-B0ud7ncc.js → erDiagram-Q63AITRT-BGWlKkvA.js} +1 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-CwE_bxam.js +1 -0
- package/web-dist/assets/flowDiagram-23GEKE2U-BY0J247Q.js +1 -0
- package/web-dist/assets/{ganttDiagram-NO4QXBWP-BdowNjAm.js → ganttDiagram-NO4QXBWP-C5eEoPLo.js} +1 -1
- package/web-dist/assets/{gitGraph-TEB2WS4Q-BSDXrBNB.js → gitGraph-TEB2WS4Q-BNmphrH5.js} +1 -1
- package/web-dist/assets/{gitGraphDiagram-IHSO6WYX-B3i3egZt.js → gitGraphDiagram-IHSO6WYX-zHU_D41b.js} +1 -1
- package/web-dist/assets/index-C-3lsl4q.css +1 -0
- package/web-dist/assets/{index-BUX0IseR.js → index-Kzg-vTmI.js} +117 -117
- package/web-dist/assets/{info-DKCQHKI2-B7CT3rc8.js → info-DKCQHKI2-BfD-7Xcw.js} +1 -1
- package/web-dist/assets/{infoDiagram-FWYZ7A6U-Bqmpgcu2.js → infoDiagram-FWYZ7A6U-CR3bcaik.js} +1 -1
- package/web-dist/assets/{ishikawaDiagram-FXEZZL3T-Bd5LBQOn.js → ishikawaDiagram-FXEZZL3T-VtEgUbJP.js} +1 -1
- package/web-dist/assets/{journeyDiagram-5HDEW3XC-lJOF3I7X.js → journeyDiagram-5HDEW3XC-DZ3fGB6L.js} +1 -1
- package/web-dist/assets/{kanban-definition-HUTT4EX6-D4E5PRAv.js → kanban-definition-HUTT4EX6-ChfTvN7D.js} +1 -1
- package/web-dist/assets/{line-C9ZcrRyz.js → line-B6kig2Co.js} +1 -1
- package/web-dist/assets/{mermaid-parser.core-DkaL73Gv.js → mermaid-parser.core-jyk1DbDV.js} +3 -3
- package/web-dist/assets/{mermaid.core-BQ89ySVU.js → mermaid.core-C5yyeZnx.js} +3 -3
- package/web-dist/assets/{mindmap-definition-LN4V7U3C-CB7JnCHh.js → mindmap-definition-LN4V7U3C-BcXFy-N9.js} +1 -1
- package/web-dist/assets/{packet-7NZHBO7P-BvyvpOhm.js → packet-7NZHBO7P-BXfwnw74.js} +1 -1
- package/web-dist/assets/{pegDiagram-2B236MQR-BoygVhix.js → pegDiagram-2B236MQR-BCD3YN2p.js} +1 -1
- package/web-dist/assets/{pie-RZYD4A2V-ChTjZLeC.js → pie-RZYD4A2V-AinCQhe4.js} +1 -1
- package/web-dist/assets/{pieDiagram-ENE6RG2P-B3UNPTpF.js → pieDiagram-ENE6RG2P-D91RCAtQ.js} +1 -1
- package/web-dist/assets/{quadrantDiagram-ABIIQ3AL-DJdWJ4GS.js → quadrantDiagram-ABIIQ3AL-CiOs81pa.js} +1 -1
- package/web-dist/assets/{radar-I7S5WNFK-DHi5ReAY.js → radar-I7S5WNFK-PjwSEfhJ.js} +1 -1
- package/web-dist/assets/{railroad-3IZDKUUU-DcLJuGRW.js → railroad-3IZDKUUU-De7aPcv6.js} +1 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-BdaR6aMg.js +1 -0
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-BQ1i-m_V.js +1 -0
- package/web-dist/assets/railroad-peg-LSFZ7HO6-Bz7gY9Z5.js +1 -0
- package/web-dist/assets/{railroadDiagram-RFXS5EU6-W4vnMFZ2.js → railroadDiagram-RFXS5EU6-Ba5vfAy2.js} +1 -1
- package/web-dist/assets/{requirementDiagram-TGXJPOKE-CV_V-9DW.js → requirementDiagram-TGXJPOKE-cl6D_V6r.js} +1 -1
- package/web-dist/assets/{sankeyDiagram-HTMAVEWB-DuIIsNBv.js → sankeyDiagram-HTMAVEWB-BiL7lO9N.js} +1 -1
- package/web-dist/assets/{sequenceDiagram-DBY2YBRQ-DTT8ETnv.js → sequenceDiagram-DBY2YBRQ-DWwMnGgF.js} +1 -1
- package/web-dist/assets/{stateDiagram-2N3HPSRC-HVZaDROf.js → stateDiagram-2N3HPSRC-DyDSg9bX.js} +1 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DdKoRulX.js +1 -0
- package/web-dist/assets/{swimlanes-5IMT3BWC-DpGdPqRB.js → swimlanes-5IMT3BWC-DXcDUTKt.js} +1 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-e28nOYgP.js +8 -0
- package/web-dist/assets/{timeline-definition-FHXFAJF6-D9u3mgpd.js → timeline-definition-FHXFAJF6-BmhB--di.js} +1 -1
- package/web-dist/assets/{treeView-QDETBFTQ-Dga6MhEJ.js → treeView-QDETBFTQ-uZOu6XJp.js} +1 -1
- package/web-dist/assets/{treemap-6X3UGDF4-BwEXmcD6.js → treemap-6X3UGDF4-vvG-U9_8.js} +1 -1
- package/web-dist/assets/{vennDiagram-L72KCM5P-BMvodYUW.js → vennDiagram-L72KCM5P-1w9D4erz.js} +1 -1
- package/web-dist/assets/{wardley-OPB4EBWU-BzB6QK8X.js → wardley-OPB4EBWU-BJKEDRlS.js} +1 -1
- package/web-dist/assets/{wardleyDiagram-EHGQE667-4ID7QRJi.js → wardleyDiagram-EHGQE667-BZuQjgMm.js} +1 -1
- package/web-dist/assets/{xychartDiagram-FW5EYKEG-Ckob9hhW.js → xychartDiagram-FW5EYKEG-BuCgSm0a.js} +1 -1
- package/web-dist/index.html +2 -2
- package/web-dist/assets/architecture-TIHT7OUA-Eb73yePg.js +0 -1
- package/web-dist/assets/channel-CgSC9ikg.js +0 -1
- package/web-dist/assets/classDiagram-OUVF2IWQ-DrMJp1ua.js +0 -1
- package/web-dist/assets/classDiagram-v2-EOCWNBFH-DrMJp1ua.js +0 -1
- package/web-dist/assets/eventmodeling-45OFAUF4-B52bjxMe.js +0 -1
- package/web-dist/assets/flowDiagram-23GEKE2U-DbFccp_w.js +0 -1
- package/web-dist/assets/index-CjEngYN7.css +0 -1
- package/web-dist/assets/railroad-abnf-AHOZXSZD-BJcLzkwL.js +0 -1
- package/web-dist/assets/railroad-ebnf-EBAXGLYW-B4jrlWYB.js +0 -1
- package/web-dist/assets/railroad-peg-LSFZ7HO6-BpIzbo9k.js +0 -1
- package/web-dist/assets/stateDiagram-v2-6OUMAXLB-DF9q3s7U.js +0 -1
- package/web-dist/assets/swimlanesDiagram-G3AALYLV-BNeW4PCd.js +0 -8
package/dist/dev-child.js
CHANGED
|
@@ -50,8 +50,14 @@ function xdg(env, name) {
|
|
|
50
50
|
const value = env[name];
|
|
51
51
|
return value && (value.startsWith("/") || /^[A-Za-z]:[\\/]/u.test(value)) ? value : void 0;
|
|
52
52
|
}
|
|
53
|
+
function insideHome(child, home) {
|
|
54
|
+
const norm = (value) => value.replace(/[\\/]+$/u, "").replaceAll("\\", "/").toLowerCase();
|
|
55
|
+
const parent = norm(home);
|
|
56
|
+
const inner = norm(child);
|
|
57
|
+
return inner === parent || inner.startsWith(`${parent}/`);
|
|
58
|
+
}
|
|
53
59
|
function windowsRoots(env, home) {
|
|
54
|
-
const local = env.LOCALAPPDATA
|
|
60
|
+
const local = env.LOCALAPPDATA && insideHome(env.LOCALAPPDATA, home) ? env.LOCALAPPDATA : join(home, "AppData", "Local");
|
|
55
61
|
const base = join(local, "Frizz");
|
|
56
62
|
return {
|
|
57
63
|
data: join(base, "Data"),
|
|
@@ -13072,6 +13078,9 @@ function prWatchExpiredWakeMessage(ref) {
|
|
|
13072
13078
|
|
|
13073
13079
|
If you still care about it, register it again with \`mcp__frizz__watch_pr\` and a fresh \`for:\`. If you do not, and it was the only thing you were waiting on, end in a proper terminal state instead of parking on it again.`;
|
|
13074
13080
|
}
|
|
13081
|
+
function queuedThread(t) {
|
|
13082
|
+
return t.kind === "session" && t.foreign !== true && t.needsYou === true && t.state !== "archived";
|
|
13083
|
+
}
|
|
13075
13084
|
function formatElapsed(ms) {
|
|
13076
13085
|
if (!Number.isFinite(ms) || ms < 0) return "an unknown time";
|
|
13077
13086
|
const s = Math.floor(ms / 1e3);
|
|
@@ -14037,8 +14046,8 @@ var init_src = __esm({
|
|
|
14037
14046
|
PermissionMode = external_exports.enum(["auto", "default", "acceptEdits", "plan", "bypassPermissions"]);
|
|
14038
14047
|
LocalFileOpener = external_exports.enum(["system", "cursor", "vscode", "finder", "copy"]);
|
|
14039
14048
|
Settings = external_exports.object({
|
|
14040
|
-
// The mode NEW Claude workers launch in. Settings surfaces exactly two of them — `
|
|
14041
|
-
//
|
|
14049
|
+
// The mode NEW Claude workers launch in. Settings surfaces exactly two of them — `bypassPermissions`
|
|
14050
|
+
// (--dangerously-skip-permissions, the shipped default since 0.7.2) and `auto` — because those are the only two
|
|
14042
14051
|
// an unattended worker can actually run in; the server's workerDispatchPermission enforces that same
|
|
14043
14052
|
// floor, so a restrictive value left here by an older build cannot reach a spawn.
|
|
14044
14053
|
permissionMode: PermissionMode,
|
|
@@ -19542,11 +19551,13 @@ var init_settings = __esm({
|
|
|
19542
19551
|
SETTINGS_KEY = "settings";
|
|
19543
19552
|
MACHINE_KEYS = ["font", "notifications", "localFileOpener", "projectRail"];
|
|
19544
19553
|
defaultSettings = () => ({
|
|
19545
|
-
// `
|
|
19546
|
-
// card.
|
|
19547
|
-
// control can
|
|
19548
|
-
//
|
|
19549
|
-
|
|
19554
|
+
// `bypassPermissions` = claude's --dangerously-skip-permissions: a headless worker never stops on an
|
|
19555
|
+
// approval card. Shipped default since 0.7.2 (maintainer 2026-08-24); the Settings "Permissions"
|
|
19556
|
+
// (under Claude) control can lower it to `auto` — the CLI's classifier mode, where risky actions
|
|
19557
|
+
// still surface an approval card in the thread. Those are the only two values a headless worker can
|
|
19558
|
+
// run in: the dispatch floor (WORKER_DISPATCH_PERMISSION) stays `auto`, and workerDispatchPermission
|
|
19559
|
+
// honors exactly one deviation from it, which is this one.
|
|
19560
|
+
permissionMode: "bypassPermissions",
|
|
19550
19561
|
model: void 0,
|
|
19551
19562
|
effort: void 0,
|
|
19552
19563
|
notifications: true,
|
|
@@ -20602,11 +20613,23 @@ var init_detached_daemons = __esm({
|
|
|
20602
20613
|
}
|
|
20603
20614
|
});
|
|
20604
20615
|
|
|
20616
|
+
// packages/server/src/backend/ipc-path.ts
|
|
20617
|
+
import { join as join13 } from "node:path";
|
|
20618
|
+
function frizzIpcPath(name) {
|
|
20619
|
+
if (process.platform === "win32") return `\\\\.\\pipe\\${name}`;
|
|
20620
|
+
return join13(process.env.TMPDIR ?? "/tmp", `${name}.sock`);
|
|
20621
|
+
}
|
|
20622
|
+
var init_ipc_path = __esm({
|
|
20623
|
+
"packages/server/src/backend/ipc-path.ts"() {
|
|
20624
|
+
"use strict";
|
|
20625
|
+
}
|
|
20626
|
+
});
|
|
20627
|
+
|
|
20605
20628
|
// packages/server/src/backend/claude-broker-host.ts
|
|
20606
20629
|
import { spawn } from "node:child_process";
|
|
20607
20630
|
import { createHash as createHash5, randomUUID as randomUUID8 } from "node:crypto";
|
|
20608
20631
|
import { accessSync, constants as fsConstants, mkdirSync as mkdirSync9, readFileSync as readFileSync9, readdirSync as readdirSync4, unlinkSync, writeFileSync as writeFileSync7 } from "node:fs";
|
|
20609
|
-
import { delimiter, dirname as dirname8, isAbsolute as isAbsolute2, join as
|
|
20632
|
+
import { delimiter, dirname as dirname8, isAbsolute as isAbsolute2, join as join14 } from "node:path";
|
|
20610
20633
|
function windowsShimTarget(shimPath) {
|
|
20611
20634
|
let body;
|
|
20612
20635
|
try {
|
|
@@ -20616,7 +20639,7 @@ function windowsShimTarget(shimPath) {
|
|
|
20616
20639
|
}
|
|
20617
20640
|
const target = WINDOWS_SHIM_TARGET.exec(body)?.[1];
|
|
20618
20641
|
if (!target) return void 0;
|
|
20619
|
-
const full =
|
|
20642
|
+
const full = join14(dirname8(shimPath), target);
|
|
20620
20643
|
try {
|
|
20621
20644
|
accessSync(full, fsConstants.F_OK);
|
|
20622
20645
|
return full;
|
|
@@ -20631,17 +20654,17 @@ function resolveClaudeExecutableAbsolute(bin, env = process.env) {
|
|
|
20631
20654
|
for (const dir of (env.PATH ?? "").split(delimiter)) {
|
|
20632
20655
|
if (!dir) continue;
|
|
20633
20656
|
if (windows) {
|
|
20634
|
-
const exe =
|
|
20657
|
+
const exe = join14(dir, `${candidate}.exe`);
|
|
20635
20658
|
try {
|
|
20636
20659
|
accessSync(exe, fsConstants.F_OK);
|
|
20637
20660
|
return exe;
|
|
20638
20661
|
} catch {
|
|
20639
20662
|
}
|
|
20640
|
-
const viaShim = windowsShimTarget(
|
|
20663
|
+
const viaShim = windowsShimTarget(join14(dir, `${candidate}.cmd`));
|
|
20641
20664
|
if (viaShim) return viaShim;
|
|
20642
20665
|
continue;
|
|
20643
20666
|
}
|
|
20644
|
-
const full =
|
|
20667
|
+
const full = join14(dir, candidate);
|
|
20645
20668
|
try {
|
|
20646
20669
|
accessSync(full, fsConstants.X_OK);
|
|
20647
20670
|
return full;
|
|
@@ -20652,16 +20675,15 @@ function resolveClaudeExecutableAbsolute(bin, env = process.env) {
|
|
|
20652
20675
|
}
|
|
20653
20676
|
function claudeBrokerSocketPath(stateDir, sessionId) {
|
|
20654
20677
|
const key = createHash5("sha256").update(stateDir).update("\0").update(sessionId).digest("hex").slice(0, 16);
|
|
20655
|
-
|
|
20656
|
-
return join13(process.env.TMPDIR ?? "/tmp", `frizz-claude-${key}.sock`);
|
|
20678
|
+
return frizzIpcPath(`frizz-claude-${key}`);
|
|
20657
20679
|
}
|
|
20658
20680
|
function claudeBrokerRecordPath(stateDir, sessionId) {
|
|
20659
20681
|
const key = createHash5("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
20660
|
-
return
|
|
20682
|
+
return join14(stateDir, "claude-broker", `${key}.json`);
|
|
20661
20683
|
}
|
|
20662
20684
|
function claudeBrokerRetirementPath(stateDir, sessionId) {
|
|
20663
20685
|
const key = createHash5("sha256").update(sessionId).digest("hex").slice(0, 16);
|
|
20664
|
-
return
|
|
20686
|
+
return join14(stateDir, "claude-broker", `${key}.retired`);
|
|
20665
20687
|
}
|
|
20666
20688
|
function markBrokerRetired(stateDir, sessionId, reason, generation) {
|
|
20667
20689
|
const mark = { at: (/* @__PURE__ */ new Date()).toISOString(), generation, reason };
|
|
@@ -20728,7 +20750,7 @@ function liveBrokerRecord(recordPath2) {
|
|
|
20728
20750
|
return null;
|
|
20729
20751
|
}
|
|
20730
20752
|
function liveBrokerRecords(stateDir) {
|
|
20731
|
-
const dir =
|
|
20753
|
+
const dir = join14(stateDir, "claude-broker");
|
|
20732
20754
|
let names;
|
|
20733
20755
|
try {
|
|
20734
20756
|
names = readdirSync4(dir);
|
|
@@ -20738,7 +20760,7 @@ function liveBrokerRecords(stateDir) {
|
|
|
20738
20760
|
const out = [];
|
|
20739
20761
|
for (const name of names) {
|
|
20740
20762
|
if (!name.endsWith(".json")) continue;
|
|
20741
|
-
const record = liveBrokerRecord(
|
|
20763
|
+
const record = liveBrokerRecord(join14(dir, name));
|
|
20742
20764
|
if (record) out.push(record);
|
|
20743
20765
|
}
|
|
20744
20766
|
return out;
|
|
@@ -20818,6 +20840,7 @@ var init_claude_broker_host = __esm({
|
|
|
20818
20840
|
"use strict";
|
|
20819
20841
|
init_detached_daemons();
|
|
20820
20842
|
init_claude_broker_diagnostics();
|
|
20843
|
+
init_ipc_path();
|
|
20821
20844
|
WINDOWS_SHIM_TARGET = /^\s*"%dp0%\\(.+?)"/mu;
|
|
20822
20845
|
}
|
|
20823
20846
|
});
|
|
@@ -21546,14 +21569,14 @@ var init_completion_relay = __esm({
|
|
|
21546
21569
|
// packages/server/src/tail-cache.ts
|
|
21547
21570
|
import { createHash as createHash6 } from "node:crypto";
|
|
21548
21571
|
import { closeSync as closeSync8, openSync as openSync9, readFileSync as readFileSync10, readSync as readSync3, statSync as statSync7 } from "node:fs";
|
|
21549
|
-
import { join as
|
|
21572
|
+
import { join as join15 } from "node:path";
|
|
21550
21573
|
function foldSchemaDigest(dir = import.meta.dirname) {
|
|
21551
21574
|
if (foldSchemaMemo) return foldSchemaMemo;
|
|
21552
21575
|
const hash = createHash6("sha256").update("frizz-tail-state-v1\0");
|
|
21553
21576
|
let read = 0;
|
|
21554
21577
|
for (const name of FOLD_SOURCES) {
|
|
21555
21578
|
try {
|
|
21556
|
-
hash.update(name).update("\0").update(readFileSync10(
|
|
21579
|
+
hash.update(name).update("\0").update(readFileSync10(join15(dir, name)));
|
|
21557
21580
|
read++;
|
|
21558
21581
|
} catch {
|
|
21559
21582
|
hash.update(name).update("\0missing\0");
|
|
@@ -21751,7 +21774,7 @@ var init_tail_cache = __esm({
|
|
|
21751
21774
|
// packages/server/src/tailer.ts
|
|
21752
21775
|
import { statSync as statSync8, openSync as openSync10, readSync as readSync4, closeSync as closeSync9, readdirSync as readdirSync5, realpathSync as realpathSync5, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, readFileSync as readFileSync11, existsSync as existsSync5 } from "node:fs";
|
|
21753
21776
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
21754
|
-
import { basename as basename4, join as
|
|
21777
|
+
import { basename as basename4, join as join16 } from "node:path";
|
|
21755
21778
|
import { homedir as homedir7 } from "node:os";
|
|
21756
21779
|
function probeShellAlive(outputFile) {
|
|
21757
21780
|
if (!existsSync5(outputFile)) return void 0;
|
|
@@ -22013,7 +22036,7 @@ function launchTaskId(text) {
|
|
|
22013
22036
|
function readDescendantSidecars(sessionDir, mtimeMs) {
|
|
22014
22037
|
let names;
|
|
22015
22038
|
try {
|
|
22016
|
-
names = readdirSync5(
|
|
22039
|
+
names = readdirSync5(join16(sessionDir, "subagents"));
|
|
22017
22040
|
} catch {
|
|
22018
22041
|
return [];
|
|
22019
22042
|
}
|
|
@@ -22024,7 +22047,7 @@ function readDescendantSidecars(sessionDir, mtimeMs) {
|
|
|
22024
22047
|
if (!agentId) continue;
|
|
22025
22048
|
let parsed;
|
|
22026
22049
|
try {
|
|
22027
|
-
parsed = JSON.parse(readFileSync11(
|
|
22050
|
+
parsed = JSON.parse(readFileSync11(join16(sessionDir, "subagents", name), "utf8"));
|
|
22028
22051
|
} catch {
|
|
22029
22052
|
continue;
|
|
22030
22053
|
}
|
|
@@ -22038,7 +22061,7 @@ function readDescendantSidecars(sessionDir, mtimeMs) {
|
|
|
22038
22061
|
agentType: text(meta.agentType),
|
|
22039
22062
|
parentAgentId: text(meta.parentAgentId),
|
|
22040
22063
|
spawnDepth: typeof meta.spawnDepth === "number" && Number.isFinite(meta.spawnDepth) ? meta.spawnDepth : void 0,
|
|
22041
|
-
spawnedAtMs: mtimeMs(
|
|
22064
|
+
spawnedAtMs: mtimeMs(join16(sessionDir, "subagents", name))
|
|
22042
22065
|
});
|
|
22043
22066
|
}
|
|
22044
22067
|
return out;
|
|
@@ -22518,7 +22541,7 @@ function defaultMtimeMs(path) {
|
|
|
22518
22541
|
}
|
|
22519
22542
|
}
|
|
22520
22543
|
function defaultLogDir(project) {
|
|
22521
|
-
return
|
|
22544
|
+
return join16(homedir7(), ".claude", "projects", project.cwdSlug);
|
|
22522
22545
|
}
|
|
22523
22546
|
function defaultReadPermMarker(project) {
|
|
22524
22547
|
if (!project.stateDir) return () => void 0;
|
|
@@ -22649,7 +22672,7 @@ function createTailer(deps) {
|
|
|
22649
22672
|
return paneDead(row.slug);
|
|
22650
22673
|
}
|
|
22651
22674
|
const defaultBackend = {
|
|
22652
|
-
transcriptPath: (sessionId) =>
|
|
22675
|
+
transcriptPath: (sessionId) => join16(logDir, `${sessionId}.jsonl`),
|
|
22653
22676
|
foldLine: (state, line) => {
|
|
22654
22677
|
const rec = parseLine(line);
|
|
22655
22678
|
if (rec) applyRecord(state, rec);
|
|
@@ -22774,7 +22797,7 @@ ${ask}`;
|
|
|
22774
22797
|
return state.path.replace(/\.jsonl$/, "");
|
|
22775
22798
|
}
|
|
22776
22799
|
function descendantSidecars(state) {
|
|
22777
|
-
const at = mtimeMs(
|
|
22800
|
+
const at = mtimeMs(join16(sessionDirOf(state), "subagents"));
|
|
22778
22801
|
const cached2 = descendantIndex.get(state.slug);
|
|
22779
22802
|
if (cached2 && cached2.at === at) return cached2.all;
|
|
22780
22803
|
const all = readDescendantSidecars(sessionDirOf(state), mtimeMs);
|
|
@@ -22788,7 +22811,7 @@ ${ask}`;
|
|
|
22788
22811
|
return descendantIndex.get(state.slug)?.byToolUse.get(id);
|
|
22789
22812
|
}
|
|
22790
22813
|
function descendantTranscript(state, meta) {
|
|
22791
|
-
return
|
|
22814
|
+
return join16(sessionDirOf(state), "subagents", `agent-${meta.agentId}.jsonl`);
|
|
22792
22815
|
}
|
|
22793
22816
|
function subAgentDescendantTasks(slug, id) {
|
|
22794
22817
|
const state = states.get(slug);
|
|
@@ -23102,7 +23125,7 @@ ${ask}`;
|
|
|
23102
23125
|
if (name.startsWith(".") || !name.endsWith(".jsonl")) continue;
|
|
23103
23126
|
const id = name.slice(0, -".jsonl".length);
|
|
23104
23127
|
if (!id || registered.has(id)) continue;
|
|
23105
|
-
const path =
|
|
23128
|
+
const path = join16(logDir, name);
|
|
23106
23129
|
let mtime;
|
|
23107
23130
|
try {
|
|
23108
23131
|
mtime = statSync8(path).mtimeMs;
|
|
@@ -23374,7 +23397,7 @@ ${ask}`;
|
|
|
23374
23397
|
);
|
|
23375
23398
|
try {
|
|
23376
23399
|
mkdirSync10(stallLogDir, { recursive: true });
|
|
23377
|
-
writeFileSync8(
|
|
23400
|
+
writeFileSync8(join16(stallLogDir, `${row.slug}.stall.log`), `session_id: ${row.session_id}
|
|
23378
23401
|
captured_at: ${new Date(now()).toISOString()}
|
|
23379
23402
|
|
|
23380
23403
|
${detail}
|
|
@@ -23402,7 +23425,7 @@ ${detail}
|
|
|
23402
23425
|
state.nextDiscoverMs = nowMs + DISCOVER_RETRY_MS;
|
|
23403
23426
|
const strandedDir = discoverTranscriptDir(logDir, row.session_id);
|
|
23404
23427
|
if (strandedDir) {
|
|
23405
|
-
state.path =
|
|
23428
|
+
state.path = join16(strandedDir, `${row.session_id}.jsonl`);
|
|
23406
23429
|
state.offset = 0;
|
|
23407
23430
|
state.partial = "";
|
|
23408
23431
|
state.primed = false;
|
|
@@ -23425,7 +23448,7 @@ ${detail}
|
|
|
23425
23448
|
committed = false;
|
|
23426
23449
|
}
|
|
23427
23450
|
if (!committed) return false;
|
|
23428
|
-
state.path =
|
|
23451
|
+
state.path = join16(logDir, `${found}.jsonl`);
|
|
23429
23452
|
state.offset = 0;
|
|
23430
23453
|
state.partial = "";
|
|
23431
23454
|
state.primed = false;
|
|
@@ -23471,7 +23494,7 @@ ${detail}
|
|
|
23471
23494
|
let state = states.get(row.slug);
|
|
23472
23495
|
const runtimeGeneration = row.runtime_generation ?? 0;
|
|
23473
23496
|
if (!state || state.sessionId !== row.session_id || state.nativeSessionId !== nativeId || state.runtimeGeneration !== runtimeGeneration) {
|
|
23474
|
-
const path = backend.transcriptPath(nativeId) ??
|
|
23497
|
+
const path = backend.transcriptPath(nativeId) ?? join16(logDir, `${nativeId}.jsonl`);
|
|
23475
23498
|
state = newTailState(row.slug, row.session_id, path, false, nativeId, runtimeGeneration);
|
|
23476
23499
|
state.dismissedOps = deps.storage.retiredOps(row.slug, row.session_id);
|
|
23477
23500
|
hydrateFromCache(state, row, nativeId);
|
|
@@ -23920,14 +23943,14 @@ var init_tailer = __esm({
|
|
|
23920
23943
|
});
|
|
23921
23944
|
|
|
23922
23945
|
// packages/server/src/backend/codex.ts
|
|
23923
|
-
import { join as
|
|
23946
|
+
import { join as join17 } from "node:path";
|
|
23924
23947
|
import { homedir as homedir8 } from "node:os";
|
|
23925
23948
|
import { readdirSync as readdirSync6, statSync as statSync9, readFileSync as readFileSync12, openSync as openSync11, readSync as readSync5, closeSync as closeSync10 } from "node:fs";
|
|
23926
23949
|
function defaultCodexHome() {
|
|
23927
|
-
return process.env.CODEX_HOME && process.env.CODEX_HOME.trim() ? process.env.CODEX_HOME :
|
|
23950
|
+
return process.env.CODEX_HOME && process.env.CODEX_HOME.trim() ? process.env.CODEX_HOME : join17(homedir8(), ".codex");
|
|
23928
23951
|
}
|
|
23929
23952
|
function sessionsDir(codexHome) {
|
|
23930
|
-
return
|
|
23953
|
+
return join17(codexHome, "sessions");
|
|
23931
23954
|
}
|
|
23932
23955
|
function codexSandbox(mode) {
|
|
23933
23956
|
switch (mode) {
|
|
@@ -24308,17 +24331,17 @@ function collectRollouts(dir, out, budget) {
|
|
|
24308
24331
|
const files = entries.filter((e) => e.isFile() && e.name.startsWith("rollout-") && e.name.endsWith(".jsonl")).sort(descByName);
|
|
24309
24332
|
for (const d of dirs) {
|
|
24310
24333
|
if (budget.n <= 0) return;
|
|
24311
|
-
collectRollouts(
|
|
24334
|
+
collectRollouts(join17(dir, d.name), out, budget);
|
|
24312
24335
|
}
|
|
24313
24336
|
for (const f of files) {
|
|
24314
24337
|
if (budget.n <= 0) return;
|
|
24315
24338
|
let mtimeMs;
|
|
24316
24339
|
try {
|
|
24317
|
-
mtimeMs = statSync9(
|
|
24340
|
+
mtimeMs = statSync9(join17(dir, f.name)).mtimeMs;
|
|
24318
24341
|
} catch {
|
|
24319
24342
|
continue;
|
|
24320
24343
|
}
|
|
24321
|
-
out.push({ path:
|
|
24344
|
+
out.push({ path: join17(dir, f.name), mtimeMs });
|
|
24322
24345
|
budget.n--;
|
|
24323
24346
|
}
|
|
24324
24347
|
}
|
|
@@ -24362,7 +24385,7 @@ function readCodexThreadNames(codexHome = defaultCodexHome()) {
|
|
|
24362
24385
|
const out = /* @__PURE__ */ new Map();
|
|
24363
24386
|
let raw2;
|
|
24364
24387
|
try {
|
|
24365
|
-
const path =
|
|
24388
|
+
const path = join17(codexHome, "session_index.jsonl");
|
|
24366
24389
|
if (statSync9(path).size > SESSION_INDEX_MAX_BYTES) return out;
|
|
24367
24390
|
raw2 = readFileSync12(path, "utf8");
|
|
24368
24391
|
} catch {
|
|
@@ -28400,16 +28423,16 @@ var init_wrapper = __esm({
|
|
|
28400
28423
|
|
|
28401
28424
|
// packages/server/src/worker-plugin-dir.ts
|
|
28402
28425
|
import { existsSync as existsSync6 } from "node:fs";
|
|
28403
|
-
import { dirname as dirname9, join as
|
|
28426
|
+
import { dirname as dirname9, join as join18 } from "node:path";
|
|
28404
28427
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
28405
28428
|
function resolveWorkerPluginDir(moduleUrl = import.meta.url, env = process.env) {
|
|
28406
28429
|
const override = env.FRIZZ_WORKER_PLUGIN_DIR;
|
|
28407
|
-
if (override && existsSync6(
|
|
28430
|
+
if (override && existsSync6(join18(override, ".claude-plugin", "plugin.json")))
|
|
28408
28431
|
return override;
|
|
28409
28432
|
let current = dirname9(fileURLToPath2(moduleUrl));
|
|
28410
28433
|
for (; ; ) {
|
|
28411
|
-
const candidate =
|
|
28412
|
-
if (existsSync6(
|
|
28434
|
+
const candidate = join18(current, "cc-worker");
|
|
28435
|
+
if (existsSync6(join18(candidate, ".claude-plugin", "plugin.json"))) return candidate;
|
|
28413
28436
|
const parent = dirname9(current);
|
|
28414
28437
|
if (parent === current) return void 0;
|
|
28415
28438
|
current = parent;
|
|
@@ -28423,7 +28446,7 @@ var init_worker_plugin_dir = __esm({
|
|
|
28423
28446
|
|
|
28424
28447
|
// packages/server/src/backend/types.ts
|
|
28425
28448
|
import { existsSync as existsSync7 } from "node:fs";
|
|
28426
|
-
import { join as
|
|
28449
|
+
import { join as join19 } from "node:path";
|
|
28427
28450
|
function frizzMcpEnv(mcp) {
|
|
28428
28451
|
return {
|
|
28429
28452
|
FRIZZ_STATE_DIR: mcp.stateDir,
|
|
@@ -28447,7 +28470,7 @@ function chromeDevtoolsMcpMount() {
|
|
|
28447
28470
|
function resolveBrowserMcpScript(moduleUrl = import.meta.url, env = process.env) {
|
|
28448
28471
|
const pluginDir = resolveWorkerPluginDir(moduleUrl, env);
|
|
28449
28472
|
if (!pluginDir) return void 0;
|
|
28450
|
-
const scriptPath =
|
|
28473
|
+
const scriptPath = join19(pluginDir, "bin", CHROME_DEVTOOLS_MCP.script);
|
|
28451
28474
|
return existsSync7(scriptPath) ? scriptPath : void 0;
|
|
28452
28475
|
}
|
|
28453
28476
|
function workerCap(name, lifted, env) {
|
|
@@ -28543,21 +28566,21 @@ var init_codex_mcp = __esm({
|
|
|
28543
28566
|
// packages/server/src/backend/codex-app-server-native.ts
|
|
28544
28567
|
import { spawn as spawn2 } from "node:child_process";
|
|
28545
28568
|
import { connect } from "node:net";
|
|
28569
|
+
import { Agent as HttpAgent } from "node:http";
|
|
28546
28570
|
import { createHash as createHash7, randomUUID as randomUUID9 } from "node:crypto";
|
|
28547
28571
|
import { existsSync as existsSync8, mkdirSync as mkdirSync11, readFileSync as readFileSync13, unlinkSync as unlinkSync2, writeFileSync as writeFileSync9 } from "node:fs";
|
|
28548
|
-
import { join as
|
|
28572
|
+
import { join as join20 } from "node:path";
|
|
28549
28573
|
import { PassThrough, Writable } from "node:stream";
|
|
28550
28574
|
import { StringDecoder } from "node:string_decoder";
|
|
28551
28575
|
function nativeDir(stateDir) {
|
|
28552
|
-
return
|
|
28576
|
+
return join20(stateDir, "codex-app-server-native");
|
|
28553
28577
|
}
|
|
28554
28578
|
function nativeRecordPath(stateDir, projectId) {
|
|
28555
|
-
return
|
|
28579
|
+
return join20(nativeDir(stateDir), `${projectId}.json`);
|
|
28556
28580
|
}
|
|
28557
28581
|
function nativeListenSocketPath(stateDir, projectId) {
|
|
28558
28582
|
const key = createHash7("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
|
|
28559
|
-
|
|
28560
|
-
return join19(process.env.TMPDIR ?? "/tmp", `frizz-codex-native-${key}.sock`);
|
|
28583
|
+
return frizzIpcPath(`frizz-codex-native-${key}`);
|
|
28561
28584
|
}
|
|
28562
28585
|
function pidAlive2(pid) {
|
|
28563
28586
|
try {
|
|
@@ -28634,9 +28657,18 @@ function socketAccepting(socketPath) {
|
|
|
28634
28657
|
setTimeout(() => done(false), 2e3).unref?.();
|
|
28635
28658
|
});
|
|
28636
28659
|
}
|
|
28660
|
+
function ipcWebSocket(endpoint) {
|
|
28661
|
+
if (process.platform !== "win32") return new import_websocket.default(`ws+unix://${endpoint}:/`, { perMessageDeflate: false });
|
|
28662
|
+
class PipeAgent extends HttpAgent {
|
|
28663
|
+
createConnection() {
|
|
28664
|
+
return connect(endpoint);
|
|
28665
|
+
}
|
|
28666
|
+
}
|
|
28667
|
+
return new import_websocket.default("ws://localhost/", { agent: new PipeAgent(), perMessageDeflate: false });
|
|
28668
|
+
}
|
|
28637
28669
|
function attach(record, timeoutMs) {
|
|
28638
28670
|
return new Promise((resolve10, reject) => {
|
|
28639
|
-
const socket =
|
|
28671
|
+
const socket = ipcWebSocket(record.socketPath);
|
|
28640
28672
|
const stdout = new PassThrough();
|
|
28641
28673
|
const stderr = new PassThrough();
|
|
28642
28674
|
const listeners = { exit: [], error: [] };
|
|
@@ -28753,6 +28785,7 @@ var init_codex_app_server_native = __esm({
|
|
|
28753
28785
|
"packages/server/src/backend/codex-app-server-native.ts"() {
|
|
28754
28786
|
"use strict";
|
|
28755
28787
|
init_wrapper();
|
|
28788
|
+
init_ipc_path();
|
|
28756
28789
|
init_codex_mcp();
|
|
28757
28790
|
init_logging();
|
|
28758
28791
|
PRESUMED_LOSSY_REJOIN = 1;
|
|
@@ -28804,23 +28837,22 @@ var init_codex_app_server_native = __esm({
|
|
|
28804
28837
|
});
|
|
28805
28838
|
|
|
28806
28839
|
// packages/server/src/backend/codex-app-server-host.ts
|
|
28807
|
-
import { spawn as spawn3 } from "node:child_process";
|
|
28840
|
+
import { spawn as spawn3, spawnSync } from "node:child_process";
|
|
28808
28841
|
import { createConnection } from "node:net";
|
|
28809
28842
|
import { createHash as createHash8, randomUUID as randomUUID10 } from "node:crypto";
|
|
28810
28843
|
import { existsSync as existsSync9, mkdirSync as mkdirSync12, readFileSync as readFileSync14, unlinkSync as unlinkSync3 } from "node:fs";
|
|
28811
|
-
import { join as
|
|
28844
|
+
import { join as join21 } from "node:path";
|
|
28812
28845
|
import { PassThrough as PassThrough2, Writable as Writable2 } from "node:stream";
|
|
28813
28846
|
import { StringDecoder as StringDecoder2 } from "node:string_decoder";
|
|
28814
28847
|
function daemonDir(stateDir) {
|
|
28815
|
-
return
|
|
28848
|
+
return join21(stateDir, "codex-app-server");
|
|
28816
28849
|
}
|
|
28817
28850
|
function recordPath(stateDir, projectId) {
|
|
28818
|
-
return
|
|
28851
|
+
return join21(daemonDir(stateDir), `${projectId}.json`);
|
|
28819
28852
|
}
|
|
28820
28853
|
function codexAppServerSocketPath(stateDir, projectId) {
|
|
28821
28854
|
const key = createHash8("sha256").update(stateDir).update("\0").update(projectId).digest("hex").slice(0, 16);
|
|
28822
|
-
|
|
28823
|
-
return join20(process.env.TMPDIR ?? "/tmp", `frizz-codex-${key}.sock`);
|
|
28855
|
+
return frizzIpcPath(`frizz-codex-${key}`);
|
|
28824
28856
|
}
|
|
28825
28857
|
function pidAlive3(pid) {
|
|
28826
28858
|
try {
|
|
@@ -28871,13 +28903,26 @@ function liveDaemonRecord(stateDir, projectId) {
|
|
|
28871
28903
|
}
|
|
28872
28904
|
return null;
|
|
28873
28905
|
}
|
|
28906
|
+
function endDaemonTree(pid, signal) {
|
|
28907
|
+
if (process.platform !== "win32") {
|
|
28908
|
+
try {
|
|
28909
|
+
process.kill(pid, signal);
|
|
28910
|
+
} catch {
|
|
28911
|
+
}
|
|
28912
|
+
return;
|
|
28913
|
+
}
|
|
28914
|
+
const killed = spawnSync("taskkill", ["/PID", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
|
|
28915
|
+
if (killed.error || killed.status !== 0) {
|
|
28916
|
+
try {
|
|
28917
|
+
process.kill(pid, signal);
|
|
28918
|
+
} catch {
|
|
28919
|
+
}
|
|
28920
|
+
}
|
|
28921
|
+
}
|
|
28874
28922
|
function killCodexAppServerDaemon(stateDir, projectId) {
|
|
28875
28923
|
const record = liveDaemonRecord(stateDir, projectId);
|
|
28876
28924
|
if (!record) return;
|
|
28877
|
-
|
|
28878
|
-
process.kill(record.daemonPid, "SIGTERM");
|
|
28879
|
-
} catch {
|
|
28880
|
-
}
|
|
28925
|
+
endDaemonTree(record.daemonPid, "SIGTERM");
|
|
28881
28926
|
try {
|
|
28882
28927
|
unlinkSync3(recordPath(stateDir, projectId));
|
|
28883
28928
|
} catch {
|
|
@@ -28893,10 +28938,7 @@ async function stopCodexAppServerDaemon(stateDir, projectId, timeoutMs = 1e4) {
|
|
|
28893
28938
|
await new Promise((resolve10) => setTimeout(resolve10, 25));
|
|
28894
28939
|
}
|
|
28895
28940
|
if (pidAlive3(record.daemonPid)) {
|
|
28896
|
-
|
|
28897
|
-
process.kill(record.daemonPid, "SIGKILL");
|
|
28898
|
-
} catch {
|
|
28899
|
-
}
|
|
28941
|
+
endDaemonTree(record.daemonPid, "SIGKILL");
|
|
28900
28942
|
while (pidAlive3(record.daemonPid) && Date.now() < deadline + 2e3) {
|
|
28901
28943
|
await new Promise((resolve10) => setTimeout(resolve10, 25));
|
|
28902
28944
|
}
|
|
@@ -29043,6 +29085,14 @@ function inProcessCodexAppServer(options) {
|
|
|
29043
29085
|
env: options.env,
|
|
29044
29086
|
stdio: ["pipe", "pipe", "pipe"]
|
|
29045
29087
|
});
|
|
29088
|
+
const kill = child.kill.bind(child);
|
|
29089
|
+
child.kill = ((signal) => {
|
|
29090
|
+
try {
|
|
29091
|
+
return kill(signal);
|
|
29092
|
+
} catch {
|
|
29093
|
+
return false;
|
|
29094
|
+
}
|
|
29095
|
+
});
|
|
29046
29096
|
return { process: child, generation: randomUUID10(), reattached: false, daemonPid: process.pid, droppedWhileDetached: 0 };
|
|
29047
29097
|
}
|
|
29048
29098
|
function directChildHost(spawnChild, generationId = randomUUID10) {
|
|
@@ -29060,6 +29110,7 @@ var init_codex_app_server_host = __esm({
|
|
|
29060
29110
|
"use strict";
|
|
29061
29111
|
init_detached_daemons();
|
|
29062
29112
|
init_codex_app_server_native();
|
|
29113
|
+
init_ipc_path();
|
|
29063
29114
|
init_codex_mcp();
|
|
29064
29115
|
init_logging();
|
|
29065
29116
|
daemonEntry = () => resolveDetachedDaemonEntry(import.meta.url, "codex-app-server-daemon");
|
|
@@ -32025,11 +32076,11 @@ var init_codex_app_server = __esm({
|
|
|
32025
32076
|
});
|
|
32026
32077
|
|
|
32027
32078
|
// packages/server/src/backend/codex-quota.ts
|
|
32028
|
-
import { join as
|
|
32079
|
+
import { join as join22 } from "node:path";
|
|
32029
32080
|
import { readdirSync as readdirSync7, statSync as statSync10, openSync as openSync12, readSync as readSync6, fstatSync, closeSync as closeSync11 } from "node:fs";
|
|
32030
32081
|
import { spawn as spawn4 } from "node:child_process";
|
|
32031
32082
|
function sessionsDir2(codexHome) {
|
|
32032
|
-
return
|
|
32083
|
+
return join22(codexHome, "sessions");
|
|
32033
32084
|
}
|
|
32034
32085
|
function newestRollouts(dir, out, budget) {
|
|
32035
32086
|
if (budget.n <= 0) return;
|
|
@@ -32043,11 +32094,11 @@ function newestRollouts(dir, out, budget) {
|
|
|
32043
32094
|
const files = entries.filter((e) => e.isFile() && e.name.startsWith("rollout-") && e.name.endsWith(".jsonl")).map((e) => e.name).sort(descByName2);
|
|
32044
32095
|
for (const d of dirs) {
|
|
32045
32096
|
if (budget.n <= 0) return;
|
|
32046
|
-
newestRollouts(
|
|
32097
|
+
newestRollouts(join22(dir, d), out, budget);
|
|
32047
32098
|
}
|
|
32048
32099
|
for (const f of files) {
|
|
32049
32100
|
if (budget.n <= 0) return;
|
|
32050
|
-
out.push(
|
|
32101
|
+
out.push(join22(dir, f));
|
|
32051
32102
|
budget.n--;
|
|
32052
32103
|
}
|
|
32053
32104
|
}
|
|
@@ -32247,7 +32298,7 @@ var init_codex_quota = __esm({
|
|
|
32247
32298
|
});
|
|
32248
32299
|
|
|
32249
32300
|
// packages/server/src/backend/claude-quota.ts
|
|
32250
|
-
import { join as
|
|
32301
|
+
import { join as join23 } from "node:path";
|
|
32251
32302
|
import { homedir as homedir9, platform } from "node:os";
|
|
32252
32303
|
import { createHash as createHash10 } from "node:crypto";
|
|
32253
32304
|
import { mkdir, readFile, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
@@ -32255,7 +32306,7 @@ import { execFile as execFile2 } from "node:child_process";
|
|
|
32255
32306
|
import { promisify as promisify2 } from "node:util";
|
|
32256
32307
|
function claudeConfigDir() {
|
|
32257
32308
|
const override = process.env.CLAUDE_CONFIG_DIR;
|
|
32258
|
-
return override && override.trim() ? override :
|
|
32309
|
+
return override && override.trim() ? override : join23(homedir9(), ".claude");
|
|
32259
32310
|
}
|
|
32260
32311
|
function tokenFromCredentialsJson(raw2) {
|
|
32261
32312
|
let doc;
|
|
@@ -32284,7 +32335,7 @@ async function readKeychainToken() {
|
|
|
32284
32335
|
}
|
|
32285
32336
|
async function readAccessToken(configDir) {
|
|
32286
32337
|
try {
|
|
32287
|
-
const fromFile = tokenFromCredentialsJson(await readFile(
|
|
32338
|
+
const fromFile = tokenFromCredentialsJson(await readFile(join23(configDir, ".credentials.json"), "utf8"));
|
|
32288
32339
|
if (fromFile) return fromFile;
|
|
32289
32340
|
} catch {
|
|
32290
32341
|
}
|
|
@@ -32353,8 +32404,8 @@ function parseClaudeUsage(body, planType) {
|
|
|
32353
32404
|
function cachePaths(cacheDir, configDir) {
|
|
32354
32405
|
const profile = createHash10("sha256").update(configDir).digest("hex").slice(0, 12);
|
|
32355
32406
|
return {
|
|
32356
|
-
data:
|
|
32357
|
-
lock:
|
|
32407
|
+
data: join23(cacheDir, `claude-${profile}.json`),
|
|
32408
|
+
lock: join23(cacheDir, `claude-${profile}.lock`)
|
|
32358
32409
|
};
|
|
32359
32410
|
}
|
|
32360
32411
|
async function readShared(path) {
|
|
@@ -32546,7 +32597,7 @@ function refreshSharedInBackground(paths, claudeBin, deps, now) {
|
|
|
32546
32597
|
async function refreshClaudeQuotaInBackground(claudeBin = "claude", deps = {}) {
|
|
32547
32598
|
const now = (deps.now ?? Date.now)();
|
|
32548
32599
|
const configDir = claudeConfigDir();
|
|
32549
|
-
const cacheDir = deps.cacheDir ??
|
|
32600
|
+
const cacheDir = deps.cacheDir ?? join23(frizzRoots().cache, "quota-cache");
|
|
32550
32601
|
try {
|
|
32551
32602
|
await mkdir(cacheDir, { recursive: true, mode: 448 });
|
|
32552
32603
|
} catch {
|
|
@@ -32557,7 +32608,7 @@ async function refreshClaudeQuotaInBackground(claudeBin = "claude", deps = {}) {
|
|
|
32557
32608
|
async function readClaudeQuota(claudeBin = "claude", deps = {}, options = {}) {
|
|
32558
32609
|
const now = (deps.now ?? Date.now)();
|
|
32559
32610
|
const configDir = claudeConfigDir();
|
|
32560
|
-
const cacheDir = deps.cacheDir ??
|
|
32611
|
+
const cacheDir = deps.cacheDir ?? join23(frizzRoots().cache, "quota-cache");
|
|
32561
32612
|
const paths = cachePaths(cacheDir, configDir);
|
|
32562
32613
|
try {
|
|
32563
32614
|
await mkdir(cacheDir, { recursive: true, mode: 448 });
|
|
@@ -32716,7 +32767,7 @@ var init_quota = __esm({
|
|
|
32716
32767
|
// packages/server/src/frizz.ts
|
|
32717
32768
|
import { execFile as execFile3 } from "node:child_process";
|
|
32718
32769
|
import { lstatSync as lstatSync2, realpathSync as realpathSync6 } from "node:fs";
|
|
32719
|
-
import { basename as basename5, dirname as dirname10, join as
|
|
32770
|
+
import { basename as basename5, dirname as dirname10, join as join24, resolve as resolve4 } from "node:path";
|
|
32720
32771
|
import { promisify as promisify3 } from "node:util";
|
|
32721
32772
|
function frizzScriptsDir() {
|
|
32722
32773
|
if (process.env.FRIZZ_SCRIPTS_DIR) return process.env.FRIZZ_SCRIPTS_DIR;
|
|
@@ -32725,7 +32776,7 @@ function frizzScriptsDir() {
|
|
|
32725
32776
|
function directFrizzRoot(projectDir) {
|
|
32726
32777
|
try {
|
|
32727
32778
|
const projectRoot = realpathSync6(projectDir);
|
|
32728
|
-
const path =
|
|
32779
|
+
const path = join24(projectRoot, ".frizz");
|
|
32729
32780
|
const stat2 = lstatSync2(path);
|
|
32730
32781
|
if (!stat2.isDirectory() || stat2.isSymbolicLink()) return null;
|
|
32731
32782
|
const real = realpathSync6(path);
|
|
@@ -32739,7 +32790,7 @@ function frizzDirExists(projectDir) {
|
|
|
32739
32790
|
}
|
|
32740
32791
|
async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
|
|
32741
32792
|
if (!directFrizzRoot(projectDir)) throw new Error("unsafe or missing .frizz directory");
|
|
32742
|
-
const { stdout } = await execFileP("node", [
|
|
32793
|
+
const { stdout } = await execFileP("node", [join24(scriptsDir, "index.mjs"), "--json"], {
|
|
32743
32794
|
cwd: projectDir,
|
|
32744
32795
|
env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir },
|
|
32745
32796
|
maxBuffer: 32 * 1024 * 1024
|
|
@@ -32764,7 +32815,7 @@ async function readBoard(projectDir, scriptsDir = frizzScriptsDir()) {
|
|
|
32764
32815
|
};
|
|
32765
32816
|
}
|
|
32766
32817
|
async function runThreadUpdate(projectDir, slug, args, scriptsDir = frizzScriptsDir()) {
|
|
32767
|
-
await execFileP("node", [
|
|
32818
|
+
await execFileP("node", [join24(scriptsDir, "thread-update.mjs"), slug, ...args], {
|
|
32768
32819
|
cwd: projectDir,
|
|
32769
32820
|
env: { ...process.env, CLAUDE_PROJECT_DIR: projectDir }
|
|
32770
32821
|
});
|
|
@@ -34649,19 +34700,19 @@ var init_claude_agent_broker_bridge = __esm({
|
|
|
34649
34700
|
});
|
|
34650
34701
|
|
|
34651
34702
|
// packages/server/src/backend/auth-status.ts
|
|
34652
|
-
import { join as
|
|
34703
|
+
import { join as join25 } from "node:path";
|
|
34653
34704
|
import { homedir as homedir11, platform as platform2 } from "node:os";
|
|
34654
34705
|
import { readFileSync as readFileSync15, statSync as statSync11 } from "node:fs";
|
|
34655
34706
|
import { execFile as execFile4 } from "node:child_process";
|
|
34656
34707
|
import { promisify as promisify4 } from "node:util";
|
|
34657
34708
|
function claudeConfigDir2() {
|
|
34658
34709
|
const override = process.env.CLAUDE_CONFIG_DIR;
|
|
34659
|
-
return override && override.trim() ? override :
|
|
34710
|
+
return override && override.trim() ? override : join25(homedir11(), ".claude");
|
|
34660
34711
|
}
|
|
34661
34712
|
function claudeFileState(configDir) {
|
|
34662
34713
|
let raw2;
|
|
34663
34714
|
try {
|
|
34664
|
-
raw2 = readFileSync15(
|
|
34715
|
+
raw2 = readFileSync15(join25(configDir, ".credentials.json"), "utf8");
|
|
34665
34716
|
} catch (err) {
|
|
34666
34717
|
return err.code === "ENOENT" ? "absent" : "error";
|
|
34667
34718
|
}
|
|
@@ -34694,7 +34745,7 @@ function readCodexAuthState(codexHome = defaultCodexHome()) {
|
|
|
34694
34745
|
if (process.env.OPENAI_API_KEY || process.env.CODEX_API_KEY || process.env.CODEX_ACCESS_TOKEN) return "authed";
|
|
34695
34746
|
let raw2;
|
|
34696
34747
|
try {
|
|
34697
|
-
raw2 = readFileSync15(
|
|
34748
|
+
raw2 = readFileSync15(join25(codexHome, "auth.json"), "utf8");
|
|
34698
34749
|
} catch (err) {
|
|
34699
34750
|
return err.code === "ENOENT" ? "signed-out" : "unknown";
|
|
34700
34751
|
}
|
|
@@ -34759,7 +34810,7 @@ function asEmail(value) {
|
|
|
34759
34810
|
}
|
|
34760
34811
|
function claudeAccountFile() {
|
|
34761
34812
|
const override = process.env.CLAUDE_CONFIG_DIR;
|
|
34762
|
-
return override && override.trim() ?
|
|
34813
|
+
return override && override.trim() ? join25(override, ".claude.json") : join25(homedir11(), ".claude.json");
|
|
34763
34814
|
}
|
|
34764
34815
|
function readClaudeAccountEmail(path = claudeAccountFile()) {
|
|
34765
34816
|
let stat2;
|
|
@@ -34783,7 +34834,7 @@ function readClaudeAccountEmail(path = claudeAccountFile()) {
|
|
|
34783
34834
|
function readCodexAccountEmail(codexHome = defaultCodexHome()) {
|
|
34784
34835
|
let doc;
|
|
34785
34836
|
try {
|
|
34786
|
-
doc = JSON.parse(readFileSync15(
|
|
34837
|
+
doc = JSON.parse(readFileSync15(join25(codexHome, "auth.json"), "utf8"));
|
|
34787
34838
|
} catch {
|
|
34788
34839
|
return void 0;
|
|
34789
34840
|
}
|
|
@@ -34851,7 +34902,7 @@ var init_auth_status = __esm({
|
|
|
34851
34902
|
|
|
34852
34903
|
// packages/server/src/dispatch.ts
|
|
34853
34904
|
import { closeSync as closeSync12, constants, existsSync as existsSync10, fstatSync as fstatSync2, lstatSync as lstatSync3, openSync as openSync13, readFileSync as readFileSync16, realpathSync as realpathSync7, statSync as statSync12, writeFileSync as writeFileSync10, mkdirSync as mkdirSync13, rmSync as rmSync8 } from "node:fs";
|
|
34854
|
-
import { basename as basename6, join as
|
|
34905
|
+
import { basename as basename6, join as join26, dirname as dirname11 } from "node:path";
|
|
34855
34906
|
import { createHash as createHash11, randomUUID as randomUUID13 } from "node:crypto";
|
|
34856
34907
|
function fallbackTitle(prompt) {
|
|
34857
34908
|
const firstLine2 = prompt.trim().split("\n", 1)[0].trim();
|
|
@@ -34870,7 +34921,7 @@ function fallbackTitle(prompt) {
|
|
|
34870
34921
|
}
|
|
34871
34922
|
function resolveSlug(frizzDir, base, taken) {
|
|
34872
34923
|
base = ThreadSlug.parse(base);
|
|
34873
|
-
const isTaken = (slug) => existsSync10(
|
|
34924
|
+
const isTaken = (slug) => existsSync10(join26(frizzDir, `${slug}.md`)) || (taken?.(slug) ?? false);
|
|
34874
34925
|
if (!isTaken(base)) return base;
|
|
34875
34926
|
for (let n = 2; ; n++) {
|
|
34876
34927
|
const suffix = `-${n}`;
|
|
@@ -34887,12 +34938,12 @@ function resolveLegacyThreadFile(projectDir, value) {
|
|
|
34887
34938
|
if (!parsed.success) return null;
|
|
34888
34939
|
try {
|
|
34889
34940
|
const projectRoot = realpathSync7(projectDir);
|
|
34890
|
-
const frizzPath =
|
|
34941
|
+
const frizzPath = join26(projectRoot, ".frizz");
|
|
34891
34942
|
const frizzStat = lstatSync3(frizzPath);
|
|
34892
34943
|
if (!frizzStat.isDirectory() || frizzStat.isSymbolicLink()) return null;
|
|
34893
34944
|
const realFrizz = realpathSync7(frizzPath);
|
|
34894
34945
|
if (dirname11(realFrizz) !== projectRoot || basename6(realFrizz) !== ".frizz") return null;
|
|
34895
|
-
const path =
|
|
34946
|
+
const path = join26(realFrizz, `${parsed.data}.md`);
|
|
34896
34947
|
const before = lstatSync3(path);
|
|
34897
34948
|
if (!before.isFile() || before.isSymbolicLink()) return null;
|
|
34898
34949
|
const realPath = realpathSync7(path);
|
|
@@ -34936,7 +34987,7 @@ function boardAuthorizesAdoption(board, slug) {
|
|
|
34936
34987
|
return !board.errorItems.some((item) => item.file === `${slug}.md`);
|
|
34937
34988
|
}
|
|
34938
34989
|
function ensureSafeDirectDirectory(parent, name) {
|
|
34939
|
-
const path =
|
|
34990
|
+
const path = join26(parent, name);
|
|
34940
34991
|
try {
|
|
34941
34992
|
mkdirSync13(path);
|
|
34942
34993
|
} catch (error) {
|
|
@@ -34966,8 +35017,8 @@ function loadWorkerPrompt(kind = "claude") {
|
|
|
34966
35017
|
function monitorScriptsDir() {
|
|
34967
35018
|
const plugin = workerPluginDir();
|
|
34968
35019
|
if (!plugin) return void 0;
|
|
34969
|
-
const dir =
|
|
34970
|
-
return existsSync10(
|
|
35020
|
+
const dir = join26(plugin, "skills", "gh", "scripts");
|
|
35021
|
+
return existsSync10(join26(dir, "ci-watch.mjs")) ? dir : void 0;
|
|
34971
35022
|
}
|
|
34972
35023
|
function codexScratchpadHookConfig(hookScript, sessionId) {
|
|
34973
35024
|
if (!hookScript || !sessionId) return {};
|
|
@@ -34979,7 +35030,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
|
|
|
34979
35030
|
}
|
|
34980
35031
|
]
|
|
34981
35032
|
});
|
|
34982
|
-
const bashBackgroundHook =
|
|
35033
|
+
const bashBackgroundHook = join26(dirname11(hookScript), "bash-background.mjs");
|
|
34983
35034
|
return {
|
|
34984
35035
|
bypass_hook_trust: true,
|
|
34985
35036
|
hooks: {
|
|
@@ -35005,7 +35056,7 @@ function codexScratchpadHookConfig(hookScript, sessionId) {
|
|
|
35005
35056
|
}
|
|
35006
35057
|
function scratchpadHookScript() {
|
|
35007
35058
|
const plugin = workerPluginDir();
|
|
35008
|
-
return plugin ?
|
|
35059
|
+
return plugin ? join26(plugin, "hooks", "scratchpad.mjs") : void 0;
|
|
35009
35060
|
}
|
|
35010
35061
|
function composePrompt(sessionId, prompt, kind = "claude") {
|
|
35011
35062
|
const children2 = kind === "codex" ? "Native sub-agents share it \u2014 have each write its OWN file rather than all editing one." : "Name it in a sub-agent's prompt when you want its notes to land somewhere you can read; give each child its OWN file rather than having them all edit one.";
|
|
@@ -35021,7 +35072,7 @@ function scratchpadOrientation(sessionId, kind = "claude") {
|
|
|
35021
35072
|
return `SCRATCH DIRECTORY: .frizz/threads/${sessionId}/ \u2014 yours, free-form, as many files as you like, and nothing is expected in it. A single direct task usually needs none; writing notes is never a substitute for doing the work. On a long effort write the doc you would want if you lost your context (${children2}), then arm mcp__frizz__recurring_prompt with post_compaction: true and a prompt LINKING that file \u2014 frizz hands the link back when your context is compacted. Nothing in this directory is read automatically.`;
|
|
35022
35073
|
}
|
|
35023
35074
|
function frizzConfigBlock(projectDir) {
|
|
35024
|
-
const path =
|
|
35075
|
+
const path = join26(projectDir, "FRIZZ.md");
|
|
35025
35076
|
let body;
|
|
35026
35077
|
try {
|
|
35027
35078
|
const st = statSync12(path);
|
|
@@ -35061,7 +35112,7 @@ function resolveFrizzMcp(target, moduleUrl = import.meta.url, env = process.env,
|
|
|
35061
35112
|
const { stateDir, serverLock, projectId } = typeof target === "string" ? { stateDir: target } : target;
|
|
35062
35113
|
const pluginDir = resolveWorkerPluginDir(moduleUrl, env);
|
|
35063
35114
|
if (!pluginDir) return void 0;
|
|
35064
|
-
const scriptPath =
|
|
35115
|
+
const scriptPath = join26(pluginDir, "bin", FRIZZ_MCP.script);
|
|
35065
35116
|
if (!existsSync10(scriptPath)) return void 0;
|
|
35066
35117
|
return {
|
|
35067
35118
|
scriptPath,
|
|
@@ -35144,7 +35195,7 @@ function buildClaudeResumeCommand(opts) {
|
|
|
35144
35195
|
}
|
|
35145
35196
|
function createDispatcher(deps) {
|
|
35146
35197
|
const readBoardSource = deps.readBoard ?? readBoard;
|
|
35147
|
-
const frizzDir =
|
|
35198
|
+
const frizzDir = join26(deps.project.dir, ".frizz");
|
|
35148
35199
|
const adoptionRuntime = deps.adoptionRuntime ?? productionRuntime;
|
|
35149
35200
|
function cleanupPrewrites(built) {
|
|
35150
35201
|
for (const path of new Set(built.prewrite.map((file) => file.path))) {
|
|
@@ -35157,7 +35208,7 @@ function createDispatcher(deps) {
|
|
|
35157
35208
|
function cleanupDispatchFiles(scratchRel, built, sessionId) {
|
|
35158
35209
|
cleanupPrewrites(built);
|
|
35159
35210
|
try {
|
|
35160
|
-
rmSync8(
|
|
35211
|
+
rmSync8(join26(deps.project.dir, scratchRel), { force: true, recursive: true });
|
|
35161
35212
|
} catch {
|
|
35162
35213
|
}
|
|
35163
35214
|
cleanupAdoptionSessionFiles(deps.project.dir, sessionId);
|
|
@@ -35590,7 +35641,7 @@ import {
|
|
|
35590
35641
|
watch as fsWatch
|
|
35591
35642
|
} from "node:fs";
|
|
35592
35643
|
import { homedir as homedir12 } from "node:os";
|
|
35593
|
-
import { join as
|
|
35644
|
+
import { join as join27 } from "node:path";
|
|
35594
35645
|
import watcher from "@parcel/watcher";
|
|
35595
35646
|
function appServerTurnStalled(liveness, lastActivityAt, nowMs) {
|
|
35596
35647
|
if (!liveness) return false;
|
|
@@ -36275,7 +36326,7 @@ function createBoard(project, storage, bus, tailer, bootId, deps = {}) {
|
|
|
36275
36326
|
if (parcelSub || stopped) return Promise.resolve();
|
|
36276
36327
|
if (watchSetup) return watchSetup;
|
|
36277
36328
|
const setup = (async () => {
|
|
36278
|
-
const next = await subscribe(
|
|
36329
|
+
const next = await subscribe(join27(project.dir, ".frizz"), () => scheduleRebuild());
|
|
36279
36330
|
if (stopped) {
|
|
36280
36331
|
await next.unsubscribe();
|
|
36281
36332
|
return;
|
|
@@ -38209,7 +38260,7 @@ var init_resume = __esm({
|
|
|
38209
38260
|
});
|
|
38210
38261
|
|
|
38211
38262
|
// packages/server/src/backend/claude.ts
|
|
38212
|
-
import { join as
|
|
38263
|
+
import { join as join28 } from "node:path";
|
|
38213
38264
|
function toolResultText2(content) {
|
|
38214
38265
|
if (typeof content === "string") return content;
|
|
38215
38266
|
if (!Array.isArray(content)) return "";
|
|
@@ -38298,7 +38349,7 @@ function createClaudeBackend(opts) {
|
|
|
38298
38349
|
return { argv, env: claudeWorkerEnvironment(), prewrite: [] };
|
|
38299
38350
|
},
|
|
38300
38351
|
transcriptPath(sessionId) {
|
|
38301
|
-
return
|
|
38352
|
+
return join28(opts.logDir, `${sessionId}.jsonl`);
|
|
38302
38353
|
},
|
|
38303
38354
|
parseLine(line) {
|
|
38304
38355
|
return parseClaudeLine(line);
|
|
@@ -38468,12 +38519,12 @@ var init_login_utility = __esm({
|
|
|
38468
38519
|
|
|
38469
38520
|
// packages/server/src/backend/codex-app-server-diagnostics.ts
|
|
38470
38521
|
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync14, renameSync as renameSync8, statSync as statSync13 } from "node:fs";
|
|
38471
|
-
import { join as
|
|
38522
|
+
import { join as join29 } from "node:path";
|
|
38472
38523
|
function codexDiagnosticLogPath(stateDir, projectId) {
|
|
38473
|
-
return
|
|
38524
|
+
return join29(stateDir, "codex-app-server", `${projectId}.diagnostics.log`);
|
|
38474
38525
|
}
|
|
38475
38526
|
function createCodexDiagnosticSink(stateDir, projectId, now = () => /* @__PURE__ */ new Date()) {
|
|
38476
|
-
const dir =
|
|
38527
|
+
const dir = join29(stateDir, "codex-app-server");
|
|
38477
38528
|
const path = codexDiagnosticLogPath(stateDir, projectId);
|
|
38478
38529
|
let ensured = false;
|
|
38479
38530
|
return (event) => {
|
|
@@ -38505,7 +38556,7 @@ var init_codex_app_server_diagnostics = __esm({
|
|
|
38505
38556
|
import { execFile as execFile7 } from "node:child_process";
|
|
38506
38557
|
import { readdirSync as readdirSync8, unlinkSync as unlinkSync4 } from "node:fs";
|
|
38507
38558
|
import { connect as connectSocket } from "node:net";
|
|
38508
|
-
import { join as
|
|
38559
|
+
import { join as join30 } from "node:path";
|
|
38509
38560
|
function parseLsofSocketNames(stdout) {
|
|
38510
38561
|
const referenced = /* @__PURE__ */ new Set();
|
|
38511
38562
|
for (const line of stdout.split("\n")) {
|
|
@@ -38522,7 +38573,7 @@ function sweepStaleSockets(options, deps = {}) {
|
|
|
38522
38573
|
const keep = new Set(options.keep ?? []);
|
|
38523
38574
|
let candidates;
|
|
38524
38575
|
try {
|
|
38525
|
-
candidates = (deps.readdir ?? readdirSync8)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) =>
|
|
38576
|
+
candidates = (deps.readdir ?? readdirSync8)(options.dir).filter((name) => name.startsWith(options.prefix) && name.endsWith(".sock")).map((name) => join30(options.dir, name)).filter((path) => !keep.has(path));
|
|
38526
38577
|
} catch {
|
|
38527
38578
|
return;
|
|
38528
38579
|
}
|
|
@@ -38986,7 +39037,7 @@ var init_thread_hibernation = __esm({
|
|
|
38986
39037
|
});
|
|
38987
39038
|
|
|
38988
39039
|
// packages/server/src/context.ts
|
|
38989
|
-
import { join as
|
|
39040
|
+
import { join as join31 } from "node:path";
|
|
38990
39041
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
38991
39042
|
import { homedir as homedir13 } from "node:os";
|
|
38992
39043
|
function reconcileSessions(storage) {
|
|
@@ -39144,7 +39195,7 @@ async function createContext(opts = {}) {
|
|
|
39144
39195
|
function createContextUnchecked(opts, resources) {
|
|
39145
39196
|
const home = opts.home ?? homedir13();
|
|
39146
39197
|
const project = opts.project ?? resolveProject();
|
|
39147
|
-
const dbPath =
|
|
39198
|
+
const dbPath = join31(project.stateDir, "ui.db");
|
|
39148
39199
|
const storage = createStorage(dbPath);
|
|
39149
39200
|
resources.storage = storage;
|
|
39150
39201
|
const bus = new Bus();
|
|
@@ -39472,6 +39523,7 @@ ${wakeDeliveryToken(deliveryId)}`;
|
|
|
39472
39523
|
getSettings: () => getSettings(storage, home),
|
|
39473
39524
|
setSettings: (s) => setSettings(storage, s, home),
|
|
39474
39525
|
resetSettings: () => resetSettings(storage, home),
|
|
39526
|
+
activeTenants: opts.activeTenants,
|
|
39475
39527
|
claudeBin: opts.claudeBin,
|
|
39476
39528
|
codexBin: opts.codexBin,
|
|
39477
39529
|
loginUtility: createLoginUtility({ claudeBin: opts.claudeBin, codexBin: opts.codexBin, cwd: project.dir })
|
|
@@ -42381,7 +42433,7 @@ var init_bash_background = __esm({
|
|
|
42381
42433
|
import { closeSync as closeSync13, existsSync as existsSync13, fstatSync as fstatSync3, mkdirSync as mkdirSync15, openSync as openSync14, readdirSync as readdirSync9, readFileSync as readFileSync20, readSync as readSync7, renameSync as renameSync9, statSync as statSync14, unlinkSync as unlinkSync5, writeFileSync as writeFileSync12 } from "node:fs";
|
|
42382
42434
|
import { createHash as createHash13 } from "node:crypto";
|
|
42383
42435
|
import { StringDecoder as StringDecoder4 } from "node:string_decoder";
|
|
42384
|
-
import { join as
|
|
42436
|
+
import { join as join32 } from "node:path";
|
|
42385
42437
|
import { homedir as homedir14 } from "node:os";
|
|
42386
42438
|
function formatTokens(n) {
|
|
42387
42439
|
if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
|
|
@@ -42931,14 +42983,14 @@ function pruneScreenshotCache() {
|
|
|
42931
42983
|
if (entries.length <= SCREENSHOT_CACHE_MAX) return;
|
|
42932
42984
|
const byMtime = entries.map((n) => {
|
|
42933
42985
|
try {
|
|
42934
|
-
return { n, m: statSync14(
|
|
42986
|
+
return { n, m: statSync14(join32(SCREENSHOT_CACHE_DIR, n)).mtimeMs };
|
|
42935
42987
|
} catch {
|
|
42936
42988
|
return { n, m: 0 };
|
|
42937
42989
|
}
|
|
42938
42990
|
}).sort((a, b) => b.m - a.m);
|
|
42939
42991
|
for (const { n } of byMtime.slice(SCREENSHOT_CACHE_MAX)) {
|
|
42940
42992
|
try {
|
|
42941
|
-
unlinkSync5(
|
|
42993
|
+
unlinkSync5(join32(SCREENSHOT_CACHE_DIR, n));
|
|
42942
42994
|
} catch {
|
|
42943
42995
|
}
|
|
42944
42996
|
}
|
|
@@ -42968,14 +43020,14 @@ function persistBase64Image(mediaType, data, idKey) {
|
|
|
42968
43020
|
const ext = IMAGE_MEDIA_EXT[typeof mediaType === "string" ? mediaType.toLowerCase() : ""];
|
|
42969
43021
|
if (!ext || !data) return void 0;
|
|
42970
43022
|
const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
|
|
42971
|
-
const path =
|
|
43023
|
+
const path = join32(SCREENSHOT_CACHE_DIR, `${name}.${ext}`);
|
|
42972
43024
|
try {
|
|
42973
43025
|
if (existsSync13(path)) return path;
|
|
42974
43026
|
if (data.length > SCREENSHOT_MAX_BASE64) return void 0;
|
|
42975
43027
|
const buf = Buffer.from(data, "base64");
|
|
42976
43028
|
if (buf.length === 0 || !looksLikeImage(buf, ext)) return void 0;
|
|
42977
43029
|
mkdirSync15(SCREENSHOT_CACHE_DIR, { recursive: true });
|
|
42978
|
-
const tmp =
|
|
43030
|
+
const tmp = join32(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
|
|
42979
43031
|
writeFileSync12(tmp, buf);
|
|
42980
43032
|
renameSync9(tmp, path);
|
|
42981
43033
|
pruneScreenshotCache();
|
|
@@ -42990,14 +43042,14 @@ function persistSentFile(srcPath, idKey) {
|
|
|
42990
43042
|
const outExt = ext === "jpeg" ? "jpg" : ext;
|
|
42991
43043
|
try {
|
|
42992
43044
|
const name = createHash13("sha256").update(idKey).digest("hex").slice(0, 32);
|
|
42993
|
-
const dest =
|
|
43045
|
+
const dest = join32(SCREENSHOT_CACHE_DIR, `${name}.${outExt}`);
|
|
42994
43046
|
if (existsSync13(dest)) return dest;
|
|
42995
43047
|
const size = statSync14(srcPath).size;
|
|
42996
43048
|
if (size === 0 || size > SENT_IMAGE_MAX_BYTES) return void 0;
|
|
42997
43049
|
const buf = readFileSync20(srcPath);
|
|
42998
43050
|
if (!looksLikeImage(buf, outExt)) return void 0;
|
|
42999
43051
|
mkdirSync15(SCREENSHOT_CACHE_DIR, { recursive: true });
|
|
43000
|
-
const tmp =
|
|
43052
|
+
const tmp = join32(SCREENSHOT_CACHE_DIR, `.${name}.${process.pid}.${screenshotTmpSeq++}.tmp`);
|
|
43001
43053
|
writeFileSync12(tmp, buf);
|
|
43002
43054
|
renameSync9(tmp, dest);
|
|
43003
43055
|
pruneScreenshotCache();
|
|
@@ -43434,16 +43486,16 @@ function verifyIncrementalParse(path, identityPrefix, incremental) {
|
|
|
43434
43486
|
}
|
|
43435
43487
|
}
|
|
43436
43488
|
function logDirOf(project) {
|
|
43437
|
-
return
|
|
43489
|
+
return join32(homedir14(), ".claude", "projects", project.cwdSlug);
|
|
43438
43490
|
}
|
|
43439
43491
|
function resolveTranscriptPath(project, sessionId) {
|
|
43440
|
-
const path =
|
|
43492
|
+
const path = join32(logDirOf(project), `${sessionId}.jsonl`);
|
|
43441
43493
|
try {
|
|
43442
43494
|
if (statSync14(path).size > 0) return path;
|
|
43443
43495
|
} catch {
|
|
43444
43496
|
}
|
|
43445
43497
|
const stranded = discoverTranscriptDir(logDirOf(project), sessionId);
|
|
43446
|
-
return stranded ?
|
|
43498
|
+
return stranded ? join32(stranded, `${sessionId}.jsonl`) : path;
|
|
43447
43499
|
}
|
|
43448
43500
|
function projectCodexTranscript(raw2, identityPrefix = "codex") {
|
|
43449
43501
|
const out = [];
|
|
@@ -44839,7 +44891,7 @@ var init_open_external = __esm({
|
|
|
44839
44891
|
import { spawn as spawn6 } from "node:child_process";
|
|
44840
44892
|
import { readFileSync as readFileSync21, realpathSync as realpathSync8, statSync as statSync15 } from "node:fs";
|
|
44841
44893
|
import { homedir as homedir15 } from "node:os";
|
|
44842
|
-
import { isAbsolute as isAbsolute3, join as
|
|
44894
|
+
import { isAbsolute as isAbsolute3, join as join33, resolve as resolve7, sep } from "node:path";
|
|
44843
44895
|
function isUnder(real, root) {
|
|
44844
44896
|
let rootReal;
|
|
44845
44897
|
try {
|
|
@@ -44869,7 +44921,7 @@ function resolveLocalFile(rawPath, roots) {
|
|
|
44869
44921
|
function resolveOpenableFile(raw2, projectDir, roots, home = homedir15()) {
|
|
44870
44922
|
const trimmed = raw2.trim().replace(/:\d+(?::\d+)?$/, "");
|
|
44871
44923
|
if (!trimmed) return null;
|
|
44872
|
-
const abs = trimmed === "~" ? home : trimmed.startsWith("~/") ?
|
|
44924
|
+
const abs = trimmed === "~" ? home : trimmed.startsWith("~/") ? join33(home, trimmed.slice(2)) : isAbsolute3(trimmed) ? trimmed : resolve7(projectDir, trimmed);
|
|
44873
44925
|
try {
|
|
44874
44926
|
return resolveLocalFile(abs, roots);
|
|
44875
44927
|
} catch {
|
|
@@ -45641,7 +45693,7 @@ var init_directory_picker = __esm({
|
|
|
45641
45693
|
|
|
45642
45694
|
// packages/server/src/router.ts
|
|
45643
45695
|
import { readFileSync as readFileSync22, statSync as statSync17 } from "node:fs";
|
|
45644
|
-
import { join as
|
|
45696
|
+
import { join as join34, resolve as resolve8 } from "node:path";
|
|
45645
45697
|
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
45646
45698
|
import { basename as basename9, dirname as dirname14 } from "node:path";
|
|
45647
45699
|
import { existsSync as existsSync14, mkdirSync as mkdirSync16, rmSync as rmSync9, writeFileSync as writeFileSync13 } from "node:fs";
|
|
@@ -45804,7 +45856,7 @@ function projectCard(entry, stale) {
|
|
|
45804
45856
|
function addProjectAtPath(input) {
|
|
45805
45857
|
const typed = input.trim();
|
|
45806
45858
|
if (!typed) throw new Error("Enter a folder path.");
|
|
45807
|
-
const expanded = typed === "~" || typed.startsWith("~/") ?
|
|
45859
|
+
const expanded = typed === "~" || typed.startsWith("~/") ? join34(homedir16(), typed.slice(1)) : typed;
|
|
45808
45860
|
const absolute = resolve8(expanded);
|
|
45809
45861
|
let stats;
|
|
45810
45862
|
try {
|
|
@@ -45857,7 +45909,7 @@ function setProjectIconFromFile(id, file) {
|
|
|
45857
45909
|
return storeProjectIcon(id, file, bytes);
|
|
45858
45910
|
}
|
|
45859
45911
|
function createRouter(ctx) {
|
|
45860
|
-
const frizzDir =
|
|
45912
|
+
const frizzDir = join34(ctx.project.dir, ".frizz");
|
|
45861
45913
|
const openRoots = openableFileRoots(ctx.project);
|
|
45862
45914
|
function isAutoTitledSession(slug) {
|
|
45863
45915
|
return ctx.storage.getSession(slug)?.title_auto === 1;
|
|
@@ -47362,6 +47414,35 @@ ${gapNote}` : input.message;
|
|
|
47362
47414
|
output: external_exports.array(ProjectCard),
|
|
47363
47415
|
handler: async () => listProjects().map((entry) => projectCard(entry, entry.stale))
|
|
47364
47416
|
}),
|
|
47417
|
+
/**
|
|
47418
|
+
* How many threads are in each project's queue, keyed by project id — the rail's badges.
|
|
47419
|
+
*
|
|
47420
|
+
* MACHINE-WIDE, answered from the boards this process has OPEN. A queue count is a board fact:
|
|
47421
|
+
* `needsYou` is derived from the tailer's live view of each session, so a project nobody has
|
|
47422
|
+
* opened since boot has no honest count, and it is left out rather than guessed at or opened for
|
|
47423
|
+
* the purpose (activating a project to badge it is exactly the cost lazy activation exists to
|
|
47424
|
+
* avoid — see tenants.ts). Absent ⇒ no badge; the project the operator is looking at is always
|
|
47425
|
+
* present, and the client draws THAT one from its own live board anyway.
|
|
47426
|
+
*
|
|
47427
|
+
* Kept OFF `projectsList` on purpose: that list is one registry-file read, cheap enough to be the
|
|
47428
|
+
* home page with forty projects, and this is a walk over live boards. The cached snapshot makes
|
|
47429
|
+
* it cheap too — but cheap-and-polled is a different budget from cheap-and-once.
|
|
47430
|
+
*/
|
|
47431
|
+
projectsQueueCounts: query({
|
|
47432
|
+
output: external_exports.record(external_exports.string(), external_exports.number().int().nonnegative()),
|
|
47433
|
+
handler: async () => {
|
|
47434
|
+
const counts = {};
|
|
47435
|
+
const open = ctx.activeTenants?.() ?? [{ project: ctx.project, board: ctx.board }];
|
|
47436
|
+
for (const { project, board } of open) {
|
|
47437
|
+
try {
|
|
47438
|
+
const { threads } = await board.snapshot();
|
|
47439
|
+
counts[project.id] = threads.filter(queuedThread).length;
|
|
47440
|
+
} catch {
|
|
47441
|
+
}
|
|
47442
|
+
}
|
|
47443
|
+
return counts;
|
|
47444
|
+
}
|
|
47445
|
+
}),
|
|
47365
47446
|
/**
|
|
47366
47447
|
* Pin the rail's order.
|
|
47367
47448
|
*
|
|
@@ -47483,7 +47564,7 @@ ${gapNote}` : input.message;
|
|
|
47483
47564
|
for (const entry of listProjects()) {
|
|
47484
47565
|
if (entry.stale) continue;
|
|
47485
47566
|
try {
|
|
47486
|
-
const db = new sqlite_default(
|
|
47567
|
+
const db = new sqlite_default(join34(projectStateDir(entry.id), "ui.db"), { readonly: true });
|
|
47487
47568
|
try {
|
|
47488
47569
|
const hit = db.prepare("SELECT 1 FROM session WHERE slug = ? LIMIT 1").get(input.slug);
|
|
47489
47570
|
if (hit) found.push({ projectSlug: entry.slug, projectName: entry.name ?? entry.slug });
|
|
@@ -47876,7 +47957,7 @@ var init_local_image = __esm({
|
|
|
47876
47957
|
// packages/server/src/project-icon.ts
|
|
47877
47958
|
import { readFileSync as readFileSync24, readdirSync as readdirSync10, realpathSync as realpathSync10, statSync as statSync19 } from "node:fs";
|
|
47878
47959
|
import { homedir as homedir17 } from "node:os";
|
|
47879
|
-
import { basename as basename10, dirname as dirname15, extname as extname3, join as
|
|
47960
|
+
import { basename as basename10, dirname as dirname15, extname as extname3, join as join35, relative, sep as sep2 } from "node:path";
|
|
47880
47961
|
function normalizeStem(stem) {
|
|
47881
47962
|
const sized = stem.toLowerCase().replace(/[@-]\d+(\.\d+)?x(\d+)?$/u, "").replace(/[-_]\d{2,4}$/u, "");
|
|
47882
47963
|
const normalized = sized.replace(VARIANT_SUFFIX, "");
|
|
@@ -47894,7 +47975,7 @@ function sizeScore(dimensions) {
|
|
|
47894
47975
|
return Math.max(0, Math.min(40, Math.round(Math.log2(edge / 24) * 8)));
|
|
47895
47976
|
}
|
|
47896
47977
|
function under(root, relativeDirectory) {
|
|
47897
|
-
return relativeDirectory ?
|
|
47978
|
+
return relativeDirectory ? join35(root, relativeDirectory) : root;
|
|
47898
47979
|
}
|
|
47899
47980
|
function listFiles(directory) {
|
|
47900
47981
|
try {
|
|
@@ -47916,19 +47997,19 @@ function iconDirectories(root) {
|
|
|
47916
47997
|
for (const asset of ASSET_DIRECTORIES) directories.push(under(root, asset));
|
|
47917
47998
|
for (const host of HOST_DIRECTORIES) {
|
|
47918
47999
|
if (!children2.has(host)) continue;
|
|
47919
|
-
for (const asset of ASSET_DIRECTORIES) directories.push(under(
|
|
48000
|
+
for (const asset of ASSET_DIRECTORIES) directories.push(under(join35(root, host), asset));
|
|
47920
48001
|
}
|
|
47921
48002
|
for (const extra of EXTRA_DIRECTORIES) directories.push(under(root, extra));
|
|
47922
48003
|
for (const container of WORKSPACE_CONTAINERS) {
|
|
47923
48004
|
if (!children2.has(container)) continue;
|
|
47924
48005
|
let members;
|
|
47925
48006
|
try {
|
|
47926
|
-
members = readdirSync10(
|
|
48007
|
+
members = readdirSync10(join35(root, container), { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
|
|
47927
48008
|
} catch {
|
|
47928
48009
|
continue;
|
|
47929
48010
|
}
|
|
47930
48011
|
for (const member of members) {
|
|
47931
|
-
for (const asset of ASSET_DIRECTORIES) directories.push(under(
|
|
48012
|
+
for (const asset of ASSET_DIRECTORIES) directories.push(under(join35(root, container, member), asset));
|
|
47932
48013
|
}
|
|
47933
48014
|
}
|
|
47934
48015
|
return [...new Set(directories)];
|
|
@@ -47942,7 +48023,7 @@ function manifestIcons(manifestPath) {
|
|
|
47942
48023
|
}
|
|
47943
48024
|
if (!Array.isArray(parsed?.icons)) return [];
|
|
47944
48025
|
const directory = dirname15(manifestPath);
|
|
47945
|
-
return parsed.icons.map((icon) => typeof icon?.src === "string" ? icon.src : void 0).filter((src) => !!src && !/^(https?:)?\/\//u.test(src) && !src.startsWith("data:")).map((src) =>
|
|
48026
|
+
return parsed.icons.map((icon) => typeof icon?.src === "string" ? icon.src : void 0).filter((src) => !!src && !/^(https?:)?\/\//u.test(src) && !src.startsWith("data:")).map((src) => join35(directory, src.replace(/[?#].*$/u, "").replace(/^\//u, "")));
|
|
47946
48027
|
}
|
|
47947
48028
|
function projectIconCandidates(root) {
|
|
47948
48029
|
const projectStem = normalizeStem(basename10(root)).normalized;
|
|
@@ -47961,7 +48042,7 @@ function projectIconCandidates(root) {
|
|
|
47961
48042
|
for (const name of listFiles(directory)) {
|
|
47962
48043
|
const extension2 = extname3(name).toLowerCase();
|
|
47963
48044
|
if (MANIFEST_NAMES.includes(name.toLowerCase())) {
|
|
47964
|
-
for (const icon of manifestIcons(
|
|
48045
|
+
for (const icon of manifestIcons(join35(directory, name))) {
|
|
47965
48046
|
if (MEASURABLE_IMAGE_EXTENSIONS.has(extname3(icon).toLowerCase())) {
|
|
47966
48047
|
fromManifest.add(icon);
|
|
47967
48048
|
files.push({ path: icon, directory: dirname15(icon) });
|
|
@@ -47972,7 +48053,7 @@ function projectIconCandidates(root) {
|
|
|
47972
48053
|
if (!MEASURABLE_IMAGE_EXTENSIONS.has(extension2)) continue;
|
|
47973
48054
|
const stem = name.slice(0, name.length - extension2.length);
|
|
47974
48055
|
if (normalizeStem(stem).normalized === "favicon") iconHomes.add(directory);
|
|
47975
|
-
files.push({ path:
|
|
48056
|
+
files.push({ path: join35(directory, name), directory });
|
|
47976
48057
|
if (files.length >= MAX_CANDIDATES) break;
|
|
47977
48058
|
}
|
|
47978
48059
|
}
|
|
@@ -48150,7 +48231,7 @@ var init_project_icon = __esm({
|
|
|
48150
48231
|
|
|
48151
48232
|
// packages/server/src/local-visualization.ts
|
|
48152
48233
|
import { readdirSync as readdirSync11, readFileSync as readFileSync25, realpathSync as realpathSync11, statSync as statSync20 } from "node:fs";
|
|
48153
|
-
import { join as
|
|
48234
|
+
import { join as join36, sep as sep3 } from "node:path";
|
|
48154
48235
|
function children(path, pattern) {
|
|
48155
48236
|
try {
|
|
48156
48237
|
return readdirSync11(path, { withFileTypes: true }).filter((entry) => entry.isDirectory() && pattern.test(entry.name)).map((entry) => entry.name).sort().reverse();
|
|
@@ -48162,7 +48243,7 @@ function isUnder2(path, root) {
|
|
|
48162
48243
|
return path === root || path.startsWith(root.endsWith(sep3) ? root : root + sep3);
|
|
48163
48244
|
}
|
|
48164
48245
|
function resolveFragment(projectDir, sessionId, file) {
|
|
48165
|
-
const base =
|
|
48246
|
+
const base = join36(projectDir, ".codex", "visualizations");
|
|
48166
48247
|
let projectReal;
|
|
48167
48248
|
let baseReal;
|
|
48168
48249
|
try {
|
|
@@ -48173,12 +48254,12 @@ function resolveFragment(projectDir, sessionId, file) {
|
|
|
48173
48254
|
}
|
|
48174
48255
|
if (!isUnder2(baseReal, projectReal)) return null;
|
|
48175
48256
|
for (const year of children(base, YEAR_PART)) {
|
|
48176
|
-
const yearDir =
|
|
48257
|
+
const yearDir = join36(base, year);
|
|
48177
48258
|
for (const month of children(yearDir, DATE_PART)) {
|
|
48178
|
-
const monthDir =
|
|
48259
|
+
const monthDir = join36(yearDir, month);
|
|
48179
48260
|
for (const day of children(monthDir, DATE_PART)) {
|
|
48180
|
-
const sessionRoot =
|
|
48181
|
-
const candidate =
|
|
48261
|
+
const sessionRoot = join36(baseReal, year, month, day, sessionId);
|
|
48262
|
+
const candidate = join36(monthDir, day, sessionId, file);
|
|
48182
48263
|
try {
|
|
48183
48264
|
const real = realpathSync11(candidate);
|
|
48184
48265
|
if (isUnder2(real, sessionRoot) && statSync20(real).isFile()) return real;
|
|
@@ -48307,7 +48388,7 @@ var init_local_visualization = __esm({
|
|
|
48307
48388
|
|
|
48308
48389
|
// packages/server/src/app.ts
|
|
48309
48390
|
import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync14 } from "node:fs";
|
|
48310
|
-
import { join as
|
|
48391
|
+
import { join as join37 } from "node:path";
|
|
48311
48392
|
import { randomUUID as randomUUID17 } from "node:crypto";
|
|
48312
48393
|
function createApp(ctx, options = {}) {
|
|
48313
48394
|
const app = new Hono2();
|
|
@@ -48411,10 +48492,10 @@ function createApp(ctx, options = {}) {
|
|
|
48411
48492
|
if (typeof body.data !== "string" || body.data.length > ATTACHMENT_MAX_BASE64_CHARS) return c.json({ error: "bad payload" }, 400);
|
|
48412
48493
|
const ext = `.${attachmentExtension(name)}`;
|
|
48413
48494
|
const buf = Buffer.from(body.data, "base64");
|
|
48414
|
-
const dir =
|
|
48495
|
+
const dir = join37(ctx.project.stateDir, "attachments");
|
|
48415
48496
|
mkdirSync17(dir, { recursive: true });
|
|
48416
48497
|
const base = name.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]+/g, "-").slice(0, 40) || "file";
|
|
48417
|
-
const path =
|
|
48498
|
+
const path = join37(dir, `${Date.now()}-${randomUUID17().slice(0, 8)}-${base}${ext}`);
|
|
48418
48499
|
writeFileSync14(path, buf);
|
|
48419
48500
|
return c.json({ path });
|
|
48420
48501
|
});
|
|
@@ -49654,9 +49735,9 @@ var init_app_socket = __esm({
|
|
|
49654
49735
|
|
|
49655
49736
|
// packages/server/src/boot-progress.ts
|
|
49656
49737
|
import { mkdirSync as mkdirSync18, readFileSync as readFileSync26, renameSync as renameSync10, rmSync as rmSync10, writeFileSync as writeFileSync15 } from "node:fs";
|
|
49657
|
-
import { basename as basename11, dirname as dirname16, join as
|
|
49738
|
+
import { basename as basename11, dirname as dirname16, join as join38 } from "node:path";
|
|
49658
49739
|
function bootProgressPath(stateDir) {
|
|
49659
|
-
return
|
|
49740
|
+
return join38(stateDir, BOOT_PROGRESS_NAME);
|
|
49660
49741
|
}
|
|
49661
49742
|
function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
|
|
49662
49743
|
if (!stateDir) {
|
|
@@ -49677,7 +49758,7 @@ function createBootProgressPublisher(stateDir, minIntervalMs = 200) {
|
|
|
49677
49758
|
step++;
|
|
49678
49759
|
try {
|
|
49679
49760
|
mkdirSync18(dirname16(path), { recursive: true, mode: 448 });
|
|
49680
|
-
const temp =
|
|
49761
|
+
const temp = join38(dirname16(path), `.${basename11(path)}.${process.pid}.tmp`);
|
|
49681
49762
|
writeFileSync15(temp, `${JSON.stringify({ pid: process.pid, step, phase, at: new Date(now).toISOString() })}
|
|
49682
49763
|
`, "utf8");
|
|
49683
49764
|
renameSync10(temp, path);
|
|
@@ -49795,7 +49876,7 @@ __export(index_exports, {
|
|
|
49795
49876
|
});
|
|
49796
49877
|
import { createServer } from "node:http";
|
|
49797
49878
|
import { readFileSync as readFileSync27, existsSync as existsSync15 } from "node:fs";
|
|
49798
|
-
import { dirname as dirname17, join as
|
|
49879
|
+
import { dirname as dirname17, join as join39, resolve as resolve9, extname as extname4, normalize } from "node:path";
|
|
49799
49880
|
function readServerAddressHolder(path) {
|
|
49800
49881
|
try {
|
|
49801
49882
|
const value = JSON.parse(readFileSync27(path, "utf8"));
|
|
@@ -49898,9 +49979,9 @@ function createShutdownSignalHandler(options) {
|
|
|
49898
49979
|
}
|
|
49899
49980
|
function serveStatic(distDir, req, res) {
|
|
49900
49981
|
const rel = normalize((req.url ?? "/").split("?")[0]).replace(/^(\.\.[/\\])+/, "");
|
|
49901
|
-
let file =
|
|
49902
|
-
if (!file.startsWith(distDir)) file =
|
|
49903
|
-
if (!existsSync15(file)) file =
|
|
49982
|
+
let file = join39(distDir, rel === "/" ? "index.html" : rel);
|
|
49983
|
+
if (!file.startsWith(distDir)) file = join39(distDir, "index.html");
|
|
49984
|
+
if (!existsSync15(file)) file = join39(distDir, "index.html");
|
|
49904
49985
|
try {
|
|
49905
49986
|
const body = readFileSync27(file);
|
|
49906
49987
|
res.writeHead(200, { "content-type": MIME[extname4(file)] ?? "application/octet-stream" });
|
|
@@ -49931,6 +50012,7 @@ async function startServer(opts = {}) {
|
|
|
49931
50012
|
`${candidate.name} is already being served by another Frizz (pid ${other}). Stop that one first \u2014 two servers on one board would fire its timers and recurring prompts twice.`
|
|
49932
50013
|
);
|
|
49933
50014
|
};
|
|
50015
|
+
const activeTenants = () => tenants.active().map(({ project: open, ctx: openCtx }) => ({ project: open, board: openCtx.board }));
|
|
49934
50016
|
const tenants = createTenantMap({
|
|
49935
50017
|
createContext: (contextOptions) => {
|
|
49936
50018
|
if (contextOptions.project) assertNotServedElsewhere(contextOptions.project);
|
|
@@ -49938,7 +50020,7 @@ async function startServer(opts = {}) {
|
|
|
49938
50020
|
},
|
|
49939
50021
|
// serverLockPath is the LAUNCHING project's: it is the only `server.lock` this process publishes
|
|
49940
50022
|
// (see "status publication"), so it is the only file a tenant's worker can read the port out of.
|
|
49941
|
-
contextOptions: { claudeBin: opts.claudeBin, serverLockPath: serverLockPathFor(project) },
|
|
50023
|
+
contextOptions: { claudeBin: opts.claudeBin, serverLockPath: serverLockPathFor(project), activeTenants },
|
|
49942
50024
|
// Each project's app carries ITS OWN owner proof, so /health stays honest per project rather than
|
|
49943
50025
|
// answering for whichever one happened to launch the server. The transports are per project for a
|
|
49944
50026
|
// blunter reason: a socket is a live feed of ONE board, so sharing the launcher's would push its
|
|
@@ -50197,6 +50279,7 @@ async function startServer(opts = {}) {
|
|
|
50197
50279
|
claudeBin: opts.claudeBin,
|
|
50198
50280
|
project,
|
|
50199
50281
|
serverLockPath: serverLockPathFor(project),
|
|
50282
|
+
activeTenants,
|
|
50200
50283
|
startup: {
|
|
50201
50284
|
afterPhase: (p) => {
|
|
50202
50285
|
bootProgress(`context: ${p}`);
|
|
@@ -50249,7 +50332,7 @@ async function startServer(opts = {}) {
|
|
|
50249
50332
|
}
|
|
50250
50333
|
statusPath = serverLockPathFor(ctx.project);
|
|
50251
50334
|
const webRoot = resolve9(import.meta.dirname, "..", "..", "web");
|
|
50252
|
-
const distDir = opts.webDistDir ? resolve9(opts.webDistDir) :
|
|
50335
|
+
const distDir = opts.webDistDir ? resolve9(opts.webDistDir) : join39(webRoot, "dist");
|
|
50253
50336
|
startupPhase = "Vite";
|
|
50254
50337
|
if (opts.dev) {
|
|
50255
50338
|
try {
|
|
@@ -50325,7 +50408,7 @@ async function startServer(opts = {}) {
|
|
|
50325
50408
|
if (vite) {
|
|
50326
50409
|
vite.middlewares(req, res, () => {
|
|
50327
50410
|
try {
|
|
50328
|
-
const html = readFileSync27(
|
|
50411
|
+
const html = readFileSync27(join39(webRoot, "index.html"), "utf8");
|
|
50329
50412
|
void vite.transformIndexHtml(url, html).then((out) => {
|
|
50330
50413
|
res.writeHead(200, { "content-type": "text/html" });
|
|
50331
50414
|
res.end(out);
|
|
@@ -50517,7 +50600,7 @@ var init_index = __esm({
|
|
|
50517
50600
|
}
|
|
50518
50601
|
};
|
|
50519
50602
|
isApiUrl = (url) => url === FRIZZ_ROUTE_PREFIX || url.startsWith(`${FRIZZ_ROUTE_PREFIX}/`);
|
|
50520
|
-
serverLockPathFor = (project) =>
|
|
50603
|
+
serverLockPathFor = (project) => join39(project.stateDir, "server.lock");
|
|
50521
50604
|
MIME = {
|
|
50522
50605
|
".html": "text/html",
|
|
50523
50606
|
".js": "text/javascript",
|
|
@@ -50536,7 +50619,7 @@ init_project_launch();
|
|
|
50536
50619
|
init_shutdown();
|
|
50537
50620
|
init_logging();
|
|
50538
50621
|
import { existsSync as existsSync16 } from "node:fs";
|
|
50539
|
-
import { join as
|
|
50622
|
+
import { join as join40 } from "node:path";
|
|
50540
50623
|
process.on("uncaughtException", (error) => {
|
|
50541
50624
|
log.error("dev-child", `uncaught exception: ${error instanceof Error ? error.stack ?? error.message : error}`);
|
|
50542
50625
|
process.exit(1);
|
|
@@ -50576,7 +50659,7 @@ try {
|
|
|
50576
50659
|
];
|
|
50577
50660
|
if (!existsSync16(stableWebDist)) throw new Error("stable artifact launch is missing its verified web directory");
|
|
50578
50661
|
for (const [name, directory, requiredFile] of required) {
|
|
50579
|
-
if (!directory || !existsSync16(
|
|
50662
|
+
if (!directory || !existsSync16(join40(directory, requiredFile)))
|
|
50580
50663
|
throw new Error(`stable artifact launch is missing verified ${name}`);
|
|
50581
50664
|
}
|
|
50582
50665
|
}
|