@dotobokuri/fleet-console 1.8.0 → 1.9.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/AGENTS.md +6 -4
- package/dist/cli-bin.mjs +1824 -599
- package/dist/cli.d.ts +4 -0
- package/dist/cli.mjs +1824 -599
- package/dist/client/assets/{_baseUniq-BvJBBAyx.js → _baseUniq-_nKBty4x.js} +1 -1
- package/dist/client/assets/{arc-_In9IKSA.js → arc-DEjqUlkY.js} +1 -1
- package/dist/client/assets/{architectureDiagram-Q4EWVU46-Ch4p9PP9.js → architectureDiagram-Q4EWVU46-CPF3RLab.js} +1 -1
- package/dist/client/assets/{blockDiagram-DXYQGD6D-dV3nM6N6.js → blockDiagram-DXYQGD6D-DguupB0e.js} +1 -1
- package/dist/client/assets/{c4Diagram-AHTNJAMY-Cd4rkDvb.js → c4Diagram-AHTNJAMY-Dd7AVc09.js} +1 -1
- package/dist/client/assets/channel-DA6xE92d.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-BdFP7-t8.js → chunk-4BX2VUAB-CSIihHG7.js} +1 -1
- package/dist/client/assets/{chunk-4TB4RGXK-CwZmzqqH.js → chunk-4TB4RGXK-DR_cPI3H.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-jonfKM4s.js → chunk-55IACEB6-97czQ3iV.js} +1 -1
- package/dist/client/assets/{chunk-EDXVE4YY-Di2ByMxa.js → chunk-EDXVE4YY-piQCPtjQ.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DXLnCQWV.js → chunk-FMBD7UC4-BIeV9l0L.js} +1 -1
- package/dist/client/assets/{chunk-OYMX7WX6-DpgtrxyA.js → chunk-OYMX7WX6-DWUJBKm_.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-BdkOO2d4.js → chunk-QZHKN3VN-DHL5fPU4.js} +1 -1
- package/dist/client/assets/{chunk-YZCP3GAM-Hfgm6DyM.js → chunk-YZCP3GAM-Dk19Wldz.js} +1 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-D46R_D_e.js +1 -0
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-D46R_D_e.js +1 -0
- package/dist/client/assets/clone-DV233GSJ.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DqClnVsA.js → cose-bilkent-S5V4N54A-CcROwyfn.js} +1 -1
- package/dist/client/assets/{dagre-KV5264BT-DlVHx9hg.js → dagre-KV5264BT-kdHN8OcZ.js} +1 -1
- package/dist/client/assets/{diagram-5BDNPKRD-DJVcbz8w.js → diagram-5BDNPKRD-yqi72mWd.js} +1 -1
- package/dist/client/assets/{diagram-G4DWMVQ6-ZCER6PqU.js → diagram-G4DWMVQ6-CTjHbP--.js} +1 -1
- package/dist/client/assets/{diagram-MMDJMWI5-DFt5a-B8.js → diagram-MMDJMWI5-BCGN9v8i.js} +1 -1
- package/dist/client/assets/{diagram-TYMM5635-DXPsYs4b.js → diagram-TYMM5635-p6gtwFXr.js} +1 -1
- package/dist/client/assets/{erDiagram-SMLLAGMA-BEiMZzzV.js → erDiagram-SMLLAGMA-BHNCT04F.js} +1 -1
- package/dist/client/assets/{flowDiagram-DWJPFMVM-DTBFF-X2.js → flowDiagram-DWJPFMVM-DP-E6Gb1.js} +1 -1
- package/dist/client/assets/{ganttDiagram-T4ZO3ILL-nE9kklkz.js → ganttDiagram-T4ZO3ILL-COKcadl7.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-VD6J4jc_.js → gitGraphDiagram-UUTBAWPF-CVkte06j.js} +1 -1
- package/dist/client/assets/{graph-CuZGH1eI.js → graph-BljmCiGu.js} +1 -1
- package/dist/client/assets/index-B7IECSX7.css +1 -0
- package/dist/client/assets/index-CSTdaEyG.js +777 -0
- package/dist/client/assets/{infoDiagram-42DDH7IO-BdxLeDgE.js → infoDiagram-42DDH7IO-Dh_U82lE.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-OG_S8qjo.js → ishikawaDiagram-UXIWVN3A-BtZhb0mv.js} +1 -1
- package/dist/client/assets/{journeyDiagram-VCZTEJTY-CvZPwJCs.js → journeyDiagram-VCZTEJTY-_Zd4No67.js} +1 -1
- package/dist/client/assets/{kanban-definition-6JOO6SKY-4hgVjEGs.js → kanban-definition-6JOO6SKY-CpIIMkPJ.js} +1 -1
- package/dist/client/assets/{layout-BHDLAxp5.js → layout-ButG21vs.js} +1 -1
- package/dist/client/assets/{linear-WT8NWS1o.js → linear-C-frnGuN.js} +1 -1
- package/dist/client/assets/{mermaid.core-UWKHwZrH.js → mermaid.core-ISlBhdkY.js} +4 -4
- package/dist/client/assets/{min-CkGW0p-k.js → min-CalB2Q9y.js} +1 -1
- package/dist/client/assets/{mindmap-definition-QFDTVHPH-BxjJxQqR.js → mindmap-definition-QFDTVHPH-BfilPIUD.js} +1 -1
- package/dist/client/assets/{pieDiagram-DEJITSTG-BTjPSbyX.js → pieDiagram-DEJITSTG-Dm_1WIPT.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-34T5L4WZ-D2fCxzGw.js → quadrantDiagram-34T5L4WZ-DMzRgLeF.js} +1 -1
- package/dist/client/assets/{requirementDiagram-MS252O5E-CtElLmk8.js → requirementDiagram-MS252O5E-Bl1lUR6U.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-XADWPNL6-DGqMKAC2.js → sankeyDiagram-XADWPNL6-VxDrFumf.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-FGHM5R23-B8Yva4cR.js → sequenceDiagram-FGHM5R23-BoB_k7L2.js} +1 -1
- package/dist/client/assets/{stateDiagram-FHFEXIEX-BxBGow-_.js → stateDiagram-FHFEXIEX-C8DFihD3.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-DlDadEC7.js +1 -0
- package/dist/client/assets/{timeline-definition-GMOUNBTQ-CUcV7Qpm.js → timeline-definition-GMOUNBTQ-G5hn4rEl.js} +1 -1
- package/dist/client/assets/{vennDiagram-DHZGUBPP-DS0hFmpX.js → vennDiagram-DHZGUBPP-D_jMNDmm.js} +1 -1
- package/dist/client/assets/{wardley-RL74JXVD-Dhd3kp0H.js → wardley-RL74JXVD-Clc5Li47.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-NUSXRM2D-B6QDK0rE.js → wardleyDiagram-NUSXRM2D-Bygn2On7.js} +1 -1
- package/dist/client/assets/{xychartDiagram-5P7HB3ND-tiuCrAL_.js → xychartDiagram-5P7HB3ND-arK3uijt.js} +1 -1
- package/dist/client/index.html +2 -2
- package/package.json +1 -1
- package/postinstall.mjs +29 -0
- package/dist/client/assets/channel-F-hXrSqZ.js +0 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-DqXQgyK4.js +0 -1
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-DqXQgyK4.js +0 -1
- package/dist/client/assets/clone-kL599Cyi.js +0 -1
- package/dist/client/assets/index-ClU0e8Rv.js +0 -734
- package/dist/client/assets/index-VeebE_4d.css +0 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-COhEt-rs.js +0 -1
package/dist/cli-bin.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { execFile, spawn, spawnSync, execSync } from 'child_process';
|
|
2
|
+
import { execFile, spawn, spawnSync, execFileSync, execSync } from 'child_process';
|
|
3
3
|
import * as fs7 from 'fs';
|
|
4
|
-
import fs7__default, { readFileSync, existsSync, mkdtempSync, writeFileSync, mkdirSync, rmSync, chmodSync, renameSync, readdirSync, constants, openSync, closeSync, lstatSync, unlinkSync,
|
|
5
|
-
import * as
|
|
6
|
-
import
|
|
7
|
-
import
|
|
4
|
+
import fs7__default, { readFileSync, existsSync, mkdtempSync, writeFileSync, mkdirSync, realpathSync, rmSync, chmodSync, renameSync, readdirSync, constants, openSync, closeSync, accessSync, lstatSync, unlinkSync, statSync, fstatSync } from 'fs';
|
|
5
|
+
import * as path92 from 'path';
|
|
6
|
+
import path92__default, { join, resolve, relative, dirname } from 'path';
|
|
7
|
+
import process9 from 'process';
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
9
|
-
import
|
|
9
|
+
import crypto3, { createHash, randomUUID, timingSafeEqual } from 'crypto';
|
|
10
10
|
import * as os22 from 'os';
|
|
11
11
|
import os22__default from 'os';
|
|
12
12
|
import { EventEmitter } from 'events';
|
|
@@ -27,7 +27,7 @@ var LOCK_FILE_MODE = 384;
|
|
|
27
27
|
function createConsoleLock(deps = {}) {
|
|
28
28
|
const fsImpl = deps.fs ?? fs7__default;
|
|
29
29
|
const now = deps.now ?? Date.now;
|
|
30
|
-
const randomToken = deps.randomToken ?? (() =>
|
|
30
|
+
const randomToken = deps.randomToken ?? (() => crypto3.randomBytes(32).toString("base64url"));
|
|
31
31
|
const hostname5 = deps.hostname ?? (() => "127.0.0.1");
|
|
32
32
|
function ensureLockDir(dir) {
|
|
33
33
|
fsImpl.mkdirSync(dir, { recursive: true, mode: LOCK_DIR_MODE });
|
|
@@ -82,7 +82,7 @@ function createConsoleLock(deps = {}) {
|
|
|
82
82
|
}
|
|
83
83
|
function assertLockModes(lockFile) {
|
|
84
84
|
if (typeof process.getuid !== "function") return;
|
|
85
|
-
const dir =
|
|
85
|
+
const dir = path92__default.dirname(lockFile);
|
|
86
86
|
const dirMode = fsImpl.statSync(dir).mode & 511;
|
|
87
87
|
const fileMode = fsImpl.statSync(lockFile).mode & 511;
|
|
88
88
|
if (dirMode !== LOCK_DIR_MODE) {
|
|
@@ -124,7 +124,7 @@ function createConsoleLock(deps = {}) {
|
|
|
124
124
|
}
|
|
125
125
|
var FLEET_DATA_DIR_NAME = ".fleet";
|
|
126
126
|
function getFleetDataDir() {
|
|
127
|
-
return
|
|
127
|
+
return path92.join(os22.homedir(), FLEET_DATA_DIR_NAME);
|
|
128
128
|
}
|
|
129
129
|
var SECURE_DIR_MODE = 448;
|
|
130
130
|
var SECURE_FILE_MODE = 384;
|
|
@@ -210,7 +210,7 @@ function cleanupTempFiles(dir, prefix, minAgeMs, now) {
|
|
|
210
210
|
if (!entry.startsWith(prefix)) {
|
|
211
211
|
continue;
|
|
212
212
|
}
|
|
213
|
-
const tempPath =
|
|
213
|
+
const tempPath = path92.join(dir, entry);
|
|
214
214
|
try {
|
|
215
215
|
const stat5 = fs7.lstatSync(tempPath);
|
|
216
216
|
if (stat5?.isFile() && !stat5.isSymbolicLink() && now - stat5.mtimeMs >= minAgeMs) {
|
|
@@ -316,7 +316,7 @@ function writeLockOwner(lockDir, ownerFileName, startedAt) {
|
|
|
316
316
|
hostname: os22.hostname(),
|
|
317
317
|
startedAt
|
|
318
318
|
};
|
|
319
|
-
const ownerPath =
|
|
319
|
+
const ownerPath = path92.join(lockDir, ownerFileName);
|
|
320
320
|
try {
|
|
321
321
|
fs7.writeFileSync(ownerPath, JSON.stringify(owner), { encoding: "utf-8", mode: 384 });
|
|
322
322
|
} catch (error51) {
|
|
@@ -325,7 +325,7 @@ function writeLockOwner(lockDir, ownerFileName, startedAt) {
|
|
|
325
325
|
}
|
|
326
326
|
}
|
|
327
327
|
function readLockOwner(lockDir, ownerFileName) {
|
|
328
|
-
const ownerPath =
|
|
328
|
+
const ownerPath = path92.join(lockDir, ownerFileName);
|
|
329
329
|
try {
|
|
330
330
|
return sanitizeLockOwner(JSON.parse(fs7.readFileSync(ownerPath, "utf-8")));
|
|
331
331
|
} catch (error51) {
|
|
@@ -1144,10 +1144,10 @@ function mergeDefs(...defs) {
|
|
|
1144
1144
|
function cloneDef(schema) {
|
|
1145
1145
|
return mergeDefs(schema._zod.def);
|
|
1146
1146
|
}
|
|
1147
|
-
function getElementAtPath(obj,
|
|
1148
|
-
if (!
|
|
1147
|
+
function getElementAtPath(obj, path36) {
|
|
1148
|
+
if (!path36)
|
|
1149
1149
|
return obj;
|
|
1150
|
-
return
|
|
1150
|
+
return path36.reduce((acc, key) => acc?.[key], obj);
|
|
1151
1151
|
}
|
|
1152
1152
|
function promiseAllObject(promisesObj) {
|
|
1153
1153
|
const keys = Object.keys(promisesObj);
|
|
@@ -1556,11 +1556,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
1556
1556
|
}
|
|
1557
1557
|
return false;
|
|
1558
1558
|
}
|
|
1559
|
-
function prefixIssues(
|
|
1559
|
+
function prefixIssues(path36, issues) {
|
|
1560
1560
|
return issues.map((iss) => {
|
|
1561
1561
|
var _a3;
|
|
1562
1562
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
1563
|
-
iss.path.unshift(
|
|
1563
|
+
iss.path.unshift(path36);
|
|
1564
1564
|
return iss;
|
|
1565
1565
|
});
|
|
1566
1566
|
}
|
|
@@ -1707,16 +1707,16 @@ function flattenError(error51, mapper = (issue3) => issue3.message) {
|
|
|
1707
1707
|
}
|
|
1708
1708
|
function formatError(error51, mapper = (issue3) => issue3.message) {
|
|
1709
1709
|
const fieldErrors = { _errors: [] };
|
|
1710
|
-
const processError = (error52,
|
|
1710
|
+
const processError = (error52, path36 = []) => {
|
|
1711
1711
|
for (const issue3 of error52.issues) {
|
|
1712
1712
|
if (issue3.code === "invalid_union" && issue3.errors.length) {
|
|
1713
|
-
issue3.errors.map((issues) => processError({ issues }, [...
|
|
1713
|
+
issue3.errors.map((issues) => processError({ issues }, [...path36, ...issue3.path]));
|
|
1714
1714
|
} else if (issue3.code === "invalid_key") {
|
|
1715
|
-
processError({ issues: issue3.issues }, [...
|
|
1715
|
+
processError({ issues: issue3.issues }, [...path36, ...issue3.path]);
|
|
1716
1716
|
} else if (issue3.code === "invalid_element") {
|
|
1717
|
-
processError({ issues: issue3.issues }, [...
|
|
1717
|
+
processError({ issues: issue3.issues }, [...path36, ...issue3.path]);
|
|
1718
1718
|
} else {
|
|
1719
|
-
const fullpath = [...
|
|
1719
|
+
const fullpath = [...path36, ...issue3.path];
|
|
1720
1720
|
if (fullpath.length === 0) {
|
|
1721
1721
|
fieldErrors._errors.push(mapper(issue3));
|
|
1722
1722
|
} else {
|
|
@@ -1743,17 +1743,17 @@ function formatError(error51, mapper = (issue3) => issue3.message) {
|
|
|
1743
1743
|
}
|
|
1744
1744
|
function treeifyError(error51, mapper = (issue3) => issue3.message) {
|
|
1745
1745
|
const result = { errors: [] };
|
|
1746
|
-
const processError = (error52,
|
|
1746
|
+
const processError = (error52, path36 = []) => {
|
|
1747
1747
|
var _a3, _b;
|
|
1748
1748
|
for (const issue3 of error52.issues) {
|
|
1749
1749
|
if (issue3.code === "invalid_union" && issue3.errors.length) {
|
|
1750
|
-
issue3.errors.map((issues) => processError({ issues }, [...
|
|
1750
|
+
issue3.errors.map((issues) => processError({ issues }, [...path36, ...issue3.path]));
|
|
1751
1751
|
} else if (issue3.code === "invalid_key") {
|
|
1752
|
-
processError({ issues: issue3.issues }, [...
|
|
1752
|
+
processError({ issues: issue3.issues }, [...path36, ...issue3.path]);
|
|
1753
1753
|
} else if (issue3.code === "invalid_element") {
|
|
1754
|
-
processError({ issues: issue3.issues }, [...
|
|
1754
|
+
processError({ issues: issue3.issues }, [...path36, ...issue3.path]);
|
|
1755
1755
|
} else {
|
|
1756
|
-
const fullpath = [...
|
|
1756
|
+
const fullpath = [...path36, ...issue3.path];
|
|
1757
1757
|
if (fullpath.length === 0) {
|
|
1758
1758
|
result.errors.push(mapper(issue3));
|
|
1759
1759
|
continue;
|
|
@@ -1785,8 +1785,8 @@ function treeifyError(error51, mapper = (issue3) => issue3.message) {
|
|
|
1785
1785
|
}
|
|
1786
1786
|
function toDotPath(_path) {
|
|
1787
1787
|
const segs = [];
|
|
1788
|
-
const
|
|
1789
|
-
for (const seg of
|
|
1788
|
+
const path36 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
1789
|
+
for (const seg of path36) {
|
|
1790
1790
|
if (typeof seg === "number")
|
|
1791
1791
|
segs.push(`[${seg}]`);
|
|
1792
1792
|
else if (typeof seg === "symbol")
|
|
@@ -14450,13 +14450,13 @@ function resolveRef(ref, ctx) {
|
|
|
14450
14450
|
if (!ref.startsWith("#")) {
|
|
14451
14451
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
14452
14452
|
}
|
|
14453
|
-
const
|
|
14454
|
-
if (
|
|
14453
|
+
const path36 = ref.slice(1).split("/").filter(Boolean);
|
|
14454
|
+
if (path36.length === 0) {
|
|
14455
14455
|
return ctx.rootSchema;
|
|
14456
14456
|
}
|
|
14457
14457
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
14458
|
-
if (
|
|
14459
|
-
const key =
|
|
14458
|
+
if (path36[0] === defsKey) {
|
|
14459
|
+
const key = path36[1];
|
|
14460
14460
|
if (!key || !ctx.defs[key]) {
|
|
14461
14461
|
throw new Error(`Reference not found: ${ref}`);
|
|
14462
14462
|
}
|
|
@@ -17641,7 +17641,7 @@ var AcpConnection = class extends BaseConnection {
|
|
|
17641
17641
|
}
|
|
17642
17642
|
/** Claude 계열 브릿지인지 여부를 단일 판별 지점으로 유지합니다. */
|
|
17643
17643
|
isClaudeBackend() {
|
|
17644
|
-
return this.cliType === "claude" || this.cliType === "claude-zai" || this.cliType === "claude-kimi";
|
|
17644
|
+
return this.cliType === "claude" || this.cliType === "claude-zai" || this.cliType === "claude-kimi" || this.cliType === "claude-glm";
|
|
17645
17645
|
}
|
|
17646
17646
|
/** Claude bridge만 native system prompt append를 지원하므로 이 경로만 사용합니다. */
|
|
17647
17647
|
getClaudeSystemPrompt(systemPrompt) {
|
|
@@ -18140,6 +18140,20 @@ var models_default = {
|
|
|
18140
18140
|
opus: "kimi-k2.7-code"
|
|
18141
18141
|
}
|
|
18142
18142
|
},
|
|
18143
|
+
"claude-glm": {
|
|
18144
|
+
name: "Claude Code with ZhipuAI GLM",
|
|
18145
|
+
defaultModel: "opus",
|
|
18146
|
+
models: [
|
|
18147
|
+
{ modelId: "haiku", name: "GLM-4.5-Air (Haiku slot)", effort: { supported: false } },
|
|
18148
|
+
{ modelId: "sonnet", name: "GLM-4.7 (Sonnet slot)", effort: { supported: false } },
|
|
18149
|
+
{ modelId: "opus", name: "GLM-5.1 (Opus slot)", effort: { supported: false } }
|
|
18150
|
+
],
|
|
18151
|
+
modelsMapping: {
|
|
18152
|
+
haiku: "glm-4.5-air",
|
|
18153
|
+
sonnet: "glm-4.7",
|
|
18154
|
+
opus: "glm-5.1"
|
|
18155
|
+
}
|
|
18156
|
+
},
|
|
18143
18157
|
codex: {
|
|
18144
18158
|
name: "OpenAI Codex CLI",
|
|
18145
18159
|
defaultModel: "gpt-5.4",
|
|
@@ -18386,6 +18400,32 @@ var CLI_BACKENDS = {
|
|
|
18386
18400
|
API_TIMEOUT_MS: "3000000"
|
|
18387
18401
|
}
|
|
18388
18402
|
},
|
|
18403
|
+
"claude-glm": {
|
|
18404
|
+
id: "claude-glm",
|
|
18405
|
+
cliCommand: "claude",
|
|
18406
|
+
protocol: "acp",
|
|
18407
|
+
authRequired: true,
|
|
18408
|
+
npxPackage: "@agentclientprotocol/claude-agent-acp@0.33.1",
|
|
18409
|
+
modes: [
|
|
18410
|
+
{ id: "default", label: "Default" },
|
|
18411
|
+
{ id: "plan", label: "Plan" },
|
|
18412
|
+
{ id: "bypassPermissions", label: "YOLO" }
|
|
18413
|
+
],
|
|
18414
|
+
supportsSessionClose: true,
|
|
18415
|
+
supportsSessionLoad: true,
|
|
18416
|
+
requiresModelAtSpawn: false,
|
|
18417
|
+
usesNpxBridge: true,
|
|
18418
|
+
defaultMaxTokens: 16384,
|
|
18419
|
+
defaultEnv: {
|
|
18420
|
+
ANTHROPIC_BASE_URL: "https://open.bigmodel.cn/api/anthropic",
|
|
18421
|
+
// ZhipuAI Claude Code 권장 슬롯 매핑 — 직접 launch(Native PTY) 경로에서도
|
|
18422
|
+
// haiku/sonnet/opus 별칭이 GLM 모델로 해석되도록 env로 고정한다.
|
|
18423
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: "glm-4.5-air",
|
|
18424
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: "glm-4.7",
|
|
18425
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: "glm-5.1",
|
|
18426
|
+
API_TIMEOUT_MS: "3000000"
|
|
18427
|
+
}
|
|
18428
|
+
},
|
|
18389
18429
|
codex: {
|
|
18390
18430
|
id: "codex",
|
|
18391
18431
|
cliCommand: "codex",
|
|
@@ -18482,6 +18522,7 @@ function getYoloModeId(cli) {
|
|
|
18482
18522
|
case "claude":
|
|
18483
18523
|
case "claude-zai":
|
|
18484
18524
|
case "claude-kimi":
|
|
18525
|
+
case "claude-glm":
|
|
18485
18526
|
return "bypassPermissions";
|
|
18486
18527
|
case "opencode-go":
|
|
18487
18528
|
return "build";
|
|
@@ -19717,12 +19758,12 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
19717
19758
|
});
|
|
19718
19759
|
}
|
|
19719
19760
|
findRolloutPathForThreadId(threadId) {
|
|
19720
|
-
const codexHome = this.codexHome ?? this.env.CODEX_HOME ??
|
|
19761
|
+
const codexHome = this.codexHome ?? this.env.CODEX_HOME ?? path92.join(this.env.HOME ?? "", ".codex");
|
|
19721
19762
|
if (!codexHome) {
|
|
19722
19763
|
return null;
|
|
19723
19764
|
}
|
|
19724
19765
|
for (const rootName of ["sessions", "archived_sessions"]) {
|
|
19725
|
-
const found = findRolloutPath(
|
|
19766
|
+
const found = findRolloutPath(path92.join(codexHome, rootName), threadId);
|
|
19726
19767
|
if (found) {
|
|
19727
19768
|
return found;
|
|
19728
19769
|
}
|
|
@@ -19826,7 +19867,7 @@ function findRolloutPath(root, threadId) {
|
|
|
19826
19867
|
return null;
|
|
19827
19868
|
}
|
|
19828
19869
|
for (const entry of fs7.readdirSync(root, { withFileTypes: true })) {
|
|
19829
|
-
const entryPath =
|
|
19870
|
+
const entryPath = path92.join(root, entry.name);
|
|
19830
19871
|
if (entry.isDirectory()) {
|
|
19831
19872
|
const found = findRolloutPath(entryPath, threadId);
|
|
19832
19873
|
if (found) {
|
|
@@ -21220,6 +21261,7 @@ var UnifiedAgent = {
|
|
|
21220
21261
|
case "claude":
|
|
21221
21262
|
case "claude-zai":
|
|
21222
21263
|
case "claude-kimi":
|
|
21264
|
+
case "claude-glm":
|
|
21223
21265
|
return new UnifiedClaudeAgentClient(cli);
|
|
21224
21266
|
case "codex":
|
|
21225
21267
|
return new UnifiedCodexAgentClient();
|
|
@@ -21238,7 +21280,7 @@ var UnifiedAgent = {
|
|
|
21238
21280
|
}
|
|
21239
21281
|
const preferred = await new CliDetector().getPreferred();
|
|
21240
21282
|
if (!preferred) {
|
|
21241
|
-
throw new Error("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C CLI\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. claude, claude-zai, claude-kimi, codex, opencode-go, cursor \uC911 \uD558\uB098\uB97C \uC124\uCE58\uD574\uC8FC\uC138\uC694.");
|
|
21283
|
+
throw new Error("\uC0AC\uC6A9 \uAC00\uB2A5\uD55C CLI\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. claude, claude-zai, claude-kimi, claude-glm, codex, opencode-go, cursor \uC911 \uD558\uB098\uB97C \uC124\uCE58\uD574\uC8FC\uC138\uC694.");
|
|
21242
21284
|
}
|
|
21243
21285
|
return this.createClient(preferred.cli);
|
|
21244
21286
|
},
|
|
@@ -21251,6 +21293,8 @@ var UnifiedAgent = {
|
|
|
21251
21293
|
return client;
|
|
21252
21294
|
}
|
|
21253
21295
|
};
|
|
21296
|
+
|
|
21297
|
+
// ../../packages/fleet-infra/dist/chunk-35EEE5KI.js
|
|
21254
21298
|
function readAuthStoreFile(filePath) {
|
|
21255
21299
|
let fd;
|
|
21256
21300
|
try {
|
|
@@ -21270,7 +21314,7 @@ function readAuthStoreFile(filePath) {
|
|
|
21270
21314
|
}
|
|
21271
21315
|
}
|
|
21272
21316
|
}
|
|
21273
|
-
var DEFAULT_AUTH_PATH =
|
|
21317
|
+
var DEFAULT_AUTH_PATH = path92.join(getFleetDataDir(), "auth.json");
|
|
21274
21318
|
var AUTH_LOCK_OWNER_FILE_NAME = "owner.json";
|
|
21275
21319
|
var AUTH_LOCK_TIMEOUT_MS = 5e3;
|
|
21276
21320
|
function createAuthService(deps = {}) {
|
|
@@ -21326,7 +21370,7 @@ function createAuthService(deps = {}) {
|
|
|
21326
21370
|
}
|
|
21327
21371
|
},
|
|
21328
21372
|
async setApiKey(providerId, key) {
|
|
21329
|
-
const dir =
|
|
21373
|
+
const dir = path92.dirname(authPath);
|
|
21330
21374
|
ensureSafeDirectory(dir);
|
|
21331
21375
|
withAuthLock(authPath, lockDir, () => {
|
|
21332
21376
|
const data = fs7.existsSync(authPath) ? readAuthStoreFile(authPath) : {};
|
|
@@ -21379,72 +21423,6 @@ function formatAuthValidationFailureMessage(input) {
|
|
|
21379
21423
|
}
|
|
21380
21424
|
return `Auth token validation failed (providerId: '${input.providerId}'). Check the token and try again.${detail}`;
|
|
21381
21425
|
}
|
|
21382
|
-
var LEGACY_AUTH_PATH = path93.join(getFleetDataDir(), "agent", "auth.json");
|
|
21383
|
-
var CURRENT_AUTH_PATH = path93.join(getFleetDataDir(), "auth.json");
|
|
21384
|
-
function mergeAuthStoresNoOverwrite(legacy, current) {
|
|
21385
|
-
const data = { ...current };
|
|
21386
|
-
const migratedProviderIds = [];
|
|
21387
|
-
const skippedProviderIds = [];
|
|
21388
|
-
for (const [providerId, entry] of Object.entries(legacy)) {
|
|
21389
|
-
if (Object.prototype.hasOwnProperty.call(data, providerId)) {
|
|
21390
|
-
skippedProviderIds.push(providerId);
|
|
21391
|
-
continue;
|
|
21392
|
-
}
|
|
21393
|
-
data[providerId] = entry;
|
|
21394
|
-
migratedProviderIds.push(providerId);
|
|
21395
|
-
}
|
|
21396
|
-
return {
|
|
21397
|
-
data,
|
|
21398
|
-
migratedProviderIds,
|
|
21399
|
-
skippedProviderIds
|
|
21400
|
-
};
|
|
21401
|
-
}
|
|
21402
|
-
async function migrateLegacyAuthStore(options = {}) {
|
|
21403
|
-
const legacyPath = options.legacyPath ?? LEGACY_AUTH_PATH;
|
|
21404
|
-
const currentPath = options.currentPath ?? CURRENT_AUTH_PATH;
|
|
21405
|
-
if (!fs7.existsSync(legacyPath)) {
|
|
21406
|
-
return createMigrationResult({
|
|
21407
|
-
legacyPath,
|
|
21408
|
-
currentPath,
|
|
21409
|
-
status: "legacy-missing",
|
|
21410
|
-
migratedProviderIds: [],
|
|
21411
|
-
skippedProviderIds: [],
|
|
21412
|
-
shouldPrintNotice: false
|
|
21413
|
-
});
|
|
21414
|
-
}
|
|
21415
|
-
const legacy = readAuthStoreFile(legacyPath);
|
|
21416
|
-
const current = fs7.existsSync(currentPath) ? readAuthStoreFile(currentPath) : {};
|
|
21417
|
-
const merged = mergeAuthStoresNoOverwrite(legacy, current);
|
|
21418
|
-
if (merged.migratedProviderIds.length > 0) {
|
|
21419
|
-
const dir = path93.dirname(currentPath);
|
|
21420
|
-
ensureSafeDirectory(dir);
|
|
21421
|
-
writeAtomicSync(currentPath, `${JSON.stringify(merged.data, null, 2)}
|
|
21422
|
-
`, {
|
|
21423
|
-
mode: SECURE_FILE_MODE,
|
|
21424
|
-
fsync: true
|
|
21425
|
-
});
|
|
21426
|
-
}
|
|
21427
|
-
return createMigrationResult({
|
|
21428
|
-
legacyPath,
|
|
21429
|
-
currentPath,
|
|
21430
|
-
status: merged.migratedProviderIds.length > 0 ? "migrated" : "unchanged",
|
|
21431
|
-
migratedProviderIds: merged.migratedProviderIds,
|
|
21432
|
-
skippedProviderIds: merged.skippedProviderIds,
|
|
21433
|
-
shouldPrintNotice: options.notify !== false && merged.migratedProviderIds.length > 0
|
|
21434
|
-
});
|
|
21435
|
-
}
|
|
21436
|
-
function createMigrationResult(input) {
|
|
21437
|
-
return {
|
|
21438
|
-
legacyPath: input.legacyPath,
|
|
21439
|
-
currentPath: input.currentPath,
|
|
21440
|
-
migratedCount: input.migratedProviderIds.length,
|
|
21441
|
-
skippedCount: input.skippedProviderIds.length,
|
|
21442
|
-
migratedProviderIds: input.migratedProviderIds,
|
|
21443
|
-
skippedProviderIds: input.skippedProviderIds,
|
|
21444
|
-
shouldPrintNotice: input.shouldPrintNotice,
|
|
21445
|
-
status: input.status
|
|
21446
|
-
};
|
|
21447
|
-
}
|
|
21448
21426
|
var DEFAULT_AUTH_VALIDATION_TIMEOUT_MS = 5e3;
|
|
21449
21427
|
async function validateAnthropicCompatibleApiKey(request) {
|
|
21450
21428
|
const controller = new AbortController();
|
|
@@ -21517,8 +21495,14 @@ function buildMessagesUrl(baseUrl) {
|
|
|
21517
21495
|
function isAbortError(error51) {
|
|
21518
21496
|
return error51 instanceof DOMException && error51.name === "AbortError";
|
|
21519
21497
|
}
|
|
21498
|
+
var CLI_TO_AUTH_PROVIDER_ID = {
|
|
21499
|
+
"claude-zai": "Claude Code with Z.AI GLM",
|
|
21500
|
+
"claude-kimi": "Claude Code with Moonshot Kimi",
|
|
21501
|
+
"claude-glm": "Claude Code with ZhipuAI GLM"
|
|
21502
|
+
};
|
|
21520
21503
|
var CLAUDE_ZAI_PROVIDER_ID = "Claude Code with Z.AI GLM";
|
|
21521
21504
|
var CLAUDE_KIMI_PROVIDER_ID = "Claude Code with Moonshot Kimi";
|
|
21505
|
+
var CLAUDE_GLM_PROVIDER_ID = "Claude Code with ZhipuAI GLM";
|
|
21522
21506
|
var AUTH_PROVIDER_DEFINITIONS = {
|
|
21523
21507
|
"claude-zai": {
|
|
21524
21508
|
providerId: CLAUDE_ZAI_PROVIDER_ID,
|
|
@@ -21529,12 +21513,16 @@ var AUTH_PROVIDER_DEFINITIONS = {
|
|
|
21529
21513
|
providerId: CLAUDE_KIMI_PROVIDER_ID,
|
|
21530
21514
|
baseUrl: CLI_BACKENDS["claude-kimi"].defaultEnv.ANTHROPIC_BASE_URL,
|
|
21531
21515
|
env: CLI_BACKENDS["claude-kimi"].defaultEnv
|
|
21516
|
+
},
|
|
21517
|
+
"claude-glm": {
|
|
21518
|
+
providerId: CLAUDE_GLM_PROVIDER_ID,
|
|
21519
|
+
baseUrl: CLI_BACKENDS["claude-glm"].defaultEnv.ANTHROPIC_BASE_URL,
|
|
21520
|
+
env: CLI_BACKENDS["claude-glm"].defaultEnv
|
|
21532
21521
|
}
|
|
21533
21522
|
};
|
|
21534
21523
|
async function resolveAuthEnv(cli, deps) {
|
|
21535
21524
|
const provider = AUTH_PROVIDER_DEFINITIONS[cli];
|
|
21536
21525
|
if (!provider) return {};
|
|
21537
|
-
await migrateLegacyAuthStore();
|
|
21538
21526
|
const auth = deps?.authService ?? createAuthService({ authPath: DEFAULT_AUTH_PATH });
|
|
21539
21527
|
const token = await auth.getApiKey(provider.providerId);
|
|
21540
21528
|
if (!token) {
|
|
@@ -21555,13 +21543,32 @@ async function resolveAuthEnv(cli, deps) {
|
|
|
21555
21543
|
}
|
|
21556
21544
|
return { ...provider.env, ANTHROPIC_AUTH_TOKEN: token };
|
|
21557
21545
|
}
|
|
21546
|
+
async function validateAuthKeyForCli(cli, apiKey) {
|
|
21547
|
+
const provider = AUTH_PROVIDER_DEFINITIONS[cli];
|
|
21548
|
+
if (!provider) {
|
|
21549
|
+
return { providerId: cli, status: "success" };
|
|
21550
|
+
}
|
|
21551
|
+
const validation = await validateAnthropicCompatibleApiKey({
|
|
21552
|
+
providerId: provider.providerId,
|
|
21553
|
+
apiKey,
|
|
21554
|
+
baseUrl: provider.baseUrl
|
|
21555
|
+
});
|
|
21556
|
+
if (isAuthValidationSuccess(validation)) {
|
|
21557
|
+
return { providerId: validation.providerId, status: "success" };
|
|
21558
|
+
}
|
|
21559
|
+
return {
|
|
21560
|
+
providerId: validation.providerId,
|
|
21561
|
+
status: validation.status,
|
|
21562
|
+
detail: validation.detail
|
|
21563
|
+
};
|
|
21564
|
+
}
|
|
21558
21565
|
var DEFAULT_TEMP_FILE_MIN_AGE_MS = 6e4;
|
|
21559
21566
|
function createDurableJsonStore(deps) {
|
|
21560
21567
|
const now = deps.now ?? (() => Date.now());
|
|
21561
21568
|
const sensitivity = deps.sensitivity;
|
|
21562
21569
|
const mode = sensitivity === "sensitive" ? SECURE_FILE_MODE : 420;
|
|
21563
21570
|
const minAgeMs = deps.tempCleanupMinAgeMs ?? DEFAULT_TEMP_FILE_MIN_AGE_MS;
|
|
21564
|
-
const dir =
|
|
21571
|
+
const dir = path92.dirname(deps.filePath);
|
|
21565
21572
|
return {
|
|
21566
21573
|
path: deps.filePath,
|
|
21567
21574
|
load() {
|
|
@@ -21645,8 +21652,8 @@ var LOCK_OWNER_FILE_NAME = "owner";
|
|
|
21645
21652
|
var TEMP_FILE_PREFIX = `.tmp-${GLOBAL_OPTIONS_FILE_NAME}-`;
|
|
21646
21653
|
function createGlobalOptionsStore(deps = {}) {
|
|
21647
21654
|
const dataDir = deps.dataDir ?? getFleetDataDir();
|
|
21648
|
-
const optionsPath =
|
|
21649
|
-
const lockDir =
|
|
21655
|
+
const optionsPath = path92.join(dataDir, GLOBAL_OPTIONS_FILE_NAME);
|
|
21656
|
+
const lockDir = path92.join(dataDir, LOCK_DIR_NAME);
|
|
21650
21657
|
const store2 = createDurableJsonStore({
|
|
21651
21658
|
filePath: optionsPath,
|
|
21652
21659
|
lockDir,
|
|
@@ -21717,7 +21724,7 @@ function readFleetConsoleRelease() {
|
|
|
21717
21724
|
const requireFromHere = createRequire(import.meta.url);
|
|
21718
21725
|
const packageJsonPath = requireFromHere.resolve("../package.json");
|
|
21719
21726
|
const pkg = requireFromHere(packageJsonPath);
|
|
21720
|
-
const packageRoot =
|
|
21727
|
+
const packageRoot = path92__default.dirname(packageJsonPath);
|
|
21721
21728
|
const version2 = pkg.version ?? "";
|
|
21722
21729
|
if (pkg.private === true) {
|
|
21723
21730
|
return { channel: "local", version: version2, packageRoot };
|
|
@@ -21735,14 +21742,14 @@ var CONSOLE_CAPTURES_DIR_NAME = "captures";
|
|
|
21735
21742
|
function createConsolePaths(deps = {}) {
|
|
21736
21743
|
const env = deps.env ?? process.env;
|
|
21737
21744
|
const base = env.FLEET_CONSOLE_DIR ?? defaultConsoleBaseDir(deps);
|
|
21738
|
-
return { dir: base, lockFile:
|
|
21745
|
+
return { dir: base, lockFile: path92__default.join(base, LOCK_FILE_NAME) };
|
|
21739
21746
|
}
|
|
21740
21747
|
function createConsoleDataPaths(deps = {}) {
|
|
21741
|
-
const dir =
|
|
21748
|
+
const dir = defaultConsoleDataBaseDir(deps);
|
|
21742
21749
|
return {
|
|
21743
21750
|
dir,
|
|
21744
|
-
stateFile:
|
|
21745
|
-
capturesDir:
|
|
21751
|
+
stateFile: path92__default.join(dir, CONSOLE_STATE_FILE_NAME),
|
|
21752
|
+
capturesDir: path92__default.join(dir, CONSOLE_CAPTURES_DIR_NAME)
|
|
21746
21753
|
};
|
|
21747
21754
|
}
|
|
21748
21755
|
function defaultConsoleBaseDir(deps) {
|
|
@@ -21750,26 +21757,93 @@ function defaultConsoleBaseDir(deps) {
|
|
|
21750
21757
|
const channel = deps.channel ?? (release = readFleetConsoleRelease()).channel;
|
|
21751
21758
|
if (channel === "local") {
|
|
21752
21759
|
const packageRoot = deps.packageRoot ?? (release ??= readFleetConsoleRelease()).packageRoot;
|
|
21753
|
-
return
|
|
21760
|
+
return localConsoleDir(packageRoot);
|
|
21754
21761
|
}
|
|
21755
21762
|
const uid = deps.uid ?? (typeof process.getuid === "function" ? process.getuid() : 0);
|
|
21756
|
-
return
|
|
21763
|
+
return path92__default.join(os22__default.tmpdir(), `${LOCK_DIR_NAME2}-${uid}-${channel}`);
|
|
21764
|
+
}
|
|
21765
|
+
function defaultConsoleDataBaseDir(deps) {
|
|
21766
|
+
if (deps.fleetDataDir !== void 0) {
|
|
21767
|
+
return path92__default.join(deps.fleetDataDir, CONSOLE_DATA_DIR_NAME);
|
|
21768
|
+
}
|
|
21769
|
+
const env = deps.env ?? process.env;
|
|
21770
|
+
if (env.FLEET_CONSOLE_DIR) {
|
|
21771
|
+
return env.FLEET_CONSOLE_DIR;
|
|
21772
|
+
}
|
|
21773
|
+
let release;
|
|
21774
|
+
const channel = deps.channel ?? (release = readFleetConsoleRelease()).channel;
|
|
21775
|
+
if (channel === "local") {
|
|
21776
|
+
const packageRoot = deps.packageRoot ?? (release ??= readFleetConsoleRelease()).packageRoot;
|
|
21777
|
+
return localConsoleDir(packageRoot);
|
|
21778
|
+
}
|
|
21779
|
+
return path92__default.join(getFleetDataDir(), CONSOLE_DATA_DIR_NAME);
|
|
21780
|
+
}
|
|
21781
|
+
function localConsoleDir(packageRoot) {
|
|
21782
|
+
return path92__default.join(path92__default.resolve(packageRoot, "..", ".."), ".fleet", CONSOLE_RUNTIME_DIR_NAME);
|
|
21757
21783
|
}
|
|
21758
21784
|
|
|
21759
21785
|
// src/attention-hook.ts
|
|
21760
21786
|
var ATTENTION_POST_TIMEOUT_MS = 1500;
|
|
21761
|
-
|
|
21787
|
+
var ATTENTION_STDIN_TIMEOUT_MS = 500;
|
|
21788
|
+
var ATTENTION_REASONS = /* @__PURE__ */ new Set([
|
|
21789
|
+
"idle_prompt",
|
|
21790
|
+
"permission_prompt",
|
|
21791
|
+
"auth_success",
|
|
21792
|
+
"elicitation_dialog",
|
|
21793
|
+
"elicitation_complete",
|
|
21794
|
+
"elicitation_response"
|
|
21795
|
+
]);
|
|
21796
|
+
async function runAttentionHook(env = process9.env, options = {}) {
|
|
21762
21797
|
try {
|
|
21763
21798
|
await postAttention(env, options);
|
|
21764
21799
|
} catch {
|
|
21765
21800
|
}
|
|
21766
21801
|
}
|
|
21802
|
+
function normalizeAttentionReason(value) {
|
|
21803
|
+
return typeof value === "string" && ATTENTION_REASONS.has(value) ? value : void 0;
|
|
21804
|
+
}
|
|
21805
|
+
async function readHookReason(options) {
|
|
21806
|
+
const stream = options.stdin ?? process9.stdin;
|
|
21807
|
+
const raw = await readHookStdin(stream, options.stdinTimeoutMs ?? ATTENTION_STDIN_TIMEOUT_MS);
|
|
21808
|
+
if (!raw) return void 0;
|
|
21809
|
+
try {
|
|
21810
|
+
const parsed = JSON.parse(raw);
|
|
21811
|
+
return normalizeAttentionReason(parsed?.notification_type);
|
|
21812
|
+
} catch {
|
|
21813
|
+
return void 0;
|
|
21814
|
+
}
|
|
21815
|
+
}
|
|
21816
|
+
async function readHookStdin(stream, timeoutMs) {
|
|
21817
|
+
return await new Promise((resolve) => {
|
|
21818
|
+
const chunks = [];
|
|
21819
|
+
let settled = false;
|
|
21820
|
+
const finish = (value) => {
|
|
21821
|
+
if (settled) return;
|
|
21822
|
+
settled = true;
|
|
21823
|
+
resolve(value);
|
|
21824
|
+
};
|
|
21825
|
+
const timer = setTimeout(() => finish(""), timeoutMs);
|
|
21826
|
+
if (typeof timer.unref === "function") timer.unref();
|
|
21827
|
+
stream.on("data", (chunk) => {
|
|
21828
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
21829
|
+
});
|
|
21830
|
+
stream.on("end", () => {
|
|
21831
|
+
clearTimeout(timer);
|
|
21832
|
+
finish(Buffer.concat(chunks).toString("utf8"));
|
|
21833
|
+
});
|
|
21834
|
+
stream.on("error", () => {
|
|
21835
|
+
clearTimeout(timer);
|
|
21836
|
+
finish("");
|
|
21837
|
+
});
|
|
21838
|
+
});
|
|
21839
|
+
}
|
|
21767
21840
|
async function postAttention(env, options) {
|
|
21768
21841
|
const sessionId = env.FLEET_CONSOLE_SESSION_ID;
|
|
21769
21842
|
if (!sessionId) return;
|
|
21770
21843
|
const paths = createConsolePaths({ env });
|
|
21771
21844
|
const lock = createConsoleLock().readLock(paths.lockFile);
|
|
21772
21845
|
if (!lock) return;
|
|
21846
|
+
const reason = await readHookReason(options);
|
|
21773
21847
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
21774
21848
|
const controller = new AbortController();
|
|
21775
21849
|
const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? ATTENTION_POST_TIMEOUT_MS);
|
|
@@ -21780,7 +21854,7 @@ async function postAttention(env, options) {
|
|
|
21780
21854
|
authorization: `Bearer ${lock.token}`,
|
|
21781
21855
|
"content-type": "application/json"
|
|
21782
21856
|
},
|
|
21783
|
-
body: JSON.stringify({}),
|
|
21857
|
+
body: JSON.stringify(reason ? { reason } : {}),
|
|
21784
21858
|
signal: controller.signal
|
|
21785
21859
|
});
|
|
21786
21860
|
} finally {
|
|
@@ -21790,17 +21864,20 @@ async function postAttention(env, options) {
|
|
|
21790
21864
|
function openBrowser(url2, deps = {}) {
|
|
21791
21865
|
const platform = deps.platform ?? os22__default.platform();
|
|
21792
21866
|
const spawnBrowser = deps.spawnBrowser ?? ((command2, args, options) => {
|
|
21793
|
-
spawn(command2, [...args], options)
|
|
21867
|
+
const child = spawn(command2, [...args], options);
|
|
21868
|
+
child.once("error", () => {
|
|
21869
|
+
});
|
|
21870
|
+
child.unref();
|
|
21794
21871
|
});
|
|
21795
21872
|
if (platform === "darwin") {
|
|
21796
|
-
spawnBrowser("open", [url2], { detached: true, stdio: "ignore" });
|
|
21873
|
+
spawnBrowser("open", [url2], { detached: true, stdio: "ignore", windowsHide: true });
|
|
21797
21874
|
return;
|
|
21798
21875
|
}
|
|
21799
21876
|
if (platform === "win32") {
|
|
21800
|
-
spawnBrowser("cmd", ["/c", "start", "", url2], { detached: true, stdio: "ignore" });
|
|
21877
|
+
spawnBrowser("cmd", ["/c", "start", "", url2], { detached: true, stdio: "ignore", windowsHide: true });
|
|
21801
21878
|
return;
|
|
21802
21879
|
}
|
|
21803
|
-
spawnBrowser("xdg-open", [url2], { detached: true, stdio: "ignore" });
|
|
21880
|
+
spawnBrowser("xdg-open", [url2], { detached: true, stdio: "ignore", windowsHide: true });
|
|
21804
21881
|
}
|
|
21805
21882
|
|
|
21806
21883
|
// src/health.ts
|
|
@@ -21980,7 +22057,7 @@ function specToMcpTool(spec) {
|
|
|
21980
22057
|
}
|
|
21981
22058
|
function installExecutorToolCallRouter(runtime, sessionToken, ctx) {
|
|
21982
22059
|
runtime.server.setOnToolCallArrived(sessionToken, (toolName, args) => {
|
|
21983
|
-
const toolCallId =
|
|
22060
|
+
const toolCallId = crypto3.randomUUID();
|
|
21984
22061
|
void runtime.registry.invoke(toolName, args, { cwd: ctx.cwd, sessionLabel: ctx.sessionLabel, toolCallId, signal: ctx.signal }).then((result) => runtime.server.resolveNextToolCall(sessionToken, toolCallId, result)).catch((err) => {
|
|
21985
22062
|
runtime.server.resolveNextToolCall(sessionToken, toolCallId, {
|
|
21986
22063
|
content: [{ type: "text", text: err instanceof Error ? err.message : String(err) }],
|
|
@@ -22371,7 +22448,7 @@ function createInProcessMcpServer(deps = {}) {
|
|
|
22371
22448
|
if (activeStopPromise) await activeStopPromise;
|
|
22372
22449
|
if (activeServer && activeServerUrl) return activeServerUrl;
|
|
22373
22450
|
if (activeStartPromise) return activeStartPromise;
|
|
22374
|
-
activeOpaquePath = `/${
|
|
22451
|
+
activeOpaquePath = `/${crypto3.randomUUID()}`;
|
|
22375
22452
|
activeStartPromise = new Promise((resolve, reject) => {
|
|
22376
22453
|
const srv = http.createServer(handleRequest);
|
|
22377
22454
|
srv.timeout = MCP_SERVER_TIMEOUT_MS;
|
|
@@ -22628,7 +22705,7 @@ function createExecutorMcpSession(deps, toolTimeoutSeconds, request) {
|
|
|
22628
22705
|
throw new Error("Executor session cwd is required");
|
|
22629
22706
|
}
|
|
22630
22707
|
assertNonEmptyExecutorTools(request.serverName, request.specs);
|
|
22631
|
-
const token =
|
|
22708
|
+
const token = crypto3.randomUUID();
|
|
22632
22709
|
registerExecutorSessionTools(runtime.runtime, token, [...request.specs]);
|
|
22633
22710
|
installExecutorToolCallRouter(runtime.runtime, token, {
|
|
22634
22711
|
cwd,
|
|
@@ -22674,7 +22751,7 @@ function issueSessionToken(deps, sessionTokensByLabel, request) {
|
|
|
22674
22751
|
for (const { name, runtime } of deps.runtimes) {
|
|
22675
22752
|
const tools = runtime.registry.getAllAgentTools();
|
|
22676
22753
|
assertNonEmptyExecutorTools(name, tools);
|
|
22677
|
-
const token =
|
|
22754
|
+
const token = crypto3.randomUUID();
|
|
22678
22755
|
registerExecutorSessionTools(runtime, token, tools);
|
|
22679
22756
|
installExecutorToolCallRouter(runtime, token, { cwd, sessionLabel: label, signal: request.signal });
|
|
22680
22757
|
tokens.push({ name, token });
|
|
@@ -22850,7 +22927,7 @@ function createChildEnv(env, overlay) {
|
|
|
22850
22927
|
return child;
|
|
22851
22928
|
}
|
|
22852
22929
|
function wrapWindowsShim(resolved, env, platform) {
|
|
22853
|
-
if (platform !== "win32" || !WINDOWS_SHIM_EXTENSIONS.has(
|
|
22930
|
+
if (platform !== "win32" || !WINDOWS_SHIM_EXTENSIONS.has(path92__default.extname(resolved).toLowerCase())) {
|
|
22854
22931
|
return { bin: resolved, prefixArgs: [] };
|
|
22855
22932
|
}
|
|
22856
22933
|
rejectCmdExpansionSensitiveShim(resolved);
|
|
@@ -22868,13 +22945,13 @@ function forceWindowsArgQuoting(value) {
|
|
|
22868
22945
|
return `${value} `;
|
|
22869
22946
|
}
|
|
22870
22947
|
function findOnPath(bin, pathValue, pathExts, platform) {
|
|
22871
|
-
const pathSeparator = platform === "win32" ? WINDOWS_PATH_SEPARATOR :
|
|
22872
|
-
if (hasPathSeparator(bin, platform) ||
|
|
22948
|
+
const pathSeparator = platform === "win32" ? WINDOWS_PATH_SEPARATOR : path92__default.delimiter;
|
|
22949
|
+
if (hasPathSeparator(bin, platform) || path92__default.isAbsolute(bin)) {
|
|
22873
22950
|
return resolveWithExtensions(bin, pathExts, platform);
|
|
22874
22951
|
}
|
|
22875
22952
|
for (const entry of pathValue.split(pathSeparator)) {
|
|
22876
22953
|
const searchDir = entry.length === 0 ? "." : entry;
|
|
22877
|
-
const candidate = resolveWithExtensions(
|
|
22954
|
+
const candidate = resolveWithExtensions(path92__default.join(searchDir, bin), pathExts, platform);
|
|
22878
22955
|
if (candidate) {
|
|
22879
22956
|
return candidate;
|
|
22880
22957
|
}
|
|
@@ -22882,7 +22959,7 @@ function findOnPath(bin, pathValue, pathExts, platform) {
|
|
|
22882
22959
|
return void 0;
|
|
22883
22960
|
}
|
|
22884
22961
|
function resolveWithExtensions(candidate, pathExts, platform) {
|
|
22885
|
-
if (platform !== "win32" ||
|
|
22962
|
+
if (platform !== "win32" || path92__default.extname(candidate).length > 0) {
|
|
22886
22963
|
return existsSync(candidate) ? candidate : void 0;
|
|
22887
22964
|
}
|
|
22888
22965
|
for (const ext of pathExts) {
|
|
@@ -23782,6 +23859,230 @@ function parseNumericPart(value) {
|
|
|
23782
23859
|
function compareNumbers(left, right) {
|
|
23783
23860
|
return left === right ? 0 : left > right ? 1 : -1;
|
|
23784
23861
|
}
|
|
23862
|
+
var DEFAULT_CHANNEL = "latest";
|
|
23863
|
+
var PACKAGE_MANAGER_COMMANDS = ["npm", "pnpm"];
|
|
23864
|
+
function createGlobalPackageUpdater(deps) {
|
|
23865
|
+
const resolvedDeps = resolveDeps(deps);
|
|
23866
|
+
return {
|
|
23867
|
+
detectPackageManager: () => detectPackageManager(resolvedDeps),
|
|
23868
|
+
update: (options = {}) => updatePackages(resolvedDeps, options),
|
|
23869
|
+
install: (manager, versionOrChannel) => installPackages(resolvedDeps, manager, versionOrChannel),
|
|
23870
|
+
createManualInstallMessage: (channel, reason) => createManualInstallMessage(resolvedDeps, channel, reason),
|
|
23871
|
+
formatInstallCommand: (command2, versionOrChannel) => formatInstallCommand(resolvedDeps.packageNames, command2, versionOrChannel)
|
|
23872
|
+
};
|
|
23873
|
+
}
|
|
23874
|
+
function resolveDeps(deps) {
|
|
23875
|
+
if (deps.packageNames.length === 0) {
|
|
23876
|
+
throw new Error("packageNames must contain at least one package");
|
|
23877
|
+
}
|
|
23878
|
+
return {
|
|
23879
|
+
packageNames: deps.packageNames,
|
|
23880
|
+
resolveCurrentPackageRoot: deps.resolveCurrentPackageRoot,
|
|
23881
|
+
resolveCurrentVersion: deps.resolveCurrentVersion,
|
|
23882
|
+
resolveLatestVersion: deps.resolveLatestVersion ?? fetchLatestVersion,
|
|
23883
|
+
isVersionGreater: deps.isVersionGreater ?? isVersionGreater,
|
|
23884
|
+
prepareInstall: deps.prepareInstall,
|
|
23885
|
+
finalizeSuccess: deps.finalizeSuccess,
|
|
23886
|
+
report: deps.report,
|
|
23887
|
+
env: deps.env ?? process.env,
|
|
23888
|
+
platform: deps.platform ?? process.platform,
|
|
23889
|
+
resolveBinary: deps.resolveBinary ?? resolvePathBinary,
|
|
23890
|
+
execFile: deps.execFile ?? defaultExecFile,
|
|
23891
|
+
spawnInstall: deps.spawnInstall ?? defaultSpawnInstall,
|
|
23892
|
+
realpath: deps.realpath ?? realpathSync,
|
|
23893
|
+
canWrite: deps.canWrite ?? defaultCanWrite
|
|
23894
|
+
};
|
|
23895
|
+
}
|
|
23896
|
+
async function updatePackages(deps, options) {
|
|
23897
|
+
const channel = options.channel ?? DEFAULT_CHANNEL;
|
|
23898
|
+
const detection = await detectPackageManager(deps);
|
|
23899
|
+
if (detection.manager === void 0) {
|
|
23900
|
+
return {
|
|
23901
|
+
status: "manual",
|
|
23902
|
+
code: 0,
|
|
23903
|
+
reason: detection.reason,
|
|
23904
|
+
manualMessage: createManualInstallMessage(deps, channel, detection.reason)
|
|
23905
|
+
};
|
|
23906
|
+
}
|
|
23907
|
+
const currentVersion = await deps.resolveCurrentVersion();
|
|
23908
|
+
const latestVersion = await deps.resolveLatestVersion(deps.packageNames[0], channel);
|
|
23909
|
+
if (currentVersion !== void 0 && latestVersion !== void 0 && !deps.isVersionGreater(latestVersion, currentVersion)) {
|
|
23910
|
+
deps.report?.(`Global package is already on the latest version (v${currentVersion}).`);
|
|
23911
|
+
return {
|
|
23912
|
+
status: "current",
|
|
23913
|
+
code: 0,
|
|
23914
|
+
manager: detection.manager,
|
|
23915
|
+
currentVersion,
|
|
23916
|
+
latestVersion
|
|
23917
|
+
};
|
|
23918
|
+
}
|
|
23919
|
+
const versionOrChannel = latestVersion ?? channel;
|
|
23920
|
+
if (latestVersion === void 0) {
|
|
23921
|
+
deps.report?.(`Could not resolve the latest package version; reinstalling ${channel}.`);
|
|
23922
|
+
} else {
|
|
23923
|
+
deps.report?.(`Installing global packages at ${versionOrChannel}.`);
|
|
23924
|
+
}
|
|
23925
|
+
const context = createInstallContext(deps, detection.manager, versionOrChannel);
|
|
23926
|
+
await deps.prepareInstall?.(context);
|
|
23927
|
+
const code = await installPackages(deps, detection.manager, versionOrChannel);
|
|
23928
|
+
if (code === 0) {
|
|
23929
|
+
await deps.finalizeSuccess?.(context);
|
|
23930
|
+
return {
|
|
23931
|
+
status: "installed",
|
|
23932
|
+
code,
|
|
23933
|
+
manager: detection.manager,
|
|
23934
|
+
currentVersion,
|
|
23935
|
+
latestVersion,
|
|
23936
|
+
versionOrChannel
|
|
23937
|
+
};
|
|
23938
|
+
}
|
|
23939
|
+
return {
|
|
23940
|
+
status: "failed",
|
|
23941
|
+
code,
|
|
23942
|
+
manager: detection.manager,
|
|
23943
|
+
currentVersion,
|
|
23944
|
+
latestVersion,
|
|
23945
|
+
versionOrChannel,
|
|
23946
|
+
manualMessage: createManualInstallMessage(deps, channel, void 0)
|
|
23947
|
+
};
|
|
23948
|
+
}
|
|
23949
|
+
async function detectPackageManager(deps) {
|
|
23950
|
+
const packageRoot = await deps.resolveCurrentPackageRoot();
|
|
23951
|
+
if (packageRoot === void 0) {
|
|
23952
|
+
return { manager: void 0, reason: "local" };
|
|
23953
|
+
}
|
|
23954
|
+
for (const command2 of PACKAGE_MANAGER_COMMANDS) {
|
|
23955
|
+
const detected = detectGlobalRoot(deps, command2, packageRoot);
|
|
23956
|
+
if (detected?.manager !== void 0 || detected?.reason === "permission") {
|
|
23957
|
+
return detected;
|
|
23958
|
+
}
|
|
23959
|
+
}
|
|
23960
|
+
return { manager: void 0, reason: "local" };
|
|
23961
|
+
}
|
|
23962
|
+
function detectGlobalRoot(deps, command2, packageRoot) {
|
|
23963
|
+
try {
|
|
23964
|
+
const resolved = deps.resolveBinary(command2, deps.env, { platform: deps.platform });
|
|
23965
|
+
if (resolved === void 0) {
|
|
23966
|
+
return void 0;
|
|
23967
|
+
}
|
|
23968
|
+
const globalRoot = deps.execFile(resolved.bin, [...resolved.prefixArgs, "root", "-g"]).trim();
|
|
23969
|
+
const resolvedRoot = normalizePath(deps, deps.realpath(resolvePathForPlatform(deps.platform, globalRoot)));
|
|
23970
|
+
const normalizedPackageRoot = normalizeExistingPath(deps, packageRoot);
|
|
23971
|
+
if (isPathInside(deps, normalizedPackageRoot, resolvedRoot)) {
|
|
23972
|
+
return createManagerDetection(deps, command2, resolvedRoot, resolved);
|
|
23973
|
+
}
|
|
23974
|
+
const expectedPackageDir = joinPathForPlatform(deps.platform, globalRoot, deps.packageNames[0]);
|
|
23975
|
+
try {
|
|
23976
|
+
const resolvedPackageDir = normalizePath(deps, deps.realpath(expectedPackageDir));
|
|
23977
|
+
if (resolvedPackageDir === normalizedPackageRoot) {
|
|
23978
|
+
return createManagerDetection(deps, command2, resolvedRoot, resolved);
|
|
23979
|
+
}
|
|
23980
|
+
} catch {
|
|
23981
|
+
}
|
|
23982
|
+
} catch (error51) {
|
|
23983
|
+
deps.report?.(`Failed to detect global ${command2} install: ${formatError2(error51)}`);
|
|
23984
|
+
return void 0;
|
|
23985
|
+
}
|
|
23986
|
+
return void 0;
|
|
23987
|
+
}
|
|
23988
|
+
function createManagerDetection(deps, command2, globalRoot, resolved) {
|
|
23989
|
+
if (!deps.canWrite(globalRoot)) {
|
|
23990
|
+
return { manager: void 0, reason: "permission" };
|
|
23991
|
+
}
|
|
23992
|
+
return {
|
|
23993
|
+
manager: {
|
|
23994
|
+
command: command2,
|
|
23995
|
+
globalRoot,
|
|
23996
|
+
resolved
|
|
23997
|
+
},
|
|
23998
|
+
reason: void 0
|
|
23999
|
+
};
|
|
24000
|
+
}
|
|
24001
|
+
function installPackages(deps, manager, versionOrChannel) {
|
|
24002
|
+
const context = createInstallContext(deps, manager, versionOrChannel);
|
|
24003
|
+
const commandArgs = [...manager.resolved.prefixArgs, "i", "-g", "--force", ...deps.packageNames.map((name) => `${name}@${versionOrChannel}`)];
|
|
24004
|
+
const child = deps.spawnInstall(manager.resolved.bin, commandArgs, { ...context, commandArgs });
|
|
24005
|
+
return new Promise((resolve) => {
|
|
24006
|
+
child.once("error", () => {
|
|
24007
|
+
resolve(1);
|
|
24008
|
+
});
|
|
24009
|
+
child.once("exit", (code, signal) => {
|
|
24010
|
+
if (typeof code === "number") {
|
|
24011
|
+
resolve(code);
|
|
24012
|
+
return;
|
|
24013
|
+
}
|
|
24014
|
+
resolve(signal === null ? 0 : 1);
|
|
24015
|
+
});
|
|
24016
|
+
});
|
|
24017
|
+
}
|
|
24018
|
+
function createInstallContext(deps, manager, versionOrChannel) {
|
|
24019
|
+
return {
|
|
24020
|
+
manager,
|
|
24021
|
+
versionOrChannel,
|
|
24022
|
+
packageNames: deps.packageNames
|
|
24023
|
+
};
|
|
24024
|
+
}
|
|
24025
|
+
function createManualInstallMessage(deps, channel, reason) {
|
|
24026
|
+
const reasonLine = reason === "permission" ? "Global package install location is not writable, so no installer was run." : "Global npm or pnpm installation could not be detected, so no installer was run.";
|
|
24027
|
+
const commands = PACKAGE_MANAGER_COMMANDS.map((command2) => formatInstallCommand(deps.packageNames, command2, channel));
|
|
24028
|
+
return [reasonLine, "Run one of these commands manually:", ...commands].join("\n");
|
|
24029
|
+
}
|
|
24030
|
+
function formatInstallCommand(packageNames, command2, versionOrChannel) {
|
|
24031
|
+
return `${command2} i -g ${packageNames.map((name) => `${name}@${versionOrChannel}`).join(" ")}`;
|
|
24032
|
+
}
|
|
24033
|
+
function isPathInside(deps, child, parent) {
|
|
24034
|
+
const separator = deps.platform === "win32" ? "\\" : path92__default.sep;
|
|
24035
|
+
return child === parent || child.startsWith(`${parent}${separator}`);
|
|
24036
|
+
}
|
|
24037
|
+
function normalizeExistingPath(deps, value) {
|
|
24038
|
+
try {
|
|
24039
|
+
return normalizePath(deps, deps.realpath(value));
|
|
24040
|
+
} catch {
|
|
24041
|
+
return normalizePath(deps, value);
|
|
24042
|
+
}
|
|
24043
|
+
}
|
|
24044
|
+
function normalizePath(deps, value) {
|
|
24045
|
+
const resolved = resolvePathForPlatform(deps.platform, value);
|
|
24046
|
+
return deps.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
24047
|
+
}
|
|
24048
|
+
function resolvePathForPlatform(platform, value) {
|
|
24049
|
+
return platform === "win32" ? path92__default.win32.resolve(value) : path92__default.resolve(value);
|
|
24050
|
+
}
|
|
24051
|
+
function joinPathForPlatform(platform, ...parts) {
|
|
24052
|
+
return platform === "win32" ? path92__default.win32.join(...parts) : path92__default.join(...parts);
|
|
24053
|
+
}
|
|
24054
|
+
function defaultExecFile(file2, args) {
|
|
24055
|
+
return execFileSync(file2, args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
24056
|
+
}
|
|
24057
|
+
function defaultSpawnInstall(file2, args) {
|
|
24058
|
+
return spawn(file2, args, { stdio: "inherit" });
|
|
24059
|
+
}
|
|
24060
|
+
function defaultCanWrite(targetPath) {
|
|
24061
|
+
try {
|
|
24062
|
+
accessSync(targetPath, constants.W_OK);
|
|
24063
|
+
return true;
|
|
24064
|
+
} catch {
|
|
24065
|
+
return false;
|
|
24066
|
+
}
|
|
24067
|
+
}
|
|
24068
|
+
function formatError2(error51) {
|
|
24069
|
+
if (typeof error51 === "object" && error51 !== null) {
|
|
24070
|
+
const stderr = "stderr" in error51 ? error51.stderr : void 0;
|
|
24071
|
+
if (Buffer.isBuffer(stderr)) {
|
|
24072
|
+
const text = stderr.toString("utf8").trim();
|
|
24073
|
+
if (text.length > 0) {
|
|
24074
|
+
return text;
|
|
24075
|
+
}
|
|
24076
|
+
}
|
|
24077
|
+
if (typeof stderr === "string" && stderr.trim().length > 0) {
|
|
24078
|
+
return stderr.trim();
|
|
24079
|
+
}
|
|
24080
|
+
}
|
|
24081
|
+
if (error51 instanceof Error) {
|
|
24082
|
+
return error51.message;
|
|
24083
|
+
}
|
|
24084
|
+
return String(error51);
|
|
24085
|
+
}
|
|
23785
24086
|
|
|
23786
24087
|
// ../../node_modules/.pnpm/typebox@1.1.34/node_modules/typebox/build/system/memory/memory.mjs
|
|
23787
24088
|
var memory_exports = {};
|
|
@@ -28247,7 +28548,7 @@ function readRawCarriersOrDefaultStore() {
|
|
|
28247
28548
|
}
|
|
28248
28549
|
function getCarriersFilePath() {
|
|
28249
28550
|
if (!runtimeState.storeDir) return null;
|
|
28250
|
-
return
|
|
28551
|
+
return path92.join(runtimeState.storeDir, FILENAME);
|
|
28251
28552
|
}
|
|
28252
28553
|
function updateCarriers(mutator) {
|
|
28253
28554
|
if (!runtimeState.storeDir) return;
|
|
@@ -28262,7 +28563,7 @@ function updateCarriers(mutator) {
|
|
|
28262
28563
|
function withStoreLock(operation) {
|
|
28263
28564
|
if (!runtimeState.storeDir) return operation();
|
|
28264
28565
|
fs7.mkdirSync(runtimeState.storeDir, { recursive: true });
|
|
28265
|
-
const lockDir =
|
|
28566
|
+
const lockDir = path92.join(runtimeState.storeDir, LOCK_DIRNAME);
|
|
28266
28567
|
return withDirectoryLock(
|
|
28267
28568
|
{ lockDir, ownerFileName: LOCK_OWNER_FILENAME },
|
|
28268
28569
|
operation
|
|
@@ -28273,10 +28574,10 @@ function readCarriers() {
|
|
|
28273
28574
|
return readCarriersFromDir(runtimeState.storeDir);
|
|
28274
28575
|
}
|
|
28275
28576
|
function resolveDefaultStoreDir() {
|
|
28276
|
-
return
|
|
28577
|
+
return path92.join(os22.homedir(), DEFAULT_STORE_DIRNAME);
|
|
28277
28578
|
}
|
|
28278
28579
|
function readCarriersFromDir(dir) {
|
|
28279
|
-
const filePath =
|
|
28580
|
+
const filePath = path92.join(dir, FILENAME);
|
|
28280
28581
|
let fd;
|
|
28281
28582
|
try {
|
|
28282
28583
|
const stat5 = fs7.lstatSync(filePath);
|
|
@@ -28306,7 +28607,7 @@ function recordLastLocalWriteFingerprint(filePath, generation) {
|
|
|
28306
28607
|
function writeCarriers(s) {
|
|
28307
28608
|
if (!runtimeState.storeDir) throw new Error("Fleet store is not initialized.");
|
|
28308
28609
|
fs7.mkdirSync(runtimeState.storeDir, { recursive: true });
|
|
28309
|
-
const filePath =
|
|
28610
|
+
const filePath = path92.join(runtimeState.storeDir, FILENAME);
|
|
28310
28611
|
const next = serializeFleetCarriers(s);
|
|
28311
28612
|
writeAtomicSync(filePath, `${JSON.stringify(next, null, 2)}
|
|
28312
28613
|
`, { fsync: false, mode: 420 });
|
|
@@ -28331,7 +28632,7 @@ function sanitizeFleetCarriers(value) {
|
|
|
28331
28632
|
}
|
|
28332
28633
|
function unlinkStaleSubagentModeFile(dir) {
|
|
28333
28634
|
try {
|
|
28334
|
-
fs7.unlinkSync(
|
|
28635
|
+
fs7.unlinkSync(path92.join(dir, STALE_SUBAGENT_MODE_FILENAME));
|
|
28335
28636
|
} catch {
|
|
28336
28637
|
}
|
|
28337
28638
|
}
|
|
@@ -31906,8 +32207,8 @@ function createBoundCarrierJobs(registry3, boundStream = createBoundCarrierStrea
|
|
|
31906
32207
|
// src/hooks/subagents-context.ts
|
|
31907
32208
|
var FLEET_PLUGIN_NAME = "fleet";
|
|
31908
32209
|
function runSubagentsContextHook(env) {
|
|
31909
|
-
const fleetRoot = env.FLEET_ROOT ??
|
|
31910
|
-
if (!canReadCarrierState(
|
|
32210
|
+
const fleetRoot = env.FLEET_ROOT ?? path92__default.join(env.HOME ?? os22__default.homedir(), ".fleet");
|
|
32211
|
+
if (!canReadCarrierState(path92__default.join(fleetRoot, "carriers.json"))) {
|
|
31911
32212
|
return JSON.stringify({ hookSpecificOutput: { hookEventName: "SessionStart", additionalContext: "" } });
|
|
31912
32213
|
}
|
|
31913
32214
|
const carrierRuntime = createCarrierRuntime();
|
|
@@ -32385,6 +32686,11 @@ var claudeCli = createClaudeFamilyCliDefinition({
|
|
|
32385
32686
|
id: "claude",
|
|
32386
32687
|
label: "Claude"
|
|
32387
32688
|
});
|
|
32689
|
+
var claudeGlmCli = createClaudeFamilyCliDefinition({
|
|
32690
|
+
authCli: "claude-glm",
|
|
32691
|
+
id: "claude-glm",
|
|
32692
|
+
label: "Claude GLM"
|
|
32693
|
+
});
|
|
32388
32694
|
var claudeKimiCli = createClaudeFamilyCliDefinition({
|
|
32389
32695
|
authCli: "claude-kimi",
|
|
32390
32696
|
id: "claude-kimi",
|
|
@@ -32424,6 +32730,7 @@ var DEFAULT_CLI_ID = "claude";
|
|
|
32424
32730
|
var DEFINITIONS = {
|
|
32425
32731
|
claude: claudeCli,
|
|
32426
32732
|
"claude-kimi": claudeKimiCli,
|
|
32733
|
+
"claude-glm": claudeGlmCli,
|
|
32427
32734
|
codex: codexCli
|
|
32428
32735
|
};
|
|
32429
32736
|
async function resolveAgentCliProfile(env, cwd, options = {}) {
|
|
@@ -32470,6 +32777,10 @@ var AGENT_CLI_INJECTION_CAPABILITIES = {
|
|
|
32470
32777
|
builderId: "claude-native",
|
|
32471
32778
|
enabled: true
|
|
32472
32779
|
},
|
|
32780
|
+
"claude-glm": {
|
|
32781
|
+
builderId: "claude-native",
|
|
32782
|
+
enabled: true
|
|
32783
|
+
},
|
|
32473
32784
|
codex: {
|
|
32474
32785
|
builderId: "codex-native",
|
|
32475
32786
|
enabled: true
|
|
@@ -32488,7 +32799,7 @@ function createSessionCaptureHookExec(deps) {
|
|
|
32488
32799
|
deps.provider
|
|
32489
32800
|
] : [deps.entryPath, "hook", "capture-session", deps.provider];
|
|
32490
32801
|
return {
|
|
32491
|
-
command: deps.execPath ??
|
|
32802
|
+
command: deps.execPath ?? process9.execPath,
|
|
32492
32803
|
args
|
|
32493
32804
|
};
|
|
32494
32805
|
}
|
|
@@ -32661,16 +32972,10 @@ function writePrivateJson(filePath, value, rootBase) {
|
|
|
32661
32972
|
function writePrivateFile(filePath, content, rootBase) {
|
|
32662
32973
|
const resolvedBase = ensureRootBase(rootBase);
|
|
32663
32974
|
ensurePathWithinRoot(resolvedBase, filePath);
|
|
32664
|
-
ensureDirectorySegments(resolvedBase,
|
|
32975
|
+
ensureDirectorySegments(resolvedBase, path92__default.dirname(filePath));
|
|
32665
32976
|
writeFileNoFollow(filePath, content);
|
|
32666
32977
|
chmodBestEffort(filePath, FILE_MODE);
|
|
32667
32978
|
}
|
|
32668
|
-
function linkPrivateSymlink(linkPath, target, rootBase) {
|
|
32669
|
-
const resolvedBase = ensureRootBase(rootBase);
|
|
32670
|
-
ensurePathWithinRoot(resolvedBase, linkPath);
|
|
32671
|
-
ensureDirectorySegments(resolvedBase, path93__default.dirname(linkPath));
|
|
32672
|
-
symlinkSync(target, linkPath);
|
|
32673
|
-
}
|
|
32674
32979
|
function removePrivatePath(targetPath, rootBase) {
|
|
32675
32980
|
const resolvedBase = assertRootBaseSafe(rootBase);
|
|
32676
32981
|
ensurePathWithinRoot(resolvedBase, targetPath);
|
|
@@ -32714,20 +33019,20 @@ function writeFileNoFollow(filePath, content) {
|
|
|
32714
33019
|
}
|
|
32715
33020
|
}
|
|
32716
33021
|
function ensureRootBase(rootBase) {
|
|
32717
|
-
const resolvedBase =
|
|
32718
|
-
const anchor = findExistingDirectoryAnchor(
|
|
33022
|
+
const resolvedBase = path92__default.resolve(rootBase);
|
|
33023
|
+
const anchor = findExistingDirectoryAnchor(path92__default.dirname(resolvedBase));
|
|
32719
33024
|
ensureDirectorySegments(anchor, resolvedBase);
|
|
32720
33025
|
assertDirectorySafe(resolvedBase, "Plugin root base");
|
|
32721
33026
|
return resolvedBase;
|
|
32722
33027
|
}
|
|
32723
33028
|
function assertRootBaseSafe(rootBase) {
|
|
32724
|
-
const resolvedBase =
|
|
32725
|
-
assertExistingSegmentsSafe(findExistingDirectoryAnchor(
|
|
33029
|
+
const resolvedBase = path92__default.resolve(rootBase);
|
|
33030
|
+
assertExistingSegmentsSafe(findExistingDirectoryAnchor(path92__default.dirname(resolvedBase)), resolvedBase);
|
|
32726
33031
|
assertDirectorySafe(resolvedBase, "Plugin root base");
|
|
32727
33032
|
return resolvedBase;
|
|
32728
33033
|
}
|
|
32729
33034
|
function findExistingDirectoryAnchor(targetPath) {
|
|
32730
|
-
const resolvedTarget =
|
|
33035
|
+
const resolvedTarget = path92__default.resolve(targetPath);
|
|
32731
33036
|
let current = resolvedTarget;
|
|
32732
33037
|
while (true) {
|
|
32733
33038
|
try {
|
|
@@ -32735,7 +33040,7 @@ function findExistingDirectoryAnchor(targetPath) {
|
|
|
32735
33040
|
return current;
|
|
32736
33041
|
} catch (error51) {
|
|
32737
33042
|
if (error51 instanceof Error && "code" in error51 && error51.code === "ENOENT") {
|
|
32738
|
-
const parent =
|
|
33043
|
+
const parent = path92__default.dirname(current);
|
|
32739
33044
|
if (parent === current) throw error51;
|
|
32740
33045
|
current = parent;
|
|
32741
33046
|
continue;
|
|
@@ -32754,17 +33059,17 @@ function assertDirectorySafe(dirPath, label) {
|
|
|
32754
33059
|
}
|
|
32755
33060
|
}
|
|
32756
33061
|
function ensurePathWithinRoot(resolvedBase, candidatePath) {
|
|
32757
|
-
const resolvedCandidate =
|
|
32758
|
-
const relative =
|
|
32759
|
-
if (relative === "" || !relative.startsWith("..") && !
|
|
33062
|
+
const resolvedCandidate = path92__default.resolve(candidatePath);
|
|
33063
|
+
const relative = path92__default.relative(resolvedBase, resolvedCandidate);
|
|
33064
|
+
if (relative === "" || !relative.startsWith("..") && !path92__default.isAbsolute(relative)) return;
|
|
32760
33065
|
throw new Error(`Plugin path escapes root base: ${candidatePath}`);
|
|
32761
33066
|
}
|
|
32762
33067
|
function ensureDirectorySegments(resolvedBase, dirPath) {
|
|
32763
|
-
const target =
|
|
32764
|
-
const relative =
|
|
33068
|
+
const target = path92__default.resolve(dirPath);
|
|
33069
|
+
const relative = path92__default.relative(resolvedBase, target);
|
|
32765
33070
|
let current = resolvedBase;
|
|
32766
|
-
for (const segment of relative.split(
|
|
32767
|
-
current =
|
|
33071
|
+
for (const segment of relative.split(path92__default.sep).filter(Boolean)) {
|
|
33072
|
+
current = path92__default.join(current, segment);
|
|
32768
33073
|
try {
|
|
32769
33074
|
const stat5 = lstatSync(current);
|
|
32770
33075
|
if (stat5.isSymbolicLink()) {
|
|
@@ -32785,11 +33090,11 @@ function ensureDirectorySegments(resolvedBase, dirPath) {
|
|
|
32785
33090
|
}
|
|
32786
33091
|
}
|
|
32787
33092
|
function assertExistingSegmentsSafe(resolvedBase, targetPath) {
|
|
32788
|
-
const target =
|
|
32789
|
-
const relative =
|
|
33093
|
+
const target = path92__default.resolve(targetPath);
|
|
33094
|
+
const relative = path92__default.relative(resolvedBase, target);
|
|
32790
33095
|
let current = resolvedBase;
|
|
32791
|
-
for (const segment of relative.split(
|
|
32792
|
-
current =
|
|
33096
|
+
for (const segment of relative.split(path92__default.sep).filter(Boolean)) {
|
|
33097
|
+
current = path92__default.join(current, segment);
|
|
32793
33098
|
const stat5 = lstatSync(current);
|
|
32794
33099
|
if (stat5.isSymbolicLink()) {
|
|
32795
33100
|
throw new Error(`Plugin path segment is a symlink: ${current}`);
|
|
@@ -32801,13 +33106,13 @@ function assertExistingSegmentsSafe(resolvedBase, targetPath) {
|
|
|
32801
33106
|
}
|
|
32802
33107
|
}
|
|
32803
33108
|
function assertExistingParentSegmentsSafe(resolvedBase, targetPath) {
|
|
32804
|
-
assertExistingSegmentsSafe(resolvedBase,
|
|
33109
|
+
assertExistingSegmentsSafe(resolvedBase, path92__default.dirname(targetPath));
|
|
32805
33110
|
}
|
|
32806
33111
|
function assertSegmentRealpathWithinRoot(resolvedBase, segmentPath) {
|
|
32807
33112
|
const baseRealpath = realpathSync(resolvedBase);
|
|
32808
33113
|
const segmentRealpath = realpathSync(segmentPath);
|
|
32809
|
-
const relative =
|
|
32810
|
-
if (relative === "" || !relative.startsWith("..") && !
|
|
33114
|
+
const relative = path92__default.relative(baseRealpath, segmentRealpath);
|
|
33115
|
+
if (relative === "" || !relative.startsWith("..") && !path92__default.isAbsolute(relative)) return;
|
|
32811
33116
|
throw new Error(`Plugin path segment escapes root base: ${segmentPath}`);
|
|
32812
33117
|
}
|
|
32813
33118
|
var CLAUDE_AGENT_FILE_STEM_ALLOWLIST = /^[A-Za-z0-9][A-Za-z0-9_-]{0,79}$/;
|
|
@@ -32825,11 +33130,11 @@ function renderAssetPluginRoot(pluginRoot, bundle, options) {
|
|
|
32825
33130
|
if (bundle.includeClaudeAgents) {
|
|
32826
33131
|
for (const subagent of options.claudeDefinitions) {
|
|
32827
33132
|
const fileStem = parseClaudeAgentFileStem(subagent.name);
|
|
32828
|
-
writePrivateFile(
|
|
33133
|
+
writePrivateFile(path92__default.join(pluginRoot, "agents", `${fileStem}.md`), claudeAgentFile(subagent), pluginRoot);
|
|
32829
33134
|
}
|
|
32830
33135
|
}
|
|
32831
|
-
if (options.cliId === "claude" || options.cliId === "claude-kimi") {
|
|
32832
|
-
writePrivateJson(
|
|
33136
|
+
if (options.cliId === "claude" || options.cliId === "claude-kimi" || options.cliId === "claude-glm") {
|
|
33137
|
+
writePrivateJson(path92__default.join(pluginRoot, "hooks", "hooks.json"), claudeHooks(options), pluginRoot);
|
|
32833
33138
|
}
|
|
32834
33139
|
}
|
|
32835
33140
|
function validateClaudeAgentFileStems(subagents) {
|
|
@@ -32838,7 +33143,7 @@ function validateClaudeAgentFileStems(subagents) {
|
|
|
32838
33143
|
}
|
|
32839
33144
|
}
|
|
32840
33145
|
function parseClaudeAgentFileStem(name) {
|
|
32841
|
-
if (CLAUDE_AGENT_FILE_STEM_ALLOWLIST.test(name) &&
|
|
33146
|
+
if (CLAUDE_AGENT_FILE_STEM_ALLOWLIST.test(name) && path92__default.basename(name) === name) return name;
|
|
32842
33147
|
throw new Error(`Invalid Claude agent file name: ${name}`);
|
|
32843
33148
|
}
|
|
32844
33149
|
function claudeHooks(options) {
|
|
@@ -32846,7 +33151,7 @@ function claudeHooks(options) {
|
|
|
32846
33151
|
if (!hookExec) {
|
|
32847
33152
|
throw new Error("Fleet Claude session hook command is required");
|
|
32848
33153
|
}
|
|
32849
|
-
const userPromptSubmitExecs = [options.captureSessionHookExec, options.turnStartHookExec].filter((exec) => exec !== void 0);
|
|
33154
|
+
const userPromptSubmitExecs = [options.captureSessionHookExec, options.turnStartHookExec, options.autoNameHookExec].filter((exec) => exec !== void 0);
|
|
32850
33155
|
const stopExecs = [options.turnEndHookExec].filter((exec) => exec !== void 0);
|
|
32851
33156
|
const inputWaitingExec = options.inputWaitingHookExec;
|
|
32852
33157
|
return {
|
|
@@ -32908,74 +33213,8 @@ function yamlScalar(value) {
|
|
|
32908
33213
|
}
|
|
32909
33214
|
function renderEmbeddedSkillAssets(pluginRoot) {
|
|
32910
33215
|
for (const asset of EMBEDDED_AGENT_CLI_SKILL_ASSETS) {
|
|
32911
|
-
writePrivateFile(
|
|
32912
|
-
}
|
|
32913
|
-
}
|
|
32914
|
-
function linkUserFleetSourcesIntoPlugin(sourceRoot, pluginRoot) {
|
|
32915
|
-
const entries = listUserFleetSourceEntries(sourceRoot);
|
|
32916
|
-
for (const entry of entries) {
|
|
32917
|
-
linkPrivateSymlink(path93__default.join(pluginRoot, entry.pluginRelative), entry.sourcePath, pluginRoot);
|
|
32918
|
-
}
|
|
32919
|
-
}
|
|
32920
|
-
function listUserFleetSourceEntries(sourceRoot) {
|
|
32921
|
-
const entries = [];
|
|
32922
|
-
for (const pluginRelative of ["skills", "agents", "hooks"]) {
|
|
32923
|
-
const sourcePath = path93__default.join(sourceRoot, pluginRelative);
|
|
32924
|
-
if (!existsSync(sourcePath)) continue;
|
|
32925
|
-
const resolvedStat = statSync(sourcePath);
|
|
32926
|
-
if (!resolvedStat.isDirectory()) {
|
|
32927
|
-
throw new Error(`Fleet plugin source path is not a directory: ${sourcePath}`);
|
|
32928
|
-
}
|
|
32929
|
-
entries.push({ kind: "directory", pluginRelative, sourcePath });
|
|
32930
|
-
}
|
|
32931
|
-
const mcpPath = path93__default.join(sourceRoot, ".mcp.json");
|
|
32932
|
-
if (existsSync(mcpPath)) {
|
|
32933
|
-
const resolvedStat = statSync(mcpPath);
|
|
32934
|
-
if (!resolvedStat.isFile()) {
|
|
32935
|
-
throw new Error(`Fleet plugin source path is not a file: ${mcpPath}`);
|
|
32936
|
-
}
|
|
32937
|
-
entries.push({ kind: "file", pluginRelative: ".mcp.json", sourcePath: mcpPath });
|
|
32938
|
-
}
|
|
32939
|
-
return entries;
|
|
32940
|
-
}
|
|
32941
|
-
var GLOBAL_FLEET_SOURCE_ENTRIES = ["skills", "agents", "hooks", ".mcp.json"];
|
|
32942
|
-
var globalBundle = {
|
|
32943
|
-
description: "Fleet global user-level agents, skills, hooks, and MCP plugin",
|
|
32944
|
-
directoryName: "fleet-global",
|
|
32945
|
-
displayName: "Fleet Global",
|
|
32946
|
-
hashFileName: ".fleet-global-codex-plugin.hash",
|
|
32947
|
-
name: "fleet-global",
|
|
32948
|
-
source: "global"
|
|
32949
|
-
};
|
|
32950
|
-
function renderGlobalPluginRoot(pluginRoot, fleetRoot) {
|
|
32951
|
-
linkUserFleetSourcesIntoPlugin(fleetRoot, pluginRoot);
|
|
32952
|
-
}
|
|
32953
|
-
function globalFleetContentExists(fleetRoot) {
|
|
32954
|
-
return GLOBAL_FLEET_SOURCE_ENTRIES.some((entry) => existsSync(path93__default.join(fleetRoot, entry)));
|
|
32955
|
-
}
|
|
32956
|
-
var projectBundle = {
|
|
32957
|
-
description: "Fleet project-local agents, skills, hooks, and MCP plugin",
|
|
32958
|
-
directoryName: "fleet-project",
|
|
32959
|
-
displayName: "Fleet Project",
|
|
32960
|
-
hashFileName: ".fleet-project-codex-plugin.hash",
|
|
32961
|
-
name: "fleet-project",
|
|
32962
|
-
source: "project"
|
|
32963
|
-
};
|
|
32964
|
-
function renderProjectPluginRoot(pluginRoot, options) {
|
|
32965
|
-
const fleetProjectRoot = resolveProjectFleetRoot(options.cwd);
|
|
32966
|
-
linkUserFleetSourcesIntoPlugin(fleetProjectRoot, pluginRoot);
|
|
32967
|
-
}
|
|
32968
|
-
function resolveProjectFleetRoot(cwd) {
|
|
32969
|
-
const fleetProjectRoot = path93__default.join(cwd, ".fleet");
|
|
32970
|
-
const sourceStat = lstatSync(fleetProjectRoot);
|
|
32971
|
-
if (sourceStat.isSymbolicLink()) {
|
|
32972
|
-
throw new Error(`Fleet project plugin source root is a symlink: ${fleetProjectRoot}`);
|
|
32973
|
-
}
|
|
32974
|
-
const verifiedStat = statSync(fleetProjectRoot);
|
|
32975
|
-
if (!verifiedStat.isDirectory()) {
|
|
32976
|
-
throw new Error(`Fleet project plugin source root is not a directory: ${fleetProjectRoot}`);
|
|
33216
|
+
writePrivateFile(path92__default.join(pluginRoot, "skills", asset.relativePath), asset.content, pluginRoot);
|
|
32977
33217
|
}
|
|
32978
|
-
return fleetProjectRoot;
|
|
32979
33218
|
}
|
|
32980
33219
|
var CONFIG_FILE_NAME = "config.toml";
|
|
32981
33220
|
var CONFIG_FILE_MODE = 384;
|
|
@@ -32989,7 +33228,7 @@ function neutralizeCodexFleetPluginConfig(options) {
|
|
|
32989
33228
|
mutateCodexConfigWithRetry(options, 0);
|
|
32990
33229
|
}
|
|
32991
33230
|
function mutateCodexConfigWithRetry(options, attempt) {
|
|
32992
|
-
const configPath =
|
|
33231
|
+
const configPath = path92__default.join(options.codexHome, CONFIG_FILE_NAME);
|
|
32993
33232
|
const targetPath = resolveRealConfigPath(configPath);
|
|
32994
33233
|
const snapshot = readConfigSnapshot(targetPath);
|
|
32995
33234
|
const nextContent = patchCodexConfig(snapshot.content, options);
|
|
@@ -33010,7 +33249,7 @@ function resolveRealConfigPath(configPath) {
|
|
|
33010
33249
|
} catch (error51) {
|
|
33011
33250
|
if (!isNodeError(error51, "ENOENT")) throw error51;
|
|
33012
33251
|
try {
|
|
33013
|
-
return
|
|
33252
|
+
return path92__default.join(realpathSync(path92__default.dirname(configPath)), path92__default.basename(configPath));
|
|
33014
33253
|
} catch (dirError) {
|
|
33015
33254
|
if (isNodeError(dirError, "ENOENT")) return configPath;
|
|
33016
33255
|
throw dirError;
|
|
@@ -33047,9 +33286,9 @@ function readConfigSnapshot(configPath) {
|
|
|
33047
33286
|
}
|
|
33048
33287
|
}
|
|
33049
33288
|
function writeConfigIfUnchanged(configPath, snapshot, content) {
|
|
33050
|
-
mkdirSync(
|
|
33289
|
+
mkdirSync(path92__default.dirname(configPath), { recursive: true, mode: 448 });
|
|
33051
33290
|
assertConfigUnchanged(configPath, snapshot);
|
|
33052
|
-
const tempPath =
|
|
33291
|
+
const tempPath = path92__default.join(path92__default.dirname(configPath), `.${path92__default.basename(configPath)}.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}.tmp`);
|
|
33053
33292
|
let fd;
|
|
33054
33293
|
try {
|
|
33055
33294
|
fd = openSync(tempPath, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, CONFIG_FILE_MODE);
|
|
@@ -33198,6 +33437,10 @@ function unlinkBestEffort(targetPath) {
|
|
|
33198
33437
|
} catch {
|
|
33199
33438
|
}
|
|
33200
33439
|
}
|
|
33440
|
+
var DEPRECATED_HOME_PLUGIN_NAME = "fleet-global";
|
|
33441
|
+
var DEPRECATED_PROJECT_PLUGIN_NAME = "fleet-project";
|
|
33442
|
+
var DEPRECATED_PROJECT_MARKETPLACE_NAME_PREFIX = "fleet-project-";
|
|
33443
|
+
var FLAT_MARKETPLACE_FS_RESIDUE_ENTRIES = [".agents", ".claude-plugin", "plugin"];
|
|
33201
33444
|
async function ensureCodexPluginRegistered(registration, command2, runCommand, withMarketplaceLock) {
|
|
33202
33445
|
try {
|
|
33203
33446
|
await withMarketplaceLock(registration.marketplaceDir, () => {
|
|
@@ -33208,6 +33451,47 @@ async function ensureCodexPluginRegistered(registration, command2, runCommand, w
|
|
|
33208
33451
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
33209
33452
|
}
|
|
33210
33453
|
}
|
|
33454
|
+
async function cleanupDeprecatedCodexPluginState(command2, runCommand, withMarketplaceLock, targets) {
|
|
33455
|
+
try {
|
|
33456
|
+
const marketplaceList = runCommand({ ...command2, args: [...command2.args, "plugin", "marketplace", "list"] });
|
|
33457
|
+
assertCommandSucceeded("codex plugin marketplace list", marketplaceList);
|
|
33458
|
+
const pluginList = runCommand({ ...command2, args: [...command2.args, "plugin", "list"] });
|
|
33459
|
+
assertCommandSucceeded("codex plugin list", pluginList);
|
|
33460
|
+
if (isCodexPluginInstalled(pluginList, DEPRECATED_HOME_PLUGIN_NAME, targets.homeMarketplaceName)) {
|
|
33461
|
+
await withMarketplaceLock(targets.homeMarketplaceRoot, () => {
|
|
33462
|
+
const removed = runCommand({
|
|
33463
|
+
...command2,
|
|
33464
|
+
args: [...command2.args, "plugin", "remove", DEPRECATED_HOME_PLUGIN_NAME, "-m", targets.homeMarketplaceName]
|
|
33465
|
+
});
|
|
33466
|
+
assertCommandSucceeded("codex plugin remove fleet-global", removed);
|
|
33467
|
+
});
|
|
33468
|
+
}
|
|
33469
|
+
const projectTargetRoot = normalizeMarketplaceRoot(targets.projectMarketplaceRoot, command2.cwd);
|
|
33470
|
+
const projectMarketplaces = parseMarketplaceEntries(marketplaceList).filter(
|
|
33471
|
+
(entry) => entry.name.startsWith(DEPRECATED_PROJECT_MARKETPLACE_NAME_PREFIX) && normalizeMarketplaceRoot(entry.root, command2.cwd) === projectTargetRoot
|
|
33472
|
+
);
|
|
33473
|
+
for (const marketplace of projectMarketplaces) {
|
|
33474
|
+
await withMarketplaceLock(targets.projectMarketplaceRoot, () => {
|
|
33475
|
+
if (isCodexPluginInstalled(pluginList, DEPRECATED_PROJECT_PLUGIN_NAME, marketplace.name)) {
|
|
33476
|
+
const removedPlugin = runCommand({
|
|
33477
|
+
...command2,
|
|
33478
|
+
args: [...command2.args, "plugin", "remove", DEPRECATED_PROJECT_PLUGIN_NAME, "-m", marketplace.name]
|
|
33479
|
+
});
|
|
33480
|
+
assertCommandSucceeded("codex plugin remove fleet-project", removedPlugin);
|
|
33481
|
+
}
|
|
33482
|
+
const removedMarketplace = runCommand({
|
|
33483
|
+
...command2,
|
|
33484
|
+
args: [...command2.args, "plugin", "marketplace", "remove", marketplace.name]
|
|
33485
|
+
});
|
|
33486
|
+
assertCommandSucceeded("codex plugin marketplace remove fleet-project", removedMarketplace);
|
|
33487
|
+
removeFlatMarketplaceResidue(targets.projectMarketplaceRoot);
|
|
33488
|
+
});
|
|
33489
|
+
}
|
|
33490
|
+
return void 0;
|
|
33491
|
+
} catch (error51) {
|
|
33492
|
+
return error51 instanceof Error ? error51.message : String(error51);
|
|
33493
|
+
}
|
|
33494
|
+
}
|
|
33211
33495
|
function ensureCodexPluginRegisteredOrThrow(registration, command2, runCommand) {
|
|
33212
33496
|
const marketplaceList = runCommand({ ...command2, args: [...command2.args, "plugin", "marketplace", "list"] });
|
|
33213
33497
|
assertCommandSucceeded("codex plugin marketplace list", marketplaceList);
|
|
@@ -33250,7 +33534,7 @@ function ensureCodexPluginRegisteredOrThrow(registration, command2, runCommand)
|
|
|
33250
33534
|
pluginKey
|
|
33251
33535
|
});
|
|
33252
33536
|
writePrivateFile(registration.hashPath, `${registration.contentHash}
|
|
33253
|
-
`,
|
|
33537
|
+
`, path92__default.dirname(registration.hashPath));
|
|
33254
33538
|
}
|
|
33255
33539
|
function assertCommandSucceeded(label, result) {
|
|
33256
33540
|
if (result.status === 0) return;
|
|
@@ -33258,20 +33542,23 @@ function assertCommandSucceeded(label, result) {
|
|
|
33258
33542
|
throw new Error(`${label} failed${detail.length > 0 ? `: ${detail}` : ""}`);
|
|
33259
33543
|
}
|
|
33260
33544
|
function resolveCodexHome(env) {
|
|
33261
|
-
return env.CODEX_HOME ??
|
|
33545
|
+
return env.CODEX_HOME ?? path92__default.join(env.HOME ?? os22__default.homedir(), ".codex");
|
|
33262
33546
|
}
|
|
33263
33547
|
function findMarketplaceEntries(result, marketplaceName) {
|
|
33548
|
+
return parseMarketplaceEntries(result).filter((entry) => entry.name === marketplaceName);
|
|
33549
|
+
}
|
|
33550
|
+
function parseMarketplaceEntries(result) {
|
|
33264
33551
|
const entries = [];
|
|
33265
33552
|
for (const line of commandOutput(result).split(/\r?\n/)) {
|
|
33266
33553
|
const match = line.trim().match(/^(\S+)\s+(.+)$/);
|
|
33267
|
-
if (match
|
|
33554
|
+
if (match) {
|
|
33268
33555
|
entries.push({ name: match[1], root: match[2].trim() });
|
|
33269
33556
|
}
|
|
33270
33557
|
}
|
|
33271
33558
|
return entries;
|
|
33272
33559
|
}
|
|
33273
33560
|
function normalizeMarketplaceRoot(rootPath, cwd) {
|
|
33274
|
-
const resolved =
|
|
33561
|
+
const resolved = path92__default.resolve(cwd, rootPath);
|
|
33275
33562
|
try {
|
|
33276
33563
|
return realpathSync(resolved);
|
|
33277
33564
|
} catch (error51) {
|
|
@@ -33293,12 +33580,15 @@ function readHash(hashPath) {
|
|
|
33293
33580
|
if (!existsSync(hashPath)) return void 0;
|
|
33294
33581
|
return readFileSync(hashPath, "utf8").trim();
|
|
33295
33582
|
}
|
|
33583
|
+
function removeFlatMarketplaceResidue(projectMarketplaceRoot) {
|
|
33584
|
+
for (const entry of FLAT_MARKETPLACE_FS_RESIDUE_ENTRIES) {
|
|
33585
|
+
removePrivatePath(path92__default.join(projectMarketplaceRoot, entry), projectMarketplaceRoot);
|
|
33586
|
+
}
|
|
33587
|
+
}
|
|
33296
33588
|
var FLEET_MARKETPLACE_NAME = "fleet-harness";
|
|
33297
|
-
var FLEET_PROJECT_MARKETPLACE_NAME_PREFIX = "fleet-project";
|
|
33298
33589
|
var MARKETPLACE_DIR_NAME = "marketplace";
|
|
33299
|
-
var FLAT_PLUGIN_DIR_NAME = "plugin";
|
|
33300
33590
|
var PLUGIN_BUNDLES_DIR_NAME = "plugins";
|
|
33301
|
-
var PLUGIN_BUNDLES = [assetBundle
|
|
33591
|
+
var PLUGIN_BUNDLES = [assetBundle];
|
|
33302
33592
|
var MARKETPLACE_MANAGED_ENTRIES = [
|
|
33303
33593
|
".agents",
|
|
33304
33594
|
".claude-plugin",
|
|
@@ -33310,11 +33600,6 @@ var MARKETPLACE_MANAGED_ENTRIES = [
|
|
|
33310
33600
|
"codex-marketplace",
|
|
33311
33601
|
"plugins"
|
|
33312
33602
|
];
|
|
33313
|
-
var FLAT_MARKETPLACE_MANAGED_ENTRIES = [
|
|
33314
|
-
".agents",
|
|
33315
|
-
".claude-plugin",
|
|
33316
|
-
"plugin"
|
|
33317
|
-
];
|
|
33318
33603
|
var MARKETPLACE_PRUNE_ENTRIES = [
|
|
33319
33604
|
".agents",
|
|
33320
33605
|
".claude-plugin",
|
|
@@ -33325,14 +33610,10 @@ var MARKETPLACE_PRUNE_ENTRIES = [
|
|
|
33325
33610
|
"claude",
|
|
33326
33611
|
"codex-marketplace"
|
|
33327
33612
|
];
|
|
33328
|
-
var FLAT_MARKETPLACE_PRUNE_ENTRIES = [
|
|
33329
|
-
".agents",
|
|
33330
|
-
".claude-plugin"
|
|
33331
|
-
];
|
|
33332
33613
|
var HASH_IGNORED_RELATIVE_PATHS = new Set(PLUGIN_BUNDLES.map((bundle) => bundle.hashFileName));
|
|
33333
33614
|
async function createAgentCliPlugin(options) {
|
|
33334
33615
|
const fleetRoot = options.rootDir ?? options.dataDir;
|
|
33335
|
-
const renderableBundles = resolveRenderablePluginBundles(
|
|
33616
|
+
const renderableBundles = resolveRenderablePluginBundles(fleetRoot);
|
|
33336
33617
|
const marketplaceBundles = groupRenderableBundlesByMarketplace(renderableBundles);
|
|
33337
33618
|
const pluginRoots = /* @__PURE__ */ new Map();
|
|
33338
33619
|
const contentHashes = /* @__PURE__ */ new Map();
|
|
@@ -33341,7 +33622,7 @@ async function createAgentCliPlugin(options) {
|
|
|
33341
33622
|
await options.withMarketplaceLock(marketplace.target.root, () => {
|
|
33342
33623
|
for (const { bundle, target } of marketplace.bundles) {
|
|
33343
33624
|
const pluginRoot = pluginRootForTarget(target, bundle);
|
|
33344
|
-
renderPluginRoot(pluginRoot, bundle, options
|
|
33625
|
+
renderPluginRoot(pluginRoot, bundle, options);
|
|
33345
33626
|
pluginRoots.set(bundle, pluginRoot);
|
|
33346
33627
|
}
|
|
33347
33628
|
renderMarketplaceRoot(marketplace.target, marketplace.bundles.map(({ bundle }) => bundle));
|
|
@@ -33356,7 +33637,7 @@ async function createAgentCliPlugin(options) {
|
|
|
33356
33637
|
cleanup,
|
|
33357
33638
|
codexRegistrations: options.cliId === "codex" ? renderableBundles.map(({ bundle, target }, index) => ({
|
|
33358
33639
|
contentHash: contentHashes.get(target.root),
|
|
33359
|
-
hashPath:
|
|
33640
|
+
hashPath: path92__default.join(target.root, bundle.hashFileName),
|
|
33360
33641
|
marketplaceDir: target.root,
|
|
33361
33642
|
marketplaceName: target.name,
|
|
33362
33643
|
pluginName: bundle.name,
|
|
@@ -33366,43 +33647,14 @@ async function createAgentCliPlugin(options) {
|
|
|
33366
33647
|
pluginRoots: resolvedPluginRoots
|
|
33367
33648
|
};
|
|
33368
33649
|
}
|
|
33369
|
-
function resolveRenderablePluginBundles(
|
|
33650
|
+
function resolveRenderablePluginBundles(fleetRoot) {
|
|
33370
33651
|
const homeMarketplace = homeMarketplaceTarget(fleetRoot);
|
|
33371
|
-
|
|
33372
|
-
const renderableBundles = [];
|
|
33373
|
-
for (const bundle of PLUGIN_BUNDLES) {
|
|
33374
|
-
switch (bundle.source) {
|
|
33375
|
-
case "project": {
|
|
33376
|
-
if (!existsSync(path93__default.join(options.cwd, ".fleet"))) break;
|
|
33377
|
-
projectMarketplace ??= projectMarketplaceTarget(options.cwd);
|
|
33378
|
-
renderableBundles.push({ bundle, target: projectMarketplace });
|
|
33379
|
-
break;
|
|
33380
|
-
}
|
|
33381
|
-
case "global":
|
|
33382
|
-
if (globalFleetContentExists(fleetRoot)) {
|
|
33383
|
-
renderableBundles.push({ bundle, target: homeMarketplace });
|
|
33384
|
-
}
|
|
33385
|
-
break;
|
|
33386
|
-
default:
|
|
33387
|
-
renderableBundles.push({ bundle, target: homeMarketplace });
|
|
33388
|
-
}
|
|
33389
|
-
}
|
|
33390
|
-
return renderableBundles;
|
|
33652
|
+
return PLUGIN_BUNDLES.map((bundle) => ({ bundle, target: homeMarketplace }));
|
|
33391
33653
|
}
|
|
33392
33654
|
function homeMarketplaceTarget(fleetRoot) {
|
|
33393
33655
|
return {
|
|
33394
|
-
flat: false,
|
|
33395
33656
|
name: FLEET_MARKETPLACE_NAME,
|
|
33396
|
-
root:
|
|
33397
|
-
};
|
|
33398
|
-
}
|
|
33399
|
-
function projectMarketplaceTarget(cwd) {
|
|
33400
|
-
const projectFleetRoot = resolveProjectFleetRoot(cwd);
|
|
33401
|
-
const hash2 = crypto4.createHash("sha256").update(path93__default.resolve(cwd, ".fleet")).digest("hex").slice(0, 12);
|
|
33402
|
-
return {
|
|
33403
|
-
flat: true,
|
|
33404
|
-
name: `${FLEET_PROJECT_MARKETPLACE_NAME_PREFIX}-${hash2}`,
|
|
33405
|
-
root: projectFleetRoot
|
|
33657
|
+
root: path92__default.join(fleetRoot, MARKETPLACE_DIR_NAME)
|
|
33406
33658
|
};
|
|
33407
33659
|
}
|
|
33408
33660
|
function groupRenderableBundlesByMarketplace(bundles) {
|
|
@@ -33417,28 +33669,22 @@ function groupRenderableBundlesByMarketplace(bundles) {
|
|
|
33417
33669
|
}
|
|
33418
33670
|
return groups;
|
|
33419
33671
|
}
|
|
33420
|
-
function renderPluginRoot(pluginRoot, bundle, options
|
|
33421
|
-
const parentRoot =
|
|
33672
|
+
function renderPluginRoot(pluginRoot, bundle, options) {
|
|
33673
|
+
const parentRoot = path92__default.dirname(pluginRoot);
|
|
33422
33674
|
ensurePrivateDir(parentRoot, parentRoot);
|
|
33423
33675
|
const stageParent = createStagingDir(parentRoot);
|
|
33424
|
-
const stagedPluginRoot =
|
|
33676
|
+
const stagedPluginRoot = path92__default.join(stageParent, path92__default.basename(pluginRoot));
|
|
33425
33677
|
try {
|
|
33426
33678
|
ensurePrivateDir(stagedPluginRoot, stagedPluginRoot);
|
|
33427
|
-
writePrivateJson(
|
|
33679
|
+
writePrivateJson(path92__default.join(stagedPluginRoot, ".claude-plugin", "plugin.json"), claudeManifest(bundle), stagedPluginRoot);
|
|
33428
33680
|
switch (bundle.source) {
|
|
33429
33681
|
case "asset":
|
|
33430
|
-
ensurePrivateDir(
|
|
33431
|
-
ensurePrivateDir(
|
|
33682
|
+
ensurePrivateDir(path92__default.join(stagedPluginRoot, "agents"), stagedPluginRoot);
|
|
33683
|
+
ensurePrivateDir(path92__default.join(stagedPluginRoot, "skills"), stagedPluginRoot);
|
|
33432
33684
|
renderAssetPluginRoot(stagedPluginRoot, bundle, options);
|
|
33433
33685
|
break;
|
|
33434
|
-
case "project":
|
|
33435
|
-
renderProjectPluginRoot(stagedPluginRoot, options);
|
|
33436
|
-
break;
|
|
33437
|
-
case "global":
|
|
33438
|
-
renderGlobalPluginRoot(stagedPluginRoot, fleetRoot);
|
|
33439
|
-
break;
|
|
33440
33686
|
}
|
|
33441
|
-
writePrivateJson(
|
|
33687
|
+
writePrivateJson(path92__default.join(stagedPluginRoot, ".codex-plugin", "plugin.json"), codexManifest(bundle, stagedPluginRoot), stagedPluginRoot);
|
|
33442
33688
|
removePrivatePath(pluginRoot, parentRoot);
|
|
33443
33689
|
renameSync(stagedPluginRoot, pluginRoot);
|
|
33444
33690
|
} finally {
|
|
@@ -33450,26 +33696,35 @@ function renderMarketplaceRoot(target, bundles) {
|
|
|
33450
33696
|
ensurePrivateDir(marketplaceRoot, marketplaceRoot);
|
|
33451
33697
|
const stagedRoot = createStagingDir(marketplaceRoot);
|
|
33452
33698
|
try {
|
|
33453
|
-
writePrivateJson(
|
|
33454
|
-
writePrivateJson(
|
|
33699
|
+
writePrivateJson(path92__default.join(stagedRoot, ".agents", "plugins", "marketplace.json"), codexMarketplace(target, bundles), stagedRoot);
|
|
33700
|
+
writePrivateJson(path92__default.join(stagedRoot, ".claude-plugin", "marketplace.json"), claudeMarketplace(target, bundles), stagedRoot);
|
|
33455
33701
|
pruneMarketplaceRoot(target);
|
|
33702
|
+
pruneStalePluginDirs(target, bundles);
|
|
33456
33703
|
for (const entry of readdirSync(stagedRoot)) {
|
|
33457
|
-
renameSync(
|
|
33704
|
+
renameSync(path92__default.join(stagedRoot, entry), path92__default.join(marketplaceRoot, entry));
|
|
33458
33705
|
}
|
|
33459
33706
|
} finally {
|
|
33460
33707
|
cleanupPrivateRoot(stagedRoot, marketplaceRoot);
|
|
33461
33708
|
}
|
|
33462
33709
|
}
|
|
33463
33710
|
function pruneMarketplaceRoot(target) {
|
|
33464
|
-
const
|
|
33465
|
-
|
|
33466
|
-
|
|
33711
|
+
for (const entry of MARKETPLACE_PRUNE_ENTRIES) {
|
|
33712
|
+
removePrivatePath(path92__default.join(target.root, entry), target.root);
|
|
33713
|
+
}
|
|
33714
|
+
}
|
|
33715
|
+
function pruneStalePluginDirs(target, bundles) {
|
|
33716
|
+
const pluginsDir = path92__default.join(target.root, PLUGIN_BUNDLES_DIR_NAME);
|
|
33717
|
+
if (!existsSync(pluginsDir)) return;
|
|
33718
|
+
const activeDirectoryNames = new Set(bundles.map((bundle) => bundle.directoryName));
|
|
33719
|
+
for (const entry of readdirSync(pluginsDir)) {
|
|
33720
|
+
if (activeDirectoryNames.has(entry)) continue;
|
|
33721
|
+
removePrivatePath(path92__default.join(pluginsDir, entry), target.root);
|
|
33467
33722
|
}
|
|
33468
33723
|
}
|
|
33469
33724
|
function buildContentHash(target) {
|
|
33470
|
-
const hash2 =
|
|
33725
|
+
const hash2 = crypto3.createHash("sha256");
|
|
33471
33726
|
for (const filePath of listRenderableFiles(target)) {
|
|
33472
|
-
const relativePath2 =
|
|
33727
|
+
const relativePath2 = path92__default.relative(target.root, filePath);
|
|
33473
33728
|
hash2.update(relativePath2);
|
|
33474
33729
|
hash2.update("\0");
|
|
33475
33730
|
hash2.update(readFileSync(filePath));
|
|
@@ -33478,15 +33733,14 @@ function buildContentHash(target) {
|
|
|
33478
33733
|
return hash2.digest("hex");
|
|
33479
33734
|
}
|
|
33480
33735
|
function createStagingDir(rootPath) {
|
|
33481
|
-
const stageRoot = mkdtempSync(
|
|
33736
|
+
const stageRoot = mkdtempSync(path92__default.join(rootPath, `.fleet-stage-${process.pid}-${Date.now()}-`));
|
|
33482
33737
|
return stageRoot;
|
|
33483
33738
|
}
|
|
33484
33739
|
function listRenderableFiles(target) {
|
|
33485
33740
|
const files = [];
|
|
33486
33741
|
const ancestorRealDirs = /* @__PURE__ */ new Set();
|
|
33487
|
-
const
|
|
33488
|
-
|
|
33489
|
-
const entryPath = path93__default.join(target.root, entry);
|
|
33742
|
+
for (const entry of MARKETPLACE_MANAGED_ENTRIES) {
|
|
33743
|
+
const entryPath = path92__default.join(target.root, entry);
|
|
33490
33744
|
if (!existsSync(entryPath)) continue;
|
|
33491
33745
|
collectRenderableFiles(target.root, entryPath, files, ancestorRealDirs);
|
|
33492
33746
|
}
|
|
@@ -33497,8 +33751,8 @@ function collectRenderableFiles(rootPath, currentPath, files, ancestorRealDirs)
|
|
|
33497
33751
|
if (ancestorRealDirs.has(realDir)) return;
|
|
33498
33752
|
ancestorRealDirs.add(realDir);
|
|
33499
33753
|
for (const entry of readdirSync(currentPath)) {
|
|
33500
|
-
const entryPath =
|
|
33501
|
-
const relativePath2 =
|
|
33754
|
+
const entryPath = path92__default.join(currentPath, entry);
|
|
33755
|
+
const relativePath2 = path92__default.relative(rootPath, entryPath);
|
|
33502
33756
|
if (HASH_IGNORED_RELATIVE_PATHS.has(relativePath2)) continue;
|
|
33503
33757
|
const stat5 = lstatSync(entryPath);
|
|
33504
33758
|
if (stat5.isSymbolicLink()) {
|
|
@@ -33564,10 +33818,9 @@ function claudeMarketplace(target, bundles) {
|
|
|
33564
33818
|
};
|
|
33565
33819
|
}
|
|
33566
33820
|
function pluginRootForTarget(target, bundle) {
|
|
33567
|
-
return
|
|
33821
|
+
return path92__default.join(target.root, PLUGIN_BUNDLES_DIR_NAME, bundle.directoryName);
|
|
33568
33822
|
}
|
|
33569
33823
|
function marketplacePluginPath(target, bundle) {
|
|
33570
|
-
if (target.flat) return `./${FLAT_PLUGIN_DIR_NAME}`;
|
|
33571
33824
|
return `./${PLUGIN_BUNDLES_DIR_NAME}/${bundle.directoryName}`;
|
|
33572
33825
|
}
|
|
33573
33826
|
function codexManifest(bundle, pluginRoot) {
|
|
@@ -33579,13 +33832,13 @@ function codexManifest(bundle, pluginRoot) {
|
|
|
33579
33832
|
};
|
|
33580
33833
|
}
|
|
33581
33834
|
function codexManifestVersion(bundle, pluginRoot) {
|
|
33582
|
-
const hash2 =
|
|
33835
|
+
const hash2 = crypto3.createHash("sha256");
|
|
33583
33836
|
hash2.update(bundle.name);
|
|
33584
33837
|
hash2.update("\0");
|
|
33585
33838
|
hash2.update(bundle.description);
|
|
33586
33839
|
hash2.update("\0");
|
|
33587
33840
|
for (const filePath of listCodexEffectivePluginFiles(pluginRoot)) {
|
|
33588
|
-
const relativePath2 =
|
|
33841
|
+
const relativePath2 = path92__default.relative(pluginRoot, filePath);
|
|
33589
33842
|
hash2.update(relativePath2);
|
|
33590
33843
|
hash2.update("\0");
|
|
33591
33844
|
hash2.update(readFileSync(filePath));
|
|
@@ -33594,7 +33847,7 @@ function codexManifestVersion(bundle, pluginRoot) {
|
|
|
33594
33847
|
return `0.0.0+${hash2.digest("hex").slice(0, 12)}`;
|
|
33595
33848
|
}
|
|
33596
33849
|
function listCodexEffectivePluginFiles(pluginRoot) {
|
|
33597
|
-
const skillsPath =
|
|
33850
|
+
const skillsPath = path92__default.join(pluginRoot, "skills");
|
|
33598
33851
|
if (!existsSync(skillsPath)) return [];
|
|
33599
33852
|
const files = [];
|
|
33600
33853
|
collectRenderableFiles(pluginRoot, skillsPath, files, /* @__PURE__ */ new Set());
|
|
@@ -33619,13 +33872,13 @@ async function injectAgentCliProfile(profile, options) {
|
|
|
33619
33872
|
const injectTone = options.enableMetaphor ?? false;
|
|
33620
33873
|
const endpoint = await options.dedicatedMcpSession.getEndpoint();
|
|
33621
33874
|
const startupDefinitions = buildStartupNativeDefinitions(profile.id, options.carrierRuntime);
|
|
33622
|
-
const tokenLabel = options.mcpSessionLabel ?? `agent:${profile.id}:${
|
|
33875
|
+
const tokenLabel = options.mcpSessionLabel ?? `agent:${profile.id}:${crypto3.randomUUID()}`;
|
|
33623
33876
|
const tokens = await options.dedicatedMcpSession.issueSessionToken({ cwd: profile.cwd, label: tokenLabel });
|
|
33624
33877
|
const mcpServers = buildAgentCliMcpServerConfigs(endpoint.servers, tokens);
|
|
33625
33878
|
const doctrine = options.buildSystemPrompt(injectTone);
|
|
33626
33879
|
const tempCleanups = [];
|
|
33627
33880
|
try {
|
|
33628
|
-
const systemPromptFile = profile.id === "claude" || profile.id === "claude-kimi" ? writeSystemPromptFile(profile.id, doctrine, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
|
|
33881
|
+
const systemPromptFile = profile.id === "claude" || profile.id === "claude-kimi" || profile.id === "claude-glm" ? writeSystemPromptFile(profile.id, doctrine, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
|
|
33629
33882
|
const plugin = await createAgentCliPlugin({
|
|
33630
33883
|
claudeDefinitions: startupDefinitions.host === "claude" ? startupDefinitions.definitions : [],
|
|
33631
33884
|
cliId: profile.id,
|
|
@@ -33637,6 +33890,7 @@ async function injectAgentCliProfile(profile, options) {
|
|
|
33637
33890
|
turnStartHookExec: options.turnStartHookExec,
|
|
33638
33891
|
turnEndHookExec: options.turnEndHookExec,
|
|
33639
33892
|
inputWaitingHookExec: options.inputWaitingHookExec,
|
|
33893
|
+
autoNameHookExec: options.autoNameHookExec,
|
|
33640
33894
|
hookExec: startupDefinitions.host === "claude" ? requireHookExec(options.hookExec) : void 0,
|
|
33641
33895
|
withMarketplaceLock: options.withMarketplaceLock
|
|
33642
33896
|
});
|
|
@@ -33644,9 +33898,25 @@ async function injectAgentCliProfile(profile, options) {
|
|
|
33644
33898
|
const codexProfile = profile.id === "codex" ? writeCodexFleetProfile(profile.env, doctrine, codexPluginKeys, {
|
|
33645
33899
|
captureSessionHookExec: options.captureSessionHookExec,
|
|
33646
33900
|
turnStartHookExec: options.turnStartHookExec,
|
|
33647
|
-
turnEndHookExec: options.turnEndHookExec
|
|
33901
|
+
turnEndHookExec: options.turnEndHookExec,
|
|
33902
|
+
autoNameHookExec: options.autoNameHookExec
|
|
33648
33903
|
}, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
|
|
33649
33904
|
const launchWarnings = [];
|
|
33905
|
+
if (profile.id === "codex") {
|
|
33906
|
+
const cleanupWarning = await cleanupDeprecatedCodexPluginState({
|
|
33907
|
+
args: [...profile.binPrefixArgs ?? []],
|
|
33908
|
+
bin: profile.bin,
|
|
33909
|
+
cwd: profile.cwd,
|
|
33910
|
+
env: { ...profile.env }
|
|
33911
|
+
}, requireCodexCommandRunner(options.codexCommandRunner), options.withMarketplaceLock, {
|
|
33912
|
+
homeMarketplaceName: FLEET_MARKETPLACE_NAME,
|
|
33913
|
+
homeMarketplaceRoot: path92__default.join(options.pluginRootDir ?? options.dataDir, "marketplace"),
|
|
33914
|
+
projectMarketplaceRoot: path92__default.join(profile.cwd, ".fleet")
|
|
33915
|
+
});
|
|
33916
|
+
if (cleanupWarning !== void 0) {
|
|
33917
|
+
launchWarnings.push(`Deprecated Codex plugin cleanup failed: ${cleanupWarning}`);
|
|
33918
|
+
}
|
|
33919
|
+
}
|
|
33650
33920
|
for (const registration of plugin.codexRegistrations) {
|
|
33651
33921
|
const registrationWarning = await ensureCodexPluginRegistered(registration, {
|
|
33652
33922
|
args: [...profile.binPrefixArgs ?? []],
|
|
@@ -33697,7 +33967,7 @@ function buildStartupNativeDefinitions(cliId, carrierRuntime) {
|
|
|
33697
33967
|
return { host, definitions: buildClaudeNativeSubagentPlan2(carrierRuntime.registry).definitions };
|
|
33698
33968
|
}
|
|
33699
33969
|
function getNativeSubagentHost(cliId) {
|
|
33700
|
-
if (cliId === "claude" || cliId === "claude-kimi") return "claude";
|
|
33970
|
+
if (cliId === "claude" || cliId === "claude-kimi" || cliId === "claude-glm") return "claude";
|
|
33701
33971
|
return "none";
|
|
33702
33972
|
}
|
|
33703
33973
|
function buildAgentCliMcpServerConfigs(endpoints, tokens) {
|
|
@@ -33714,19 +33984,19 @@ function buildAgentCliMcpServerConfigs(endpoints, tokens) {
|
|
|
33714
33984
|
});
|
|
33715
33985
|
}
|
|
33716
33986
|
function writeSystemPromptFile(cliId, systemPrompt, onCleanup) {
|
|
33717
|
-
const tempDir = mkdtempSync(
|
|
33987
|
+
const tempDir = mkdtempSync(path92__default.join(os22__default.tmpdir(), `fleet-${cliId}-`));
|
|
33718
33988
|
onCleanup(() => rmBestEffort(tempDir));
|
|
33719
|
-
const filePath =
|
|
33989
|
+
const filePath = path92__default.join(tempDir, "system-prompt.md");
|
|
33720
33990
|
writeFileSync(filePath, systemPrompt, { encoding: "utf8", flag: "wx", mode: SYSTEM_PROMPT_FILE_MODE });
|
|
33721
33991
|
chmodBestEffort2(filePath, SYSTEM_PROMPT_FILE_MODE);
|
|
33722
33992
|
return filePath;
|
|
33723
33993
|
}
|
|
33724
33994
|
function writeCodexFleetProfile(env, doctrine, pluginKeys, hookExecs, onCleanup) {
|
|
33725
|
-
const codexHome = env.CODEX_HOME ??
|
|
33995
|
+
const codexHome = env.CODEX_HOME ?? path92__default.join(env.HOME ?? os22__default.homedir(), ".codex");
|
|
33726
33996
|
mkdirSync(codexHome, { recursive: true });
|
|
33727
33997
|
pruneStaleCodexFleetProfiles(codexHome);
|
|
33728
|
-
const profileName = `fleet-${
|
|
33729
|
-
const profilePath =
|
|
33998
|
+
const profileName = `fleet-${crypto3.randomUUID()}`;
|
|
33999
|
+
const profilePath = path92__default.join(codexHome, `${profileName}.config.toml`);
|
|
33730
34000
|
onCleanup(() => rmBestEffort(profilePath));
|
|
33731
34001
|
writeFileNoFollow2(profilePath, [
|
|
33732
34002
|
CODEX_FLEET_PROFILE_MARKER,
|
|
@@ -33747,7 +34017,7 @@ function writeCodexFleetProfile(env, doctrine, pluginKeys, hookExecs, onCleanup)
|
|
|
33747
34017
|
return { profileName, profilePath };
|
|
33748
34018
|
}
|
|
33749
34019
|
function codexHooksConfig(hookExecs) {
|
|
33750
|
-
const userPromptSubmitExecs = [hookExecs.captureSessionHookExec, hookExecs.turnStartHookExec].filter((exec) => exec !== void 0);
|
|
34020
|
+
const userPromptSubmitExecs = [hookExecs.captureSessionHookExec, hookExecs.turnStartHookExec, hookExecs.autoNameHookExec].filter((exec) => exec !== void 0);
|
|
33751
34021
|
const stopExecs = [hookExecs.turnEndHookExec].filter((exec) => exec !== void 0);
|
|
33752
34022
|
if (userPromptSubmitExecs.length === 0 && stopExecs.length === 0) return [];
|
|
33753
34023
|
const lines = ["[hooks]"];
|
|
@@ -33786,7 +34056,7 @@ function pruneStaleCodexFleetProfiles(codexHome) {
|
|
|
33786
34056
|
const now = Date.now();
|
|
33787
34057
|
for (const entry of entries) {
|
|
33788
34058
|
if (!CODEX_FLEET_PROFILE_FILE_NAME_PATTERN.test(entry)) continue;
|
|
33789
|
-
const filePath =
|
|
34059
|
+
const filePath = path92__default.join(codexHome, entry);
|
|
33790
34060
|
if (!isStaleFleetCodexProfile(filePath, now)) continue;
|
|
33791
34061
|
unlinkBestEffort2(filePath);
|
|
33792
34062
|
}
|
|
@@ -34230,7 +34500,7 @@ function extractLegacyMarkdownWikiLinks(body, wikiDir, basePath) {
|
|
|
34230
34500
|
}
|
|
34231
34501
|
function resolveLegacyWikiTarget(target, wikiDir, basePath) {
|
|
34232
34502
|
if (!target || target.startsWith("#")) return null;
|
|
34233
|
-
if (
|
|
34503
|
+
if (path92__default.isAbsolute(target)) return null;
|
|
34234
34504
|
if (/^[a-z][a-z0-9+.-]*:/i.test(target)) return null;
|
|
34235
34505
|
const withoutFragment = target.split("#", 1)[0]?.split("?", 1)[0] ?? "";
|
|
34236
34506
|
if (!withoutFragment.endsWith(".md")) return null;
|
|
@@ -34240,12 +34510,12 @@ function resolveLegacyWikiTarget(target, wikiDir, basePath) {
|
|
|
34240
34510
|
} catch {
|
|
34241
34511
|
return null;
|
|
34242
34512
|
}
|
|
34243
|
-
const resolved =
|
|
34244
|
-
const relative =
|
|
34245
|
-
if (!relative || relative.startsWith("..") ||
|
|
34513
|
+
const resolved = path92__default.resolve(path92__default.dirname(basePath), decodedTarget);
|
|
34514
|
+
const relative = path92__default.relative(wikiDir, resolved);
|
|
34515
|
+
if (!relative || relative.startsWith("..") || path92__default.isAbsolute(relative)) return null;
|
|
34246
34516
|
return {
|
|
34247
34517
|
target,
|
|
34248
|
-
entryId:
|
|
34518
|
+
entryId: path92__default.basename(relative, ".md")
|
|
34249
34519
|
};
|
|
34250
34520
|
}
|
|
34251
34521
|
var KNOWLEDGE_ROOT_DIRNAME = ".fleet/knowledge";
|
|
@@ -34503,18 +34773,18 @@ Always read \`schema/wiki-schema.md\` directly before composing or revising entr
|
|
|
34503
34773
|
`;
|
|
34504
34774
|
async function ensureWorkspaceSchema(paths) {
|
|
34505
34775
|
await mkdir(paths.schemaDir, { recursive: true });
|
|
34506
|
-
await writeDefaultFileIfMissing(
|
|
34507
|
-
await writeDefaultFileIfMissing(
|
|
34776
|
+
await writeDefaultFileIfMissing(path92__default.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME), DEFAULT_WORKSPACE_SCHEMA_AGENTS);
|
|
34777
|
+
await writeDefaultFileIfMissing(path92__default.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME), DEFAULT_WORKSPACE_WIKI_SCHEMA);
|
|
34508
34778
|
await writeDefaultFileIfMissing(buildTemplatePath(paths, "prd"), DEFAULT_TEMPLATE_PRD);
|
|
34509
34779
|
return readWorkspaceSchemaSummary(paths);
|
|
34510
34780
|
}
|
|
34511
34781
|
async function ensureWorkspaceDoctrine(paths) {
|
|
34512
34782
|
await mkdir(paths.root, { recursive: true });
|
|
34513
|
-
await writeDefaultFileIfMissing(
|
|
34783
|
+
await writeDefaultFileIfMissing(path92__default.join(paths.root, WORKSPACE_KNOWLEDGE_AGENTS_FILENAME), DEFAULT_WORKSPACE_KNOWLEDGE_AGENTS);
|
|
34514
34784
|
}
|
|
34515
34785
|
async function readWorkspaceSchemaSummary(paths) {
|
|
34516
|
-
const agentsPath =
|
|
34517
|
-
const wikiSchemaPath =
|
|
34786
|
+
const agentsPath = path92__default.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME);
|
|
34787
|
+
const wikiSchemaPath = path92__default.join(paths.schemaDir, WORKSPACE_SCHEMA_FILENAME);
|
|
34518
34788
|
const wikiSchemaContent = await tryReadFile(wikiSchemaPath);
|
|
34519
34789
|
const templates = await scanTemplates(paths);
|
|
34520
34790
|
if (wikiSchemaContent === null) {
|
|
@@ -34553,7 +34823,7 @@ async function scanTemplates(paths) {
|
|
|
34553
34823
|
if (!entry.name.startsWith(WORKSPACE_TEMPLATE_PREFIX) || !entry.name.endsWith(WORKSPACE_TEMPLATE_SUFFIX)) continue;
|
|
34554
34824
|
const id = entry.name.slice(WORKSPACE_TEMPLATE_PREFIX.length, -WORKSPACE_TEMPLATE_SUFFIX.length);
|
|
34555
34825
|
if (!id) continue;
|
|
34556
|
-
const filePath =
|
|
34826
|
+
const filePath = path92__default.join(paths.schemaDir, entry.name);
|
|
34557
34827
|
try {
|
|
34558
34828
|
const parsed = parseTemplateMarkdown(await readFile(filePath, "utf8"));
|
|
34559
34829
|
templates.push({
|
|
@@ -34587,7 +34857,7 @@ async function validateTemplateCompliance(paths, templateId, body) {
|
|
|
34587
34857
|
}
|
|
34588
34858
|
}
|
|
34589
34859
|
function inferTemplateIdFromTarget(target, knownTemplateIds) {
|
|
34590
|
-
const basename =
|
|
34860
|
+
const basename = path92__default.basename(target, ".md");
|
|
34591
34861
|
const ids = knownTemplateIds ?? DEFAULT_TEMPLATE_IDS;
|
|
34592
34862
|
const sorted = [...ids].sort((a, b) => b.length - a.length);
|
|
34593
34863
|
for (const id of sorted) {
|
|
@@ -34616,7 +34886,7 @@ function extractSchemaSummary(content) {
|
|
|
34616
34886
|
return lines.find((line) => line.length > 0 && !line.startsWith("#")) ?? "Workspace schema is present.";
|
|
34617
34887
|
}
|
|
34618
34888
|
function buildTemplatePath(paths, id) {
|
|
34619
|
-
return
|
|
34889
|
+
return path92__default.join(paths.schemaDir, `${WORKSPACE_TEMPLATE_PREFIX}${id}${WORKSPACE_TEMPLATE_SUFFIX}`);
|
|
34620
34890
|
}
|
|
34621
34891
|
function parseTemplateMarkdown(content) {
|
|
34622
34892
|
const normalized = content.replace(/\r\n/g, "\n");
|
|
@@ -34641,16 +34911,16 @@ function isAlreadyExistsError(error51) {
|
|
|
34641
34911
|
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "EEXIST";
|
|
34642
34912
|
}
|
|
34643
34913
|
function resolveMemoryPaths(cwd) {
|
|
34644
|
-
const root =
|
|
34914
|
+
const root = path92__default.join(cwd, KNOWLEDGE_ROOT_DIRNAME);
|
|
34645
34915
|
return {
|
|
34646
34916
|
root,
|
|
34647
|
-
rawDir:
|
|
34648
|
-
wikiDir:
|
|
34649
|
-
schemaDir:
|
|
34650
|
-
queueDir:
|
|
34651
|
-
archiveDir:
|
|
34652
|
-
conflictsDir:
|
|
34653
|
-
indexFile:
|
|
34917
|
+
rawDir: path92__default.join(root, RAW_DIRNAME),
|
|
34918
|
+
wikiDir: path92__default.join(root, WIKI_DIRNAME),
|
|
34919
|
+
schemaDir: path92__default.join(root, SCHEMA_DIRNAME),
|
|
34920
|
+
queueDir: path92__default.join(root, QUEUE_DIRNAME),
|
|
34921
|
+
archiveDir: path92__default.join(root, ARCHIVE_DIRNAME),
|
|
34922
|
+
conflictsDir: path92__default.join(root, CONFLICTS_DIRNAME),
|
|
34923
|
+
indexFile: path92__default.join(root, INDEX_FILENAME)
|
|
34654
34924
|
};
|
|
34655
34925
|
}
|
|
34656
34926
|
async function ensureMemoryRoot(paths) {
|
|
@@ -34665,10 +34935,10 @@ async function ensureMemoryRoot(paths) {
|
|
|
34665
34935
|
await ensureWorkspaceDoctrine(paths);
|
|
34666
34936
|
}
|
|
34667
34937
|
function getIndexMarkdownFile(paths) {
|
|
34668
|
-
return
|
|
34938
|
+
return path92__default.join(paths.wikiDir, INDEX_MD_FILENAME);
|
|
34669
34939
|
}
|
|
34670
34940
|
function getLogFile(paths) {
|
|
34671
|
-
return
|
|
34941
|
+
return path92__default.join(paths.root, LOG_MD_FILENAME);
|
|
34672
34942
|
}
|
|
34673
34943
|
var LOG_HEADER_PATTERN = /^## (.+) — (.+)$/;
|
|
34674
34944
|
var LOG_BULLET_PATTERN = /^- ([a-z0-9_]+): `([\s\S]*)`$/;
|
|
@@ -34826,12 +35096,12 @@ async function readWikiEntry(id, paths) {
|
|
|
34826
35096
|
const index = await loadIndex(paths);
|
|
34827
35097
|
const indexed = index[id];
|
|
34828
35098
|
if (indexed) {
|
|
34829
|
-
const resolved =
|
|
34830
|
-
const rel =
|
|
34831
|
-
if (!rel || rel.startsWith("..") ||
|
|
35099
|
+
const resolved = path92__default.resolve(paths.root, indexed.path);
|
|
35100
|
+
const rel = path92__default.relative(paths.wikiDir, resolved);
|
|
35101
|
+
if (!rel || rel.startsWith("..") || path92__default.isAbsolute(rel)) return null;
|
|
34832
35102
|
return readMarkdownFile(resolved);
|
|
34833
35103
|
}
|
|
34834
|
-
const fallbackPath =
|
|
35104
|
+
const fallbackPath = path92__default.join(paths.wikiDir, `${id}.md`);
|
|
34835
35105
|
if (await pathExists(fallbackPath)) {
|
|
34836
35106
|
return readMarkdownFile(fallbackPath);
|
|
34837
35107
|
}
|
|
@@ -34842,20 +35112,20 @@ async function readWikiEntry(id, paths) {
|
|
|
34842
35112
|
async function writeWikiEntryAtTarget(entry, target, paths) {
|
|
34843
35113
|
await ensureMemoryRoot(paths);
|
|
34844
35114
|
assertSafeEntryId(entry.id);
|
|
34845
|
-
const absoluteTarget =
|
|
34846
|
-
const relativeTarget =
|
|
34847
|
-
if (!relativeTarget || relativeTarget.startsWith("..") ||
|
|
35115
|
+
const absoluteTarget = path92__default.resolve(paths.root, target);
|
|
35116
|
+
const relativeTarget = path92__default.relative(paths.wikiDir, absoluteTarget);
|
|
35117
|
+
if (!relativeTarget || relativeTarget.startsWith("..") || path92__default.isAbsolute(relativeTarget)) {
|
|
34848
35118
|
throw new Error(`[fleet-wiki] wiki target escapes wiki/: ${target}`);
|
|
34849
35119
|
}
|
|
34850
35120
|
if (!absoluteTarget.endsWith(".md")) {
|
|
34851
35121
|
throw new Error(`[fleet-wiki] wiki target must end with .md: ${target}`);
|
|
34852
35122
|
}
|
|
34853
|
-
if (
|
|
35123
|
+
if (path92__default.basename(absoluteTarget, ".md") !== entry.id) {
|
|
34854
35124
|
throw new Error("wiki patch body id must match target filename");
|
|
34855
35125
|
}
|
|
34856
|
-
await mkdir(
|
|
35126
|
+
await mkdir(path92__default.dirname(absoluteTarget), { recursive: true });
|
|
34857
35127
|
await writeMarkdownAtomic(absoluteTarget, serializeWikiEntry(entry), paths);
|
|
34858
|
-
return
|
|
35128
|
+
return path92__default.join("wiki", relativeTarget).replaceAll(path92__default.sep, "/");
|
|
34859
35129
|
}
|
|
34860
35130
|
async function writeRawSourceEntry(entry, paths) {
|
|
34861
35131
|
await ensureMemoryRoot(paths);
|
|
@@ -34874,11 +35144,11 @@ async function writeRawSourceEntry(entry, paths) {
|
|
|
34874
35144
|
},
|
|
34875
35145
|
entry.content
|
|
34876
35146
|
);
|
|
34877
|
-
await writeMarkdownAtomic(
|
|
35147
|
+
await writeMarkdownAtomic(path92__default.join(paths.root, relativePath2), content, paths);
|
|
34878
35148
|
return relativePath2;
|
|
34879
35149
|
}
|
|
34880
35150
|
async function readRawSourceEntry(rawSourceRef, paths) {
|
|
34881
|
-
const absolutePath =
|
|
35151
|
+
const absolutePath = path92__default.resolve(paths.root, rawSourceRef);
|
|
34882
35152
|
assertWithinRawDir(absolutePath, paths);
|
|
34883
35153
|
const parsed = parseMarkdown(await readFile(absolutePath, "utf8"));
|
|
34884
35154
|
return {
|
|
@@ -35066,11 +35336,11 @@ function stripLeadingFrontmatter(body) {
|
|
|
35066
35336
|
return stripped ? next : body;
|
|
35067
35337
|
}
|
|
35068
35338
|
function computeContentHash(content) {
|
|
35069
|
-
return
|
|
35339
|
+
return crypto3.createHash("sha256").update(content, "utf8").digest("hex").slice(0, 8);
|
|
35070
35340
|
}
|
|
35071
35341
|
function assertWithinRawDir(absolutePath, paths) {
|
|
35072
|
-
const relative =
|
|
35073
|
-
if (!relative || relative.startsWith("..") ||
|
|
35342
|
+
const relative = path92__default.relative(paths.rawDir, absolutePath);
|
|
35343
|
+
if (!relative || relative.startsWith("..") || path92__default.isAbsolute(relative)) {
|
|
35074
35344
|
throw new Error(`[fleet-wiki] raw source ref escapes raw/: ${absolutePath}`);
|
|
35075
35345
|
}
|
|
35076
35346
|
}
|
|
@@ -35126,7 +35396,7 @@ function parseWikiEntry(content) {
|
|
|
35126
35396
|
async function listWikiRecords(paths) {
|
|
35127
35397
|
return listMarkdownEntriesRecursive(paths.wikiDir, paths, (content, filePath) => ({
|
|
35128
35398
|
entry: parseWikiEntry(content),
|
|
35129
|
-
path:
|
|
35399
|
+
path: path92__default.relative(paths.root, filePath).replaceAll(path92__default.sep, "/")
|
|
35130
35400
|
}));
|
|
35131
35401
|
}
|
|
35132
35402
|
async function listMarkdownEntriesRecursive(dirPath, paths, parser) {
|
|
@@ -35139,7 +35409,7 @@ async function listMarkdownEntriesRecursive(dirPath, paths, parser) {
|
|
|
35139
35409
|
}
|
|
35140
35410
|
const sortedEntries = entries.sort((left, right) => left.name.localeCompare(right.name));
|
|
35141
35411
|
for (const entry of sortedEntries) {
|
|
35142
|
-
const filePath =
|
|
35412
|
+
const filePath = path92__default.join(dirPath, entry.name);
|
|
35143
35413
|
if (entry.isDirectory()) {
|
|
35144
35414
|
items.push(...await listMarkdownEntriesRecursive(filePath, paths, parser));
|
|
35145
35415
|
continue;
|
|
@@ -35277,9 +35547,9 @@ async function writeJsonAtomic(filePath, value, paths) {
|
|
|
35277
35547
|
}
|
|
35278
35548
|
async function writeAtomic(filePath, content, paths) {
|
|
35279
35549
|
await ensureMemoryRoot(paths);
|
|
35280
|
-
const tempPath =
|
|
35281
|
-
|
|
35282
|
-
`.tmp-${process.pid}-${Date.now()}-${
|
|
35550
|
+
const tempPath = path92__default.join(
|
|
35551
|
+
path92__default.dirname(filePath),
|
|
35552
|
+
`.tmp-${process.pid}-${Date.now()}-${crypto3.randomUUID()}-${os22__default.hostname()}`
|
|
35283
35553
|
);
|
|
35284
35554
|
await writeFile(tempPath, content, "utf8");
|
|
35285
35555
|
await rename(tempPath, filePath);
|
|
@@ -35323,7 +35593,7 @@ async function enhancedSearch(paths, options) {
|
|
|
35323
35593
|
for (const entry of entries) {
|
|
35324
35594
|
if (!index[entry.id]) {
|
|
35325
35595
|
index[entry.id] = {
|
|
35326
|
-
path:
|
|
35596
|
+
path: path92__default.join("wiki", `${entry.id}.md`),
|
|
35327
35597
|
title: entry.title,
|
|
35328
35598
|
tags: entry.tags,
|
|
35329
35599
|
updated: entry.updated
|
|
@@ -35459,7 +35729,7 @@ function toEnhancedHit(entry, signals) {
|
|
|
35459
35729
|
score: enhancedScore,
|
|
35460
35730
|
reason: signals.legacyReason ?? "body",
|
|
35461
35731
|
excerpt,
|
|
35462
|
-
path:
|
|
35732
|
+
path: path92__default.join("wiki", `${entry.id}.md`),
|
|
35463
35733
|
tags: entry.tags,
|
|
35464
35734
|
updated: entry.updated,
|
|
35465
35735
|
version: entry.version,
|
|
@@ -35653,7 +35923,7 @@ function toRankedHit(entry, reason, detail, graphBoost, backlinksById) {
|
|
|
35653
35923
|
score: basePriority * 100 + statusPriority * 10 + graphScore + (detail.tagBoost ?? 0),
|
|
35654
35924
|
reason,
|
|
35655
35925
|
excerpt,
|
|
35656
|
-
path:
|
|
35926
|
+
path: path92__default.join("wiki", `${entry.id}.md`),
|
|
35657
35927
|
tags: entry.tags,
|
|
35658
35928
|
updated: entry.updated,
|
|
35659
35929
|
version: entry.version,
|
|
@@ -36077,15 +36347,15 @@ var PATCH_SET_DIRNAME = "_sets";
|
|
|
36077
36347
|
var PATCH_SET_META_FILENAME = PATCH_META_FILENAME;
|
|
36078
36348
|
function getPatchSetDir(paths, patchSetId) {
|
|
36079
36349
|
assertSafePatchSetId(patchSetId);
|
|
36080
|
-
const patchSetDir =
|
|
36081
|
-
const relative =
|
|
36082
|
-
if (!relative || relative.startsWith("..") ||
|
|
36350
|
+
const patchSetDir = path92__default.join(paths.queueDir, PATCH_SET_DIRNAME, patchSetId);
|
|
36351
|
+
const relative = path92__default.relative(path92__default.join(paths.queueDir, PATCH_SET_DIRNAME), patchSetDir);
|
|
36352
|
+
if (!relative || relative.startsWith("..") || path92__default.isAbsolute(relative)) {
|
|
36083
36353
|
throw new Error(`[fleet-wiki] patch set id escapes queue/_sets: ${patchSetId}`);
|
|
36084
36354
|
}
|
|
36085
36355
|
return patchSetDir;
|
|
36086
36356
|
}
|
|
36087
36357
|
function getPatchSetMetaFile(paths, patchSetId) {
|
|
36088
|
-
return
|
|
36358
|
+
return path92__default.join(getPatchSetDir(paths, patchSetId), PATCH_SET_META_FILENAME);
|
|
36089
36359
|
}
|
|
36090
36360
|
function buildPatchSetId(createdAt, sourceRef) {
|
|
36091
36361
|
const compact = createdAt.replace(/[:.]/g, "-");
|
|
@@ -36118,7 +36388,7 @@ async function createConflict(input, paths) {
|
|
|
36118
36388
|
await ensureMemoryRoot(paths);
|
|
36119
36389
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
36120
36390
|
const conflictId = buildConflictId(now, input.wikiId, input.reason, input.proposed);
|
|
36121
|
-
const conflictDir =
|
|
36391
|
+
const conflictDir = path92__default.join(paths.conflictsDir, conflictId);
|
|
36122
36392
|
await mkdir(conflictDir, { recursive: true });
|
|
36123
36393
|
const meta3 = {
|
|
36124
36394
|
id: conflictId,
|
|
@@ -36138,13 +36408,13 @@ async function createConflict(input, paths) {
|
|
|
36138
36408
|
currentHash: input.currentHash,
|
|
36139
36409
|
warnings: input.warnings
|
|
36140
36410
|
};
|
|
36141
|
-
await writeJsonFile(
|
|
36142
|
-
await writePatchFile(
|
|
36411
|
+
await writeJsonFile(path92__default.join(conflictDir, CONFLICT_META_FILENAME), meta3, paths);
|
|
36412
|
+
await writePatchFile(path92__default.join(conflictDir, CONFLICT_PROPOSED_FILENAME), input.proposed, paths);
|
|
36143
36413
|
if (input.current !== void 0) {
|
|
36144
|
-
await writePatchFile(
|
|
36414
|
+
await writePatchFile(path92__default.join(conflictDir, CONFLICT_CURRENT_FILENAME), input.current, paths);
|
|
36145
36415
|
}
|
|
36146
36416
|
if (input.rawSource !== void 0) {
|
|
36147
|
-
await writePatchFile(
|
|
36417
|
+
await writePatchFile(path92__default.join(conflictDir, CONFLICT_RAW_SOURCE_FILENAME), input.rawSource, paths);
|
|
36148
36418
|
}
|
|
36149
36419
|
return {
|
|
36150
36420
|
meta: meta3,
|
|
@@ -36158,7 +36428,7 @@ async function listConflicts(paths) {
|
|
|
36158
36428
|
const metas = [];
|
|
36159
36429
|
for (const id of ids) {
|
|
36160
36430
|
try {
|
|
36161
|
-
metas.push(await readJsonFile2(
|
|
36431
|
+
metas.push(await readJsonFile2(path92__default.join(paths.conflictsDir, id, CONFLICT_META_FILENAME)));
|
|
36162
36432
|
} catch {
|
|
36163
36433
|
continue;
|
|
36164
36434
|
}
|
|
@@ -36167,13 +36437,13 @@ async function listConflicts(paths) {
|
|
|
36167
36437
|
}
|
|
36168
36438
|
async function readConflict(conflictId, paths) {
|
|
36169
36439
|
const conflictDir = resolveConflictDir(conflictId, paths);
|
|
36170
|
-
const meta3 = await readJsonFile2(
|
|
36171
|
-
const currentPath =
|
|
36172
|
-
const rawSourcePath =
|
|
36440
|
+
const meta3 = await readJsonFile2(path92__default.join(conflictDir, CONFLICT_META_FILENAME));
|
|
36441
|
+
const currentPath = path92__default.join(conflictDir, CONFLICT_CURRENT_FILENAME);
|
|
36442
|
+
const rawSourcePath = path92__default.join(conflictDir, CONFLICT_RAW_SOURCE_FILENAME);
|
|
36173
36443
|
return {
|
|
36174
36444
|
meta: meta3,
|
|
36175
36445
|
current: await pathExists(currentPath) ? await readPatchFile(currentPath) : void 0,
|
|
36176
|
-
proposed: await readPatchFile(
|
|
36446
|
+
proposed: await readPatchFile(path92__default.join(conflictDir, CONFLICT_PROPOSED_FILENAME)),
|
|
36177
36447
|
rawSource: await pathExists(rawSourcePath) ? await readPatchFile(rawSourcePath) : void 0
|
|
36178
36448
|
};
|
|
36179
36449
|
}
|
|
@@ -36192,9 +36462,9 @@ function sanitizeConflictToken(value) {
|
|
|
36192
36462
|
return value.toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "unknown";
|
|
36193
36463
|
}
|
|
36194
36464
|
function resolveConflictDir(conflictId, paths) {
|
|
36195
|
-
const conflictDir =
|
|
36196
|
-
const relative =
|
|
36197
|
-
if (!relative || relative.startsWith("..") ||
|
|
36465
|
+
const conflictDir = path92__default.resolve(paths.conflictsDir, conflictId);
|
|
36466
|
+
const relative = path92__default.relative(paths.conflictsDir, conflictDir);
|
|
36467
|
+
if (!relative || relative.startsWith("..") || path92__default.isAbsolute(relative)) {
|
|
36198
36468
|
throw new Error(`[fleet-wiki] conflict id escapes conflicts/: ${conflictId}`);
|
|
36199
36469
|
}
|
|
36200
36470
|
return conflictDir;
|
|
@@ -36230,11 +36500,11 @@ async function validatePatch(patch, paths) {
|
|
|
36230
36500
|
if (!target || !summary || !proposer || !created) throw new Error("patch frontmatter is incomplete");
|
|
36231
36501
|
if (summary.length > 120) throw new Error("patch summary exceeds 120 chars");
|
|
36232
36502
|
assertCanonicalPatchTarget(target);
|
|
36233
|
-
const absoluteTarget =
|
|
36234
|
-
if (!absoluteTarget.startsWith(`${paths.root}${
|
|
36503
|
+
const absoluteTarget = path92__default.resolve(paths.root, target);
|
|
36504
|
+
if (!absoluteTarget.startsWith(`${paths.root}${path92__default.sep}`) && absoluteTarget !== paths.root) {
|
|
36235
36505
|
throw new Error("patch target escapes wiki root");
|
|
36236
36506
|
}
|
|
36237
|
-
if (!absoluteTarget.startsWith(`${paths.wikiDir}${
|
|
36507
|
+
if (!absoluteTarget.startsWith(`${paths.wikiDir}${path92__default.sep}`)) throw new Error("wiki patch must target wiki/");
|
|
36238
36508
|
assertNoSymlinkPathComponents(target, paths);
|
|
36239
36509
|
if (op === "create_wiki" && await pathExists(absoluteTarget)) {
|
|
36240
36510
|
throw new Error(
|
|
@@ -36255,19 +36525,19 @@ async function applyPatch(patch, paths) {
|
|
|
36255
36525
|
async function enqueuePatch(patch, paths, metaOverrides) {
|
|
36256
36526
|
await ensureMemoryRoot(paths);
|
|
36257
36527
|
const patchId = buildPatchId(patch.frontmatter.created, patch.frontmatter.summary, patch.frontmatter.target, patch.body);
|
|
36258
|
-
const queueDir =
|
|
36528
|
+
const queueDir = path92__default.join(paths.queueDir, patchId);
|
|
36259
36529
|
if (await pathExists(queueDir)) {
|
|
36260
36530
|
throw new Error(`[fleet-wiki] patch id collision: ${patchId} - this should never happen with target+body hashing`);
|
|
36261
36531
|
}
|
|
36262
36532
|
await mkdir(queueDir, { recursive: true });
|
|
36263
|
-
await writePatchFile(
|
|
36533
|
+
await writePatchFile(path92__default.join(queueDir, PATCH_FILENAME), serializePatch(patch), paths);
|
|
36264
36534
|
const meta3 = {
|
|
36265
36535
|
id: patchId,
|
|
36266
36536
|
status: "pending",
|
|
36267
36537
|
createdAt: patch.frontmatter.created,
|
|
36268
36538
|
...metaOverrides
|
|
36269
36539
|
};
|
|
36270
|
-
await writeJsonFile(
|
|
36540
|
+
await writeJsonFile(path92__default.join(queueDir, PATCH_META_FILENAME), meta3, paths);
|
|
36271
36541
|
await appendLog(paths, "patch enqueued", {
|
|
36272
36542
|
patch_id: patchId,
|
|
36273
36543
|
patch_set_id: meta3.patch_set_id ?? null,
|
|
@@ -36285,7 +36555,7 @@ async function listQueue(paths) {
|
|
|
36285
36555
|
for (const id of ids) {
|
|
36286
36556
|
if (id === "_sets") continue;
|
|
36287
36557
|
try {
|
|
36288
|
-
const meta3 = await readJsonFile2(
|
|
36558
|
+
const meta3 = await readJsonFile2(path92__default.join(paths.queueDir, id, PATCH_META_FILENAME));
|
|
36289
36559
|
results.push({ id, meta: meta3 });
|
|
36290
36560
|
} catch {
|
|
36291
36561
|
continue;
|
|
@@ -36310,17 +36580,17 @@ async function resolveQueueSelection(id, paths) {
|
|
|
36310
36580
|
}
|
|
36311
36581
|
async function showQueue(id, paths) {
|
|
36312
36582
|
const selection = await resolveQueueSelection(id, paths);
|
|
36313
|
-
const queueDir =
|
|
36314
|
-
const patch = await parsePatch(await readPatchFile(
|
|
36315
|
-
const meta3 = await readJsonFile2(
|
|
36583
|
+
const queueDir = path92__default.join(paths.queueDir, selection.id);
|
|
36584
|
+
const patch = await parsePatch(await readPatchFile(path92__default.join(queueDir, PATCH_FILENAME)));
|
|
36585
|
+
const meta3 = await readJsonFile2(path92__default.join(queueDir, PATCH_META_FILENAME));
|
|
36316
36586
|
return { patch, meta: meta3 };
|
|
36317
36587
|
}
|
|
36318
36588
|
async function rewriteQueuedPatch(id, paths, patch, meta3, expectedPatchHash) {
|
|
36319
36589
|
assertSafeQueueId(id);
|
|
36320
36590
|
return withPatchEditLock(paths, id, async () => {
|
|
36321
|
-
const queueDir =
|
|
36591
|
+
const queueDir = path92__default.join(paths.queueDir, id);
|
|
36322
36592
|
if (expectedPatchHash !== void 0) {
|
|
36323
|
-
const currentMarkdown = await readPatchFile(
|
|
36593
|
+
const currentMarkdown = await readPatchFile(path92__default.join(queueDir, PATCH_FILENAME));
|
|
36324
36594
|
const currentHash = computeContentHash(currentMarkdown);
|
|
36325
36595
|
if (currentHash !== expectedPatchHash) {
|
|
36326
36596
|
throw new Error(`[fleet-wiki] wiki_patch_edit stale base_patch_hash: expected ${currentHash}, got ${expectedPatchHash}`);
|
|
@@ -36329,8 +36599,8 @@ async function rewriteQueuedPatch(id, paths, patch, meta3, expectedPatchHash) {
|
|
|
36329
36599
|
const patchMarkdown = serializePatch(patch);
|
|
36330
36600
|
const patchHash = computeContentHash(patchMarkdown);
|
|
36331
36601
|
const nextMeta = { ...meta3, lastEditHash: patchHash };
|
|
36332
|
-
await writePatchFile(
|
|
36333
|
-
await writeJsonFile(
|
|
36602
|
+
await writePatchFile(path92__default.join(queueDir, PATCH_FILENAME), patchMarkdown, paths);
|
|
36603
|
+
await writeJsonFile(path92__default.join(queueDir, PATCH_META_FILENAME), nextMeta, paths);
|
|
36334
36604
|
return patchHash;
|
|
36335
36605
|
});
|
|
36336
36606
|
}
|
|
@@ -36354,8 +36624,8 @@ async function approvePatch(id, paths) {
|
|
|
36354
36624
|
rawSourceRef: meta3.rawSourceRef,
|
|
36355
36625
|
warnings: meta3.warnings
|
|
36356
36626
|
});
|
|
36357
|
-
const queueDir =
|
|
36358
|
-
await writeJsonFile(
|
|
36627
|
+
const queueDir = path92__default.join(paths.queueDir, id);
|
|
36628
|
+
await writeJsonFile(path92__default.join(queueDir, PATCH_META_FILENAME), {
|
|
36359
36629
|
...meta3,
|
|
36360
36630
|
conflictId
|
|
36361
36631
|
}, paths);
|
|
@@ -36391,7 +36661,7 @@ async function approvePatchSet(patchSetId, paths) {
|
|
|
36391
36661
|
const failed = [];
|
|
36392
36662
|
const missing = [];
|
|
36393
36663
|
for (const patchId of patchSet.patchIds) {
|
|
36394
|
-
const queueDir =
|
|
36664
|
+
const queueDir = path92__default.join(paths.queueDir, patchId);
|
|
36395
36665
|
if (!await pathExists(queueDir)) {
|
|
36396
36666
|
missing.push(patchId);
|
|
36397
36667
|
continue;
|
|
@@ -36457,7 +36727,7 @@ ${patch.body}`;
|
|
|
36457
36727
|
}
|
|
36458
36728
|
async function normalizeWikiEntryPatch(entry, target, paths) {
|
|
36459
36729
|
assertSafeEntryId(entry.id);
|
|
36460
|
-
if (entry.id !==
|
|
36730
|
+
if (entry.id !== path92__default.basename(target, ".md")) {
|
|
36461
36731
|
throw new Error("wiki patch body id must match target filename");
|
|
36462
36732
|
}
|
|
36463
36733
|
const inlineRawSourceRef = extractInlineRawSourceRef(entry.body);
|
|
@@ -36500,9 +36770,9 @@ function buildPatchId(createdAt, summary, target, body) {
|
|
|
36500
36770
|
}
|
|
36501
36771
|
async function validatePatchBase(patch, meta3, paths) {
|
|
36502
36772
|
if (patch.frontmatter.op !== "update_wiki" || !meta3?.baseVersion && !meta3?.baseHash) return;
|
|
36503
|
-
const wikiId =
|
|
36773
|
+
const wikiId = path92__default.basename(patch.frontmatter.target, ".md");
|
|
36504
36774
|
const currentEntry = await readWikiEntry(wikiId, paths);
|
|
36505
|
-
const currentPath =
|
|
36775
|
+
const currentPath = path92__default.join(paths.root, patch.frontmatter.target);
|
|
36506
36776
|
const currentMarkdown = await pathExists(currentPath) ? await readPatchFile(currentPath) : void 0;
|
|
36507
36777
|
if (meta3.baseVersion !== void 0 && currentEntry?.version !== meta3.baseVersion) {
|
|
36508
36778
|
throw new Error(
|
|
@@ -36561,17 +36831,17 @@ function assertCanonicalPatchTarget(target) {
|
|
|
36561
36831
|
if (target.endsWith("/")) {
|
|
36562
36832
|
throw new Error("patch target must not end with a slash");
|
|
36563
36833
|
}
|
|
36564
|
-
if (target.startsWith("/") ||
|
|
36834
|
+
if (target.startsWith("/") || path92__default.posix.isAbsolute(target) || path92__default.win32.isAbsolute(target)) {
|
|
36565
36835
|
throw new Error("patch target must be relative");
|
|
36566
36836
|
}
|
|
36567
|
-
if (
|
|
36837
|
+
if (path92__default.posix.normalize(target) !== target) {
|
|
36568
36838
|
throw new Error("patch target must not contain dot segments or redundant separators");
|
|
36569
36839
|
}
|
|
36570
36840
|
}
|
|
36571
36841
|
function canonicalApprovalLockKey(paths, target) {
|
|
36572
36842
|
const wikiRoot = realpathSync(paths.wikiDir);
|
|
36573
|
-
const relativeTarget =
|
|
36574
|
-
const targetPath =
|
|
36843
|
+
const relativeTarget = path92__default.posix.relative("wiki", target);
|
|
36844
|
+
const targetPath = path92__default.join(wikiRoot, ...relativeTarget.split("/"));
|
|
36575
36845
|
return `${wikiRoot}\0${targetPath}`.toLowerCase();
|
|
36576
36846
|
}
|
|
36577
36847
|
function canonicalPatchEditLockKey(paths, patchId) {
|
|
@@ -36587,7 +36857,7 @@ function assertNoSymlinkPathComponents(target, paths) {
|
|
|
36587
36857
|
throw error51;
|
|
36588
36858
|
}
|
|
36589
36859
|
for (const part of parts) {
|
|
36590
|
-
current =
|
|
36860
|
+
current = path92__default.join(current, part);
|
|
36591
36861
|
try {
|
|
36592
36862
|
if (lstatSync(current).isSymbolicLink()) {
|
|
36593
36863
|
throw new Error("patch target must not include symlink path components");
|
|
@@ -36602,8 +36872,8 @@ function assertSafeRawSourceRef(rawSourceRef, paths) {
|
|
|
36602
36872
|
if (!rawSourceRef.startsWith("raw/")) {
|
|
36603
36873
|
throw new Error("raw source provenance must point into raw/");
|
|
36604
36874
|
}
|
|
36605
|
-
const absoluteRef =
|
|
36606
|
-
if (!absoluteRef.startsWith(`${paths.rawDir}${
|
|
36875
|
+
const absoluteRef = path92__default.resolve(paths.root, rawSourceRef);
|
|
36876
|
+
if (!absoluteRef.startsWith(`${paths.rawDir}${path92__default.sep}`)) {
|
|
36607
36877
|
throw new Error("raw source provenance must point into raw/");
|
|
36608
36878
|
}
|
|
36609
36879
|
}
|
|
@@ -36619,14 +36889,14 @@ function classifyPatchConflict(error51) {
|
|
|
36619
36889
|
}
|
|
36620
36890
|
async function recordPatchConflict(patch, paths, reason, options) {
|
|
36621
36891
|
const now = /* @__PURE__ */ new Date();
|
|
36622
|
-
const targetPath =
|
|
36892
|
+
const targetPath = path92__default.join(paths.root, patch.frontmatter.target);
|
|
36623
36893
|
const current = await pathExists(targetPath) ? await readPatchFile(targetPath) : void 0;
|
|
36624
36894
|
const currentEntry = current ? parseStoredWikiEntry(current) : void 0;
|
|
36625
36895
|
const proposedEntry = parsePatchBodyEntry(patch.body);
|
|
36626
36896
|
const record2 = await createConflict({
|
|
36627
36897
|
reason,
|
|
36628
36898
|
target: patch.frontmatter.target,
|
|
36629
|
-
wikiId: proposedEntry?.id ??
|
|
36899
|
+
wikiId: proposedEntry?.id ?? path92__default.basename(patch.frontmatter.target, ".md"),
|
|
36630
36900
|
title: proposedEntry?.title,
|
|
36631
36901
|
proposer: patch.frontmatter.proposer,
|
|
36632
36902
|
rawSourceRef: options?.rawSourceRef,
|
|
@@ -36722,11 +36992,11 @@ function parseInlineArray(value) {
|
|
|
36722
36992
|
return inner.split(",").map((item) => item.trim().replace(/^"(.*)"$/, "$1"));
|
|
36723
36993
|
}
|
|
36724
36994
|
async function archiveQueueEntry(id, paths, meta3) {
|
|
36725
|
-
const fromDir =
|
|
36726
|
-
const toDir =
|
|
36995
|
+
const fromDir = path92__default.join(paths.queueDir, id);
|
|
36996
|
+
const toDir = path92__default.join(paths.archiveDir, id);
|
|
36727
36997
|
await removePath(toDir);
|
|
36728
36998
|
await movePath(fromDir, toDir);
|
|
36729
|
-
await writeJsonFile(
|
|
36999
|
+
await writeJsonFile(path92__default.join(toDir, PATCH_META_FILENAME), meta3, paths);
|
|
36730
37000
|
}
|
|
36731
37001
|
function buildQueueIdHelp(prefix, availableIds) {
|
|
36732
37002
|
if (availableIds.length === 0) {
|
|
@@ -36934,7 +37204,7 @@ async function resolveCompileSource(input, paths, now) {
|
|
|
36934
37204
|
}
|
|
36935
37205
|
async function buildCompileProposals(input, paths, now, resolvedSource) {
|
|
36936
37206
|
const sourceTarget = `wiki/sources/${resolvedSource.sourcePageId}.md`;
|
|
36937
|
-
const sourceExists = await pathExists(
|
|
37207
|
+
const sourceExists = await pathExists(path92__default.join(paths.root, sourceTarget));
|
|
36938
37208
|
const existingEntries = await listWiki(paths);
|
|
36939
37209
|
const sourcePageTitle = resolvedSource.sourceTitle?.trim() || `Source ${resolvedSource.sourcePageId}`;
|
|
36940
37210
|
const existingSourceEntry = existingEntries.find((entry) => entry.id === resolvedSource.sourcePageId);
|
|
@@ -36956,7 +37226,7 @@ async function buildCompileProposals(input, paths, now, resolvedSource) {
|
|
|
36956
37226
|
target: sourceTarget,
|
|
36957
37227
|
summary: truncateSummary(`Compile source page ${sourcePageTitle}`),
|
|
36958
37228
|
entry: sourceEntry,
|
|
36959
|
-
baseHash: sourceExists ? computeContentHash(await readPatchFile(
|
|
37229
|
+
baseHash: sourceExists ? computeContentHash(await readPatchFile(path92__default.join(paths.root, sourceTarget))) : void 0,
|
|
36960
37230
|
baseVersion: existingSourceEntry?.version
|
|
36961
37231
|
}];
|
|
36962
37232
|
const relatedCandidates = await discoverRelatedEntryCandidates(paths, resolvedSource.sourceContent, resolvedSource.sourceTitle);
|
|
@@ -36976,7 +37246,7 @@ async function buildCompileProposals(input, paths, now, resolvedSource) {
|
|
|
36976
37246
|
rawSourceRefs: mergeRawSourceRefs(existing.rawSourceRefs, existing.rawSourceRef, { ref: resolvedSource.rawSourceRef }),
|
|
36977
37247
|
body: appendSourceCompileNote(existing.body, resolvedSource.sourcePageId, resolvedSource.rawSourceRef)
|
|
36978
37248
|
},
|
|
36979
|
-
baseHash: computeContentHash(await readPatchFile(
|
|
37249
|
+
baseHash: computeContentHash(await readPatchFile(path92__default.join(paths.wikiDir, `${existing.id}.md`))),
|
|
36980
37250
|
baseVersion: existing.version
|
|
36981
37251
|
});
|
|
36982
37252
|
}
|
|
@@ -37111,13 +37381,13 @@ async function readClaims(entryId, paths) {
|
|
|
37111
37381
|
}
|
|
37112
37382
|
}
|
|
37113
37383
|
function getClaimsDir(paths) {
|
|
37114
|
-
return
|
|
37384
|
+
return path92__default.join(paths.wikiDir, CLAIMS_DIRNAME);
|
|
37115
37385
|
}
|
|
37116
37386
|
function getClaimsFile(paths, entryId) {
|
|
37117
37387
|
assertSafeEntryId(entryId);
|
|
37118
|
-
const claimsFile =
|
|
37119
|
-
const relative =
|
|
37120
|
-
if (!relative || relative.startsWith("..") ||
|
|
37388
|
+
const claimsFile = path92__default.join(getClaimsDir(paths), `${entryId}.json`);
|
|
37389
|
+
const relative = path92__default.relative(getClaimsDir(paths), claimsFile);
|
|
37390
|
+
if (!relative || relative.startsWith("..") || path92__default.isAbsolute(relative)) {
|
|
37121
37391
|
throw new Error(`[fleet-wiki] claims sidecar escapes wiki/.claims: ${entryId}`);
|
|
37122
37392
|
}
|
|
37123
37393
|
return claimsFile;
|
|
@@ -37208,7 +37478,7 @@ function assertSafeClaimRawRef(ref) {
|
|
|
37208
37478
|
if (!ref.startsWith("raw/")) {
|
|
37209
37479
|
throw new Error(`claim sourceRef must point into raw/: ${ref}`);
|
|
37210
37480
|
}
|
|
37211
|
-
if (ref.includes("..") ||
|
|
37481
|
+
if (ref.includes("..") || path92__default.isAbsolute(ref)) {
|
|
37212
37482
|
throw new Error(`claim sourceRef escapes raw/: ${ref}`);
|
|
37213
37483
|
}
|
|
37214
37484
|
}
|
|
@@ -37284,22 +37554,22 @@ async function runDryDock(paths, options = {}) {
|
|
|
37284
37554
|
}
|
|
37285
37555
|
for (const fileName of await listFileNames(paths.rawDir)) {
|
|
37286
37556
|
if (!fileName.endsWith(".md")) continue;
|
|
37287
|
-
const filePath =
|
|
37557
|
+
const filePath = path92__default.join(paths.rawDir, fileName);
|
|
37288
37558
|
issues.push(...safetyIssues(await readPatchFile(filePath), filePath));
|
|
37289
37559
|
}
|
|
37290
37560
|
for (const queueId of await listDirectoryNames(paths.queueDir)) {
|
|
37291
37561
|
if (queueId === PATCH_SET_DIRNAME) continue;
|
|
37292
|
-
const queueDir =
|
|
37562
|
+
const queueDir = path92__default.join(paths.queueDir, queueId);
|
|
37293
37563
|
try {
|
|
37294
|
-
const patchContent = await readPatchFile(
|
|
37295
|
-
issues.push(...safetyIssues(patchContent,
|
|
37296
|
-
await readJsonFile2(
|
|
37564
|
+
const patchContent = await readPatchFile(path92__default.join(queueDir, PATCH_FILENAME));
|
|
37565
|
+
issues.push(...safetyIssues(patchContent, path92__default.join(queueDir, PATCH_FILENAME)));
|
|
37566
|
+
await readJsonFile2(path92__default.join(queueDir, PATCH_META_FILENAME));
|
|
37297
37567
|
} catch {
|
|
37298
37568
|
issues.push(issue2("malformed_queue", "error", "\uC190\uC0C1\uB41C queue \uC5D4\uD2B8\uB9AC", queueDir));
|
|
37299
37569
|
}
|
|
37300
37570
|
}
|
|
37301
|
-
for (const patchSetId of await listDirectoryNames(
|
|
37302
|
-
const patchSetMetaFile =
|
|
37571
|
+
for (const patchSetId of await listDirectoryNames(path92__default.join(paths.queueDir, PATCH_SET_DIRNAME))) {
|
|
37572
|
+
const patchSetMetaFile = path92__default.join(paths.queueDir, PATCH_SET_DIRNAME, patchSetId, PATCH_META_FILENAME);
|
|
37303
37573
|
let patchSet;
|
|
37304
37574
|
try {
|
|
37305
37575
|
patchSet = await readPatchSet(paths, patchSetId);
|
|
@@ -37308,8 +37578,8 @@ async function runDryDock(paths, options = {}) {
|
|
|
37308
37578
|
continue;
|
|
37309
37579
|
}
|
|
37310
37580
|
for (const patchId of patchSet.patchIds) {
|
|
37311
|
-
const queueMetaFile =
|
|
37312
|
-
const archiveMetaFile =
|
|
37581
|
+
const queueMetaFile = path92__default.join(paths.queueDir, patchId, PATCH_META_FILENAME);
|
|
37582
|
+
const archiveMetaFile = path92__default.join(paths.archiveDir, patchId, PATCH_META_FILENAME);
|
|
37313
37583
|
if (!await pathExists(queueMetaFile) && !await pathExists(archiveMetaFile)) {
|
|
37314
37584
|
issues.push(
|
|
37315
37585
|
issue2(
|
|
@@ -37346,7 +37616,7 @@ async function runDryDock(paths, options = {}) {
|
|
|
37346
37616
|
"conflict_unresolved",
|
|
37347
37617
|
"warning",
|
|
37348
37618
|
`\uBBF8\uD574\uACB0 conflict: ${conflict.reason} (${conflict.target})`,
|
|
37349
|
-
|
|
37619
|
+
path92__default.join(paths.conflictsDir, conflict.id, "meta.json")
|
|
37350
37620
|
)
|
|
37351
37621
|
);
|
|
37352
37622
|
}
|
|
@@ -37359,7 +37629,7 @@ async function runDryDock(paths, options = {}) {
|
|
|
37359
37629
|
"unresolved_conflict",
|
|
37360
37630
|
"warning",
|
|
37361
37631
|
"\uC190\uC0C1\uB41C conflict \uC5D4\uD2B8\uB9AC",
|
|
37362
|
-
|
|
37632
|
+
path92__default.join(paths.conflictsDir, conflictId, "meta.json")
|
|
37363
37633
|
)
|
|
37364
37634
|
);
|
|
37365
37635
|
}
|
|
@@ -37416,8 +37686,8 @@ async function claimIssues(paths, wikiIds) {
|
|
|
37416
37686
|
const claimsDir = getClaimsDir(paths);
|
|
37417
37687
|
for (const fileName of await listFileNames(claimsDir)) {
|
|
37418
37688
|
if (!fileName.endsWith(".json")) continue;
|
|
37419
|
-
const filePath =
|
|
37420
|
-
const entryIdFromFile =
|
|
37689
|
+
const filePath = path92__default.join(claimsDir, fileName);
|
|
37690
|
+
const entryIdFromFile = path92__default.basename(fileName, ".json");
|
|
37421
37691
|
let raw;
|
|
37422
37692
|
try {
|
|
37423
37693
|
raw = await readJsonFile2(filePath);
|
|
@@ -37496,7 +37766,7 @@ function toSemanticEntry(filePath, frontmatter, body) {
|
|
|
37496
37766
|
async function schemaIssues(paths) {
|
|
37497
37767
|
const issues = [];
|
|
37498
37768
|
const schema = await readWorkspaceSchemaSummary(paths);
|
|
37499
|
-
const agentsPath =
|
|
37769
|
+
const agentsPath = path92__default.join(paths.schemaDir, WORKSPACE_SCHEMA_AGENTS_FILENAME);
|
|
37500
37770
|
if (!await pathExists(schema.wikiSchemaPath)) {
|
|
37501
37771
|
issues.push(issue2("schema_missing", "warning", `Workspace schema file is missing: schema/${WORKSPACE_SCHEMA_FILENAME}`, schema.wikiSchemaPath));
|
|
37502
37772
|
} else {
|
|
@@ -37816,7 +38086,7 @@ function parseOptionalIsoDate(value) {
|
|
|
37816
38086
|
return Number.isFinite(timestamp) ? timestamp : null;
|
|
37817
38087
|
}
|
|
37818
38088
|
function hashBodyForComparison(body) {
|
|
37819
|
-
return
|
|
38089
|
+
return crypto3.createHash("sha256").update(body.replace(/\s+/g, " ").trim(), "utf8").digest("hex").slice(0, 8);
|
|
37820
38090
|
}
|
|
37821
38091
|
function hasConflictingStatuses(entries) {
|
|
37822
38092
|
const statuses = new Set(entries.map((entry) => entry.status).filter((status) => status !== "unknown"));
|
|
@@ -37883,7 +38153,7 @@ async function listWikiMarkdownFiles(dirPath) {
|
|
|
37883
38153
|
const files = [];
|
|
37884
38154
|
const sortedEntries = entries.sort((left, right) => left.name.localeCompare(right.name));
|
|
37885
38155
|
for (const entry of sortedEntries) {
|
|
37886
|
-
const filePath =
|
|
38156
|
+
const filePath = path92__default.join(dirPath, entry.name);
|
|
37887
38157
|
if (entry.isDirectory()) {
|
|
37888
38158
|
files.push(...await listWikiMarkdownFiles(filePath));
|
|
37889
38159
|
continue;
|
|
@@ -37965,7 +38235,7 @@ async function planIngest(input, paths, now) {
|
|
|
37965
38235
|
const target = `wiki/${input.id}.md`;
|
|
37966
38236
|
const proposer = input.proposer ?? "tool:wiki_ingest";
|
|
37967
38237
|
const currentEntry = await readWikiEntry(input.id, paths);
|
|
37968
|
-
const currentMarkdown = currentEntry ? await readPatchFile(
|
|
38238
|
+
const currentMarkdown = currentEntry ? await readPatchFile(path92__default.join(paths.wikiDir, `${input.id}.md`)) : void 0;
|
|
37969
38239
|
const currentHash = currentMarkdown ? computeContentHash(currentMarkdown) : void 0;
|
|
37970
38240
|
const rawSource = buildRawSourceEntry(input, now);
|
|
37971
38241
|
await ensureWorkspaceSchema(paths);
|
|
@@ -38644,11 +38914,11 @@ async function editQueuedPatch(input, paths) {
|
|
|
38644
38914
|
};
|
|
38645
38915
|
}
|
|
38646
38916
|
async function readQueuedPatchSnapshot(paths, patchId) {
|
|
38647
|
-
const queueDir =
|
|
38648
|
-
const markdown = await readPatchFile(
|
|
38917
|
+
const queueDir = path92__default.join(paths.queueDir, patchId);
|
|
38918
|
+
const markdown = await readPatchFile(path92__default.join(queueDir, PATCH_FILENAME));
|
|
38649
38919
|
return {
|
|
38650
38920
|
patch: await parsePatch(markdown),
|
|
38651
|
-
meta: await readJsonFile2(
|
|
38921
|
+
meta: await readJsonFile2(path92__default.join(queueDir, PATCH_META_FILENAME)),
|
|
38652
38922
|
patchHash: computeContentHash(markdown)
|
|
38653
38923
|
};
|
|
38654
38924
|
}
|
|
@@ -39404,7 +39674,7 @@ ${input.answer ?? ""}`)}`;
|
|
|
39404
39674
|
assertSafeEntryId(targetId);
|
|
39405
39675
|
const subdir = input.targetType === "synthesis" ? "synthesis" : "queries";
|
|
39406
39676
|
const target = `wiki/${subdir}/${targetId}.md`;
|
|
39407
|
-
const absoluteTarget =
|
|
39677
|
+
const absoluteTarget = path92__default.join(paths.root, target);
|
|
39408
39678
|
const exists = await pathExists(absoluteTarget);
|
|
39409
39679
|
const existingEntry = exists ? await readWikiEntry(targetId, paths) : null;
|
|
39410
39680
|
if (exists && !existingEntry) {
|
|
@@ -39486,7 +39756,7 @@ function assertSafeRawRef(rawRef) {
|
|
|
39486
39756
|
if (!rawRef.startsWith("raw/")) {
|
|
39487
39757
|
throw new Error(`[fleet-wiki] wiki_query raw source ref must point into raw/: ${rawRef}`);
|
|
39488
39758
|
}
|
|
39489
|
-
if (rawRef.includes("..") ||
|
|
39759
|
+
if (rawRef.includes("..") || path92__default.isAbsolute(rawRef)) {
|
|
39490
39760
|
throw new Error(`[fleet-wiki] wiki_query raw source ref escapes raw/: ${rawRef}`);
|
|
39491
39761
|
}
|
|
39492
39762
|
}
|
|
@@ -39605,7 +39875,7 @@ async function buildReadEntryResult(entry, paths, graph, input) {
|
|
|
39605
39875
|
rawSourceRef: entry.rawSourceRef,
|
|
39606
39876
|
rawSourceRefs,
|
|
39607
39877
|
source: {
|
|
39608
|
-
path:
|
|
39878
|
+
path: path92__default.join("wiki", `${entry.id}.md`),
|
|
39609
39879
|
rawSourceRef: entry.rawSourceRef,
|
|
39610
39880
|
rawSourceRefs
|
|
39611
39881
|
},
|
|
@@ -39731,7 +40001,7 @@ function buildRelatedEntries(entry, graph) {
|
|
|
39731
40001
|
deduped.set(candidate.id, {
|
|
39732
40002
|
id: relatedEntry.id,
|
|
39733
40003
|
title: relatedEntry.title,
|
|
39734
|
-
path:
|
|
40004
|
+
path: path92__default.join("wiki", `${relatedEntry.id}.md`),
|
|
39735
40005
|
reason: candidate.reason
|
|
39736
40006
|
});
|
|
39737
40007
|
}
|
|
@@ -40000,7 +40270,7 @@ function buildWikiToolSpec(config2, usage) {
|
|
|
40000
40270
|
}
|
|
40001
40271
|
|
|
40002
40272
|
// src/carrier-settings-routes.ts
|
|
40003
|
-
var SUBAGENT_CLI_TYPES = /* @__PURE__ */ new Set(["claude", "claude-zai", "claude-kimi"]);
|
|
40273
|
+
var SUBAGENT_CLI_TYPES = /* @__PURE__ */ new Set(["claude", "claude-zai", "claude-kimi", "claude-glm"]);
|
|
40004
40274
|
var TASKFORCE_MIN_BACKENDS = 2;
|
|
40005
40275
|
function createCarrierSettingsRouter(deps) {
|
|
40006
40276
|
const controller = createStatusOverlayController(deps.registry);
|
|
@@ -40440,13 +40710,13 @@ function safeEqual(left, right) {
|
|
|
40440
40710
|
return timingSafeEqual(leftBytes, rightBytes);
|
|
40441
40711
|
}
|
|
40442
40712
|
function workspaceHash(canonicalCwd) {
|
|
40443
|
-
return
|
|
40713
|
+
return crypto3.createHash("sha256").update(canonicalCwd).digest("hex").slice(0, 12);
|
|
40444
40714
|
}
|
|
40445
40715
|
async function canonicalizeTheaterPath(cwd) {
|
|
40446
40716
|
return canonicalizeTheaterPathSync(cwd);
|
|
40447
40717
|
}
|
|
40448
40718
|
function canonicalizeTheaterPathSync(cwd) {
|
|
40449
|
-
const resolved =
|
|
40719
|
+
const resolved = path92__default.resolve(cwd);
|
|
40450
40720
|
try {
|
|
40451
40721
|
return fs7__default.realpathSync.native(resolved);
|
|
40452
40722
|
} catch {
|
|
@@ -40454,7 +40724,7 @@ function canonicalizeTheaterPathSync(cwd) {
|
|
|
40454
40724
|
}
|
|
40455
40725
|
}
|
|
40456
40726
|
function theaterLabel(cwd) {
|
|
40457
|
-
return
|
|
40727
|
+
return path92__default.basename(cwd) || cwd;
|
|
40458
40728
|
}
|
|
40459
40729
|
|
|
40460
40730
|
// src/codex/workspaces.ts
|
|
@@ -40462,7 +40732,7 @@ var WorkspaceRegistry = class {
|
|
|
40462
40732
|
#items = /* @__PURE__ */ new Map();
|
|
40463
40733
|
#mruId = null;
|
|
40464
40734
|
async register(cwdInput, lastOpenedAt) {
|
|
40465
|
-
const cwd =
|
|
40735
|
+
const cwd = path92__default.resolve(cwdInput);
|
|
40466
40736
|
const real = await canonicalizeTheaterPath(cwd);
|
|
40467
40737
|
const paths = resolveMemoryPaths(real);
|
|
40468
40738
|
if (!await directoryExists(paths.root)) {
|
|
@@ -40478,7 +40748,7 @@ var WorkspaceRegistry = class {
|
|
|
40478
40748
|
id,
|
|
40479
40749
|
cwd,
|
|
40480
40750
|
realpath: real,
|
|
40481
|
-
label:
|
|
40751
|
+
label: path92__default.basename(cwd),
|
|
40482
40752
|
paths,
|
|
40483
40753
|
registeredAt: existing?.registeredAt ?? now,
|
|
40484
40754
|
// 복원 경로는 durable lastOpenedAt을 그대로 보존해 재시작 후에도 워크스페이스 최근성
|
|
@@ -41281,7 +41551,7 @@ function statusRank(status) {
|
|
|
41281
41551
|
|
|
41282
41552
|
// src/security-headers.ts
|
|
41283
41553
|
var CONSOLE_SECURITY_HEADERS = {
|
|
41284
|
-
"Content-Security-Policy": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss
|
|
41554
|
+
"Content-Security-Policy": "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:; connect-src 'self' ws: wss: https://api.github.com; object-src 'none'; base-uri 'none'",
|
|
41285
41555
|
"X-Content-Type-Options": "nosniff",
|
|
41286
41556
|
"Referrer-Policy": "no-referrer",
|
|
41287
41557
|
"Cache-Control": "no-store"
|
|
@@ -41533,7 +41803,7 @@ function createConsoleDurableStateStore(deps = {}) {
|
|
|
41533
41803
|
const createStore = deps.createStore ?? createDurableJsonStore;
|
|
41534
41804
|
return createStore({
|
|
41535
41805
|
filePath: paths.stateFile,
|
|
41536
|
-
lockDir:
|
|
41806
|
+
lockDir: path92__default.join(paths.dir, STATE_LOCK_DIR_NAME),
|
|
41537
41807
|
lockOwnerFileName: STATE_LOCK_OWNER_FILE_NAME,
|
|
41538
41808
|
now: deps.now,
|
|
41539
41809
|
sanitize: sanitizeDurableConsoleState,
|
|
@@ -41555,7 +41825,7 @@ function emptyDurableConsoleState() {
|
|
|
41555
41825
|
function readProviderSessionCapture(fleetSessionId, deps = {}) {
|
|
41556
41826
|
if (!isSafeCaptureId(fleetSessionId)) return null;
|
|
41557
41827
|
const capturesDir = deps.capturesDir ?? createConsoleDataPaths().capturesDir;
|
|
41558
|
-
const filePath =
|
|
41828
|
+
const filePath = path92__default.join(capturesDir, `${fleetSessionId}.json`);
|
|
41559
41829
|
try {
|
|
41560
41830
|
const parsed = JSON.parse(fs7__default.readFileSync(filePath, "utf8"));
|
|
41561
41831
|
return sanitizeProviderSession(parsed);
|
|
@@ -41578,7 +41848,7 @@ function unlinkProviderSessionCapture(fleetSessionId, deps = {}) {
|
|
|
41578
41848
|
if (!isSafeCaptureId(fleetSessionId)) return false;
|
|
41579
41849
|
const capturesDir = deps.capturesDir ?? createConsoleDataPaths().capturesDir;
|
|
41580
41850
|
try {
|
|
41581
|
-
fs7__default.unlinkSync(
|
|
41851
|
+
fs7__default.unlinkSync(path92__default.join(capturesDir, `${fleetSessionId}.json`));
|
|
41582
41852
|
return true;
|
|
41583
41853
|
} catch {
|
|
41584
41854
|
return false;
|
|
@@ -41627,6 +41897,9 @@ function sanitizeDurableOperation(value) {
|
|
|
41627
41897
|
const sequence = readPositiveInteger(value.sequence);
|
|
41628
41898
|
const createdAt = readFiniteNumber(value.createdAt);
|
|
41629
41899
|
if (!sessionId || !theaterId || !cwd || !cwdLabel || sequence === null || createdAt === null) return null;
|
|
41900
|
+
const label = readOptionalString(value.label);
|
|
41901
|
+
const labelSource = readLabelSource(value.labelSource);
|
|
41902
|
+
const autoNamePromptSeen = value.autoNamePromptSeen === true || labelSource === "auto" && label !== void 0;
|
|
41630
41903
|
const providerSession = sanitizeProviderSession(value.providerSession);
|
|
41631
41904
|
return {
|
|
41632
41905
|
sessionId,
|
|
@@ -41634,7 +41907,9 @@ function sanitizeDurableOperation(value) {
|
|
|
41634
41907
|
cwd,
|
|
41635
41908
|
cwdLabel,
|
|
41636
41909
|
sequence,
|
|
41637
|
-
...
|
|
41910
|
+
...label ? { label } : {},
|
|
41911
|
+
...labelSource ? { labelSource } : {},
|
|
41912
|
+
...autoNamePromptSeen ? { autoNamePromptSeen: true } : {},
|
|
41638
41913
|
...readOptionalString(value.cliId) ? { cliId: readOptionalString(value.cliId) } : {},
|
|
41639
41914
|
...readOptionalString(value.cliLabel) ? { cliLabel: readOptionalString(value.cliLabel) } : {},
|
|
41640
41915
|
createdAt,
|
|
@@ -41659,7 +41934,7 @@ function isRecord4(value) {
|
|
|
41659
41934
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
41660
41935
|
}
|
|
41661
41936
|
function isSafeCaptureId(value) {
|
|
41662
|
-
return value.length > 0 &&
|
|
41937
|
+
return value.length > 0 && path92__default.basename(value) === value && !value.includes(path92__default.sep) && !value.includes(path92__default.posix.sep);
|
|
41663
41938
|
}
|
|
41664
41939
|
function readNonEmptyString(value) {
|
|
41665
41940
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
@@ -41667,6 +41942,9 @@ function readNonEmptyString(value) {
|
|
|
41667
41942
|
function readOptionalString(value) {
|
|
41668
41943
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
41669
41944
|
}
|
|
41945
|
+
function readLabelSource(value) {
|
|
41946
|
+
return value === "user" || value === "auto" ? value : void 0;
|
|
41947
|
+
}
|
|
41670
41948
|
function readPositiveInteger(value) {
|
|
41671
41949
|
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : null;
|
|
41672
41950
|
}
|
|
@@ -41674,6 +41952,69 @@ function readFiniteNumber(value) {
|
|
|
41674
41952
|
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
41675
41953
|
}
|
|
41676
41954
|
|
|
41955
|
+
// src/auto-name.ts
|
|
41956
|
+
var MAX_LABEL_LENGTH = 60;
|
|
41957
|
+
var MIN_LABEL_LENGTH = 4;
|
|
41958
|
+
var MAX_SCAN_LINES = 6;
|
|
41959
|
+
var SECRET_MIN_TOKEN_LENGTH = 24;
|
|
41960
|
+
var CODE_FENCE_PATTERN = /^(```|~~~)/;
|
|
41961
|
+
var MARKER_PREFIX_PATTERN = /^([>#]+|[-*+]|\d+[.)])\s+/;
|
|
41962
|
+
var WRAPPER_TRIM_PATTERN = /^[*_`~]+|[*_`~]+$/g;
|
|
41963
|
+
var CONTROL_CHAR_PATTERN2 = new RegExp("[\\u0000-\\u001F\\u007F]", "g");
|
|
41964
|
+
var WHITESPACE_RUN_PATTERN = /\s+/g;
|
|
41965
|
+
var TRAILING_PUNCT_PATTERN = /[.,;:!?)\]}'"]+$/;
|
|
41966
|
+
var URL_PATTERN = /(https?:\/\/|ftp:\/\/|www\.)/i;
|
|
41967
|
+
var PATH_PATTERN = /(^|\s)(\/[^\s/]|~\/|\.{1,2}\/|[a-zA-Z]:[\\/])/;
|
|
41968
|
+
var LOW_SIGNAL_PATTERN = /^(continue|계속|진행|다음|next|ok|okay|go|run|yes|yep|sure|y|n|no|네|응|예|그래|stop|wait|hold on|fix it|do it|please|thanks?|thank you)$/i;
|
|
41969
|
+
var SECRET_PREFIX_PATTERN = /^(ghp_|gho_|ghs_|ghu_|ghr_|github_pat_|sk-|sk_live_|sk_test_|pk-|rk-|xox[baprs]-|AKIA|ASIA|AIza|ya29\.|glpat-|eyJ)/;
|
|
41970
|
+
var SECRET_CHARSET_PATTERN = /^[A-Za-z0-9_\-+/=.]+$/;
|
|
41971
|
+
function deriveOperationLabel(prompt) {
|
|
41972
|
+
if (typeof prompt !== "string" || prompt.length === 0) return null;
|
|
41973
|
+
const lines = prompt.split(/\r?\n/);
|
|
41974
|
+
let examined = 0;
|
|
41975
|
+
let inFence = false;
|
|
41976
|
+
for (const rawLine of lines) {
|
|
41977
|
+
const trimmed = rawLine.trim();
|
|
41978
|
+
if (trimmed.length === 0) continue;
|
|
41979
|
+
if (CODE_FENCE_PATTERN.test(trimmed)) {
|
|
41980
|
+
inFence = !inFence;
|
|
41981
|
+
continue;
|
|
41982
|
+
}
|
|
41983
|
+
if (inFence) continue;
|
|
41984
|
+
examined += 1;
|
|
41985
|
+
if (examined > MAX_SCAN_LINES) break;
|
|
41986
|
+
const candidate = normalizeLine(trimmed);
|
|
41987
|
+
if (candidate !== null) return candidate;
|
|
41988
|
+
}
|
|
41989
|
+
return null;
|
|
41990
|
+
}
|
|
41991
|
+
function normalizeLine(line) {
|
|
41992
|
+
let value = line.replace(CONTROL_CHAR_PATTERN2, " ").replace(WHITESPACE_RUN_PATTERN, " ").trim();
|
|
41993
|
+
for (let depth = 0; depth < 4; depth += 1) {
|
|
41994
|
+
const before = value;
|
|
41995
|
+
value = value.replace(MARKER_PREFIX_PATTERN, "").trim();
|
|
41996
|
+
value = value.replace(WRAPPER_TRIM_PATTERN, "").trim();
|
|
41997
|
+
if (value === before) break;
|
|
41998
|
+
}
|
|
41999
|
+
if (value.length === 0) return null;
|
|
42000
|
+
if (value.startsWith("/")) return null;
|
|
42001
|
+
if (URL_PATTERN.test(value)) return null;
|
|
42002
|
+
if (PATH_PATTERN.test(value)) return null;
|
|
42003
|
+
if (hasSecretToken(value)) return null;
|
|
42004
|
+
if (LOW_SIGNAL_PATTERN.test(value)) return null;
|
|
42005
|
+
if (value.length < MIN_LABEL_LENGTH) return null;
|
|
42006
|
+
return value.length > MAX_LABEL_LENGTH ? value.slice(0, MAX_LABEL_LENGTH).trimEnd() : value;
|
|
42007
|
+
}
|
|
42008
|
+
function hasSecretToken(value) {
|
|
42009
|
+
return value.split(/\s+/).some(looksSecretToken);
|
|
42010
|
+
}
|
|
42011
|
+
function looksSecretToken(rawToken) {
|
|
42012
|
+
const token = rawToken.replace(TRAILING_PUNCT_PATTERN, "");
|
|
42013
|
+
if (token.length === 0) return false;
|
|
42014
|
+
if (SECRET_PREFIX_PATTERN.test(token)) return true;
|
|
42015
|
+
return token.length >= SECRET_MIN_TOKEN_LENGTH && SECRET_CHARSET_PATTERN.test(token) && /[0-9]/.test(token) && /[A-Za-z]/.test(token);
|
|
42016
|
+
}
|
|
42017
|
+
|
|
41677
42018
|
// src/global-settings-routes.ts
|
|
41678
42019
|
function createGlobalSettingsRouter(deps) {
|
|
41679
42020
|
return async function handleGlobalSettingsRoute(context) {
|
|
@@ -41740,6 +42081,259 @@ function isJsonRequest3(req) {
|
|
|
41740
42081
|
const contentType = req.headers["content-type"];
|
|
41741
42082
|
return typeof contentType === "string" && contentType.toLowerCase().split(";")[0]?.trim() === "application/json";
|
|
41742
42083
|
}
|
|
42084
|
+
var BINARY_DISPLAY_NAMES = {
|
|
42085
|
+
claude: "Claude Code",
|
|
42086
|
+
codex: "Codex CLI",
|
|
42087
|
+
opencode: "OpenCode",
|
|
42088
|
+
"cursor-agent": "Cursor Agent"
|
|
42089
|
+
};
|
|
42090
|
+
var OVERRIDE_ENV_BY_COMMAND = {
|
|
42091
|
+
claude: "CLAUDE_BIN",
|
|
42092
|
+
codex: "CODEX_BIN"
|
|
42093
|
+
};
|
|
42094
|
+
var VERSION_PROBE_TIMEOUT_MS = 5e3;
|
|
42095
|
+
var SEMVER_PATTERN = /(\d+\.\d+\.\d+)/;
|
|
42096
|
+
function createAgentCliDetector(deps) {
|
|
42097
|
+
return {
|
|
42098
|
+
detect: async () => {
|
|
42099
|
+
const commands = distinctBinaryCommands();
|
|
42100
|
+
return Promise.all(commands.map((command2) => detectOne(command2, deps)));
|
|
42101
|
+
}
|
|
42102
|
+
};
|
|
42103
|
+
}
|
|
42104
|
+
function createDefaultAgentCliDetector() {
|
|
42105
|
+
return createAgentCliDetector({
|
|
42106
|
+
resolve: (command2) => resolveCommandWithOverride(command2, process.env),
|
|
42107
|
+
runVersion: (bin, args) => execFileVersion(bin, args)
|
|
42108
|
+
});
|
|
42109
|
+
}
|
|
42110
|
+
function resolveCommandWithOverride(command2, env) {
|
|
42111
|
+
const overrideName = OVERRIDE_ENV_BY_COMMAND[command2];
|
|
42112
|
+
const override = overrideName ? env[overrideName] : void 0;
|
|
42113
|
+
if (override && override.trim().length > 0) {
|
|
42114
|
+
return resolvePathBinary(override, env);
|
|
42115
|
+
}
|
|
42116
|
+
return resolvePathBinary(command2, env);
|
|
42117
|
+
}
|
|
42118
|
+
function distinctBinaryCommands() {
|
|
42119
|
+
const seen = /* @__PURE__ */ new Set();
|
|
42120
|
+
const commands = [];
|
|
42121
|
+
for (const backend of Object.values(CLI_BACKENDS)) {
|
|
42122
|
+
if (!seen.has(backend.cliCommand)) {
|
|
42123
|
+
seen.add(backend.cliCommand);
|
|
42124
|
+
commands.push(backend.cliCommand);
|
|
42125
|
+
}
|
|
42126
|
+
}
|
|
42127
|
+
return commands;
|
|
42128
|
+
}
|
|
42129
|
+
async function detectOne(command2, deps) {
|
|
42130
|
+
const resolved = deps.resolve(command2);
|
|
42131
|
+
const available = resolved !== void 0;
|
|
42132
|
+
let version2 = null;
|
|
42133
|
+
if (resolved) {
|
|
42134
|
+
version2 = await probeVersionSafe(resolved, deps);
|
|
42135
|
+
}
|
|
42136
|
+
return {
|
|
42137
|
+
id: command2,
|
|
42138
|
+
displayName: BINARY_DISPLAY_NAMES[command2] ?? command2,
|
|
42139
|
+
available,
|
|
42140
|
+
version: version2
|
|
42141
|
+
};
|
|
42142
|
+
}
|
|
42143
|
+
async function probeVersionSafe(resolved, deps) {
|
|
42144
|
+
try {
|
|
42145
|
+
const output = await deps.runVersion(resolved.bin, [...resolved.prefixArgs, "--version"]);
|
|
42146
|
+
return output.match(SEMVER_PATTERN)?.[1] ?? null;
|
|
42147
|
+
} catch {
|
|
42148
|
+
return null;
|
|
42149
|
+
}
|
|
42150
|
+
}
|
|
42151
|
+
function execFileVersion(bin, args) {
|
|
42152
|
+
return new Promise((resolve, reject) => {
|
|
42153
|
+
execFile(
|
|
42154
|
+
bin,
|
|
42155
|
+
[...args],
|
|
42156
|
+
{ encoding: "utf-8", timeout: VERSION_PROBE_TIMEOUT_MS, windowsHide: true },
|
|
42157
|
+
(error51, stdout, stderr) => {
|
|
42158
|
+
if (error51) {
|
|
42159
|
+
reject(error51);
|
|
42160
|
+
return;
|
|
42161
|
+
}
|
|
42162
|
+
resolve((stdout || stderr || "").trim());
|
|
42163
|
+
}
|
|
42164
|
+
);
|
|
42165
|
+
});
|
|
42166
|
+
}
|
|
42167
|
+
|
|
42168
|
+
// src/agent-cli-launch-metadata.ts
|
|
42169
|
+
function combineAgentCliLaunchMetadata(metadata, installStatuses, authStatuses) {
|
|
42170
|
+
const availableByCommand = new Map(installStatuses.map((entry) => [entry.id, entry.available]));
|
|
42171
|
+
const signedInByCli = new Map(authStatuses.map((entry) => [entry.cli, entry.signedIn]));
|
|
42172
|
+
return metadata.map((meta3) => ({
|
|
42173
|
+
id: meta3.id,
|
|
42174
|
+
label: meta3.label,
|
|
42175
|
+
// claude 계열 3종은 같은 `claude` 바이너리를 공유하므로 cliCommand로 설치 여부를 판정한다.
|
|
42176
|
+
available: availableByCommand.get(CLI_BACKENDS[meta3.id].cliCommand) ?? false,
|
|
42177
|
+
// model-auth 게이트 대상(claude-kimi/glm)만 실제 로그인 상태를 반영하고,
|
|
42178
|
+
// 자체 인증 CLI(claude/codex)는 Fleet이 로그인 여부를 알 수 없으므로 게이트하지 않는다(true).
|
|
42179
|
+
signedIn: signedInByCli.has(meta3.id) ? signedInByCli.get(meta3.id) ?? false : true
|
|
42180
|
+
}));
|
|
42181
|
+
}
|
|
42182
|
+
|
|
42183
|
+
// src/agent-cli-routes.ts
|
|
42184
|
+
function createAgentCliRouter(deps) {
|
|
42185
|
+
return async function handleAgentCliRoute(context) {
|
|
42186
|
+
const { req, res, pathname } = context;
|
|
42187
|
+
if (pathname === "/agent-cli/state") {
|
|
42188
|
+
if (req.method !== "GET") {
|
|
42189
|
+
deps.writeJson(res, 405, { error: "Method not allowed" });
|
|
42190
|
+
return true;
|
|
42191
|
+
}
|
|
42192
|
+
const clis = await deps.detect();
|
|
42193
|
+
const body = { clis };
|
|
42194
|
+
deps.writeJson(res, 200, body);
|
|
42195
|
+
return true;
|
|
42196
|
+
}
|
|
42197
|
+
return false;
|
|
42198
|
+
};
|
|
42199
|
+
}
|
|
42200
|
+
|
|
42201
|
+
// src/model-auth-routes.ts
|
|
42202
|
+
var MODEL_AUTH_PROVIDERS = [
|
|
42203
|
+
{ cli: "claude-kimi", displayName: "Moonshot Kimi" },
|
|
42204
|
+
{ cli: "claude-glm", displayName: "ZhipuAI GLM" }
|
|
42205
|
+
];
|
|
42206
|
+
var UPSTREAM_FAILURE_STATUSES = /* @__PURE__ */ new Set(["timeout", "network", "server"]);
|
|
42207
|
+
function createModelAuthRouter(deps) {
|
|
42208
|
+
return async function handleModelAuthRoute(context) {
|
|
42209
|
+
const { req, res, pathname } = context;
|
|
42210
|
+
if (pathname === "/model-auth/state") {
|
|
42211
|
+
if (req.method !== "GET") {
|
|
42212
|
+
deps.writeJson(res, 405, { error: "Method not allowed" });
|
|
42213
|
+
return true;
|
|
42214
|
+
}
|
|
42215
|
+
deps.writeJson(res, 200, await buildModelAuthState(deps.authService));
|
|
42216
|
+
return true;
|
|
42217
|
+
}
|
|
42218
|
+
const cli = parseProviderPath(pathname);
|
|
42219
|
+
if (!cli) return false;
|
|
42220
|
+
const provider = MODEL_AUTH_PROVIDERS.find((entry) => entry.cli === cli);
|
|
42221
|
+
if (!provider) {
|
|
42222
|
+
deps.writeJson(res, 404, { error: "provider_not_found" });
|
|
42223
|
+
return true;
|
|
42224
|
+
}
|
|
42225
|
+
if (req.method === "PUT") {
|
|
42226
|
+
await signInProvider(req, res, deps, provider);
|
|
42227
|
+
return true;
|
|
42228
|
+
}
|
|
42229
|
+
if (req.method === "DELETE") {
|
|
42230
|
+
await signOutProvider(req, res, deps, provider);
|
|
42231
|
+
return true;
|
|
42232
|
+
}
|
|
42233
|
+
deps.writeJson(res, 405, { error: "Method not allowed" });
|
|
42234
|
+
return true;
|
|
42235
|
+
};
|
|
42236
|
+
}
|
|
42237
|
+
async function buildModelAuthState(authService) {
|
|
42238
|
+
const signedInIds = new Set(await authService.listProviderIds());
|
|
42239
|
+
return {
|
|
42240
|
+
providers: MODEL_AUTH_PROVIDERS.map((provider) => toProviderState(provider, signedInIds))
|
|
42241
|
+
};
|
|
42242
|
+
}
|
|
42243
|
+
async function signInProvider(req, res, deps, provider) {
|
|
42244
|
+
if (!deps.isAuthorized(req)) {
|
|
42245
|
+
deps.writeJson(res, 401, { error: "unauthorized" });
|
|
42246
|
+
return;
|
|
42247
|
+
}
|
|
42248
|
+
if (!isJsonRequest4(req)) {
|
|
42249
|
+
deps.writeJson(res, 415, { error: "unsupported_media_type" });
|
|
42250
|
+
return;
|
|
42251
|
+
}
|
|
42252
|
+
const body = await deps.readJsonBody(req);
|
|
42253
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
42254
|
+
deps.writeJson(res, 400, { error: "invalid_json" });
|
|
42255
|
+
return;
|
|
42256
|
+
}
|
|
42257
|
+
const apiKey = typeof body.apiKey === "string" ? body.apiKey.trim() : "";
|
|
42258
|
+
if (apiKey.length === 0) {
|
|
42259
|
+
deps.writeJson(res, 400, { error: "invalid_api_key" });
|
|
42260
|
+
return;
|
|
42261
|
+
}
|
|
42262
|
+
const providerId = CLI_TO_AUTH_PROVIDER_ID[provider.cli];
|
|
42263
|
+
if (!providerId) {
|
|
42264
|
+
deps.writeJson(res, 500, { error: "provider_unavailable" });
|
|
42265
|
+
return;
|
|
42266
|
+
}
|
|
42267
|
+
const validation = await deps.validateApiKey(provider.cli, apiKey);
|
|
42268
|
+
if (validation.status !== "success") {
|
|
42269
|
+
const status = UPSTREAM_FAILURE_STATUSES.has(validation.status) ? 502 : 400;
|
|
42270
|
+
deps.writeJson(res, status, {
|
|
42271
|
+
error: formatSignInFailureMessage(provider.displayName, validation.status),
|
|
42272
|
+
status: validation.status
|
|
42273
|
+
});
|
|
42274
|
+
return;
|
|
42275
|
+
}
|
|
42276
|
+
await deps.authService.setApiKey(providerId, apiKey);
|
|
42277
|
+
await writeMutationState2(res, deps);
|
|
42278
|
+
}
|
|
42279
|
+
async function signOutProvider(req, res, deps, provider) {
|
|
42280
|
+
if (!deps.isAuthorized(req)) {
|
|
42281
|
+
deps.writeJson(res, 401, { error: "unauthorized" });
|
|
42282
|
+
return;
|
|
42283
|
+
}
|
|
42284
|
+
const providerId = CLI_TO_AUTH_PROVIDER_ID[provider.cli];
|
|
42285
|
+
if (!providerId) {
|
|
42286
|
+
deps.writeJson(res, 500, { error: "provider_unavailable" });
|
|
42287
|
+
return;
|
|
42288
|
+
}
|
|
42289
|
+
await deps.authService.deleteApiKey(providerId);
|
|
42290
|
+
await writeMutationState2(res, deps);
|
|
42291
|
+
}
|
|
42292
|
+
async function writeMutationState2(res, deps) {
|
|
42293
|
+
const response = { state: await buildModelAuthState(deps.authService) };
|
|
42294
|
+
deps.writeJson(res, 200, response);
|
|
42295
|
+
}
|
|
42296
|
+
function toProviderState(provider, signedInIds) {
|
|
42297
|
+
const providerId = CLI_TO_AUTH_PROVIDER_ID[provider.cli] ?? provider.cli;
|
|
42298
|
+
return {
|
|
42299
|
+
cli: provider.cli,
|
|
42300
|
+
displayName: provider.displayName,
|
|
42301
|
+
signedIn: signedInIds.has(providerId)
|
|
42302
|
+
};
|
|
42303
|
+
}
|
|
42304
|
+
function parseProviderPath(pathname) {
|
|
42305
|
+
const parts = pathname.split("/").filter(Boolean);
|
|
42306
|
+
if (parts.length !== 3 || parts[0] !== "model-auth" || parts[1] !== "providers") return null;
|
|
42307
|
+
const cli = safeDecodeURIComponent2(parts[2] ?? "");
|
|
42308
|
+
return cli ? cli : null;
|
|
42309
|
+
}
|
|
42310
|
+
function safeDecodeURIComponent2(value) {
|
|
42311
|
+
try {
|
|
42312
|
+
return decodeURIComponent(value);
|
|
42313
|
+
} catch {
|
|
42314
|
+
return null;
|
|
42315
|
+
}
|
|
42316
|
+
}
|
|
42317
|
+
function isJsonRequest4(req) {
|
|
42318
|
+
const contentType = req.headers["content-type"];
|
|
42319
|
+
return typeof contentType === "string" && contentType.toLowerCase().split(";")[0]?.trim() === "application/json";
|
|
42320
|
+
}
|
|
42321
|
+
function formatSignInFailureMessage(displayName, status) {
|
|
42322
|
+
switch (status) {
|
|
42323
|
+
case "unauthorized":
|
|
42324
|
+
return `${displayName} rejected the API key. Check the key and try again.`;
|
|
42325
|
+
case "forbidden":
|
|
42326
|
+
return `The API key is not allowed for ${displayName}. Check its permissions.`;
|
|
42327
|
+
case "timeout":
|
|
42328
|
+
return `Validating the ${displayName} API key timed out. Check your connection and try again.`;
|
|
42329
|
+
case "network":
|
|
42330
|
+
return `Could not reach ${displayName} to validate the API key. Check your connection and try again.`;
|
|
42331
|
+
case "server":
|
|
42332
|
+
return `${displayName} returned an error while validating the API key. Try again later.`;
|
|
42333
|
+
default:
|
|
42334
|
+
return `Could not validate the ${displayName} API key. Check the key and try again.`;
|
|
42335
|
+
}
|
|
42336
|
+
}
|
|
41743
42337
|
|
|
41744
42338
|
// src/observability-routes.ts
|
|
41745
42339
|
function writeObserverEvents(req, res, workspace, store2) {
|
|
@@ -41779,10 +42373,14 @@ function writeAggregateObserverEvents(req, res, workspaces, store2, resolveWorks
|
|
|
41779
42373
|
}
|
|
41780
42374
|
const unsubscribers = options.subscribeAll ? [
|
|
41781
42375
|
store2.subscribeAll((event) => {
|
|
41782
|
-
if (isSessionUpdatedEvent(event)
|
|
42376
|
+
if (isSessionUpdatedEvent(event)) {
|
|
41783
42377
|
writeEvent(res, 0, event.type, { session: event.session });
|
|
41784
42378
|
return;
|
|
41785
42379
|
}
|
|
42380
|
+
if (isSessionAttentionEvent(event)) {
|
|
42381
|
+
writeEvent(res, 0, event.type, { session: event.session, reason: event.reason });
|
|
42382
|
+
return;
|
|
42383
|
+
}
|
|
41786
42384
|
writeEvent(res, event.id, event.type, { tenant: resolvedWorkspaceSnapshot(resolveWorkspace, event.tenantId), event });
|
|
41787
42385
|
})
|
|
41788
42386
|
] : workspaces.map(
|
|
@@ -41932,7 +42530,7 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
41932
42530
|
return terminalSessionsById.get(sessionId)?.cwd ?? workspacesByCliRunId.get(sessionId)?.session.cwd ?? null;
|
|
41933
42531
|
}
|
|
41934
42532
|
function createPendingTerminalSession(input) {
|
|
41935
|
-
if (!
|
|
42533
|
+
if (!path92__default.isAbsolute(input.cwd)) throw new Error("Terminal session cwd must be absolute");
|
|
41936
42534
|
const createdAt = input.createdAt ?? now();
|
|
41937
42535
|
const canonicalCwd = canonicalizeTheaterPathSync(input.cwd);
|
|
41938
42536
|
const theaterId = workspaceHash(canonicalCwd);
|
|
@@ -41942,7 +42540,7 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
41942
42540
|
sessionId: input.sessionId,
|
|
41943
42541
|
cwd: input.cwd,
|
|
41944
42542
|
canonicalCwd,
|
|
41945
|
-
cwdLabel:
|
|
42543
|
+
cwdLabel: path92__default.basename(input.cwd) || input.cwd,
|
|
41946
42544
|
sequence,
|
|
41947
42545
|
cliId: input.cliId,
|
|
41948
42546
|
createdAt,
|
|
@@ -41963,6 +42561,8 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
41963
42561
|
cwdLabel: operation.cwdLabel,
|
|
41964
42562
|
sequence: operation.sequence,
|
|
41965
42563
|
label: operation.label,
|
|
42564
|
+
labelSource: operation.labelSource,
|
|
42565
|
+
autoNamePromptSeen: operation.autoNamePromptSeen,
|
|
41966
42566
|
cliId: operation.cliId,
|
|
41967
42567
|
cliLabel: operation.cliLabel,
|
|
41968
42568
|
createdAt: operation.createdAt,
|
|
@@ -41985,6 +42585,8 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
41985
42585
|
cwdLabel: session.cwdLabel,
|
|
41986
42586
|
sequence: session.sequence,
|
|
41987
42587
|
...session.label ? { label: session.label } : {},
|
|
42588
|
+
...session.labelSource ? { labelSource: session.labelSource } : {},
|
|
42589
|
+
...session.autoNamePromptSeen ? { autoNamePromptSeen: true } : {},
|
|
41988
42590
|
...session.cliId ? { cliId: session.cliId } : {},
|
|
41989
42591
|
...session.cliLabel ? { cliLabel: session.cliLabel } : {},
|
|
41990
42592
|
createdAt: session.createdAt,
|
|
@@ -42030,11 +42632,31 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
42030
42632
|
const label = rawLabel.trim().slice(0, 200);
|
|
42031
42633
|
if (label.length === 0) {
|
|
42032
42634
|
delete session.label;
|
|
42635
|
+
delete session.labelSource;
|
|
42636
|
+
delete session.autoNamePromptSeen;
|
|
42033
42637
|
} else {
|
|
42034
42638
|
session.label = label;
|
|
42639
|
+
session.labelSource = "user";
|
|
42640
|
+
session.autoNamePromptSeen = true;
|
|
42035
42641
|
}
|
|
42036
42642
|
return toTerminalSessionInfo(session);
|
|
42037
42643
|
}
|
|
42644
|
+
function autoNameTerminalSession(sessionId, label) {
|
|
42645
|
+
const session = terminalSessionsById.get(sessionId);
|
|
42646
|
+
if (!session) return null;
|
|
42647
|
+
const effectiveSource = session.labelSource ?? (session.label ? "user" : void 0);
|
|
42648
|
+
if (effectiveSource === "user" || session.autoNamePromptSeen) {
|
|
42649
|
+
return { session: toTerminalSessionInfo(session), changed: false, renamed: false };
|
|
42650
|
+
}
|
|
42651
|
+
session.autoNamePromptSeen = true;
|
|
42652
|
+
const next = label?.trim().slice(0, 200) ?? "";
|
|
42653
|
+
if (next.length === 0 || next === session.label) {
|
|
42654
|
+
return { session: toTerminalSessionInfo(session), changed: true, renamed: false };
|
|
42655
|
+
}
|
|
42656
|
+
session.label = next;
|
|
42657
|
+
session.labelSource = "auto";
|
|
42658
|
+
return { session: toTerminalSessionInfo(session), changed: true, renamed: true };
|
|
42659
|
+
}
|
|
42038
42660
|
function notifySessionUpdated(session) {
|
|
42039
42661
|
const event = { type: "session:updated", session };
|
|
42040
42662
|
for (const listener of allListeners) listener(event);
|
|
@@ -42043,8 +42665,8 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
42043
42665
|
const session = terminalSessionsById.get(sessionId);
|
|
42044
42666
|
return session ? toTerminalSessionInfo(session) : null;
|
|
42045
42667
|
}
|
|
42046
|
-
function notifySessionAttention(session) {
|
|
42047
|
-
const event = { type: "session:attention", session };
|
|
42668
|
+
function notifySessionAttention(session, reason) {
|
|
42669
|
+
const event = { type: "session:attention", session, reason };
|
|
42048
42670
|
for (const listener of allListeners) listener(event);
|
|
42049
42671
|
}
|
|
42050
42672
|
function removeTerminalSession(sessionId) {
|
|
@@ -42085,6 +42707,7 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
42085
42707
|
notifySessionAttention,
|
|
42086
42708
|
notifySessionUpdated,
|
|
42087
42709
|
renameTerminalSession,
|
|
42710
|
+
autoNameTerminalSession,
|
|
42088
42711
|
subscribe,
|
|
42089
42712
|
subscribeAll,
|
|
42090
42713
|
updateTerminalSessionProviderSession,
|
|
@@ -42318,7 +42941,7 @@ function tryServeStaticConsole(req, res, pathname) {
|
|
|
42318
42941
|
res.end(JSON.stringify({ error: "Not found" }));
|
|
42319
42942
|
return true;
|
|
42320
42943
|
}
|
|
42321
|
-
const absolutePath =
|
|
42944
|
+
const absolutePath = path92__default.resolve(CONSOLE_ROOT, relativePath2);
|
|
42322
42945
|
if (!absolutePath.startsWith(CONSOLE_ROOT)) {
|
|
42323
42946
|
res.writeHead(404, withSecurityHeaders2({ "Content-Type": "application/json" }));
|
|
42324
42947
|
res.end(JSON.stringify({ error: "Not found" }));
|
|
@@ -42326,7 +42949,7 @@ function tryServeStaticConsole(req, res, pathname) {
|
|
|
42326
42949
|
}
|
|
42327
42950
|
try {
|
|
42328
42951
|
const data = fs7__default.readFileSync(absolutePath);
|
|
42329
|
-
const contentType = MIME_TYPES[
|
|
42952
|
+
const contentType = MIME_TYPES[path92__default.extname(absolutePath)] ?? "application/octet-stream";
|
|
42330
42953
|
res.writeHead(200, withSecurityHeaders2({ "Content-Type": contentType }));
|
|
42331
42954
|
if (req.method === "HEAD") {
|
|
42332
42955
|
res.end();
|
|
@@ -42346,7 +42969,7 @@ function tryServeStaticConsole(req, res, pathname) {
|
|
|
42346
42969
|
}
|
|
42347
42970
|
function serveFallbackIndex(req, res) {
|
|
42348
42971
|
try {
|
|
42349
|
-
const data = fs7__default.readFileSync(
|
|
42972
|
+
const data = fs7__default.readFileSync(path92__default.join(CONSOLE_ROOT, "index.html"));
|
|
42350
42973
|
res.writeHead(200, withSecurityHeaders2({ "Content-Type": MIME_TYPES[".html"] }));
|
|
42351
42974
|
if (req.method === "HEAD") {
|
|
42352
42975
|
res.end();
|
|
@@ -42372,7 +42995,7 @@ function resolveConsolePath(pathname) {
|
|
|
42372
42995
|
}
|
|
42373
42996
|
if (withoutPrefix === "") return "index.html";
|
|
42374
42997
|
if (withoutPrefix.includes("\0")) return null;
|
|
42375
|
-
if (!
|
|
42998
|
+
if (!path92__default.extname(withoutPrefix)) return "index.html";
|
|
42376
42999
|
return withoutPrefix;
|
|
42377
43000
|
}
|
|
42378
43001
|
var TerminalFolderListError = class extends Error {
|
|
@@ -42406,14 +43029,14 @@ async function listTerminalFolders(requestedPath, deps = {}) {
|
|
|
42406
43029
|
}
|
|
42407
43030
|
function normalizeFolderBrowserPath(value, platform = process.platform) {
|
|
42408
43031
|
if (typeof value !== "string" || value.length === 0 || value.includes("\0")) throw new TerminalFolderListError("invalid_path");
|
|
42409
|
-
if (isWindowsAmbiguousPath(value, platform) || !
|
|
42410
|
-
return
|
|
43032
|
+
if (isWindowsAmbiguousPath(value, platform) || !path92__default.isAbsolute(value)) throw new TerminalFolderListError("invalid_path");
|
|
43033
|
+
return path92__default.resolve(value);
|
|
42411
43034
|
}
|
|
42412
43035
|
function normalizeListPath(requestedPath, platform, deps) {
|
|
42413
43036
|
if (requestedPath === null || requestedPath === void 0) {
|
|
42414
43037
|
const home = deps.homedir?.() ?? os22__default.homedir();
|
|
42415
43038
|
const start = home || deps.cwd?.() || process.cwd();
|
|
42416
|
-
return
|
|
43039
|
+
return path92__default.resolve(start);
|
|
42417
43040
|
}
|
|
42418
43041
|
return normalizeFolderBrowserPath(requestedPath, platform);
|
|
42419
43042
|
}
|
|
@@ -42464,7 +43087,7 @@ async function openDirectory(targetPath, opendir) {
|
|
|
42464
43087
|
}
|
|
42465
43088
|
async function toTerminalFolderEntry(targetPath, dirent, stat5) {
|
|
42466
43089
|
if (!dirent.isDirectory() && !dirent.isSymbolicLink()) return null;
|
|
42467
|
-
const entryPath =
|
|
43090
|
+
const entryPath = path92__default.join(targetPath, dirent.name);
|
|
42468
43091
|
if (dirent.isDirectory()) return { name: dirent.name, path: entryPath, kind: "dir", accessible: true };
|
|
42469
43092
|
const accessible = await statSymlinkDirectory(entryPath, stat5);
|
|
42470
43093
|
if (accessible === null) return null;
|
|
@@ -42484,10 +43107,10 @@ function mapFsError(error51) {
|
|
|
42484
43107
|
return new TerminalFolderListError("invalid_path");
|
|
42485
43108
|
}
|
|
42486
43109
|
function parentPath(targetPath, platform) {
|
|
42487
|
-
const parsed =
|
|
42488
|
-
const resolved =
|
|
42489
|
-
if (resolved ===
|
|
42490
|
-
const parent =
|
|
43110
|
+
const parsed = path92__default.parse(targetPath);
|
|
43111
|
+
const resolved = path92__default.resolve(targetPath);
|
|
43112
|
+
if (resolved === path92__default.resolve(parsed.root)) return null;
|
|
43113
|
+
const parent = path92__default.dirname(resolved);
|
|
42491
43114
|
if (platform === "win32" && parent === resolved) return null;
|
|
42492
43115
|
return parent;
|
|
42493
43116
|
}
|
|
@@ -42498,14 +43121,14 @@ function isWindowsAmbiguousPath(value, platform) {
|
|
|
42498
43121
|
var GRANT_ID_BYTES = 24;
|
|
42499
43122
|
var DEFAULT_GRANT_TTL_MS = 6e4;
|
|
42500
43123
|
function createFolderGrantStore(deps = {}) {
|
|
42501
|
-
const randomId = deps.randomId ?? (() =>
|
|
42502
|
-
const
|
|
43124
|
+
const randomId = deps.randomId ?? (() => crypto3.randomBytes(GRANT_ID_BYTES).toString("base64url"));
|
|
43125
|
+
const statSync4 = deps.statSync ?? fs7__default.statSync;
|
|
42503
43126
|
const ttlMs = deps.ttlMs ?? DEFAULT_GRANT_TTL_MS;
|
|
42504
43127
|
const now = deps.now ?? Date.now;
|
|
42505
43128
|
const grants = /* @__PURE__ */ new Map();
|
|
42506
43129
|
function issue3(cwd) {
|
|
42507
43130
|
prune();
|
|
42508
|
-
const normalized = validateAbsoluteDirectory(cwd,
|
|
43131
|
+
const normalized = validateAbsoluteDirectory(cwd, statSync4);
|
|
42509
43132
|
const folderGrantId = randomId();
|
|
42510
43133
|
grants.set(folderGrantId, { cwd: normalized, expiresAt: now() + ttlMs });
|
|
42511
43134
|
return folderGrantId;
|
|
@@ -42525,11 +43148,11 @@ function createFolderGrantStore(deps = {}) {
|
|
|
42525
43148
|
}
|
|
42526
43149
|
return { issue: issue3, consume };
|
|
42527
43150
|
}
|
|
42528
|
-
function validateAbsoluteDirectory(cwd,
|
|
43151
|
+
function validateAbsoluteDirectory(cwd, statSync4 = fs7__default.statSync) {
|
|
42529
43152
|
if (typeof cwd !== "string" || cwd.length === 0 || cwd.includes("\0")) throw new Error("invalid_folder");
|
|
42530
|
-
if (isWindowsAmbiguousPath2(cwd) || !
|
|
42531
|
-
const normalized =
|
|
42532
|
-
if (!
|
|
43153
|
+
if (isWindowsAmbiguousPath2(cwd) || !path92__default.isAbsolute(cwd)) throw new Error("invalid_folder");
|
|
43154
|
+
const normalized = path92__default.resolve(cwd);
|
|
43155
|
+
if (!statSync4(normalized).isDirectory()) throw new Error("invalid_folder");
|
|
42533
43156
|
return normalized;
|
|
42534
43157
|
}
|
|
42535
43158
|
function isWindowsAmbiguousPath2(value) {
|
|
@@ -42551,8 +43174,11 @@ function buildConsoleTurnHookCommand(entry, phase) {
|
|
|
42551
43174
|
function buildConsoleAttentionHookCommand(entry) {
|
|
42552
43175
|
return buildConsoleCliHookExec(entry, ["hook", "attention"]);
|
|
42553
43176
|
}
|
|
43177
|
+
function buildConsoleAutoNameHookCommand(entry) {
|
|
43178
|
+
return buildConsoleCliHookExec(entry, ["hook", "auto-name"]);
|
|
43179
|
+
}
|
|
42554
43180
|
function buildConsoleCaptureHookCommand(entry, cliId) {
|
|
42555
|
-
const extension =
|
|
43181
|
+
const extension = path92__default.extname(entry.entryPath);
|
|
42556
43182
|
if (JAVASCRIPT_ENTRY_EXTENSIONS.has(extension)) {
|
|
42557
43183
|
return createSessionCaptureHookExec({
|
|
42558
43184
|
entryPath: entry.entryPath,
|
|
@@ -42592,11 +43218,11 @@ function runCodexCommand(command2) {
|
|
|
42592
43218
|
}
|
|
42593
43219
|
function withConsoleMarketplaceLock(target, fn) {
|
|
42594
43220
|
const lockDir = `${target}${MARKETPLACE_LOCK_DIR_SUFFIX}`;
|
|
42595
|
-
mkdirSync(
|
|
43221
|
+
mkdirSync(path92__default.dirname(lockDir), { recursive: true });
|
|
42596
43222
|
return withDirectoryLock({ lockDir }, fn);
|
|
42597
43223
|
}
|
|
42598
43224
|
function buildConsoleCliHookExec(entry, trailingArgs) {
|
|
42599
|
-
const extension =
|
|
43225
|
+
const extension = path92__default.extname(entry.entryPath);
|
|
42600
43226
|
if (JAVASCRIPT_ENTRY_EXTENSIONS.has(extension)) {
|
|
42601
43227
|
return {
|
|
42602
43228
|
command: entry.execPath,
|
|
@@ -42622,12 +43248,12 @@ var CONSOLE_ENTRY_PATH = fileURLToPath(import.meta.url);
|
|
|
42622
43248
|
var HOOK_ENTRY_EXTENSIONS = /* @__PURE__ */ new Set([".cjs", ".cts", ".js", ".mjs", ".mts", ".ts", ".tsx"]);
|
|
42623
43249
|
var require2 = createRequire(import.meta.url);
|
|
42624
43250
|
function createDefaultTerminalLaunchResolver(deps = {}) {
|
|
42625
|
-
const baseCwd = deps.cwd ??
|
|
42626
|
-
const env = deps.env ??
|
|
42627
|
-
const execPath = deps.execPath ??
|
|
43251
|
+
const baseCwd = deps.cwd ?? process9.cwd();
|
|
43252
|
+
const env = deps.env ?? process9.env;
|
|
43253
|
+
const execPath = deps.execPath ?? process9.execPath;
|
|
42628
43254
|
const homedir3 = deps.homedir ?? DEFAULT_TERMINAL_CWD_FALLBACK;
|
|
42629
|
-
const platform = deps.platform ??
|
|
42630
|
-
const entryPath = resolveHookEntryPath(deps.entryPath ??
|
|
43255
|
+
const platform = deps.platform ?? process9.platform;
|
|
43256
|
+
const entryPath = resolveHookEntryPath(deps.entryPath ?? process9.argv[1]);
|
|
42631
43257
|
const tsxLoaderPath = deps.tsxLoaderPath ?? resolveOptionalPackage("tsx");
|
|
42632
43258
|
const dataDir = deps.dataDir ?? getFleetDataDir();
|
|
42633
43259
|
const infraServices = deps.infraServices ?? createInfraServices();
|
|
@@ -42684,11 +43310,11 @@ function resolveHookEntryPath(candidate) {
|
|
|
42684
43310
|
return CONSOLE_ENTRY_PATH;
|
|
42685
43311
|
}
|
|
42686
43312
|
function hasHookEntryExtension(entryPath) {
|
|
42687
|
-
return HOOK_ENTRY_EXTENSIONS.has(
|
|
43313
|
+
return HOOK_ENTRY_EXTENSIONS.has(path92__default.extname(entryPath));
|
|
42688
43314
|
}
|
|
42689
43315
|
function startTerminalShell(launch, size) {
|
|
42690
43316
|
const { spawn: spawnPty } = require2("node-pty");
|
|
42691
|
-
const useConptyDll = resolveUseConptyDll(
|
|
43317
|
+
const useConptyDll = resolveUseConptyDll(process9.platform, process9.env);
|
|
42692
43318
|
return spawnPty(launch.bin, [...launch.args], {
|
|
42693
43319
|
cols: size.cols,
|
|
42694
43320
|
rows: size.rows,
|
|
@@ -42728,6 +43354,7 @@ async function createAgentCliLaunchSpec(options) {
|
|
|
42728
43354
|
turnStartHookExec: buildConsoleTurnHookCommand(options.hookEntry, "start"),
|
|
42729
43355
|
turnEndHookExec: buildConsoleTurnHookCommand(options.hookEntry, "end"),
|
|
42730
43356
|
inputWaitingHookExec: buildConsoleAttentionHookCommand(options.hookEntry),
|
|
43357
|
+
autoNameHookExec: buildConsoleAutoNameHookCommand(options.hookEntry),
|
|
42731
43358
|
hookExec: buildConsoleHookCommand(options.hookEntry),
|
|
42732
43359
|
onCleanup: (cleanup) => cleanupStack.push(cleanup),
|
|
42733
43360
|
replaceSystemPrompt: globalSettings.replaceSystemPrompt,
|
|
@@ -42861,6 +43488,9 @@ function createTerminalSessionManager(deps) {
|
|
|
42861
43488
|
socket.on("message", (data, isBinary) => handleSocketMessage(session, data, isBinary));
|
|
42862
43489
|
socket.once("close", () => detachSocket(session, socket));
|
|
42863
43490
|
}
|
|
43491
|
+
function hasLiveSessions() {
|
|
43492
|
+
return sessions.size > 0 || pendingSessions.size > 0;
|
|
43493
|
+
}
|
|
42864
43494
|
async function createSession(context) {
|
|
42865
43495
|
await getOrCreateSession(context);
|
|
42866
43496
|
}
|
|
@@ -43002,7 +43632,7 @@ function createTerminalSessionManager(deps) {
|
|
|
43002
43632
|
await runLaunchCleanup(session.cleanup);
|
|
43003
43633
|
}
|
|
43004
43634
|
}
|
|
43005
|
-
return { canAttach, createSession, attach, getSessionMessagePolicy, getSessionRenameCommand, terminate, stop, writeToSession };
|
|
43635
|
+
return { canAttach, createSession, attach, hasLiveSessions, getSessionMessagePolicy, getSessionRenameCommand, terminate, stop, writeToSession };
|
|
43006
43636
|
}
|
|
43007
43637
|
async function runLaunchCleanup(cleanup) {
|
|
43008
43638
|
try {
|
|
@@ -43040,7 +43670,7 @@ var DEFAULT_TICKET_TTL_MS = 1e4;
|
|
|
43040
43670
|
function createTerminalTicketRegistry(deps = {}) {
|
|
43041
43671
|
const ttlMs = deps.ttlMs ?? DEFAULT_TICKET_TTL_MS;
|
|
43042
43672
|
const now = deps.now ?? Date.now;
|
|
43043
|
-
const randomTicket = deps.randomTicket ?? (() =>
|
|
43673
|
+
const randomTicket = deps.randomTicket ?? (() => crypto3.randomBytes(32).toString("base64url"));
|
|
43044
43674
|
const tickets = /* @__PURE__ */ new Map();
|
|
43045
43675
|
function issue3(context) {
|
|
43046
43676
|
prune();
|
|
@@ -43212,7 +43842,7 @@ var TheaterRegistry = class {
|
|
|
43212
43842
|
#items = /* @__PURE__ */ new Map();
|
|
43213
43843
|
#mruId = null;
|
|
43214
43844
|
async register(cwd) {
|
|
43215
|
-
const resolved =
|
|
43845
|
+
const resolved = path92__default.resolve(cwd);
|
|
43216
43846
|
const real = await canonicalizeTheaterPath(resolved);
|
|
43217
43847
|
const id = workspaceHash(real);
|
|
43218
43848
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -43267,6 +43897,383 @@ var TheaterRegistry = class {
|
|
|
43267
43897
|
return removed;
|
|
43268
43898
|
}
|
|
43269
43899
|
};
|
|
43900
|
+
var PACKAGE_NAMES = ["@dotobokuri/fleet-cli", "@dotobokuri/fleet-console"];
|
|
43901
|
+
var WORKER_FILE_PREFIX = "fleet-console-update-";
|
|
43902
|
+
var WORKER_FILE_SUFFIX = ".mjs";
|
|
43903
|
+
var STATUS_FILE_SUFFIX = ".status.json";
|
|
43904
|
+
var LOG_FILE_SUFFIX = ".log";
|
|
43905
|
+
var TEMP_FILE_MODE = 384;
|
|
43906
|
+
function createConsoleUpdateApplyService(deps = {}) {
|
|
43907
|
+
const env = deps.env ?? process9.env;
|
|
43908
|
+
const execPath = deps.execPath ?? process9.execPath;
|
|
43909
|
+
const makeDir = deps.makeDir ?? ((dirPath, options) => {
|
|
43910
|
+
fs7__default.mkdirSync(dirPath, options);
|
|
43911
|
+
});
|
|
43912
|
+
const now = deps.now ?? Date.now;
|
|
43913
|
+
const processPid = deps.processPid ?? process9.pid;
|
|
43914
|
+
const preflightInstall = deps.preflightInstall ?? ((currentPackageRoot) => preflightPackageManager(currentPackageRoot, env));
|
|
43915
|
+
const serverModulePath = deps.serverModulePath ?? resolveDefaultServerModulePath();
|
|
43916
|
+
const spawnWorker = deps.spawnWorker ?? defaultSpawnWorker;
|
|
43917
|
+
const tmpDir = deps.tmpDir ?? os22__default.tmpdir();
|
|
43918
|
+
const writeFile4 = deps.writeFile ?? ((filePath, content, options) => {
|
|
43919
|
+
fs7__default.writeFileSync(filePath, content, { mode: options.mode });
|
|
43920
|
+
});
|
|
43921
|
+
async function start(request) {
|
|
43922
|
+
const packageManager = await preflightInstall(request.currentPackageRoot);
|
|
43923
|
+
const stamp = `${now()}-${processPid}`;
|
|
43924
|
+
const workerPath = path92__default.join(tmpDir, `${WORKER_FILE_PREFIX}${stamp}${WORKER_FILE_SUFFIX}`);
|
|
43925
|
+
makeDir(request.dataDir, { recursive: true, mode: 448 });
|
|
43926
|
+
const statusFile = path92__default.join(request.dataDir, `${WORKER_FILE_PREFIX}${stamp}${STATUS_FILE_SUFFIX}`);
|
|
43927
|
+
const logFile = path92__default.join(request.dataDir, `${WORKER_FILE_PREFIX}${stamp}${LOG_FILE_SUFFIX}`);
|
|
43928
|
+
const script = emitConsoleUpdateWorkerScript({
|
|
43929
|
+
currentEndpoint: request.currentEndpoint,
|
|
43930
|
+
currentPackageRoot: request.currentPackageRoot,
|
|
43931
|
+
currentPid: request.currentPid,
|
|
43932
|
+
lockFile: request.lockFile,
|
|
43933
|
+
logFile,
|
|
43934
|
+
packageManager,
|
|
43935
|
+
packageNames: PACKAGE_NAMES,
|
|
43936
|
+
serverModulePath,
|
|
43937
|
+
statusFile,
|
|
43938
|
+
targetVersion: request.targetVersion,
|
|
43939
|
+
workerPath
|
|
43940
|
+
});
|
|
43941
|
+
writeFile4(workerPath, script, { mode: TEMP_FILE_MODE });
|
|
43942
|
+
await spawnDetachedWorker(spawnWorker, execPath, [workerPath], env);
|
|
43943
|
+
return { accepted: true };
|
|
43944
|
+
}
|
|
43945
|
+
return { start };
|
|
43946
|
+
}
|
|
43947
|
+
function emitConsoleUpdateWorkerScript(config2) {
|
|
43948
|
+
return `import { execFileSync, spawn } from "node:child_process";
|
|
43949
|
+
import fs from "node:fs";
|
|
43950
|
+
import os from "node:os";
|
|
43951
|
+
import path from "node:path";
|
|
43952
|
+
|
|
43953
|
+
const config = ${JSON.stringify(config2)};
|
|
43954
|
+
const stalePrefix = ${JSON.stringify(WORKER_FILE_PREFIX)};
|
|
43955
|
+
const workerSuffix = ${JSON.stringify(WORKER_FILE_SUFFIX)};
|
|
43956
|
+
const stopTimeoutMs = 60000;
|
|
43957
|
+
const startTimeoutMs = 60000;
|
|
43958
|
+
const sleepMs = 250;
|
|
43959
|
+
|
|
43960
|
+
async function main() {
|
|
43961
|
+
writeStatus("starting");
|
|
43962
|
+
cleanupStaleWorkers();
|
|
43963
|
+
const manager = detectPackageManager();
|
|
43964
|
+
ensureGlobalRootWritable(manager);
|
|
43965
|
+
writeStatus("preflight-ok", { manager: manager.command });
|
|
43966
|
+
await stopCurrentConsole();
|
|
43967
|
+
await waitForOldConsoleExit();
|
|
43968
|
+
writeStatus("installing", { manager: manager.command });
|
|
43969
|
+
await installPackages(manager);
|
|
43970
|
+
writeStatus("starting-daemon");
|
|
43971
|
+
const lock = await startNewDaemon();
|
|
43972
|
+
openBrowser(new URL("console/", lock.endpoint).toString());
|
|
43973
|
+
writeStatus("completed");
|
|
43974
|
+
}
|
|
43975
|
+
|
|
43976
|
+
main()
|
|
43977
|
+
.catch((error) => {
|
|
43978
|
+
writeStatus("failed", { error: sanitizeError(error) });
|
|
43979
|
+
log("failed: " + sanitizeError(error));
|
|
43980
|
+
process.exitCode = 1;
|
|
43981
|
+
})
|
|
43982
|
+
.finally(() => {
|
|
43983
|
+
try {
|
|
43984
|
+
fs.rmSync(config.workerPath, { force: true });
|
|
43985
|
+
} catch {
|
|
43986
|
+
// \uC790\uAC00 \uC815\uB9AC\uB294 \uC2E4\uD328\uD574\uB3C4 \uC5C5\uB370\uC774\uD2B8 \uACB0\uACFC\uB97C \uB9C9\uC9C0 \uC54A\uB294\uB2E4.
|
|
43987
|
+
}
|
|
43988
|
+
});
|
|
43989
|
+
|
|
43990
|
+
function writeStatus(phase, extra = {}) {
|
|
43991
|
+
const payload = {
|
|
43992
|
+
phase,
|
|
43993
|
+
updatedAt: new Date().toISOString(),
|
|
43994
|
+
...extra,
|
|
43995
|
+
};
|
|
43996
|
+
fs.writeFileSync(config.statusFile, JSON.stringify(payload, null, 2), { mode: 0o600 });
|
|
43997
|
+
log("phase: " + phase);
|
|
43998
|
+
}
|
|
43999
|
+
|
|
44000
|
+
function log(message) {
|
|
44001
|
+
fs.appendFileSync(config.logFile, new Date().toISOString() + " " + message + "\\n", { mode: 0o600 });
|
|
44002
|
+
}
|
|
44003
|
+
|
|
44004
|
+
function cleanupStaleWorkers() {
|
|
44005
|
+
const now = Date.now();
|
|
44006
|
+
for (const entry of fs.readdirSync(os.tmpdir())) {
|
|
44007
|
+
if (!entry.startsWith(stalePrefix) || !entry.endsWith(workerSuffix)) continue;
|
|
44008
|
+
const filePath = path.join(os.tmpdir(), entry);
|
|
44009
|
+
if (filePath === config.workerPath) continue;
|
|
44010
|
+
try {
|
|
44011
|
+
const stat = fs.statSync(filePath);
|
|
44012
|
+
if (now - stat.mtimeMs > 24 * 60 * 60 * 1000) fs.rmSync(filePath, { force: true });
|
|
44013
|
+
} catch {
|
|
44014
|
+
// \uC624\uB798\uB41C \uC784\uC2DC worker \uC815\uB9AC\uB294 \uCD5C\uC120 \uB178\uB825\uC73C\uB85C\uB9CC \uC218\uD589\uD55C\uB2E4.
|
|
44015
|
+
}
|
|
44016
|
+
}
|
|
44017
|
+
}
|
|
44018
|
+
|
|
44019
|
+
async function stopCurrentConsole() {
|
|
44020
|
+
writeStatus("stopping-console");
|
|
44021
|
+
try {
|
|
44022
|
+
process.kill(config.currentPid, "SIGTERM");
|
|
44023
|
+
} catch (error) {
|
|
44024
|
+
if (!isNoSuchProcess(error)) throw error;
|
|
44025
|
+
}
|
|
44026
|
+
}
|
|
44027
|
+
|
|
44028
|
+
async function waitForOldConsoleExit() {
|
|
44029
|
+
const deadline = Date.now() + stopTimeoutMs;
|
|
44030
|
+
let escalated = false;
|
|
44031
|
+
while (Date.now() < deadline) {
|
|
44032
|
+
const pidGone = !isProcessAlive(config.currentPid);
|
|
44033
|
+
const lockGone = !fs.existsSync(config.lockFile);
|
|
44034
|
+
const healthGone = await isHealthGone(config.currentEndpoint);
|
|
44035
|
+
if (pidGone && lockGone && healthGone) return;
|
|
44036
|
+
if (!escalated && Date.now() > deadline - 10000 && isProcessAlive(config.currentPid)) {
|
|
44037
|
+
escalated = true;
|
|
44038
|
+
try {
|
|
44039
|
+
process.kill(config.currentPid, "SIGKILL");
|
|
44040
|
+
} catch (error) {
|
|
44041
|
+
if (!isNoSuchProcess(error)) throw error;
|
|
44042
|
+
}
|
|
44043
|
+
}
|
|
44044
|
+
await sleep(sleepMs);
|
|
44045
|
+
}
|
|
44046
|
+
throw new Error("old console did not stop before timeout");
|
|
44047
|
+
}
|
|
44048
|
+
|
|
44049
|
+
function detectPackageManager() {
|
|
44050
|
+
const configured = config.packageManager;
|
|
44051
|
+
try {
|
|
44052
|
+
const root = execFileSync(configured.bin, [...configured.prefixArgs, "root", "-g"], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
44053
|
+
if (!root) throw new Error("global package manager root is empty");
|
|
44054
|
+
const rootReal = safeRealpath(root);
|
|
44055
|
+
const packageReal = normalizeExistingPath(config.currentPackageRoot);
|
|
44056
|
+
if (!rootReal || !packageReal) throw new Error("global package manager root could not be resolved");
|
|
44057
|
+
if (isPathInside(packageReal, rootReal)) {
|
|
44058
|
+
return { ...configured, root: rootReal };
|
|
44059
|
+
}
|
|
44060
|
+
for (const packageName of config.packageNames) {
|
|
44061
|
+
if (packageReal === safeRealpath(path.join(root, packageName))) {
|
|
44062
|
+
return { ...configured, root: rootReal };
|
|
44063
|
+
}
|
|
44064
|
+
}
|
|
44065
|
+
} catch (error) {
|
|
44066
|
+
throw new Error("no supported global package manager found: " + sanitizeError(error));
|
|
44067
|
+
}
|
|
44068
|
+
throw new Error("no supported global package manager found");
|
|
44069
|
+
}
|
|
44070
|
+
|
|
44071
|
+
function ensureGlobalRootWritable(manager) {
|
|
44072
|
+
try {
|
|
44073
|
+
fs.accessSync(manager.root, fs.constants.W_OK);
|
|
44074
|
+
} catch {
|
|
44075
|
+
throw new Error("global package manager root is not writable");
|
|
44076
|
+
}
|
|
44077
|
+
}
|
|
44078
|
+
|
|
44079
|
+
async function installPackages(manager) {
|
|
44080
|
+
const packages = config.packageNames.map((name) => name + "@" + config.targetVersion);
|
|
44081
|
+
const code = await spawnExit(manager.bin, [...manager.prefixArgs, "i", "-g", "--force", ...packages]);
|
|
44082
|
+
if (code !== 0) throw new Error("global package install failed with exit code " + code);
|
|
44083
|
+
}
|
|
44084
|
+
|
|
44085
|
+
async function startNewDaemon() {
|
|
44086
|
+
const child = spawn(process.execPath, [config.serverModulePath, "serve"], {
|
|
44087
|
+
detached: true,
|
|
44088
|
+
env: process.env,
|
|
44089
|
+
stdio: "ignore",
|
|
44090
|
+
windowsHide: true,
|
|
44091
|
+
});
|
|
44092
|
+
child.once("error", () => {});
|
|
44093
|
+
child.unref();
|
|
44094
|
+
const deadline = Date.now() + startTimeoutMs;
|
|
44095
|
+
while (Date.now() < deadline) {
|
|
44096
|
+
const lock = readLock();
|
|
44097
|
+
if (lock && lock.pid !== config.currentPid && await isNewHealthOk(lock)) return lock;
|
|
44098
|
+
await sleep(sleepMs);
|
|
44099
|
+
}
|
|
44100
|
+
throw new Error("new console daemon did not become healthy");
|
|
44101
|
+
}
|
|
44102
|
+
|
|
44103
|
+
function openBrowser(url) {
|
|
44104
|
+
const platform = os.platform();
|
|
44105
|
+
if (platform === "darwin") {
|
|
44106
|
+
spawnBrowser("open", [url]);
|
|
44107
|
+
return;
|
|
44108
|
+
}
|
|
44109
|
+
if (platform === "win32") {
|
|
44110
|
+
spawnBrowser("cmd", ["/c", "start", "", url]);
|
|
44111
|
+
return;
|
|
44112
|
+
}
|
|
44113
|
+
spawnBrowser("xdg-open", [url]);
|
|
44114
|
+
}
|
|
44115
|
+
|
|
44116
|
+
function spawnBrowser(command, args) {
|
|
44117
|
+
const child = spawn(command, args, { detached: true, stdio: "ignore", windowsHide: true });
|
|
44118
|
+
child.once("error", () => {});
|
|
44119
|
+
child.unref();
|
|
44120
|
+
}
|
|
44121
|
+
|
|
44122
|
+
function spawnExit(command, args) {
|
|
44123
|
+
return new Promise((resolve) => {
|
|
44124
|
+
const child = spawn(command, args, { stdio: "ignore", windowsHide: true });
|
|
44125
|
+
child.once("error", () => resolve(1));
|
|
44126
|
+
child.once("exit", (code) => resolve(code ?? 1));
|
|
44127
|
+
});
|
|
44128
|
+
}
|
|
44129
|
+
|
|
44130
|
+
function readLock() {
|
|
44131
|
+
try {
|
|
44132
|
+
return JSON.parse(fs.readFileSync(config.lockFile, "utf8"));
|
|
44133
|
+
} catch {
|
|
44134
|
+
return null;
|
|
44135
|
+
}
|
|
44136
|
+
}
|
|
44137
|
+
|
|
44138
|
+
async function isNewHealthOk(lock) {
|
|
44139
|
+
if (!lock || typeof lock.endpoint !== "string" || typeof lock.token !== "string") return false;
|
|
44140
|
+
try {
|
|
44141
|
+
const response = await fetch(new URL("health", lock.endpoint), {
|
|
44142
|
+
headers: { authorization: "Bearer " + lock.token },
|
|
44143
|
+
});
|
|
44144
|
+
if (!response.ok) return false;
|
|
44145
|
+
const version = await readHealthVersion(response);
|
|
44146
|
+
if (version === null) {
|
|
44147
|
+
log("new health response did not expose a version; waiting for verified target");
|
|
44148
|
+
return false;
|
|
44149
|
+
}
|
|
44150
|
+
return version === config.targetVersion;
|
|
44151
|
+
} catch {
|
|
44152
|
+
return false;
|
|
44153
|
+
}
|
|
44154
|
+
}
|
|
44155
|
+
|
|
44156
|
+
async function readHealthVersion(response) {
|
|
44157
|
+
try {
|
|
44158
|
+
const payload = await response.json();
|
|
44159
|
+
return typeof payload.version === "string" ? payload.version : null;
|
|
44160
|
+
} catch {
|
|
44161
|
+
return null;
|
|
44162
|
+
}
|
|
44163
|
+
}
|
|
44164
|
+
|
|
44165
|
+
async function isHealthGone(endpoint) {
|
|
44166
|
+
try {
|
|
44167
|
+
await fetch(new URL("health", endpoint));
|
|
44168
|
+
return false;
|
|
44169
|
+
} catch {
|
|
44170
|
+
return true;
|
|
44171
|
+
}
|
|
44172
|
+
}
|
|
44173
|
+
|
|
44174
|
+
function isProcessAlive(pid) {
|
|
44175
|
+
try {
|
|
44176
|
+
process.kill(pid, 0);
|
|
44177
|
+
return true;
|
|
44178
|
+
} catch (error) {
|
|
44179
|
+
return !isNoSuchProcess(error);
|
|
44180
|
+
}
|
|
44181
|
+
}
|
|
44182
|
+
|
|
44183
|
+
function isNoSuchProcess(error) {
|
|
44184
|
+
return error && typeof error === "object" && error.code === "ESRCH";
|
|
44185
|
+
}
|
|
44186
|
+
|
|
44187
|
+
function safeRealpath(targetPath) {
|
|
44188
|
+
try {
|
|
44189
|
+
return normalizePath(fs.realpathSync(targetPath));
|
|
44190
|
+
} catch {
|
|
44191
|
+
return "";
|
|
44192
|
+
}
|
|
44193
|
+
}
|
|
44194
|
+
|
|
44195
|
+
function normalizeExistingPath(targetPath) {
|
|
44196
|
+
return safeRealpath(targetPath) || normalizePath(targetPath);
|
|
44197
|
+
}
|
|
44198
|
+
|
|
44199
|
+
function normalizePath(targetPath) {
|
|
44200
|
+
const resolved = path.resolve(targetPath);
|
|
44201
|
+
return os.platform() === "win32" ? resolved.toLowerCase() : resolved;
|
|
44202
|
+
}
|
|
44203
|
+
|
|
44204
|
+
function isPathInside(targetPath, rootPath) {
|
|
44205
|
+
const relative = path.relative(rootPath, targetPath);
|
|
44206
|
+
return relative === "" || (!!relative && !relative.startsWith("..") && !path.isAbsolute(relative));
|
|
44207
|
+
}
|
|
44208
|
+
|
|
44209
|
+
function sleep(ms) {
|
|
44210
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
44211
|
+
}
|
|
44212
|
+
|
|
44213
|
+
function sanitizeError(error) {
|
|
44214
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
44215
|
+
return message
|
|
44216
|
+
.replaceAll(config.currentPackageRoot, "[path]")
|
|
44217
|
+
.replaceAll(config.lockFile, "[path]")
|
|
44218
|
+
.replaceAll(config.logFile, "[path]")
|
|
44219
|
+
.replaceAll(config.statusFile, "[path]")
|
|
44220
|
+
.replaceAll(config.workerPath, "[path]");
|
|
44221
|
+
}
|
|
44222
|
+
`;
|
|
44223
|
+
}
|
|
44224
|
+
async function preflightPackageManager(packageRoot, env) {
|
|
44225
|
+
const updater = createGlobalPackageUpdater({
|
|
44226
|
+
env,
|
|
44227
|
+
packageNames: PACKAGE_NAMES,
|
|
44228
|
+
resolveCurrentPackageRoot: () => packageRoot,
|
|
44229
|
+
resolveCurrentVersion: () => void 0
|
|
44230
|
+
});
|
|
44231
|
+
const detection = await updater.detectPackageManager();
|
|
44232
|
+
if (detection.manager === void 0) {
|
|
44233
|
+
if (detection.reason === "permission") {
|
|
44234
|
+
throw new Error("global package manager root is not writable");
|
|
44235
|
+
}
|
|
44236
|
+
throw new Error("no supported global package manager found");
|
|
44237
|
+
}
|
|
44238
|
+
return {
|
|
44239
|
+
bin: detection.manager.resolved.bin,
|
|
44240
|
+
command: detection.manager.command,
|
|
44241
|
+
globalRoot: detection.manager.globalRoot,
|
|
44242
|
+
prefixArgs: detection.manager.resolved.prefixArgs
|
|
44243
|
+
};
|
|
44244
|
+
}
|
|
44245
|
+
function spawnDetachedWorker(spawnWorker, execPath, args, env) {
|
|
44246
|
+
return new Promise((resolve, reject) => {
|
|
44247
|
+
const child = spawnWorker(execPath, args, { detached: true, env, stdio: "ignore", windowsHide: true });
|
|
44248
|
+
let settled = false;
|
|
44249
|
+
child.once("error", (error51) => {
|
|
44250
|
+
if (settled) return;
|
|
44251
|
+
settled = true;
|
|
44252
|
+
reject(error51);
|
|
44253
|
+
});
|
|
44254
|
+
child.unref();
|
|
44255
|
+
queueMicrotask(() => {
|
|
44256
|
+
if (settled) return;
|
|
44257
|
+
settled = true;
|
|
44258
|
+
resolve();
|
|
44259
|
+
});
|
|
44260
|
+
});
|
|
44261
|
+
}
|
|
44262
|
+
function defaultSpawnWorker(execPath, args, options) {
|
|
44263
|
+
const child = spawn(execPath, [...args], options);
|
|
44264
|
+
child.once("error", () => {
|
|
44265
|
+
});
|
|
44266
|
+
return child;
|
|
44267
|
+
}
|
|
44268
|
+
function resolveDefaultServerModulePath() {
|
|
44269
|
+
const builtPath = fileURLToPath(new URL("../dist/cli.mjs", import.meta.url));
|
|
44270
|
+
if (fs7__default.existsSync(builtPath)) return builtPath;
|
|
44271
|
+
const sourcePath = fileURLToPath(import.meta.url);
|
|
44272
|
+
if (sourcePath.endsWith(".ts")) {
|
|
44273
|
+
return sourcePath.replace(/update-apply\.ts$/, "cli.ts");
|
|
44274
|
+
}
|
|
44275
|
+
return path92__default.join(path92__default.dirname(sourcePath), "cli.mjs");
|
|
44276
|
+
}
|
|
43270
44277
|
|
|
43271
44278
|
// src/update-check.ts
|
|
43272
44279
|
var FLEET_CONSOLE_PACKAGE_NAME = "@dotobokuri/fleet-console";
|
|
@@ -43288,9 +44295,9 @@ function createConsoleUpdateCheckService(deps = {}) {
|
|
|
43288
44295
|
void refresh();
|
|
43289
44296
|
return current?.status ?? NO_UPDATE_STATUS;
|
|
43290
44297
|
};
|
|
43291
|
-
const refresh = async () => {
|
|
44298
|
+
const refresh = async (options = {}) => {
|
|
43292
44299
|
const current = cached2;
|
|
43293
|
-
if (current && now() - current.checkedAt < ttlMs) {
|
|
44300
|
+
if (options.force !== true && current && now() - current.checkedAt < ttlMs) {
|
|
43294
44301
|
return current.status;
|
|
43295
44302
|
}
|
|
43296
44303
|
if (inFlight) {
|
|
@@ -43328,23 +44335,26 @@ var SHELL_TERMINAL_SESSION_ID = "shell";
|
|
|
43328
44335
|
var THEATER_SHELL_SESSION_PREFIX2 = "shell:";
|
|
43329
44336
|
var SERVER_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
43330
44337
|
var MAX_BODY_BYTES = 1024 * 1024;
|
|
44338
|
+
var UPDATE_APPLY_FORBIDDEN_BODY_KEYS = /* @__PURE__ */ new Set(["channel", "package", "packageName", "packageVersion", "packages", "targetVersion", "version"]);
|
|
43331
44339
|
function createConsoleServer(deps = {}) {
|
|
43332
44340
|
const host = deps.host ?? DEFAULT_HOST2;
|
|
43333
44341
|
const port = deps.port ?? DEFAULT_PORT2;
|
|
43334
|
-
const
|
|
43335
|
-
const
|
|
44342
|
+
const release = deps.release ?? readFleetConsoleRelease();
|
|
44343
|
+
const version2 = deps.version ?? release.version;
|
|
44344
|
+
const channel = release.channel;
|
|
43336
44345
|
const carrierRegistry = createCarrierRegistry();
|
|
43337
44346
|
registerDefaultCarriers(carrierRegistry);
|
|
43338
44347
|
const lock = createConsoleLock({ hostname: () => host });
|
|
43339
44348
|
const observability = createConsoleObservabilityStore();
|
|
43340
44349
|
const updateCheck = deps.updateCheck ?? createConsoleUpdateCheckService();
|
|
44350
|
+
const updateApply = deps.updateApply ?? createConsoleUpdateApplyService();
|
|
43341
44351
|
const theaters = new TheaterRegistry();
|
|
43342
44352
|
const terminalTickets = createTerminalTicketRegistry();
|
|
43343
44353
|
const folderGrants = createFolderGrantStore();
|
|
43344
44354
|
const infraServices = createInfraServices();
|
|
43345
44355
|
const dataDir = deps.dataDir ?? getFleetDataDir();
|
|
43346
44356
|
initStore(dataDir);
|
|
43347
|
-
const durablePaths = createConsoleDataPaths({ fleetDataDir: dataDir });
|
|
44357
|
+
const durablePaths = createConsoleDataPaths({ fleetDataDir: deps.dataDir });
|
|
43348
44358
|
const durableStateStore = createConsoleDurableStateStore({ paths: durablePaths });
|
|
43349
44359
|
const authEnvResolver = (cli) => resolveAuthEnv(cli, { authService: infraServices.authService });
|
|
43350
44360
|
const ownsAgentRuntime = deps.agentRuntime === void 0;
|
|
@@ -43423,9 +44433,11 @@ function createConsoleServer(deps = {}) {
|
|
|
43423
44433
|
let server = null;
|
|
43424
44434
|
let loopbackServer = null;
|
|
43425
44435
|
let lockHandle = null;
|
|
44436
|
+
let activeLockFile = null;
|
|
43426
44437
|
let activeEndpoint = null;
|
|
43427
44438
|
let agentRuntimeStopped = false;
|
|
43428
44439
|
let consoleResourcesDisposed = false;
|
|
44440
|
+
let updateApplyInFlight = false;
|
|
43429
44441
|
const carrierSettingsRouter = createCarrierSettingsRouter({
|
|
43430
44442
|
registry: carrierRegistry,
|
|
43431
44443
|
isAuthorized: isTerminalAuthorized,
|
|
@@ -43438,6 +44450,18 @@ function createConsoleServer(deps = {}) {
|
|
|
43438
44450
|
readJsonBody,
|
|
43439
44451
|
writeJson
|
|
43440
44452
|
});
|
|
44453
|
+
const agentCliDetector = deps.agentCliDetector ?? createDefaultAgentCliDetector();
|
|
44454
|
+
const agentCliRouter = createAgentCliRouter({
|
|
44455
|
+
detect: agentCliDetector.detect,
|
|
44456
|
+
writeJson
|
|
44457
|
+
});
|
|
44458
|
+
const modelAuthRouter = createModelAuthRouter({
|
|
44459
|
+
authService: infraServices.authService,
|
|
44460
|
+
validateApiKey: (cli, apiKey) => validateAuthKeyForCli(cli, apiKey),
|
|
44461
|
+
isAuthorized: isTerminalAuthorized,
|
|
44462
|
+
readJsonBody,
|
|
44463
|
+
writeJson
|
|
44464
|
+
});
|
|
43441
44465
|
function handleRequest(req, res) {
|
|
43442
44466
|
const pathname = getPathname(req);
|
|
43443
44467
|
if (pathname === "/console/codex" || pathname.startsWith("/console/codex/")) {
|
|
@@ -43484,6 +44508,11 @@ function createConsoleServer(deps = {}) {
|
|
|
43484
44508
|
runAsyncHandler(handleTerminalSessionAttention(req, res, decodeURIComponent(terminalSessionAttentionMatch[1] ?? "")), res);
|
|
43485
44509
|
return;
|
|
43486
44510
|
}
|
|
44511
|
+
const terminalSessionAutoNameMatch = pathname.match(/^\/terminal\/sessions\/([^/]+)\/auto-name$/);
|
|
44512
|
+
if (terminalSessionAutoNameMatch) {
|
|
44513
|
+
runAsyncHandler(handleTerminalSessionAutoName(req, res, decodeURIComponent(terminalSessionAutoNameMatch[1] ?? "")), res);
|
|
44514
|
+
return;
|
|
44515
|
+
}
|
|
43487
44516
|
const terminalSessionItemMatch = pathname.match(/^\/terminal\/sessions\/([^/]+)$/);
|
|
43488
44517
|
if (terminalSessionItemMatch) {
|
|
43489
44518
|
runAsyncHandler(handleTerminalSessionItem(req, res, decodeURIComponent(terminalSessionItemMatch[1] ?? "")), res);
|
|
@@ -43507,6 +44536,10 @@ function createConsoleServer(deps = {}) {
|
|
|
43507
44536
|
handleObserverStatus(req, res);
|
|
43508
44537
|
return;
|
|
43509
44538
|
}
|
|
44539
|
+
if (pathname === "/update/apply") {
|
|
44540
|
+
runAsyncHandler(handleUpdateApply(req, res), res);
|
|
44541
|
+
return;
|
|
44542
|
+
}
|
|
43510
44543
|
if (pathname === "/observer/carriers") {
|
|
43511
44544
|
handleObserverCarriers(req, res);
|
|
43512
44545
|
return;
|
|
@@ -43519,6 +44552,14 @@ function createConsoleServer(deps = {}) {
|
|
|
43519
44552
|
runAsyncBooleanHandler(globalSettingsRouter({ req, res, pathname }), res);
|
|
43520
44553
|
return;
|
|
43521
44554
|
}
|
|
44555
|
+
if (pathname === "/agent-cli" || pathname.startsWith("/agent-cli/")) {
|
|
44556
|
+
runAsyncBooleanHandler(agentCliRouter({ req, res, pathname }), res);
|
|
44557
|
+
return;
|
|
44558
|
+
}
|
|
44559
|
+
if (pathname === "/model-auth" || pathname.startsWith("/model-auth/")) {
|
|
44560
|
+
runAsyncBooleanHandler(modelAuthRouter({ req, res, pathname }), res);
|
|
44561
|
+
return;
|
|
44562
|
+
}
|
|
43522
44563
|
if (pathname === "/observer/tenants") {
|
|
43523
44564
|
handleObserverWorkspaces(req, res);
|
|
43524
44565
|
return;
|
|
@@ -43593,9 +44634,31 @@ function createConsoleServer(deps = {}) {
|
|
|
43593
44634
|
writeJson(res, 404, { error: "terminal_session_not_found" });
|
|
43594
44635
|
return;
|
|
43595
44636
|
}
|
|
43596
|
-
|
|
44637
|
+
const body = await readJsonBody(req);
|
|
44638
|
+
observability.notifySessionAttention(session, normalizeAttentionReason(body?.reason));
|
|
43597
44639
|
writeJson(res, 200, { ok: true });
|
|
43598
44640
|
}
|
|
44641
|
+
async function handleTerminalSessionAutoName(req, res, sessionId) {
|
|
44642
|
+
if (req.method !== "POST") {
|
|
44643
|
+
writeJson(res, 405, { error: "Method not allowed" });
|
|
44644
|
+
return;
|
|
44645
|
+
}
|
|
44646
|
+
const token = lockHandle?.payload.token;
|
|
44647
|
+
if (!token || req.headers.authorization !== `Bearer ${token}`) {
|
|
44648
|
+
writeJson(res, 401, { error: "Unauthorized" });
|
|
44649
|
+
return;
|
|
44650
|
+
}
|
|
44651
|
+
const body = await readJsonBody(req);
|
|
44652
|
+
const label = deriveOperationLabel(body?.prompt);
|
|
44653
|
+
const result = observability.autoNameTerminalSession(sessionId, label);
|
|
44654
|
+
if (result?.renamed) {
|
|
44655
|
+
observability.notifySessionUpdated(result.session);
|
|
44656
|
+
}
|
|
44657
|
+
if (result?.changed) {
|
|
44658
|
+
persistDurableState();
|
|
44659
|
+
}
|
|
44660
|
+
writeJson(res, 200, { ok: true, renamed: result?.renamed === true });
|
|
44661
|
+
}
|
|
43599
44662
|
async function handleTerminalTicket(req, res) {
|
|
43600
44663
|
if (req.method !== "POST") {
|
|
43601
44664
|
writeJson(res, 405, { error: "Method not allowed" });
|
|
@@ -43805,9 +44868,20 @@ function createConsoleServer(deps = {}) {
|
|
|
43805
44868
|
writeJson(res, 503, { error: "terminal_unavailable" });
|
|
43806
44869
|
}
|
|
43807
44870
|
}
|
|
44871
|
+
async function buildAgentCliLaunchMetadata() {
|
|
44872
|
+
const metadata = getAgentCliMetadata();
|
|
44873
|
+
if ((process.env.FLEET_TERMINAL_CMD ?? "").trim().length > 0) {
|
|
44874
|
+
return metadata.map((meta3) => ({ id: meta3.id, label: meta3.label, available: true, signedIn: true }));
|
|
44875
|
+
}
|
|
44876
|
+
const [detected, modelAuth] = await Promise.all([
|
|
44877
|
+
agentCliDetector.detect(),
|
|
44878
|
+
buildModelAuthState(infraServices.authService)
|
|
44879
|
+
]);
|
|
44880
|
+
return combineAgentCliLaunchMetadata(metadata, detected, modelAuth.providers);
|
|
44881
|
+
}
|
|
43808
44882
|
async function handleObserverTheaters(req, res) {
|
|
43809
44883
|
if (req.method === "GET") {
|
|
43810
|
-
writeJson(res, 200, { theaters: listTheaterInfos(), agentClis:
|
|
44884
|
+
writeJson(res, 200, { theaters: listTheaterInfos(), agentClis: await buildAgentCliLaunchMetadata() });
|
|
43811
44885
|
return;
|
|
43812
44886
|
}
|
|
43813
44887
|
if (req.method !== "POST") {
|
|
@@ -43877,7 +44951,14 @@ function createConsoleServer(deps = {}) {
|
|
|
43877
44951
|
await createTerminalSessionForCwd(theater.path, res, cliId);
|
|
43878
44952
|
}
|
|
43879
44953
|
async function createTerminalSessionForCwd(cwd, res, cliId) {
|
|
43880
|
-
|
|
44954
|
+
if (cliId) {
|
|
44955
|
+
const meta3 = (await buildAgentCliLaunchMetadata()).find((entry) => entry.id === cliId);
|
|
44956
|
+
if (!meta3 || !meta3.available || !meta3.signedIn) {
|
|
44957
|
+
writeJson(res, 409, { error: "agent_cli_unavailable" });
|
|
44958
|
+
return;
|
|
44959
|
+
}
|
|
44960
|
+
}
|
|
44961
|
+
const sessionId = crypto3.randomUUID();
|
|
43881
44962
|
const session = observability.createPendingTerminalSession({ sessionId, cwd, cliId });
|
|
43882
44963
|
try {
|
|
43883
44964
|
await terminalSessions.createSession({ sessionId, cwd, cliId });
|
|
@@ -43906,6 +44987,69 @@ function createConsoleServer(deps = {}) {
|
|
|
43906
44987
|
};
|
|
43907
44988
|
writeJson(res, 200, payload);
|
|
43908
44989
|
}
|
|
44990
|
+
async function handleUpdateApply(req, res) {
|
|
44991
|
+
if (req.method !== "POST") {
|
|
44992
|
+
writeJson(res, 405, { error: "Method not allowed" });
|
|
44993
|
+
return;
|
|
44994
|
+
}
|
|
44995
|
+
if (!isExactConsoleOrigin(req)) {
|
|
44996
|
+
writeJson(res, 401, { error: "unauthorized" });
|
|
44997
|
+
return;
|
|
44998
|
+
}
|
|
44999
|
+
const body = await readJsonBody(req);
|
|
45000
|
+
if (body === null && requestHasBody(req)) {
|
|
45001
|
+
writeJson(res, 400, { error: "invalid_update_apply_body" });
|
|
45002
|
+
return;
|
|
45003
|
+
}
|
|
45004
|
+
if (body !== null && (!isPlainObject2(body) || hasForbiddenUpdateApplyBodyKeys(body))) {
|
|
45005
|
+
writeJson(res, 400, { error: "invalid_update_apply_body" });
|
|
45006
|
+
return;
|
|
45007
|
+
}
|
|
45008
|
+
if (channel === "local") {
|
|
45009
|
+
writeJson(res, 403, { error: "local_channel" });
|
|
45010
|
+
return;
|
|
45011
|
+
}
|
|
45012
|
+
if (updateApplyInFlight) {
|
|
45013
|
+
writeJson(res, 409, { error: "update_already_in_progress" });
|
|
45014
|
+
return;
|
|
45015
|
+
}
|
|
45016
|
+
if (terminalSessions.hasLiveSessions()) {
|
|
45017
|
+
writeJson(res, 409, { error: "active_terminal_sessions" });
|
|
45018
|
+
return;
|
|
45019
|
+
}
|
|
45020
|
+
const freshStatus = await updateCheck.refresh({ force: true });
|
|
45021
|
+
if (!freshStatus.updateAvailable || !freshStatus.latestVersion) {
|
|
45022
|
+
writeJson(res, 409, { error: "update_not_available" });
|
|
45023
|
+
return;
|
|
45024
|
+
}
|
|
45025
|
+
const handle = lockHandle;
|
|
45026
|
+
if (!handle || !activeEndpoint || !activeLockFile) {
|
|
45027
|
+
writeJson(res, 503, { error: "console_not_ready" });
|
|
45028
|
+
return;
|
|
45029
|
+
}
|
|
45030
|
+
updateApplyInFlight = true;
|
|
45031
|
+
try {
|
|
45032
|
+
await updateApply.start({
|
|
45033
|
+
currentEndpoint: activeEndpoint,
|
|
45034
|
+
currentPackageRoot: release.packageRoot,
|
|
45035
|
+
currentPid: process.pid,
|
|
45036
|
+
dataDir: durablePaths.dir,
|
|
45037
|
+
lockFile: activeLockFile,
|
|
45038
|
+
targetVersion: freshStatus.latestVersion
|
|
45039
|
+
});
|
|
45040
|
+
} catch {
|
|
45041
|
+
updateApplyInFlight = false;
|
|
45042
|
+
writeJson(res, 503, { error: "update_worker_unavailable" });
|
|
45043
|
+
return;
|
|
45044
|
+
}
|
|
45045
|
+
res.once("finish", () => {
|
|
45046
|
+
setImmediate(() => {
|
|
45047
|
+
void stopAfterAcceptedUpdateApply();
|
|
45048
|
+
});
|
|
45049
|
+
});
|
|
45050
|
+
const payload = { status: "accepted" };
|
|
45051
|
+
writeJson(res, 202, payload);
|
|
45052
|
+
}
|
|
43909
45053
|
function handleObserverCarriers(_req, res) {
|
|
43910
45054
|
writeJson(res, 200, {
|
|
43911
45055
|
carriers: readCarrierStatusEntries(carrierRegistry).map(toCarrierReadinessEntry)
|
|
@@ -43949,6 +45093,10 @@ function createConsoleServer(deps = {}) {
|
|
|
43949
45093
|
if (!lockHandle) return false;
|
|
43950
45094
|
return isAllowedTerminalOrigin(req, lockHandle.payload.port ?? port);
|
|
43951
45095
|
}
|
|
45096
|
+
function isExactConsoleOrigin(req) {
|
|
45097
|
+
if (!lockHandle) return false;
|
|
45098
|
+
return req.headers.origin === `http://127.0.0.1:${lockHandle.payload.port ?? port}`;
|
|
45099
|
+
}
|
|
43952
45100
|
function listVisibleWorkspaces(requestedTenantId) {
|
|
43953
45101
|
if (requestedTenantId) {
|
|
43954
45102
|
const workspace = observability.getWorkspace(requestedTenantId);
|
|
@@ -44000,6 +45148,13 @@ function createConsoleServer(deps = {}) {
|
|
|
44000
45148
|
await agentRuntime.cleanup();
|
|
44001
45149
|
agentRuntimeStopped = true;
|
|
44002
45150
|
}
|
|
45151
|
+
async function stopAfterAcceptedUpdateApply() {
|
|
45152
|
+
try {
|
|
45153
|
+
await stopServer();
|
|
45154
|
+
} catch (error51) {
|
|
45155
|
+
console.warn(`[fleet-console] Update apply shutdown failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
45156
|
+
}
|
|
45157
|
+
}
|
|
44003
45158
|
async function cleanupAfterFailedStart() {
|
|
44004
45159
|
const current = server;
|
|
44005
45160
|
const currentLoopback = loopbackServer;
|
|
@@ -44007,6 +45162,7 @@ function createConsoleServer(deps = {}) {
|
|
|
44007
45162
|
server = null;
|
|
44008
45163
|
loopbackServer = null;
|
|
44009
45164
|
lockHandle = null;
|
|
45165
|
+
activeLockFile = null;
|
|
44010
45166
|
activeEndpoint = null;
|
|
44011
45167
|
await Promise.all([
|
|
44012
45168
|
closeHttpServer(current),
|
|
@@ -44097,7 +45253,35 @@ function createConsoleServer(deps = {}) {
|
|
|
44097
45253
|
if (operation.providerSession) observability.updateTerminalSessionProviderSession(operation.sessionId, operation.providerSession);
|
|
44098
45254
|
}
|
|
44099
45255
|
}
|
|
44100
|
-
|
|
45256
|
+
async function stopServer() {
|
|
45257
|
+
const current = server;
|
|
45258
|
+
const currentLoopback = loopbackServer;
|
|
45259
|
+
const currentLock = lockHandle;
|
|
45260
|
+
let cleanupError;
|
|
45261
|
+
server = null;
|
|
45262
|
+
loopbackServer = null;
|
|
45263
|
+
lockHandle = null;
|
|
45264
|
+
activeLockFile = null;
|
|
45265
|
+
activeEndpoint = null;
|
|
45266
|
+
try {
|
|
45267
|
+
await Promise.all([
|
|
45268
|
+
closeHttpServer(current),
|
|
45269
|
+
closeHttpServer(currentLoopback)
|
|
45270
|
+
]);
|
|
45271
|
+
await terminalSessions.stop();
|
|
45272
|
+
if (!agentRuntimeStopped) {
|
|
45273
|
+
try {
|
|
45274
|
+
if (ownsAgentRuntime) await cleanupOwnedAgentRuntime();
|
|
45275
|
+
} catch (error51) {
|
|
45276
|
+
cleanupError = error51;
|
|
45277
|
+
}
|
|
45278
|
+
}
|
|
45279
|
+
} finally {
|
|
45280
|
+
disposeConsoleResources(currentLock);
|
|
45281
|
+
}
|
|
45282
|
+
if (cleanupError) throw cleanupError;
|
|
45283
|
+
}
|
|
45284
|
+
const returnedServer = {
|
|
44101
45285
|
host,
|
|
44102
45286
|
port,
|
|
44103
45287
|
async start(lockPaths) {
|
|
@@ -44117,6 +45301,7 @@ function createConsoleServer(deps = {}) {
|
|
|
44117
45301
|
server = srv;
|
|
44118
45302
|
loopbackServer = localLoopbackServer;
|
|
44119
45303
|
lockHandle = lock.writeLock({ dir: lockPaths.dir, lockFile: lockPaths.lockFile, pid: process.pid, port: actualPort, endpoint, version: version2 });
|
|
45304
|
+
activeLockFile = lockPaths.lockFile;
|
|
44120
45305
|
activeEndpoint = endpoint;
|
|
44121
45306
|
resolve();
|
|
44122
45307
|
} catch (err) {
|
|
@@ -44137,40 +45322,10 @@ function createConsoleServer(deps = {}) {
|
|
|
44137
45322
|
return activeEndpoint;
|
|
44138
45323
|
},
|
|
44139
45324
|
async stop() {
|
|
44140
|
-
|
|
44141
|
-
const currentLoopback = loopbackServer;
|
|
44142
|
-
const currentLock = lockHandle;
|
|
44143
|
-
let cleanupError;
|
|
44144
|
-
server = null;
|
|
44145
|
-
loopbackServer = null;
|
|
44146
|
-
lockHandle = null;
|
|
44147
|
-
activeEndpoint = null;
|
|
44148
|
-
try {
|
|
44149
|
-
await Promise.all([
|
|
44150
|
-
closeHttpServer(current),
|
|
44151
|
-
closeHttpServer(currentLoopback)
|
|
44152
|
-
]);
|
|
44153
|
-
await terminalSessions.stop();
|
|
44154
|
-
if (!agentRuntimeStopped) {
|
|
44155
|
-
try {
|
|
44156
|
-
if (ownsAgentRuntime) await cleanupOwnedAgentRuntime();
|
|
44157
|
-
} catch (error51) {
|
|
44158
|
-
cleanupError = error51;
|
|
44159
|
-
}
|
|
44160
|
-
}
|
|
44161
|
-
} finally {
|
|
44162
|
-
disposeConsoleResources(currentLock);
|
|
44163
|
-
}
|
|
44164
|
-
if (cleanupError) throw cleanupError;
|
|
45325
|
+
await stopServer();
|
|
44165
45326
|
}
|
|
44166
45327
|
};
|
|
44167
|
-
|
|
44168
|
-
function readConsoleChannel() {
|
|
44169
|
-
try {
|
|
44170
|
-
return readFleetConsoleRelease().channel;
|
|
44171
|
-
} catch {
|
|
44172
|
-
return "unknown";
|
|
44173
|
-
}
|
|
45328
|
+
return returnedServer;
|
|
44174
45329
|
}
|
|
44175
45330
|
function resolveCarrierEventOrigin(event, jobOriginById) {
|
|
44176
45331
|
const originSessionId = event.originSessionId;
|
|
@@ -44261,6 +45416,14 @@ function terminalFolderListStatus(error51) {
|
|
|
44261
45416
|
function isPlainObject2(value) {
|
|
44262
45417
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
44263
45418
|
}
|
|
45419
|
+
function hasForbiddenUpdateApplyBodyKeys(body) {
|
|
45420
|
+
return Object.keys(body).some((key) => UPDATE_APPLY_FORBIDDEN_BODY_KEYS.has(key));
|
|
45421
|
+
}
|
|
45422
|
+
function requestHasBody(req) {
|
|
45423
|
+
const contentLength = req.headers["content-length"];
|
|
45424
|
+
if (typeof contentLength === "string" && contentLength !== "0") return true;
|
|
45425
|
+
return req.headers["transfer-encoding"] !== void 0;
|
|
45426
|
+
}
|
|
44264
45427
|
async function readJsonBody(req) {
|
|
44265
45428
|
const chunks = [];
|
|
44266
45429
|
let total = 0;
|
|
@@ -44320,9 +45483,9 @@ function isAllowedTerminalOrigin(req, expectedPort) {
|
|
|
44320
45483
|
return origin === `http://127.0.0.1:${expectedPort}`;
|
|
44321
45484
|
}
|
|
44322
45485
|
var CAPTURE_TEMP_PREFIX = ".capture.";
|
|
44323
|
-
async function runCaptureSessionHook(provider, env =
|
|
45486
|
+
async function runCaptureSessionHook(provider, env = process9.env) {
|
|
44324
45487
|
return captureSession({
|
|
44325
|
-
diagnostics:
|
|
45488
|
+
diagnostics: process9.stderr,
|
|
44326
45489
|
env,
|
|
44327
45490
|
input: await readStdin(),
|
|
44328
45491
|
provider
|
|
@@ -44339,12 +45502,12 @@ function captureSession(options) {
|
|
|
44339
45502
|
}
|
|
44340
45503
|
function captureSessionStrict(options) {
|
|
44341
45504
|
const provider = parseProvider(options.provider);
|
|
44342
|
-
const fleetSessionId = readFleetSessionId(options.env ??
|
|
45505
|
+
const fleetSessionId = readFleetSessionId(options.env ?? process9.env);
|
|
44343
45506
|
const input = parseHookInput(options.input ?? "");
|
|
44344
45507
|
const providerSession = toProviderSession(provider, input, options.now ?? (() => /* @__PURE__ */ new Date()));
|
|
44345
45508
|
const capturesDir = (options.paths ?? createConsoleDataPaths()).capturesDir;
|
|
44346
|
-
const finalPath =
|
|
44347
|
-
const tempPath =
|
|
45509
|
+
const finalPath = path92__default.join(capturesDir, `${fleetSessionId}.json`);
|
|
45510
|
+
const tempPath = path92__default.join(capturesDir, `${CAPTURE_TEMP_PREFIX}${fleetSessionId}.${process9.pid}.${Date.now()}.tmp`);
|
|
44348
45511
|
fs7__default.mkdirSync(capturesDir, { recursive: true, mode: 448 });
|
|
44349
45512
|
fs7__default.writeFileSync(tempPath, `${JSON.stringify(providerSession, null, 2)}
|
|
44350
45513
|
`, { mode: 384 });
|
|
@@ -44358,7 +45521,7 @@ function parseProvider(value) {
|
|
|
44358
45521
|
function readFleetSessionId(env) {
|
|
44359
45522
|
const value = env.FLEET_CONSOLE_SESSION_ID;
|
|
44360
45523
|
if (!value) throw new Error("missing_fleet_session_id");
|
|
44361
|
-
if (
|
|
45524
|
+
if (path92__default.basename(value) !== value || value.includes(path92__default.sep) || value.includes(path92__default.posix.sep)) {
|
|
44362
45525
|
throw new Error("invalid_fleet_session_id");
|
|
44363
45526
|
}
|
|
44364
45527
|
return value;
|
|
@@ -44384,11 +45547,11 @@ function toProviderSession(provider, input, now) {
|
|
|
44384
45547
|
function readStdin() {
|
|
44385
45548
|
return new Promise((resolve, reject) => {
|
|
44386
45549
|
const chunks = [];
|
|
44387
|
-
|
|
45550
|
+
process9.stdin.on("data", (chunk) => {
|
|
44388
45551
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
44389
45552
|
});
|
|
44390
|
-
|
|
44391
|
-
|
|
45553
|
+
process9.stdin.on("error", reject);
|
|
45554
|
+
process9.stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
44392
45555
|
});
|
|
44393
45556
|
}
|
|
44394
45557
|
function createConsoleStalePolicy(deps = {}) {
|
|
@@ -44404,7 +45567,7 @@ function createConsoleStalePolicy(deps = {}) {
|
|
|
44404
45567
|
return { isBuildStale };
|
|
44405
45568
|
}
|
|
44406
45569
|
var TURN_POST_TIMEOUT_MS = 1500;
|
|
44407
|
-
async function runTurnStateHook(phase, env =
|
|
45570
|
+
async function runTurnStateHook(phase, env = process9.env, options = {}) {
|
|
44408
45571
|
try {
|
|
44409
45572
|
await postTurnState(phase, env, options);
|
|
44410
45573
|
} catch {
|
|
@@ -44433,12 +45596,66 @@ async function postTurnState(phase, env, options) {
|
|
|
44433
45596
|
clearTimeout(timer);
|
|
44434
45597
|
}
|
|
44435
45598
|
}
|
|
45599
|
+
var AUTO_NAME_POST_TIMEOUT_MS = 1500;
|
|
45600
|
+
var MAX_PROMPT_PAYLOAD = 2e3;
|
|
45601
|
+
async function runAutoNameHook(env = process9.env, options = {}) {
|
|
45602
|
+
try {
|
|
45603
|
+
await postAutoName(env, options);
|
|
45604
|
+
} catch {
|
|
45605
|
+
}
|
|
45606
|
+
}
|
|
45607
|
+
async function postAutoName(env, options) {
|
|
45608
|
+
const sessionId = env.FLEET_CONSOLE_SESSION_ID;
|
|
45609
|
+
if (!sessionId) return;
|
|
45610
|
+
const prompt = extractPrompt(options.input ?? await readStdin2());
|
|
45611
|
+
if (prompt === null) return;
|
|
45612
|
+
const paths = createConsolePaths({ env });
|
|
45613
|
+
const lock = createConsoleLock().readLock(paths.lockFile);
|
|
45614
|
+
if (!lock) return;
|
|
45615
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
45616
|
+
const controller = new AbortController();
|
|
45617
|
+
const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? AUTO_NAME_POST_TIMEOUT_MS);
|
|
45618
|
+
try {
|
|
45619
|
+
await fetchImpl(`${lock.endpoint}terminal/sessions/${encodeURIComponent(sessionId)}/auto-name`, {
|
|
45620
|
+
method: "POST",
|
|
45621
|
+
headers: {
|
|
45622
|
+
authorization: `Bearer ${lock.token}`,
|
|
45623
|
+
"content-type": "application/json"
|
|
45624
|
+
},
|
|
45625
|
+
body: JSON.stringify({ prompt }),
|
|
45626
|
+
signal: controller.signal
|
|
45627
|
+
});
|
|
45628
|
+
} finally {
|
|
45629
|
+
clearTimeout(timer);
|
|
45630
|
+
}
|
|
45631
|
+
}
|
|
45632
|
+
function extractPrompt(input) {
|
|
45633
|
+
try {
|
|
45634
|
+
const parsed = JSON.parse(input);
|
|
45635
|
+
if (typeof parsed !== "object" || parsed === null) return null;
|
|
45636
|
+
const value = parsed.prompt;
|
|
45637
|
+
if (typeof value !== "string" || value.trim().length === 0) return null;
|
|
45638
|
+
return value.slice(0, MAX_PROMPT_PAYLOAD);
|
|
45639
|
+
} catch {
|
|
45640
|
+
return null;
|
|
45641
|
+
}
|
|
45642
|
+
}
|
|
45643
|
+
function readStdin2() {
|
|
45644
|
+
return new Promise((resolve, reject) => {
|
|
45645
|
+
const chunks = [];
|
|
45646
|
+
process9.stdin.on("data", (chunk) => {
|
|
45647
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
45648
|
+
});
|
|
45649
|
+
process9.stdin.on("error", reject);
|
|
45650
|
+
process9.stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
45651
|
+
});
|
|
45652
|
+
}
|
|
44436
45653
|
|
|
44437
45654
|
// src/cli.ts
|
|
44438
45655
|
var FIXED_HOST = "127.0.0.1";
|
|
44439
45656
|
var HELP_BANNER_INDENT = " ";
|
|
44440
45657
|
var DEFAULT_HELP_RELEASE = "local";
|
|
44441
|
-
var CONSOLE_HOOK_COMMANDS = /* @__PURE__ */ new Set(["capture-session", "subagents-context", "turn-start", "turn-end", "attention"]);
|
|
45658
|
+
var CONSOLE_HOOK_COMMANDS = /* @__PURE__ */ new Set(["capture-session", "subagents-context", "turn-start", "turn-end", "attention", "auto-name"]);
|
|
44442
45659
|
function parseConsoleCliMode(argv) {
|
|
44443
45660
|
if (argv.length === 0) return "start";
|
|
44444
45661
|
const [first, ...rest] = argv;
|
|
@@ -44472,6 +45689,7 @@ function parseConsoleHookCommand(argv) {
|
|
|
44472
45689
|
if (commandName === "turn-start" && rest.length === 0) return { command: "turn-start" };
|
|
44473
45690
|
if (commandName === "turn-end" && rest.length === 0) return { command: "turn-end" };
|
|
44474
45691
|
if (commandName === "attention" && rest.length === 0) return { command: "attention" };
|
|
45692
|
+
if (commandName === "auto-name" && rest.length === 0) return { command: "auto-name" };
|
|
44475
45693
|
if (commandName === "capture-session" && rest.length === 1 && rest[0]) return { command: "capture-session", provider: rest[0] };
|
|
44476
45694
|
throw new Error("Unknown fleet-console hook command");
|
|
44477
45695
|
}
|
|
@@ -44535,11 +45753,14 @@ function buildWikiHelpText(options = {}) {
|
|
|
44535
45753
|
return colorEnabled ? text : stripAnsi(text);
|
|
44536
45754
|
}
|
|
44537
45755
|
function createConsoleDaemonLifecycle(deps = {}) {
|
|
44538
|
-
const env = deps.env ??
|
|
44539
|
-
const execPath = deps.execPath ??
|
|
44540
|
-
const serverModulePath = deps.serverModulePath ??
|
|
45756
|
+
const env = deps.env ?? process9.env;
|
|
45757
|
+
const execPath = deps.execPath ?? process9.execPath;
|
|
45758
|
+
const serverModulePath = deps.serverModulePath ?? resolveDefaultServerModulePath2();
|
|
44541
45759
|
const spawnDetached = deps.spawnDetached ?? ((bin, args, options) => {
|
|
44542
|
-
spawn(bin, [...args], options)
|
|
45760
|
+
const child = spawn(bin, [...args], options);
|
|
45761
|
+
child.once("error", () => {
|
|
45762
|
+
});
|
|
45763
|
+
child.unref();
|
|
44543
45764
|
});
|
|
44544
45765
|
const sleep = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
44545
45766
|
const paths = createConsolePaths({ env });
|
|
@@ -44550,10 +45771,10 @@ function createConsoleDaemonLifecycle(deps = {}) {
|
|
|
44550
45771
|
const server = createConsoleServer();
|
|
44551
45772
|
await server.start(paths);
|
|
44552
45773
|
await new Promise((resolve) => {
|
|
44553
|
-
|
|
45774
|
+
process9.once("SIGTERM", () => {
|
|
44554
45775
|
void server.stop().finally(resolve);
|
|
44555
45776
|
});
|
|
44556
|
-
|
|
45777
|
+
process9.once("SIGINT", () => {
|
|
44557
45778
|
void server.stop().finally(resolve);
|
|
44558
45779
|
});
|
|
44559
45780
|
});
|
|
@@ -44567,14 +45788,14 @@ function createConsoleDaemonLifecycle(deps = {}) {
|
|
|
44567
45788
|
const payload = readTrustedLock();
|
|
44568
45789
|
if (!payload) return;
|
|
44569
45790
|
try {
|
|
44570
|
-
|
|
45791
|
+
process9.kill(payload.pid, "SIGTERM");
|
|
44571
45792
|
} catch (err) {
|
|
44572
45793
|
if (err.code !== "ESRCH") throw err;
|
|
44573
45794
|
}
|
|
44574
45795
|
await sleep(200);
|
|
44575
45796
|
try {
|
|
44576
|
-
|
|
44577
|
-
|
|
45797
|
+
process9.kill(payload.pid, 0);
|
|
45798
|
+
process9.kill(payload.pid, "SIGKILL");
|
|
44578
45799
|
} catch (err) {
|
|
44579
45800
|
if (err.code !== "ESRCH") throw err;
|
|
44580
45801
|
}
|
|
@@ -44589,7 +45810,7 @@ function createConsoleDaemonLifecycle(deps = {}) {
|
|
|
44589
45810
|
if (typeof probeResult.health?.workspaceCount === "number" && probeResult.health.workspaceCount > 0) return current.endpoint;
|
|
44590
45811
|
}
|
|
44591
45812
|
if (current) await stop();
|
|
44592
|
-
spawnDetached(execPath, [serverModulePath, "serve"], { detached: true, env, stdio: "ignore" });
|
|
45813
|
+
spawnDetached(execPath, [serverModulePath, "serve"], { detached: true, env, stdio: "ignore", windowsHide: true });
|
|
44593
45814
|
for (let i = 0; i < 30; i += 1) {
|
|
44594
45815
|
await sleep(100);
|
|
44595
45816
|
const next = await probe();
|
|
@@ -44640,7 +45861,7 @@ async function openFleetWikiWorkspace(options) {
|
|
|
44640
45861
|
authorization: `Bearer ${status.lock.token}`,
|
|
44641
45862
|
"content-type": "application/json"
|
|
44642
45863
|
},
|
|
44643
|
-
body: JSON.stringify({ cwd:
|
|
45864
|
+
body: JSON.stringify({ cwd: path92__default.resolve(options.cwd) })
|
|
44644
45865
|
});
|
|
44645
45866
|
if (!response.ok) {
|
|
44646
45867
|
throw new Error(`Fleet Console Codex workspace registration failed: ${response.status} ${await response.text()}`);
|
|
@@ -44681,59 +45902,63 @@ async function runConsoleRestart(deps = {}) {
|
|
|
44681
45902
|
return openFleetConsole({ lifecycle, openBrowser: deps.openBrowser });
|
|
44682
45903
|
}
|
|
44683
45904
|
async function main() {
|
|
44684
|
-
if (
|
|
45905
|
+
if (process9.argv[2] === "serve") {
|
|
44685
45906
|
await createConsoleDaemonLifecycle().runServer();
|
|
44686
45907
|
return;
|
|
44687
45908
|
}
|
|
44688
|
-
if (
|
|
44689
|
-
const hookCommand = parseConsoleHookCommand(
|
|
45909
|
+
if (process9.argv[2] === "hook") {
|
|
45910
|
+
const hookCommand = parseConsoleHookCommand(process9.argv.slice(3));
|
|
44690
45911
|
if (hookCommand.command === "subagents-context") {
|
|
44691
|
-
|
|
45912
|
+
process9.stdout.write(`${runSubagentsContextHook(process9.env)}
|
|
44692
45913
|
`);
|
|
44693
45914
|
return;
|
|
44694
45915
|
}
|
|
44695
45916
|
if (hookCommand.command === "turn-start" || hookCommand.command === "turn-end") {
|
|
44696
|
-
await runTurnStateHook(hookCommand.command === "turn-start" ? "start" : "end",
|
|
45917
|
+
await runTurnStateHook(hookCommand.command === "turn-start" ? "start" : "end", process9.env);
|
|
44697
45918
|
return;
|
|
44698
45919
|
}
|
|
44699
45920
|
if (hookCommand.command === "attention") {
|
|
44700
|
-
await runAttentionHook(
|
|
45921
|
+
await runAttentionHook(process9.env);
|
|
45922
|
+
return;
|
|
45923
|
+
}
|
|
45924
|
+
if (hookCommand.command === "auto-name") {
|
|
45925
|
+
await runAutoNameHook(process9.env);
|
|
44701
45926
|
return;
|
|
44702
45927
|
}
|
|
44703
|
-
await runCaptureSessionHook(hookCommand.provider,
|
|
45928
|
+
await runCaptureSessionHook(hookCommand.provider, process9.env);
|
|
44704
45929
|
return;
|
|
44705
45930
|
}
|
|
44706
|
-
if (
|
|
44707
|
-
await mainWiki(
|
|
45931
|
+
if (process9.argv[2] === "codex") {
|
|
45932
|
+
await mainWiki(process9.argv.slice(3));
|
|
44708
45933
|
return;
|
|
44709
45934
|
}
|
|
44710
|
-
const mode = parseConsoleCliMode(
|
|
45935
|
+
const mode = parseConsoleCliMode(process9.argv.slice(2));
|
|
44711
45936
|
if (mode === "help") {
|
|
44712
|
-
|
|
45937
|
+
process9.stdout.write(`${buildConsoleHelpText({ env: process9.env, isTTY: process9.stdout.isTTY })}
|
|
44713
45938
|
`);
|
|
44714
45939
|
return;
|
|
44715
45940
|
}
|
|
44716
45941
|
if (mode === "status") {
|
|
44717
|
-
|
|
45942
|
+
process9.stdout.write(`${await runConsoleStatus()}
|
|
44718
45943
|
`);
|
|
44719
45944
|
return;
|
|
44720
45945
|
}
|
|
44721
45946
|
if (mode === "stop") {
|
|
44722
|
-
|
|
45947
|
+
process9.stdout.write(`${await runConsoleStop()}
|
|
44723
45948
|
`);
|
|
44724
45949
|
return;
|
|
44725
45950
|
}
|
|
44726
45951
|
if (mode === "restart") {
|
|
44727
45952
|
await runConsoleRestart();
|
|
44728
|
-
|
|
45953
|
+
process9.stdout.write("Fleet Console restarted.\n");
|
|
44729
45954
|
return;
|
|
44730
45955
|
}
|
|
44731
45956
|
await openFleetConsole();
|
|
44732
|
-
|
|
45957
|
+
process9.stdout.write("Fleet Console opened.\n");
|
|
44733
45958
|
}
|
|
44734
|
-
async function mainWiki(argv =
|
|
45959
|
+
async function mainWiki(argv = process9.argv.slice(2)) {
|
|
44735
45960
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
44736
|
-
|
|
45961
|
+
process9.stdout.write(`${buildWikiHelpText({ env: process9.env, isTTY: process9.stdout.isTTY })}
|
|
44737
45962
|
`);
|
|
44738
45963
|
return;
|
|
44739
45964
|
}
|
|
@@ -44745,19 +45970,19 @@ async function mainWiki(argv = process7.argv.slice(2)) {
|
|
|
44745
45970
|
if (unsupported.length > 0) {
|
|
44746
45971
|
throw new Error(`Unknown fleet wiki option: ${unsupported[0]}`);
|
|
44747
45972
|
}
|
|
44748
|
-
await openFleetWikiWorkspace({ cwd:
|
|
45973
|
+
await openFleetWikiWorkspace({ cwd: process9.cwd() });
|
|
44749
45974
|
}
|
|
44750
|
-
function
|
|
45975
|
+
function resolveDefaultServerModulePath2() {
|
|
44751
45976
|
const builtPath = new URL("../dist/cli.mjs", import.meta.url).pathname;
|
|
44752
45977
|
if (fs7__default.existsSync(builtPath)) return builtPath;
|
|
44753
45978
|
return fileURLToPath(import.meta.url);
|
|
44754
45979
|
}
|
|
44755
|
-
var isDirectRun =
|
|
45980
|
+
var isDirectRun = process9.argv[1] && path92__default.resolve(process9.argv[1]) === fileURLToPath(import.meta.url);
|
|
44756
45981
|
if (isDirectRun) {
|
|
44757
45982
|
await main().catch((error51) => {
|
|
44758
|
-
|
|
45983
|
+
process9.stderr.write(`${error51 instanceof Error ? error51.message : String(error51)}
|
|
44759
45984
|
`);
|
|
44760
|
-
|
|
45985
|
+
process9.exitCode = 1;
|
|
44761
45986
|
});
|
|
44762
45987
|
}
|
|
44763
45988
|
|