@dotobokuri/fleet-cli 1.6.0 → 1.7.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/dist/index.js +497 -303
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -17560,7 +17560,9 @@ function killProcess(child, forceTimeoutMs = 3e3) {
|
|
|
17560
17560
|
try {
|
|
17561
17561
|
execSync(`taskkill /PID ${child.pid} /T /F`, {
|
|
17562
17562
|
stdio: "pipe",
|
|
17563
|
-
timeout: 5e3
|
|
17563
|
+
timeout: 5e3,
|
|
17564
|
+
// 콘솔 없는 호스트에서 taskkill 호출 시 새 콘솔 창이 깜빡이는 것을 방지한다.
|
|
17565
|
+
windowsHide: true
|
|
17564
17566
|
});
|
|
17565
17567
|
} catch {
|
|
17566
17568
|
child.kill("SIGKILL");
|
|
@@ -17663,7 +17665,12 @@ var init_BaseConnection = __esm({
|
|
|
17663
17665
|
cwd: this.cwd,
|
|
17664
17666
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17665
17667
|
env: this.env,
|
|
17666
|
-
windowsVerbatimArguments: true
|
|
17668
|
+
windowsVerbatimArguments: true,
|
|
17669
|
+
// 콘솔이 없는 호스트(예: fleet-console 백엔드)에서 cmd.exe를 spawn하면
|
|
17670
|
+
// Windows가 새 콘솔 창을 할당해 깜빡인다. stdio는 모두 pipe라 가시 콘솔이
|
|
17671
|
+
// 불필요하므로 CREATE_NO_WINDOW로 창 생성을 억제한다. (fleet-cli처럼 콘솔이
|
|
17672
|
+
// 이미 있는 경우에도 무해하다.)
|
|
17673
|
+
windowsHide: true
|
|
17667
17674
|
}) : spawn(this.command, this.args, {
|
|
17668
17675
|
cwd: this.cwd,
|
|
17669
17676
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -18423,7 +18430,9 @@ function resolveNpxPath(env) {
|
|
|
18423
18430
|
encoding: "utf-8",
|
|
18424
18431
|
stdio: "pipe",
|
|
18425
18432
|
timeout: 5e3,
|
|
18426
|
-
env
|
|
18433
|
+
env,
|
|
18434
|
+
// 콘솔 없는 호스트에서 `where npx` 실행 시 콘솔 창이 깜빡이는 것을 방지한다.
|
|
18435
|
+
windowsHide: true
|
|
18427
18436
|
}).trim();
|
|
18428
18437
|
const candidates = result.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
18429
18438
|
if (windows) {
|
|
@@ -33897,15 +33906,21 @@ function claudeHooks(options2) {
|
|
|
33897
33906
|
if (!hookExec) {
|
|
33898
33907
|
throw new Error("Fleet Claude session hook command is required");
|
|
33899
33908
|
}
|
|
33900
|
-
const
|
|
33909
|
+
const userPromptSubmitExecs = [options2.captureSessionHookExec, options2.turnStartHookExec].filter((exec) => exec !== void 0);
|
|
33910
|
+
const stopExecs = [options2.turnEndHookExec].filter((exec) => exec !== void 0);
|
|
33901
33911
|
return {
|
|
33902
33912
|
hooks: {
|
|
33903
33913
|
SessionStart: [{
|
|
33904
33914
|
hooks: [claudeCommandHook(hookExec)]
|
|
33905
33915
|
}],
|
|
33906
|
-
...
|
|
33916
|
+
...userPromptSubmitExecs.length > 0 ? {
|
|
33907
33917
|
UserPromptSubmit: [{
|
|
33908
|
-
hooks:
|
|
33918
|
+
hooks: userPromptSubmitExecs.map(claudeCommandHook)
|
|
33919
|
+
}]
|
|
33920
|
+
} : {},
|
|
33921
|
+
...stopExecs.length > 0 ? {
|
|
33922
|
+
Stop: [{
|
|
33923
|
+
hooks: stopExecs.map(claudeCommandHook)
|
|
33909
33924
|
}]
|
|
33910
33925
|
} : {}
|
|
33911
33926
|
}
|
|
@@ -34668,11 +34683,17 @@ async function injectAgentCliProfile(profile, options2) {
|
|
|
34668
34683
|
dataDir: options2.dataDir,
|
|
34669
34684
|
rootDir: options2.pluginRootDir,
|
|
34670
34685
|
captureSessionHookExec: options2.captureSessionHookExec,
|
|
34686
|
+
turnStartHookExec: options2.turnStartHookExec,
|
|
34687
|
+
turnEndHookExec: options2.turnEndHookExec,
|
|
34671
34688
|
hookExec: startupDefinitions.host === "claude" ? requireHookExec(options2.hookExec) : void 0,
|
|
34672
34689
|
withMarketplaceLock: options2.withMarketplaceLock
|
|
34673
34690
|
});
|
|
34674
34691
|
const codexPluginKeys = plugin.codexRegistrations.map((registration) => `${registration.pluginName}@${registration.marketplaceName}`);
|
|
34675
|
-
const codexProfile = profile.id === "codex" ? writeCodexFleetProfile(profile.env, doctrine, codexPluginKeys,
|
|
34692
|
+
const codexProfile = profile.id === "codex" ? writeCodexFleetProfile(profile.env, doctrine, codexPluginKeys, {
|
|
34693
|
+
captureSessionHookExec: options2.captureSessionHookExec,
|
|
34694
|
+
turnStartHookExec: options2.turnStartHookExec,
|
|
34695
|
+
turnEndHookExec: options2.turnEndHookExec
|
|
34696
|
+
}, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
|
|
34676
34697
|
const launchWarnings = [];
|
|
34677
34698
|
for (const registration of plugin.codexRegistrations) {
|
|
34678
34699
|
const registrationWarning = await ensureCodexPluginRegistered(registration, {
|
|
@@ -34748,7 +34769,7 @@ function writeSystemPromptFile(cliId, systemPrompt, onCleanup) {
|
|
|
34748
34769
|
chmodBestEffort2(filePath, SYSTEM_PROMPT_FILE_MODE);
|
|
34749
34770
|
return filePath;
|
|
34750
34771
|
}
|
|
34751
|
-
function writeCodexFleetProfile(env, doctrine, pluginKeys,
|
|
34772
|
+
function writeCodexFleetProfile(env, doctrine, pluginKeys, hookExecs, onCleanup) {
|
|
34752
34773
|
const codexHome = env.CODEX_HOME ?? path92.join(env.HOME ?? os23.homedir(), ".codex");
|
|
34753
34774
|
mkdirSync32(codexHome, { recursive: true });
|
|
34754
34775
|
pruneStaleCodexFleetProfiles(codexHome);
|
|
@@ -34768,19 +34789,31 @@ function writeCodexFleetProfile(env, doctrine, pluginKeys, captureSessionHookExe
|
|
|
34768
34789
|
"enabled = true",
|
|
34769
34790
|
""
|
|
34770
34791
|
]),
|
|
34771
|
-
...
|
|
34792
|
+
...codexHooksConfig(hookExecs)
|
|
34772
34793
|
].join("\n"));
|
|
34773
34794
|
chmodBestEffort2(profilePath, SYSTEM_PROMPT_FILE_MODE);
|
|
34774
34795
|
return { profileName, profilePath };
|
|
34775
34796
|
}
|
|
34776
|
-
function
|
|
34777
|
-
|
|
34778
|
-
const
|
|
34779
|
-
return [
|
|
34780
|
-
|
|
34781
|
-
|
|
34782
|
-
|
|
34783
|
-
|
|
34797
|
+
function codexHooksConfig(hookExecs) {
|
|
34798
|
+
const userPromptSubmitExecs = [hookExecs.captureSessionHookExec, hookExecs.turnStartHookExec].filter((exec) => exec !== void 0);
|
|
34799
|
+
const stopExecs = [hookExecs.turnEndHookExec].filter((exec) => exec !== void 0);
|
|
34800
|
+
if (userPromptSubmitExecs.length === 0 && stopExecs.length === 0) return [];
|
|
34801
|
+
const lines = ["[hooks]"];
|
|
34802
|
+
if (userPromptSubmitExecs.length > 0) {
|
|
34803
|
+
lines.push(`UserPromptSubmit = ${codexHookHandlersInline(userPromptSubmitExecs)}`);
|
|
34804
|
+
}
|
|
34805
|
+
if (stopExecs.length > 0) {
|
|
34806
|
+
lines.push(`Stop = ${codexHookHandlersInline(stopExecs)}`);
|
|
34807
|
+
}
|
|
34808
|
+
lines.push("");
|
|
34809
|
+
return lines;
|
|
34810
|
+
}
|
|
34811
|
+
function codexHookHandlersInline(execs) {
|
|
34812
|
+
const handlers = execs.map((exec) => {
|
|
34813
|
+
const command3 = buildPosixShellCommand([exec.command, ...exec.args]);
|
|
34814
|
+
return `{ type = "command", command = "${escapeTomlBasicString2(command3)}" }`;
|
|
34815
|
+
}).join(", ");
|
|
34816
|
+
return `[{ hooks = [${handlers}] }]`;
|
|
34784
34817
|
}
|
|
34785
34818
|
function writeFileNoFollow2(filePath, content) {
|
|
34786
34819
|
const flags = constants32.O_WRONLY | constants32.O_CREAT | constants32.O_TRUNC | constants32.O_NOFOLLOW;
|
|
@@ -39685,7 +39718,7 @@ import * as fs52 from "fs";
|
|
|
39685
39718
|
import fs5__default, { readFileSync as readFileSync8, existsSync as existsSync8, mkdtempSync as mkdtempSync3, writeFileSync as writeFileSync6, mkdirSync as mkdirSync8, rmSync as rmSync5, chmodSync as chmodSync5, renameSync as renameSync5, readdirSync as readdirSync6, constants as constants8, openSync as openSync8, closeSync as closeSync8, lstatSync as lstatSync8, unlinkSync as unlinkSync5, realpathSync as realpathSync6, statSync as statSync6, symlinkSync as symlinkSync2, fstatSync as fstatSync7 } from "fs";
|
|
39686
39719
|
import * as path93 from "path";
|
|
39687
39720
|
import path93__default, { join as join10, resolve, relative, dirname as dirname6 } from "path";
|
|
39688
|
-
import
|
|
39721
|
+
import process6 from "process";
|
|
39689
39722
|
import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
|
|
39690
39723
|
import * as os222 from "os";
|
|
39691
39724
|
import os22__default from "os";
|
|
@@ -40637,10 +40670,10 @@ function mergeDefs2(...defs) {
|
|
|
40637
40670
|
function cloneDef2(schema) {
|
|
40638
40671
|
return mergeDefs2(schema._zod.def);
|
|
40639
40672
|
}
|
|
40640
|
-
function getElementAtPath2(obj,
|
|
40641
|
-
if (!
|
|
40673
|
+
function getElementAtPath2(obj, path35) {
|
|
40674
|
+
if (!path35)
|
|
40642
40675
|
return obj;
|
|
40643
|
-
return
|
|
40676
|
+
return path35.reduce((acc, key) => acc?.[key], obj);
|
|
40644
40677
|
}
|
|
40645
40678
|
function promiseAllObject2(promisesObj) {
|
|
40646
40679
|
const keys = Object.keys(promisesObj);
|
|
@@ -41049,11 +41082,11 @@ function explicitlyAborted2(x, startIndex = 0) {
|
|
|
41049
41082
|
}
|
|
41050
41083
|
return false;
|
|
41051
41084
|
}
|
|
41052
|
-
function prefixIssues2(
|
|
41085
|
+
function prefixIssues2(path35, issues) {
|
|
41053
41086
|
return issues.map((iss) => {
|
|
41054
41087
|
var _a32;
|
|
41055
41088
|
(_a32 = iss).path ?? (_a32.path = []);
|
|
41056
|
-
iss.path.unshift(
|
|
41089
|
+
iss.path.unshift(path35);
|
|
41057
41090
|
return iss;
|
|
41058
41091
|
});
|
|
41059
41092
|
}
|
|
@@ -41198,16 +41231,16 @@ function flattenError2(error512, mapper = (issue32) => issue32.message) {
|
|
|
41198
41231
|
}
|
|
41199
41232
|
function formatError3(error512, mapper = (issue32) => issue32.message) {
|
|
41200
41233
|
const fieldErrors = { _errors: [] };
|
|
41201
|
-
const processError = (error522,
|
|
41234
|
+
const processError = (error522, path35 = []) => {
|
|
41202
41235
|
for (const issue32 of error522.issues) {
|
|
41203
41236
|
if (issue32.code === "invalid_union" && issue32.errors.length) {
|
|
41204
|
-
issue32.errors.map((issues) => processError({ issues }, [...
|
|
41237
|
+
issue32.errors.map((issues) => processError({ issues }, [...path35, ...issue32.path]));
|
|
41205
41238
|
} else if (issue32.code === "invalid_key") {
|
|
41206
|
-
processError({ issues: issue32.issues }, [...
|
|
41239
|
+
processError({ issues: issue32.issues }, [...path35, ...issue32.path]);
|
|
41207
41240
|
} else if (issue32.code === "invalid_element") {
|
|
41208
|
-
processError({ issues: issue32.issues }, [...
|
|
41241
|
+
processError({ issues: issue32.issues }, [...path35, ...issue32.path]);
|
|
41209
41242
|
} else {
|
|
41210
|
-
const fullpath = [...
|
|
41243
|
+
const fullpath = [...path35, ...issue32.path];
|
|
41211
41244
|
if (fullpath.length === 0) {
|
|
41212
41245
|
fieldErrors._errors.push(mapper(issue32));
|
|
41213
41246
|
} else {
|
|
@@ -41234,17 +41267,17 @@ function formatError3(error512, mapper = (issue32) => issue32.message) {
|
|
|
41234
41267
|
}
|
|
41235
41268
|
function treeifyError2(error512, mapper = (issue32) => issue32.message) {
|
|
41236
41269
|
const result = { errors: [] };
|
|
41237
|
-
const processError = (error522,
|
|
41270
|
+
const processError = (error522, path35 = []) => {
|
|
41238
41271
|
var _a32, _b;
|
|
41239
41272
|
for (const issue32 of error522.issues) {
|
|
41240
41273
|
if (issue32.code === "invalid_union" && issue32.errors.length) {
|
|
41241
|
-
issue32.errors.map((issues) => processError({ issues }, [...
|
|
41274
|
+
issue32.errors.map((issues) => processError({ issues }, [...path35, ...issue32.path]));
|
|
41242
41275
|
} else if (issue32.code === "invalid_key") {
|
|
41243
|
-
processError({ issues: issue32.issues }, [...
|
|
41276
|
+
processError({ issues: issue32.issues }, [...path35, ...issue32.path]);
|
|
41244
41277
|
} else if (issue32.code === "invalid_element") {
|
|
41245
|
-
processError({ issues: issue32.issues }, [...
|
|
41278
|
+
processError({ issues: issue32.issues }, [...path35, ...issue32.path]);
|
|
41246
41279
|
} else {
|
|
41247
|
-
const fullpath = [...
|
|
41280
|
+
const fullpath = [...path35, ...issue32.path];
|
|
41248
41281
|
if (fullpath.length === 0) {
|
|
41249
41282
|
result.errors.push(mapper(issue32));
|
|
41250
41283
|
continue;
|
|
@@ -41276,8 +41309,8 @@ function treeifyError2(error512, mapper = (issue32) => issue32.message) {
|
|
|
41276
41309
|
}
|
|
41277
41310
|
function toDotPath2(_path) {
|
|
41278
41311
|
const segs = [];
|
|
41279
|
-
const
|
|
41280
|
-
for (const seg of
|
|
41312
|
+
const path35 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
41313
|
+
for (const seg of path35) {
|
|
41281
41314
|
if (typeof seg === "number")
|
|
41282
41315
|
segs.push(`[${seg}]`);
|
|
41283
41316
|
else if (typeof seg === "symbol")
|
|
@@ -53798,13 +53831,13 @@ function resolveRef2(ref, ctx) {
|
|
|
53798
53831
|
if (!ref.startsWith("#")) {
|
|
53799
53832
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
53800
53833
|
}
|
|
53801
|
-
const
|
|
53802
|
-
if (
|
|
53834
|
+
const path35 = ref.slice(1).split("/").filter(Boolean);
|
|
53835
|
+
if (path35.length === 0) {
|
|
53803
53836
|
return ctx.rootSchema;
|
|
53804
53837
|
}
|
|
53805
53838
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
53806
|
-
if (
|
|
53807
|
-
const key =
|
|
53839
|
+
if (path35[0] === defsKey) {
|
|
53840
|
+
const key = path35[1];
|
|
53808
53841
|
if (!key || !ctx.defs[key]) {
|
|
53809
53842
|
throw new Error(`Reference not found: ${ref}`);
|
|
53810
53843
|
}
|
|
@@ -56555,7 +56588,9 @@ function killProcess2(child, forceTimeoutMs = 3e3) {
|
|
|
56555
56588
|
try {
|
|
56556
56589
|
execSync3(`taskkill /PID ${child.pid} /T /F`, {
|
|
56557
56590
|
stdio: "pipe",
|
|
56558
|
-
timeout: 5e3
|
|
56591
|
+
timeout: 5e3,
|
|
56592
|
+
// 콘솔 없는 호스트에서 taskkill 호출 시 새 콘솔 창이 깜빡이는 것을 방지한다.
|
|
56593
|
+
windowsHide: true
|
|
56559
56594
|
});
|
|
56560
56595
|
} catch {
|
|
56561
56596
|
child.kill("SIGKILL");
|
|
@@ -56627,7 +56662,12 @@ var BaseConnection2 = class extends EventEmitter6 {
|
|
|
56627
56662
|
cwd: this.cwd,
|
|
56628
56663
|
stdio: ["pipe", "pipe", "pipe"],
|
|
56629
56664
|
env: this.env,
|
|
56630
|
-
windowsVerbatimArguments: true
|
|
56665
|
+
windowsVerbatimArguments: true,
|
|
56666
|
+
// 콘솔이 없는 호스트(예: fleet-console 백엔드)에서 cmd.exe를 spawn하면
|
|
56667
|
+
// Windows가 새 콘솔 창을 할당해 깜빡인다. stdio는 모두 pipe라 가시 콘솔이
|
|
56668
|
+
// 불필요하므로 CREATE_NO_WINDOW로 창 생성을 억제한다. (fleet-cli처럼 콘솔이
|
|
56669
|
+
// 이미 있는 경우에도 무해하다.)
|
|
56670
|
+
windowsHide: true
|
|
56631
56671
|
}) : spawn3(this.command, this.args, {
|
|
56632
56672
|
cwd: this.cwd,
|
|
56633
56673
|
stdio: ["pipe", "pipe", "pipe"],
|
|
@@ -57381,7 +57421,9 @@ function resolveNpxPath2(env) {
|
|
|
57381
57421
|
encoding: "utf-8",
|
|
57382
57422
|
stdio: "pipe",
|
|
57383
57423
|
timeout: 5e3,
|
|
57384
|
-
env
|
|
57424
|
+
env,
|
|
57425
|
+
// 콘솔 없는 호스트에서 `where npx` 실행 시 콘솔 창이 깜빡이는 것을 방지한다.
|
|
57426
|
+
windowsHide: true
|
|
57385
57427
|
}).trim();
|
|
57386
57428
|
const candidates = result.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
57387
57429
|
if (windows) {
|
|
@@ -71400,7 +71442,7 @@ function createSessionCaptureHookExec(deps) {
|
|
|
71400
71442
|
deps.provider
|
|
71401
71443
|
] : [deps.entryPath, "hook", "capture-session", deps.provider];
|
|
71402
71444
|
return {
|
|
71403
|
-
command: deps.execPath ??
|
|
71445
|
+
command: deps.execPath ?? process6.execPath,
|
|
71404
71446
|
args
|
|
71405
71447
|
};
|
|
71406
71448
|
}
|
|
@@ -71758,15 +71800,21 @@ function claudeHooks2(options2) {
|
|
|
71758
71800
|
if (!hookExec) {
|
|
71759
71801
|
throw new Error("Fleet Claude session hook command is required");
|
|
71760
71802
|
}
|
|
71761
|
-
const
|
|
71803
|
+
const userPromptSubmitExecs = [options2.captureSessionHookExec, options2.turnStartHookExec].filter((exec) => exec !== void 0);
|
|
71804
|
+
const stopExecs = [options2.turnEndHookExec].filter((exec) => exec !== void 0);
|
|
71762
71805
|
return {
|
|
71763
71806
|
hooks: {
|
|
71764
71807
|
SessionStart: [{
|
|
71765
71808
|
hooks: [claudeCommandHook2(hookExec)]
|
|
71766
71809
|
}],
|
|
71767
|
-
...
|
|
71810
|
+
...userPromptSubmitExecs.length > 0 ? {
|
|
71768
71811
|
UserPromptSubmit: [{
|
|
71769
|
-
hooks:
|
|
71812
|
+
hooks: userPromptSubmitExecs.map(claudeCommandHook2)
|
|
71813
|
+
}]
|
|
71814
|
+
} : {},
|
|
71815
|
+
...stopExecs.length > 0 ? {
|
|
71816
|
+
Stop: [{
|
|
71817
|
+
hooks: stopExecs.map(claudeCommandHook2)
|
|
71770
71818
|
}]
|
|
71771
71819
|
} : {}
|
|
71772
71820
|
}
|
|
@@ -72529,11 +72577,17 @@ async function injectAgentCliProfile2(profile, options2) {
|
|
|
72529
72577
|
dataDir: options2.dataDir,
|
|
72530
72578
|
rootDir: options2.pluginRootDir,
|
|
72531
72579
|
captureSessionHookExec: options2.captureSessionHookExec,
|
|
72580
|
+
turnStartHookExec: options2.turnStartHookExec,
|
|
72581
|
+
turnEndHookExec: options2.turnEndHookExec,
|
|
72532
72582
|
hookExec: startupDefinitions.host === "claude" ? requireHookExec2(options2.hookExec) : void 0,
|
|
72533
72583
|
withMarketplaceLock: options2.withMarketplaceLock
|
|
72534
72584
|
});
|
|
72535
72585
|
const codexPluginKeys = plugin.codexRegistrations.map((registration) => `${registration.pluginName}@${registration.marketplaceName}`);
|
|
72536
|
-
const codexProfile = profile.id === "codex" ? writeCodexFleetProfile2(profile.env, doctrine, codexPluginKeys,
|
|
72586
|
+
const codexProfile = profile.id === "codex" ? writeCodexFleetProfile2(profile.env, doctrine, codexPluginKeys, {
|
|
72587
|
+
captureSessionHookExec: options2.captureSessionHookExec,
|
|
72588
|
+
turnStartHookExec: options2.turnStartHookExec,
|
|
72589
|
+
turnEndHookExec: options2.turnEndHookExec
|
|
72590
|
+
}, (cleanup2) => tempCleanups.push(cleanup2)) : void 0;
|
|
72537
72591
|
const launchWarnings = [];
|
|
72538
72592
|
for (const registration of plugin.codexRegistrations) {
|
|
72539
72593
|
const registrationWarning = await ensureCodexPluginRegistered2(registration, {
|
|
@@ -72609,7 +72663,7 @@ function writeSystemPromptFile2(cliId, systemPrompt, onCleanup) {
|
|
|
72609
72663
|
chmodBestEffort22(filePath, SYSTEM_PROMPT_FILE_MODE2);
|
|
72610
72664
|
return filePath;
|
|
72611
72665
|
}
|
|
72612
|
-
function writeCodexFleetProfile2(env, doctrine, pluginKeys,
|
|
72666
|
+
function writeCodexFleetProfile2(env, doctrine, pluginKeys, hookExecs, onCleanup) {
|
|
72613
72667
|
const codexHome = env.CODEX_HOME ?? path93__default.join(env.HOME ?? os22__default.homedir(), ".codex");
|
|
72614
72668
|
mkdirSync8(codexHome, { recursive: true });
|
|
72615
72669
|
pruneStaleCodexFleetProfiles2(codexHome);
|
|
@@ -72629,19 +72683,31 @@ function writeCodexFleetProfile2(env, doctrine, pluginKeys, captureSessionHookEx
|
|
|
72629
72683
|
"enabled = true",
|
|
72630
72684
|
""
|
|
72631
72685
|
]),
|
|
72632
|
-
...
|
|
72686
|
+
...codexHooksConfig2(hookExecs)
|
|
72633
72687
|
].join("\n"));
|
|
72634
72688
|
chmodBestEffort22(profilePath, SYSTEM_PROMPT_FILE_MODE2);
|
|
72635
72689
|
return { profileName, profilePath };
|
|
72636
72690
|
}
|
|
72637
|
-
function
|
|
72638
|
-
|
|
72639
|
-
const
|
|
72640
|
-
return [
|
|
72641
|
-
|
|
72642
|
-
|
|
72643
|
-
|
|
72644
|
-
|
|
72691
|
+
function codexHooksConfig2(hookExecs) {
|
|
72692
|
+
const userPromptSubmitExecs = [hookExecs.captureSessionHookExec, hookExecs.turnStartHookExec].filter((exec) => exec !== void 0);
|
|
72693
|
+
const stopExecs = [hookExecs.turnEndHookExec].filter((exec) => exec !== void 0);
|
|
72694
|
+
if (userPromptSubmitExecs.length === 0 && stopExecs.length === 0) return [];
|
|
72695
|
+
const lines = ["[hooks]"];
|
|
72696
|
+
if (userPromptSubmitExecs.length > 0) {
|
|
72697
|
+
lines.push(`UserPromptSubmit = ${codexHookHandlersInline2(userPromptSubmitExecs)}`);
|
|
72698
|
+
}
|
|
72699
|
+
if (stopExecs.length > 0) {
|
|
72700
|
+
lines.push(`Stop = ${codexHookHandlersInline2(stopExecs)}`);
|
|
72701
|
+
}
|
|
72702
|
+
lines.push("");
|
|
72703
|
+
return lines;
|
|
72704
|
+
}
|
|
72705
|
+
function codexHookHandlersInline2(execs) {
|
|
72706
|
+
const handlers = execs.map((exec) => {
|
|
72707
|
+
const command22 = buildPosixShellCommand2([exec.command, ...exec.args]);
|
|
72708
|
+
return `{ type = "command", command = "${escapeTomlBasicString22(command22)}" }`;
|
|
72709
|
+
}).join(", ");
|
|
72710
|
+
return `[{ hooks = [${handlers}] }]`;
|
|
72645
72711
|
}
|
|
72646
72712
|
function writeFileNoFollow22(filePath, content) {
|
|
72647
72713
|
const flags = constants8.O_WRONLY | constants8.O_CREAT | constants8.O_TRUNC | constants8.O_NOFOLLOW;
|
|
@@ -80781,6 +80847,12 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
80781
80847
|
session.status = status;
|
|
80782
80848
|
return toTerminalSessionInfo(session);
|
|
80783
80849
|
}
|
|
80850
|
+
function setTerminalSessionTurnState(sessionId, turnState) {
|
|
80851
|
+
const session = terminalSessionsById.get(sessionId);
|
|
80852
|
+
if (!session) return null;
|
|
80853
|
+
session.turnState = turnState;
|
|
80854
|
+
return toTerminalSessionInfo(session);
|
|
80855
|
+
}
|
|
80784
80856
|
function transitionTerminalSessionToDormant(sessionId, providerSession) {
|
|
80785
80857
|
const session = terminalSessionsById.get(sessionId);
|
|
80786
80858
|
if (!session) return null;
|
|
@@ -80848,6 +80920,7 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
80848
80920
|
subscribeAll,
|
|
80849
80921
|
updateTerminalSessionProviderSession,
|
|
80850
80922
|
updateTerminalSessionStatus,
|
|
80923
|
+
setTerminalSessionTurnState,
|
|
80851
80924
|
transitionTerminalSessionToDormant,
|
|
80852
80925
|
removeTerminalSession,
|
|
80853
80926
|
registerTerminalRuntimeSession,
|
|
@@ -80916,6 +80989,7 @@ function toTerminalSessionInfo(state) {
|
|
|
80916
80989
|
cliId: state.cliId,
|
|
80917
80990
|
cliLabel: state.cliLabel,
|
|
80918
80991
|
status: state.status,
|
|
80992
|
+
turnState: state.turnState ?? "none",
|
|
80919
80993
|
createdAt: state.createdAt,
|
|
80920
80994
|
theaterId: state.theaterId,
|
|
80921
80995
|
registrationId: state.registrationId,
|
|
@@ -81132,6 +81206,126 @@ function resolveConsolePath(pathname) {
|
|
|
81132
81206
|
if (!path93__default.extname(withoutPrefix)) return "index.html";
|
|
81133
81207
|
return withoutPrefix;
|
|
81134
81208
|
}
|
|
81209
|
+
var TerminalFolderListError = class extends Error {
|
|
81210
|
+
code;
|
|
81211
|
+
constructor(code) {
|
|
81212
|
+
super(code);
|
|
81213
|
+
this.name = "TerminalFolderListError";
|
|
81214
|
+
this.code = code;
|
|
81215
|
+
}
|
|
81216
|
+
};
|
|
81217
|
+
var DIRECTORY_ENTRY_CAP = 500;
|
|
81218
|
+
var WINDOWS_DRIVE_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split("");
|
|
81219
|
+
async function listTerminalFolders(requestedPath, deps = {}) {
|
|
81220
|
+
const platform2 = deps.platform ?? process.platform;
|
|
81221
|
+
const stat5 = deps.stat ?? fs5__default.promises.stat;
|
|
81222
|
+
const opendir = deps.opendir ?? fs5__default.promises.opendir;
|
|
81223
|
+
const targetPath = normalizeListPath(requestedPath, platform2, deps);
|
|
81224
|
+
const roots = await listRoots(platform2, stat5);
|
|
81225
|
+
const targetStat = await statDirectory(targetPath, stat5);
|
|
81226
|
+
if (!targetStat.isDirectory()) throw new TerminalFolderListError("invalid_path");
|
|
81227
|
+
const entries = [];
|
|
81228
|
+
const truncated = await collectDirectoryEntries(targetPath, opendir, stat5, entries);
|
|
81229
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
81230
|
+
return {
|
|
81231
|
+
path: targetPath,
|
|
81232
|
+
parentPath: parentPath(targetPath, platform2),
|
|
81233
|
+
roots,
|
|
81234
|
+
entries,
|
|
81235
|
+
...truncated ? { truncated: true } : {}
|
|
81236
|
+
};
|
|
81237
|
+
}
|
|
81238
|
+
function normalizeFolderBrowserPath(value, platform2 = process.platform) {
|
|
81239
|
+
if (typeof value !== "string" || value.length === 0 || value.includes("\0")) throw new TerminalFolderListError("invalid_path");
|
|
81240
|
+
if (isWindowsAmbiguousPath(value, platform2) || !path93__default.isAbsolute(value)) throw new TerminalFolderListError("invalid_path");
|
|
81241
|
+
return path93__default.resolve(value);
|
|
81242
|
+
}
|
|
81243
|
+
function normalizeListPath(requestedPath, platform2, deps) {
|
|
81244
|
+
if (requestedPath === null || requestedPath === void 0) {
|
|
81245
|
+
const home = deps.homedir?.() ?? os22__default.homedir();
|
|
81246
|
+
const start = home || deps.cwd?.() || process.cwd();
|
|
81247
|
+
return path93__default.resolve(start);
|
|
81248
|
+
}
|
|
81249
|
+
return normalizeFolderBrowserPath(requestedPath, platform2);
|
|
81250
|
+
}
|
|
81251
|
+
async function listRoots(platform2, stat5) {
|
|
81252
|
+
if (platform2 !== "win32") return ["/"];
|
|
81253
|
+
const roots = [];
|
|
81254
|
+
await Promise.all(WINDOWS_DRIVE_LETTERS.map(async (letter) => {
|
|
81255
|
+
const root = `${letter}:\\`;
|
|
81256
|
+
try {
|
|
81257
|
+
if ((await stat5(root)).isDirectory()) roots.push(root);
|
|
81258
|
+
} catch {
|
|
81259
|
+
}
|
|
81260
|
+
}));
|
|
81261
|
+
return roots.sort();
|
|
81262
|
+
}
|
|
81263
|
+
async function statDirectory(targetPath, stat5) {
|
|
81264
|
+
try {
|
|
81265
|
+
return await stat5(targetPath);
|
|
81266
|
+
} catch (error512) {
|
|
81267
|
+
throw mapFsError(error512);
|
|
81268
|
+
}
|
|
81269
|
+
}
|
|
81270
|
+
async function collectDirectoryEntries(targetPath, opendir, stat5, entries) {
|
|
81271
|
+
const directory = await openDirectory(targetPath, opendir);
|
|
81272
|
+
try {
|
|
81273
|
+
let dirent = await directory.read();
|
|
81274
|
+
while (dirent !== null) {
|
|
81275
|
+
const entry = await toTerminalFolderEntry(targetPath, dirent, stat5);
|
|
81276
|
+
if (entry !== null) {
|
|
81277
|
+
if (entries.length >= DIRECTORY_ENTRY_CAP) return true;
|
|
81278
|
+
entries.push(entry);
|
|
81279
|
+
}
|
|
81280
|
+
dirent = await directory.read();
|
|
81281
|
+
}
|
|
81282
|
+
return false;
|
|
81283
|
+
} catch (error512) {
|
|
81284
|
+
throw mapFsError(error512);
|
|
81285
|
+
} finally {
|
|
81286
|
+
await directory.close();
|
|
81287
|
+
}
|
|
81288
|
+
}
|
|
81289
|
+
async function openDirectory(targetPath, opendir) {
|
|
81290
|
+
try {
|
|
81291
|
+
return await opendir(targetPath);
|
|
81292
|
+
} catch (error512) {
|
|
81293
|
+
throw mapFsError(error512);
|
|
81294
|
+
}
|
|
81295
|
+
}
|
|
81296
|
+
async function toTerminalFolderEntry(targetPath, dirent, stat5) {
|
|
81297
|
+
if (!dirent.isDirectory() && !dirent.isSymbolicLink()) return null;
|
|
81298
|
+
const entryPath = path93__default.join(targetPath, dirent.name);
|
|
81299
|
+
if (dirent.isDirectory()) return { name: dirent.name, path: entryPath, kind: "dir", accessible: true };
|
|
81300
|
+
const accessible = await statSymlinkDirectory(entryPath, stat5);
|
|
81301
|
+
if (accessible === null) return null;
|
|
81302
|
+
return { name: dirent.name, path: entryPath, kind: "dir", accessible };
|
|
81303
|
+
}
|
|
81304
|
+
async function statSymlinkDirectory(entryPath, stat5) {
|
|
81305
|
+
try {
|
|
81306
|
+
return (await stat5(entryPath)).isDirectory() ? true : null;
|
|
81307
|
+
} catch {
|
|
81308
|
+
return false;
|
|
81309
|
+
}
|
|
81310
|
+
}
|
|
81311
|
+
function mapFsError(error512) {
|
|
81312
|
+
const code = error512.code;
|
|
81313
|
+
if (code === "EACCES" || code === "EPERM") return new TerminalFolderListError("forbidden");
|
|
81314
|
+
if (code === "ENOENT" || code === "ENOTDIR") return new TerminalFolderListError("not_found");
|
|
81315
|
+
return new TerminalFolderListError("invalid_path");
|
|
81316
|
+
}
|
|
81317
|
+
function parentPath(targetPath, platform2) {
|
|
81318
|
+
const parsed = path93__default.parse(targetPath);
|
|
81319
|
+
const resolved = path93__default.resolve(targetPath);
|
|
81320
|
+
if (resolved === path93__default.resolve(parsed.root)) return null;
|
|
81321
|
+
const parent = path93__default.dirname(resolved);
|
|
81322
|
+
if (platform2 === "win32" && parent === resolved) return null;
|
|
81323
|
+
return parent;
|
|
81324
|
+
}
|
|
81325
|
+
function isWindowsAmbiguousPath(value, platform2) {
|
|
81326
|
+
if (platform2 !== "win32") return false;
|
|
81327
|
+
return /^[a-zA-Z]:(?![\\/])/.test(value) || /^[\\/](?![\\/])/.test(value);
|
|
81328
|
+
}
|
|
81135
81329
|
var GRANT_ID_BYTES = 24;
|
|
81136
81330
|
var DEFAULT_GRANT_TTL_MS = 6e4;
|
|
81137
81331
|
function createFolderGrantStore(deps = {}) {
|
|
@@ -81163,165 +81357,15 @@ function createFolderGrantStore(deps = {}) {
|
|
|
81163
81357
|
return { issue: issue32, consume };
|
|
81164
81358
|
}
|
|
81165
81359
|
function validateAbsoluteDirectory(cwd, statSync52 = fs5__default.statSync) {
|
|
81166
|
-
if (
|
|
81360
|
+
if (typeof cwd !== "string" || cwd.length === 0 || cwd.includes("\0")) throw new Error("invalid_folder");
|
|
81361
|
+
if (isWindowsAmbiguousPath2(cwd) || !path93__default.isAbsolute(cwd)) throw new Error("invalid_folder");
|
|
81167
81362
|
const normalized = path93__default.resolve(cwd);
|
|
81168
81363
|
if (!statSync52(normalized).isDirectory()) throw new Error("invalid_folder");
|
|
81169
81364
|
return normalized;
|
|
81170
81365
|
}
|
|
81171
|
-
|
|
81172
|
-
|
|
81173
|
-
|
|
81174
|
-
using System;
|
|
81175
|
-
using System.Runtime.InteropServices;
|
|
81176
|
-
namespace FleetPicker {
|
|
81177
|
-
[ComImport, Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
81178
|
-
public interface IShellItem {
|
|
81179
|
-
void BindToHandler();
|
|
81180
|
-
void GetParent();
|
|
81181
|
-
[PreserveSig] int GetDisplayName(int sigdn, out IntPtr ppszName);
|
|
81182
|
-
void GetAttributes();
|
|
81183
|
-
void Compare();
|
|
81184
|
-
}
|
|
81185
|
-
[ComImport, Guid("d57c7288-d4ad-4768-be02-9d969532d960"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
81186
|
-
public interface IFileOpenDialog {
|
|
81187
|
-
[PreserveSig] int Show(IntPtr parent);
|
|
81188
|
-
void SetFileTypes(); void SetFileTypeIndex(); void GetFileTypeIndex();
|
|
81189
|
-
void Advise(); void Unadvise();
|
|
81190
|
-
[PreserveSig] int SetOptions(uint fos);
|
|
81191
|
-
[PreserveSig] int GetOptions(out uint pfos);
|
|
81192
|
-
void SetDefaultFolder();
|
|
81193
|
-
void SetFolder(IShellItem psi);
|
|
81194
|
-
void GetFolder(); void GetCurrentSelection();
|
|
81195
|
-
void SetFileName(); void GetFileName(); void SetTitle(); void SetOkButtonLabel(); void SetFileNameLabel();
|
|
81196
|
-
[PreserveSig] int GetResult(out IShellItem ppsi);
|
|
81197
|
-
void AddPlace(IShellItem psi, int fdap);
|
|
81198
|
-
void SetDefaultExtension(); void Close(); void SetClientGuid(); void ClearClientData(); void SetFilter();
|
|
81199
|
-
void GetResults(); void GetSelectedItems();
|
|
81200
|
-
}
|
|
81201
|
-
[ComImport, Guid("DC1C5A9C-E88A-4DDE-A5A1-60F82A20AEF7")] public class FileOpenDialog { }
|
|
81202
|
-
public static class Picker {
|
|
81203
|
-
[DllImport("shell32.dll", CharSet=CharSet.Unicode, PreserveSig=false)]
|
|
81204
|
-
static extern void SHCreateItemFromParsingName(string pszPath, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem ppv);
|
|
81205
|
-
static IShellItem ItemFromPath(string path) {
|
|
81206
|
-
Guid iid = new Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe");
|
|
81207
|
-
IShellItem it; SHCreateItemFromParsingName(path, IntPtr.Zero, ref iid, out it); return it;
|
|
81208
|
-
}
|
|
81209
|
-
public static string Pick(string initialPath) {
|
|
81210
|
-
var dlg = (IFileOpenDialog)(new FileOpenDialog());
|
|
81211
|
-
uint opts; dlg.GetOptions(out opts);
|
|
81212
|
-
dlg.SetOptions(opts | 0x20); // FOS_PICKFOLDERS
|
|
81213
|
-
if (!string.IsNullOrEmpty(initialPath)) {
|
|
81214
|
-
// \uC2DC\uC791 \uD3F4\uB354\uB97C WSL \uC704\uCE58\uB85C \uC9C0\uC815\uD558\uACE0 \uC88C\uCE21\uC5D0 \uACE0\uC815(FDAP_TOP). \uC2E4\uD328\uD574\uB3C4 \uAE30\uBCF8 \uC704\uCE58\uB85C \uC9C4\uD589\uD55C\uB2E4.
|
|
81215
|
-
try { IShellItem s = ItemFromPath(initialPath); dlg.AddPlace(s, 1); dlg.SetFolder(s); } catch { }
|
|
81216
|
-
}
|
|
81217
|
-
if (dlg.Show(IntPtr.Zero) != 0) return null; // \uCDE8\uC18C/\uC2E4\uD328 \uC2DC null
|
|
81218
|
-
IShellItem item; dlg.GetResult(out item);
|
|
81219
|
-
IntPtr ptr; if (item.GetDisplayName(unchecked((int)0x80058000), out ptr) != 0) return null; // SIGDN_FILESYSPATH; \uBE44 \uD30C\uC77C\uC2DC\uC2A4\uD15C \uC120\uD0DD \uAC00\uB4DC
|
|
81220
|
-
string path = Marshal.PtrToStringAuto(ptr);
|
|
81221
|
-
Marshal.FreeCoTaskMem(ptr);
|
|
81222
|
-
return path;
|
|
81223
|
-
}
|
|
81224
|
-
}
|
|
81225
|
-
}`;
|
|
81226
|
-
function createNativeFolderPicker(deps = {}) {
|
|
81227
|
-
const platform2 = deps.platform ?? process.platform;
|
|
81228
|
-
const runCommand = deps.runCommand ?? runNativeCommand;
|
|
81229
|
-
const statSync52 = deps.statSync ?? fs5__default.statSync;
|
|
81230
|
-
const readProcVersion = deps.readProcVersion ?? defaultReadProcVersion;
|
|
81231
|
-
const env = deps.env ?? process.env;
|
|
81232
|
-
return async () => {
|
|
81233
|
-
const isWsl = platform2 === "linux" && detectWsl(readProcVersion, env);
|
|
81234
|
-
const wslStartPath = isWsl ? wslStartFolderUnc(env) : "";
|
|
81235
|
-
const commands = buildPickerCommands(platform2, isWsl, wslStartPath);
|
|
81236
|
-
if (commands.length === 0) return { kind: "error", error: "unsupported_platform" };
|
|
81237
|
-
for (const command22 of commands) {
|
|
81238
|
-
const result = await runPickerCommand(runCommand, command22);
|
|
81239
|
-
if ("kind" in result && result.kind === "unavailable") continue;
|
|
81240
|
-
if ("kind" in result && result.kind === "cancelled") return { kind: "cancelled" };
|
|
81241
|
-
if ("kind" in result && result.kind === "timeout") return { kind: "error", error: "dialog_timeout" };
|
|
81242
|
-
if ("kind" in result) continue;
|
|
81243
|
-
let resolvedPath = result.stdout.trim();
|
|
81244
|
-
if (command22.postProcess === "wslpath") {
|
|
81245
|
-
try {
|
|
81246
|
-
const wslResult = await runCommand("wslpath", ["-u", resolvedPath]);
|
|
81247
|
-
resolvedPath = wslResult.stdout.trim();
|
|
81248
|
-
} catch {
|
|
81249
|
-
return { kind: "error", error: "invalid_folder" };
|
|
81250
|
-
}
|
|
81251
|
-
}
|
|
81252
|
-
try {
|
|
81253
|
-
return { kind: "selected", cwd: validateAbsoluteDirectory(resolvedPath, statSync52) };
|
|
81254
|
-
} catch {
|
|
81255
|
-
return { kind: "error", error: "invalid_folder" };
|
|
81256
|
-
}
|
|
81257
|
-
}
|
|
81258
|
-
return { kind: "error", error: "dialog_unavailable" };
|
|
81259
|
-
};
|
|
81260
|
-
}
|
|
81261
|
-
function defaultReadProcVersion() {
|
|
81262
|
-
try {
|
|
81263
|
-
return fs5__default.readFileSync("/proc/version", "utf8");
|
|
81264
|
-
} catch {
|
|
81265
|
-
return "";
|
|
81266
|
-
}
|
|
81267
|
-
}
|
|
81268
|
-
function detectWsl(readProcVersion, env) {
|
|
81269
|
-
if (env.WSL_INTEROP !== void 0 || env.WSL_DISTRO_NAME !== void 0) return true;
|
|
81270
|
-
return /microsoft|wsl/i.test(readProcVersion());
|
|
81271
|
-
}
|
|
81272
|
-
function buildPickerCommands(platform2, isWsl = false, wslStartPath = "") {
|
|
81273
|
-
if (platform2 === "darwin") {
|
|
81274
|
-
return [{ bin: "osascript", args: ["-e", 'POSIX path of (choose folder with prompt "Choose a Fleet workspace")'] }];
|
|
81275
|
-
}
|
|
81276
|
-
if (platform2 === "linux") {
|
|
81277
|
-
const commands = [];
|
|
81278
|
-
if (isWsl) {
|
|
81279
|
-
commands.push({ bin: "powershell.exe", args: buildPowerShellPickerArgs(wslStartPath), postProcess: "wslpath" });
|
|
81280
|
-
}
|
|
81281
|
-
commands.push(
|
|
81282
|
-
{ bin: "zenity", args: ["--file-selection", "--directory", "--title=Choose a Fleet workspace"] },
|
|
81283
|
-
{ bin: "kdialog", args: ["--getexistingdirectory", ".", "Choose a Fleet workspace"] }
|
|
81284
|
-
);
|
|
81285
|
-
return commands;
|
|
81286
|
-
}
|
|
81287
|
-
if (platform2 === "win32") {
|
|
81288
|
-
return [{ bin: "powershell.exe", args: buildPowerShellPickerArgs("") }];
|
|
81289
|
-
}
|
|
81290
|
-
return [];
|
|
81291
|
-
}
|
|
81292
|
-
function buildPowerShellPickerArgs(initialWindowsPath) {
|
|
81293
|
-
const escaped = initialWindowsPath.replace(/'/g, "''");
|
|
81294
|
-
const script = [
|
|
81295
|
-
"[Console]::OutputEncoding=[Text.Encoding]::UTF8",
|
|
81296
|
-
`Add-Type -TypeDefinition '${POWERSHELL_FOLDER_PICKER_CSHARP}'`,
|
|
81297
|
-
`$selection = [FleetPicker.Picker]::Pick('${escaped}')`,
|
|
81298
|
-
"if ([string]::IsNullOrEmpty($selection)) { exit 1 }",
|
|
81299
|
-
"[Console]::Out.Write($selection)"
|
|
81300
|
-
].join("\n");
|
|
81301
|
-
return ["-NoProfile", "-Sta", "-Command", script];
|
|
81302
|
-
}
|
|
81303
|
-
function wslStartFolderUnc(env) {
|
|
81304
|
-
const distro = env.WSL_DISTRO_NAME;
|
|
81305
|
-
if (!distro) return "";
|
|
81306
|
-
const home = env.HOME;
|
|
81307
|
-
if (home && home.startsWith("/") && !home.startsWith("/mnt/")) {
|
|
81308
|
-
return `\\\\wsl.localhost\\${distro}${home.replace(/\//g, "\\")}`;
|
|
81309
|
-
}
|
|
81310
|
-
return `\\\\wsl.localhost\\${distro}`;
|
|
81311
|
-
}
|
|
81312
|
-
async function runPickerCommand(runCommand, command22) {
|
|
81313
|
-
try {
|
|
81314
|
-
return await runCommand(command22.bin, command22.args);
|
|
81315
|
-
} catch (error512) {
|
|
81316
|
-
const err = error512;
|
|
81317
|
-
if (err.code === "ENOENT") return { kind: "unavailable" };
|
|
81318
|
-
if (err.code === "ETIMEDOUT") return { kind: "timeout" };
|
|
81319
|
-
return { kind: "cancelled" };
|
|
81320
|
-
}
|
|
81321
|
-
}
|
|
81322
|
-
async function runNativeCommand(bin, args) {
|
|
81323
|
-
const result = await execFileAsync(bin, [...args], { timeout: DIALOG_TIMEOUT_MS, windowsHide: true });
|
|
81324
|
-
return { stdout: result.stdout, stderr: result.stderr };
|
|
81366
|
+
function isWindowsAmbiguousPath2(value) {
|
|
81367
|
+
if (process.platform !== "win32") return false;
|
|
81368
|
+
return /^[a-zA-Z]:(?![\\/])/.test(value) || /^[\\/](?![\\/])/.test(value);
|
|
81325
81369
|
}
|
|
81326
81370
|
var JAVASCRIPT_ENTRY_EXTENSIONS2 = /* @__PURE__ */ new Set([".cjs", ".js", ".mjs"]);
|
|
81327
81371
|
var TYPESCRIPT_ENTRY_EXTENSIONS2 = /* @__PURE__ */ new Set([".cts", ".mts", ".ts", ".tsx"]);
|
|
@@ -81330,23 +81374,10 @@ function buildConsoleHookCommand(entry) {
|
|
|
81330
81374
|
if (entry === void 0) {
|
|
81331
81375
|
throw new Error("Fleet Console session hook command requires the current console entry path");
|
|
81332
81376
|
}
|
|
81333
|
-
|
|
81334
|
-
|
|
81335
|
-
|
|
81336
|
-
|
|
81337
|
-
args: [entry.entryPath, "hook", "subagents-context"]
|
|
81338
|
-
};
|
|
81339
|
-
}
|
|
81340
|
-
if (TYPESCRIPT_ENTRY_EXTENSIONS2.has(extension)) {
|
|
81341
|
-
if (!entry.tsxLoaderPath) {
|
|
81342
|
-
throw new Error("Fleet Console session hook command for TypeScript entries requires a tsx loader path");
|
|
81343
|
-
}
|
|
81344
|
-
return {
|
|
81345
|
-
command: entry.execPath,
|
|
81346
|
-
args: ["--import", pathToFileURL2(entry.tsxLoaderPath).href, entry.entryPath, "hook", "subagents-context"]
|
|
81347
|
-
};
|
|
81348
|
-
}
|
|
81349
|
-
throw new Error(`Unsupported Fleet Console session hook entry extension: ${extension}`);
|
|
81377
|
+
return buildConsoleCliHookExec(entry, ["hook", "subagents-context"]);
|
|
81378
|
+
}
|
|
81379
|
+
function buildConsoleTurnHookCommand(entry, phase) {
|
|
81380
|
+
return buildConsoleCliHookExec(entry, ["hook", phase === "start" ? "turn-start" : "turn-end"]);
|
|
81350
81381
|
}
|
|
81351
81382
|
function buildConsoleCaptureHookCommand(entry, cliId) {
|
|
81352
81383
|
const extension = path93__default.extname(entry.entryPath);
|
|
@@ -81377,7 +81408,9 @@ function runCodexCommand2(command22) {
|
|
|
81377
81408
|
const result = spawnSync2(command22.bin, command22.args, {
|
|
81378
81409
|
cwd: command22.cwd,
|
|
81379
81410
|
encoding: "utf8",
|
|
81380
|
-
env: command22.env
|
|
81411
|
+
env: command22.env,
|
|
81412
|
+
// 콘솔 없는 fleet-console 백엔드에서 codex 등록 명령 실행 시 콘솔 창이 깜빡이는 것을 방지한다.
|
|
81413
|
+
windowsHide: true
|
|
81381
81414
|
});
|
|
81382
81415
|
return {
|
|
81383
81416
|
status: result.status,
|
|
@@ -81390,18 +81423,37 @@ function withConsoleMarketplaceLock(target, fn) {
|
|
|
81390
81423
|
mkdirSync8(path93__default.dirname(lockDir), { recursive: true });
|
|
81391
81424
|
return withDirectoryLock2({ lockDir }, fn);
|
|
81392
81425
|
}
|
|
81426
|
+
function buildConsoleCliHookExec(entry, trailingArgs) {
|
|
81427
|
+
const extension = path93__default.extname(entry.entryPath);
|
|
81428
|
+
if (JAVASCRIPT_ENTRY_EXTENSIONS2.has(extension)) {
|
|
81429
|
+
return {
|
|
81430
|
+
command: entry.execPath,
|
|
81431
|
+
args: [entry.entryPath, ...trailingArgs]
|
|
81432
|
+
};
|
|
81433
|
+
}
|
|
81434
|
+
if (TYPESCRIPT_ENTRY_EXTENSIONS2.has(extension)) {
|
|
81435
|
+
if (!entry.tsxLoaderPath) {
|
|
81436
|
+
throw new Error("Fleet Console session hook command for TypeScript entries requires a tsx loader path");
|
|
81437
|
+
}
|
|
81438
|
+
return {
|
|
81439
|
+
command: entry.execPath,
|
|
81440
|
+
args: ["--import", pathToFileURL2(entry.tsxLoaderPath).href, entry.entryPath, ...trailingArgs]
|
|
81441
|
+
};
|
|
81442
|
+
}
|
|
81443
|
+
throw new Error(`Unsupported Fleet Console session hook entry extension: ${extension}`);
|
|
81444
|
+
}
|
|
81393
81445
|
var DEFAULT_TERMINAL_CWD_FALLBACK = os22__default.homedir;
|
|
81394
81446
|
var TERMINAL_TERM = "xterm-256color";
|
|
81395
81447
|
var CONSOLE_ENTRY_PATH = fileURLToPath(import.meta.url);
|
|
81396
81448
|
var HOOK_ENTRY_EXTENSIONS = /* @__PURE__ */ new Set([".cjs", ".cts", ".js", ".mjs", ".mts", ".ts", ".tsx"]);
|
|
81397
81449
|
var require2 = createRequire(import.meta.url);
|
|
81398
81450
|
function createDefaultTerminalLaunchResolver(deps = {}) {
|
|
81399
|
-
const baseCwd = deps.cwd ??
|
|
81400
|
-
const env = deps.env ??
|
|
81401
|
-
const execPath = deps.execPath ??
|
|
81451
|
+
const baseCwd = deps.cwd ?? process6.cwd();
|
|
81452
|
+
const env = deps.env ?? process6.env;
|
|
81453
|
+
const execPath = deps.execPath ?? process6.execPath;
|
|
81402
81454
|
const homedir32 = deps.homedir ?? DEFAULT_TERMINAL_CWD_FALLBACK;
|
|
81403
|
-
const platform2 = deps.platform ??
|
|
81404
|
-
const entryPath = resolveHookEntryPath(deps.entryPath ??
|
|
81455
|
+
const platform2 = deps.platform ?? process6.platform;
|
|
81456
|
+
const entryPath = resolveHookEntryPath(deps.entryPath ?? process6.argv[1]);
|
|
81405
81457
|
const tsxLoaderPath = deps.tsxLoaderPath ?? resolveOptionalPackage("tsx");
|
|
81406
81458
|
const dataDir = deps.dataDir ?? getFleetDataDir2();
|
|
81407
81459
|
const infraServices = deps.infraServices ?? createInfraServices2();
|
|
@@ -81462,7 +81514,7 @@ function hasHookEntryExtension(entryPath) {
|
|
|
81462
81514
|
}
|
|
81463
81515
|
function startTerminalShell(launch, size) {
|
|
81464
81516
|
const { spawn: spawnPty } = require2("node-pty");
|
|
81465
|
-
const useConptyDll = resolveUseConptyDll2(
|
|
81517
|
+
const useConptyDll = resolveUseConptyDll2(process6.platform, process6.env);
|
|
81466
81518
|
return spawnPty(launch.bin, [...launch.args], {
|
|
81467
81519
|
cols: size.cols,
|
|
81468
81520
|
rows: size.rows,
|
|
@@ -81498,6 +81550,8 @@ async function createAgentCliLaunchSpec(options2) {
|
|
|
81498
81550
|
dedicatedMcpSession: agentRuntime.dedicatedMcpSession,
|
|
81499
81551
|
enableMetaphor: false,
|
|
81500
81552
|
captureSessionHookExec: buildConsoleCaptureHookCommand(options2.hookEntry, profile.id),
|
|
81553
|
+
turnStartHookExec: buildConsoleTurnHookCommand(options2.hookEntry, "start"),
|
|
81554
|
+
turnEndHookExec: buildConsoleTurnHookCommand(options2.hookEntry, "end"),
|
|
81501
81555
|
hookExec: buildConsoleHookCommand(options2.hookEntry),
|
|
81502
81556
|
onCleanup: (cleanup) => cleanupStack.push(cleanup),
|
|
81503
81557
|
replaceSystemPrompt: false,
|
|
@@ -81596,6 +81650,8 @@ var DEFAULT_COLS = 80;
|
|
|
81596
81650
|
var DEFAULT_ROWS2 = 24;
|
|
81597
81651
|
var DEFAULT_SCROLLBACK_LIMIT = 512;
|
|
81598
81652
|
var WS_OPEN_STATE = 1;
|
|
81653
|
+
var THEATER_SHELL_SESSION_PREFIX = "shell:";
|
|
81654
|
+
var THEATER_SHELL_DETACH_GRACE_MS = 4e3;
|
|
81599
81655
|
function createTerminalSessionManager(deps) {
|
|
81600
81656
|
const startShell2 = deps.startShell ?? startTerminalShell;
|
|
81601
81657
|
const scrollbackLimit = deps.scrollbackLimit ?? DEFAULT_SCROLLBACK_LIMIT;
|
|
@@ -81606,6 +81662,7 @@ function createTerminalSessionManager(deps) {
|
|
|
81606
81662
|
}
|
|
81607
81663
|
async function attach(socket, context) {
|
|
81608
81664
|
const session = await getOrCreateSession(context);
|
|
81665
|
+
clearGraceTimer(session);
|
|
81609
81666
|
if (session.activeSocket && session.activeSocket !== socket) {
|
|
81610
81667
|
session.activeSocket.close(4e3, "terminal_replaced");
|
|
81611
81668
|
}
|
|
@@ -81685,7 +81742,8 @@ function createTerminalSessionManager(deps) {
|
|
|
81685
81742
|
renameCommand: launch.renameCommand,
|
|
81686
81743
|
activeSocket: null,
|
|
81687
81744
|
cols: DEFAULT_COLS,
|
|
81688
|
-
rows: DEFAULT_ROWS2
|
|
81745
|
+
rows: DEFAULT_ROWS2,
|
|
81746
|
+
graceTimer: null
|
|
81689
81747
|
};
|
|
81690
81748
|
const dataDisposable = pty.onData((data) => handlePtyData(session, data));
|
|
81691
81749
|
const exitDisposable = pty.onExit(() => removeSession(session));
|
|
@@ -81723,6 +81781,13 @@ function createTerminalSessionManager(deps) {
|
|
|
81723
81781
|
function detachSocket(session, socket) {
|
|
81724
81782
|
if (session.activeSocket !== socket) return;
|
|
81725
81783
|
session.activeSocket = null;
|
|
81784
|
+
if (isTheaterShell(session.id)) {
|
|
81785
|
+
clearGraceTimer(session);
|
|
81786
|
+
session.graceTimer = setTimeout(() => {
|
|
81787
|
+
session.graceTimer = null;
|
|
81788
|
+
if (session.activeSocket === null) removeSession(session);
|
|
81789
|
+
}, THEATER_SHELL_DETACH_GRACE_MS);
|
|
81790
|
+
}
|
|
81726
81791
|
}
|
|
81727
81792
|
function replayScrollback(session, socket) {
|
|
81728
81793
|
for (const chunk of session.scrollback) {
|
|
@@ -81738,6 +81803,7 @@ function createTerminalSessionManager(deps) {
|
|
|
81738
81803
|
}
|
|
81739
81804
|
async function killSession(session, options2 = {}) {
|
|
81740
81805
|
const killPty = options2.killPty ?? true;
|
|
81806
|
+
clearGraceTimer(session);
|
|
81741
81807
|
session.activeSocket?.close(4001, "terminal_closed");
|
|
81742
81808
|
session.activeSocket = null;
|
|
81743
81809
|
for (const disposable of session.disposables) disposable.dispose();
|
|
@@ -81761,6 +81827,14 @@ function killPtyBestEffort2(pty) {
|
|
|
81761
81827
|
} catch {
|
|
81762
81828
|
}
|
|
81763
81829
|
}
|
|
81830
|
+
function isTheaterShell(sessionId) {
|
|
81831
|
+
return sessionId.startsWith(THEATER_SHELL_SESSION_PREFIX);
|
|
81832
|
+
}
|
|
81833
|
+
function clearGraceTimer(session) {
|
|
81834
|
+
if (session.graceTimer === null) return;
|
|
81835
|
+
clearTimeout(session.graceTimer);
|
|
81836
|
+
session.graceTimer = null;
|
|
81837
|
+
}
|
|
81764
81838
|
function toBuffer(data) {
|
|
81765
81839
|
if (Buffer.isBuffer(data)) return data;
|
|
81766
81840
|
if (Array.isArray(data)) return Buffer.concat(data);
|
|
@@ -81804,7 +81878,7 @@ function createTerminalTicketRegistry(deps = {}) {
|
|
|
81804
81878
|
}
|
|
81805
81879
|
return { ttlMs, issue: issue32, consume, prune };
|
|
81806
81880
|
}
|
|
81807
|
-
var
|
|
81881
|
+
var execFileAsync = promisify(execFile2);
|
|
81808
81882
|
var GIT_STATUS_TIMEOUT_MS = 4e3;
|
|
81809
81883
|
var GIT_STATUS_MAX_BUFFER = 1024 * 1024;
|
|
81810
81884
|
var GIT_HASH_TIMEOUT_MS = 4e3;
|
|
@@ -81813,11 +81887,13 @@ function createWorkspaceChangeScanner() {
|
|
|
81813
81887
|
return {
|
|
81814
81888
|
async snapshot(cwd) {
|
|
81815
81889
|
try {
|
|
81816
|
-
const { stdout } = await
|
|
81890
|
+
const { stdout } = await execFileAsync("git", ["status", "--porcelain=v1", "-z", "--untracked-files=all"], {
|
|
81817
81891
|
cwd,
|
|
81818
81892
|
encoding: "utf8",
|
|
81819
81893
|
maxBuffer: GIT_STATUS_MAX_BUFFER,
|
|
81820
|
-
timeout: GIT_STATUS_TIMEOUT_MS
|
|
81894
|
+
timeout: GIT_STATUS_TIMEOUT_MS,
|
|
81895
|
+
// 콘솔 없는 fleet-console 백엔드에서 git.exe 실행 시 콘솔 창이 깜빡이는 것을 방지한다.
|
|
81896
|
+
windowsHide: true
|
|
81821
81897
|
});
|
|
81822
81898
|
const entries = parseGitStatusPorcelainZ(stdout);
|
|
81823
81899
|
if (!entries) return null;
|
|
@@ -81877,7 +81953,9 @@ function execGitHashObject(cwd, paths) {
|
|
|
81877
81953
|
cwd,
|
|
81878
81954
|
encoding: "utf8",
|
|
81879
81955
|
maxBuffer: GIT_HASH_MAX_BUFFER,
|
|
81880
|
-
timeout: GIT_HASH_TIMEOUT_MS
|
|
81956
|
+
timeout: GIT_HASH_TIMEOUT_MS,
|
|
81957
|
+
// 콘솔 없는 fleet-console 백엔드에서 git.exe 실행 시 콘솔 창이 깜빡이는 것을 방지한다.
|
|
81958
|
+
windowsHide: true
|
|
81881
81959
|
},
|
|
81882
81960
|
(error512, stdout) => {
|
|
81883
81961
|
if (error512) {
|
|
@@ -82054,6 +82132,7 @@ function createConsoleUpdateCheckService(deps = {}) {
|
|
|
82054
82132
|
var DEFAULT_HOST22 = "127.0.0.1";
|
|
82055
82133
|
var DEFAULT_PORT22 = 0;
|
|
82056
82134
|
var SHELL_TERMINAL_SESSION_ID = "shell";
|
|
82135
|
+
var THEATER_SHELL_SESSION_PREFIX2 = "shell:";
|
|
82057
82136
|
var SERVER_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
82058
82137
|
var MAX_BODY_BYTES = 1024 * 1024;
|
|
82059
82138
|
function createConsoleServer(deps = {}) {
|
|
@@ -82098,7 +82177,6 @@ function createConsoleServer(deps = {}) {
|
|
|
82098
82177
|
getPort: () => lockHandle?.payload.port ?? port,
|
|
82099
82178
|
getAdminToken: () => lockHandle?.payload.token ?? null
|
|
82100
82179
|
});
|
|
82101
|
-
const pickTerminalFolder = deps.terminalPickFolder ?? createNativeFolderPicker();
|
|
82102
82180
|
const pendingRuntimeSessions = /* @__PURE__ */ new Map();
|
|
82103
82181
|
const terminalSessions = createTerminalSessionManager({
|
|
82104
82182
|
launch: deps.terminalLaunch ?? createDefaultTerminalLaunchResolver({
|
|
@@ -82180,8 +82258,12 @@ function createConsoleServer(deps = {}) {
|
|
|
82180
82258
|
runAsyncHandler(handleTerminalTicket(req, res), res);
|
|
82181
82259
|
return;
|
|
82182
82260
|
}
|
|
82183
|
-
if (pathname === "/terminal/folders/
|
|
82184
|
-
runAsyncHandler(
|
|
82261
|
+
if (pathname === "/terminal/folders/list") {
|
|
82262
|
+
runAsyncHandler(handleTerminalFoldersList(req, res), res);
|
|
82263
|
+
return;
|
|
82264
|
+
}
|
|
82265
|
+
if (pathname === "/terminal/folders/grants") {
|
|
82266
|
+
runAsyncHandler(handleTerminalFolderGrants(req, res), res);
|
|
82185
82267
|
return;
|
|
82186
82268
|
}
|
|
82187
82269
|
if (pathname === "/terminal/sessions") {
|
|
@@ -82193,6 +82275,11 @@ function createConsoleServer(deps = {}) {
|
|
|
82193
82275
|
runAsyncHandler(handleTerminalSessionResume(req, res, decodeURIComponent(terminalSessionResumeMatch[1] ?? "")), res);
|
|
82194
82276
|
return;
|
|
82195
82277
|
}
|
|
82278
|
+
const terminalSessionTurnMatch = pathname.match(/^\/terminal\/sessions\/([^/]+)\/turn$/);
|
|
82279
|
+
if (terminalSessionTurnMatch) {
|
|
82280
|
+
runAsyncHandler(handleTerminalSessionTurn(req, res, decodeURIComponent(terminalSessionTurnMatch[1] ?? "")), res);
|
|
82281
|
+
return;
|
|
82282
|
+
}
|
|
82196
82283
|
const terminalSessionItemMatch = pathname.match(/^\/terminal\/sessions\/([^/]+)$/);
|
|
82197
82284
|
if (terminalSessionItemMatch) {
|
|
82198
82285
|
runAsyncHandler(handleTerminalSessionItem(req, res, decodeURIComponent(terminalSessionItemMatch[1] ?? "")), res);
|
|
@@ -82259,6 +82346,30 @@ function createConsoleServer(deps = {}) {
|
|
|
82259
82346
|
};
|
|
82260
82347
|
writeJson(res, 200, body);
|
|
82261
82348
|
}
|
|
82349
|
+
async function handleTerminalSessionTurn(req, res, sessionId) {
|
|
82350
|
+
if (req.method !== "POST") {
|
|
82351
|
+
writeJson(res, 405, { error: "Method not allowed" });
|
|
82352
|
+
return;
|
|
82353
|
+
}
|
|
82354
|
+
const token = lockHandle?.payload.token;
|
|
82355
|
+
if (!token || req.headers.authorization !== `Bearer ${token}`) {
|
|
82356
|
+
writeJson(res, 401, { error: "Unauthorized" });
|
|
82357
|
+
return;
|
|
82358
|
+
}
|
|
82359
|
+
const body = await readJsonBody(req);
|
|
82360
|
+
const turnState = body?.phase === "start" ? "running" : body?.phase === "end" ? "ended" : null;
|
|
82361
|
+
if (turnState === null) {
|
|
82362
|
+
writeJson(res, 400, { error: "invalid_phase" });
|
|
82363
|
+
return;
|
|
82364
|
+
}
|
|
82365
|
+
const updated = observability.setTerminalSessionTurnState(sessionId, turnState);
|
|
82366
|
+
if (!updated) {
|
|
82367
|
+
writeJson(res, 404, { error: "terminal_session_not_found" });
|
|
82368
|
+
return;
|
|
82369
|
+
}
|
|
82370
|
+
observability.notifySessionUpdated(updated);
|
|
82371
|
+
writeJson(res, 200, { ok: true });
|
|
82372
|
+
}
|
|
82262
82373
|
async function handleTerminalTicket(req, res) {
|
|
82263
82374
|
if (req.method !== "POST") {
|
|
82264
82375
|
writeJson(res, 405, { error: "Method not allowed" });
|
|
@@ -82271,16 +82382,29 @@ function createConsoleServer(deps = {}) {
|
|
|
82271
82382
|
const body = await readJsonBody(req);
|
|
82272
82383
|
const kind = body?.kind === "shell" ? "shell" : "fleet";
|
|
82273
82384
|
const requestedSessionId = body?.sessionId;
|
|
82385
|
+
const requestedTheaterId = typeof body?.theaterId === "string" ? body.theaterId : void 0;
|
|
82274
82386
|
let sessionId;
|
|
82387
|
+
let cwd;
|
|
82275
82388
|
if (kind === "shell") {
|
|
82276
|
-
|
|
82389
|
+
if (typeof requestedSessionId === "string" && requestedSessionId.startsWith(THEATER_SHELL_SESSION_PREFIX2) && requestedTheaterId) {
|
|
82390
|
+
const theater = theaters.get(requestedTheaterId);
|
|
82391
|
+
if (!theater) {
|
|
82392
|
+
writeJson(res, 404, { error: "theater_not_found" });
|
|
82393
|
+
return;
|
|
82394
|
+
}
|
|
82395
|
+
sessionId = requestedSessionId;
|
|
82396
|
+
cwd = theater.path;
|
|
82397
|
+
} else {
|
|
82398
|
+
sessionId = SHELL_TERMINAL_SESSION_ID;
|
|
82399
|
+
cwd = "";
|
|
82400
|
+
}
|
|
82277
82401
|
} else if (typeof requestedSessionId === "string" && requestedSessionId.length > 0) {
|
|
82278
82402
|
sessionId = requestedSessionId;
|
|
82403
|
+
cwd = observability.getLaunchCwd(sessionId);
|
|
82279
82404
|
} else {
|
|
82280
82405
|
writeJson(res, 400, { error: "terminal_session_not_found" });
|
|
82281
82406
|
return;
|
|
82282
82407
|
}
|
|
82283
|
-
const cwd = kind === "shell" ? "" : observability.getLaunchCwd(sessionId);
|
|
82284
82408
|
if (cwd === null) {
|
|
82285
82409
|
writeJson(res, 404, { error: "terminal_session_not_found" });
|
|
82286
82410
|
return;
|
|
@@ -82295,7 +82419,7 @@ function createConsoleServer(deps = {}) {
|
|
|
82295
82419
|
kind
|
|
82296
82420
|
}));
|
|
82297
82421
|
}
|
|
82298
|
-
async function
|
|
82422
|
+
async function handleTerminalFoldersList(req, res) {
|
|
82299
82423
|
if (req.method !== "POST") {
|
|
82300
82424
|
writeJson(res, 405, { error: "Method not allowed" });
|
|
82301
82425
|
return;
|
|
@@ -82304,16 +82428,41 @@ function createConsoleServer(deps = {}) {
|
|
|
82304
82428
|
writeJson(res, 401, { error: "unauthorized" });
|
|
82305
82429
|
return;
|
|
82306
82430
|
}
|
|
82307
|
-
const
|
|
82308
|
-
if (
|
|
82309
|
-
writeJson(res,
|
|
82431
|
+
const body = await readJsonBody(req);
|
|
82432
|
+
if (!isPlainObject22(body) || body.path !== void 0 && body.path !== null && typeof body.path !== "string") {
|
|
82433
|
+
writeJson(res, 400, { error: "invalid_path" });
|
|
82434
|
+
return;
|
|
82435
|
+
}
|
|
82436
|
+
try {
|
|
82437
|
+
const payload = await listTerminalFolders(body.path === void 0 ? null : body.path);
|
|
82438
|
+
writeJson(res, 200, payload);
|
|
82439
|
+
} catch (error512) {
|
|
82440
|
+
if (error512 instanceof TerminalFolderListError) {
|
|
82441
|
+
writeJson(res, terminalFolderListStatus(error512), { error: error512.code });
|
|
82442
|
+
return;
|
|
82443
|
+
}
|
|
82444
|
+
throw error512;
|
|
82445
|
+
}
|
|
82446
|
+
}
|
|
82447
|
+
async function handleTerminalFolderGrants(req, res) {
|
|
82448
|
+
if (req.method !== "POST") {
|
|
82449
|
+
writeJson(res, 405, { error: "Method not allowed" });
|
|
82450
|
+
return;
|
|
82451
|
+
}
|
|
82452
|
+
if (!isTerminalAuthorized(req)) {
|
|
82453
|
+
writeJson(res, 401, { error: "unauthorized" });
|
|
82310
82454
|
return;
|
|
82311
82455
|
}
|
|
82312
|
-
|
|
82313
|
-
|
|
82456
|
+
const body = await readJsonBody(req);
|
|
82457
|
+
if (!isPlainObject22(body) || typeof body.path !== "string") {
|
|
82458
|
+
writeJson(res, 400, { error: "invalid_folder" });
|
|
82314
82459
|
return;
|
|
82315
82460
|
}
|
|
82316
|
-
|
|
82461
|
+
try {
|
|
82462
|
+
writeJson(res, 200, { folderGrantId: folderGrants.issue(body.path) });
|
|
82463
|
+
} catch {
|
|
82464
|
+
writeJson(res, 400, { error: "invalid_folder" });
|
|
82465
|
+
}
|
|
82317
82466
|
}
|
|
82318
82467
|
async function handleTerminalSessions(req, res) {
|
|
82319
82468
|
if (!isTerminalAuthorized(req)) {
|
|
@@ -82443,19 +82592,20 @@ function createConsoleServer(deps = {}) {
|
|
|
82443
82592
|
writeJson(res, 401, { error: "unauthorized" });
|
|
82444
82593
|
return;
|
|
82445
82594
|
}
|
|
82446
|
-
const
|
|
82447
|
-
if (
|
|
82448
|
-
writeJson(res,
|
|
82595
|
+
const body = await readJsonBody(req);
|
|
82596
|
+
if (!isPlainObject22(body) || typeof body.folderGrantId !== "string") {
|
|
82597
|
+
writeJson(res, 400, { error: "invalid_folder_grant" });
|
|
82449
82598
|
return;
|
|
82450
82599
|
}
|
|
82451
|
-
|
|
82452
|
-
|
|
82600
|
+
const cwd = folderGrants.consume(body.folderGrantId);
|
|
82601
|
+
if (!cwd) {
|
|
82602
|
+
writeJson(res, 400, { error: "invalid_folder_grant" });
|
|
82453
82603
|
return;
|
|
82454
82604
|
}
|
|
82455
|
-
const theater = await theaters.register(
|
|
82605
|
+
const theater = await theaters.register(cwd);
|
|
82456
82606
|
let hasWiki = false;
|
|
82457
82607
|
try {
|
|
82458
|
-
await codex.registerWorkspace(
|
|
82608
|
+
await codex.registerWorkspace(cwd);
|
|
82459
82609
|
hasWiki = true;
|
|
82460
82610
|
} catch (error512) {
|
|
82461
82611
|
if (!(error512 instanceof Error && error512.message === "knowledge_root_missing")) {
|
|
@@ -82475,11 +82625,7 @@ function createConsoleServer(deps = {}) {
|
|
|
82475
82625
|
return;
|
|
82476
82626
|
}
|
|
82477
82627
|
const operations = observability.listDurableOperations().filter((operation) => operation.theaterId === theaterId);
|
|
82478
|
-
|
|
82479
|
-
if (!removed) {
|
|
82480
|
-
writeJson(res, 404, { error: "theater_not_found" });
|
|
82481
|
-
return;
|
|
82482
|
-
}
|
|
82628
|
+
theaters.remove(theaterId);
|
|
82483
82629
|
for (const operation of operations) forgetTerminalSession(operation.sessionId, { persist: false });
|
|
82484
82630
|
persistDurableState();
|
|
82485
82631
|
writeJson(res, 200, { ok: true });
|
|
@@ -82867,6 +83013,14 @@ function readOptionalAgentCliId(value, res) {
|
|
|
82867
83013
|
return false;
|
|
82868
83014
|
}
|
|
82869
83015
|
}
|
|
83016
|
+
function terminalFolderListStatus(error512) {
|
|
83017
|
+
if (error512.code === "forbidden") return 403;
|
|
83018
|
+
if (error512.code === "not_found") return 404;
|
|
83019
|
+
return 400;
|
|
83020
|
+
}
|
|
83021
|
+
function isPlainObject22(value) {
|
|
83022
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
83023
|
+
}
|
|
82870
83024
|
async function readJsonBody(req) {
|
|
82871
83025
|
const chunks = [];
|
|
82872
83026
|
let total = 0;
|
|
@@ -82926,9 +83080,9 @@ function isAllowedTerminalOrigin(req, expectedPort) {
|
|
|
82926
83080
|
return origin === `http://127.0.0.1:${expectedPort}`;
|
|
82927
83081
|
}
|
|
82928
83082
|
var CAPTURE_TEMP_PREFIX = ".capture.";
|
|
82929
|
-
async function runCaptureSessionHook(provider, env =
|
|
83083
|
+
async function runCaptureSessionHook(provider, env = process6.env) {
|
|
82930
83084
|
return captureSession({
|
|
82931
|
-
diagnostics:
|
|
83085
|
+
diagnostics: process6.stderr,
|
|
82932
83086
|
env,
|
|
82933
83087
|
input: await readStdin(),
|
|
82934
83088
|
provider
|
|
@@ -82945,12 +83099,12 @@ function captureSession(options2) {
|
|
|
82945
83099
|
}
|
|
82946
83100
|
function captureSessionStrict(options2) {
|
|
82947
83101
|
const provider = parseProvider(options2.provider);
|
|
82948
|
-
const fleetSessionId = readFleetSessionId(options2.env ??
|
|
83102
|
+
const fleetSessionId = readFleetSessionId(options2.env ?? process6.env);
|
|
82949
83103
|
const input = parseHookInput(options2.input ?? "");
|
|
82950
83104
|
const providerSession = toProviderSession(provider, input, options2.now ?? (() => /* @__PURE__ */ new Date()));
|
|
82951
83105
|
const capturesDir = (options2.paths ?? createConsoleDataPaths()).capturesDir;
|
|
82952
83106
|
const finalPath = path93__default.join(capturesDir, `${fleetSessionId}.json`);
|
|
82953
|
-
const tempPath = path93__default.join(capturesDir, `${CAPTURE_TEMP_PREFIX}${fleetSessionId}.${
|
|
83107
|
+
const tempPath = path93__default.join(capturesDir, `${CAPTURE_TEMP_PREFIX}${fleetSessionId}.${process6.pid}.${Date.now()}.tmp`);
|
|
82954
83108
|
fs5__default.mkdirSync(capturesDir, { recursive: true, mode: 448 });
|
|
82955
83109
|
fs5__default.writeFileSync(tempPath, `${JSON.stringify(providerSession, null, 2)}
|
|
82956
83110
|
`, { mode: 384 });
|
|
@@ -82990,11 +83144,11 @@ function toProviderSession(provider, input, now) {
|
|
|
82990
83144
|
function readStdin() {
|
|
82991
83145
|
return new Promise((resolve2, reject) => {
|
|
82992
83146
|
const chunks = [];
|
|
82993
|
-
|
|
83147
|
+
process6.stdin.on("data", (chunk) => {
|
|
82994
83148
|
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
82995
83149
|
});
|
|
82996
|
-
|
|
82997
|
-
|
|
83150
|
+
process6.stdin.on("error", reject);
|
|
83151
|
+
process6.stdin.on("end", () => resolve2(Buffer.concat(chunks).toString("utf8")));
|
|
82998
83152
|
});
|
|
82999
83153
|
}
|
|
83000
83154
|
function createConsoleStalePolicy(deps = {}) {
|
|
@@ -83009,10 +83163,40 @@ function createConsoleStalePolicy(deps = {}) {
|
|
|
83009
83163
|
}
|
|
83010
83164
|
return { isBuildStale };
|
|
83011
83165
|
}
|
|
83166
|
+
var TURN_POST_TIMEOUT_MS = 1500;
|
|
83167
|
+
async function runTurnStateHook(phase, env = process6.env, options2 = {}) {
|
|
83168
|
+
try {
|
|
83169
|
+
await postTurnState(phase, env, options2);
|
|
83170
|
+
} catch {
|
|
83171
|
+
}
|
|
83172
|
+
}
|
|
83173
|
+
async function postTurnState(phase, env, options2) {
|
|
83174
|
+
const sessionId = env.FLEET_CONSOLE_SESSION_ID;
|
|
83175
|
+
if (!sessionId) return;
|
|
83176
|
+
const paths = createConsolePaths({ env });
|
|
83177
|
+
const lock = createConsoleLock().readLock(paths.lockFile);
|
|
83178
|
+
if (!lock) return;
|
|
83179
|
+
const fetchImpl = options2.fetchImpl ?? fetch;
|
|
83180
|
+
const controller = new AbortController();
|
|
83181
|
+
const timer = setTimeout(() => controller.abort(), options2.timeoutMs ?? TURN_POST_TIMEOUT_MS);
|
|
83182
|
+
try {
|
|
83183
|
+
await fetchImpl(`${lock.endpoint}terminal/sessions/${encodeURIComponent(sessionId)}/turn`, {
|
|
83184
|
+
method: "POST",
|
|
83185
|
+
headers: {
|
|
83186
|
+
authorization: `Bearer ${lock.token}`,
|
|
83187
|
+
"content-type": "application/json"
|
|
83188
|
+
},
|
|
83189
|
+
body: JSON.stringify({ phase }),
|
|
83190
|
+
signal: controller.signal
|
|
83191
|
+
});
|
|
83192
|
+
} finally {
|
|
83193
|
+
clearTimeout(timer);
|
|
83194
|
+
}
|
|
83195
|
+
}
|
|
83012
83196
|
var FIXED_HOST = "127.0.0.1";
|
|
83013
83197
|
var HELP_BANNER_INDENT = " ";
|
|
83014
83198
|
var DEFAULT_HELP_RELEASE = "local";
|
|
83015
|
-
var CONSOLE_HOOK_COMMANDS = /* @__PURE__ */ new Set(["capture-session", "subagents-context"]);
|
|
83199
|
+
var CONSOLE_HOOK_COMMANDS = /* @__PURE__ */ new Set(["capture-session", "subagents-context", "turn-start", "turn-end"]);
|
|
83016
83200
|
function parseConsoleCliMode(argv2) {
|
|
83017
83201
|
if (argv2.length === 0) return "start";
|
|
83018
83202
|
const [first, ...rest] = argv2;
|
|
@@ -83043,6 +83227,8 @@ function parseConsoleHookCommand(argv2) {
|
|
|
83043
83227
|
throw new Error("Unknown fleet-console hook command");
|
|
83044
83228
|
}
|
|
83045
83229
|
if (commandName === "subagents-context" && rest.length === 0) return { command: "subagents-context" };
|
|
83230
|
+
if (commandName === "turn-start" && rest.length === 0) return { command: "turn-start" };
|
|
83231
|
+
if (commandName === "turn-end" && rest.length === 0) return { command: "turn-end" };
|
|
83046
83232
|
if (commandName === "capture-session" && rest.length === 1 && rest[0]) return { command: "capture-session", provider: rest[0] };
|
|
83047
83233
|
throw new Error("Unknown fleet-console hook command");
|
|
83048
83234
|
}
|
|
@@ -83106,8 +83292,8 @@ function buildWikiHelpText(options2 = {}) {
|
|
|
83106
83292
|
return colorEnabled ? text : stripAnsi2(text);
|
|
83107
83293
|
}
|
|
83108
83294
|
function createConsoleDaemonLifecycle(deps = {}) {
|
|
83109
|
-
const env = deps.env ??
|
|
83110
|
-
const execPath = deps.execPath ??
|
|
83295
|
+
const env = deps.env ?? process6.env;
|
|
83296
|
+
const execPath = deps.execPath ?? process6.execPath;
|
|
83111
83297
|
const serverModulePath = deps.serverModulePath ?? resolveDefaultServerModulePath();
|
|
83112
83298
|
const spawnDetached = deps.spawnDetached ?? ((bin, args, options2) => {
|
|
83113
83299
|
spawn3(bin, [...args], options2).unref();
|
|
@@ -83121,10 +83307,10 @@ function createConsoleDaemonLifecycle(deps = {}) {
|
|
|
83121
83307
|
const server = createConsoleServer();
|
|
83122
83308
|
await server.start(paths);
|
|
83123
83309
|
await new Promise((resolve2) => {
|
|
83124
|
-
|
|
83310
|
+
process6.once("SIGTERM", () => {
|
|
83125
83311
|
void server.stop().finally(resolve2);
|
|
83126
83312
|
});
|
|
83127
|
-
|
|
83313
|
+
process6.once("SIGINT", () => {
|
|
83128
83314
|
void server.stop().finally(resolve2);
|
|
83129
83315
|
});
|
|
83130
83316
|
});
|
|
@@ -83138,14 +83324,14 @@ function createConsoleDaemonLifecycle(deps = {}) {
|
|
|
83138
83324
|
const payload = readTrustedLock();
|
|
83139
83325
|
if (!payload) return;
|
|
83140
83326
|
try {
|
|
83141
|
-
|
|
83327
|
+
process6.kill(payload.pid, "SIGTERM");
|
|
83142
83328
|
} catch (err) {
|
|
83143
83329
|
if (err.code !== "ESRCH") throw err;
|
|
83144
83330
|
}
|
|
83145
83331
|
await sleep(200);
|
|
83146
83332
|
try {
|
|
83147
|
-
|
|
83148
|
-
|
|
83333
|
+
process6.kill(payload.pid, 0);
|
|
83334
|
+
process6.kill(payload.pid, "SIGKILL");
|
|
83149
83335
|
} catch (err) {
|
|
83150
83336
|
if (err.code !== "ESRCH") throw err;
|
|
83151
83337
|
}
|
|
@@ -83263,51 +83449,55 @@ async function runConsoleRestart(deps = {}) {
|
|
|
83263
83449
|
return openFleetConsole({ lifecycle, openBrowser: deps.openBrowser });
|
|
83264
83450
|
}
|
|
83265
83451
|
async function main() {
|
|
83266
|
-
if (
|
|
83452
|
+
if (process6.argv[2] === "serve") {
|
|
83267
83453
|
await createConsoleDaemonLifecycle().runServer();
|
|
83268
83454
|
return;
|
|
83269
83455
|
}
|
|
83270
|
-
if (
|
|
83271
|
-
const hookCommand = parseConsoleHookCommand(
|
|
83456
|
+
if (process6.argv[2] === "hook") {
|
|
83457
|
+
const hookCommand = parseConsoleHookCommand(process6.argv.slice(3));
|
|
83272
83458
|
if (hookCommand.command === "subagents-context") {
|
|
83273
|
-
|
|
83459
|
+
process6.stdout.write(`${runSubagentsContextHook(process6.env)}
|
|
83274
83460
|
`);
|
|
83275
83461
|
return;
|
|
83276
83462
|
}
|
|
83277
|
-
|
|
83463
|
+
if (hookCommand.command === "turn-start" || hookCommand.command === "turn-end") {
|
|
83464
|
+
await runTurnStateHook(hookCommand.command === "turn-start" ? "start" : "end", process6.env);
|
|
83465
|
+
return;
|
|
83466
|
+
}
|
|
83467
|
+
await runCaptureSessionHook(hookCommand.provider, process6.env);
|
|
83278
83468
|
return;
|
|
83279
83469
|
}
|
|
83280
|
-
if (
|
|
83281
|
-
await mainWiki(
|
|
83470
|
+
if (process6.argv[2] === "codex") {
|
|
83471
|
+
await mainWiki(process6.argv.slice(3));
|
|
83282
83472
|
return;
|
|
83283
83473
|
}
|
|
83284
|
-
const mode = parseConsoleCliMode(
|
|
83474
|
+
const mode = parseConsoleCliMode(process6.argv.slice(2));
|
|
83285
83475
|
if (mode === "help") {
|
|
83286
|
-
|
|
83476
|
+
process6.stdout.write(`${buildConsoleHelpText({ env: process6.env, isTTY: process6.stdout.isTTY })}
|
|
83287
83477
|
`);
|
|
83288
83478
|
return;
|
|
83289
83479
|
}
|
|
83290
83480
|
if (mode === "status") {
|
|
83291
|
-
|
|
83481
|
+
process6.stdout.write(`${await runConsoleStatus()}
|
|
83292
83482
|
`);
|
|
83293
83483
|
return;
|
|
83294
83484
|
}
|
|
83295
83485
|
if (mode === "stop") {
|
|
83296
|
-
|
|
83486
|
+
process6.stdout.write(`${await runConsoleStop()}
|
|
83297
83487
|
`);
|
|
83298
83488
|
return;
|
|
83299
83489
|
}
|
|
83300
83490
|
if (mode === "restart") {
|
|
83301
83491
|
await runConsoleRestart();
|
|
83302
|
-
|
|
83492
|
+
process6.stdout.write("Fleet Console restarted.\n");
|
|
83303
83493
|
return;
|
|
83304
83494
|
}
|
|
83305
83495
|
await openFleetConsole();
|
|
83306
|
-
|
|
83496
|
+
process6.stdout.write("Fleet Console opened.\n");
|
|
83307
83497
|
}
|
|
83308
|
-
async function mainWiki(argv2 =
|
|
83498
|
+
async function mainWiki(argv2 = process6.argv.slice(2)) {
|
|
83309
83499
|
if (argv2.includes("--help") || argv2.includes("-h")) {
|
|
83310
|
-
|
|
83500
|
+
process6.stdout.write(`${buildWikiHelpText({ env: process6.env, isTTY: process6.stdout.isTTY })}
|
|
83311
83501
|
`);
|
|
83312
83502
|
return;
|
|
83313
83503
|
}
|
|
@@ -83319,19 +83509,19 @@ async function mainWiki(argv2 = process5.argv.slice(2)) {
|
|
|
83319
83509
|
if (unsupported.length > 0) {
|
|
83320
83510
|
throw new Error(`Unknown fleet wiki option: ${unsupported[0]}`);
|
|
83321
83511
|
}
|
|
83322
|
-
await openFleetWikiWorkspace({ cwd:
|
|
83512
|
+
await openFleetWikiWorkspace({ cwd: process6.cwd() });
|
|
83323
83513
|
}
|
|
83324
83514
|
function resolveDefaultServerModulePath() {
|
|
83325
83515
|
const builtPath = new URL("../dist/cli.mjs", import.meta.url).pathname;
|
|
83326
83516
|
if (fs5__default.existsSync(builtPath)) return builtPath;
|
|
83327
83517
|
return fileURLToPath(import.meta.url);
|
|
83328
83518
|
}
|
|
83329
|
-
var isDirectRun =
|
|
83519
|
+
var isDirectRun = process6.argv[1] && path93__default.resolve(process6.argv[1]) === fileURLToPath(import.meta.url);
|
|
83330
83520
|
if (isDirectRun) {
|
|
83331
83521
|
await main().catch((error512) => {
|
|
83332
|
-
|
|
83522
|
+
process6.stderr.write(`${error512 instanceof Error ? error512.message : String(error512)}
|
|
83333
83523
|
`);
|
|
83334
|
-
|
|
83524
|
+
process6.exitCode = 1;
|
|
83335
83525
|
});
|
|
83336
83526
|
}
|
|
83337
83527
|
|
|
@@ -91551,7 +91741,7 @@ function reconcileRuntimeState(carrierRuntime) {
|
|
|
91551
91741
|
// src/runtime/workspace-scanner.ts
|
|
91552
91742
|
import { execFile as execFile3 } from "child_process";
|
|
91553
91743
|
import { promisify as promisify2 } from "util";
|
|
91554
|
-
var
|
|
91744
|
+
var execFileAsync2 = promisify2(execFile3);
|
|
91555
91745
|
var GIT_STATUS_TIMEOUT_MS2 = 4e3;
|
|
91556
91746
|
var GIT_STATUS_MAX_BUFFER2 = 1024 * 1024;
|
|
91557
91747
|
var GIT_HASH_TIMEOUT_MS2 = 4e3;
|
|
@@ -91560,11 +91750,13 @@ function createWorkspaceChangeScanner2() {
|
|
|
91560
91750
|
return {
|
|
91561
91751
|
async snapshot(cwd) {
|
|
91562
91752
|
try {
|
|
91563
|
-
const { stdout } = await
|
|
91753
|
+
const { stdout } = await execFileAsync2("git", ["status", "--porcelain=v1", "-z", "--untracked-files=all"], {
|
|
91564
91754
|
cwd,
|
|
91565
91755
|
encoding: "utf8",
|
|
91566
91756
|
maxBuffer: GIT_STATUS_MAX_BUFFER2,
|
|
91567
|
-
timeout: GIT_STATUS_TIMEOUT_MS2
|
|
91757
|
+
timeout: GIT_STATUS_TIMEOUT_MS2,
|
|
91758
|
+
// 콘솔 없는 호스트에서 git.exe 실행 시 콘솔 창이 깜빡이는 것을 방지한다(방어적).
|
|
91759
|
+
windowsHide: true
|
|
91568
91760
|
});
|
|
91569
91761
|
const entries = parseGitStatusPorcelainZ2(stdout);
|
|
91570
91762
|
if (!entries) return null;
|
|
@@ -91623,7 +91815,9 @@ function execGitHashObject2(cwd, paths) {
|
|
|
91623
91815
|
cwd,
|
|
91624
91816
|
encoding: "utf8",
|
|
91625
91817
|
maxBuffer: GIT_HASH_MAX_BUFFER2,
|
|
91626
|
-
timeout: GIT_HASH_TIMEOUT_MS2
|
|
91818
|
+
timeout: GIT_HASH_TIMEOUT_MS2,
|
|
91819
|
+
// 콘솔 없는 호스트에서 git.exe 실행 시 콘솔 창이 깜빡이는 것을 방지한다(방어적).
|
|
91820
|
+
windowsHide: true
|
|
91627
91821
|
},
|
|
91628
91822
|
(error53, stdout) => {
|
|
91629
91823
|
if (error53) {
|