oh-my-opencode 4.16.2 → 4.16.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/pre-publish-review/SKILL.md +3 -0
- package/README.md +2 -2
- package/dist/agents/hephaestus/agent.d.ts +1 -1
- package/dist/agents/hephaestus/gpt-5-6.d.ts +2 -0
- package/dist/agents/momus-gpt-5-6.d.ts +1 -0
- package/dist/agents/types.d.ts +2 -0
- package/dist/cli/index.js +800 -536
- package/dist/cli-node/index.js +800 -536
- package/dist/features/background-agent/error-classifier.d.ts +5 -0
- package/dist/features/builtin-commands/templates/refactor-sections/intro-and-analysis.d.ts +1 -1
- package/dist/features/builtin-commands/templates/remove-ai-slops.d.ts +1 -1
- package/dist/index.js +416 -37
- package/dist/shared/live-server-route.d.ts +1 -1
- package/dist/skills/review-work/SKILL.md +1 -1
- package/dist/skills/ulw-plan/references/full-workflow.md +1 -1
- package/dist/skills/ulw-research/SKILL.md +2 -2
- package/dist/skills/visual-qa/SKILL.md +1 -1
- package/dist/tui.js +125 -13
- package/package.json +13 -13
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +398 -246
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.6.md +93 -0
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +43 -24
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/src/codex-hook.ts +2 -1
- package/packages/omo-codex/plugin/components/rules/src/dynamic-target-fingerprints.ts +15 -6
- package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +7 -2
- package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +2 -2
- package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +32 -0
- package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +106 -0
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/AGENTS.md +12 -9
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/SKILL.md +136 -76
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-guide.mjs +94 -23
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-state.mjs +94 -14
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team-transport.mjs +55 -0
- package/packages/omo-codex/plugin/components/teammode/skills/teammode/scripts/team.mjs +72 -18
- package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +23 -0
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/explorer.toml +24 -41
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-clone-fidelity-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-code-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-executor.toml +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-gate-reviewer.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/lazycodex-qa-executor.toml +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/agents/librarian.toml +21 -49
- package/packages/omo-codex/plugin/components/ultrawork/agents/metis.toml +17 -29
- package/packages/omo-codex/plugin/components/ultrawork/agents/momus.toml +20 -50
- package/packages/omo-codex/plugin/components/ultrawork/agents/plan.toml +18 -39
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +13 -13
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +9 -2
- package/packages/omo-codex/plugin/scripts/entry-guard.mjs +26 -0
- package/packages/omo-codex/plugin/scripts/materialize-shared-upstreams.mjs +3 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/multi-agent-v2-guard.mjs +39 -4
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/subagent-limit-guard.mjs +24 -4
- package/packages/omo-codex/plugin/scripts/migrate-codex-config.mjs +3 -3
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +2 -2
- package/packages/omo-codex/plugin/scripts/sync-hook-status-messages.mjs +2 -2
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +6 -4
- package/packages/omo-codex/plugin/scripts/sync-version.mjs +4 -2
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/teammode/SKILL.md +136 -76
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-guide.mjs +94 -23
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-state.mjs +94 -14
- package/packages/omo-codex/plugin/skills/teammode/scripts/team-transport.mjs +55 -0
- package/packages/omo-codex/plugin/skills/teammode/scripts/team.mjs +72 -18
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +2 -2
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +47 -1
- package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +4 -2
- package/packages/omo-codex/plugin/test/auto-update-restart-notice.test.mjs +33 -0
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +146 -9
- package/packages/omo-codex/plugin/test/multi-agent-v2-regression.test.mjs +71 -0
- package/packages/omo-codex/plugin/test/subagent-limit-migration.test.mjs +32 -0
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +9 -2
- package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +345 -0
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +436 -284
- package/packages/omo-codex/scripts/install-generated-bundle.test.mjs +111 -1
- package/packages/shared-skills/skills/review-work/SKILL.md +1 -1
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +1 -1
- package/packages/shared-skills/skills/ulw-research/SKILL.md +2 -2
- package/packages/shared-skills/skills/visual-qa/SKILL.md +1 -1
- /package/packages/omo-codex/plugin/components/rules/bundled-rules/{hephaestus.md → hephaestus/gpt-5.5.md} +0 -0
|
@@ -440,7 +440,7 @@ async function readOptionalFile(path) {
|
|
|
440
440
|
// components/bootstrap/src/worker.ts
|
|
441
441
|
import { appendFile as appendFile2, mkdir as mkdir8, readFile as readFile13 } from "node:fs/promises";
|
|
442
442
|
import { homedir as homedir4 } from "node:os";
|
|
443
|
-
import { dirname as
|
|
443
|
+
import { dirname as dirname9, join as join22, resolve as resolve7 } from "node:path";
|
|
444
444
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
445
445
|
|
|
446
446
|
// components/bootstrap/src/provision.ts
|
|
@@ -864,211 +864,129 @@ async function defaultVersionProbe2(binaryPath) {
|
|
|
864
864
|
}
|
|
865
865
|
|
|
866
866
|
// components/bootstrap/src/setup.ts
|
|
867
|
-
import { copyFile as copyFile2, mkdir as mkdir7, readdir as
|
|
868
|
-
import { join as
|
|
867
|
+
import { copyFile as copyFile2, mkdir as mkdir7, readdir as readdir5, rm as rm10, stat as stat5 } from "node:fs/promises";
|
|
868
|
+
import { join as join21 } from "node:path";
|
|
869
869
|
|
|
870
870
|
// ../src/install/link-cached-plugin-agents.ts
|
|
871
|
-
import { copyFile, lstat as
|
|
872
|
-
import { basename as basename3, join as
|
|
871
|
+
import { copyFile, lstat as lstat3, mkdir as mkdir4, readdir as readdir2, rm as rm6, writeFile as writeFile4 } from "node:fs/promises";
|
|
872
|
+
import { basename as basename3, join as join10 } from "node:path";
|
|
873
873
|
|
|
874
|
-
// ../src/install/
|
|
875
|
-
import { lstat, readFile as readFile4,
|
|
874
|
+
// ../src/install/preserved-agent-settings.ts
|
|
875
|
+
import { lstat, readFile as readFile4, readdir, writeFile as writeFile3 } from "node:fs/promises";
|
|
876
876
|
import { join as join8 } from "node:path";
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
]
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
}
|
|
907
|
-
async function readTextIfExists(path) {
|
|
908
|
-
try {
|
|
909
|
-
return await readFile4(path, "utf8");
|
|
910
|
-
} catch (error) {
|
|
911
|
-
if (nodeErrorCode(error) === "ENOENT")
|
|
912
|
-
return null;
|
|
913
|
-
throw error;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
async function exists(path) {
|
|
917
|
-
try {
|
|
918
|
-
await lstat(path);
|
|
919
|
-
return true;
|
|
920
|
-
} catch (error) {
|
|
921
|
-
if (nodeErrorCode(error) !== "ENOENT")
|
|
922
|
-
throw error;
|
|
923
|
-
return false;
|
|
877
|
+
|
|
878
|
+
// ../src/install/managed-agent-reasoning-defaults.ts
|
|
879
|
+
var MANAGED_REASONING_DEFAULT_UPGRADES = new Map([
|
|
880
|
+
[
|
|
881
|
+
"explorer",
|
|
882
|
+
{
|
|
883
|
+
previous: { model: "gpt-5.4-mini", effort: "low" },
|
|
884
|
+
current: { model: "gpt-5.6-terra", effort: "medium" }
|
|
885
|
+
}
|
|
886
|
+
],
|
|
887
|
+
[
|
|
888
|
+
"librarian",
|
|
889
|
+
{
|
|
890
|
+
previous: { model: "gpt-5.4-mini", effort: "low" },
|
|
891
|
+
current: { model: "gpt-5.6-terra", effort: "medium" }
|
|
892
|
+
}
|
|
893
|
+
],
|
|
894
|
+
[
|
|
895
|
+
"momus",
|
|
896
|
+
{
|
|
897
|
+
previous: { model: "gpt-5.5", effort: "xhigh" },
|
|
898
|
+
current: { model: "gpt-5.6-sol", effort: "ultra" }
|
|
899
|
+
}
|
|
900
|
+
]
|
|
901
|
+
]);
|
|
902
|
+
function resolveManagedAgentReasoning(input) {
|
|
903
|
+
const upgrade = MANAGED_REASONING_DEFAULT_UPGRADES.get(input.agentName);
|
|
904
|
+
if (upgrade !== undefined && input.preserved.model === upgrade.previous.model && input.preserved.effort === upgrade.previous.effort && input.bundledModel === upgrade.current.model && input.bundledEffort === upgrade.current.effort) {
|
|
905
|
+
return upgrade.current.effort;
|
|
924
906
|
}
|
|
925
|
-
|
|
926
|
-
function nodeErrorCode(error) {
|
|
927
|
-
if (!(error instanceof Error) || !("code" in error))
|
|
928
|
-
return null;
|
|
929
|
-
return typeof error.code === "string" ? error.code : null;
|
|
907
|
+
return input.preserved.effort;
|
|
930
908
|
}
|
|
931
909
|
|
|
932
|
-
// ../src/install/
|
|
933
|
-
var MANIFEST_FILE = ".installed-agents.json";
|
|
910
|
+
// ../src/install/preserved-agent-settings.ts
|
|
934
911
|
async function capturePreservedAgentReasoning(input) {
|
|
935
|
-
const agentsDir =
|
|
936
|
-
if (!await
|
|
912
|
+
const agentsDir = join8(input.codexHome, "agents");
|
|
913
|
+
if (!await exists(agentsDir))
|
|
937
914
|
return new Map;
|
|
938
915
|
const preserved = new Map;
|
|
939
916
|
const agentEntries = await readdir(agentsDir, { withFileTypes: true });
|
|
940
917
|
for (const entry of agentEntries) {
|
|
941
918
|
if (!entry.name.endsWith(".toml"))
|
|
942
919
|
continue;
|
|
943
|
-
const content = await
|
|
920
|
+
const content = await readTextIfExists(join8(agentsDir, entry.name));
|
|
944
921
|
if (content === null)
|
|
945
922
|
continue;
|
|
946
923
|
const effort = extractReasoningEffort(content);
|
|
947
|
-
if (effort !== null)
|
|
948
|
-
preserved.set(agentNameFromToml(entry.name),
|
|
924
|
+
if (effort !== null) {
|
|
925
|
+
preserved.set(agentNameFromToml(entry.name), {
|
|
926
|
+
model: extractModel(content),
|
|
927
|
+
effort
|
|
928
|
+
});
|
|
929
|
+
}
|
|
949
930
|
}
|
|
950
931
|
return preserved;
|
|
951
932
|
}
|
|
952
933
|
async function capturePreservedAgentServiceTier(input) {
|
|
953
|
-
const agentsDir =
|
|
954
|
-
if (!await
|
|
934
|
+
const agentsDir = join8(input.codexHome, "agents");
|
|
935
|
+
if (!await exists(agentsDir))
|
|
955
936
|
return new Map;
|
|
956
937
|
const preserved = new Map;
|
|
957
938
|
const agentEntries = await readdir(agentsDir, { withFileTypes: true });
|
|
958
939
|
for (const entry of agentEntries) {
|
|
959
940
|
if (!entry.name.endsWith(".toml"))
|
|
960
941
|
continue;
|
|
961
|
-
const content = await
|
|
942
|
+
const content = await readTextIfExists(join8(agentsDir, entry.name));
|
|
962
943
|
if (content === null)
|
|
963
944
|
continue;
|
|
964
945
|
preserved.set(agentNameFromToml(entry.name), extractServiceTier(content));
|
|
965
946
|
}
|
|
966
947
|
return preserved;
|
|
967
948
|
}
|
|
968
|
-
async function
|
|
969
|
-
|
|
970
|
-
await purgeRetiredManagedAgentFiles({ codexHome: input.codexHome });
|
|
971
|
-
if (bundledAgents.length === 0) {
|
|
972
|
-
await writeManifest(input.pluginRoot, []);
|
|
973
|
-
return [];
|
|
974
|
-
}
|
|
975
|
-
const agentsDir = join9(input.codexHome, "agents");
|
|
976
|
-
await mkdir4(agentsDir, { recursive: true });
|
|
977
|
-
const linked = [];
|
|
978
|
-
for (const agentPath of bundledAgents) {
|
|
979
|
-
const agentFileName = basename3(agentPath);
|
|
980
|
-
const agentName = agentNameFromToml(agentFileName);
|
|
981
|
-
const linkPath = join9(agentsDir, agentFileName);
|
|
982
|
-
await replaceWithCopy(linkPath, agentPath);
|
|
983
|
-
await restorePreservedReasoning({
|
|
984
|
-
agentName,
|
|
985
|
-
linkPath,
|
|
986
|
-
target: agentPath,
|
|
987
|
-
value: input.preservedReasoning?.get(agentName)
|
|
988
|
-
});
|
|
989
|
-
await restorePreservedServiceTier({
|
|
990
|
-
linkPath,
|
|
991
|
-
preserved: input.preservedServiceTier?.has(agentName) ?? false,
|
|
992
|
-
value: input.preservedServiceTier?.get(agentName) ?? null
|
|
993
|
-
});
|
|
994
|
-
linked.push({ name: agentFileName, path: linkPath, target: agentPath });
|
|
995
|
-
}
|
|
996
|
-
await writeManifest(input.pluginRoot, linked.map((entry) => entry.path));
|
|
997
|
-
return linked;
|
|
998
|
-
}
|
|
999
|
-
async function restorePreservedServiceTier(input) {
|
|
1000
|
-
if (!input.preserved)
|
|
949
|
+
async function restorePreservedReasoning(input) {
|
|
950
|
+
if (input.value === undefined)
|
|
1001
951
|
return;
|
|
1002
|
-
const content = await
|
|
1003
|
-
|
|
952
|
+
const content = await readFile4(input.target, "utf8");
|
|
953
|
+
const bundledEffort = extractReasoningEffort(content);
|
|
954
|
+
const effort = resolveManagedAgentReasoning({
|
|
955
|
+
agentName: input.agentName,
|
|
956
|
+
bundledModel: extractModel(content),
|
|
957
|
+
bundledEffort,
|
|
958
|
+
preserved: input.value
|
|
959
|
+
});
|
|
960
|
+
if (bundledEffort === effort)
|
|
1004
961
|
return;
|
|
1005
|
-
const replacement =
|
|
962
|
+
const replacement = replaceTopLevelStringSetting(content, "model_reasoning_effort", effort, { insertIfMissing: false });
|
|
1006
963
|
if (!replacement.replaced)
|
|
1007
964
|
return;
|
|
1008
965
|
await writeFile3(input.linkPath, replacement.content);
|
|
1009
966
|
}
|
|
1010
|
-
async function
|
|
1011
|
-
|
|
1012
|
-
if (!await exists2(componentsRoot))
|
|
1013
|
-
return [];
|
|
1014
|
-
const componentEntries = await readdir(componentsRoot, { withFileTypes: true });
|
|
1015
|
-
const agents = [];
|
|
1016
|
-
for (const entry of componentEntries) {
|
|
1017
|
-
if (!entry.isDirectory())
|
|
1018
|
-
continue;
|
|
1019
|
-
const agentsRoot = join9(componentsRoot, entry.name, "agents");
|
|
1020
|
-
if (!await exists2(agentsRoot))
|
|
1021
|
-
continue;
|
|
1022
|
-
const agentEntries = await readdir(agentsRoot, { withFileTypes: true });
|
|
1023
|
-
for (const file of agentEntries) {
|
|
1024
|
-
if (!file.isFile() || !file.name.endsWith(".toml"))
|
|
1025
|
-
continue;
|
|
1026
|
-
agents.push(join9(agentsRoot, file.name));
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
agents.sort();
|
|
1030
|
-
return agents;
|
|
1031
|
-
}
|
|
1032
|
-
async function replaceWithCopy(linkPath, target) {
|
|
1033
|
-
await prepareReplacement(linkPath);
|
|
1034
|
-
await copyFile(target, linkPath);
|
|
1035
|
-
}
|
|
1036
|
-
async function prepareReplacement(linkPath) {
|
|
1037
|
-
if (!await exists2(linkPath))
|
|
1038
|
-
return;
|
|
1039
|
-
const entryStat = await lstat2(linkPath);
|
|
1040
|
-
if (entryStat.isDirectory() && !entryStat.isSymbolicLink()) {
|
|
1041
|
-
throw new Error(`${linkPath} already exists and is a directory; refusing to replace`);
|
|
1042
|
-
}
|
|
1043
|
-
await rm6(linkPath, { force: true });
|
|
1044
|
-
}
|
|
1045
|
-
async function writeManifest(pluginRoot, agentPaths) {
|
|
1046
|
-
const manifestPath = join9(pluginRoot, MANIFEST_FILE);
|
|
1047
|
-
const payload = { agents: [...agentPaths].sort() };
|
|
1048
|
-
await writeFile3(manifestPath, `${JSON.stringify(payload, null, "\t")}
|
|
1049
|
-
`);
|
|
1050
|
-
}
|
|
1051
|
-
async function restorePreservedReasoning(input) {
|
|
1052
|
-
if (input.value === undefined)
|
|
967
|
+
async function restorePreservedServiceTier(input) {
|
|
968
|
+
if (!input.preserved)
|
|
1053
969
|
return;
|
|
1054
|
-
const content = await
|
|
1055
|
-
|
|
1056
|
-
if (bundledEffort === input.value)
|
|
970
|
+
const content = await readFile4(input.linkPath, "utf8");
|
|
971
|
+
if (extractServiceTier(content) === input.value)
|
|
1057
972
|
return;
|
|
1058
|
-
const replacement =
|
|
973
|
+
const replacement = replaceTopLevelStringSetting(content, "service_tier", input.value, { insertIfMissing: true });
|
|
1059
974
|
if (!replacement.replaced)
|
|
1060
975
|
return;
|
|
1061
976
|
await writeFile3(input.linkPath, replacement.content);
|
|
1062
977
|
}
|
|
1063
|
-
async function
|
|
978
|
+
async function readTextIfExists(path) {
|
|
1064
979
|
try {
|
|
1065
|
-
return await
|
|
980
|
+
return await readFile4(path, "utf8");
|
|
1066
981
|
} catch (error) {
|
|
1067
|
-
if (
|
|
982
|
+
if (nodeErrorCode(error) === "ENOENT")
|
|
1068
983
|
return null;
|
|
1069
984
|
throw error;
|
|
1070
985
|
}
|
|
1071
986
|
}
|
|
987
|
+
function extractModel(content) {
|
|
988
|
+
return extractTopLevelStringSetting(content, "model");
|
|
989
|
+
}
|
|
1072
990
|
function extractReasoningEffort(content) {
|
|
1073
991
|
return extractTopLevelStringSetting(content, "model_reasoning_effort");
|
|
1074
992
|
}
|
|
@@ -1088,12 +1006,6 @@ function extractTopLevelStringSetting(content, key) {
|
|
|
1088
1006
|
}
|
|
1089
1007
|
return null;
|
|
1090
1008
|
}
|
|
1091
|
-
function replaceReasoningEffort(content, value) {
|
|
1092
|
-
return replaceTopLevelStringSetting(content, "model_reasoning_effort", value, { insertIfMissing: false });
|
|
1093
|
-
}
|
|
1094
|
-
function replaceServiceTier(content, value) {
|
|
1095
|
-
return replaceTopLevelStringSetting(content, "service_tier", value, { insertIfMissing: true });
|
|
1096
|
-
}
|
|
1097
1009
|
function replaceTopLevelStringSetting(content, key, value, options) {
|
|
1098
1010
|
const lines = content.split(/\n/);
|
|
1099
1011
|
for (let index = 0;index < lines.length; index += 1) {
|
|
@@ -1153,6 +1065,64 @@ function parseJsonString(value) {
|
|
|
1153
1065
|
return null;
|
|
1154
1066
|
}
|
|
1155
1067
|
}
|
|
1068
|
+
async function exists(path) {
|
|
1069
|
+
try {
|
|
1070
|
+
await lstat(path);
|
|
1071
|
+
return true;
|
|
1072
|
+
} catch (error) {
|
|
1073
|
+
if (nodeErrorCode(error) !== "ENOENT")
|
|
1074
|
+
throw error;
|
|
1075
|
+
return false;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
function nodeErrorCode(error) {
|
|
1079
|
+
if (!(error instanceof Error) || !("code" in error))
|
|
1080
|
+
return null;
|
|
1081
|
+
return typeof error.code === "string" ? error.code : null;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
// ../src/install/retired-managed-agent-purge.ts
|
|
1085
|
+
import { lstat as lstat2, readFile as readFile5, rm as rm5 } from "node:fs/promises";
|
|
1086
|
+
import { join as join9 } from "node:path";
|
|
1087
|
+
var RETIRED_MANAGED_AGENT_FILES = [
|
|
1088
|
+
{
|
|
1089
|
+
fileName: "codex-ultrawork-reviewer.toml",
|
|
1090
|
+
requiredMarkers: [
|
|
1091
|
+
'name = "codex-ultrawork-reviewer"',
|
|
1092
|
+
'description = "Strict ultrawork verification reviewer.',
|
|
1093
|
+
'developer_instructions = """You are the ultrawork verification reviewer.'
|
|
1094
|
+
]
|
|
1095
|
+
}
|
|
1096
|
+
];
|
|
1097
|
+
async function purgeRetiredManagedAgentFiles(input) {
|
|
1098
|
+
const agentsDir = join9(input.codexHome, "agents");
|
|
1099
|
+
if (!await exists2(agentsDir))
|
|
1100
|
+
return;
|
|
1101
|
+
for (const retiredAgent of RETIRED_MANAGED_AGENT_FILES) {
|
|
1102
|
+
const agentPath = join9(agentsDir, retiredAgent.fileName);
|
|
1103
|
+
if (!await exists2(agentPath))
|
|
1104
|
+
continue;
|
|
1105
|
+
const agentStat = await lstat2(agentPath);
|
|
1106
|
+
if (agentStat.isDirectory() && !agentStat.isSymbolicLink())
|
|
1107
|
+
continue;
|
|
1108
|
+
const content = await readTextIfExists2(agentPath);
|
|
1109
|
+
if (content === null || !hasRequiredMarkers(content, retiredAgent.requiredMarkers))
|
|
1110
|
+
continue;
|
|
1111
|
+
await rm5(agentPath, { force: true });
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
function hasRequiredMarkers(content, markers) {
|
|
1115
|
+
return markers.every((marker) => content.includes(marker));
|
|
1116
|
+
}
|
|
1117
|
+
async function readTextIfExists2(path) {
|
|
1118
|
+
try {
|
|
1119
|
+
return await readFile5(path, "utf8");
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
if (nodeErrorCode2(error) === "ENOENT")
|
|
1122
|
+
return null;
|
|
1123
|
+
throw error;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1156
1126
|
async function exists2(path) {
|
|
1157
1127
|
try {
|
|
1158
1128
|
await lstat2(path);
|
|
@@ -1169,9 +1139,102 @@ function nodeErrorCode2(error) {
|
|
|
1169
1139
|
return typeof error.code === "string" ? error.code : null;
|
|
1170
1140
|
}
|
|
1171
1141
|
|
|
1142
|
+
// ../src/install/link-cached-plugin-agents.ts
|
|
1143
|
+
var MANIFEST_FILE = ".installed-agents.json";
|
|
1144
|
+
async function linkCachedPluginAgents(input) {
|
|
1145
|
+
const bundledAgents = await discoverBundledAgents(input.pluginRoot);
|
|
1146
|
+
await purgeRetiredManagedAgentFiles({ codexHome: input.codexHome });
|
|
1147
|
+
if (bundledAgents.length === 0) {
|
|
1148
|
+
await writeManifest(input.pluginRoot, []);
|
|
1149
|
+
return [];
|
|
1150
|
+
}
|
|
1151
|
+
const agentsDir = join10(input.codexHome, "agents");
|
|
1152
|
+
await mkdir4(agentsDir, { recursive: true });
|
|
1153
|
+
const linked = [];
|
|
1154
|
+
for (const agentPath of bundledAgents) {
|
|
1155
|
+
const agentFileName = basename3(agentPath);
|
|
1156
|
+
const agentName = agentNameFromToml2(agentFileName);
|
|
1157
|
+
const linkPath = join10(agentsDir, agentFileName);
|
|
1158
|
+
await replaceWithCopy(linkPath, agentPath);
|
|
1159
|
+
await restorePreservedReasoning({
|
|
1160
|
+
agentName,
|
|
1161
|
+
linkPath,
|
|
1162
|
+
target: agentPath,
|
|
1163
|
+
value: input.preservedReasoning?.get(agentName)
|
|
1164
|
+
});
|
|
1165
|
+
await restorePreservedServiceTier({
|
|
1166
|
+
linkPath,
|
|
1167
|
+
preserved: input.preservedServiceTier?.has(agentName) ?? false,
|
|
1168
|
+
value: input.preservedServiceTier?.get(agentName) ?? null
|
|
1169
|
+
});
|
|
1170
|
+
linked.push({ name: agentFileName, path: linkPath, target: agentPath });
|
|
1171
|
+
}
|
|
1172
|
+
await writeManifest(input.pluginRoot, linked.map((entry) => entry.path));
|
|
1173
|
+
return linked;
|
|
1174
|
+
}
|
|
1175
|
+
async function discoverBundledAgents(pluginRoot) {
|
|
1176
|
+
const componentsRoot = join10(pluginRoot, "components");
|
|
1177
|
+
if (!await exists3(componentsRoot))
|
|
1178
|
+
return [];
|
|
1179
|
+
const componentEntries = await readdir2(componentsRoot, { withFileTypes: true });
|
|
1180
|
+
const agents = [];
|
|
1181
|
+
for (const entry of componentEntries) {
|
|
1182
|
+
if (!entry.isDirectory())
|
|
1183
|
+
continue;
|
|
1184
|
+
const agentsRoot = join10(componentsRoot, entry.name, "agents");
|
|
1185
|
+
if (!await exists3(agentsRoot))
|
|
1186
|
+
continue;
|
|
1187
|
+
const agentEntries = await readdir2(agentsRoot, { withFileTypes: true });
|
|
1188
|
+
for (const file of agentEntries) {
|
|
1189
|
+
if (!file.isFile() || !file.name.endsWith(".toml"))
|
|
1190
|
+
continue;
|
|
1191
|
+
agents.push(join10(agentsRoot, file.name));
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
agents.sort();
|
|
1195
|
+
return agents;
|
|
1196
|
+
}
|
|
1197
|
+
async function replaceWithCopy(linkPath, target) {
|
|
1198
|
+
await prepareReplacement(linkPath);
|
|
1199
|
+
await copyFile(target, linkPath);
|
|
1200
|
+
}
|
|
1201
|
+
async function prepareReplacement(linkPath) {
|
|
1202
|
+
if (!await exists3(linkPath))
|
|
1203
|
+
return;
|
|
1204
|
+
const entryStat = await lstat3(linkPath);
|
|
1205
|
+
if (entryStat.isDirectory() && !entryStat.isSymbolicLink()) {
|
|
1206
|
+
throw new Error(`${linkPath} already exists and is a directory; refusing to replace`);
|
|
1207
|
+
}
|
|
1208
|
+
await rm6(linkPath, { force: true });
|
|
1209
|
+
}
|
|
1210
|
+
async function writeManifest(pluginRoot, agentPaths) {
|
|
1211
|
+
const manifestPath = join10(pluginRoot, MANIFEST_FILE);
|
|
1212
|
+
const payload = { agents: [...agentPaths].sort() };
|
|
1213
|
+
await writeFile4(manifestPath, `${JSON.stringify(payload, null, "\t")}
|
|
1214
|
+
`);
|
|
1215
|
+
}
|
|
1216
|
+
function agentNameFromToml2(fileName) {
|
|
1217
|
+
return fileName.endsWith(".toml") ? fileName.slice(0, -".toml".length) : fileName;
|
|
1218
|
+
}
|
|
1219
|
+
async function exists3(path) {
|
|
1220
|
+
try {
|
|
1221
|
+
await lstat3(path);
|
|
1222
|
+
return true;
|
|
1223
|
+
} catch (error) {
|
|
1224
|
+
if (nodeErrorCode3(error) !== "ENOENT")
|
|
1225
|
+
throw error;
|
|
1226
|
+
return false;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
function nodeErrorCode3(error) {
|
|
1230
|
+
if (!(error instanceof Error) || !("code" in error))
|
|
1231
|
+
return null;
|
|
1232
|
+
return typeof error.code === "string" ? error.code : null;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1172
1235
|
// ../src/install/codex-cache-bins.ts
|
|
1173
|
-
import { chmod as chmod2, lstat as
|
|
1174
|
-
import { basename as basename4, isAbsolute as isAbsolute3, join as
|
|
1236
|
+
import { chmod as chmod2, lstat as lstat7, mkdir as mkdir5, readFile as readFile8, readdir as readdir4, readlink as readlink3, rm as rm9, stat as stat4, symlink, writeFile as writeFile5 } from "node:fs/promises";
|
|
1237
|
+
import { basename as basename4, isAbsolute as isAbsolute3, join as join14, relative as relative2, resolve as resolve4, sep } from "node:path";
|
|
1175
1238
|
|
|
1176
1239
|
// ../src/install/codex-cache-command-shim.ts
|
|
1177
1240
|
var COMMAND_SHIM_MARKER = ":: generated by oh-my-openagent Codex installer";
|
|
@@ -1215,14 +1278,14 @@ function windowsCommandShim(targetPath) {
|
|
|
1215
1278
|
}
|
|
1216
1279
|
|
|
1217
1280
|
// ../src/install/codex-cache-dangling-bins.ts
|
|
1218
|
-
import { lstat as
|
|
1219
|
-
import { dirname as dirname5, isAbsolute as isAbsolute2, join as
|
|
1281
|
+
import { lstat as lstat5, readFile as readFile6, readdir as readdir3, readlink, rm as rm7, stat as stat3 } from "node:fs/promises";
|
|
1282
|
+
import { dirname as dirname5, isAbsolute as isAbsolute2, join as join11, resolve as resolve3 } from "node:path";
|
|
1220
1283
|
|
|
1221
1284
|
// ../src/install/codex-cache-fs.ts
|
|
1222
|
-
import { lstat as
|
|
1285
|
+
import { lstat as lstat4 } from "node:fs/promises";
|
|
1223
1286
|
async function fileExistsStrict(path) {
|
|
1224
1287
|
try {
|
|
1225
|
-
await
|
|
1288
|
+
await lstat4(path);
|
|
1226
1289
|
return true;
|
|
1227
1290
|
} catch (error) {
|
|
1228
1291
|
if (isNodeErrorWithCode(error) && error.code === "ENOENT")
|
|
@@ -1239,12 +1302,12 @@ function isNodeErrorWithCode(error) {
|
|
|
1239
1302
|
|
|
1240
1303
|
// ../src/install/codex-cache-dangling-bins.ts
|
|
1241
1304
|
async function removeDanglingManagedComponentBins(binDir, platform, managedBinNames) {
|
|
1242
|
-
const entries = await
|
|
1305
|
+
const entries = await readdir3(binDir, { withFileTypes: true });
|
|
1243
1306
|
for (const entry of entries) {
|
|
1244
1307
|
const binName = managedBinNameForEntry(entry.name, platform);
|
|
1245
1308
|
if (binName === null || !managedBinNames.has(binName))
|
|
1246
1309
|
continue;
|
|
1247
|
-
const linkPath =
|
|
1310
|
+
const linkPath = join11(binDir, entry.name);
|
|
1248
1311
|
if (platform === "win32") {
|
|
1249
1312
|
await removeDanglingGeneratedCommandShim(linkPath);
|
|
1250
1313
|
continue;
|
|
@@ -1259,7 +1322,7 @@ function managedBinNameForEntry(name, platform) {
|
|
|
1259
1322
|
}
|
|
1260
1323
|
async function removeDanglingManagedSymlink(linkPath) {
|
|
1261
1324
|
try {
|
|
1262
|
-
const linkStat = await
|
|
1325
|
+
const linkStat = await lstat5(linkPath);
|
|
1263
1326
|
if (!linkStat.isSymbolicLink())
|
|
1264
1327
|
return;
|
|
1265
1328
|
const linkTarget = await readlink(linkPath);
|
|
@@ -1274,7 +1337,7 @@ async function removeDanglingManagedSymlink(linkPath) {
|
|
|
1274
1337
|
}
|
|
1275
1338
|
async function removeDanglingGeneratedCommandShim(linkPath) {
|
|
1276
1339
|
try {
|
|
1277
|
-
const linkStat = await
|
|
1340
|
+
const linkStat = await lstat5(linkPath);
|
|
1278
1341
|
if (!linkStat.isFile())
|
|
1279
1342
|
return;
|
|
1280
1343
|
const content = await readFile6(linkPath, "utf8");
|
|
@@ -1325,8 +1388,8 @@ function hasOmoCodexPluginPrefix(parts, endExclusive) {
|
|
|
1325
1388
|
}
|
|
1326
1389
|
|
|
1327
1390
|
// ../src/install/codex-cache-legacy-bins.ts
|
|
1328
|
-
import { lstat as
|
|
1329
|
-
import { join as
|
|
1391
|
+
import { lstat as lstat6, readFile as readFile7, readlink as readlink2, rm as rm8 } from "node:fs/promises";
|
|
1392
|
+
import { join as join12 } from "node:path";
|
|
1330
1393
|
var LEGACY_CODEX_COMPONENT_BINS = [
|
|
1331
1394
|
{ name: "omo", component: "ulw-loop" },
|
|
1332
1395
|
{ name: "codex-comment-checker", component: "comment-checker" },
|
|
@@ -1338,13 +1401,13 @@ var LEGACY_CODEX_COMPONENT_BINS = [
|
|
|
1338
1401
|
];
|
|
1339
1402
|
async function removeLegacyCodexComponentBins(binDir, platform) {
|
|
1340
1403
|
for (const entry of LEGACY_CODEX_COMPONENT_BINS) {
|
|
1341
|
-
const linkPath =
|
|
1404
|
+
const linkPath = join12(binDir, platform === "win32" ? `${entry.name}.cmd` : entry.name);
|
|
1342
1405
|
await removeLegacyCodexComponentBin(linkPath, entry.component, platform);
|
|
1343
1406
|
}
|
|
1344
1407
|
}
|
|
1345
1408
|
async function removeLegacyCodexComponentBin(linkPath, component, platform) {
|
|
1346
1409
|
try {
|
|
1347
|
-
const stat4 = await
|
|
1410
|
+
const stat4 = await lstat6(linkPath);
|
|
1348
1411
|
if (platform !== "win32") {
|
|
1349
1412
|
if (!stat4.isSymbolicLink())
|
|
1350
1413
|
return;
|
|
@@ -1389,10 +1452,10 @@ function isNodeErrorWithCode2(error) {
|
|
|
1389
1452
|
}
|
|
1390
1453
|
|
|
1391
1454
|
// ../src/install/codex-cache-runtime-wrapper.ts
|
|
1392
|
-
import { join as
|
|
1455
|
+
import { join as join13 } from "node:path";
|
|
1393
1456
|
var RUNTIME_WRAPPER_MARKER = "OMO_GENERATED_RUNTIME_WRAPPER";
|
|
1394
1457
|
function posixRuntimeWrapper(cliPath, codexHome, binDir, nodeCliPath) {
|
|
1395
|
-
const ulwLoopBin = toPosixPath(
|
|
1458
|
+
const ulwLoopBin = toPosixPath(join13(binDir, "omo-ulw-loop"));
|
|
1396
1459
|
const nodeCli = escapePosixDoubleQuoted(toPosixPath(nodeCliPath));
|
|
1397
1460
|
const escapedCliPath = escapePosixDoubleQuoted(toPosixPath(cliPath));
|
|
1398
1461
|
const escapedCodexHome = escapePosixDoubleQuoted(toPosixPath(codexHome));
|
|
@@ -1437,7 +1500,7 @@ function posixRuntimeWrapper(cliPath, codexHome, binDir, nodeCliPath) {
|
|
|
1437
1500
|
`);
|
|
1438
1501
|
}
|
|
1439
1502
|
function windowsRuntimeWrapper(cliPath, codexHome, binDir, nodeCliPath) {
|
|
1440
|
-
const ulwLoopBin =
|
|
1503
|
+
const ulwLoopBin = join13(binDir, "omo-ulw-loop.cmd");
|
|
1441
1504
|
return [
|
|
1442
1505
|
"@echo off",
|
|
1443
1506
|
`rem ${RUNTIME_WRAPPER_MARKER}`,
|
|
@@ -1494,29 +1557,29 @@ async function linkCachedPluginBins(input) {
|
|
|
1494
1557
|
return linked;
|
|
1495
1558
|
}
|
|
1496
1559
|
async function linkRootRuntimeBin(input) {
|
|
1497
|
-
const cliPath =
|
|
1560
|
+
const cliPath = join14(input.repoRoot, "dist", "cli", "index.js");
|
|
1498
1561
|
if (!await isFile2(cliPath))
|
|
1499
1562
|
return null;
|
|
1500
|
-
const nodeCliPath =
|
|
1563
|
+
const nodeCliPath = join14(input.repoRoot, "dist", "cli-node", "index.js");
|
|
1501
1564
|
const platform = input.platform ?? process.platform;
|
|
1502
1565
|
await mkdir5(input.binDir, { recursive: true });
|
|
1503
1566
|
if (platform === "win32") {
|
|
1504
|
-
const linkPath2 =
|
|
1567
|
+
const linkPath2 = join14(input.binDir, "omo.cmd");
|
|
1505
1568
|
await replaceRuntimeWrapper(linkPath2, windowsRuntimeWrapper(cliPath, input.codexHome, input.binDir, nodeCliPath));
|
|
1506
1569
|
return { name: "omo", path: linkPath2, target: cliPath };
|
|
1507
1570
|
}
|
|
1508
|
-
const linkPath =
|
|
1571
|
+
const linkPath = join14(input.binDir, "omo");
|
|
1509
1572
|
await replaceRuntimeWrapper(linkPath, posixRuntimeWrapper(cliPath, input.codexHome, input.binDir, nodeCliPath));
|
|
1510
1573
|
await chmod2(linkPath, 493);
|
|
1511
1574
|
return { name: "omo", path: linkPath, target: cliPath };
|
|
1512
1575
|
}
|
|
1513
1576
|
async function linkCachedPluginBin(binDir, link, platform) {
|
|
1514
1577
|
if (platform === "win32") {
|
|
1515
|
-
const linkPath2 =
|
|
1578
|
+
const linkPath2 = join14(binDir, `${link.name}.cmd`);
|
|
1516
1579
|
await replaceCommandShim(linkPath2, link.target);
|
|
1517
1580
|
return linkPath2;
|
|
1518
1581
|
}
|
|
1519
|
-
const linkPath =
|
|
1582
|
+
const linkPath = join14(binDir, link.name);
|
|
1520
1583
|
await replaceSymlink(linkPath, link.target);
|
|
1521
1584
|
return linkPath;
|
|
1522
1585
|
}
|
|
@@ -1535,16 +1598,16 @@ async function discoverPackageBins(root) {
|
|
|
1535
1598
|
return links;
|
|
1536
1599
|
}
|
|
1537
1600
|
async function collectPackageBins(directory, root, links) {
|
|
1538
|
-
const entries = await
|
|
1601
|
+
const entries = await readdir4(directory, { withFileTypes: true });
|
|
1539
1602
|
if (entries.some((entry) => entry.isFile() && entry.name === "package.json")) {
|
|
1540
|
-
await appendPackageBinLinks(
|
|
1603
|
+
await appendPackageBinLinks(join14(directory, "package.json"), directory, root, links);
|
|
1541
1604
|
}
|
|
1542
1605
|
for (const entry of entries) {
|
|
1543
1606
|
if (!entry.isDirectory())
|
|
1544
1607
|
continue;
|
|
1545
1608
|
if (entry.name === "node_modules" || entry.name === ".git" || entry.name === "dist")
|
|
1546
1609
|
continue;
|
|
1547
|
-
const childPath =
|
|
1610
|
+
const childPath = join14(directory, entry.name);
|
|
1548
1611
|
if (!childPath.startsWith(root))
|
|
1549
1612
|
continue;
|
|
1550
1613
|
await collectPackageBins(childPath, root, links);
|
|
@@ -1603,17 +1666,17 @@ async function replaceSymlink(linkPath, targetPath) {
|
|
|
1603
1666
|
async function replaceCommandShim(linkPath, targetPath) {
|
|
1604
1667
|
if (await existingNonShim(linkPath))
|
|
1605
1668
|
throw new Error(`${linkPath} already exists and is not a command shim`);
|
|
1606
|
-
await
|
|
1669
|
+
await writeFile5(linkPath, windowsCommandShim(targetPath));
|
|
1607
1670
|
}
|
|
1608
1671
|
async function replaceRuntimeWrapper(linkPath, content) {
|
|
1609
1672
|
if (await existingNonRuntimeWrapper(linkPath))
|
|
1610
1673
|
throw new Error(`${linkPath} already exists and is not a generated OMO runtime wrapper`);
|
|
1611
1674
|
await rm9(linkPath, { force: true });
|
|
1612
|
-
await
|
|
1675
|
+
await writeFile5(linkPath, content);
|
|
1613
1676
|
}
|
|
1614
1677
|
async function existingNonRuntimeWrapper(path) {
|
|
1615
1678
|
try {
|
|
1616
|
-
const stat5 = await
|
|
1679
|
+
const stat5 = await lstat7(path);
|
|
1617
1680
|
if (stat5.isSymbolicLink())
|
|
1618
1681
|
return false;
|
|
1619
1682
|
if (!stat5.isFile())
|
|
@@ -1628,7 +1691,7 @@ async function existingNonRuntimeWrapper(path) {
|
|
|
1628
1691
|
}
|
|
1629
1692
|
async function existingNonShim(path) {
|
|
1630
1693
|
try {
|
|
1631
|
-
const stat5 = await
|
|
1694
|
+
const stat5 = await lstat7(path);
|
|
1632
1695
|
if (!stat5.isFile())
|
|
1633
1696
|
return true;
|
|
1634
1697
|
const content = await readFile8(path, "utf8");
|
|
@@ -1643,7 +1706,7 @@ async function existingNonShim(path) {
|
|
|
1643
1706
|
}
|
|
1644
1707
|
async function existingNonSymlink(path) {
|
|
1645
1708
|
try {
|
|
1646
|
-
const stat5 = await
|
|
1709
|
+
const stat5 = await lstat7(path);
|
|
1647
1710
|
if (!stat5.isSymbolicLink())
|
|
1648
1711
|
return true;
|
|
1649
1712
|
await readlink3(path);
|
|
@@ -1657,7 +1720,7 @@ async function existingNonSymlink(path) {
|
|
|
1657
1720
|
|
|
1658
1721
|
// ../src/install/codex-config-toml.ts
|
|
1659
1722
|
import { mkdir as mkdir6, readFile as readFile10 } from "node:fs/promises";
|
|
1660
|
-
import { dirname as
|
|
1723
|
+
import { dirname as dirname8 } from "node:path";
|
|
1661
1724
|
|
|
1662
1725
|
// ../src/install/toml-section-editor.ts
|
|
1663
1726
|
function findTomlSection(config, header) {
|
|
@@ -2015,14 +2078,14 @@ function tomlKeySegment(value) {
|
|
|
2015
2078
|
}
|
|
2016
2079
|
|
|
2017
2080
|
// ../src/install/codex-config-atomic-write.ts
|
|
2018
|
-
import { lstat as
|
|
2019
|
-
import { basename as basename5, dirname as dirname6, isAbsolute as isAbsolute4, join as
|
|
2081
|
+
import { lstat as lstat8, readlink as readlink4, realpath, rename as rename3, unlink, writeFile as writeFile6 } from "node:fs/promises";
|
|
2082
|
+
import { basename as basename5, dirname as dirname6, isAbsolute as isAbsolute4, join as join15, resolve as resolve5 } from "node:path";
|
|
2020
2083
|
var RENAME_RETRY_DELAYS_MS = [10, 25, 50];
|
|
2021
2084
|
var RETRIABLE_RENAME_CODES = new Set(["EPERM", "EBUSY"]);
|
|
2022
2085
|
async function writeFileAtomic(targetPath, data) {
|
|
2023
2086
|
const writeTarget = await resolveSymlinkTarget(targetPath);
|
|
2024
|
-
const temporaryPath =
|
|
2025
|
-
await
|
|
2087
|
+
const temporaryPath = join15(dirname6(writeTarget), `.tmp-${basename5(writeTarget)}-${process.pid}-${Date.now()}`);
|
|
2088
|
+
await writeFile6(temporaryPath, data);
|
|
2026
2089
|
try {
|
|
2027
2090
|
await renameWithRetry(temporaryPath, writeTarget);
|
|
2028
2091
|
} catch (error) {
|
|
@@ -2036,7 +2099,7 @@ async function writeFileAtomic(targetPath, data) {
|
|
|
2036
2099
|
}
|
|
2037
2100
|
async function resolveSymlinkTarget(targetPath) {
|
|
2038
2101
|
try {
|
|
2039
|
-
const linkStats = await
|
|
2102
|
+
const linkStats = await lstat8(targetPath);
|
|
2040
2103
|
if (!linkStats.isSymbolicLink())
|
|
2041
2104
|
return targetPath;
|
|
2042
2105
|
} catch (error) {
|
|
@@ -2392,7 +2455,7 @@ function isRootSetting(line, key) {
|
|
|
2392
2455
|
|
|
2393
2456
|
// ../src/install/codex-model-catalog.ts
|
|
2394
2457
|
import { readFile as readFile9 } from "node:fs/promises";
|
|
2395
|
-
import { join as
|
|
2458
|
+
import { join as join16 } from "node:path";
|
|
2396
2459
|
var FALLBACK_CODEX_MODEL_CATALOG = {
|
|
2397
2460
|
current: {
|
|
2398
2461
|
model: "gpt-5.5",
|
|
@@ -2411,7 +2474,7 @@ var FALLBACK_CODEX_MODEL_CATALOG = {
|
|
|
2411
2474
|
]
|
|
2412
2475
|
};
|
|
2413
2476
|
async function readCodexModelCatalog(codexPackageRoot) {
|
|
2414
|
-
const catalogPath =
|
|
2477
|
+
const catalogPath = join16(codexPackageRoot, "plugin", "model-catalog.json");
|
|
2415
2478
|
try {
|
|
2416
2479
|
const parsed = JSON.parse(await readFile9(catalogPath, "utf8"));
|
|
2417
2480
|
return parseCodexModelCatalog(parsed) ?? FALLBACK_CODEX_MODEL_CATALOG;
|
|
@@ -2494,30 +2557,87 @@ function isRootSetting2(line, key) {
|
|
|
2494
2557
|
}
|
|
2495
2558
|
|
|
2496
2559
|
// ../src/install/codex-multi-agent-v2-config.ts
|
|
2560
|
+
import { readFileSync } from "node:fs";
|
|
2561
|
+
import { dirname as dirname7, isAbsolute as isAbsolute5, join as join17 } from "node:path";
|
|
2497
2562
|
var CODEX_AGENTS_HEADER = "agents";
|
|
2498
2563
|
var CODEX_MULTI_AGENT_V2_HEADER = "features.multi_agent_v2";
|
|
2499
2564
|
var CODEX_SUBAGENT_THREAD_LIMIT = 1000;
|
|
2500
|
-
function ensureCodexMultiAgentV2Config(config) {
|
|
2565
|
+
function ensureCodexMultiAgentV2Config(config, options = {}) {
|
|
2501
2566
|
const featureFlag = removeFeatureFlagSetting(config, "multi_agent_v2");
|
|
2502
|
-
const
|
|
2503
|
-
const
|
|
2567
|
+
const v2Preferred = options.multiAgentVersion === "v2";
|
|
2568
|
+
const modelKnown = options.multiAgentVersion != null || readRootModel(featureFlag.config) !== null;
|
|
2569
|
+
const agentsConfig = v2Preferred ? removeAgentsMaxThreads(featureFlag.config) : modelKnown ? ensureAgentsMaxThreads(featureFlag.config) : raiseExistingAgentsMaxThreads(featureFlag.config);
|
|
2504
2570
|
const maxThreadsValue = CODEX_SUBAGENT_THREAD_LIMIT.toString();
|
|
2571
|
+
const preserveDisable = featureFlag.value === false && !v2Preferred;
|
|
2572
|
+
const featureConfig = preserveDisable ? setMultiAgentV2Disable(agentsConfig) : v2Preferred ? removeMultiAgentV2Disable(agentsConfig) : agentsConfig;
|
|
2573
|
+
const section = findTomlSection(featureConfig, CODEX_MULTI_AGENT_V2_HEADER);
|
|
2505
2574
|
if (!section) {
|
|
2506
|
-
const enabledSetting =
|
|
2575
|
+
const enabledSetting = preserveDisable ? `enabled = false
|
|
2507
2576
|
` : "";
|
|
2508
|
-
return appendBlock(
|
|
2577
|
+
return appendBlock(featureConfig, `[${CODEX_MULTI_AGENT_V2_HEADER}]
|
|
2509
2578
|
${enabledSetting}max_concurrent_threads_per_session = ${maxThreadsValue}
|
|
2510
2579
|
`);
|
|
2511
2580
|
}
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2581
|
+
return replaceOrInsertSetting(featureConfig, section, "max_concurrent_threads_per_session", maxThreadsValue);
|
|
2582
|
+
}
|
|
2583
|
+
function resolveCodexMultiAgentVersion(config, configPath) {
|
|
2584
|
+
const model = readRootModel(config);
|
|
2585
|
+
if (model === null)
|
|
2586
|
+
return null;
|
|
2587
|
+
const catalogPath = resolveCatalogPath(readRootModelCatalogPath(config), configPath);
|
|
2588
|
+
const catalogVersion = readCatalogMultiAgentVersion(model, catalogPath);
|
|
2589
|
+
if (catalogVersion !== null)
|
|
2590
|
+
return catalogVersion;
|
|
2591
|
+
return /^gpt-5\.6\b/i.test(model) ? "v2" : null;
|
|
2592
|
+
}
|
|
2593
|
+
function resolveCatalogPath(configuredPath, configPath) {
|
|
2594
|
+
if (configuredPath === null)
|
|
2595
|
+
return join17(dirname7(configPath), "models_cache.json");
|
|
2596
|
+
return isAbsolute5(configuredPath) ? configuredPath : join17(dirname7(configPath), configuredPath);
|
|
2597
|
+
}
|
|
2598
|
+
function readCatalogMultiAgentVersion(model, cachePath) {
|
|
2599
|
+
let raw;
|
|
2600
|
+
try {
|
|
2601
|
+
raw = readFileSync(cachePath, "utf8");
|
|
2602
|
+
} catch {
|
|
2603
|
+
return null;
|
|
2604
|
+
}
|
|
2605
|
+
let cache;
|
|
2606
|
+
try {
|
|
2607
|
+
cache = JSON.parse(raw);
|
|
2608
|
+
} catch {
|
|
2609
|
+
return null;
|
|
2519
2610
|
}
|
|
2520
|
-
|
|
2611
|
+
if (!isRecord2(cache) || !Array.isArray(cache.models))
|
|
2612
|
+
return null;
|
|
2613
|
+
for (const entry of cache.models) {
|
|
2614
|
+
if (!isRecord2(entry))
|
|
2615
|
+
continue;
|
|
2616
|
+
if (entry.slug !== model && entry.id !== model)
|
|
2617
|
+
continue;
|
|
2618
|
+
const version = entry.multi_agent_version;
|
|
2619
|
+
if (version === "v1" || version === "v2")
|
|
2620
|
+
return version;
|
|
2621
|
+
return null;
|
|
2622
|
+
}
|
|
2623
|
+
return null;
|
|
2624
|
+
}
|
|
2625
|
+
function readRootModel(config) {
|
|
2626
|
+
const double = config.match(/^\s*model\s*=\s*"([^"]+)"/m);
|
|
2627
|
+
if (double !== null)
|
|
2628
|
+
return double[1] ?? null;
|
|
2629
|
+
const single = config.match(/^\s*model\s*=\s*'([^']+)'/m);
|
|
2630
|
+
return single?.[1] ?? null;
|
|
2631
|
+
}
|
|
2632
|
+
function readRootModelCatalogPath(config) {
|
|
2633
|
+
const double = config.match(/^\s*model_catalog_json\s*=\s*"([^"]+)"/m);
|
|
2634
|
+
if (double !== null)
|
|
2635
|
+
return double[1] ?? null;
|
|
2636
|
+
const single = config.match(/^\s*model_catalog_json\s*=\s*'([^']+)'/m);
|
|
2637
|
+
return single?.[1] ?? null;
|
|
2638
|
+
}
|
|
2639
|
+
function isRecord2(value) {
|
|
2640
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2521
2641
|
}
|
|
2522
2642
|
function removeFeatureFlagSetting(config, featureName) {
|
|
2523
2643
|
const section = findTomlSection(config, "features");
|
|
@@ -2538,6 +2658,36 @@ max_threads = ${maxThreadsValue}
|
|
|
2538
2658
|
}
|
|
2539
2659
|
return replaceOrInsertSetting(config, section, "max_threads", maxThreadsValue);
|
|
2540
2660
|
}
|
|
2661
|
+
function removeAgentsMaxThreads(config) {
|
|
2662
|
+
const section = findTomlSection(config, CODEX_AGENTS_HEADER);
|
|
2663
|
+
if (!section)
|
|
2664
|
+
return config;
|
|
2665
|
+
if (!/^\s*max_threads\s*=/m.test(section.text))
|
|
2666
|
+
return config;
|
|
2667
|
+
return removeSetting(config, section, "max_threads");
|
|
2668
|
+
}
|
|
2669
|
+
function removeMultiAgentV2Disable(config) {
|
|
2670
|
+
const section = findTomlSection(config, CODEX_MULTI_AGENT_V2_HEADER);
|
|
2671
|
+
if (!section)
|
|
2672
|
+
return config;
|
|
2673
|
+
if (!/^\s*enabled\s*=\s*false(?:\s*#.*)?$/m.test(section.text))
|
|
2674
|
+
return config;
|
|
2675
|
+
return removeSetting(config, section, "enabled");
|
|
2676
|
+
}
|
|
2677
|
+
function setMultiAgentV2Disable(config) {
|
|
2678
|
+
const section = findTomlSection(config, CODEX_MULTI_AGENT_V2_HEADER);
|
|
2679
|
+
if (!section)
|
|
2680
|
+
return config;
|
|
2681
|
+
return replaceOrInsertSetting(config, section, "enabled", "false");
|
|
2682
|
+
}
|
|
2683
|
+
function raiseExistingAgentsMaxThreads(config) {
|
|
2684
|
+
const section = findTomlSection(config, CODEX_AGENTS_HEADER);
|
|
2685
|
+
if (!section)
|
|
2686
|
+
return config;
|
|
2687
|
+
if (!/^\s*max_threads\s*=/m.test(section.text))
|
|
2688
|
+
return config;
|
|
2689
|
+
return replaceOrInsertSetting(config, section, "max_threads", CODEX_SUBAGENT_THREAD_LIMIT.toString());
|
|
2690
|
+
}
|
|
2541
2691
|
function readBooleanSetting(sectionText, key) {
|
|
2542
2692
|
const match = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=\\s*(true|false)\\s*(?:#.*)?$`, "m").exec(sectionText);
|
|
2543
2693
|
if (!match)
|
|
@@ -2547,7 +2697,7 @@ function readBooleanSetting(sectionText, key) {
|
|
|
2547
2697
|
|
|
2548
2698
|
// ../src/install/codex-config-toml.ts
|
|
2549
2699
|
async function updateCodexConfig(input) {
|
|
2550
|
-
await mkdir6(
|
|
2700
|
+
await mkdir6(dirname8(input.configPath), { recursive: true });
|
|
2551
2701
|
let config;
|
|
2552
2702
|
try {
|
|
2553
2703
|
config = await readFile10(input.configPath, "utf8");
|
|
@@ -2570,7 +2720,9 @@ async function updateCodexConfig(input) {
|
|
|
2570
2720
|
config = ensureFeatureEnabled(config, "multi_agent");
|
|
2571
2721
|
config = removeUnsupportedCodexMultiAgentModeConfig(config);
|
|
2572
2722
|
config = ensureCodexReasoningConfig(config, await readCodexModelCatalog(input.repoRoot));
|
|
2573
|
-
config = ensureCodexMultiAgentV2Config(config
|
|
2723
|
+
config = ensureCodexMultiAgentV2Config(config, {
|
|
2724
|
+
multiAgentVersion: resolveCodexMultiAgentVersion(config, input.configPath)
|
|
2725
|
+
});
|
|
2574
2726
|
if (input.autonomousPermissions === true)
|
|
2575
2727
|
config = ensureAutonomousPermissions(config);
|
|
2576
2728
|
if (!(input.preserveMarketplaceSource === true && hasMarketplaceBlock(config, input.marketplaceName))) {
|
|
@@ -2594,12 +2746,12 @@ function isMissingFileError(error) {
|
|
|
2594
2746
|
}
|
|
2595
2747
|
|
|
2596
2748
|
// ../src/install/codex-git-bash-mcp-env.ts
|
|
2597
|
-
import { readFile as readFile11, writeFile as
|
|
2598
|
-
import { join as
|
|
2749
|
+
import { readFile as readFile11, writeFile as writeFile7 } from "node:fs/promises";
|
|
2750
|
+
import { join as join18 } from "node:path";
|
|
2599
2751
|
var GIT_BASH_ENV_KEY = "OMO_CODEX_GIT_BASH_PATH";
|
|
2600
2752
|
var CODEGRAPH_RELATIVE_ARGS = new Set(["components/codegraph/dist/serve.js", "./components/codegraph/dist/serve.js"]);
|
|
2601
2753
|
async function stampGitBashMcpEnv(input) {
|
|
2602
|
-
const manifestPath =
|
|
2754
|
+
const manifestPath = join18(input.pluginRoot, ".mcp.json");
|
|
2603
2755
|
if (!await fileExistsStrict(manifestPath))
|
|
2604
2756
|
return false;
|
|
2605
2757
|
const parsed = JSON.parse(await readFile11(manifestPath, "utf8"));
|
|
@@ -2620,7 +2772,7 @@ async function stampGitBashMcpEnv(input) {
|
|
|
2620
2772
|
}
|
|
2621
2773
|
if (!changed)
|
|
2622
2774
|
return false;
|
|
2623
|
-
await
|
|
2775
|
+
await writeFile7(manifestPath, `${JSON.stringify(parsed, null, "\t")}
|
|
2624
2776
|
`);
|
|
2625
2777
|
return true;
|
|
2626
2778
|
}
|
|
@@ -2632,14 +2784,14 @@ function stampCodegraphMcpPath(mcpServers, pluginRoot) {
|
|
|
2632
2784
|
const entrypoint = args[0];
|
|
2633
2785
|
if (typeof entrypoint !== "string" || !CODEGRAPH_RELATIVE_ARGS.has(entrypoint))
|
|
2634
2786
|
return false;
|
|
2635
|
-
codegraphServer["args"] = [
|
|
2787
|
+
codegraphServer["args"] = [join18(pluginRoot, "components", "codegraph", "dist", "serve.js"), ...args.slice(1)];
|
|
2636
2788
|
return true;
|
|
2637
2789
|
}
|
|
2638
2790
|
|
|
2639
2791
|
// ../src/install/codex-hook-trust.ts
|
|
2640
2792
|
import { createHash as createHash3 } from "node:crypto";
|
|
2641
2793
|
import { readFile as readFile12 } from "node:fs/promises";
|
|
2642
|
-
import { join as
|
|
2794
|
+
import { join as join19 } from "node:path";
|
|
2643
2795
|
var EVENT_LABELS = new Map([
|
|
2644
2796
|
["PreToolUse", "pre_tool_use"],
|
|
2645
2797
|
["PermissionRequest", "permission_request"],
|
|
@@ -2653,16 +2805,16 @@ var EVENT_LABELS = new Map([
|
|
|
2653
2805
|
["Stop", "stop"]
|
|
2654
2806
|
]);
|
|
2655
2807
|
async function trustedHookStatesForPlugin(input) {
|
|
2656
|
-
const manifestPath =
|
|
2657
|
-
if (!await
|
|
2808
|
+
const manifestPath = join19(input.pluginRoot, ".codex-plugin", "plugin.json");
|
|
2809
|
+
if (!await exists4(manifestPath))
|
|
2658
2810
|
return [];
|
|
2659
2811
|
const manifest = JSON.parse(await readFile12(manifestPath, "utf8"));
|
|
2660
2812
|
if (!isPlainRecord(manifest))
|
|
2661
2813
|
return [];
|
|
2662
2814
|
const states = [];
|
|
2663
2815
|
for (const hookPath of hookManifestPaths(manifest.hooks)) {
|
|
2664
|
-
const hooksPath =
|
|
2665
|
-
if (!await
|
|
2816
|
+
const hooksPath = join19(input.pluginRoot, hookPath);
|
|
2817
|
+
if (!await exists4(hooksPath))
|
|
2666
2818
|
continue;
|
|
2667
2819
|
const parsed = JSON.parse(await readFile12(hooksPath, "utf8"));
|
|
2668
2820
|
if (!isPlainRecord(parsed) || !isPlainRecord(parsed.hooks))
|
|
@@ -2745,7 +2897,7 @@ function canonicalJson(value) {
|
|
|
2745
2897
|
function stripDotSlash(value) {
|
|
2746
2898
|
return value.startsWith("./") ? value.slice(2) : value;
|
|
2747
2899
|
}
|
|
2748
|
-
async function
|
|
2900
|
+
async function exists4(path) {
|
|
2749
2901
|
try {
|
|
2750
2902
|
await readFile12(path, "utf8");
|
|
2751
2903
|
return true;
|
|
@@ -2758,7 +2910,7 @@ async function exists3(path) {
|
|
|
2758
2910
|
|
|
2759
2911
|
// ../src/install/codex-installer-bin-dir.ts
|
|
2760
2912
|
import { homedir as homedir3 } from "node:os";
|
|
2761
|
-
import { join as
|
|
2913
|
+
import { join as join20, resolve as resolve6 } from "node:path";
|
|
2762
2914
|
function resolveCodexInstallerBinDir(input) {
|
|
2763
2915
|
const explicitBinDir = input.binDir ?? input.env?.CODEX_LOCAL_BIN_DIR;
|
|
2764
2916
|
if (explicitBinDir !== undefined && explicitBinDir.trim().length > 0)
|
|
@@ -2767,7 +2919,7 @@ function resolveCodexInstallerBinDir(input) {
|
|
|
2767
2919
|
const defaultCodexHome = resolve6(homeDir, ".codex");
|
|
2768
2920
|
const resolvedCodexHome = resolve6(input.codexHome);
|
|
2769
2921
|
if (resolvedCodexHome !== defaultCodexHome)
|
|
2770
|
-
return
|
|
2922
|
+
return join20(resolvedCodexHome, "bin");
|
|
2771
2923
|
return resolve6(homeDir, ".local", "bin");
|
|
2772
2924
|
}
|
|
2773
2925
|
|
|
@@ -2923,9 +3075,9 @@ async function resolveGitBashStep(options, degraded) {
|
|
|
2923
3075
|
return false;
|
|
2924
3076
|
}
|
|
2925
3077
|
async function linkBundledAgentsStep(options) {
|
|
2926
|
-
const agentsTarget =
|
|
3078
|
+
const agentsTarget = join21(options.codexHome, "agents");
|
|
2927
3079
|
try {
|
|
2928
|
-
const stageRoot =
|
|
3080
|
+
const stageRoot = join21(options.pluginData, "bootstrap", "agents-stage");
|
|
2929
3081
|
await stageBundledAgents(options.pluginRoot, stageRoot);
|
|
2930
3082
|
const preservedReasoning = await capturePreservedAgentReasoning({ codexHome: options.codexHome });
|
|
2931
3083
|
const preservedServiceTier = await capturePreservedAgentServiceTier({ codexHome: options.codexHome });
|
|
@@ -2935,7 +3087,7 @@ async function linkBundledAgentsStep(options) {
|
|
|
2935
3087
|
preservedReasoning,
|
|
2936
3088
|
preservedServiceTier
|
|
2937
3089
|
});
|
|
2938
|
-
const agentConfigs = linked.map((link) => ({ configFile: `./agents/${link.name}`, name:
|
|
3090
|
+
const agentConfigs = linked.map((link) => ({ configFile: `./agents/${link.name}`, name: agentNameFromToml3(link.name) })).sort((left, right) => left.name.localeCompare(right.name));
|
|
2939
3091
|
return { agentConfigs, degraded: [] };
|
|
2940
3092
|
} catch (error) {
|
|
2941
3093
|
return {
|
|
@@ -2953,21 +3105,21 @@ async function linkBundledAgentsStep(options) {
|
|
|
2953
3105
|
async function stageBundledAgents(pluginRoot, stageRoot) {
|
|
2954
3106
|
await rm10(stageRoot, { force: true, recursive: true });
|
|
2955
3107
|
await mkdir7(stageRoot, { recursive: true });
|
|
2956
|
-
const componentsRoot =
|
|
3108
|
+
const componentsRoot = join21(pluginRoot, "components");
|
|
2957
3109
|
for (const componentName of await directoryNames(componentsRoot)) {
|
|
2958
|
-
const agentsDir =
|
|
3110
|
+
const agentsDir = join21(componentsRoot, componentName, "agents");
|
|
2959
3111
|
const agentFiles = (await fileNames(agentsDir)).filter((name) => name.endsWith(".toml"));
|
|
2960
3112
|
if (agentFiles.length === 0)
|
|
2961
3113
|
continue;
|
|
2962
|
-
const stagedAgentsDir =
|
|
3114
|
+
const stagedAgentsDir = join21(stageRoot, "components", componentName, "agents");
|
|
2963
3115
|
await mkdir7(stagedAgentsDir, { recursive: true });
|
|
2964
3116
|
for (const agentFile of agentFiles) {
|
|
2965
|
-
await copyFile2(
|
|
3117
|
+
await copyFile2(join21(agentsDir, agentFile), join21(stagedAgentsDir, agentFile));
|
|
2966
3118
|
}
|
|
2967
3119
|
}
|
|
2968
3120
|
}
|
|
2969
3121
|
async function updateConfigStep(options, inputs, degraded) {
|
|
2970
|
-
const configPath =
|
|
3122
|
+
const configPath = join21(options.codexHome, "config.toml");
|
|
2971
3123
|
try {
|
|
2972
3124
|
await assertWritableConfigIfPresent(configPath);
|
|
2973
3125
|
const trustedHookStates = await trustedHookStatesForPlugin({
|
|
@@ -3023,7 +3175,7 @@ async function linkComponentBinsStep(options, degraded) {
|
|
|
3023
3175
|
await linkRuntimeWrapperStep(options, binDir, degraded);
|
|
3024
3176
|
}
|
|
3025
3177
|
async function linkRuntimeWrapperStep(options, binDir, degraded) {
|
|
3026
|
-
const cliPath =
|
|
3178
|
+
const cliPath = join21(options.pluginRoot, "dist", "cli", "index.js");
|
|
3027
3179
|
try {
|
|
3028
3180
|
const linked = await linkRootRuntimeBin({
|
|
3029
3181
|
binDir,
|
|
@@ -3056,7 +3208,7 @@ async function stampGitBashEnvStep(options, degraded) {
|
|
|
3056
3208
|
degraded.push({
|
|
3057
3209
|
component: "git-bash-env",
|
|
3058
3210
|
hint: BOOTSTRAP_DOCTOR_HINT,
|
|
3059
|
-
reason: `failed to stamp ${
|
|
3211
|
+
reason: `failed to stamp ${join21(options.pluginRoot, ".mcp.json")}: ${errorMessage(error)}`
|
|
3060
3212
|
});
|
|
3061
3213
|
}
|
|
3062
3214
|
}
|
|
@@ -3068,7 +3220,7 @@ async function fileNames(root) {
|
|
|
3068
3220
|
}
|
|
3069
3221
|
async function entryNames(root, keep) {
|
|
3070
3222
|
try {
|
|
3071
|
-
const entries = await
|
|
3223
|
+
const entries = await readdir5(root, { withFileTypes: true });
|
|
3072
3224
|
return entries.filter((entry) => keep(entry)).map((entry) => entry.name).sort();
|
|
3073
3225
|
} catch (error) {
|
|
3074
3226
|
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
@@ -3076,7 +3228,7 @@ async function entryNames(root, keep) {
|
|
|
3076
3228
|
throw error;
|
|
3077
3229
|
}
|
|
3078
3230
|
}
|
|
3079
|
-
function
|
|
3231
|
+
function agentNameFromToml3(fileName) {
|
|
3080
3232
|
return fileName.endsWith(".toml") ? fileName.slice(0, -".toml".length) : fileName;
|
|
3081
3233
|
}
|
|
3082
3234
|
function errorMessage(error) {
|
|
@@ -3124,11 +3276,11 @@ function resolvePluginDataRoot(env) {
|
|
|
3124
3276
|
const fromEnv = env["PLUGIN_DATA"]?.trim();
|
|
3125
3277
|
if (fromEnv !== undefined && fromEnv.length > 0)
|
|
3126
3278
|
return fromEnv;
|
|
3127
|
-
return
|
|
3279
|
+
return join22(homedir4(), ".local", "share", "lazycodex");
|
|
3128
3280
|
}
|
|
3129
3281
|
async function readPluginVersion(pluginRoot) {
|
|
3130
3282
|
try {
|
|
3131
|
-
const parsed = JSON.parse(await readFile13(
|
|
3283
|
+
const parsed = JSON.parse(await readFile13(join22(pluginRoot, ".codex-plugin", "plugin.json"), "utf8"));
|
|
3132
3284
|
if (typeof parsed !== "object" || parsed === null)
|
|
3133
3285
|
return;
|
|
3134
3286
|
const version = parsed["version"];
|
|
@@ -3195,7 +3347,7 @@ async function runBootstrapWorker(options = {}) {
|
|
|
3195
3347
|
degraded.push({
|
|
3196
3348
|
component: "bootstrap",
|
|
3197
3349
|
hint: BOOTSTRAP_DOCTOR_HINT,
|
|
3198
|
-
reason: `plugin version unresolved from ${
|
|
3350
|
+
reason: `plugin version unresolved from ${join22(pluginRoot, ".codex-plugin", "plugin.json")}`
|
|
3199
3351
|
});
|
|
3200
3352
|
}
|
|
3201
3353
|
for (const step of steps) {
|
|
@@ -3234,12 +3386,12 @@ function resolvePluginRoot(env) {
|
|
|
3234
3386
|
const fromEnv = env["PLUGIN_ROOT"]?.trim();
|
|
3235
3387
|
if (fromEnv !== undefined && fromEnv.length > 0)
|
|
3236
3388
|
return fromEnv;
|
|
3237
|
-
return resolve7(
|
|
3389
|
+
return resolve7(dirname9(fileURLToPath2(import.meta.url)), "..", "..", "..");
|
|
3238
3390
|
}
|
|
3239
3391
|
async function appendBootstrapLog(pluginData, now, event, details) {
|
|
3240
3392
|
try {
|
|
3241
|
-
const logPath =
|
|
3242
|
-
await mkdir8(
|
|
3393
|
+
const logPath = join22(pluginData, "bootstrap", "bootstrap.log");
|
|
3394
|
+
await mkdir8(dirname9(logPath), { recursive: true });
|
|
3243
3395
|
await appendFile2(logPath, `${JSON.stringify({ timestamp: new Date(now).toISOString(), event, ...details })}
|
|
3244
3396
|
`);
|
|
3245
3397
|
} catch {}
|