@dotobokuri/fleet-console 1.33.0 → 1.34.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/cli.mjs +553 -433
- package/dist/client/assets/{_baseUniq-DGGrBWAb.js → _baseUniq-kpxXKqaz.js} +1 -1
- package/dist/client/assets/{arc-BNCMUJG_.js → arc-Cf0soLes.js} +1 -1
- package/dist/client/assets/{architectureDiagram-Q4EWVU46-C7qQq1FU.js → architectureDiagram-Q4EWVU46-DiRqbCQ7.js} +1 -1
- package/dist/client/assets/{blockDiagram-DXYQGD6D-Cd8j3SNd.js → blockDiagram-DXYQGD6D-DC25h3LU.js} +1 -1
- package/dist/client/assets/{c4Diagram-AHTNJAMY-fFAORcJP.js → c4Diagram-AHTNJAMY-BJLnKoD4.js} +1 -1
- package/dist/client/assets/channel-Deg6stWj.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-peomhKWw.js → chunk-4BX2VUAB-DWUk4gCy.js} +1 -1
- package/dist/client/assets/{chunk-4TB4RGXK-TEb8s6Dl.js → chunk-4TB4RGXK-DW4Ee9nw.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-11aKxGwZ.js → chunk-55IACEB6-8z_Na955.js} +1 -1
- package/dist/client/assets/{chunk-EDXVE4YY-CPeOY-w0.js → chunk-EDXVE4YY-C3Z4nalr.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DpbKBDUG.js → chunk-FMBD7UC4-UIVDEAE7.js} +1 -1
- package/dist/client/assets/{chunk-OYMX7WX6-DQiIenR8.js → chunk-OYMX7WX6-DpFWa4G9.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-ByEBhAst.js → chunk-QZHKN3VN-BJndYOsb.js} +1 -1
- package/dist/client/assets/{chunk-YZCP3GAM-Ca8uNdzu.js → chunk-YZCP3GAM-DJcSuWBd.js} +1 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-CpidLq53.js +1 -0
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-CpidLq53.js +1 -0
- package/dist/client/assets/clone-CPyCexwP.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-B9r4jGi9.js → cose-bilkent-S5V4N54A-C3m_quy1.js} +1 -1
- package/dist/client/assets/{dagre-KV5264BT-Csnn3Aws.js → dagre-KV5264BT-DzDFWezD.js} +1 -1
- package/dist/client/assets/{diagram-5BDNPKRD-xgvBmNve.js → diagram-5BDNPKRD-D3OFrOF_.js} +1 -1
- package/dist/client/assets/{diagram-G4DWMVQ6-eDo2cgdI.js → diagram-G4DWMVQ6-CgCqSaI7.js} +1 -1
- package/dist/client/assets/{diagram-MMDJMWI5-C3GDlrcv.js → diagram-MMDJMWI5-CnJzOV_w.js} +1 -1
- package/dist/client/assets/{diagram-TYMM5635-BDyVzMHP.js → diagram-TYMM5635-BrUz8pH4.js} +1 -1
- package/dist/client/assets/{erDiagram-SMLLAGMA-YegVvYsw.js → erDiagram-SMLLAGMA-C1IvCMgN.js} +1 -1
- package/dist/client/assets/{flowDiagram-DWJPFMVM-zcVenDmh.js → flowDiagram-DWJPFMVM-DCrfhs19.js} +1 -1
- package/dist/client/assets/{ganttDiagram-T4ZO3ILL-CkMabQtg.js → ganttDiagram-T4ZO3ILL-ChQcD1Li.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-CuD1D5LQ.js → gitGraphDiagram-UUTBAWPF-C5aEYdTT.js} +1 -1
- package/dist/client/assets/{graph-DvVj819O.js → graph-CpGaCv1x.js} +1 -1
- package/dist/client/assets/index-DKrNZlfG.css +1 -0
- package/dist/client/assets/index-aW5PuGmI.js +452 -0
- package/dist/client/assets/{infoDiagram-42DDH7IO-DPoWXM0E.js → infoDiagram-42DDH7IO-BMhiz3U-.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-BBoXoRxo.js → ishikawaDiagram-UXIWVN3A-5_f4rhFk.js} +1 -1
- package/dist/client/assets/{journeyDiagram-VCZTEJTY-B-IoiUw0.js → journeyDiagram-VCZTEJTY-BHP2UyTZ.js} +1 -1
- package/dist/client/assets/{kanban-definition-6JOO6SKY-BcjjEa8G.js → kanban-definition-6JOO6SKY-edTTflKa.js} +1 -1
- package/dist/client/assets/{layout-BjaFRuOv.js → layout-B7z9q0n7.js} +1 -1
- package/dist/client/assets/{linear-DLVG-hZ_.js → linear-BDNnEnhj.js} +1 -1
- package/dist/client/assets/{mermaid.core-6fYEjApv.js → mermaid.core-DDcMYg9W.js} +4 -4
- package/dist/client/assets/{min-BfgBrJLR.js → min-D6WC647e.js} +1 -1
- package/dist/client/assets/{mindmap-definition-QFDTVHPH-BjelYLWH.js → mindmap-definition-QFDTVHPH-lvrJFtla.js} +1 -1
- package/dist/client/assets/{pieDiagram-DEJITSTG-BznY8oUt.js → pieDiagram-DEJITSTG-D1h_ZTUL.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-34T5L4WZ-jEnKUROj.js → quadrantDiagram-34T5L4WZ-DSAYqOT0.js} +1 -1
- package/dist/client/assets/{requirementDiagram-MS252O5E-BuQqQSjX.js → requirementDiagram-MS252O5E-BtNZUJPU.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-XADWPNL6-B9g8trZW.js → sankeyDiagram-XADWPNL6-Ci2wj876.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-FGHM5R23-V6Zwufo5.js → sequenceDiagram-FGHM5R23-ES3fQi8m.js} +1 -1
- package/dist/client/assets/{stateDiagram-FHFEXIEX-8E2cIHyh.js → stateDiagram-FHFEXIEX-BAJV8Z8I.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-CiX1nm_r.js +1 -0
- package/dist/client/assets/{timeline-definition-GMOUNBTQ-DpiM_Ig9.js → timeline-definition-GMOUNBTQ-Bl7xwJpF.js} +1 -1
- package/dist/client/assets/{vennDiagram-DHZGUBPP-D975VPJg.js → vennDiagram-DHZGUBPP-Csv3w_qu.js} +1 -1
- package/dist/client/assets/{wardley-RL74JXVD-BiM6uI8Z.js → wardley-RL74JXVD-CaXvusTS.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-NUSXRM2D-IoXxaljw.js → wardleyDiagram-NUSXRM2D-DfKsNCHq.js} +1 -1
- package/dist/client/assets/{xychartDiagram-5P7HB3ND-BqNE-iqW.js → xychartDiagram-5P7HB3ND-BmDHSI31.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/fleet-plugins/file-explorer/routes.mjs +102 -5
- package/dist/fleet-plugins/repository/routes.mjs +106 -4
- package/dist/fleet-plugins/skills/routes.mjs +93 -42
- package/dist/fleet-plugins/terminal/routes.mjs +901 -799
- package/package.json +1 -1
- package/dist/client/assets/channel-BDofRchL.js +0 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-BrRbVOSf.js +0 -1
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-BrRbVOSf.js +0 -1
- package/dist/client/assets/clone-CEWs7Jhj.js +0 -1
- package/dist/client/assets/index-DeA0aGZd.css +0 -1
- package/dist/client/assets/index-Dk_jqw8o.js +0 -451
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-0HROefWC.js +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -903,16 +903,22 @@ function sanitizeGlobalOptionsData(value) {
|
|
|
903
903
|
return { data: createEmptyGlobalOptionsData(), changed: true };
|
|
904
904
|
}
|
|
905
905
|
const kimiModel = sanitizeKimiModel(value.kimiModel);
|
|
906
|
+
const agentIdleDormantMinutes = sanitizeAgentIdleDormantMinutes(value.agentIdleDormantMinutes);
|
|
906
907
|
const data = {
|
|
907
908
|
version: GLOBAL_OPTIONS_VERSION,
|
|
908
909
|
...typeof value.enableMetaphor === "boolean" ? { enableMetaphor: value.enableMetaphor } : {},
|
|
909
|
-
...
|
|
910
|
-
...
|
|
910
|
+
...kimiModel ? { kimiModel } : {},
|
|
911
|
+
...agentIdleDormantMinutes !== void 0 ? { agentIdleDormantMinutes } : {}
|
|
911
912
|
};
|
|
912
|
-
const allowedKeys = /* @__PURE__ */ new Set(["version", "enableMetaphor", "
|
|
913
|
-
const changed = Object.keys(value).some((key) => !allowedKeys.has(key)) || "enableMetaphor" in value && typeof value.enableMetaphor !== "boolean" || "
|
|
913
|
+
const allowedKeys = /* @__PURE__ */ new Set(["version", "enableMetaphor", "kimiModel", "agentIdleDormantMinutes"]);
|
|
914
|
+
const changed = Object.keys(value).some((key) => !allowedKeys.has(key)) || "enableMetaphor" in value && typeof value.enableMetaphor !== "boolean" || "kimiModel" in value && kimiModel === void 0 || "agentIdleDormantMinutes" in value && agentIdleDormantMinutes === void 0;
|
|
914
915
|
return { data, changed };
|
|
915
916
|
}
|
|
917
|
+
function sanitizeAgentIdleDormantMinutes(value) {
|
|
918
|
+
if (value === null) return null;
|
|
919
|
+
if (typeof value === "number" && Number.isFinite(value) && Number.isInteger(value) && value > 0) return value;
|
|
920
|
+
return void 0;
|
|
921
|
+
}
|
|
916
922
|
function sanitizeKimiModel(value) {
|
|
917
923
|
if (!isRecord(value)) {
|
|
918
924
|
return void 0;
|
|
@@ -31774,35 +31780,23 @@ var AcpConnection = class extends BaseConnection {
|
|
|
31774
31780
|
}
|
|
31775
31781
|
case "tool_call": {
|
|
31776
31782
|
const { sessionUpdate: _tc, ...toolCallData } = update;
|
|
31777
|
-
const rawTcTitle = toolCallData.title ?? "";
|
|
31778
|
-
const cleanTcTitle = rawTcTitle.replace(/\s*\(\s*[\d.,\s-]*\b(?:NaN|undefined)\b[\d.,\s-]*\)/g, "");
|
|
31779
|
-
if (cleanTcTitle !== rawTcTitle) {
|
|
31780
|
-
console.debug("[AcpConnection] sanitized tool_call payload", { rawTitle: rawTcTitle, cleanTitle: cleanTcTitle });
|
|
31781
|
-
}
|
|
31782
|
-
const titleTcOverride = "title" in toolCallData ? { title: cleanTcTitle } : {};
|
|
31783
31783
|
this.emit(
|
|
31784
31784
|
"toolCall",
|
|
31785
|
-
|
|
31785
|
+
toolCallData.title ?? "",
|
|
31786
31786
|
toolCallData.status ?? "",
|
|
31787
31787
|
sessionId,
|
|
31788
|
-
|
|
31788
|
+
toolCallData
|
|
31789
31789
|
);
|
|
31790
31790
|
break;
|
|
31791
31791
|
}
|
|
31792
31792
|
case "tool_call_update": {
|
|
31793
31793
|
const { sessionUpdate: _tcu, ...toolCallUpdateData } = update;
|
|
31794
|
-
const rawTitle = toolCallUpdateData.title ?? "";
|
|
31795
|
-
const cleanTitle = rawTitle.replace(/\s*\(\s*[\d.,\s-]*\b(?:NaN|undefined)\b[\d.,\s-]*\)/g, "");
|
|
31796
|
-
if (cleanTitle !== rawTitle) {
|
|
31797
|
-
console.debug("[AcpConnection] sanitized tool_call_update payload", { rawTitle, cleanTitle });
|
|
31798
|
-
}
|
|
31799
|
-
const titleOverride = "title" in toolCallUpdateData ? { title: cleanTitle } : {};
|
|
31800
31794
|
this.emit(
|
|
31801
31795
|
"toolCallUpdate",
|
|
31802
|
-
|
|
31796
|
+
toolCallUpdateData.title ?? "",
|
|
31803
31797
|
toolCallUpdateData.status ?? "",
|
|
31804
31798
|
sessionId,
|
|
31805
|
-
|
|
31799
|
+
toolCallUpdateData
|
|
31806
31800
|
);
|
|
31807
31801
|
break;
|
|
31808
31802
|
}
|
|
@@ -31967,7 +31961,7 @@ function inferBinName(packageName) {
|
|
|
31967
31961
|
// ../../packages/core-unified-agent/models.json
|
|
31968
31962
|
var models_default = {
|
|
31969
31963
|
version: 1,
|
|
31970
|
-
updatedAt: "2026-07-
|
|
31964
|
+
updatedAt: "2026-07-25T00:00:00Z",
|
|
31971
31965
|
providers: {
|
|
31972
31966
|
claude: {
|
|
31973
31967
|
name: "Claude Code",
|
|
@@ -32003,11 +31997,13 @@ var models_default = {
|
|
|
32003
31997
|
defaultModel: "gpt-5.6-sol",
|
|
32004
31998
|
models: [
|
|
32005
31999
|
{ modelId: "gpt-5.6-sol", name: "GPT-5.6-Sol", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max", "ultra"], default: "low" } },
|
|
32000
|
+
{ modelId: "gpt-5.6-sol-fast", name: "GPT-5.6-Sol Fast", providerModelId: "gpt-5.6-sol", serviceTier: "priority", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max", "ultra"], default: "low" } },
|
|
32006
32001
|
{ modelId: "gpt-5.6-terra", name: "GPT-5.6-Terra", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max", "ultra"], default: "medium" } },
|
|
32002
|
+
{ modelId: "gpt-5.6-terra-fast", name: "GPT-5.6-Terra Fast", providerModelId: "gpt-5.6-terra", serviceTier: "priority", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max", "ultra"], default: "medium" } },
|
|
32007
32003
|
{ modelId: "gpt-5.6-luna", name: "GPT-5.6-Luna", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "medium" } },
|
|
32004
|
+
{ modelId: "gpt-5.6-luna-fast", name: "GPT-5.6-Luna Fast", providerModelId: "gpt-5.6-luna", serviceTier: "priority", effort: { supported: true, levels: ["low", "medium", "high", "xhigh", "max"], default: "medium" } },
|
|
32008
32005
|
{ modelId: "gpt-5.5", name: "GPT-5.5", effort: { supported: true, levels: ["low", "medium", "high", "xhigh"], default: "high" } },
|
|
32009
|
-
{ modelId: "gpt-5.
|
|
32010
|
-
{ modelId: "gpt-5.4-mini", name: "GPT-5.4 Mini", effort: { supported: true, levels: ["low", "medium", "high", "xhigh"], default: "high" } }
|
|
32006
|
+
{ modelId: "gpt-5.5-fast", name: "GPT-5.5 Fast", providerModelId: "gpt-5.5", serviceTier: "priority", effort: { supported: true, levels: ["low", "medium", "high", "xhigh"], default: "high" } }
|
|
32011
32007
|
]
|
|
32012
32008
|
},
|
|
32013
32009
|
"opencode-go": {
|
|
@@ -32093,6 +32089,10 @@ var ModelEntrySchema = external_exports.object({
|
|
|
32093
32089
|
description: external_exports.string().optional(),
|
|
32094
32090
|
/** spawn 시 실제 CLI 모델 ID를 조립해야 하는 경우의 템플릿 */
|
|
32095
32091
|
spawnModelTemplate: external_exports.string().optional(),
|
|
32092
|
+
/** 카탈로그 ID와 실제 provider 모델 ID가 다른 경우의 원본 모델 ID */
|
|
32093
|
+
providerModelId: external_exports.string().optional(),
|
|
32094
|
+
/** provider가 모델과 별도로 받는 서비스 티어 */
|
|
32095
|
+
serviceTier: external_exports.string().optional(),
|
|
32096
32096
|
/** 모델의 컨텍스트 윈도우 크기 (토큰) */
|
|
32097
32097
|
contextWindow: external_exports.number().int().positive().optional(),
|
|
32098
32098
|
/** 모델별 effort 설정 */
|
|
@@ -32115,6 +32115,14 @@ var ModelEntrySchema = external_exports.object({
|
|
|
32115
32115
|
path: ["spawnModelTemplate"]
|
|
32116
32116
|
});
|
|
32117
32117
|
}
|
|
32118
|
+
if (ctx.value.serviceTier && !ctx.value.providerModelId) {
|
|
32119
|
+
ctx.issues.push({
|
|
32120
|
+
code: "custom",
|
|
32121
|
+
input: ctx.value.serviceTier,
|
|
32122
|
+
message: "serviceTier\uB97C \uC9C0\uC815\uD55C \uBAA8\uB378\uC740 providerModelId\uB3C4 \uC9C0\uC815\uD574\uC57C \uD569\uB2C8\uB2E4",
|
|
32123
|
+
path: ["serviceTier"]
|
|
32124
|
+
});
|
|
32125
|
+
}
|
|
32118
32126
|
});
|
|
32119
32127
|
var ModelsMappingSchema = external_exports.record(external_exports.string(), external_exports.string());
|
|
32120
32128
|
var ProviderSchema = external_exports.object({
|
|
@@ -32264,8 +32272,6 @@ var CLI_BACKENDS = {
|
|
|
32264
32272
|
cliCommand: "codex",
|
|
32265
32273
|
protocol: "codex-app-server",
|
|
32266
32274
|
authRequired: true,
|
|
32267
|
-
npxPackage: "@agentclientprotocol/codex-acp@1.1.2",
|
|
32268
|
-
acpArgs: [],
|
|
32269
32275
|
appServerArgs: ["app-server", "--listen", "stdio://"],
|
|
32270
32276
|
modes: [
|
|
32271
32277
|
{ id: "default", label: "Plan" },
|
|
@@ -32275,7 +32281,7 @@ var CLI_BACKENDS = {
|
|
|
32275
32281
|
supportsSessionClose: true,
|
|
32276
32282
|
supportsSessionLoad: true,
|
|
32277
32283
|
requiresModelAtSpawn: false,
|
|
32278
|
-
usesNpxBridge:
|
|
32284
|
+
usesNpxBridge: false,
|
|
32279
32285
|
defaultMaxTokens: 1e5
|
|
32280
32286
|
},
|
|
32281
32287
|
"opencode-go": {
|
|
@@ -32366,22 +32372,6 @@ function getYoloModeId(cli) {
|
|
|
32366
32372
|
function getAllBackendConfigs() {
|
|
32367
32373
|
return Object.values(CLI_BACKENDS);
|
|
32368
32374
|
}
|
|
32369
|
-
function buildCodexConfigEnv(configOverrides, baseConfigJson) {
|
|
32370
|
-
const map2 = parseBaseConfigMap(baseConfigJson);
|
|
32371
|
-
for (const override of configOverrides ?? []) {
|
|
32372
|
-
const eqIndex = override.indexOf("=");
|
|
32373
|
-
if (eqIndex < 0) {
|
|
32374
|
-
continue;
|
|
32375
|
-
}
|
|
32376
|
-
const key = override.slice(0, eqIndex);
|
|
32377
|
-
const rawValue = override.slice(eqIndex + 1);
|
|
32378
|
-
assignNestedKey(map2, key, parseOverrideValue(rawValue));
|
|
32379
|
-
}
|
|
32380
|
-
if (Object.keys(map2).length === 0) {
|
|
32381
|
-
return void 0;
|
|
32382
|
-
}
|
|
32383
|
-
return JSON.stringify(map2);
|
|
32384
|
-
}
|
|
32385
32375
|
function buildConfigOverrideArgs(overrides) {
|
|
32386
32376
|
return overrides.flatMap((override) => ["-c", override]);
|
|
32387
32377
|
}
|
|
@@ -32408,45 +32398,6 @@ function mcpServerConfigsToAcp(servers) {
|
|
|
32408
32398
|
headers: server.headers ?? []
|
|
32409
32399
|
}));
|
|
32410
32400
|
}
|
|
32411
|
-
function parseBaseConfigMap(baseConfigJson) {
|
|
32412
|
-
if (!baseConfigJson) {
|
|
32413
|
-
return {};
|
|
32414
|
-
}
|
|
32415
|
-
try {
|
|
32416
|
-
const parsed = JSON.parse(baseConfigJson);
|
|
32417
|
-
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
32418
|
-
return parsed;
|
|
32419
|
-
}
|
|
32420
|
-
} catch {
|
|
32421
|
-
}
|
|
32422
|
-
return {};
|
|
32423
|
-
}
|
|
32424
|
-
function parseOverrideValue(raw) {
|
|
32425
|
-
try {
|
|
32426
|
-
return JSON.parse(raw);
|
|
32427
|
-
} catch {
|
|
32428
|
-
if (raw.length >= 2 && raw.startsWith('"') && raw.endsWith('"')) {
|
|
32429
|
-
return raw.slice(1, -1);
|
|
32430
|
-
}
|
|
32431
|
-
return raw;
|
|
32432
|
-
}
|
|
32433
|
-
}
|
|
32434
|
-
function assignNestedKey(target, dottedKey, value) {
|
|
32435
|
-
const segments = dottedKey.split(".");
|
|
32436
|
-
let cursor = target;
|
|
32437
|
-
for (let i = 0; i < segments.length - 1; i += 1) {
|
|
32438
|
-
const segment = segments[i];
|
|
32439
|
-
const existing = cursor[segment];
|
|
32440
|
-
if (typeof existing === "object" && existing !== null && !Array.isArray(existing)) {
|
|
32441
|
-
cursor = existing;
|
|
32442
|
-
} else {
|
|
32443
|
-
const nested = {};
|
|
32444
|
-
cursor[segment] = nested;
|
|
32445
|
-
cursor = nested;
|
|
32446
|
-
}
|
|
32447
|
-
}
|
|
32448
|
-
cursor[segments[segments.length - 1]] = value;
|
|
32449
|
-
}
|
|
32450
32401
|
|
|
32451
32402
|
// ../../packages/core-unified-agent/src/detector/CliDetector.ts
|
|
32452
32403
|
var CLI_DETECT_LIST = Object.entries(CLI_BACKENDS).map(([id, backend]) => ({
|
|
@@ -33002,6 +32953,7 @@ var CODEX_METHODS = {
|
|
|
33002
32953
|
THREAD_RESUME: "thread/resume",
|
|
33003
32954
|
THREAD_READ: "thread/read",
|
|
33004
32955
|
THREAD_ARCHIVE: "thread/archive",
|
|
32956
|
+
THREAD_UNARCHIVE: "thread/unarchive",
|
|
33005
32957
|
TURN_START: "turn/start",
|
|
33006
32958
|
TURN_INTERRUPT: "turn/interrupt",
|
|
33007
32959
|
TURN_STEER: "turn/steer"
|
|
@@ -33030,6 +32982,7 @@ var CODEX_MCP_READY_STATUS = "ready";
|
|
|
33030
32982
|
var CODEX_MCP_FAILED_STATUSES = /* @__PURE__ */ new Set(["failed", "error"]);
|
|
33031
32983
|
var DEFAULT_MCP_STARTUP_TIMEOUT = 6e4;
|
|
33032
32984
|
var STDERR_TAIL_LIMIT = 20;
|
|
32985
|
+
var SESSION_TEARDOWN_TIMEOUT_MS = 5e3;
|
|
33033
32986
|
var CodexAppServerConnection = class extends BaseConnection {
|
|
33034
32987
|
clientInfo;
|
|
33035
32988
|
autoApprove;
|
|
@@ -33042,6 +32995,7 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33042
32995
|
pendingMcpReadyWaiters = /* @__PURE__ */ new Set();
|
|
33043
32996
|
stdoutBuffer = "";
|
|
33044
32997
|
pendingModel = null;
|
|
32998
|
+
pendingServiceTier = void 0;
|
|
33045
32999
|
pendingEffort = null;
|
|
33046
33000
|
codexHome = null;
|
|
33047
33001
|
isDisconnecting = false;
|
|
@@ -33066,6 +33020,9 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33066
33020
|
setPendingModel(model) {
|
|
33067
33021
|
this.pendingModel = model;
|
|
33068
33022
|
}
|
|
33023
|
+
setPendingServiceTier(serviceTier) {
|
|
33024
|
+
this.pendingServiceTier = serviceTier;
|
|
33025
|
+
}
|
|
33069
33026
|
setPendingEffort(effort) {
|
|
33070
33027
|
this.pendingEffort = effort;
|
|
33071
33028
|
}
|
|
@@ -33108,6 +33065,7 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33108
33065
|
cwd: options?.cwd ?? this.cwd,
|
|
33109
33066
|
developerInstructions: options?.developerInstructions ?? null,
|
|
33110
33067
|
model: options?.model ?? null,
|
|
33068
|
+
serviceTier: options?.serviceTier ?? null,
|
|
33111
33069
|
approvalPolicy: options?.approvalPolicy ?? null,
|
|
33112
33070
|
sandbox: options?.sandbox ?? null,
|
|
33113
33071
|
config: options?.config ?? null
|
|
@@ -33118,10 +33076,11 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33118
33076
|
this.setState("ready");
|
|
33119
33077
|
return response;
|
|
33120
33078
|
} catch (error51) {
|
|
33079
|
+
const diagnosticError = this.withStderrDiagnostics(error51, "Codex initialize");
|
|
33121
33080
|
this.setState("error");
|
|
33122
33081
|
this.isDisconnecting = true;
|
|
33123
33082
|
await this.disconnect();
|
|
33124
|
-
throw
|
|
33083
|
+
throw diagnosticError;
|
|
33125
33084
|
}
|
|
33126
33085
|
}
|
|
33127
33086
|
async loadSession(threadId, options) {
|
|
@@ -33129,11 +33088,37 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33129
33088
|
try {
|
|
33130
33089
|
response = await this.sendThreadResumeRequest(threadId, options);
|
|
33131
33090
|
} catch (error51) {
|
|
33132
|
-
|
|
33133
|
-
|
|
33134
|
-
|
|
33091
|
+
if (isArchivedThreadError(error51, threadId)) {
|
|
33092
|
+
try {
|
|
33093
|
+
await this.sendRequest(
|
|
33094
|
+
CODEX_METHODS.THREAD_UNARCHIVE,
|
|
33095
|
+
{ threadId }
|
|
33096
|
+
);
|
|
33097
|
+
} catch (unarchiveError) {
|
|
33098
|
+
const message = unarchiveError instanceof Error ? unarchiveError.message : String(unarchiveError);
|
|
33099
|
+
throw new Error(
|
|
33100
|
+
`thread/unarchive\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4(\uC6D0\uC778: archived \uC0C1\uD0DC\uB85C resume \uAC70\uBD80\uB428): ${message}`,
|
|
33101
|
+
{ cause: unarchiveError }
|
|
33102
|
+
);
|
|
33103
|
+
}
|
|
33104
|
+
try {
|
|
33105
|
+
response = await this.sendThreadResumeRequest(threadId, options);
|
|
33106
|
+
} catch (resumeError) {
|
|
33107
|
+
await this.sendRequest(
|
|
33108
|
+
CODEX_METHODS.THREAD_ARCHIVE,
|
|
33109
|
+
{ threadId },
|
|
33110
|
+
SESSION_TEARDOWN_TIMEOUT_MS
|
|
33111
|
+
).catch(() => {
|
|
33112
|
+
});
|
|
33113
|
+
throw resumeError;
|
|
33114
|
+
}
|
|
33115
|
+
} else {
|
|
33116
|
+
const rolloutPath = this.findRolloutPathForThreadId(threadId);
|
|
33117
|
+
if (!rolloutPath || !isMissingRolloutError(error51, threadId)) {
|
|
33118
|
+
throw error51;
|
|
33119
|
+
}
|
|
33120
|
+
response = await this.sendThreadResumeRequest(threadId, options, rolloutPath);
|
|
33135
33121
|
}
|
|
33136
|
-
response = await this.sendThreadResumeRequest(threadId, options, rolloutPath);
|
|
33137
33122
|
}
|
|
33138
33123
|
this.threadId = response.thread.id;
|
|
33139
33124
|
this.turnId = null;
|
|
@@ -33195,16 +33180,19 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33195
33180
|
this.on("exit", onExit);
|
|
33196
33181
|
});
|
|
33197
33182
|
try {
|
|
33183
|
+
const serviceTier = options?.serviceTier !== void 0 ? options.serviceTier : this.pendingServiceTier;
|
|
33198
33184
|
const response = await this.sendRequest(
|
|
33199
33185
|
CODEX_METHODS.TURN_START,
|
|
33200
33186
|
{
|
|
33201
33187
|
threadId: sessionId,
|
|
33202
33188
|
input,
|
|
33203
33189
|
model: options?.model ?? this.pendingModel ?? null,
|
|
33190
|
+
...serviceTier !== void 0 ? { serviceTier } : {},
|
|
33204
33191
|
effort: options?.effort ?? this.pendingEffort ?? null
|
|
33205
33192
|
}
|
|
33206
33193
|
);
|
|
33207
33194
|
this.pendingModel = null;
|
|
33195
|
+
this.pendingServiceTier = void 0;
|
|
33208
33196
|
this.pendingEffort = null;
|
|
33209
33197
|
this.turnId = response.turn.id;
|
|
33210
33198
|
await turnCompleted;
|
|
@@ -33231,14 +33219,16 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33231
33219
|
if (threadId && activeTurnId) {
|
|
33232
33220
|
await this.sendRequest(
|
|
33233
33221
|
CODEX_METHODS.TURN_INTERRUPT,
|
|
33234
|
-
{ threadId, turnId: activeTurnId }
|
|
33222
|
+
{ threadId, turnId: activeTurnId },
|
|
33223
|
+
SESSION_TEARDOWN_TIMEOUT_MS
|
|
33235
33224
|
).catch(() => {
|
|
33236
33225
|
});
|
|
33237
33226
|
}
|
|
33238
33227
|
if (threadId) {
|
|
33239
33228
|
await this.sendRequest(
|
|
33240
33229
|
CODEX_METHODS.THREAD_ARCHIVE,
|
|
33241
|
-
{ threadId }
|
|
33230
|
+
{ threadId },
|
|
33231
|
+
SESSION_TEARDOWN_TIMEOUT_MS
|
|
33242
33232
|
).catch(() => {
|
|
33243
33233
|
});
|
|
33244
33234
|
}
|
|
@@ -33256,6 +33246,7 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33256
33246
|
cwd: options?.cwd ?? this.cwd,
|
|
33257
33247
|
developerInstructions: options?.developerInstructions ?? null,
|
|
33258
33248
|
model: options?.model ?? null,
|
|
33249
|
+
serviceTier: options?.serviceTier ?? null,
|
|
33259
33250
|
approvalPolicy: options?.approvalPolicy ?? null,
|
|
33260
33251
|
sandbox: options?.sandbox ?? null,
|
|
33261
33252
|
config: options?.config ?? null
|
|
@@ -33273,6 +33264,9 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33273
33264
|
this.rejectPendingRequests(new Error("Codex \uC5F0\uACB0\uC774 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
33274
33265
|
this.rejectPendingMcpReadyWaiters(new Error("Codex \uC5F0\uACB0\uC774 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
33275
33266
|
this.stdoutBuffer = "";
|
|
33267
|
+
this.pendingModel = null;
|
|
33268
|
+
this.pendingServiceTier = void 0;
|
|
33269
|
+
this.pendingEffort = null;
|
|
33276
33270
|
this.codexHome = null;
|
|
33277
33271
|
try {
|
|
33278
33272
|
await super.disconnect();
|
|
@@ -33721,6 +33715,7 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33721
33715
|
path: rolloutPath ?? null,
|
|
33722
33716
|
cwd: options?.cwd ?? this.cwd,
|
|
33723
33717
|
model: options?.model ?? null,
|
|
33718
|
+
serviceTier: options?.serviceTier ?? null,
|
|
33724
33719
|
approvalPolicy: options?.approvalPolicy ?? null,
|
|
33725
33720
|
sandbox: options?.sandbox ?? null,
|
|
33726
33721
|
developerInstructions: options?.developerInstructions ?? null,
|
|
@@ -33840,6 +33835,9 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33840
33835
|
function isMissingRolloutError(error51, threadId) {
|
|
33841
33836
|
return error51 instanceof Error && error51.message.includes(`no rollout found for thread id ${threadId}`);
|
|
33842
33837
|
}
|
|
33838
|
+
function isArchivedThreadError(error51, threadId) {
|
|
33839
|
+
return error51 instanceof Error && error51.message.includes(`session ${threadId} is archived`);
|
|
33840
|
+
}
|
|
33843
33841
|
function findRolloutPath(root, threadId) {
|
|
33844
33842
|
if (!fs10.existsSync(root)) {
|
|
33845
33843
|
return null;
|
|
@@ -33861,7 +33859,7 @@ function findRolloutPath(root, threadId) {
|
|
|
33861
33859
|
}
|
|
33862
33860
|
|
|
33863
33861
|
// ../../packages/core-unified-agent/src/client/UnifiedCodexAgentClient.ts
|
|
33864
|
-
var CODEX_TURN_LEVEL_CONFIG_KEYS = /* @__PURE__ */ new Set(["effort"
|
|
33862
|
+
var CODEX_TURN_LEVEL_CONFIG_KEYS = /* @__PURE__ */ new Set(["effort"]);
|
|
33865
33863
|
var CODEX_THREAD_POLICY_CONFIG_KEYS = /* @__PURE__ */ new Set(["approvalPolicy", "sandbox"]);
|
|
33866
33864
|
var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
33867
33865
|
connection = null;
|
|
@@ -33870,6 +33868,8 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33870
33868
|
currentSystemPrompt = null;
|
|
33871
33869
|
firstPromptPending = null;
|
|
33872
33870
|
pendingOverrides = null;
|
|
33871
|
+
currentModelSelection = {};
|
|
33872
|
+
archiveSessionOnDisconnect = false;
|
|
33873
33873
|
detector = new CliDetector();
|
|
33874
33874
|
on(event, listener) {
|
|
33875
33875
|
return super.on(event, listener);
|
|
@@ -33889,9 +33889,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33889
33889
|
throw new Error("UnifiedCodexAgentClient\uB294 codex CLI\uB9CC \uC9C0\uC6D0\uD569\uB2C8\uB2E4.");
|
|
33890
33890
|
}
|
|
33891
33891
|
this.validateModelEffort(options.model, options.effort);
|
|
33892
|
-
if (shouldUseCodexAcp(options)) {
|
|
33893
|
-
return this.connectAcp(options);
|
|
33894
|
-
}
|
|
33895
33892
|
return this.connectAppServer(options);
|
|
33896
33893
|
}
|
|
33897
33894
|
async connectAppServer(options) {
|
|
@@ -33900,6 +33897,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33900
33897
|
const command2 = options.cliPath ?? backend.cliCommand;
|
|
33901
33898
|
const baseArgs = backend.appServerArgs ?? ["app-server", "--listen", "stdio://"];
|
|
33902
33899
|
const modeMapping = this.resolveMode(options.yoloMode === false ? "default" : "yolo");
|
|
33900
|
+
const modelSelection = this.resolveModelSelection(options.model);
|
|
33903
33901
|
const args = [
|
|
33904
33902
|
...baseArgs,
|
|
33905
33903
|
...this.buildStartupConfigArgs(options.configOverrides, options.mcpServers, modeMapping)
|
|
@@ -33923,13 +33921,14 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33923
33921
|
if (options.sessionId) {
|
|
33924
33922
|
await connection.connect({
|
|
33925
33923
|
skipThreadStart: true,
|
|
33926
|
-
model:
|
|
33924
|
+
model: modelSelection.providerModelId,
|
|
33925
|
+
serviceTier: modelSelection.serviceTier
|
|
33927
33926
|
});
|
|
33928
33927
|
await connection.loadSession(
|
|
33929
33928
|
options.sessionId,
|
|
33930
33929
|
this.buildCodexThreadDefaultsForResume(
|
|
33931
33930
|
options.cwd,
|
|
33932
|
-
|
|
33931
|
+
modelSelection,
|
|
33933
33932
|
null,
|
|
33934
33933
|
modeMapping
|
|
33935
33934
|
)
|
|
@@ -33937,7 +33936,8 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33937
33936
|
} else {
|
|
33938
33937
|
await connection.connect({
|
|
33939
33938
|
developerInstructions: void 0,
|
|
33940
|
-
model:
|
|
33939
|
+
model: modelSelection.providerModelId,
|
|
33940
|
+
serviceTier: modelSelection.serviceTier,
|
|
33941
33941
|
approvalPolicy: modeMapping.approvalPolicy,
|
|
33942
33942
|
sandbox: modeMapping.sandbox
|
|
33943
33943
|
});
|
|
@@ -33951,6 +33951,8 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33951
33951
|
this.sessionCwd = options.cwd;
|
|
33952
33952
|
this.currentSystemPrompt = options.systemPrompt ?? null;
|
|
33953
33953
|
this.firstPromptPending = options.sessionId ? null : this.currentSystemPrompt;
|
|
33954
|
+
this.currentModelSelection = modelSelection;
|
|
33955
|
+
this.archiveSessionOnDisconnect = options.archiveSessionOnDisconnect === true;
|
|
33954
33956
|
this.pendingOverrides = {
|
|
33955
33957
|
turnConfig: options.effort ? { effort: options.effort } : {},
|
|
33956
33958
|
threadConfig: {
|
|
@@ -33964,71 +33966,17 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33964
33966
|
session: { sessionId }
|
|
33965
33967
|
};
|
|
33966
33968
|
}
|
|
33967
|
-
async connectAcp(options) {
|
|
33968
|
-
const cleanEnv = cleanEnvironment(process.env, options.env);
|
|
33969
|
-
const spawnConfig = createSpawnConfig("codex", options);
|
|
33970
|
-
const codexConfigEnv = buildCodexConfigEnv(
|
|
33971
|
-
options.configOverrides,
|
|
33972
|
-
cleanEnv.CODEX_CONFIG
|
|
33973
|
-
);
|
|
33974
|
-
const connection = new AcpConnection({
|
|
33975
|
-
command: spawnConfig.command,
|
|
33976
|
-
args: spawnConfig.args,
|
|
33977
|
-
cliType: "codex",
|
|
33978
|
-
cwd: options.cwd,
|
|
33979
|
-
env: { ...cleanEnv, ...codexConfigEnv ? { CODEX_CONFIG: codexConfigEnv } : {} },
|
|
33980
|
-
requestTimeout: options.timeout ?? 6e5,
|
|
33981
|
-
initTimeout: options.timeout ?? 6e4,
|
|
33982
|
-
promptIdleTimeout: options.promptIdleTimeout ?? 6e5,
|
|
33983
|
-
clientInfo: options.clientInfo,
|
|
33984
|
-
autoApprove: options.autoApprove,
|
|
33985
|
-
fsAccess: options.fsAccess
|
|
33986
|
-
});
|
|
33987
|
-
this.connection = connection;
|
|
33988
|
-
this.setupEventForwarding();
|
|
33989
|
-
const recentLogs = [];
|
|
33990
|
-
const collectLog = (message) => {
|
|
33991
|
-
recentLogs.push(message);
|
|
33992
|
-
if (recentLogs.length > 30) {
|
|
33993
|
-
recentLogs.shift();
|
|
33994
|
-
}
|
|
33995
|
-
};
|
|
33996
|
-
connection.on("log", collectLog);
|
|
33997
|
-
let session;
|
|
33998
|
-
try {
|
|
33999
|
-
session = await connection.connect(
|
|
34000
|
-
options.cwd,
|
|
34001
|
-
options.sessionId,
|
|
34002
|
-
this.resolveAcpMcpServers(options.mcpServers)
|
|
34003
|
-
);
|
|
34004
|
-
} catch (error51) {
|
|
34005
|
-
const connectionError = this.buildConnectionError(error51, recentLogs);
|
|
34006
|
-
await this.cleanupFailedConnection();
|
|
34007
|
-
throw connectionError;
|
|
34008
|
-
} finally {
|
|
34009
|
-
connection.off("log", collectLog);
|
|
34010
|
-
}
|
|
34011
|
-
await this.finalizeAcpConnect(options, session);
|
|
34012
|
-
return {
|
|
34013
|
-
cli: "codex",
|
|
34014
|
-
protocol: "acp",
|
|
34015
|
-
session
|
|
34016
|
-
};
|
|
34017
|
-
}
|
|
34018
33969
|
async disconnect() {
|
|
34019
33970
|
if (!this.connection) {
|
|
34020
33971
|
this.clearSessionState();
|
|
34021
33972
|
return;
|
|
34022
33973
|
}
|
|
34023
|
-
|
|
34024
|
-
|
|
34025
|
-
|
|
34026
|
-
await conn.endSession(this.sessionId);
|
|
34027
|
-
} catch {
|
|
34028
|
-
}
|
|
33974
|
+
if (this.archiveSessionOnDisconnect && this.sessionId) {
|
|
33975
|
+
await this.connection.endSession().catch(() => {
|
|
33976
|
+
});
|
|
34029
33977
|
}
|
|
34030
|
-
await
|
|
34031
|
-
|
|
33978
|
+
await this.connection.disconnect();
|
|
33979
|
+
this.connection.removeAllListeners();
|
|
34032
33980
|
this.connection = null;
|
|
34033
33981
|
this.clearSessionState();
|
|
34034
33982
|
}
|
|
@@ -34036,14 +33984,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34036
33984
|
if (!this.connection) {
|
|
34037
33985
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34038
33986
|
}
|
|
34039
|
-
|
|
34040
|
-
if (!this.sessionId) {
|
|
34041
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34042
|
-
}
|
|
34043
|
-
await this.connection.endSession(this.sessionId);
|
|
34044
|
-
} else {
|
|
34045
|
-
await this.connection.endSession();
|
|
34046
|
-
}
|
|
33987
|
+
await this.connection.endSession();
|
|
34047
33988
|
this.sessionId = null;
|
|
34048
33989
|
this.sessionCwd = null;
|
|
34049
33990
|
}
|
|
@@ -34058,7 +33999,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34058
33999
|
}
|
|
34059
34000
|
return {
|
|
34060
34001
|
cli: "codex",
|
|
34061
|
-
protocol:
|
|
34002
|
+
protocol: "codex-app-server",
|
|
34062
34003
|
sessionId: this.sessionId,
|
|
34063
34004
|
state: this.connection.connectionState
|
|
34064
34005
|
};
|
|
@@ -34070,12 +34011,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34070
34011
|
if (!this.connection) {
|
|
34071
34012
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34072
34013
|
}
|
|
34073
|
-
if (this.connection instanceof AcpConnection) {
|
|
34074
|
-
if (!this.sessionId) {
|
|
34075
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34076
|
-
}
|
|
34077
|
-
return this.sendPromptWithPendingSystemPrompt(content);
|
|
34078
|
-
}
|
|
34079
34014
|
this.applyPendingOverrides();
|
|
34080
34015
|
const input = typeof content === "string" ? [{ type: "text", text: content, text_elements: [] }] : content.map((block) => "text" in block ? { type: "text", text: block.text, text_elements: [] } : { type: "text", text: JSON.stringify(block), text_elements: [] });
|
|
34081
34016
|
const systemPrompt = this.firstPromptPending;
|
|
@@ -34086,53 +34021,20 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34086
34021
|
}
|
|
34087
34022
|
return { stopReason: "end_turn" };
|
|
34088
34023
|
}
|
|
34089
|
-
async sendPromptWithPendingSystemPrompt(content) {
|
|
34090
|
-
if (!(this.connection instanceof AcpConnection) || !this.sessionId) {
|
|
34091
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34092
|
-
}
|
|
34093
|
-
const systemPrompt = this.firstPromptPending;
|
|
34094
|
-
if (!systemPrompt) {
|
|
34095
|
-
return this.connection.sendPrompt(this.sessionId, content);
|
|
34096
|
-
}
|
|
34097
|
-
const userBlocks = typeof content === "string" ? [{ type: "text", text: content }] : content;
|
|
34098
|
-
const response = await this.connection.sendPrompt(this.sessionId, [
|
|
34099
|
-
{ type: "text", text: systemPrompt },
|
|
34100
|
-
...userBlocks
|
|
34101
|
-
]);
|
|
34102
|
-
this.firstPromptPending = null;
|
|
34103
|
-
return response;
|
|
34104
|
-
}
|
|
34105
34024
|
async cancelPrompt() {
|
|
34106
34025
|
if (!this.connection) {
|
|
34107
34026
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34108
34027
|
}
|
|
34109
|
-
if (this.connection instanceof AcpConnection) {
|
|
34110
|
-
if (!this.sessionId) {
|
|
34111
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34112
|
-
}
|
|
34113
|
-
await this.connection.cancelSession(this.sessionId);
|
|
34114
|
-
return;
|
|
34115
|
-
}
|
|
34116
34028
|
await this.connection.cancelPrompt();
|
|
34117
34029
|
}
|
|
34118
34030
|
async setModel(model) {
|
|
34119
|
-
|
|
34120
|
-
|
|
34121
|
-
|
|
34122
|
-
}
|
|
34123
|
-
this.ensurePendingOverrides().model = model;
|
|
34031
|
+
const selection = this.resolveModelSelection(model);
|
|
34032
|
+
this.currentModelSelection = selection;
|
|
34033
|
+
this.ensurePendingOverrides().model = selection;
|
|
34124
34034
|
}
|
|
34125
34035
|
async setConfigOption(configId, value) {
|
|
34126
|
-
if (
|
|
34127
|
-
|
|
34128
|
-
await this.connection.setModel(this.sessionId, value);
|
|
34129
|
-
return;
|
|
34130
|
-
}
|
|
34131
|
-
await this.connection.setConfigOption(
|
|
34132
|
-
this.sessionId,
|
|
34133
|
-
configId === "effort" ? "reasoning_effort" : configId,
|
|
34134
|
-
value
|
|
34135
|
-
);
|
|
34036
|
+
if (configId === "model") {
|
|
34037
|
+
await this.setModel(value);
|
|
34136
34038
|
return;
|
|
34137
34039
|
}
|
|
34138
34040
|
const pending = this.ensurePendingOverrides();
|
|
@@ -34144,10 +34046,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34144
34046
|
this.emitTyped("log", `[codex] config '${configId}' will apply on next thread/start or thread/resume`);
|
|
34145
34047
|
}
|
|
34146
34048
|
async setMode(mode) {
|
|
34147
|
-
if (this.connection instanceof AcpConnection && this.sessionId) {
|
|
34148
|
-
await this.connection.setMode(this.sessionId, this.resolveAcpMode(mode));
|
|
34149
|
-
return;
|
|
34150
|
-
}
|
|
34151
34049
|
const resolved = this.resolveMode(mode);
|
|
34152
34050
|
const pending = this.ensurePendingOverrides();
|
|
34153
34051
|
pending.threadConfig.approvalPolicy = resolved.approvalPolicy;
|
|
@@ -34170,17 +34068,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34170
34068
|
if (!this.connection) {
|
|
34171
34069
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34172
34070
|
}
|
|
34173
|
-
if (this.connection instanceof AcpConnection) {
|
|
34174
|
-
await this.connection.loadSession({
|
|
34175
|
-
sessionId,
|
|
34176
|
-
cwd: this.sessionCwd ?? process.cwd(),
|
|
34177
|
-
mcpServers: this.resolveAcpMcpServers(mcpServers)
|
|
34178
|
-
});
|
|
34179
|
-
this.sessionId = sessionId;
|
|
34180
|
-
this.currentSystemPrompt = null;
|
|
34181
|
-
this.firstPromptPending = null;
|
|
34182
|
-
return;
|
|
34183
|
-
}
|
|
34184
34071
|
if (mcpServers?.length) {
|
|
34185
34072
|
this.emitTyped(
|
|
34186
34073
|
"log",
|
|
@@ -34192,7 +34079,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34192
34079
|
sessionId,
|
|
34193
34080
|
this.buildCodexThreadDefaultsForResume(
|
|
34194
34081
|
targetCwd,
|
|
34195
|
-
|
|
34082
|
+
this.currentModelSelection,
|
|
34196
34083
|
null,
|
|
34197
34084
|
this.pendingOverrides?.threadConfig ?? {}
|
|
34198
34085
|
)
|
|
@@ -34206,24 +34093,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34206
34093
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34207
34094
|
}
|
|
34208
34095
|
const targetCwd = cwd ?? this.sessionCwd ?? process.cwd();
|
|
34209
|
-
if (this.connection instanceof AcpConnection) {
|
|
34210
|
-
if (!this.sessionId) {
|
|
34211
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34212
|
-
}
|
|
34213
|
-
if (!this.connection.canResetSession) {
|
|
34214
|
-
throw new Error("[codex] \uC138\uC158 \uB9AC\uC14B\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. disconnect() \uD6C4 \uC7AC\uC5F0\uACB0\uD558\uC138\uC694.");
|
|
34215
|
-
}
|
|
34216
|
-
await this.connection.endSession(this.sessionId);
|
|
34217
|
-
const session = await this.connection.reconnectSession(targetCwd);
|
|
34218
|
-
this.sessionId = session.sessionId;
|
|
34219
|
-
this.sessionCwd = targetCwd;
|
|
34220
|
-
this.firstPromptPending = this.currentSystemPrompt;
|
|
34221
|
-
return {
|
|
34222
|
-
cli: "codex",
|
|
34223
|
-
protocol: "acp",
|
|
34224
|
-
session
|
|
34225
|
-
};
|
|
34226
|
-
}
|
|
34227
34096
|
const result = await this.connection.resetSession(
|
|
34228
34097
|
this.buildCodexThreadDefaultsForReset(targetCwd)
|
|
34229
34098
|
);
|
|
@@ -34239,33 +34108,14 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34239
34108
|
protocol: "codex-app-server"
|
|
34240
34109
|
};
|
|
34241
34110
|
}
|
|
34242
|
-
resolveAcpMcpServers(servers) {
|
|
34243
|
-
return servers?.length ? mcpServerConfigsToAcp(servers) : [];
|
|
34244
|
-
}
|
|
34245
|
-
async finalizeAcpConnect(options, session) {
|
|
34246
|
-
this.sessionId = session.sessionId;
|
|
34247
|
-
this.sessionCwd = options.cwd;
|
|
34248
|
-
this.currentSystemPrompt = options.systemPrompt ?? null;
|
|
34249
|
-
this.firstPromptPending = options.sessionId ? null : this.currentSystemPrompt;
|
|
34250
|
-
this.pendingOverrides = {
|
|
34251
|
-
turnConfig: {},
|
|
34252
|
-
threadConfig: {}
|
|
34253
|
-
};
|
|
34254
|
-
const mode = options.yoloMode === false ? "default" : "yolo";
|
|
34255
|
-
await this.setMode(mode);
|
|
34256
|
-
if (options.model) {
|
|
34257
|
-
await this.setModel(options.model);
|
|
34258
|
-
}
|
|
34259
|
-
if (options.effort) {
|
|
34260
|
-
await this.setConfigOption("effort", options.effort);
|
|
34261
|
-
}
|
|
34262
|
-
}
|
|
34263
34111
|
clearSessionState() {
|
|
34264
34112
|
this.sessionId = null;
|
|
34265
34113
|
this.sessionCwd = null;
|
|
34266
34114
|
this.currentSystemPrompt = null;
|
|
34267
34115
|
this.firstPromptPending = null;
|
|
34268
34116
|
this.pendingOverrides = null;
|
|
34117
|
+
this.currentModelSelection = {};
|
|
34118
|
+
this.archiveSessionOnDisconnect = false;
|
|
34269
34119
|
}
|
|
34270
34120
|
validateModelEffort(modelId, effort) {
|
|
34271
34121
|
if (!effort) {
|
|
@@ -34288,69 +34138,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34288
34138
|
}
|
|
34289
34139
|
setupEventForwarding() {
|
|
34290
34140
|
if (!this.connection) return;
|
|
34291
|
-
|
|
34292
|
-
if (connection instanceof AcpConnection) {
|
|
34293
|
-
this.setupAcpEventForwarding(connection);
|
|
34294
|
-
return;
|
|
34295
|
-
}
|
|
34296
|
-
this.setupAppServerEventForwarding(connection);
|
|
34297
|
-
}
|
|
34298
|
-
setupAcpEventForwarding(connection) {
|
|
34299
|
-
connection.on("stateChange", (state) => {
|
|
34300
|
-
this.emitTyped("stateChange", state);
|
|
34301
|
-
});
|
|
34302
|
-
connection.on("userMessageChunk", (text, sessionId) => {
|
|
34303
|
-
this.emitTyped("userMessageChunk", text, sessionId);
|
|
34304
|
-
});
|
|
34305
|
-
connection.on("messageChunk", (text, sessionId) => {
|
|
34306
|
-
this.emitTyped("messageChunk", text, sessionId);
|
|
34307
|
-
});
|
|
34308
|
-
connection.on("thoughtChunk", (text, sessionId) => {
|
|
34309
|
-
this.emitTyped("thoughtChunk", text, sessionId);
|
|
34310
|
-
});
|
|
34311
|
-
connection.on("toolCall", (title, status, sessionId, data) => {
|
|
34312
|
-
this.emitTyped("toolCall", title, status, sessionId, data);
|
|
34313
|
-
});
|
|
34314
|
-
connection.on("toolCallUpdate", (title, status, sessionId, data) => {
|
|
34315
|
-
this.emitTyped("toolCallUpdate", title, status, sessionId, data);
|
|
34316
|
-
});
|
|
34317
|
-
connection.on("plan", (plan, sessionId) => {
|
|
34318
|
-
this.emitTyped("plan", plan, sessionId);
|
|
34319
|
-
});
|
|
34320
|
-
connection.on("availableCommandsUpdate", (commands, sessionId) => {
|
|
34321
|
-
this.emitTyped("availableCommandsUpdate", commands, sessionId);
|
|
34322
|
-
});
|
|
34323
|
-
connection.on("promptComplete", (sessionId) => {
|
|
34324
|
-
this.emitTyped("promptComplete", sessionId);
|
|
34325
|
-
});
|
|
34326
|
-
connection.on("permissionRequest", (params, resolve3) => {
|
|
34327
|
-
this.emitTyped(
|
|
34328
|
-
"permissionRequest",
|
|
34329
|
-
params,
|
|
34330
|
-
resolve3
|
|
34331
|
-
);
|
|
34332
|
-
});
|
|
34333
|
-
connection.on("sessionUpdate", (update) => {
|
|
34334
|
-
this.emitTyped("sessionUpdate", update);
|
|
34335
|
-
});
|
|
34336
|
-
connection.on("fileRead", (params, resolve3) => {
|
|
34337
|
-
this.emitTyped("fileRead", params, resolve3);
|
|
34338
|
-
});
|
|
34339
|
-
connection.on("fileWrite", (params, resolve3) => {
|
|
34340
|
-
this.emitTyped("fileWrite", params, resolve3);
|
|
34341
|
-
});
|
|
34342
|
-
connection.on("error", (err) => {
|
|
34343
|
-
this.emitTyped("error", err);
|
|
34344
|
-
});
|
|
34345
|
-
connection.on("exit", (code, signal) => {
|
|
34346
|
-
this.emitTyped("exit", code, signal);
|
|
34347
|
-
});
|
|
34348
|
-
connection.on("log", (msg) => {
|
|
34349
|
-
this.emitTyped("log", msg);
|
|
34350
|
-
});
|
|
34351
|
-
connection.on("logEntry", (entry) => {
|
|
34352
|
-
this.emitTyped("logEntry", entry);
|
|
34353
|
-
});
|
|
34141
|
+
this.setupAppServerEventForwarding(this.connection);
|
|
34354
34142
|
}
|
|
34355
34143
|
setupAppServerEventForwarding(connection) {
|
|
34356
34144
|
connection.on("stateChange", (state) => {
|
|
@@ -34413,15 +34201,15 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34413
34201
|
if (!this.pendingOverrides || !this.connection) {
|
|
34414
34202
|
return;
|
|
34415
34203
|
}
|
|
34416
|
-
if (this.connection instanceof AcpConnection) {
|
|
34417
|
-
return;
|
|
34418
|
-
}
|
|
34419
34204
|
if (this.pendingOverrides.model) {
|
|
34420
|
-
this.connection.setPendingModel(this.pendingOverrides.model);
|
|
34205
|
+
this.connection.setPendingModel(this.pendingOverrides.model.providerModelId ?? null);
|
|
34206
|
+
this.connection.setPendingServiceTier(this.pendingOverrides.model.serviceTier ?? null);
|
|
34421
34207
|
this.pendingOverrides.model = void 0;
|
|
34422
34208
|
}
|
|
34423
34209
|
if (this.pendingOverrides.turnConfig.model) {
|
|
34424
|
-
this.
|
|
34210
|
+
const selection = this.resolveModelSelection(this.pendingOverrides.turnConfig.model);
|
|
34211
|
+
this.connection.setPendingModel(selection.providerModelId ?? null);
|
|
34212
|
+
this.connection.setPendingServiceTier(selection.serviceTier ?? null);
|
|
34425
34213
|
delete this.pendingOverrides.turnConfig.model;
|
|
34426
34214
|
}
|
|
34427
34215
|
if (this.pendingOverrides.turnConfig.effort) {
|
|
@@ -34436,19 +34224,22 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34436
34224
|
const config2 = configEntries.length > 0 ? Object.fromEntries(configEntries) : void 0;
|
|
34437
34225
|
return {
|
|
34438
34226
|
cwd,
|
|
34227
|
+
model: this.currentModelSelection.providerModelId,
|
|
34228
|
+
serviceTier: this.currentModelSelection.serviceTier,
|
|
34439
34229
|
approvalPolicy,
|
|
34440
34230
|
sandbox,
|
|
34441
34231
|
developerInstructions: void 0,
|
|
34442
34232
|
config: config2
|
|
34443
34233
|
};
|
|
34444
34234
|
}
|
|
34445
|
-
buildCodexThreadDefaultsForResume(cwd,
|
|
34235
|
+
buildCodexThreadDefaultsForResume(cwd, modelSelection, systemPrompt, threadConfig) {
|
|
34446
34236
|
const { approvalPolicy, sandbox } = threadConfig;
|
|
34447
34237
|
const configEntries = Object.entries(threadConfig).filter(([key]) => !CODEX_THREAD_POLICY_CONFIG_KEYS.has(key));
|
|
34448
34238
|
const config2 = configEntries.length > 0 ? Object.fromEntries(configEntries) : void 0;
|
|
34449
34239
|
return {
|
|
34450
34240
|
cwd,
|
|
34451
|
-
...
|
|
34241
|
+
...modelSelection.providerModelId ? { model: modelSelection.providerModelId } : {},
|
|
34242
|
+
...modelSelection.serviceTier ? { serviceTier: modelSelection.serviceTier } : {},
|
|
34452
34243
|
approvalPolicy,
|
|
34453
34244
|
sandbox,
|
|
34454
34245
|
developerInstructions: systemPrompt ?? void 0,
|
|
@@ -34465,16 +34256,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34465
34256
|
return { approvalPolicy: "on-request", sandbox: "read-only" };
|
|
34466
34257
|
}
|
|
34467
34258
|
}
|
|
34468
|
-
resolveAcpMode(modeId) {
|
|
34469
|
-
switch (modeId) {
|
|
34470
|
-
case "autoEdit":
|
|
34471
|
-
return "agent";
|
|
34472
|
-
case "yolo":
|
|
34473
|
-
return "agent-full-access";
|
|
34474
|
-
default:
|
|
34475
|
-
return "read-only";
|
|
34476
|
-
}
|
|
34477
|
-
}
|
|
34478
34259
|
buildStartupConfigArgs(overrides, servers, modeMapping) {
|
|
34479
34260
|
const configArgs = [
|
|
34480
34261
|
...modeMapping ? [
|
|
@@ -34504,6 +34285,10 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34504
34285
|
return;
|
|
34505
34286
|
}
|
|
34506
34287
|
try {
|
|
34288
|
+
if (this.archiveSessionOnDisconnect && this.sessionId) {
|
|
34289
|
+
await this.connection.endSession().catch(() => {
|
|
34290
|
+
});
|
|
34291
|
+
}
|
|
34507
34292
|
await this.connection.disconnect();
|
|
34508
34293
|
} catch {
|
|
34509
34294
|
}
|
|
@@ -34511,65 +34296,17 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34511
34296
|
this.connection = null;
|
|
34512
34297
|
this.clearSessionState();
|
|
34513
34298
|
}
|
|
34514
|
-
|
|
34515
|
-
if (
|
|
34516
|
-
return
|
|
34517
|
-
"[codex] \uC778\uC99D\uC774 \uD544\uC694\uD558\uAC70\uB098 \uC778\uC99D\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 \uD574\uB2F9 CLI\uC5D0\uC11C \uB85C\uADF8\uC778/\uC778\uC99D\uC744 \uC644\uB8CC\uD55C \uB4A4 \uB2E4\uC2DC \uC2DC\uB3C4\uD574\uC8FC\uC138\uC694."
|
|
34518
|
-
);
|
|
34519
|
-
}
|
|
34520
|
-
if (error51 instanceof Error) {
|
|
34521
|
-
return error51;
|
|
34522
|
-
}
|
|
34523
|
-
if (typeof error51 === "object" && error51 !== null) {
|
|
34524
|
-
const obj = error51;
|
|
34525
|
-
if (typeof obj.message === "string") {
|
|
34526
|
-
const code = typeof obj.code === "number" ? ` (code: ${obj.code})` : "";
|
|
34527
|
-
const data = obj.data ? ` \u2014 ${JSON.stringify(obj.data)}` : "";
|
|
34528
|
-
return new Error(`${obj.message}${code}${data}`);
|
|
34529
|
-
}
|
|
34530
|
-
return new Error(JSON.stringify(error51));
|
|
34531
|
-
}
|
|
34532
|
-
return new Error(String(error51));
|
|
34533
|
-
}
|
|
34534
|
-
isAuthenticationError(error51, recentLogs) {
|
|
34535
|
-
const authPatterns = [
|
|
34536
|
-
/auth_required/i,
|
|
34537
|
-
/authentication required/i,
|
|
34538
|
-
/not authenticated/i,
|
|
34539
|
-
/please login/i,
|
|
34540
|
-
/please log in/i,
|
|
34541
|
-
/sign in/i,
|
|
34542
|
-
/reauth/i,
|
|
34543
|
-
/unauthorized/i,
|
|
34544
|
-
/invalid api key/i
|
|
34545
|
-
];
|
|
34546
|
-
if (this.matchAnyPattern(this.extractErrorText(error51), authPatterns)) {
|
|
34547
|
-
return true;
|
|
34548
|
-
}
|
|
34549
|
-
return recentLogs.some((log) => this.matchAnyPattern(log, authPatterns));
|
|
34550
|
-
}
|
|
34551
|
-
extractErrorText(error51) {
|
|
34552
|
-
if (error51 instanceof Error) {
|
|
34553
|
-
const code = error51.code;
|
|
34554
|
-
if (code === -32e3) {
|
|
34555
|
-
return `auth_required ${error51.message}`;
|
|
34556
|
-
}
|
|
34557
|
-
return error51.message;
|
|
34558
|
-
}
|
|
34559
|
-
if (typeof error51 === "string") {
|
|
34560
|
-
return error51;
|
|
34299
|
+
resolveModelSelection(modelId) {
|
|
34300
|
+
if (!modelId) {
|
|
34301
|
+
return {};
|
|
34561
34302
|
}
|
|
34562
|
-
|
|
34563
|
-
|
|
34564
|
-
|
|
34565
|
-
|
|
34303
|
+
const model = getProviderModels("codex").models.find((entry) => entry.modelId === modelId);
|
|
34304
|
+
return {
|
|
34305
|
+
providerModelId: model?.providerModelId ?? modelId,
|
|
34306
|
+
serviceTier: model?.serviceTier
|
|
34307
|
+
};
|
|
34566
34308
|
}
|
|
34567
34309
|
};
|
|
34568
|
-
function shouldUseCodexAcp(options) {
|
|
34569
|
-
const value = options.env?.CODEX_USE_ACP ?? process.env.CODEX_USE_ACP;
|
|
34570
|
-
const normalized = value?.trim().toLowerCase();
|
|
34571
|
-
return normalized !== void 0 && normalized !== "false" && normalized !== "0";
|
|
34572
|
-
}
|
|
34573
34310
|
var UnifiedCursorAgentClient = class extends EventEmitter {
|
|
34574
34311
|
connection = null;
|
|
34575
34312
|
sessionId = null;
|
|
@@ -38086,9 +37823,243 @@ function stripIpv6Brackets2(host) {
|
|
|
38086
37823
|
|
|
38087
37824
|
// core/host/operations/types.ts
|
|
38088
37825
|
var MAX_GROUP_NAME_LENGTH = 64;
|
|
37826
|
+
var DELETION_GRACE_MS = 8e3;
|
|
38089
37827
|
|
|
38090
|
-
// core/host/
|
|
38091
|
-
var
|
|
37828
|
+
// core/host/deferred-deletion.ts
|
|
37829
|
+
var DeferredDeletionError = class extends Error {
|
|
37830
|
+
status;
|
|
37831
|
+
constructor(status, message) {
|
|
37832
|
+
super(message);
|
|
37833
|
+
this.name = "DeferredDeletionError";
|
|
37834
|
+
this.status = status;
|
|
37835
|
+
}
|
|
37836
|
+
};
|
|
37837
|
+
var OPERATION_DELETED_EVENT_CHANNEL = "operation:deleted";
|
|
37838
|
+
var OPERATION_RESTORED_EVENT_CHANNEL = "operation:restored";
|
|
37839
|
+
var OPERATION_PURGED_EVENT_CHANNEL = "operation:purged";
|
|
37840
|
+
var PURGE_RETRY_MS = 1e3;
|
|
37841
|
+
function createDeferredDeletionCoordinator(deps) {
|
|
37842
|
+
const now = deps.now ?? Date.now;
|
|
37843
|
+
const randomId = deps.randomId ?? crypto2.randomUUID;
|
|
37844
|
+
const setTimer = deps.setTimer ?? setTimeout;
|
|
37845
|
+
const clearTimer = deps.clearTimer ?? clearTimeout;
|
|
37846
|
+
let tombstones = [];
|
|
37847
|
+
let timer = null;
|
|
37848
|
+
function list() {
|
|
37849
|
+
return tombstones;
|
|
37850
|
+
}
|
|
37851
|
+
function load(nextTombstones) {
|
|
37852
|
+
tombstones = [...nextTombstones];
|
|
37853
|
+
schedule();
|
|
37854
|
+
}
|
|
37855
|
+
function deleteOperation(operationId) {
|
|
37856
|
+
sweepExpired();
|
|
37857
|
+
const existing = tombstones.find((item) => item.kind === "operation" && item.targetId === operationId);
|
|
37858
|
+
if (existing) return toReceipt(existing);
|
|
37859
|
+
const operation = deps.operations.get(operationId);
|
|
37860
|
+
if (!operation) return null;
|
|
37861
|
+
const previousOperations = deps.operations.list();
|
|
37862
|
+
const deletedAt = now();
|
|
37863
|
+
const tombstone = {
|
|
37864
|
+
deletionId: randomId(),
|
|
37865
|
+
targetId: operation.id,
|
|
37866
|
+
deletedAt,
|
|
37867
|
+
expiresAt: deletedAt + DELETION_GRACE_MS,
|
|
37868
|
+
kind: "operation",
|
|
37869
|
+
operation
|
|
37870
|
+
};
|
|
37871
|
+
const nextTombstones = [...tombstones, tombstone];
|
|
37872
|
+
deps.operations.delete(operationId);
|
|
37873
|
+
try {
|
|
37874
|
+
deps.save(nextTombstones);
|
|
37875
|
+
} catch (error51) {
|
|
37876
|
+
deps.operations.replace(previousOperations);
|
|
37877
|
+
throw error51;
|
|
37878
|
+
}
|
|
37879
|
+
tombstones = nextTombstones;
|
|
37880
|
+
publishOperation(OPERATION_DELETED_EVENT_CHANNEL, operation);
|
|
37881
|
+
schedule();
|
|
37882
|
+
return toReceipt(tombstone);
|
|
37883
|
+
}
|
|
37884
|
+
function deleteTheater(theaterId) {
|
|
37885
|
+
sweepExpired();
|
|
37886
|
+
const existing = tombstones.find((item) => item.kind === "theater" && item.targetId === theaterId);
|
|
37887
|
+
if (existing) return toReceipt(existing);
|
|
37888
|
+
const theater = deps.theaters.get(theaterId);
|
|
37889
|
+
if (!theater) return null;
|
|
37890
|
+
const previousTheaters = deps.theaters.list();
|
|
37891
|
+
const previousOperations = deps.operations.list();
|
|
37892
|
+
const previousGroups = deps.operations.listAllGroups();
|
|
37893
|
+
const deletedOperations = deps.operations.listByTheater(theaterId);
|
|
37894
|
+
const deletedGroups = deps.operations.listGroups(theaterId);
|
|
37895
|
+
const deletedAt = now();
|
|
37896
|
+
const tombstone = {
|
|
37897
|
+
deletionId: randomId(),
|
|
37898
|
+
targetId: theater.id,
|
|
37899
|
+
deletedAt,
|
|
37900
|
+
expiresAt: deletedAt + DELETION_GRACE_MS,
|
|
37901
|
+
kind: "theater",
|
|
37902
|
+
theater,
|
|
37903
|
+
operations: deletedOperations,
|
|
37904
|
+
groups: deletedGroups
|
|
37905
|
+
};
|
|
37906
|
+
const nextTombstones = [...tombstones, tombstone];
|
|
37907
|
+
deps.theaters.remove(theaterId);
|
|
37908
|
+
deps.operations.deleteByTheater(theaterId);
|
|
37909
|
+
try {
|
|
37910
|
+
deps.save(nextTombstones);
|
|
37911
|
+
} catch (error51) {
|
|
37912
|
+
deps.theaters.restore(previousTheaters);
|
|
37913
|
+
deps.operations.replace(previousOperations);
|
|
37914
|
+
deps.operations.replaceGroups(previousGroups);
|
|
37915
|
+
throw error51;
|
|
37916
|
+
}
|
|
37917
|
+
tombstones = nextTombstones;
|
|
37918
|
+
deps.unregisterTheaterWorkspaces(theaterId);
|
|
37919
|
+
for (const operation of deletedOperations) publishOperation(OPERATION_DELETED_EVENT_CHANNEL, operation);
|
|
37920
|
+
schedule();
|
|
37921
|
+
return toReceipt(tombstone);
|
|
37922
|
+
}
|
|
37923
|
+
async function restore(deletionId) {
|
|
37924
|
+
const restoredAt = now();
|
|
37925
|
+
const tombstone = tombstones.find((item) => item.deletionId === deletionId);
|
|
37926
|
+
if (!tombstone || tombstone.expiresAt <= restoredAt) {
|
|
37927
|
+
if (tombstone) sweepExpired();
|
|
37928
|
+
throw new DeferredDeletionError(404, "deletion_not_found");
|
|
37929
|
+
}
|
|
37930
|
+
if (tombstone.kind === "operation") {
|
|
37931
|
+
if (deps.operations.get(tombstone.targetId) || !deps.theaters.get(tombstone.operation.theaterId)) {
|
|
37932
|
+
throw new DeferredDeletionError(409, "restore_conflict");
|
|
37933
|
+
}
|
|
37934
|
+
const previousOperations2 = deps.operations.list();
|
|
37935
|
+
const nextTombstones2 = tombstones.filter((item) => item.deletionId !== deletionId);
|
|
37936
|
+
deps.operations.replace([...previousOperations2, tombstone.operation]);
|
|
37937
|
+
try {
|
|
37938
|
+
deps.save(nextTombstones2);
|
|
37939
|
+
} catch (error51) {
|
|
37940
|
+
deps.operations.replace(previousOperations2);
|
|
37941
|
+
throw error51;
|
|
37942
|
+
}
|
|
37943
|
+
tombstones = nextTombstones2;
|
|
37944
|
+
publishOperation(OPERATION_RESTORED_EVENT_CHANNEL, tombstone.operation);
|
|
37945
|
+
schedule();
|
|
37946
|
+
return { ok: true, kind: tombstone.kind, targetId: tombstone.targetId };
|
|
37947
|
+
}
|
|
37948
|
+
await deps.validateTheaterRestore(tombstone.theater);
|
|
37949
|
+
if (deps.theaters.get(tombstone.targetId) || tombstone.operations.some((operation) => deps.operations.get(operation.id)) || hasGroupConflict(tombstone.groups, deps.operations.listAllGroups())) {
|
|
37950
|
+
throw new DeferredDeletionError(409, "restore_conflict");
|
|
37951
|
+
}
|
|
37952
|
+
const previousTheaters = deps.theaters.list();
|
|
37953
|
+
const previousOperations = deps.operations.list();
|
|
37954
|
+
const previousGroups = deps.operations.listAllGroups();
|
|
37955
|
+
const nextTombstones = tombstones.filter((item) => item.deletionId !== deletionId);
|
|
37956
|
+
deps.theaters.restore([...previousTheaters, tombstone.theater]);
|
|
37957
|
+
deps.operations.replace([...previousOperations, ...tombstone.operations]);
|
|
37958
|
+
deps.operations.replaceGroups([...previousGroups, ...tombstone.groups]);
|
|
37959
|
+
try {
|
|
37960
|
+
deps.save(nextTombstones);
|
|
37961
|
+
} catch (error51) {
|
|
37962
|
+
deps.theaters.restore(previousTheaters);
|
|
37963
|
+
deps.operations.replace(previousOperations);
|
|
37964
|
+
deps.operations.replaceGroups(previousGroups);
|
|
37965
|
+
throw error51;
|
|
37966
|
+
}
|
|
37967
|
+
tombstones = nextTombstones;
|
|
37968
|
+
await deps.registerTheaterWorkspace(tombstone.theater);
|
|
37969
|
+
for (const operation of tombstone.operations) publishOperation(OPERATION_RESTORED_EVENT_CHANNEL, operation);
|
|
37970
|
+
schedule();
|
|
37971
|
+
return { ok: true, kind: tombstone.kind, targetId: tombstone.targetId };
|
|
37972
|
+
}
|
|
37973
|
+
function sweepExpired() {
|
|
37974
|
+
const cutoff = now();
|
|
37975
|
+
const expired = tombstones.filter((item) => item.expiresAt <= cutoff);
|
|
37976
|
+
if (expired.length === 0) {
|
|
37977
|
+
schedule();
|
|
37978
|
+
return;
|
|
37979
|
+
}
|
|
37980
|
+
const expiredIds = new Set(expired.map((item) => item.deletionId));
|
|
37981
|
+
const nextTombstones = tombstones.filter((item) => !expiredIds.has(item.deletionId));
|
|
37982
|
+
try {
|
|
37983
|
+
deps.save(nextTombstones);
|
|
37984
|
+
} catch (error51) {
|
|
37985
|
+
schedule(PURGE_RETRY_MS);
|
|
37986
|
+
throw error51;
|
|
37987
|
+
}
|
|
37988
|
+
tombstones = nextTombstones;
|
|
37989
|
+
for (const tombstone of expired) {
|
|
37990
|
+
if (tombstone.kind === "operation") {
|
|
37991
|
+
publishOperation(OPERATION_PURGED_EVENT_CHANNEL, tombstone.operation);
|
|
37992
|
+
} else {
|
|
37993
|
+
for (const operation of tombstone.operations) publishOperation(OPERATION_PURGED_EVENT_CHANNEL, operation);
|
|
37994
|
+
}
|
|
37995
|
+
}
|
|
37996
|
+
schedule();
|
|
37997
|
+
}
|
|
37998
|
+
function hasPendingOperation(operationId) {
|
|
37999
|
+
sweepExpired();
|
|
38000
|
+
return tombstones.some((item) => item.kind === "operation" ? item.targetId === operationId : item.operations.some((operation) => operation.id === operationId));
|
|
38001
|
+
}
|
|
38002
|
+
function hasPendingTheater(theaterId) {
|
|
38003
|
+
sweepExpired();
|
|
38004
|
+
return tombstones.some((item) => item.kind === "theater" && item.targetId === theaterId);
|
|
38005
|
+
}
|
|
38006
|
+
function schedule(forcedDelay) {
|
|
38007
|
+
if (timer) clearTimer(timer);
|
|
38008
|
+
timer = null;
|
|
38009
|
+
if (forcedDelay !== void 0) {
|
|
38010
|
+
timer = setTimer(runScheduledSweep, forcedDelay);
|
|
38011
|
+
timer.unref?.();
|
|
38012
|
+
return;
|
|
38013
|
+
}
|
|
38014
|
+
const nearest = tombstones.reduce((minimum, item) => minimum === null ? item.expiresAt : Math.min(minimum, item.expiresAt), null);
|
|
38015
|
+
if (nearest === null) return;
|
|
38016
|
+
timer = setTimer(runScheduledSweep, Math.max(0, nearest - now()));
|
|
38017
|
+
timer.unref?.();
|
|
38018
|
+
}
|
|
38019
|
+
function runScheduledSweep() {
|
|
38020
|
+
timer = null;
|
|
38021
|
+
try {
|
|
38022
|
+
sweepExpired();
|
|
38023
|
+
} catch {
|
|
38024
|
+
}
|
|
38025
|
+
}
|
|
38026
|
+
function dispose() {
|
|
38027
|
+
if (timer) clearTimer(timer);
|
|
38028
|
+
timer = null;
|
|
38029
|
+
}
|
|
38030
|
+
function publishOperation(channel, operation) {
|
|
38031
|
+
deps.publish(channel, {
|
|
38032
|
+
operationId: operation.id,
|
|
38033
|
+
pluginId: operation.pluginId,
|
|
38034
|
+
type: operation.type,
|
|
38035
|
+
...channel === OPERATION_RESTORED_EVENT_CHANNEL ? { operation } : {}
|
|
38036
|
+
});
|
|
38037
|
+
}
|
|
38038
|
+
return {
|
|
38039
|
+
list,
|
|
38040
|
+
load,
|
|
38041
|
+
deleteOperation,
|
|
38042
|
+
deleteTheater,
|
|
38043
|
+
restore,
|
|
38044
|
+
sweepExpired,
|
|
38045
|
+
hasPendingOperation,
|
|
38046
|
+
hasPendingTheater,
|
|
38047
|
+
dispose
|
|
38048
|
+
};
|
|
38049
|
+
}
|
|
38050
|
+
function toReceipt(tombstone) {
|
|
38051
|
+
return {
|
|
38052
|
+
deletionId: tombstone.deletionId,
|
|
38053
|
+
kind: tombstone.kind,
|
|
38054
|
+
targetId: tombstone.targetId,
|
|
38055
|
+
expiresAt: tombstone.expiresAt
|
|
38056
|
+
};
|
|
38057
|
+
}
|
|
38058
|
+
function hasGroupConflict(groups, existing) {
|
|
38059
|
+
const existingIds = new Set(existing.map((group) => group.id));
|
|
38060
|
+
return groups.some((group) => existingIds.has(group.id));
|
|
38061
|
+
}
|
|
38062
|
+
var STATE_VERSION = 3;
|
|
38092
38063
|
var STATE_LOCK_DIR_NAME = "state.lock";
|
|
38093
38064
|
var STATE_LOCK_OWNER_FILE_NAME = "owner.json";
|
|
38094
38065
|
var STATE_TEMP_PREFIX = ".state.";
|
|
@@ -38135,25 +38106,37 @@ function sanitizeDurableConsoleState(value) {
|
|
|
38135
38106
|
version: STATE_VERSION,
|
|
38136
38107
|
theaters: readTheaterRegistrations(upgraded.theaters),
|
|
38137
38108
|
operations: readOperations(upgraded.operations),
|
|
38138
|
-
groups: readOperationGroups(upgraded.groups)
|
|
38109
|
+
groups: readOperationGroups(upgraded.groups),
|
|
38110
|
+
deletionTombstones: readDeletionTombstones(upgraded.deletionTombstones)
|
|
38139
38111
|
};
|
|
38140
38112
|
}
|
|
38141
38113
|
function emptyDurableConsoleState() {
|
|
38142
|
-
return { version: STATE_VERSION, theaters: [], operations: [], groups: [] };
|
|
38114
|
+
return { version: STATE_VERSION, theaters: [], operations: [], groups: [], deletionTombstones: [] };
|
|
38143
38115
|
}
|
|
38144
38116
|
function migrateToCurrentVersion(value) {
|
|
38145
|
-
|
|
38146
|
-
|
|
38117
|
+
let current = value;
|
|
38118
|
+
if (current.version === 1) current = migrateV1ToV2(current);
|
|
38119
|
+
if (current.version === 2) current = migrateV2ToV3(current);
|
|
38120
|
+
return current;
|
|
38147
38121
|
}
|
|
38148
38122
|
function migrateV1ToV2(v1) {
|
|
38149
38123
|
const operations = Array.isArray(v1.operations) ? v1.operations.map(migrateV1Operation) : [];
|
|
38150
38124
|
return {
|
|
38151
|
-
version:
|
|
38125
|
+
version: 2,
|
|
38152
38126
|
theaters: v1.theaters ?? [],
|
|
38153
38127
|
operations,
|
|
38154
38128
|
groups: []
|
|
38155
38129
|
};
|
|
38156
38130
|
}
|
|
38131
|
+
function migrateV2ToV3(v2) {
|
|
38132
|
+
return {
|
|
38133
|
+
version: STATE_VERSION,
|
|
38134
|
+
theaters: v2.theaters ?? [],
|
|
38135
|
+
operations: v2.operations ?? [],
|
|
38136
|
+
groups: v2.groups ?? [],
|
|
38137
|
+
deletionTombstones: []
|
|
38138
|
+
};
|
|
38139
|
+
}
|
|
38157
38140
|
function migrateV1Operation(value) {
|
|
38158
38141
|
if (!isRecord5(value)) return null;
|
|
38159
38142
|
const sessionId = readNonEmptyString(value.sessionId);
|
|
@@ -38317,6 +38300,37 @@ function sanitizeOperationGroup(value) {
|
|
|
38317
38300
|
if (!VALID_GROUP_COLOR_KEYS.has(color)) return null;
|
|
38318
38301
|
return { id, theaterId, name: rawName, color, order, createdAt };
|
|
38319
38302
|
}
|
|
38303
|
+
function readDeletionTombstones(value) {
|
|
38304
|
+
if (!Array.isArray(value)) return [];
|
|
38305
|
+
const tombstones = [];
|
|
38306
|
+
for (const item of value) {
|
|
38307
|
+
const tombstone = sanitizeDeletionTombstone(item);
|
|
38308
|
+
if (tombstone) tombstones.push(tombstone);
|
|
38309
|
+
}
|
|
38310
|
+
return tombstones;
|
|
38311
|
+
}
|
|
38312
|
+
function sanitizeDeletionTombstone(value) {
|
|
38313
|
+
if (!isRecord5(value)) return null;
|
|
38314
|
+
const deletionId = readNonEmptyString(value.deletionId);
|
|
38315
|
+
const targetId = readNonEmptyString(value.targetId);
|
|
38316
|
+
const deletedAt = readFiniteNumber(value.deletedAt);
|
|
38317
|
+
const expiresAt = readFiniteNumber(value.expiresAt);
|
|
38318
|
+
if (!deletionId || !targetId || deletedAt === null || expiresAt === null) return null;
|
|
38319
|
+
if (value.kind === "operation") {
|
|
38320
|
+
const operation = sanitizeOperationNode(value.operation);
|
|
38321
|
+
if (!operation || operation.id !== targetId) return null;
|
|
38322
|
+
return { deletionId, targetId, deletedAt, expiresAt, kind: "operation", operation };
|
|
38323
|
+
}
|
|
38324
|
+
if (value.kind === "theater") {
|
|
38325
|
+
const theater = sanitizeTheaterRegistration(value.theater);
|
|
38326
|
+
if (!theater || theater.id !== targetId || !Array.isArray(value.operations) || !Array.isArray(value.groups)) return null;
|
|
38327
|
+
const operations = value.operations.map(sanitizeOperationNode).filter((operation) => operation !== null);
|
|
38328
|
+
const groups = value.groups.map(sanitizeOperationGroup).filter((group) => group !== null);
|
|
38329
|
+
if (operations.length !== value.operations.length || groups.length !== value.groups.length || operations.some((operation) => operation.theaterId !== targetId) || groups.some((group) => group.theaterId !== targetId)) return null;
|
|
38330
|
+
return { deletionId, targetId, deletedAt, expiresAt, kind: "theater", theater, operations, groups };
|
|
38331
|
+
}
|
|
38332
|
+
return null;
|
|
38333
|
+
}
|
|
38320
38334
|
|
|
38321
38335
|
// core/host/operations/sanitize.ts
|
|
38322
38336
|
var FIXED_SENSITIVE_OPERATION_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -38332,11 +38346,20 @@ var FIXED_SENSITIVE_OPERATION_FIELDS = /* @__PURE__ */ new Set([
|
|
|
38332
38346
|
]);
|
|
38333
38347
|
function createSanitizedOpDto(node, options = {}) {
|
|
38334
38348
|
const sensitiveFields = /* @__PURE__ */ new Set([...FIXED_SENSITIVE_OPERATION_FIELDS, ...options.sensitiveFields ?? []]);
|
|
38349
|
+
const payload = sanitizeRecord(node.payload, sensitiveFields);
|
|
38350
|
+
delete payload.resumeAvailable;
|
|
38351
|
+
if (isResumableProviderSession(node.payload?.providerSession)) payload.resumeAvailable = true;
|
|
38335
38352
|
return {
|
|
38336
38353
|
...node,
|
|
38337
|
-
payload
|
|
38354
|
+
payload
|
|
38338
38355
|
};
|
|
38339
38356
|
}
|
|
38357
|
+
function isResumableProviderSession(value) {
|
|
38358
|
+
if (!isRecord6(value)) return false;
|
|
38359
|
+
const provider = value.provider;
|
|
38360
|
+
const sessionId = value.sessionId;
|
|
38361
|
+
return typeof provider === "string" && provider.length > 0 && typeof sessionId === "string" && sessionId.length > 0;
|
|
38362
|
+
}
|
|
38340
38363
|
function sanitizeRecord(value, sensitiveFields) {
|
|
38341
38364
|
const output = {};
|
|
38342
38365
|
for (const [key, item] of Object.entries(value)) {
|
|
@@ -38418,6 +38441,10 @@ async function handleCollection(req, res, deps) {
|
|
|
38418
38441
|
deps.writeJson(res, 400, { error: "invalid_operation_accent" });
|
|
38419
38442
|
return;
|
|
38420
38443
|
}
|
|
38444
|
+
if (typeof body2.id === "string" && deps.isPendingDeletion?.(body2.id)) {
|
|
38445
|
+
deps.writeJson(res, 409, { error: "pending_deletion" });
|
|
38446
|
+
return;
|
|
38447
|
+
}
|
|
38421
38448
|
try {
|
|
38422
38449
|
const node = deps.store.create({
|
|
38423
38450
|
id: typeof body2.id === "string" ? body2.id : void 0,
|
|
@@ -38450,8 +38477,8 @@ async function handleItem(req, res, id, deps) {
|
|
|
38450
38477
|
return;
|
|
38451
38478
|
}
|
|
38452
38479
|
if (req.method === "DELETE") {
|
|
38453
|
-
const
|
|
38454
|
-
deps.writeJson(res,
|
|
38480
|
+
const deletion = deps.deleteOperation(id);
|
|
38481
|
+
deps.writeJson(res, 200, { ok: true, deletion });
|
|
38455
38482
|
return;
|
|
38456
38483
|
}
|
|
38457
38484
|
const body2 = await deps.readJsonBody(req);
|
|
@@ -39042,6 +39069,10 @@ function createPlansRouter(deps) {
|
|
|
39042
39069
|
await handlePlansRead(req, res, deps);
|
|
39043
39070
|
return true;
|
|
39044
39071
|
}
|
|
39072
|
+
if (pathname === "/api/v1/plans/search") {
|
|
39073
|
+
await handlePlansSearch(req, res, deps);
|
|
39074
|
+
return true;
|
|
39075
|
+
}
|
|
39045
39076
|
if (pathname === "/api/v1/plans/events") {
|
|
39046
39077
|
await handlePlansEvents(req, res, deps);
|
|
39047
39078
|
return true;
|
|
@@ -39049,6 +39080,38 @@ function createPlansRouter(deps) {
|
|
|
39049
39080
|
return false;
|
|
39050
39081
|
};
|
|
39051
39082
|
}
|
|
39083
|
+
async function handlePlansSearch(req, res, deps) {
|
|
39084
|
+
if (req.method !== "POST") {
|
|
39085
|
+
deps.writeJson(res, 405, { error: "Method not allowed" });
|
|
39086
|
+
return;
|
|
39087
|
+
}
|
|
39088
|
+
if (!deps.isAuthorized(req)) {
|
|
39089
|
+
deps.writeJson(res, 401, { error: "unauthorized" });
|
|
39090
|
+
return;
|
|
39091
|
+
}
|
|
39092
|
+
const body2 = await deps.readJsonBody(req);
|
|
39093
|
+
if (!isPlainObject2(body2) || typeof body2.theaterId !== "string" || typeof body2.query !== "string" || body2.query.trim() === "" || !Number.isInteger(body2.limit) || body2.limit < 1 || body2.limit > 8 || "relPath" in body2) {
|
|
39094
|
+
deps.writeJson(res, 400, { error: "invalid_request" });
|
|
39095
|
+
return;
|
|
39096
|
+
}
|
|
39097
|
+
const theaterPath = deps.resolveTheaterPath(body2.theaterId);
|
|
39098
|
+
if (!theaterPath) {
|
|
39099
|
+
deps.writeJson(res, 404, { error: "theater_not_found" });
|
|
39100
|
+
return;
|
|
39101
|
+
}
|
|
39102
|
+
try {
|
|
39103
|
+
const context = await resolveTheaterRoot(theaterPath);
|
|
39104
|
+
const tokens = body2.query.trim().toLocaleLowerCase().split(/\s+/).filter(Boolean);
|
|
39105
|
+
const plans = (await listPlansForWorkspace(deps.dataDir, context.realRoot)).filter((plan) => {
|
|
39106
|
+
const text = `${plan.name}
|
|
39107
|
+
${plan.title}`.toLocaleLowerCase();
|
|
39108
|
+
return tokens.every((token) => text.includes(token));
|
|
39109
|
+
}).slice(0, body2.limit).map((plan) => ({ name: plan.name, title: plan.title }));
|
|
39110
|
+
deps.writeJson(res, 200, { plans });
|
|
39111
|
+
} catch (error51) {
|
|
39112
|
+
writePlanStoreError(res, deps, error51);
|
|
39113
|
+
}
|
|
39114
|
+
}
|
|
39052
39115
|
async function handlePlansEvents(req, res, deps) {
|
|
39053
39116
|
if (req.method !== "GET") {
|
|
39054
39117
|
deps.writeJson(res, 405, { error: "Method not allowed" });
|
|
@@ -40864,7 +40927,6 @@ var SERVER_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
|
40864
40927
|
var MAX_BODY_BYTES = 1024 * 1024;
|
|
40865
40928
|
var UPDATE_APPLY_FORBIDDEN_BODY_KEYS = /* @__PURE__ */ new Set(["channel", "package", "packageName", "packageVersion", "packages", "targetVersion", "version"]);
|
|
40866
40929
|
var OPERATION_RENAMED_EVENT_CHANNEL = "operation:renamed";
|
|
40867
|
-
var OPERATION_DELETED_EVENT_CHANNEL = "operation:deleted";
|
|
40868
40930
|
var PAIRING_IDENTITY_PATH = "/api/v1/pairing-identity";
|
|
40869
40931
|
var PAIRING_IDENTITY = { product: "fleet-console", schemaVersion: 1, pairingProtocolVersion: 1 };
|
|
40870
40932
|
var SERVER_API_CATALOG = [
|
|
@@ -40924,6 +40986,13 @@ var SERVER_API_CATALOG = [
|
|
|
40924
40986
|
category: "Observer",
|
|
40925
40987
|
gate: "origin-write"
|
|
40926
40988
|
},
|
|
40989
|
+
{
|
|
40990
|
+
method: "POST",
|
|
40991
|
+
path: "/api/v1/deletions/:deletionId/restore",
|
|
40992
|
+
summary: "\uC720\uC608 \uC911\uC778 Operation \uB610\uB294 Theater \uC0AD\uC81C\uB97C \uBCF5\uAD6C\uD569\uB2C8\uB2E4.",
|
|
40993
|
+
category: "Observer",
|
|
40994
|
+
gate: "origin-write"
|
|
40995
|
+
},
|
|
40927
40996
|
{
|
|
40928
40997
|
method: "POST",
|
|
40929
40998
|
path: "/api/v1/theaters/:theaterId/codex-workspace",
|
|
@@ -41051,16 +41120,29 @@ function createConsoleServer(deps = {}) {
|
|
|
41051
41120
|
function publishPluginEvent(channel2, payload) {
|
|
41052
41121
|
for (const listener of pluginEventListeners.get(channel2) ?? []) listener(payload);
|
|
41053
41122
|
}
|
|
41054
|
-
|
|
41055
|
-
|
|
41056
|
-
|
|
41057
|
-
|
|
41058
|
-
publishPluginEvent
|
|
41059
|
-
|
|
41060
|
-
|
|
41061
|
-
|
|
41062
|
-
|
|
41063
|
-
|
|
41123
|
+
const deletionCoordinator = createDeferredDeletionCoordinator({
|
|
41124
|
+
operations,
|
|
41125
|
+
theaters,
|
|
41126
|
+
save: saveDurableState,
|
|
41127
|
+
publish: publishPluginEvent,
|
|
41128
|
+
unregisterTheaterWorkspaces: (theaterId) => codex.unregisterTheaterWorkspaces(theaterId),
|
|
41129
|
+
validateTheaterRestore: async (theater) => {
|
|
41130
|
+
try {
|
|
41131
|
+
const restoredRealpath = await fs10__default.promises.realpath(theater.path);
|
|
41132
|
+
const stat4 = await fs10__default.promises.stat(restoredRealpath);
|
|
41133
|
+
if (!stat4.isDirectory() || restoredRealpath !== theater.realpath || workspaceHash(restoredRealpath) !== theater.id) {
|
|
41134
|
+
throw new Error("restore_conflict");
|
|
41135
|
+
}
|
|
41136
|
+
} catch {
|
|
41137
|
+
throw new DeferredDeletionError(409, "restore_parent_missing");
|
|
41138
|
+
}
|
|
41139
|
+
},
|
|
41140
|
+
registerTheaterWorkspace: async (theater) => {
|
|
41141
|
+
await codex.registerWorkspace(theater.realpath, theater.lastOpenedAt, theater.id);
|
|
41142
|
+
}
|
|
41143
|
+
});
|
|
41144
|
+
function deleteOperationForPlugin(operationId) {
|
|
41145
|
+
return deletionCoordinator.deleteOperation(operationId) !== null;
|
|
41064
41146
|
}
|
|
41065
41147
|
let desktopFullscreen = false;
|
|
41066
41148
|
let unsubscribeUpdateCheckChanges = updateCheck.onChange?.(() => {
|
|
@@ -41071,6 +41153,7 @@ function createConsoleServer(deps = {}) {
|
|
|
41071
41153
|
list: () => operations.list(),
|
|
41072
41154
|
get: (id) => operations.get(id),
|
|
41073
41155
|
create: (input) => {
|
|
41156
|
+
if (input.id && deletionCoordinator.hasPendingOperation(input.id)) throw new Error("pending_deletion");
|
|
41074
41157
|
const operation = operations.create(input);
|
|
41075
41158
|
persistDurableState();
|
|
41076
41159
|
return operation;
|
|
@@ -41086,7 +41169,7 @@ function createConsoleServer(deps = {}) {
|
|
|
41086
41169
|
}
|
|
41087
41170
|
return operation;
|
|
41088
41171
|
},
|
|
41089
|
-
delete:
|
|
41172
|
+
delete: deleteOperationForPlugin,
|
|
41090
41173
|
registerOperationType: (type) => {
|
|
41091
41174
|
pluginOperationTypes.add(type);
|
|
41092
41175
|
return () => {
|
|
@@ -41300,7 +41383,8 @@ function createConsoleServer(deps = {}) {
|
|
|
41300
41383
|
readJsonBody,
|
|
41301
41384
|
writeJson,
|
|
41302
41385
|
persist: persistDurableState,
|
|
41303
|
-
deleteOperation,
|
|
41386
|
+
deleteOperation: (operationId) => deletionCoordinator.deleteOperation(operationId),
|
|
41387
|
+
isPendingDeletion: (operationId) => deletionCoordinator.hasPendingOperation(operationId),
|
|
41304
41388
|
getPluginSensitiveFields: (pluginId) => [
|
|
41305
41389
|
...pluginHost.sensitiveFieldsByPluginId.get(pluginId) ?? [],
|
|
41306
41390
|
...pluginPayloadSanitizers.get(pluginId) ?? []
|
|
@@ -41390,6 +41474,11 @@ function createConsoleServer(deps = {}) {
|
|
|
41390
41474
|
runAsyncBooleanHandler(plansRouter({ req, res, pathname }), res, () => false);
|
|
41391
41475
|
return;
|
|
41392
41476
|
}
|
|
41477
|
+
const restoreMatch = pathname.match(/^\/api\/v1\/deletions\/([^/]+)\/restore$/);
|
|
41478
|
+
if (restoreMatch) {
|
|
41479
|
+
runAsyncHandler(handleDeferredDeletionRestore(req, res, decodeURIComponent(restoreMatch[1] ?? "")), res);
|
|
41480
|
+
return;
|
|
41481
|
+
}
|
|
41393
41482
|
const theaterItemMatch = pathname.match(/^\/api\/v1\/theaters\/([^/]+)$/);
|
|
41394
41483
|
if (theaterItemMatch) {
|
|
41395
41484
|
runAsyncHandler(handleObserverTheaterItem(req, res, decodeURIComponent(theaterItemMatch[1] ?? "")), res);
|
|
@@ -41537,6 +41626,11 @@ function createConsoleServer(deps = {}) {
|
|
|
41537
41626
|
writeJson(res, 400, { error: "invalid_folder_grant" });
|
|
41538
41627
|
return;
|
|
41539
41628
|
}
|
|
41629
|
+
const canonicalCwd = canonicalizeTheaterPathSync(cwd);
|
|
41630
|
+
if (deletionCoordinator.hasPendingTheater(workspaceHash(canonicalCwd))) {
|
|
41631
|
+
writeJson(res, 409, { error: "pending_deletion" });
|
|
41632
|
+
return;
|
|
41633
|
+
}
|
|
41540
41634
|
const theater = await theaters.register(cwd);
|
|
41541
41635
|
await codex.registerWorkspace(theater.realpath, void 0, theater.id);
|
|
41542
41636
|
persistDurableState();
|
|
@@ -41566,12 +41660,27 @@ function createConsoleServer(deps = {}) {
|
|
|
41566
41660
|
writeJson(res, 200, toTheaterInfo(theater, true));
|
|
41567
41661
|
return;
|
|
41568
41662
|
}
|
|
41569
|
-
|
|
41570
|
-
|
|
41571
|
-
|
|
41572
|
-
|
|
41573
|
-
|
|
41574
|
-
|
|
41663
|
+
const deletion = deletionCoordinator.deleteTheater(theaterId);
|
|
41664
|
+
writeJson(res, 200, { ok: true, deletion });
|
|
41665
|
+
}
|
|
41666
|
+
async function handleDeferredDeletionRestore(req, res, deletionId) {
|
|
41667
|
+
if (req.method !== "POST") {
|
|
41668
|
+
writeJson(res, 405, { error: "Method not allowed" });
|
|
41669
|
+
return;
|
|
41670
|
+
}
|
|
41671
|
+
if (!isTerminalAuthorized(req)) {
|
|
41672
|
+
writeJson(res, 401, { error: "unauthorized" });
|
|
41673
|
+
return;
|
|
41674
|
+
}
|
|
41675
|
+
try {
|
|
41676
|
+
writeJson(res, 200, await deletionCoordinator.restore(deletionId));
|
|
41677
|
+
} catch (error51) {
|
|
41678
|
+
if (error51 instanceof DeferredDeletionError) {
|
|
41679
|
+
writeJson(res, error51.status, { error: error51.message });
|
|
41680
|
+
return;
|
|
41681
|
+
}
|
|
41682
|
+
throw error51;
|
|
41683
|
+
}
|
|
41575
41684
|
}
|
|
41576
41685
|
function handleStatus(req, res) {
|
|
41577
41686
|
const theaterId = readUrl(req).searchParams.get("theaterId");
|
|
@@ -41788,6 +41897,12 @@ function createConsoleServer(deps = {}) {
|
|
|
41788
41897
|
operations.replace([]);
|
|
41789
41898
|
operations.replaceGroups([]);
|
|
41790
41899
|
}
|
|
41900
|
+
deletionCoordinator.load(state.deletionTombstones ?? []);
|
|
41901
|
+
try {
|
|
41902
|
+
deletionCoordinator.sweepExpired();
|
|
41903
|
+
} catch (error51) {
|
|
41904
|
+
console.warn(`[fleet-console] Expired deletion sweep deferred: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
41905
|
+
}
|
|
41791
41906
|
await restoreCodexWorkspaces();
|
|
41792
41907
|
}
|
|
41793
41908
|
async function restoreCodexWorkspaces() {
|
|
@@ -41829,16 +41944,20 @@ function createConsoleServer(deps = {}) {
|
|
|
41829
41944
|
}
|
|
41830
41945
|
function persistDurableState() {
|
|
41831
41946
|
try {
|
|
41832
|
-
|
|
41833
|
-
version: 2,
|
|
41834
|
-
theaters: theaters.list(),
|
|
41835
|
-
operations: operations.list(),
|
|
41836
|
-
groups: operations.listAllGroups()
|
|
41837
|
-
});
|
|
41947
|
+
saveDurableState(deletionCoordinator.list());
|
|
41838
41948
|
} catch (error51) {
|
|
41839
41949
|
console.warn(`[fleet-console] Durable state save failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
41840
41950
|
}
|
|
41841
41951
|
}
|
|
41952
|
+
function saveDurableState(deletionTombstones) {
|
|
41953
|
+
durableStateStore.save({
|
|
41954
|
+
version: STATE_VERSION,
|
|
41955
|
+
theaters: theaters.list(),
|
|
41956
|
+
operations: operations.list(),
|
|
41957
|
+
groups: operations.listAllGroups(),
|
|
41958
|
+
deletionTombstones
|
|
41959
|
+
});
|
|
41960
|
+
}
|
|
41842
41961
|
async function stopServer() {
|
|
41843
41962
|
const current = server;
|
|
41844
41963
|
const currentLoopback = loopbackServer;
|
|
@@ -41848,6 +41967,7 @@ function createConsoleServer(deps = {}) {
|
|
|
41848
41967
|
lockHandle = null;
|
|
41849
41968
|
activeLockFile = null;
|
|
41850
41969
|
activeEndpoint = null;
|
|
41970
|
+
deletionCoordinator.dispose();
|
|
41851
41971
|
try {
|
|
41852
41972
|
await Promise.all([
|
|
41853
41973
|
closeHttpServer(current),
|