@dotobokuri/fleet-cli 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -25,7 +25,6 @@ Confirm each readiness check below before the Workflow. Work through them in ord
|
|
|
25
25
|
- [ ] **Common** — objective stated (Mission Anchor), mode-fit holds (Mode Gate), Standing Orders binding. → report `common: ready`
|
|
26
26
|
- [ ] **Impact radius** — flag public-surface or API impact, irreversibility, and any security-sensitive surface. → report `impact: <…>`
|
|
27
27
|
- [ ] **Rollback** — identify a rollback-safe checkpoint and any Admiral of the Navy approval point before execution begins. → report `rollback: <…>`
|
|
28
|
-
- [ ] **Isolation** — confirm a working branch or worktree isolates the change; no direct work on the default branch. → report `isolation: <branch>`
|
|
29
28
|
- [ ] **Carrier availability** — confirm the intended carriers are actually exposed and available this session. → report `carriers: <…>`
|
|
30
29
|
- [ ] **Ownership** — pre-sketch each carrier's file or responsibility boundary. → report `ownership: <…>`
|
|
31
30
|
- [ ] **Shared resources** — flag shared mutable resources (same files, lock files, or a singleton test environment). → report `shared: <…|none>`
|
|
@@ -26,7 +26,6 @@ Confirm each readiness check below before the Workflow. Work through them in ord
|
|
|
26
26
|
- [ ] **Doctrine** — enumerate the applicable AGENTS.md files to load for the affected scope. → report `doctrine: <…>`
|
|
27
27
|
- [ ] **Impact radius** — flag public-surface or API impact, irreversibility, and any security-sensitive surface. → report `impact: <…>`
|
|
28
28
|
- [ ] **Rollback** — identify a rollback-safe checkpoint and any Admiral of the Navy approval point before execution begins. → report `rollback: <…>`
|
|
29
|
-
- [ ] **Isolation** — confirm a working branch or worktree isolates the change; no direct work on the default branch. → report `isolation: <branch>`
|
|
30
29
|
- [ ] **Escalation** — if multiple carriers or parallel ownership boundaries are required, re-classify under frontline. → report `escalation: clear`
|
|
31
30
|
|
|
32
31
|
## Workflow
|
package/dist/index.js
CHANGED
|
@@ -141,8 +141,8 @@ var init_resolve_bin = __esm({
|
|
|
141
141
|
// src/release.ts
|
|
142
142
|
import { createRequire as createRequire2 } from "module";
|
|
143
143
|
function readFleetCliRelease() {
|
|
144
|
-
const
|
|
145
|
-
const pkg =
|
|
144
|
+
const requireFromHere2 = createRequire2(import.meta.url);
|
|
145
|
+
const pkg = requireFromHere2("../package.json");
|
|
146
146
|
const version3 = pkg.version ?? "";
|
|
147
147
|
if (pkg.private === true) {
|
|
148
148
|
return { channel: "local", version: version3 };
|
|
@@ -374,16 +374,58 @@ var init_check = __esm({
|
|
|
374
374
|
}
|
|
375
375
|
});
|
|
376
376
|
|
|
377
|
+
// src/update/stop-console.ts
|
|
378
|
+
import { spawn as spawn4 } from "child_process";
|
|
379
|
+
import { createRequire as createRequire3 } from "module";
|
|
380
|
+
async function stopRunningConsoleBeforeUpdate(io) {
|
|
381
|
+
let cliPath;
|
|
382
|
+
try {
|
|
383
|
+
cliPath = requireFromHere.resolve(CONSOLE_CLI_SPECIFIER);
|
|
384
|
+
} catch {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
io.stdout.write("Stopping the running Fleet Console to release file locks before update...\n");
|
|
388
|
+
await runConsoleStop2(cliPath, io);
|
|
389
|
+
}
|
|
390
|
+
function runConsoleStop2(cliPath, io) {
|
|
391
|
+
return new Promise((resolve2) => {
|
|
392
|
+
let settled = false;
|
|
393
|
+
const child = spawn4(process.execPath, [cliPath, "stop"], { stdio: "ignore" });
|
|
394
|
+
const timer = setTimeout(() => {
|
|
395
|
+
io.stderr.write("Fleet Console did not stop within the timeout; continuing with the update.\n");
|
|
396
|
+
child.kill();
|
|
397
|
+
finish();
|
|
398
|
+
}, STOP_TIMEOUT_MS);
|
|
399
|
+
const finish = () => {
|
|
400
|
+
if (settled) return;
|
|
401
|
+
settled = true;
|
|
402
|
+
clearTimeout(timer);
|
|
403
|
+
resolve2();
|
|
404
|
+
};
|
|
405
|
+
child.on("error", finish);
|
|
406
|
+
child.on("exit", finish);
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
var CONSOLE_CLI_SPECIFIER, STOP_TIMEOUT_MS, requireFromHere;
|
|
410
|
+
var init_stop_console = __esm({
|
|
411
|
+
"src/update/stop-console.ts"() {
|
|
412
|
+
"use strict";
|
|
413
|
+
CONSOLE_CLI_SPECIFIER = "@dotobokuri/fleet-console/cli";
|
|
414
|
+
STOP_TIMEOUT_MS = 15e3;
|
|
415
|
+
requireFromHere = createRequire3(import.meta.url);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
|
|
377
419
|
// src/update/installer.ts
|
|
378
420
|
var installer_exports = {};
|
|
379
421
|
__export(installer_exports, {
|
|
380
422
|
__installerTestHooks: () => __installerTestHooks,
|
|
381
423
|
runFleetUpdate: () => runFleetUpdate
|
|
382
424
|
});
|
|
383
|
-
import { spawn as
|
|
425
|
+
import { spawn as spawn5 } from "child_process";
|
|
384
426
|
import { execFileSync } from "child_process";
|
|
385
427
|
import { accessSync, constants as constants10, realpathSync as realpathSync8 } from "fs";
|
|
386
|
-
import { createRequire as
|
|
428
|
+
import { createRequire as createRequire4 } from "module";
|
|
387
429
|
import path25 from "path";
|
|
388
430
|
async function runFleetUpdate(io) {
|
|
389
431
|
const release2 = readFleetCliRelease();
|
|
@@ -412,6 +454,7 @@ async function runFleetUpdate(io) {
|
|
|
412
454
|
io.stdout.write(`Updating Fleet packages with ${target.manager.command} (${versionOrChannel})...
|
|
413
455
|
`);
|
|
414
456
|
}
|
|
457
|
+
await stopRunningConsoleBeforeUpdate(io);
|
|
415
458
|
const status = await installFleetPackages(target.manager, versionOrChannel, io);
|
|
416
459
|
if (status !== 0) {
|
|
417
460
|
io.stderr.write(`Fleet update did not complete. You can run this manually:
|
|
@@ -469,11 +512,11 @@ function detectGlobalRoot(command3, packageRoot, io) {
|
|
|
469
512
|
return void 0;
|
|
470
513
|
}
|
|
471
514
|
function getCurrentPackageRoot() {
|
|
472
|
-
const
|
|
515
|
+
const requireFromHere2 = createRequire4(import.meta.url);
|
|
473
516
|
for (const candidate of PACKAGE_JSON_CANDIDATES) {
|
|
474
517
|
try {
|
|
475
|
-
const packageJsonPath =
|
|
476
|
-
const pkg =
|
|
518
|
+
const packageJsonPath = requireFromHere2.resolve(candidate);
|
|
519
|
+
const pkg = requireFromHere2(packageJsonPath);
|
|
477
520
|
if (pkg.name === FLEET_CLI_PACKAGE_NAME) {
|
|
478
521
|
return normalizePath(realpathSync8(path25.dirname(packageJsonPath)));
|
|
479
522
|
}
|
|
@@ -483,7 +526,7 @@ function getCurrentPackageRoot() {
|
|
|
483
526
|
return void 0;
|
|
484
527
|
}
|
|
485
528
|
function installFleetPackages(manager, versionOrChannel, io) {
|
|
486
|
-
const child =
|
|
529
|
+
const child = spawn5(manager.resolved.bin, [...manager.resolved.prefixArgs, "i", "-g", "--force", ...PACKAGE_NAMES.map((name) => `${name}@${versionOrChannel}`)], {
|
|
487
530
|
stdio: "inherit"
|
|
488
531
|
});
|
|
489
532
|
return new Promise((resolve2) => {
|
|
@@ -577,6 +620,7 @@ var init_installer = __esm({
|
|
|
577
620
|
init_resolve_bin();
|
|
578
621
|
init_release();
|
|
579
622
|
init_check();
|
|
623
|
+
init_stop_console();
|
|
580
624
|
PACKAGE_NAMES = ["@dotobokuri/fleet-cli", "@dotobokuri/fleet-console"];
|
|
581
625
|
FLEET_CLI_PACKAGE_NAME = "@dotobokuri/fleet-cli";
|
|
582
626
|
PACKAGE_JSON_CANDIDATES = ["../package.json", "../../package.json"];
|
|
@@ -588,10 +632,10 @@ var init_installer = __esm({
|
|
|
588
632
|
});
|
|
589
633
|
|
|
590
634
|
// src/index.ts
|
|
591
|
-
import { spawn as
|
|
635
|
+
import { spawn as spawn6 } from "child_process";
|
|
592
636
|
import path26, { dirname as dirname6 } from "path";
|
|
593
637
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
594
|
-
import { createRequire as
|
|
638
|
+
import { createRequire as createRequire5 } from "module";
|
|
595
639
|
|
|
596
640
|
// ../../packages/fleet-infra/dist/chunk-IUYHSUHV.js
|
|
597
641
|
init_chunk_UH3Q34DS();
|
|
@@ -39165,9 +39209,9 @@ function createConsoleLock(deps = {}) {
|
|
|
39165
39209
|
return { ensureLockDir, readLock, writeLock, removeLock, assertLockModes, assertTrustedLock };
|
|
39166
39210
|
}
|
|
39167
39211
|
function readFleetConsoleRelease() {
|
|
39168
|
-
const
|
|
39169
|
-
const packageJsonPath =
|
|
39170
|
-
const pkg =
|
|
39212
|
+
const requireFromHere2 = createRequire(import.meta.url);
|
|
39213
|
+
const packageJsonPath = requireFromHere2.resolve("../package.json");
|
|
39214
|
+
const pkg = requireFromHere2(packageJsonPath);
|
|
39171
39215
|
const packageRoot = path9__default.dirname(packageJsonPath);
|
|
39172
39216
|
const version22 = pkg.version ?? "";
|
|
39173
39217
|
if (pkg.private === true) {
|
|
@@ -39942,10 +39986,10 @@ function mergeDefs2(...defs) {
|
|
|
39942
39986
|
function cloneDef2(schema) {
|
|
39943
39987
|
return mergeDefs2(schema._zod.def);
|
|
39944
39988
|
}
|
|
39945
|
-
function getElementAtPath2(obj,
|
|
39946
|
-
if (!
|
|
39989
|
+
function getElementAtPath2(obj, path192) {
|
|
39990
|
+
if (!path192)
|
|
39947
39991
|
return obj;
|
|
39948
|
-
return
|
|
39992
|
+
return path192.reduce((acc, key) => acc?.[key], obj);
|
|
39949
39993
|
}
|
|
39950
39994
|
function promiseAllObject2(promisesObj) {
|
|
39951
39995
|
const keys = Object.keys(promisesObj);
|
|
@@ -40354,11 +40398,11 @@ function explicitlyAborted2(x, startIndex = 0) {
|
|
|
40354
40398
|
}
|
|
40355
40399
|
return false;
|
|
40356
40400
|
}
|
|
40357
|
-
function prefixIssues2(
|
|
40401
|
+
function prefixIssues2(path192, issues) {
|
|
40358
40402
|
return issues.map((iss) => {
|
|
40359
40403
|
var _a32;
|
|
40360
40404
|
(_a32 = iss).path ?? (_a32.path = []);
|
|
40361
|
-
iss.path.unshift(
|
|
40405
|
+
iss.path.unshift(path192);
|
|
40362
40406
|
return iss;
|
|
40363
40407
|
});
|
|
40364
40408
|
}
|
|
@@ -40503,16 +40547,16 @@ function flattenError2(error512, mapper = (issue22) => issue22.message) {
|
|
|
40503
40547
|
}
|
|
40504
40548
|
function formatError3(error512, mapper = (issue22) => issue22.message) {
|
|
40505
40549
|
const fieldErrors = { _errors: [] };
|
|
40506
|
-
const processError = (error522,
|
|
40550
|
+
const processError = (error522, path192 = []) => {
|
|
40507
40551
|
for (const issue22 of error522.issues) {
|
|
40508
40552
|
if (issue22.code === "invalid_union" && issue22.errors.length) {
|
|
40509
|
-
issue22.errors.map((issues) => processError({ issues }, [...
|
|
40553
|
+
issue22.errors.map((issues) => processError({ issues }, [...path192, ...issue22.path]));
|
|
40510
40554
|
} else if (issue22.code === "invalid_key") {
|
|
40511
|
-
processError({ issues: issue22.issues }, [...
|
|
40555
|
+
processError({ issues: issue22.issues }, [...path192, ...issue22.path]);
|
|
40512
40556
|
} else if (issue22.code === "invalid_element") {
|
|
40513
|
-
processError({ issues: issue22.issues }, [...
|
|
40557
|
+
processError({ issues: issue22.issues }, [...path192, ...issue22.path]);
|
|
40514
40558
|
} else {
|
|
40515
|
-
const fullpath = [...
|
|
40559
|
+
const fullpath = [...path192, ...issue22.path];
|
|
40516
40560
|
if (fullpath.length === 0) {
|
|
40517
40561
|
fieldErrors._errors.push(mapper(issue22));
|
|
40518
40562
|
} else {
|
|
@@ -40539,17 +40583,17 @@ function formatError3(error512, mapper = (issue22) => issue22.message) {
|
|
|
40539
40583
|
}
|
|
40540
40584
|
function treeifyError2(error512, mapper = (issue22) => issue22.message) {
|
|
40541
40585
|
const result = { errors: [] };
|
|
40542
|
-
const processError = (error522,
|
|
40586
|
+
const processError = (error522, path192 = []) => {
|
|
40543
40587
|
var _a32, _b;
|
|
40544
40588
|
for (const issue22 of error522.issues) {
|
|
40545
40589
|
if (issue22.code === "invalid_union" && issue22.errors.length) {
|
|
40546
|
-
issue22.errors.map((issues) => processError({ issues }, [...
|
|
40590
|
+
issue22.errors.map((issues) => processError({ issues }, [...path192, ...issue22.path]));
|
|
40547
40591
|
} else if (issue22.code === "invalid_key") {
|
|
40548
|
-
processError({ issues: issue22.issues }, [...
|
|
40592
|
+
processError({ issues: issue22.issues }, [...path192, ...issue22.path]);
|
|
40549
40593
|
} else if (issue22.code === "invalid_element") {
|
|
40550
|
-
processError({ issues: issue22.issues }, [...
|
|
40594
|
+
processError({ issues: issue22.issues }, [...path192, ...issue22.path]);
|
|
40551
40595
|
} else {
|
|
40552
|
-
const fullpath = [...
|
|
40596
|
+
const fullpath = [...path192, ...issue22.path];
|
|
40553
40597
|
if (fullpath.length === 0) {
|
|
40554
40598
|
result.errors.push(mapper(issue22));
|
|
40555
40599
|
continue;
|
|
@@ -40581,8 +40625,8 @@ function treeifyError2(error512, mapper = (issue22) => issue22.message) {
|
|
|
40581
40625
|
}
|
|
40582
40626
|
function toDotPath2(_path) {
|
|
40583
40627
|
const segs = [];
|
|
40584
|
-
const
|
|
40585
|
-
for (const seg of
|
|
40628
|
+
const path192 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
40629
|
+
for (const seg of path192) {
|
|
40586
40630
|
if (typeof seg === "number")
|
|
40587
40631
|
segs.push(`[${seg}]`);
|
|
40588
40632
|
else if (typeof seg === "symbol")
|
|
@@ -53103,13 +53147,13 @@ function resolveRef2(ref, ctx) {
|
|
|
53103
53147
|
if (!ref.startsWith("#")) {
|
|
53104
53148
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
53105
53149
|
}
|
|
53106
|
-
const
|
|
53107
|
-
if (
|
|
53150
|
+
const path192 = ref.slice(1).split("/").filter(Boolean);
|
|
53151
|
+
if (path192.length === 0) {
|
|
53108
53152
|
return ctx.rootSchema;
|
|
53109
53153
|
}
|
|
53110
53154
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
53111
|
-
if (
|
|
53112
|
-
const key =
|
|
53155
|
+
if (path192[0] === defsKey) {
|
|
53156
|
+
const key = path192[1];
|
|
53113
53157
|
if (!key || !ctx.defs[key]) {
|
|
53114
53158
|
throw new Error(`Reference not found: ${ref}`);
|
|
53115
53159
|
}
|
|
@@ -71608,6 +71652,10 @@ function writeAggregateObserverEvents(req, res, workspaces, store22, resolveWork
|
|
|
71608
71652
|
}
|
|
71609
71653
|
const unsubscribers = options2.subscribeAll ? [
|
|
71610
71654
|
store22.subscribeAll((event) => {
|
|
71655
|
+
if (isSessionUpdatedEvent(event)) {
|
|
71656
|
+
writeEvent(res, 0, event.type, { session: event.session });
|
|
71657
|
+
return;
|
|
71658
|
+
}
|
|
71611
71659
|
writeEvent(res, event.id, event.type, { tenant: resolvedWorkspaceSnapshot(resolveWorkspace, event.tenantId), event });
|
|
71612
71660
|
})
|
|
71613
71661
|
] : workspaces.map(
|
|
@@ -71630,6 +71678,9 @@ function writeEvent(res, id, event, data) {
|
|
|
71630
71678
|
|
|
71631
71679
|
`);
|
|
71632
71680
|
}
|
|
71681
|
+
function isSessionUpdatedEvent(event) {
|
|
71682
|
+
return event.type === "session:updated" && "session" in event;
|
|
71683
|
+
}
|
|
71633
71684
|
function workspaceSnapshot(workspace) {
|
|
71634
71685
|
return {
|
|
71635
71686
|
tenantId: workspace.tenantId,
|
|
@@ -71665,6 +71716,7 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
71665
71716
|
const truncationByTenant = /* @__PURE__ */ new Map();
|
|
71666
71717
|
const jobsByTenant = /* @__PURE__ */ new Map();
|
|
71667
71718
|
const terminalSessionsById = /* @__PURE__ */ new Map();
|
|
71719
|
+
const terminalSequenceByTheater = /* @__PURE__ */ new Map();
|
|
71668
71720
|
const listenersByTenant = /* @__PURE__ */ new Map();
|
|
71669
71721
|
const allListeners = /* @__PURE__ */ new Set();
|
|
71670
71722
|
let nextObservedId = 1;
|
|
@@ -71828,13 +71880,18 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
71828
71880
|
function createPendingTerminalSession(input) {
|
|
71829
71881
|
if (!path9__default.isAbsolute(input.cwd)) throw new Error("Terminal session cwd must be absolute");
|
|
71830
71882
|
const createdAt = input.createdAt ?? now();
|
|
71883
|
+
const canonicalCwd = canonicalizeTheaterPathSync(input.cwd);
|
|
71884
|
+
const theaterId = workspaceHash(canonicalCwd);
|
|
71885
|
+
const sequence = (terminalSequenceByTheater.get(theaterId) ?? 0) + 1;
|
|
71886
|
+
terminalSequenceByTheater.set(theaterId, sequence);
|
|
71831
71887
|
const state = {
|
|
71832
71888
|
sessionId: input.sessionId,
|
|
71833
71889
|
cwd: input.cwd,
|
|
71834
|
-
canonicalCwd
|
|
71890
|
+
canonicalCwd,
|
|
71835
71891
|
cwdLabel: path9__default.basename(input.cwd) || input.cwd,
|
|
71892
|
+
sequence,
|
|
71836
71893
|
createdAt,
|
|
71837
|
-
theaterId
|
|
71894
|
+
theaterId,
|
|
71838
71895
|
terminalSessionId: input.sessionId,
|
|
71839
71896
|
status: "starting"
|
|
71840
71897
|
};
|
|
@@ -71850,6 +71907,21 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
71850
71907
|
session.status = status;
|
|
71851
71908
|
return toTerminalSessionInfo(session);
|
|
71852
71909
|
}
|
|
71910
|
+
function renameTerminalSession(sessionId, rawLabel) {
|
|
71911
|
+
const session = terminalSessionsById.get(sessionId);
|
|
71912
|
+
if (!session) return null;
|
|
71913
|
+
const label = rawLabel.trim().slice(0, 200);
|
|
71914
|
+
if (label.length === 0) {
|
|
71915
|
+
delete session.label;
|
|
71916
|
+
} else {
|
|
71917
|
+
session.label = label;
|
|
71918
|
+
}
|
|
71919
|
+
return toTerminalSessionInfo(session);
|
|
71920
|
+
}
|
|
71921
|
+
function notifySessionUpdated(session) {
|
|
71922
|
+
const event = { type: "session:updated", session };
|
|
71923
|
+
for (const listener of allListeners) listener(event);
|
|
71924
|
+
}
|
|
71853
71925
|
function removeTerminalSession(sessionId) {
|
|
71854
71926
|
return terminalSessionsById.delete(sessionId);
|
|
71855
71927
|
}
|
|
@@ -71861,6 +71933,7 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
71861
71933
|
truncationByTenant.clear();
|
|
71862
71934
|
jobsByTenant.clear();
|
|
71863
71935
|
terminalSessionsById.clear();
|
|
71936
|
+
terminalSequenceByTheater.clear();
|
|
71864
71937
|
listenersByTenant.clear();
|
|
71865
71938
|
allListeners.clear();
|
|
71866
71939
|
}
|
|
@@ -71880,6 +71953,8 @@ function createConsoleObservabilityStore(deps = {}) {
|
|
|
71880
71953
|
pushEvents,
|
|
71881
71954
|
register,
|
|
71882
71955
|
createPendingTerminalSession,
|
|
71956
|
+
notifySessionUpdated,
|
|
71957
|
+
renameTerminalSession,
|
|
71883
71958
|
subscribe,
|
|
71884
71959
|
subscribeAll,
|
|
71885
71960
|
updateTerminalSessionStatus,
|
|
@@ -71961,6 +72036,8 @@ function toTerminalSessionInfo(state) {
|
|
|
71961
72036
|
sessionId: state.sessionId,
|
|
71962
72037
|
terminalSessionId: state.terminalSessionId,
|
|
71963
72038
|
cwdLabel: state.cwdLabel,
|
|
72039
|
+
sequence: state.sequence,
|
|
72040
|
+
label: state.label,
|
|
71964
72041
|
status: state.status,
|
|
71965
72042
|
createdAt: state.createdAt,
|
|
71966
72043
|
theaterId: state.theaterId,
|
|
@@ -72290,6 +72367,75 @@ async function runNativeCommand(bin, args) {
|
|
|
72290
72367
|
const result = await execFileAsync(bin, [...args], { timeout: DIALOG_TIMEOUT_MS });
|
|
72291
72368
|
return { stdout: result.stdout, stderr: result.stderr };
|
|
72292
72369
|
}
|
|
72370
|
+
var DEFAULT_WINDOWS_PATHEXT2 = ".COM;.EXE;.BAT;.CMD";
|
|
72371
|
+
var WINDOWS_PATH_SEPARATOR2 = ";";
|
|
72372
|
+
var WINDOWS_SHIM_EXTENSIONS2 = /* @__PURE__ */ new Set([".cmd", ".bat"]);
|
|
72373
|
+
var CMD_EXPANSION_SENSITIVE_PATTERN2 = /[%^]/;
|
|
72374
|
+
function resolvePathBinary2(command22, env, options2 = {}) {
|
|
72375
|
+
const platform2 = options2.platform ?? process.platform;
|
|
72376
|
+
const isWindows22 = platform2 === "win32";
|
|
72377
|
+
const pathValue = isWindows22 ? env.Path ?? env.PATH ?? "" : env.PATH ?? "";
|
|
72378
|
+
const pathExts = isWindows22 ? parsePathExt2(env.PATHEXT) : [""];
|
|
72379
|
+
const resolved = findOnPath2(command22, pathValue, pathExts, platform2, options2.exists ?? fs4__default.existsSync);
|
|
72380
|
+
return resolved ? wrapWindowsShim2(resolved, env, platform2) : void 0;
|
|
72381
|
+
}
|
|
72382
|
+
function wrapWindowsShim2(resolved, env, platform2) {
|
|
72383
|
+
if (platform2 !== "win32" || !WINDOWS_SHIM_EXTENSIONS2.has(path9__default.extname(resolved).toLowerCase())) {
|
|
72384
|
+
return { bin: resolved, prefixArgs: [] };
|
|
72385
|
+
}
|
|
72386
|
+
rejectCmdExpansionSensitiveShim2(resolved);
|
|
72387
|
+
return {
|
|
72388
|
+
bin: env.ComSpec ?? "cmd.exe",
|
|
72389
|
+
prefixArgs: ["/d", "/s", "/c", "call", forceWindowsArgQuoting2(resolved)]
|
|
72390
|
+
};
|
|
72391
|
+
}
|
|
72392
|
+
function rejectCmdExpansionSensitiveShim2(resolved) {
|
|
72393
|
+
if (CMD_EXPANSION_SENSITIVE_PATTERN2.test(resolved)) {
|
|
72394
|
+
throw new Error(`Refusing to run Windows shim path with cmd.exe expansion-sensitive characters (% or ^): ${resolved}`);
|
|
72395
|
+
}
|
|
72396
|
+
}
|
|
72397
|
+
function forceWindowsArgQuoting2(value) {
|
|
72398
|
+
return `${value} `;
|
|
72399
|
+
}
|
|
72400
|
+
function findOnPath2(bin, pathValue, pathExts, platform2, exists) {
|
|
72401
|
+
const pathSeparator = platform2 === "win32" ? WINDOWS_PATH_SEPARATOR2 : path9__default.delimiter;
|
|
72402
|
+
if (hasPathSeparator2(bin, platform2) || path9__default.isAbsolute(bin)) {
|
|
72403
|
+
return resolveWithExtensions2(bin, pathExts, platform2, exists);
|
|
72404
|
+
}
|
|
72405
|
+
for (const entry of pathValue.split(pathSeparator)) {
|
|
72406
|
+
const searchDir = entry.length === 0 ? "." : entry;
|
|
72407
|
+
const candidate = resolveWithExtensions2(path9__default.join(searchDir, bin), pathExts, platform2, exists);
|
|
72408
|
+
if (candidate) {
|
|
72409
|
+
return candidate;
|
|
72410
|
+
}
|
|
72411
|
+
}
|
|
72412
|
+
return void 0;
|
|
72413
|
+
}
|
|
72414
|
+
function resolveWithExtensions2(candidate, pathExts, platform2, exists) {
|
|
72415
|
+
if (platform2 !== "win32" || path9__default.extname(candidate).length > 0) {
|
|
72416
|
+
return exists(candidate) ? candidate : void 0;
|
|
72417
|
+
}
|
|
72418
|
+
for (const ext of pathExts) {
|
|
72419
|
+
if (ext.length === 0) {
|
|
72420
|
+
continue;
|
|
72421
|
+
}
|
|
72422
|
+
const withExt = `${candidate}${ext}`;
|
|
72423
|
+
if (exists(withExt)) {
|
|
72424
|
+
return withExt;
|
|
72425
|
+
}
|
|
72426
|
+
}
|
|
72427
|
+
return exists(candidate) ? candidate : void 0;
|
|
72428
|
+
}
|
|
72429
|
+
function hasPathSeparator2(value, platform2) {
|
|
72430
|
+
if (value.includes("/")) {
|
|
72431
|
+
return true;
|
|
72432
|
+
}
|
|
72433
|
+
return platform2 === "win32" && value.includes("\\");
|
|
72434
|
+
}
|
|
72435
|
+
function parsePathExt2(pathExt) {
|
|
72436
|
+
const raw = pathExt && pathExt.trim().length > 0 ? pathExt : DEFAULT_WINDOWS_PATHEXT2;
|
|
72437
|
+
return raw.split(WINDOWS_PATH_SEPARATOR2).map((entry) => entry.trim()).filter((entry) => entry.length > 0);
|
|
72438
|
+
}
|
|
72293
72439
|
var DEFAULT_TERMINAL_CWD_FALLBACK = os22__default.homedir;
|
|
72294
72440
|
var TERMINAL_TERM = "xterm-256color";
|
|
72295
72441
|
var FLEET_HEADLESS_NATIVE_FLAGS = ["--headless", "--native"];
|
|
@@ -72300,16 +72446,26 @@ function createDefaultTerminalLaunchResolver(deps = {}) {
|
|
|
72300
72446
|
const execPath = deps.execPath ?? process4.execPath;
|
|
72301
72447
|
const homedir22 = deps.homedir ?? DEFAULT_TERMINAL_CWD_FALLBACK;
|
|
72302
72448
|
const exists = deps.exists ?? fs4__default.existsSync;
|
|
72449
|
+
const platform2 = deps.platform ?? process4.platform;
|
|
72303
72450
|
const release2 = deps.release ?? readFleetConsoleRelease();
|
|
72304
72451
|
return (selectedCwd, context) => {
|
|
72305
72452
|
const cwd = selectedCwd || baseCwd || homedir22();
|
|
72306
72453
|
if (context?.kind === "shell") {
|
|
72307
|
-
|
|
72454
|
+
const shell = resolveWindowsLaunchBinary(resolveUserShell(env, platform2), [], env, exists, platform2, "user shell");
|
|
72455
|
+
return { bin: shell.bin, args: shell.args, cwd, env: buildShellLaunchEnv(env) };
|
|
72308
72456
|
}
|
|
72309
72457
|
const launchEnv = buildLaunchEnv(env, cwd, context?.sessionId);
|
|
72310
72458
|
const override = parseTerminalCommand(env.FLEET_TERMINAL_CMD);
|
|
72311
72459
|
if (override) {
|
|
72312
|
-
|
|
72460
|
+
const resolvedOverride = resolveWindowsLaunchBinary(
|
|
72461
|
+
override.bin,
|
|
72462
|
+
override.args,
|
|
72463
|
+
env,
|
|
72464
|
+
exists,
|
|
72465
|
+
platform2,
|
|
72466
|
+
"FLEET_TERMINAL_CMD"
|
|
72467
|
+
);
|
|
72468
|
+
return { ...resolvedOverride, cwd, env: launchEnv };
|
|
72313
72469
|
}
|
|
72314
72470
|
if (release2.channel === "local") {
|
|
72315
72471
|
const localCli = resolveSiblingFleetCliEntry(release2.packageRoot, exists);
|
|
@@ -72320,7 +72476,15 @@ function createDefaultTerminalLaunchResolver(deps = {}) {
|
|
|
72320
72476
|
}
|
|
72321
72477
|
return { bin: execPath, args: [localCli, ...FLEET_HEADLESS_NATIVE_FLAGS], cwd, env: launchEnv };
|
|
72322
72478
|
}
|
|
72323
|
-
|
|
72479
|
+
const stableFleet = resolveWindowsLaunchBinary(
|
|
72480
|
+
"fleet",
|
|
72481
|
+
[...FLEET_HEADLESS_NATIVE_FLAGS],
|
|
72482
|
+
env,
|
|
72483
|
+
exists,
|
|
72484
|
+
platform2,
|
|
72485
|
+
"fleet stable terminal binary"
|
|
72486
|
+
);
|
|
72487
|
+
return { ...stableFleet, cwd, env: launchEnv };
|
|
72324
72488
|
};
|
|
72325
72489
|
}
|
|
72326
72490
|
function startTerminalShell(launch, size) {
|
|
@@ -72333,11 +72497,21 @@ function startTerminalShell(launch, size) {
|
|
|
72333
72497
|
name: TERMINAL_TERM
|
|
72334
72498
|
});
|
|
72335
72499
|
}
|
|
72336
|
-
function resolveUserShell(env) {
|
|
72500
|
+
function resolveUserShell(env, platform2) {
|
|
72337
72501
|
if (env.SHELL) return env.SHELL;
|
|
72338
|
-
if (
|
|
72502
|
+
if (platform2 === "win32") return env.ComSpec || "powershell.exe";
|
|
72339
72503
|
return "/bin/bash";
|
|
72340
72504
|
}
|
|
72505
|
+
function resolveWindowsLaunchBinary(bin, args, env, exists, platform2, label) {
|
|
72506
|
+
if (platform2 !== "win32") {
|
|
72507
|
+
return { bin, args };
|
|
72508
|
+
}
|
|
72509
|
+
const resolved = resolvePathBinary2(bin, env, { exists, platform: platform2 });
|
|
72510
|
+
if (!resolved) {
|
|
72511
|
+
throw new Error(`${label} "${bin}" was not found on PATH; provide an absolute path or install it before launching a terminal session.`);
|
|
72512
|
+
}
|
|
72513
|
+
return { bin: resolved.bin, args: [...resolved.prefixArgs, ...args] };
|
|
72514
|
+
}
|
|
72341
72515
|
function resolveSiblingFleetCliEntry(consolePackageRoot, exists = fs4__default.existsSync) {
|
|
72342
72516
|
const candidate = expectedSiblingFleetCliEntry(consolePackageRoot);
|
|
72343
72517
|
return exists(candidate) ? candidate : null;
|
|
@@ -72367,15 +72541,11 @@ function buildShellLaunchEnv(env) {
|
|
|
72367
72541
|
}
|
|
72368
72542
|
var DEFAULT_COLS = 80;
|
|
72369
72543
|
var DEFAULT_ROWS2 = 24;
|
|
72370
|
-
var DEFAULT_GRACE_MS = 18e4;
|
|
72371
72544
|
var DEFAULT_SCROLLBACK_LIMIT = 512;
|
|
72372
72545
|
var WS_OPEN_STATE = 1;
|
|
72373
72546
|
function createTerminalSessionManager(deps) {
|
|
72374
72547
|
const startShell2 = deps.startShell ?? startTerminalShell;
|
|
72375
|
-
const graceMs = deps.graceMs ?? DEFAULT_GRACE_MS;
|
|
72376
72548
|
const scrollbackLimit = deps.scrollbackLimit ?? DEFAULT_SCROLLBACK_LIMIT;
|
|
72377
|
-
const setTimeoutImpl = deps.setTimeout ?? setTimeout;
|
|
72378
|
-
const clearTimeoutImpl = deps.clearTimeout ?? clearTimeout;
|
|
72379
72549
|
const sessions = /* @__PURE__ */ new Map();
|
|
72380
72550
|
function canAttach() {
|
|
72381
72551
|
return true;
|
|
@@ -72385,10 +72555,6 @@ function createTerminalSessionManager(deps) {
|
|
|
72385
72555
|
if (session.activeSocket && session.activeSocket !== socket) {
|
|
72386
72556
|
session.activeSocket.close(4e3, "terminal_replaced");
|
|
72387
72557
|
}
|
|
72388
|
-
if (session.graceTimer) {
|
|
72389
|
-
clearTimeoutImpl(session.graceTimer);
|
|
72390
|
-
session.graceTimer = null;
|
|
72391
|
-
}
|
|
72392
72558
|
session.activeSocket = socket;
|
|
72393
72559
|
session.pty.resize(session.cols, session.rows);
|
|
72394
72560
|
replayScrollback(session, socket);
|
|
@@ -72420,7 +72586,6 @@ function createTerminalSessionManager(deps) {
|
|
|
72420
72586
|
disposables: [],
|
|
72421
72587
|
scrollback: [],
|
|
72422
72588
|
activeSocket: null,
|
|
72423
|
-
graceTimer: null,
|
|
72424
72589
|
cols: DEFAULT_COLS,
|
|
72425
72590
|
rows: DEFAULT_ROWS2
|
|
72426
72591
|
};
|
|
@@ -72460,7 +72625,6 @@ function createTerminalSessionManager(deps) {
|
|
|
72460
72625
|
function detachSocket(session, socket) {
|
|
72461
72626
|
if (session.activeSocket !== socket) return;
|
|
72462
72627
|
session.activeSocket = null;
|
|
72463
|
-
session.graceTimer = setTimeoutImpl(() => removeSession(session), graceMs);
|
|
72464
72628
|
}
|
|
72465
72629
|
function replayScrollback(session, socket) {
|
|
72466
72630
|
for (const chunk of session.scrollback) {
|
|
@@ -72476,10 +72640,6 @@ function createTerminalSessionManager(deps) {
|
|
|
72476
72640
|
}
|
|
72477
72641
|
function killSession(session, options2 = {}) {
|
|
72478
72642
|
const killPty = options2.killPty ?? true;
|
|
72479
|
-
if (session.graceTimer) {
|
|
72480
|
-
clearTimeoutImpl(session.graceTimer);
|
|
72481
|
-
session.graceTimer = null;
|
|
72482
|
-
}
|
|
72483
72643
|
session.activeSocket?.close(4001, "terminal_closed");
|
|
72484
72644
|
session.activeSocket = null;
|
|
72485
72645
|
for (const disposable of session.disposables) disposable.dispose();
|
|
@@ -72619,7 +72779,7 @@ var MAX_BODY_BYTES = 1024 * 1024;
|
|
|
72619
72779
|
function createConsoleServer(deps = {}) {
|
|
72620
72780
|
const host = deps.host ?? DEFAULT_HOST2;
|
|
72621
72781
|
const port = deps.port ?? DEFAULT_PORT2;
|
|
72622
|
-
const version22 = deps.version ?? (
|
|
72782
|
+
const version22 = deps.version ?? readFleetConsoleRelease().version;
|
|
72623
72783
|
const channel = readConsoleChannel();
|
|
72624
72784
|
const carrierRegistry = createCarrierRegistry2();
|
|
72625
72785
|
registerDefaultCarriers2(carrierRegistry);
|
|
@@ -72639,7 +72799,6 @@ function createConsoleServer(deps = {}) {
|
|
|
72639
72799
|
const terminalSessions = createTerminalSessionManager({
|
|
72640
72800
|
launch: deps.terminalLaunch ?? createDefaultTerminalLaunchResolver(),
|
|
72641
72801
|
startShell: deps.terminalStartShell,
|
|
72642
|
-
graceMs: deps.terminalGraceMs,
|
|
72643
72802
|
maxSessions: deps.maxTerminalSessions,
|
|
72644
72803
|
// PTY가 종료되면(예: fleet-cli 종료) 콘솔 세션 목록에서도 제거해 잔존/재실행을 막는다.
|
|
72645
72804
|
onSessionExit: (sessionId) => observability.removeTerminalSession(sessionId)
|
|
@@ -72700,7 +72859,7 @@ function createConsoleServer(deps = {}) {
|
|
|
72700
72859
|
}
|
|
72701
72860
|
const terminalSessionItemMatch = pathname.match(/^\/terminal\/sessions\/([^/]+)$/);
|
|
72702
72861
|
if (terminalSessionItemMatch) {
|
|
72703
|
-
handleTerminalSessionItem(req, res, decodeURIComponent(terminalSessionItemMatch[1] ?? ""));
|
|
72862
|
+
runAsyncHandler(handleTerminalSessionItem(req, res, decodeURIComponent(terminalSessionItemMatch[1] ?? "")), res);
|
|
72704
72863
|
return;
|
|
72705
72864
|
}
|
|
72706
72865
|
if (pathname === "/observer/theaters") {
|
|
@@ -72896,8 +73055,8 @@ function createConsoleServer(deps = {}) {
|
|
|
72896
73055
|
}
|
|
72897
73056
|
await createTerminalSessionForCwd(cwd, res);
|
|
72898
73057
|
}
|
|
72899
|
-
function handleTerminalSessionItem(req, res, sessionId) {
|
|
72900
|
-
if (req.method !== "DELETE") {
|
|
73058
|
+
async function handleTerminalSessionItem(req, res, sessionId) {
|
|
73059
|
+
if (req.method !== "DELETE" && req.method !== "PATCH") {
|
|
72901
73060
|
writeJson(res, 405, { error: "Method not allowed" });
|
|
72902
73061
|
return;
|
|
72903
73062
|
}
|
|
@@ -72905,6 +73064,21 @@ function createConsoleServer(deps = {}) {
|
|
|
72905
73064
|
writeJson(res, 401, { error: "unauthorized" });
|
|
72906
73065
|
return;
|
|
72907
73066
|
}
|
|
73067
|
+
if (req.method === "PATCH") {
|
|
73068
|
+
const body = await readJsonBody(req);
|
|
73069
|
+
if (!body || body.label !== void 0 && typeof body.label !== "string") {
|
|
73070
|
+
writeJson(res, 400, { error: "invalid_session_label" });
|
|
73071
|
+
return;
|
|
73072
|
+
}
|
|
73073
|
+
const updated = observability.renameTerminalSession(sessionId, body.label ?? "");
|
|
73074
|
+
if (!updated) {
|
|
73075
|
+
writeJson(res, 404, { error: "session_not_found" });
|
|
73076
|
+
return;
|
|
73077
|
+
}
|
|
73078
|
+
observability.notifySessionUpdated(updated);
|
|
73079
|
+
writeJson(res, 200, updated);
|
|
73080
|
+
return;
|
|
73081
|
+
}
|
|
72908
73082
|
terminalSessions.terminate(sessionId);
|
|
72909
73083
|
observability.removeTerminalSession(sessionId);
|
|
72910
73084
|
writeJson(res, 200, { ok: true });
|
|
@@ -83117,7 +83291,7 @@ async function dispatchUpdateCommand(argv2, io) {
|
|
|
83117
83291
|
|
|
83118
83292
|
// src/index.ts
|
|
83119
83293
|
var HELP_HINT2 = "Run 'fleet --help' for usage.";
|
|
83120
|
-
var require4 =
|
|
83294
|
+
var require4 = createRequire5(import.meta.url);
|
|
83121
83295
|
var FLEET_ENTRY_PATH = fileURLToPath2(import.meta.url);
|
|
83122
83296
|
var PLUGIN_ASSETS_DIR = path26.join(dirname6(dirname6(FLEET_ENTRY_PATH)), "assets");
|
|
83123
83297
|
var PLUGIN_TSX_LOADER_PATH = resolveOptionalPackage("tsx");
|
|
@@ -83209,7 +83383,7 @@ function resolveOptionalPackage(id) {
|
|
|
83209
83383
|
}
|
|
83210
83384
|
async function relayToPackageCli(specifier, args) {
|
|
83211
83385
|
const cliPath = require4.resolve(specifier);
|
|
83212
|
-
const child =
|
|
83386
|
+
const child = spawn6(process.execPath, [cliPath, ...args], {
|
|
83213
83387
|
stdio: "inherit",
|
|
83214
83388
|
cwd: process.env.INIT_CWD || process.cwd()
|
|
83215
83389
|
});
|