@dotobokuri/fleet-console 1.32.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 +578 -451
- package/dist/client/assets/{_baseUniq-BcB5wmG1.js → _baseUniq-kpxXKqaz.js} +1 -1
- package/dist/client/assets/{arc-DdDM-o2K.js → arc-Cf0soLes.js} +1 -1
- package/dist/client/assets/{architectureDiagram-Q4EWVU46-CIF7NLBh.js → architectureDiagram-Q4EWVU46-DiRqbCQ7.js} +1 -1
- package/dist/client/assets/{blockDiagram-DXYQGD6D-uTDIsi9C.js → blockDiagram-DXYQGD6D-DC25h3LU.js} +1 -1
- package/dist/client/assets/{c4Diagram-AHTNJAMY-B-L5_peH.js → c4Diagram-AHTNJAMY-BJLnKoD4.js} +1 -1
- package/dist/client/assets/channel-Deg6stWj.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-R3NuBeMM.js → chunk-4BX2VUAB-DWUk4gCy.js} +1 -1
- package/dist/client/assets/{chunk-4TB4RGXK-GqEsM9Hl.js → chunk-4TB4RGXK-DW4Ee9nw.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-D4a7-QMt.js → chunk-55IACEB6-8z_Na955.js} +1 -1
- package/dist/client/assets/{chunk-EDXVE4YY-CFnwIApt.js → chunk-EDXVE4YY-C3Z4nalr.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-Bx6k_N10.js → chunk-FMBD7UC4-UIVDEAE7.js} +1 -1
- package/dist/client/assets/{chunk-OYMX7WX6-2QjCvEfI.js → chunk-OYMX7WX6-DpFWa4G9.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-SRIQm3h2.js → chunk-QZHKN3VN-BJndYOsb.js} +1 -1
- package/dist/client/assets/{chunk-YZCP3GAM-D3j-Ehhn.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-BDRpmFTS.js → cose-bilkent-S5V4N54A-C3m_quy1.js} +1 -1
- package/dist/client/assets/{dagre-KV5264BT-CNnBa0oO.js → dagre-KV5264BT-DzDFWezD.js} +1 -1
- package/dist/client/assets/{diagram-5BDNPKRD-DmLR5VLJ.js → diagram-5BDNPKRD-D3OFrOF_.js} +1 -1
- package/dist/client/assets/{diagram-G4DWMVQ6-D9-S4gAC.js → diagram-G4DWMVQ6-CgCqSaI7.js} +1 -1
- package/dist/client/assets/{diagram-MMDJMWI5-BgkkFSRH.js → diagram-MMDJMWI5-CnJzOV_w.js} +1 -1
- package/dist/client/assets/{diagram-TYMM5635-CRwM_tDY.js → diagram-TYMM5635-BrUz8pH4.js} +1 -1
- package/dist/client/assets/{erDiagram-SMLLAGMA-DU-pow1m.js → erDiagram-SMLLAGMA-C1IvCMgN.js} +1 -1
- package/dist/client/assets/{flowDiagram-DWJPFMVM-B91EFbjc.js → flowDiagram-DWJPFMVM-DCrfhs19.js} +1 -1
- package/dist/client/assets/{ganttDiagram-T4ZO3ILL-B-gUVWSs.js → ganttDiagram-T4ZO3ILL-ChQcD1Li.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-TBkviHit.js → gitGraphDiagram-UUTBAWPF-C5aEYdTT.js} +1 -1
- package/dist/client/assets/{graph-Da2r3MMt.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-CAdIgU9C.js → infoDiagram-42DDH7IO-BMhiz3U-.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-DKMRplux.js → ishikawaDiagram-UXIWVN3A-5_f4rhFk.js} +1 -1
- package/dist/client/assets/{journeyDiagram-VCZTEJTY-CPR33z10.js → journeyDiagram-VCZTEJTY-BHP2UyTZ.js} +1 -1
- package/dist/client/assets/{kanban-definition-6JOO6SKY-CDsviLfH.js → kanban-definition-6JOO6SKY-edTTflKa.js} +1 -1
- package/dist/client/assets/{layout-CkN1-8C9.js → layout-B7z9q0n7.js} +1 -1
- package/dist/client/assets/{linear-BxLFCpuS.js → linear-BDNnEnhj.js} +1 -1
- package/dist/client/assets/{mermaid.core-DA-WJY50.js → mermaid.core-DDcMYg9W.js} +4 -4
- package/dist/client/assets/{min-BsISxNaF.js → min-D6WC647e.js} +1 -1
- package/dist/client/assets/{mindmap-definition-QFDTVHPH-B-IUTdhh.js → mindmap-definition-QFDTVHPH-lvrJFtla.js} +1 -1
- package/dist/client/assets/{pieDiagram-DEJITSTG-hwSroJDA.js → pieDiagram-DEJITSTG-D1h_ZTUL.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-34T5L4WZ-DDt9AzF7.js → quadrantDiagram-34T5L4WZ-DSAYqOT0.js} +1 -1
- package/dist/client/assets/{requirementDiagram-MS252O5E-C5Xj9gqW.js → requirementDiagram-MS252O5E-BtNZUJPU.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-XADWPNL6-ZwBDrthi.js → sankeyDiagram-XADWPNL6-Ci2wj876.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-FGHM5R23-DmyMDdrv.js → sequenceDiagram-FGHM5R23-ES3fQi8m.js} +1 -1
- package/dist/client/assets/{stateDiagram-FHFEXIEX-VD5zvoai.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-DP8udMAZ.js → timeline-definition-GMOUNBTQ-Bl7xwJpF.js} +1 -1
- package/dist/client/assets/{vennDiagram-DHZGUBPP-CiBN7TbR.js → vennDiagram-DHZGUBPP-Csv3w_qu.js} +1 -1
- package/dist/client/assets/{wardley-RL74JXVD-BtqeTzop.js → wardley-RL74JXVD-CaXvusTS.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-NUSXRM2D-DaRdj2RP.js → wardleyDiagram-NUSXRM2D-DfKsNCHq.js} +1 -1
- package/dist/client/assets/{xychartDiagram-5P7HB3ND-jlgNCyFB.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 +1003 -917
- package/package.json +1 -1
- package/dist/client/assets/channel-BamKwHPs.js +0 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-sEh9Glhk.js +0 -1
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-sEh9Glhk.js +0 -1
- package/dist/client/assets/clone-iMU-qXwc.js +0 -1
- package/dist/client/assets/index-5-y-ZMI6.js +0 -451
- package/dist/client/assets/index-BBOlVlPk.css +0 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-CFTLlJ0p.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;
|
|
@@ -1679,55 +1685,55 @@ authority: Admiral of the Navy (\uB300\uC6D0\uC218)
|
|
|
1679
1685
|
|
|
1680
1686
|
# Fleet Wiki Workspace Doctrine
|
|
1681
1687
|
|
|
1682
|
-
This directory is the **Fleet Wiki** \u2014 a workspace-local markdown knowledge base. All entries here are governed by a deterministic patch queue with mandatory
|
|
1688
|
+
This directory is the **Fleet Wiki** \u2014 a workspace-local markdown knowledge base. All entries here are governed by a deterministic patch queue with mandatory host approval. **Direct filesystem edits are forbidden for any agent or carrier.**
|
|
1683
1689
|
|
|
1684
1690
|
The active entry schema is defined in \`schema/wiki-schema.md\` and may be revised by the Admiral of the Navy (\uB300\uC6D0\uC218) at any time. Always consult the current schema rather than assuming a fixed format.
|
|
1685
1691
|
|
|
1686
1692
|
## 1. Hard Boundaries (CRITICAL)
|
|
1687
1693
|
|
|
1688
|
-
The following prohibitions are **absolute** for every carrier
|
|
1694
|
+
The following prohibitions are **absolute** for every carrier and any sub-agent operating in this directory:
|
|
1689
1695
|
|
|
1690
|
-
- **NEVER** edit any file under \`wiki/\` directly via filesystem tools (Read/Write/Edit). Entry creation and new staged revisions must go through \`wiki_ingest\`; already-pending queue proposal revisions may use \`wiki_patch_edit\`.
|
|
1696
|
+
- **NEVER** edit any file under \`wiki/\` directly via filesystem tools (Read/Write/Edit). Entry creation and new staged revisions must go through host-only \`wiki_ingest\`; already-pending queue proposal revisions may use host-only \`wiki_patch_edit\`.
|
|
1691
1697
|
- **NEVER** edit \`index.json\`, \`wiki/index.md\`, or \`log.md\` by hand. These files are **system-managed** and rebuilt automatically when patches are approved.
|
|
1692
1698
|
- **NEVER** edit files under \`raw/\` after creation \u2014 raw sources are immutable evidence and \`wiki_ingest\` writes them automatically.
|
|
1693
1699
|
- **NEVER** touch \`queue/\`, \`archive/\`, or \`conflicts/\` \u2014 these are workflow-internal stores managed by the wiki tooling.
|
|
1694
|
-
-
|
|
1700
|
+
- **NEVER** invoke mutation, staging, lint, schema, or approval Wiki tools from a carrier executor. Those tools are **host-only**; runtime ACLs are authoritative.
|
|
1701
|
+
- **NEVER** approve or reject patches from a carrier executor. Approval authority is **host-only** through \`wiki_patch_queue\`.
|
|
1695
1702
|
|
|
1696
1703
|
## 2. Roles and Gates
|
|
1697
1704
|
|
|
1698
1705
|
| Role | Capability | Gate |
|
|
1699
1706
|
|------|-----------|------|
|
|
1700
|
-
| **Carriers**
|
|
1701
|
-
| **
|
|
1707
|
+
| **Carriers** | Read-only consult: \`wiki_orient\` \xB7 \`wiki_briefing\` \xB7 \`wiki_read\` \xB7 \`wiki_resolve\` | Cannot mutate, stage, lint, inspect/create schema, or approve patches |
|
|
1708
|
+
| **Host (Admiral PI)** | Read, compose, stage (\`wiki_ingest\`), revise pending (\`wiki_patch_edit\`), lint (\`wiki_drydock\`), query (\`wiki_query\`), compile (\`wiki_compile_source\`), schema (\`wiki_schema_list\` / \`wiki_schema_read\` / \`wiki_schema_create\`), approve/reject (\`wiki_patch_queue\`) | Sole mutation, schema, and approval authority |
|
|
1702
1709
|
|
|
1703
|
-
|
|
1710
|
+
The host performs every Fleet Wiki operation directly. Carriers may consult read-only tools for context but must not stage entries, revise patches, lint, create schema templates, or approve queue items.
|
|
1704
1711
|
|
|
1705
1712
|
## 3. Standard Workflow
|
|
1706
1713
|
|
|
1707
1714
|
### 3.1 Read / Lookup
|
|
1708
1715
|
|
|
1709
|
-
\`wiki_orient\` \u2192 \`wiki_briefing\` \u2192 \`wiki_read\` \u2192 \`wiki_resolve\`. Read-only; no approval needed.
|
|
1716
|
+
\`wiki_orient\` \u2192 \`wiki_briefing\` \u2192 \`wiki_read\` \u2192 \`wiki_resolve\`. Read-only; globally shared with carriers; no approval needed.
|
|
1710
1717
|
|
|
1711
|
-
### 3.2
|
|
1718
|
+
### 3.2 Stage a New Entry (Host)
|
|
1712
1719
|
|
|
1713
1720
|
1. **Orient** \u2014 \`wiki_orient\` to confirm workspace state and locate the active schema.
|
|
1714
1721
|
2. **Compose** \u2014 Draft the entry body per the active workspace schema (see \`schema/wiki-schema.md\`). Synthesize raw sources, never copy verbatim.
|
|
1715
1722
|
3. **Ingest** \u2014 \`wiki_ingest\` with \`id\`, \`title\`, \`tags\`, \`body\`, and \`source\` (raw evidence). System auto-writes raw, stages a patch under \`queue/\`, and returns a \`patch_id\`.
|
|
1716
1723
|
4. **Lint** \u2014 \`wiki_drydock\` to verify schema compliance and link integrity.
|
|
1717
|
-
5. **
|
|
1718
|
-
6. **Admiral approves** \u2014 \`wiki_patch_queue approve\` writes the entry to \`wiki/\`, updates indexes, and appends to \`log.md\`. No mutation is performed by hand.
|
|
1724
|
+
5. **Approve** \u2014 \`wiki_patch_queue approve\` writes the entry to \`wiki/\`, updates indexes, and appends to \`log.md\`. No filesystem mutation is performed by hand.
|
|
1719
1725
|
|
|
1720
|
-
### 3.3 Update an Existing Entry
|
|
1726
|
+
### 3.3 Update an Existing Entry (Host)
|
|
1721
1727
|
|
|
1722
1728
|
Same as 3.2 but \`wiki_ingest\` runs in \`update\` mode with \`base_version\` for stale-base detection.
|
|
1723
1729
|
|
|
1724
|
-
### 3.4 Revise an Already-Pending Patch
|
|
1730
|
+
### 3.4 Revise an Already-Pending Patch (Host)
|
|
1725
1731
|
|
|
1726
|
-
Use \`wiki_patch_edit\` with a pending \`patch_id\` for small exact body replacements or metadata corrections before
|
|
1732
|
+
Use \`wiki_patch_edit\` with a pending \`patch_id\` for small exact body replacements or metadata corrections before approval. Do not create another ingest patch for a one-line correction to an existing pending proposal.
|
|
1727
1733
|
|
|
1728
1734
|
## 4. Schema Reference
|
|
1729
1735
|
|
|
1730
|
-
The authoritative source is **\`schema/wiki-schema.md\`**. The Admiral of the Navy (\uB300\uC6D0\uC218) may revise the schema at any time, and \`wiki_drydock\` enforces the current version.
|
|
1736
|
+
The authoritative source is **\`schema/wiki-schema.md\`**. The Admiral of the Navy (\uB300\uC6D0\uC218) may revise the schema at any time through host-only schema tools, and \`wiki_drydock\` enforces the current version.
|
|
1731
1737
|
|
|
1732
1738
|
\`schema/AGENTS.md\` defines the maintainer role for the schema directory itself.
|
|
1733
1739
|
|
|
@@ -1742,7 +1748,7 @@ Always read \`schema/wiki-schema.md\` directly before composing or revising entr
|
|
|
1742
1748
|
## 6. Escalation
|
|
1743
1749
|
|
|
1744
1750
|
- Schema disputes \u2192 Admiral.
|
|
1745
|
-
- Approval
|
|
1751
|
+
- Approval or rejection decisions \u2192 host via \`wiki_patch_queue\`.
|
|
1746
1752
|
- Tool failures / stale state \u2192 re-run \`wiki_drydock\`, then escalate to Admiral if unresolved.
|
|
1747
1753
|
`;
|
|
1748
1754
|
async function ensureWorkspaceSchema(paths) {
|
|
@@ -1911,9 +1917,10 @@ async function writeDefaultFileIfMissing(filePath, content) {
|
|
|
1911
1917
|
try {
|
|
1912
1918
|
await writeFile(filePath, content, { encoding: "utf8", flag: "wx" });
|
|
1913
1919
|
} catch (error51) {
|
|
1914
|
-
if (
|
|
1915
|
-
|
|
1920
|
+
if (isAlreadyExistsError(error51) || isEisdirError(error51) || isEloopError(error51)) {
|
|
1921
|
+
return;
|
|
1916
1922
|
}
|
|
1923
|
+
throw error51;
|
|
1917
1924
|
}
|
|
1918
1925
|
}
|
|
1919
1926
|
async function tryReadSchemaFile(paths, filePath) {
|
|
@@ -2023,6 +2030,12 @@ function parseRequiredSections(content) {
|
|
|
2023
2030
|
}
|
|
2024
2031
|
return sections;
|
|
2025
2032
|
}
|
|
2033
|
+
function isEloopError(error51) {
|
|
2034
|
+
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ELOOP";
|
|
2035
|
+
}
|
|
2036
|
+
function isEisdirError(error51) {
|
|
2037
|
+
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "EISDIR";
|
|
2038
|
+
}
|
|
2026
2039
|
function isAlreadyExistsError(error51) {
|
|
2027
2040
|
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "EEXIST";
|
|
2028
2041
|
}
|
|
@@ -31767,35 +31780,23 @@ var AcpConnection = class extends BaseConnection {
|
|
|
31767
31780
|
}
|
|
31768
31781
|
case "tool_call": {
|
|
31769
31782
|
const { sessionUpdate: _tc, ...toolCallData } = update;
|
|
31770
|
-
const rawTcTitle = toolCallData.title ?? "";
|
|
31771
|
-
const cleanTcTitle = rawTcTitle.replace(/\s*\(\s*[\d.,\s-]*\b(?:NaN|undefined)\b[\d.,\s-]*\)/g, "");
|
|
31772
|
-
if (cleanTcTitle !== rawTcTitle) {
|
|
31773
|
-
console.debug("[AcpConnection] sanitized tool_call payload", { rawTitle: rawTcTitle, cleanTitle: cleanTcTitle });
|
|
31774
|
-
}
|
|
31775
|
-
const titleTcOverride = "title" in toolCallData ? { title: cleanTcTitle } : {};
|
|
31776
31783
|
this.emit(
|
|
31777
31784
|
"toolCall",
|
|
31778
|
-
|
|
31785
|
+
toolCallData.title ?? "",
|
|
31779
31786
|
toolCallData.status ?? "",
|
|
31780
31787
|
sessionId,
|
|
31781
|
-
|
|
31788
|
+
toolCallData
|
|
31782
31789
|
);
|
|
31783
31790
|
break;
|
|
31784
31791
|
}
|
|
31785
31792
|
case "tool_call_update": {
|
|
31786
31793
|
const { sessionUpdate: _tcu, ...toolCallUpdateData } = update;
|
|
31787
|
-
const rawTitle = toolCallUpdateData.title ?? "";
|
|
31788
|
-
const cleanTitle = rawTitle.replace(/\s*\(\s*[\d.,\s-]*\b(?:NaN|undefined)\b[\d.,\s-]*\)/g, "");
|
|
31789
|
-
if (cleanTitle !== rawTitle) {
|
|
31790
|
-
console.debug("[AcpConnection] sanitized tool_call_update payload", { rawTitle, cleanTitle });
|
|
31791
|
-
}
|
|
31792
|
-
const titleOverride = "title" in toolCallUpdateData ? { title: cleanTitle } : {};
|
|
31793
31794
|
this.emit(
|
|
31794
31795
|
"toolCallUpdate",
|
|
31795
|
-
|
|
31796
|
+
toolCallUpdateData.title ?? "",
|
|
31796
31797
|
toolCallUpdateData.status ?? "",
|
|
31797
31798
|
sessionId,
|
|
31798
|
-
|
|
31799
|
+
toolCallUpdateData
|
|
31799
31800
|
);
|
|
31800
31801
|
break;
|
|
31801
31802
|
}
|
|
@@ -31960,7 +31961,7 @@ function inferBinName(packageName) {
|
|
|
31960
31961
|
// ../../packages/core-unified-agent/models.json
|
|
31961
31962
|
var models_default = {
|
|
31962
31963
|
version: 1,
|
|
31963
|
-
updatedAt: "2026-07-
|
|
31964
|
+
updatedAt: "2026-07-25T00:00:00Z",
|
|
31964
31965
|
providers: {
|
|
31965
31966
|
claude: {
|
|
31966
31967
|
name: "Claude Code",
|
|
@@ -31996,11 +31997,13 @@ var models_default = {
|
|
|
31996
31997
|
defaultModel: "gpt-5.6-sol",
|
|
31997
31998
|
models: [
|
|
31998
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" } },
|
|
31999
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" } },
|
|
32000
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" } },
|
|
32001
32005
|
{ modelId: "gpt-5.5", name: "GPT-5.5", effort: { supported: true, levels: ["low", "medium", "high", "xhigh"], default: "high" } },
|
|
32002
|
-
{ modelId: "gpt-5.
|
|
32003
|
-
{ 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" } }
|
|
32004
32007
|
]
|
|
32005
32008
|
},
|
|
32006
32009
|
"opencode-go": {
|
|
@@ -32086,6 +32089,10 @@ var ModelEntrySchema = external_exports.object({
|
|
|
32086
32089
|
description: external_exports.string().optional(),
|
|
32087
32090
|
/** spawn 시 실제 CLI 모델 ID를 조립해야 하는 경우의 템플릿 */
|
|
32088
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(),
|
|
32089
32096
|
/** 모델의 컨텍스트 윈도우 크기 (토큰) */
|
|
32090
32097
|
contextWindow: external_exports.number().int().positive().optional(),
|
|
32091
32098
|
/** 모델별 effort 설정 */
|
|
@@ -32108,6 +32115,14 @@ var ModelEntrySchema = external_exports.object({
|
|
|
32108
32115
|
path: ["spawnModelTemplate"]
|
|
32109
32116
|
});
|
|
32110
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
|
+
}
|
|
32111
32126
|
});
|
|
32112
32127
|
var ModelsMappingSchema = external_exports.record(external_exports.string(), external_exports.string());
|
|
32113
32128
|
var ProviderSchema = external_exports.object({
|
|
@@ -32257,8 +32272,6 @@ var CLI_BACKENDS = {
|
|
|
32257
32272
|
cliCommand: "codex",
|
|
32258
32273
|
protocol: "codex-app-server",
|
|
32259
32274
|
authRequired: true,
|
|
32260
|
-
npxPackage: "@agentclientprotocol/codex-acp@1.1.2",
|
|
32261
|
-
acpArgs: [],
|
|
32262
32275
|
appServerArgs: ["app-server", "--listen", "stdio://"],
|
|
32263
32276
|
modes: [
|
|
32264
32277
|
{ id: "default", label: "Plan" },
|
|
@@ -32268,7 +32281,7 @@ var CLI_BACKENDS = {
|
|
|
32268
32281
|
supportsSessionClose: true,
|
|
32269
32282
|
supportsSessionLoad: true,
|
|
32270
32283
|
requiresModelAtSpawn: false,
|
|
32271
|
-
usesNpxBridge:
|
|
32284
|
+
usesNpxBridge: false,
|
|
32272
32285
|
defaultMaxTokens: 1e5
|
|
32273
32286
|
},
|
|
32274
32287
|
"opencode-go": {
|
|
@@ -32359,22 +32372,6 @@ function getYoloModeId(cli) {
|
|
|
32359
32372
|
function getAllBackendConfigs() {
|
|
32360
32373
|
return Object.values(CLI_BACKENDS);
|
|
32361
32374
|
}
|
|
32362
|
-
function buildCodexConfigEnv(configOverrides, baseConfigJson) {
|
|
32363
|
-
const map2 = parseBaseConfigMap(baseConfigJson);
|
|
32364
|
-
for (const override of configOverrides ?? []) {
|
|
32365
|
-
const eqIndex = override.indexOf("=");
|
|
32366
|
-
if (eqIndex < 0) {
|
|
32367
|
-
continue;
|
|
32368
|
-
}
|
|
32369
|
-
const key = override.slice(0, eqIndex);
|
|
32370
|
-
const rawValue = override.slice(eqIndex + 1);
|
|
32371
|
-
assignNestedKey(map2, key, parseOverrideValue(rawValue));
|
|
32372
|
-
}
|
|
32373
|
-
if (Object.keys(map2).length === 0) {
|
|
32374
|
-
return void 0;
|
|
32375
|
-
}
|
|
32376
|
-
return JSON.stringify(map2);
|
|
32377
|
-
}
|
|
32378
32375
|
function buildConfigOverrideArgs(overrides) {
|
|
32379
32376
|
return overrides.flatMap((override) => ["-c", override]);
|
|
32380
32377
|
}
|
|
@@ -32401,45 +32398,6 @@ function mcpServerConfigsToAcp(servers) {
|
|
|
32401
32398
|
headers: server.headers ?? []
|
|
32402
32399
|
}));
|
|
32403
32400
|
}
|
|
32404
|
-
function parseBaseConfigMap(baseConfigJson) {
|
|
32405
|
-
if (!baseConfigJson) {
|
|
32406
|
-
return {};
|
|
32407
|
-
}
|
|
32408
|
-
try {
|
|
32409
|
-
const parsed = JSON.parse(baseConfigJson);
|
|
32410
|
-
if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
|
|
32411
|
-
return parsed;
|
|
32412
|
-
}
|
|
32413
|
-
} catch {
|
|
32414
|
-
}
|
|
32415
|
-
return {};
|
|
32416
|
-
}
|
|
32417
|
-
function parseOverrideValue(raw) {
|
|
32418
|
-
try {
|
|
32419
|
-
return JSON.parse(raw);
|
|
32420
|
-
} catch {
|
|
32421
|
-
if (raw.length >= 2 && raw.startsWith('"') && raw.endsWith('"')) {
|
|
32422
|
-
return raw.slice(1, -1);
|
|
32423
|
-
}
|
|
32424
|
-
return raw;
|
|
32425
|
-
}
|
|
32426
|
-
}
|
|
32427
|
-
function assignNestedKey(target, dottedKey, value) {
|
|
32428
|
-
const segments = dottedKey.split(".");
|
|
32429
|
-
let cursor = target;
|
|
32430
|
-
for (let i = 0; i < segments.length - 1; i += 1) {
|
|
32431
|
-
const segment = segments[i];
|
|
32432
|
-
const existing = cursor[segment];
|
|
32433
|
-
if (typeof existing === "object" && existing !== null && !Array.isArray(existing)) {
|
|
32434
|
-
cursor = existing;
|
|
32435
|
-
} else {
|
|
32436
|
-
const nested = {};
|
|
32437
|
-
cursor[segment] = nested;
|
|
32438
|
-
cursor = nested;
|
|
32439
|
-
}
|
|
32440
|
-
}
|
|
32441
|
-
cursor[segments[segments.length - 1]] = value;
|
|
32442
|
-
}
|
|
32443
32401
|
|
|
32444
32402
|
// ../../packages/core-unified-agent/src/detector/CliDetector.ts
|
|
32445
32403
|
var CLI_DETECT_LIST = Object.entries(CLI_BACKENDS).map(([id, backend]) => ({
|
|
@@ -32995,6 +32953,7 @@ var CODEX_METHODS = {
|
|
|
32995
32953
|
THREAD_RESUME: "thread/resume",
|
|
32996
32954
|
THREAD_READ: "thread/read",
|
|
32997
32955
|
THREAD_ARCHIVE: "thread/archive",
|
|
32956
|
+
THREAD_UNARCHIVE: "thread/unarchive",
|
|
32998
32957
|
TURN_START: "turn/start",
|
|
32999
32958
|
TURN_INTERRUPT: "turn/interrupt",
|
|
33000
32959
|
TURN_STEER: "turn/steer"
|
|
@@ -33023,6 +32982,7 @@ var CODEX_MCP_READY_STATUS = "ready";
|
|
|
33023
32982
|
var CODEX_MCP_FAILED_STATUSES = /* @__PURE__ */ new Set(["failed", "error"]);
|
|
33024
32983
|
var DEFAULT_MCP_STARTUP_TIMEOUT = 6e4;
|
|
33025
32984
|
var STDERR_TAIL_LIMIT = 20;
|
|
32985
|
+
var SESSION_TEARDOWN_TIMEOUT_MS = 5e3;
|
|
33026
32986
|
var CodexAppServerConnection = class extends BaseConnection {
|
|
33027
32987
|
clientInfo;
|
|
33028
32988
|
autoApprove;
|
|
@@ -33035,6 +32995,7 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33035
32995
|
pendingMcpReadyWaiters = /* @__PURE__ */ new Set();
|
|
33036
32996
|
stdoutBuffer = "";
|
|
33037
32997
|
pendingModel = null;
|
|
32998
|
+
pendingServiceTier = void 0;
|
|
33038
32999
|
pendingEffort = null;
|
|
33039
33000
|
codexHome = null;
|
|
33040
33001
|
isDisconnecting = false;
|
|
@@ -33059,6 +33020,9 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33059
33020
|
setPendingModel(model) {
|
|
33060
33021
|
this.pendingModel = model;
|
|
33061
33022
|
}
|
|
33023
|
+
setPendingServiceTier(serviceTier) {
|
|
33024
|
+
this.pendingServiceTier = serviceTier;
|
|
33025
|
+
}
|
|
33062
33026
|
setPendingEffort(effort) {
|
|
33063
33027
|
this.pendingEffort = effort;
|
|
33064
33028
|
}
|
|
@@ -33101,6 +33065,7 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33101
33065
|
cwd: options?.cwd ?? this.cwd,
|
|
33102
33066
|
developerInstructions: options?.developerInstructions ?? null,
|
|
33103
33067
|
model: options?.model ?? null,
|
|
33068
|
+
serviceTier: options?.serviceTier ?? null,
|
|
33104
33069
|
approvalPolicy: options?.approvalPolicy ?? null,
|
|
33105
33070
|
sandbox: options?.sandbox ?? null,
|
|
33106
33071
|
config: options?.config ?? null
|
|
@@ -33111,10 +33076,11 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33111
33076
|
this.setState("ready");
|
|
33112
33077
|
return response;
|
|
33113
33078
|
} catch (error51) {
|
|
33079
|
+
const diagnosticError = this.withStderrDiagnostics(error51, "Codex initialize");
|
|
33114
33080
|
this.setState("error");
|
|
33115
33081
|
this.isDisconnecting = true;
|
|
33116
33082
|
await this.disconnect();
|
|
33117
|
-
throw
|
|
33083
|
+
throw diagnosticError;
|
|
33118
33084
|
}
|
|
33119
33085
|
}
|
|
33120
33086
|
async loadSession(threadId, options) {
|
|
@@ -33122,11 +33088,37 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33122
33088
|
try {
|
|
33123
33089
|
response = await this.sendThreadResumeRequest(threadId, options);
|
|
33124
33090
|
} catch (error51) {
|
|
33125
|
-
|
|
33126
|
-
|
|
33127
|
-
|
|
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);
|
|
33128
33121
|
}
|
|
33129
|
-
response = await this.sendThreadResumeRequest(threadId, options, rolloutPath);
|
|
33130
33122
|
}
|
|
33131
33123
|
this.threadId = response.thread.id;
|
|
33132
33124
|
this.turnId = null;
|
|
@@ -33188,16 +33180,19 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33188
33180
|
this.on("exit", onExit);
|
|
33189
33181
|
});
|
|
33190
33182
|
try {
|
|
33183
|
+
const serviceTier = options?.serviceTier !== void 0 ? options.serviceTier : this.pendingServiceTier;
|
|
33191
33184
|
const response = await this.sendRequest(
|
|
33192
33185
|
CODEX_METHODS.TURN_START,
|
|
33193
33186
|
{
|
|
33194
33187
|
threadId: sessionId,
|
|
33195
33188
|
input,
|
|
33196
33189
|
model: options?.model ?? this.pendingModel ?? null,
|
|
33190
|
+
...serviceTier !== void 0 ? { serviceTier } : {},
|
|
33197
33191
|
effort: options?.effort ?? this.pendingEffort ?? null
|
|
33198
33192
|
}
|
|
33199
33193
|
);
|
|
33200
33194
|
this.pendingModel = null;
|
|
33195
|
+
this.pendingServiceTier = void 0;
|
|
33201
33196
|
this.pendingEffort = null;
|
|
33202
33197
|
this.turnId = response.turn.id;
|
|
33203
33198
|
await turnCompleted;
|
|
@@ -33224,14 +33219,16 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33224
33219
|
if (threadId && activeTurnId) {
|
|
33225
33220
|
await this.sendRequest(
|
|
33226
33221
|
CODEX_METHODS.TURN_INTERRUPT,
|
|
33227
|
-
{ threadId, turnId: activeTurnId }
|
|
33222
|
+
{ threadId, turnId: activeTurnId },
|
|
33223
|
+
SESSION_TEARDOWN_TIMEOUT_MS
|
|
33228
33224
|
).catch(() => {
|
|
33229
33225
|
});
|
|
33230
33226
|
}
|
|
33231
33227
|
if (threadId) {
|
|
33232
33228
|
await this.sendRequest(
|
|
33233
33229
|
CODEX_METHODS.THREAD_ARCHIVE,
|
|
33234
|
-
{ threadId }
|
|
33230
|
+
{ threadId },
|
|
33231
|
+
SESSION_TEARDOWN_TIMEOUT_MS
|
|
33235
33232
|
).catch(() => {
|
|
33236
33233
|
});
|
|
33237
33234
|
}
|
|
@@ -33249,6 +33246,7 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33249
33246
|
cwd: options?.cwd ?? this.cwd,
|
|
33250
33247
|
developerInstructions: options?.developerInstructions ?? null,
|
|
33251
33248
|
model: options?.model ?? null,
|
|
33249
|
+
serviceTier: options?.serviceTier ?? null,
|
|
33252
33250
|
approvalPolicy: options?.approvalPolicy ?? null,
|
|
33253
33251
|
sandbox: options?.sandbox ?? null,
|
|
33254
33252
|
config: options?.config ?? null
|
|
@@ -33266,6 +33264,9 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33266
33264
|
this.rejectPendingRequests(new Error("Codex \uC5F0\uACB0\uC774 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
33267
33265
|
this.rejectPendingMcpReadyWaiters(new Error("Codex \uC5F0\uACB0\uC774 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
33268
33266
|
this.stdoutBuffer = "";
|
|
33267
|
+
this.pendingModel = null;
|
|
33268
|
+
this.pendingServiceTier = void 0;
|
|
33269
|
+
this.pendingEffort = null;
|
|
33269
33270
|
this.codexHome = null;
|
|
33270
33271
|
try {
|
|
33271
33272
|
await super.disconnect();
|
|
@@ -33714,6 +33715,7 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33714
33715
|
path: rolloutPath ?? null,
|
|
33715
33716
|
cwd: options?.cwd ?? this.cwd,
|
|
33716
33717
|
model: options?.model ?? null,
|
|
33718
|
+
serviceTier: options?.serviceTier ?? null,
|
|
33717
33719
|
approvalPolicy: options?.approvalPolicy ?? null,
|
|
33718
33720
|
sandbox: options?.sandbox ?? null,
|
|
33719
33721
|
developerInstructions: options?.developerInstructions ?? null,
|
|
@@ -33833,6 +33835,9 @@ var CodexAppServerConnection = class extends BaseConnection {
|
|
|
33833
33835
|
function isMissingRolloutError(error51, threadId) {
|
|
33834
33836
|
return error51 instanceof Error && error51.message.includes(`no rollout found for thread id ${threadId}`);
|
|
33835
33837
|
}
|
|
33838
|
+
function isArchivedThreadError(error51, threadId) {
|
|
33839
|
+
return error51 instanceof Error && error51.message.includes(`session ${threadId} is archived`);
|
|
33840
|
+
}
|
|
33836
33841
|
function findRolloutPath(root, threadId) {
|
|
33837
33842
|
if (!fs10.existsSync(root)) {
|
|
33838
33843
|
return null;
|
|
@@ -33854,7 +33859,7 @@ function findRolloutPath(root, threadId) {
|
|
|
33854
33859
|
}
|
|
33855
33860
|
|
|
33856
33861
|
// ../../packages/core-unified-agent/src/client/UnifiedCodexAgentClient.ts
|
|
33857
|
-
var CODEX_TURN_LEVEL_CONFIG_KEYS = /* @__PURE__ */ new Set(["effort"
|
|
33862
|
+
var CODEX_TURN_LEVEL_CONFIG_KEYS = /* @__PURE__ */ new Set(["effort"]);
|
|
33858
33863
|
var CODEX_THREAD_POLICY_CONFIG_KEYS = /* @__PURE__ */ new Set(["approvalPolicy", "sandbox"]);
|
|
33859
33864
|
var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
33860
33865
|
connection = null;
|
|
@@ -33863,6 +33868,8 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33863
33868
|
currentSystemPrompt = null;
|
|
33864
33869
|
firstPromptPending = null;
|
|
33865
33870
|
pendingOverrides = null;
|
|
33871
|
+
currentModelSelection = {};
|
|
33872
|
+
archiveSessionOnDisconnect = false;
|
|
33866
33873
|
detector = new CliDetector();
|
|
33867
33874
|
on(event, listener) {
|
|
33868
33875
|
return super.on(event, listener);
|
|
@@ -33882,9 +33889,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33882
33889
|
throw new Error("UnifiedCodexAgentClient\uB294 codex CLI\uB9CC \uC9C0\uC6D0\uD569\uB2C8\uB2E4.");
|
|
33883
33890
|
}
|
|
33884
33891
|
this.validateModelEffort(options.model, options.effort);
|
|
33885
|
-
if (shouldUseCodexAcp(options)) {
|
|
33886
|
-
return this.connectAcp(options);
|
|
33887
|
-
}
|
|
33888
33892
|
return this.connectAppServer(options);
|
|
33889
33893
|
}
|
|
33890
33894
|
async connectAppServer(options) {
|
|
@@ -33893,6 +33897,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33893
33897
|
const command2 = options.cliPath ?? backend.cliCommand;
|
|
33894
33898
|
const baseArgs = backend.appServerArgs ?? ["app-server", "--listen", "stdio://"];
|
|
33895
33899
|
const modeMapping = this.resolveMode(options.yoloMode === false ? "default" : "yolo");
|
|
33900
|
+
const modelSelection = this.resolveModelSelection(options.model);
|
|
33896
33901
|
const args = [
|
|
33897
33902
|
...baseArgs,
|
|
33898
33903
|
...this.buildStartupConfigArgs(options.configOverrides, options.mcpServers, modeMapping)
|
|
@@ -33916,13 +33921,14 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33916
33921
|
if (options.sessionId) {
|
|
33917
33922
|
await connection.connect({
|
|
33918
33923
|
skipThreadStart: true,
|
|
33919
|
-
model:
|
|
33924
|
+
model: modelSelection.providerModelId,
|
|
33925
|
+
serviceTier: modelSelection.serviceTier
|
|
33920
33926
|
});
|
|
33921
33927
|
await connection.loadSession(
|
|
33922
33928
|
options.sessionId,
|
|
33923
33929
|
this.buildCodexThreadDefaultsForResume(
|
|
33924
33930
|
options.cwd,
|
|
33925
|
-
|
|
33931
|
+
modelSelection,
|
|
33926
33932
|
null,
|
|
33927
33933
|
modeMapping
|
|
33928
33934
|
)
|
|
@@ -33930,7 +33936,8 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33930
33936
|
} else {
|
|
33931
33937
|
await connection.connect({
|
|
33932
33938
|
developerInstructions: void 0,
|
|
33933
|
-
model:
|
|
33939
|
+
model: modelSelection.providerModelId,
|
|
33940
|
+
serviceTier: modelSelection.serviceTier,
|
|
33934
33941
|
approvalPolicy: modeMapping.approvalPolicy,
|
|
33935
33942
|
sandbox: modeMapping.sandbox
|
|
33936
33943
|
});
|
|
@@ -33944,6 +33951,8 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33944
33951
|
this.sessionCwd = options.cwd;
|
|
33945
33952
|
this.currentSystemPrompt = options.systemPrompt ?? null;
|
|
33946
33953
|
this.firstPromptPending = options.sessionId ? null : this.currentSystemPrompt;
|
|
33954
|
+
this.currentModelSelection = modelSelection;
|
|
33955
|
+
this.archiveSessionOnDisconnect = options.archiveSessionOnDisconnect === true;
|
|
33947
33956
|
this.pendingOverrides = {
|
|
33948
33957
|
turnConfig: options.effort ? { effort: options.effort } : {},
|
|
33949
33958
|
threadConfig: {
|
|
@@ -33957,71 +33966,17 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
33957
33966
|
session: { sessionId }
|
|
33958
33967
|
};
|
|
33959
33968
|
}
|
|
33960
|
-
async connectAcp(options) {
|
|
33961
|
-
const cleanEnv = cleanEnvironment(process.env, options.env);
|
|
33962
|
-
const spawnConfig = createSpawnConfig("codex", options);
|
|
33963
|
-
const codexConfigEnv = buildCodexConfigEnv(
|
|
33964
|
-
options.configOverrides,
|
|
33965
|
-
cleanEnv.CODEX_CONFIG
|
|
33966
|
-
);
|
|
33967
|
-
const connection = new AcpConnection({
|
|
33968
|
-
command: spawnConfig.command,
|
|
33969
|
-
args: spawnConfig.args,
|
|
33970
|
-
cliType: "codex",
|
|
33971
|
-
cwd: options.cwd,
|
|
33972
|
-
env: { ...cleanEnv, ...codexConfigEnv ? { CODEX_CONFIG: codexConfigEnv } : {} },
|
|
33973
|
-
requestTimeout: options.timeout ?? 6e5,
|
|
33974
|
-
initTimeout: options.timeout ?? 6e4,
|
|
33975
|
-
promptIdleTimeout: options.promptIdleTimeout ?? 6e5,
|
|
33976
|
-
clientInfo: options.clientInfo,
|
|
33977
|
-
autoApprove: options.autoApprove,
|
|
33978
|
-
fsAccess: options.fsAccess
|
|
33979
|
-
});
|
|
33980
|
-
this.connection = connection;
|
|
33981
|
-
this.setupEventForwarding();
|
|
33982
|
-
const recentLogs = [];
|
|
33983
|
-
const collectLog = (message) => {
|
|
33984
|
-
recentLogs.push(message);
|
|
33985
|
-
if (recentLogs.length > 30) {
|
|
33986
|
-
recentLogs.shift();
|
|
33987
|
-
}
|
|
33988
|
-
};
|
|
33989
|
-
connection.on("log", collectLog);
|
|
33990
|
-
let session;
|
|
33991
|
-
try {
|
|
33992
|
-
session = await connection.connect(
|
|
33993
|
-
options.cwd,
|
|
33994
|
-
options.sessionId,
|
|
33995
|
-
this.resolveAcpMcpServers(options.mcpServers)
|
|
33996
|
-
);
|
|
33997
|
-
} catch (error51) {
|
|
33998
|
-
const connectionError = this.buildConnectionError(error51, recentLogs);
|
|
33999
|
-
await this.cleanupFailedConnection();
|
|
34000
|
-
throw connectionError;
|
|
34001
|
-
} finally {
|
|
34002
|
-
connection.off("log", collectLog);
|
|
34003
|
-
}
|
|
34004
|
-
await this.finalizeAcpConnect(options, session);
|
|
34005
|
-
return {
|
|
34006
|
-
cli: "codex",
|
|
34007
|
-
protocol: "acp",
|
|
34008
|
-
session
|
|
34009
|
-
};
|
|
34010
|
-
}
|
|
34011
33969
|
async disconnect() {
|
|
34012
33970
|
if (!this.connection) {
|
|
34013
33971
|
this.clearSessionState();
|
|
34014
33972
|
return;
|
|
34015
33973
|
}
|
|
34016
|
-
|
|
34017
|
-
|
|
34018
|
-
|
|
34019
|
-
await conn.endSession(this.sessionId);
|
|
34020
|
-
} catch {
|
|
34021
|
-
}
|
|
33974
|
+
if (this.archiveSessionOnDisconnect && this.sessionId) {
|
|
33975
|
+
await this.connection.endSession().catch(() => {
|
|
33976
|
+
});
|
|
34022
33977
|
}
|
|
34023
|
-
await
|
|
34024
|
-
|
|
33978
|
+
await this.connection.disconnect();
|
|
33979
|
+
this.connection.removeAllListeners();
|
|
34025
33980
|
this.connection = null;
|
|
34026
33981
|
this.clearSessionState();
|
|
34027
33982
|
}
|
|
@@ -34029,14 +33984,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34029
33984
|
if (!this.connection) {
|
|
34030
33985
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34031
33986
|
}
|
|
34032
|
-
|
|
34033
|
-
if (!this.sessionId) {
|
|
34034
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34035
|
-
}
|
|
34036
|
-
await this.connection.endSession(this.sessionId);
|
|
34037
|
-
} else {
|
|
34038
|
-
await this.connection.endSession();
|
|
34039
|
-
}
|
|
33987
|
+
await this.connection.endSession();
|
|
34040
33988
|
this.sessionId = null;
|
|
34041
33989
|
this.sessionCwd = null;
|
|
34042
33990
|
}
|
|
@@ -34051,7 +33999,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34051
33999
|
}
|
|
34052
34000
|
return {
|
|
34053
34001
|
cli: "codex",
|
|
34054
|
-
protocol:
|
|
34002
|
+
protocol: "codex-app-server",
|
|
34055
34003
|
sessionId: this.sessionId,
|
|
34056
34004
|
state: this.connection.connectionState
|
|
34057
34005
|
};
|
|
@@ -34063,12 +34011,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34063
34011
|
if (!this.connection) {
|
|
34064
34012
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34065
34013
|
}
|
|
34066
|
-
if (this.connection instanceof AcpConnection) {
|
|
34067
|
-
if (!this.sessionId) {
|
|
34068
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34069
|
-
}
|
|
34070
|
-
return this.sendPromptWithPendingSystemPrompt(content);
|
|
34071
|
-
}
|
|
34072
34014
|
this.applyPendingOverrides();
|
|
34073
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: [] });
|
|
34074
34016
|
const systemPrompt = this.firstPromptPending;
|
|
@@ -34079,53 +34021,20 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34079
34021
|
}
|
|
34080
34022
|
return { stopReason: "end_turn" };
|
|
34081
34023
|
}
|
|
34082
|
-
async sendPromptWithPendingSystemPrompt(content) {
|
|
34083
|
-
if (!(this.connection instanceof AcpConnection) || !this.sessionId) {
|
|
34084
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34085
|
-
}
|
|
34086
|
-
const systemPrompt = this.firstPromptPending;
|
|
34087
|
-
if (!systemPrompt) {
|
|
34088
|
-
return this.connection.sendPrompt(this.sessionId, content);
|
|
34089
|
-
}
|
|
34090
|
-
const userBlocks = typeof content === "string" ? [{ type: "text", text: content }] : content;
|
|
34091
|
-
const response = await this.connection.sendPrompt(this.sessionId, [
|
|
34092
|
-
{ type: "text", text: systemPrompt },
|
|
34093
|
-
...userBlocks
|
|
34094
|
-
]);
|
|
34095
|
-
this.firstPromptPending = null;
|
|
34096
|
-
return response;
|
|
34097
|
-
}
|
|
34098
34024
|
async cancelPrompt() {
|
|
34099
34025
|
if (!this.connection) {
|
|
34100
34026
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34101
34027
|
}
|
|
34102
|
-
if (this.connection instanceof AcpConnection) {
|
|
34103
|
-
if (!this.sessionId) {
|
|
34104
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34105
|
-
}
|
|
34106
|
-
await this.connection.cancelSession(this.sessionId);
|
|
34107
|
-
return;
|
|
34108
|
-
}
|
|
34109
34028
|
await this.connection.cancelPrompt();
|
|
34110
34029
|
}
|
|
34111
34030
|
async setModel(model) {
|
|
34112
|
-
|
|
34113
|
-
|
|
34114
|
-
|
|
34115
|
-
}
|
|
34116
|
-
this.ensurePendingOverrides().model = model;
|
|
34031
|
+
const selection = this.resolveModelSelection(model);
|
|
34032
|
+
this.currentModelSelection = selection;
|
|
34033
|
+
this.ensurePendingOverrides().model = selection;
|
|
34117
34034
|
}
|
|
34118
34035
|
async setConfigOption(configId, value) {
|
|
34119
|
-
if (
|
|
34120
|
-
|
|
34121
|
-
await this.connection.setModel(this.sessionId, value);
|
|
34122
|
-
return;
|
|
34123
|
-
}
|
|
34124
|
-
await this.connection.setConfigOption(
|
|
34125
|
-
this.sessionId,
|
|
34126
|
-
configId === "effort" ? "reasoning_effort" : configId,
|
|
34127
|
-
value
|
|
34128
|
-
);
|
|
34036
|
+
if (configId === "model") {
|
|
34037
|
+
await this.setModel(value);
|
|
34129
34038
|
return;
|
|
34130
34039
|
}
|
|
34131
34040
|
const pending = this.ensurePendingOverrides();
|
|
@@ -34137,10 +34046,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34137
34046
|
this.emitTyped("log", `[codex] config '${configId}' will apply on next thread/start or thread/resume`);
|
|
34138
34047
|
}
|
|
34139
34048
|
async setMode(mode) {
|
|
34140
|
-
if (this.connection instanceof AcpConnection && this.sessionId) {
|
|
34141
|
-
await this.connection.setMode(this.sessionId, this.resolveAcpMode(mode));
|
|
34142
|
-
return;
|
|
34143
|
-
}
|
|
34144
34049
|
const resolved = this.resolveMode(mode);
|
|
34145
34050
|
const pending = this.ensurePendingOverrides();
|
|
34146
34051
|
pending.threadConfig.approvalPolicy = resolved.approvalPolicy;
|
|
@@ -34163,17 +34068,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34163
34068
|
if (!this.connection) {
|
|
34164
34069
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34165
34070
|
}
|
|
34166
|
-
if (this.connection instanceof AcpConnection) {
|
|
34167
|
-
await this.connection.loadSession({
|
|
34168
|
-
sessionId,
|
|
34169
|
-
cwd: this.sessionCwd ?? process.cwd(),
|
|
34170
|
-
mcpServers: this.resolveAcpMcpServers(mcpServers)
|
|
34171
|
-
});
|
|
34172
|
-
this.sessionId = sessionId;
|
|
34173
|
-
this.currentSystemPrompt = null;
|
|
34174
|
-
this.firstPromptPending = null;
|
|
34175
|
-
return;
|
|
34176
|
-
}
|
|
34177
34071
|
if (mcpServers?.length) {
|
|
34178
34072
|
this.emitTyped(
|
|
34179
34073
|
"log",
|
|
@@ -34185,7 +34079,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34185
34079
|
sessionId,
|
|
34186
34080
|
this.buildCodexThreadDefaultsForResume(
|
|
34187
34081
|
targetCwd,
|
|
34188
|
-
|
|
34082
|
+
this.currentModelSelection,
|
|
34189
34083
|
null,
|
|
34190
34084
|
this.pendingOverrides?.threadConfig ?? {}
|
|
34191
34085
|
)
|
|
@@ -34199,24 +34093,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34199
34093
|
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34200
34094
|
}
|
|
34201
34095
|
const targetCwd = cwd ?? this.sessionCwd ?? process.cwd();
|
|
34202
|
-
if (this.connection instanceof AcpConnection) {
|
|
34203
|
-
if (!this.sessionId) {
|
|
34204
|
-
throw new Error("\uC5F0\uACB0\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4");
|
|
34205
|
-
}
|
|
34206
|
-
if (!this.connection.canResetSession) {
|
|
34207
|
-
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.");
|
|
34208
|
-
}
|
|
34209
|
-
await this.connection.endSession(this.sessionId);
|
|
34210
|
-
const session = await this.connection.reconnectSession(targetCwd);
|
|
34211
|
-
this.sessionId = session.sessionId;
|
|
34212
|
-
this.sessionCwd = targetCwd;
|
|
34213
|
-
this.firstPromptPending = this.currentSystemPrompt;
|
|
34214
|
-
return {
|
|
34215
|
-
cli: "codex",
|
|
34216
|
-
protocol: "acp",
|
|
34217
|
-
session
|
|
34218
|
-
};
|
|
34219
|
-
}
|
|
34220
34096
|
const result = await this.connection.resetSession(
|
|
34221
34097
|
this.buildCodexThreadDefaultsForReset(targetCwd)
|
|
34222
34098
|
);
|
|
@@ -34232,33 +34108,14 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34232
34108
|
protocol: "codex-app-server"
|
|
34233
34109
|
};
|
|
34234
34110
|
}
|
|
34235
|
-
resolveAcpMcpServers(servers) {
|
|
34236
|
-
return servers?.length ? mcpServerConfigsToAcp(servers) : [];
|
|
34237
|
-
}
|
|
34238
|
-
async finalizeAcpConnect(options, session) {
|
|
34239
|
-
this.sessionId = session.sessionId;
|
|
34240
|
-
this.sessionCwd = options.cwd;
|
|
34241
|
-
this.currentSystemPrompt = options.systemPrompt ?? null;
|
|
34242
|
-
this.firstPromptPending = options.sessionId ? null : this.currentSystemPrompt;
|
|
34243
|
-
this.pendingOverrides = {
|
|
34244
|
-
turnConfig: {},
|
|
34245
|
-
threadConfig: {}
|
|
34246
|
-
};
|
|
34247
|
-
const mode = options.yoloMode === false ? "default" : "yolo";
|
|
34248
|
-
await this.setMode(mode);
|
|
34249
|
-
if (options.model) {
|
|
34250
|
-
await this.setModel(options.model);
|
|
34251
|
-
}
|
|
34252
|
-
if (options.effort) {
|
|
34253
|
-
await this.setConfigOption("effort", options.effort);
|
|
34254
|
-
}
|
|
34255
|
-
}
|
|
34256
34111
|
clearSessionState() {
|
|
34257
34112
|
this.sessionId = null;
|
|
34258
34113
|
this.sessionCwd = null;
|
|
34259
34114
|
this.currentSystemPrompt = null;
|
|
34260
34115
|
this.firstPromptPending = null;
|
|
34261
34116
|
this.pendingOverrides = null;
|
|
34117
|
+
this.currentModelSelection = {};
|
|
34118
|
+
this.archiveSessionOnDisconnect = false;
|
|
34262
34119
|
}
|
|
34263
34120
|
validateModelEffort(modelId, effort) {
|
|
34264
34121
|
if (!effort) {
|
|
@@ -34281,69 +34138,7 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34281
34138
|
}
|
|
34282
34139
|
setupEventForwarding() {
|
|
34283
34140
|
if (!this.connection) return;
|
|
34284
|
-
|
|
34285
|
-
if (connection instanceof AcpConnection) {
|
|
34286
|
-
this.setupAcpEventForwarding(connection);
|
|
34287
|
-
return;
|
|
34288
|
-
}
|
|
34289
|
-
this.setupAppServerEventForwarding(connection);
|
|
34290
|
-
}
|
|
34291
|
-
setupAcpEventForwarding(connection) {
|
|
34292
|
-
connection.on("stateChange", (state) => {
|
|
34293
|
-
this.emitTyped("stateChange", state);
|
|
34294
|
-
});
|
|
34295
|
-
connection.on("userMessageChunk", (text, sessionId) => {
|
|
34296
|
-
this.emitTyped("userMessageChunk", text, sessionId);
|
|
34297
|
-
});
|
|
34298
|
-
connection.on("messageChunk", (text, sessionId) => {
|
|
34299
|
-
this.emitTyped("messageChunk", text, sessionId);
|
|
34300
|
-
});
|
|
34301
|
-
connection.on("thoughtChunk", (text, sessionId) => {
|
|
34302
|
-
this.emitTyped("thoughtChunk", text, sessionId);
|
|
34303
|
-
});
|
|
34304
|
-
connection.on("toolCall", (title, status, sessionId, data) => {
|
|
34305
|
-
this.emitTyped("toolCall", title, status, sessionId, data);
|
|
34306
|
-
});
|
|
34307
|
-
connection.on("toolCallUpdate", (title, status, sessionId, data) => {
|
|
34308
|
-
this.emitTyped("toolCallUpdate", title, status, sessionId, data);
|
|
34309
|
-
});
|
|
34310
|
-
connection.on("plan", (plan, sessionId) => {
|
|
34311
|
-
this.emitTyped("plan", plan, sessionId);
|
|
34312
|
-
});
|
|
34313
|
-
connection.on("availableCommandsUpdate", (commands, sessionId) => {
|
|
34314
|
-
this.emitTyped("availableCommandsUpdate", commands, sessionId);
|
|
34315
|
-
});
|
|
34316
|
-
connection.on("promptComplete", (sessionId) => {
|
|
34317
|
-
this.emitTyped("promptComplete", sessionId);
|
|
34318
|
-
});
|
|
34319
|
-
connection.on("permissionRequest", (params, resolve3) => {
|
|
34320
|
-
this.emitTyped(
|
|
34321
|
-
"permissionRequest",
|
|
34322
|
-
params,
|
|
34323
|
-
resolve3
|
|
34324
|
-
);
|
|
34325
|
-
});
|
|
34326
|
-
connection.on("sessionUpdate", (update) => {
|
|
34327
|
-
this.emitTyped("sessionUpdate", update);
|
|
34328
|
-
});
|
|
34329
|
-
connection.on("fileRead", (params, resolve3) => {
|
|
34330
|
-
this.emitTyped("fileRead", params, resolve3);
|
|
34331
|
-
});
|
|
34332
|
-
connection.on("fileWrite", (params, resolve3) => {
|
|
34333
|
-
this.emitTyped("fileWrite", params, resolve3);
|
|
34334
|
-
});
|
|
34335
|
-
connection.on("error", (err) => {
|
|
34336
|
-
this.emitTyped("error", err);
|
|
34337
|
-
});
|
|
34338
|
-
connection.on("exit", (code, signal) => {
|
|
34339
|
-
this.emitTyped("exit", code, signal);
|
|
34340
|
-
});
|
|
34341
|
-
connection.on("log", (msg) => {
|
|
34342
|
-
this.emitTyped("log", msg);
|
|
34343
|
-
});
|
|
34344
|
-
connection.on("logEntry", (entry) => {
|
|
34345
|
-
this.emitTyped("logEntry", entry);
|
|
34346
|
-
});
|
|
34141
|
+
this.setupAppServerEventForwarding(this.connection);
|
|
34347
34142
|
}
|
|
34348
34143
|
setupAppServerEventForwarding(connection) {
|
|
34349
34144
|
connection.on("stateChange", (state) => {
|
|
@@ -34406,15 +34201,15 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34406
34201
|
if (!this.pendingOverrides || !this.connection) {
|
|
34407
34202
|
return;
|
|
34408
34203
|
}
|
|
34409
|
-
if (this.connection instanceof AcpConnection) {
|
|
34410
|
-
return;
|
|
34411
|
-
}
|
|
34412
34204
|
if (this.pendingOverrides.model) {
|
|
34413
|
-
this.connection.setPendingModel(this.pendingOverrides.model);
|
|
34205
|
+
this.connection.setPendingModel(this.pendingOverrides.model.providerModelId ?? null);
|
|
34206
|
+
this.connection.setPendingServiceTier(this.pendingOverrides.model.serviceTier ?? null);
|
|
34414
34207
|
this.pendingOverrides.model = void 0;
|
|
34415
34208
|
}
|
|
34416
34209
|
if (this.pendingOverrides.turnConfig.model) {
|
|
34417
|
-
this.
|
|
34210
|
+
const selection = this.resolveModelSelection(this.pendingOverrides.turnConfig.model);
|
|
34211
|
+
this.connection.setPendingModel(selection.providerModelId ?? null);
|
|
34212
|
+
this.connection.setPendingServiceTier(selection.serviceTier ?? null);
|
|
34418
34213
|
delete this.pendingOverrides.turnConfig.model;
|
|
34419
34214
|
}
|
|
34420
34215
|
if (this.pendingOverrides.turnConfig.effort) {
|
|
@@ -34429,19 +34224,22 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34429
34224
|
const config2 = configEntries.length > 0 ? Object.fromEntries(configEntries) : void 0;
|
|
34430
34225
|
return {
|
|
34431
34226
|
cwd,
|
|
34227
|
+
model: this.currentModelSelection.providerModelId,
|
|
34228
|
+
serviceTier: this.currentModelSelection.serviceTier,
|
|
34432
34229
|
approvalPolicy,
|
|
34433
34230
|
sandbox,
|
|
34434
34231
|
developerInstructions: void 0,
|
|
34435
34232
|
config: config2
|
|
34436
34233
|
};
|
|
34437
34234
|
}
|
|
34438
|
-
buildCodexThreadDefaultsForResume(cwd,
|
|
34235
|
+
buildCodexThreadDefaultsForResume(cwd, modelSelection, systemPrompt, threadConfig) {
|
|
34439
34236
|
const { approvalPolicy, sandbox } = threadConfig;
|
|
34440
34237
|
const configEntries = Object.entries(threadConfig).filter(([key]) => !CODEX_THREAD_POLICY_CONFIG_KEYS.has(key));
|
|
34441
34238
|
const config2 = configEntries.length > 0 ? Object.fromEntries(configEntries) : void 0;
|
|
34442
34239
|
return {
|
|
34443
34240
|
cwd,
|
|
34444
|
-
...
|
|
34241
|
+
...modelSelection.providerModelId ? { model: modelSelection.providerModelId } : {},
|
|
34242
|
+
...modelSelection.serviceTier ? { serviceTier: modelSelection.serviceTier } : {},
|
|
34445
34243
|
approvalPolicy,
|
|
34446
34244
|
sandbox,
|
|
34447
34245
|
developerInstructions: systemPrompt ?? void 0,
|
|
@@ -34458,16 +34256,6 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34458
34256
|
return { approvalPolicy: "on-request", sandbox: "read-only" };
|
|
34459
34257
|
}
|
|
34460
34258
|
}
|
|
34461
|
-
resolveAcpMode(modeId) {
|
|
34462
|
-
switch (modeId) {
|
|
34463
|
-
case "autoEdit":
|
|
34464
|
-
return "agent";
|
|
34465
|
-
case "yolo":
|
|
34466
|
-
return "agent-full-access";
|
|
34467
|
-
default:
|
|
34468
|
-
return "read-only";
|
|
34469
|
-
}
|
|
34470
|
-
}
|
|
34471
34259
|
buildStartupConfigArgs(overrides, servers, modeMapping) {
|
|
34472
34260
|
const configArgs = [
|
|
34473
34261
|
...modeMapping ? [
|
|
@@ -34497,6 +34285,10 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34497
34285
|
return;
|
|
34498
34286
|
}
|
|
34499
34287
|
try {
|
|
34288
|
+
if (this.archiveSessionOnDisconnect && this.sessionId) {
|
|
34289
|
+
await this.connection.endSession().catch(() => {
|
|
34290
|
+
});
|
|
34291
|
+
}
|
|
34500
34292
|
await this.connection.disconnect();
|
|
34501
34293
|
} catch {
|
|
34502
34294
|
}
|
|
@@ -34504,65 +34296,17 @@ var UnifiedCodexAgentClient = class extends EventEmitter {
|
|
|
34504
34296
|
this.connection = null;
|
|
34505
34297
|
this.clearSessionState();
|
|
34506
34298
|
}
|
|
34507
|
-
|
|
34508
|
-
if (
|
|
34509
|
-
return
|
|
34510
|
-
"[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."
|
|
34511
|
-
);
|
|
34512
|
-
}
|
|
34513
|
-
if (error51 instanceof Error) {
|
|
34514
|
-
return error51;
|
|
34515
|
-
}
|
|
34516
|
-
if (typeof error51 === "object" && error51 !== null) {
|
|
34517
|
-
const obj = error51;
|
|
34518
|
-
if (typeof obj.message === "string") {
|
|
34519
|
-
const code = typeof obj.code === "number" ? ` (code: ${obj.code})` : "";
|
|
34520
|
-
const data = obj.data ? ` \u2014 ${JSON.stringify(obj.data)}` : "";
|
|
34521
|
-
return new Error(`${obj.message}${code}${data}`);
|
|
34522
|
-
}
|
|
34523
|
-
return new Error(JSON.stringify(error51));
|
|
34524
|
-
}
|
|
34525
|
-
return new Error(String(error51));
|
|
34526
|
-
}
|
|
34527
|
-
isAuthenticationError(error51, recentLogs) {
|
|
34528
|
-
const authPatterns = [
|
|
34529
|
-
/auth_required/i,
|
|
34530
|
-
/authentication required/i,
|
|
34531
|
-
/not authenticated/i,
|
|
34532
|
-
/please login/i,
|
|
34533
|
-
/please log in/i,
|
|
34534
|
-
/sign in/i,
|
|
34535
|
-
/reauth/i,
|
|
34536
|
-
/unauthorized/i,
|
|
34537
|
-
/invalid api key/i
|
|
34538
|
-
];
|
|
34539
|
-
if (this.matchAnyPattern(this.extractErrorText(error51), authPatterns)) {
|
|
34540
|
-
return true;
|
|
34541
|
-
}
|
|
34542
|
-
return recentLogs.some((log) => this.matchAnyPattern(log, authPatterns));
|
|
34543
|
-
}
|
|
34544
|
-
extractErrorText(error51) {
|
|
34545
|
-
if (error51 instanceof Error) {
|
|
34546
|
-
const code = error51.code;
|
|
34547
|
-
if (code === -32e3) {
|
|
34548
|
-
return `auth_required ${error51.message}`;
|
|
34549
|
-
}
|
|
34550
|
-
return error51.message;
|
|
34551
|
-
}
|
|
34552
|
-
if (typeof error51 === "string") {
|
|
34553
|
-
return error51;
|
|
34299
|
+
resolveModelSelection(modelId) {
|
|
34300
|
+
if (!modelId) {
|
|
34301
|
+
return {};
|
|
34554
34302
|
}
|
|
34555
|
-
|
|
34556
|
-
|
|
34557
|
-
|
|
34558
|
-
|
|
34303
|
+
const model = getProviderModels("codex").models.find((entry) => entry.modelId === modelId);
|
|
34304
|
+
return {
|
|
34305
|
+
providerModelId: model?.providerModelId ?? modelId,
|
|
34306
|
+
serviceTier: model?.serviceTier
|
|
34307
|
+
};
|
|
34559
34308
|
}
|
|
34560
34309
|
};
|
|
34561
|
-
function shouldUseCodexAcp(options) {
|
|
34562
|
-
const value = options.env?.CODEX_USE_ACP ?? process.env.CODEX_USE_ACP;
|
|
34563
|
-
const normalized = value?.trim().toLowerCase();
|
|
34564
|
-
return normalized !== void 0 && normalized !== "false" && normalized !== "0";
|
|
34565
|
-
}
|
|
34566
34310
|
var UnifiedCursorAgentClient = class extends EventEmitter {
|
|
34567
34311
|
connection = null;
|
|
34568
34312
|
sessionId = null;
|
|
@@ -38079,9 +37823,243 @@ function stripIpv6Brackets2(host) {
|
|
|
38079
37823
|
|
|
38080
37824
|
// core/host/operations/types.ts
|
|
38081
37825
|
var MAX_GROUP_NAME_LENGTH = 64;
|
|
37826
|
+
var DELETION_GRACE_MS = 8e3;
|
|
38082
37827
|
|
|
38083
|
-
// core/host/
|
|
38084
|
-
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;
|
|
38085
38063
|
var STATE_LOCK_DIR_NAME = "state.lock";
|
|
38086
38064
|
var STATE_LOCK_OWNER_FILE_NAME = "owner.json";
|
|
38087
38065
|
var STATE_TEMP_PREFIX = ".state.";
|
|
@@ -38128,25 +38106,37 @@ function sanitizeDurableConsoleState(value) {
|
|
|
38128
38106
|
version: STATE_VERSION,
|
|
38129
38107
|
theaters: readTheaterRegistrations(upgraded.theaters),
|
|
38130
38108
|
operations: readOperations(upgraded.operations),
|
|
38131
|
-
groups: readOperationGroups(upgraded.groups)
|
|
38109
|
+
groups: readOperationGroups(upgraded.groups),
|
|
38110
|
+
deletionTombstones: readDeletionTombstones(upgraded.deletionTombstones)
|
|
38132
38111
|
};
|
|
38133
38112
|
}
|
|
38134
38113
|
function emptyDurableConsoleState() {
|
|
38135
|
-
return { version: STATE_VERSION, theaters: [], operations: [], groups: [] };
|
|
38114
|
+
return { version: STATE_VERSION, theaters: [], operations: [], groups: [], deletionTombstones: [] };
|
|
38136
38115
|
}
|
|
38137
38116
|
function migrateToCurrentVersion(value) {
|
|
38138
|
-
|
|
38139
|
-
|
|
38117
|
+
let current = value;
|
|
38118
|
+
if (current.version === 1) current = migrateV1ToV2(current);
|
|
38119
|
+
if (current.version === 2) current = migrateV2ToV3(current);
|
|
38120
|
+
return current;
|
|
38140
38121
|
}
|
|
38141
38122
|
function migrateV1ToV2(v1) {
|
|
38142
38123
|
const operations = Array.isArray(v1.operations) ? v1.operations.map(migrateV1Operation) : [];
|
|
38143
38124
|
return {
|
|
38144
|
-
version:
|
|
38125
|
+
version: 2,
|
|
38145
38126
|
theaters: v1.theaters ?? [],
|
|
38146
38127
|
operations,
|
|
38147
38128
|
groups: []
|
|
38148
38129
|
};
|
|
38149
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
|
+
}
|
|
38150
38140
|
function migrateV1Operation(value) {
|
|
38151
38141
|
if (!isRecord5(value)) return null;
|
|
38152
38142
|
const sessionId = readNonEmptyString(value.sessionId);
|
|
@@ -38310,6 +38300,37 @@ function sanitizeOperationGroup(value) {
|
|
|
38310
38300
|
if (!VALID_GROUP_COLOR_KEYS.has(color)) return null;
|
|
38311
38301
|
return { id, theaterId, name: rawName, color, order, createdAt };
|
|
38312
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
|
+
}
|
|
38313
38334
|
|
|
38314
38335
|
// core/host/operations/sanitize.ts
|
|
38315
38336
|
var FIXED_SENSITIVE_OPERATION_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -38325,11 +38346,20 @@ var FIXED_SENSITIVE_OPERATION_FIELDS = /* @__PURE__ */ new Set([
|
|
|
38325
38346
|
]);
|
|
38326
38347
|
function createSanitizedOpDto(node, options = {}) {
|
|
38327
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;
|
|
38328
38352
|
return {
|
|
38329
38353
|
...node,
|
|
38330
|
-
payload
|
|
38354
|
+
payload
|
|
38331
38355
|
};
|
|
38332
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
|
+
}
|
|
38333
38363
|
function sanitizeRecord(value, sensitiveFields) {
|
|
38334
38364
|
const output = {};
|
|
38335
38365
|
for (const [key, item] of Object.entries(value)) {
|
|
@@ -38411,6 +38441,10 @@ async function handleCollection(req, res, deps) {
|
|
|
38411
38441
|
deps.writeJson(res, 400, { error: "invalid_operation_accent" });
|
|
38412
38442
|
return;
|
|
38413
38443
|
}
|
|
38444
|
+
if (typeof body2.id === "string" && deps.isPendingDeletion?.(body2.id)) {
|
|
38445
|
+
deps.writeJson(res, 409, { error: "pending_deletion" });
|
|
38446
|
+
return;
|
|
38447
|
+
}
|
|
38414
38448
|
try {
|
|
38415
38449
|
const node = deps.store.create({
|
|
38416
38450
|
id: typeof body2.id === "string" ? body2.id : void 0,
|
|
@@ -38443,8 +38477,8 @@ async function handleItem(req, res, id, deps) {
|
|
|
38443
38477
|
return;
|
|
38444
38478
|
}
|
|
38445
38479
|
if (req.method === "DELETE") {
|
|
38446
|
-
const
|
|
38447
|
-
deps.writeJson(res,
|
|
38480
|
+
const deletion = deps.deleteOperation(id);
|
|
38481
|
+
deps.writeJson(res, 200, { ok: true, deletion });
|
|
38448
38482
|
return;
|
|
38449
38483
|
}
|
|
38450
38484
|
const body2 = await deps.readJsonBody(req);
|
|
@@ -39035,6 +39069,10 @@ function createPlansRouter(deps) {
|
|
|
39035
39069
|
await handlePlansRead(req, res, deps);
|
|
39036
39070
|
return true;
|
|
39037
39071
|
}
|
|
39072
|
+
if (pathname === "/api/v1/plans/search") {
|
|
39073
|
+
await handlePlansSearch(req, res, deps);
|
|
39074
|
+
return true;
|
|
39075
|
+
}
|
|
39038
39076
|
if (pathname === "/api/v1/plans/events") {
|
|
39039
39077
|
await handlePlansEvents(req, res, deps);
|
|
39040
39078
|
return true;
|
|
@@ -39042,6 +39080,38 @@ function createPlansRouter(deps) {
|
|
|
39042
39080
|
return false;
|
|
39043
39081
|
};
|
|
39044
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
|
+
}
|
|
39045
39115
|
async function handlePlansEvents(req, res, deps) {
|
|
39046
39116
|
if (req.method !== "GET") {
|
|
39047
39117
|
deps.writeJson(res, 405, { error: "Method not allowed" });
|
|
@@ -40857,7 +40927,6 @@ var SERVER_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
|
40857
40927
|
var MAX_BODY_BYTES = 1024 * 1024;
|
|
40858
40928
|
var UPDATE_APPLY_FORBIDDEN_BODY_KEYS = /* @__PURE__ */ new Set(["channel", "package", "packageName", "packageVersion", "packages", "targetVersion", "version"]);
|
|
40859
40929
|
var OPERATION_RENAMED_EVENT_CHANNEL = "operation:renamed";
|
|
40860
|
-
var OPERATION_DELETED_EVENT_CHANNEL = "operation:deleted";
|
|
40861
40930
|
var PAIRING_IDENTITY_PATH = "/api/v1/pairing-identity";
|
|
40862
40931
|
var PAIRING_IDENTITY = { product: "fleet-console", schemaVersion: 1, pairingProtocolVersion: 1 };
|
|
40863
40932
|
var SERVER_API_CATALOG = [
|
|
@@ -40917,6 +40986,13 @@ var SERVER_API_CATALOG = [
|
|
|
40917
40986
|
category: "Observer",
|
|
40918
40987
|
gate: "origin-write"
|
|
40919
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
|
+
},
|
|
40920
40996
|
{
|
|
40921
40997
|
method: "POST",
|
|
40922
40998
|
path: "/api/v1/theaters/:theaterId/codex-workspace",
|
|
@@ -41044,16 +41120,29 @@ function createConsoleServer(deps = {}) {
|
|
|
41044
41120
|
function publishPluginEvent(channel2, payload) {
|
|
41045
41121
|
for (const listener of pluginEventListeners.get(channel2) ?? []) listener(payload);
|
|
41046
41122
|
}
|
|
41047
|
-
|
|
41048
|
-
|
|
41049
|
-
|
|
41050
|
-
|
|
41051
|
-
publishPluginEvent
|
|
41052
|
-
|
|
41053
|
-
|
|
41054
|
-
|
|
41055
|
-
|
|
41056
|
-
|
|
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;
|
|
41057
41146
|
}
|
|
41058
41147
|
let desktopFullscreen = false;
|
|
41059
41148
|
let unsubscribeUpdateCheckChanges = updateCheck.onChange?.(() => {
|
|
@@ -41064,6 +41153,7 @@ function createConsoleServer(deps = {}) {
|
|
|
41064
41153
|
list: () => operations.list(),
|
|
41065
41154
|
get: (id) => operations.get(id),
|
|
41066
41155
|
create: (input) => {
|
|
41156
|
+
if (input.id && deletionCoordinator.hasPendingOperation(input.id)) throw new Error("pending_deletion");
|
|
41067
41157
|
const operation = operations.create(input);
|
|
41068
41158
|
persistDurableState();
|
|
41069
41159
|
return operation;
|
|
@@ -41079,7 +41169,7 @@ function createConsoleServer(deps = {}) {
|
|
|
41079
41169
|
}
|
|
41080
41170
|
return operation;
|
|
41081
41171
|
},
|
|
41082
|
-
delete:
|
|
41172
|
+
delete: deleteOperationForPlugin,
|
|
41083
41173
|
registerOperationType: (type) => {
|
|
41084
41174
|
pluginOperationTypes.add(type);
|
|
41085
41175
|
return () => {
|
|
@@ -41293,7 +41383,8 @@ function createConsoleServer(deps = {}) {
|
|
|
41293
41383
|
readJsonBody,
|
|
41294
41384
|
writeJson,
|
|
41295
41385
|
persist: persistDurableState,
|
|
41296
|
-
deleteOperation,
|
|
41386
|
+
deleteOperation: (operationId) => deletionCoordinator.deleteOperation(operationId),
|
|
41387
|
+
isPendingDeletion: (operationId) => deletionCoordinator.hasPendingOperation(operationId),
|
|
41297
41388
|
getPluginSensitiveFields: (pluginId) => [
|
|
41298
41389
|
...pluginHost.sensitiveFieldsByPluginId.get(pluginId) ?? [],
|
|
41299
41390
|
...pluginPayloadSanitizers.get(pluginId) ?? []
|
|
@@ -41383,6 +41474,11 @@ function createConsoleServer(deps = {}) {
|
|
|
41383
41474
|
runAsyncBooleanHandler(plansRouter({ req, res, pathname }), res, () => false);
|
|
41384
41475
|
return;
|
|
41385
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
|
+
}
|
|
41386
41482
|
const theaterItemMatch = pathname.match(/^\/api\/v1\/theaters\/([^/]+)$/);
|
|
41387
41483
|
if (theaterItemMatch) {
|
|
41388
41484
|
runAsyncHandler(handleObserverTheaterItem(req, res, decodeURIComponent(theaterItemMatch[1] ?? "")), res);
|
|
@@ -41530,6 +41626,11 @@ function createConsoleServer(deps = {}) {
|
|
|
41530
41626
|
writeJson(res, 400, { error: "invalid_folder_grant" });
|
|
41531
41627
|
return;
|
|
41532
41628
|
}
|
|
41629
|
+
const canonicalCwd = canonicalizeTheaterPathSync(cwd);
|
|
41630
|
+
if (deletionCoordinator.hasPendingTheater(workspaceHash(canonicalCwd))) {
|
|
41631
|
+
writeJson(res, 409, { error: "pending_deletion" });
|
|
41632
|
+
return;
|
|
41633
|
+
}
|
|
41533
41634
|
const theater = await theaters.register(cwd);
|
|
41534
41635
|
await codex.registerWorkspace(theater.realpath, void 0, theater.id);
|
|
41535
41636
|
persistDurableState();
|
|
@@ -41559,12 +41660,27 @@ function createConsoleServer(deps = {}) {
|
|
|
41559
41660
|
writeJson(res, 200, toTheaterInfo(theater, true));
|
|
41560
41661
|
return;
|
|
41561
41662
|
}
|
|
41562
|
-
|
|
41563
|
-
|
|
41564
|
-
|
|
41565
|
-
|
|
41566
|
-
|
|
41567
|
-
|
|
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
|
+
}
|
|
41568
41684
|
}
|
|
41569
41685
|
function handleStatus(req, res) {
|
|
41570
41686
|
const theaterId = readUrl(req).searchParams.get("theaterId");
|
|
@@ -41781,6 +41897,12 @@ function createConsoleServer(deps = {}) {
|
|
|
41781
41897
|
operations.replace([]);
|
|
41782
41898
|
operations.replaceGroups([]);
|
|
41783
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
|
+
}
|
|
41784
41906
|
await restoreCodexWorkspaces();
|
|
41785
41907
|
}
|
|
41786
41908
|
async function restoreCodexWorkspaces() {
|
|
@@ -41822,16 +41944,20 @@ function createConsoleServer(deps = {}) {
|
|
|
41822
41944
|
}
|
|
41823
41945
|
function persistDurableState() {
|
|
41824
41946
|
try {
|
|
41825
|
-
|
|
41826
|
-
version: 2,
|
|
41827
|
-
theaters: theaters.list(),
|
|
41828
|
-
operations: operations.list(),
|
|
41829
|
-
groups: operations.listAllGroups()
|
|
41830
|
-
});
|
|
41947
|
+
saveDurableState(deletionCoordinator.list());
|
|
41831
41948
|
} catch (error51) {
|
|
41832
41949
|
console.warn(`[fleet-console] Durable state save failed: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
41833
41950
|
}
|
|
41834
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
|
+
}
|
|
41835
41961
|
async function stopServer() {
|
|
41836
41962
|
const current = server;
|
|
41837
41963
|
const currentLoopback = loopbackServer;
|
|
@@ -41841,6 +41967,7 @@ function createConsoleServer(deps = {}) {
|
|
|
41841
41967
|
lockHandle = null;
|
|
41842
41968
|
activeLockFile = null;
|
|
41843
41969
|
activeEndpoint = null;
|
|
41970
|
+
deletionCoordinator.dispose();
|
|
41844
41971
|
try {
|
|
41845
41972
|
await Promise.all([
|
|
41846
41973
|
closeHttpServer(current),
|