lazycodex-ai 5.1.4 → 5.1.5
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/index.js +464 -186
- package/dist/cli-node/index.js +464 -186
- package/package.json +1 -1
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +309 -133
- 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/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/dist/.omo-runtime-manifest.json +2 -2
- 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/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- 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/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- 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/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +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-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/post-tool-use-recording-spawn-admission.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-guarding-ulw-loop-spawns.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-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-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.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 +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +311 -135
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// omo-codex-install:
|
|
2
|
+
// omo-codex-install:76bfd9555dc0f5ee104bb34f42f75e7c52948d77356eed6b57e7b57738df399f:1745be8f0e5a6fbaa5f97e2df68fa6cecf8bb9b22d612762cf912b589505c6b7
|
|
3
3
|
var __esm = (fn, res, err) => () => {
|
|
4
4
|
if (fn)
|
|
5
5
|
try {
|
|
@@ -9984,7 +9984,7 @@ var package_default;
|
|
|
9984
9984
|
var init_package = __esm(() => {
|
|
9985
9985
|
package_default = {
|
|
9986
9986
|
name: "@oh-my-opencode/omo-codex",
|
|
9987
|
-
version: "5.1.
|
|
9987
|
+
version: "5.1.5",
|
|
9988
9988
|
type: "module",
|
|
9989
9989
|
private: true,
|
|
9990
9990
|
description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
|
|
@@ -19252,7 +19252,6 @@ function normalizeLegacyModelFields(entry) {
|
|
|
19252
19252
|
delete normalized["reasoningEffort"];
|
|
19253
19253
|
delete normalized["thinking"];
|
|
19254
19254
|
delete normalized["textVerbosity"];
|
|
19255
|
-
delete normalized["maxTokens"];
|
|
19256
19255
|
delete normalized["providerOptions"];
|
|
19257
19256
|
if (typeof entry["model"] === "string")
|
|
19258
19257
|
normalized["model"] = canonicalModelString(entry["model"]);
|
|
@@ -19270,10 +19269,15 @@ function normalizeLegacyModelFields(entry) {
|
|
|
19270
19269
|
providerOptions["textVerbosity"] = entry["textVerbosity"];
|
|
19271
19270
|
if (Object.keys(providerOptions).length > 0)
|
|
19272
19271
|
normalized["provider_options"] = providerOptions;
|
|
19273
|
-
if (entry["max_tokens"] !== undefined)
|
|
19272
|
+
if (entry["max_tokens"] !== undefined) {
|
|
19274
19273
|
normalized["max_tokens"] = entry["max_tokens"];
|
|
19275
|
-
|
|
19274
|
+
if (entry["maxTokens"] === undefined || typeof entry["maxTokens"] === "number") {
|
|
19275
|
+
delete normalized["maxTokens"];
|
|
19276
|
+
}
|
|
19277
|
+
} else if (typeof entry["maxTokens"] === "number") {
|
|
19276
19278
|
normalized["max_tokens"] = entry["maxTokens"];
|
|
19279
|
+
delete normalized["maxTokens"];
|
|
19280
|
+
}
|
|
19277
19281
|
return normalized;
|
|
19278
19282
|
}
|
|
19279
19283
|
var OmoLegacyFallbackModelObjectInputSchema = object({
|
|
@@ -19303,6 +19307,19 @@ function isRecord3(value) {
|
|
|
19303
19307
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
19304
19308
|
}
|
|
19305
19309
|
var OmoAgentModelEntrySchema = union([string2(), OmoFallbackModelObjectSchema]);
|
|
19310
|
+
var PermissionValueSchema = _enum(["ask", "allow", "deny"]);
|
|
19311
|
+
var BashPermissionSchema = union([
|
|
19312
|
+
PermissionValueSchema,
|
|
19313
|
+
record(string2(), PermissionValueSchema)
|
|
19314
|
+
]);
|
|
19315
|
+
var OmoAgentPermissionSchema = object({
|
|
19316
|
+
edit: PermissionValueSchema.optional(),
|
|
19317
|
+
bash: BashPermissionSchema.optional(),
|
|
19318
|
+
webfetch: PermissionValueSchema.optional(),
|
|
19319
|
+
task: PermissionValueSchema.optional(),
|
|
19320
|
+
doom_loop: PermissionValueSchema.optional(),
|
|
19321
|
+
external_directory: PermissionValueSchema.optional()
|
|
19322
|
+
}).catchall(PermissionValueSchema.optional());
|
|
19306
19323
|
var OmoAgentDefInputSchema = object({
|
|
19307
19324
|
description: string2().optional(),
|
|
19308
19325
|
prompt: string2().optional(),
|
|
@@ -19319,7 +19336,9 @@ var OmoAgentDefInputSchema = object({
|
|
|
19319
19336
|
disallowed_tools: array(string2()).optional(),
|
|
19320
19337
|
max_turns: number2().int().nonnegative().optional(),
|
|
19321
19338
|
temperature: number2().min(0).max(2).optional(),
|
|
19322
|
-
disable: boolean2().optional()
|
|
19339
|
+
disable: boolean2().optional(),
|
|
19340
|
+
permission: OmoAgentPermissionSchema.optional(),
|
|
19341
|
+
prompt_append: string2().optional()
|
|
19323
19342
|
}).strict();
|
|
19324
19343
|
var OmoAgentDefSchema = preprocess((value) => isRecord3(value) ? normalizeLegacyModelFields(value) : value, OmoAgentDefInputSchema);
|
|
19325
19344
|
var OmoAgentsConfigSchema = record(string2(), OmoAgentDefSchema);
|
|
@@ -20008,6 +20027,16 @@ function canonicalizeLegacyHarnessBlocks(document) {
|
|
|
20008
20027
|
return { document: canonicalized, renames };
|
|
20009
20028
|
}
|
|
20010
20029
|
|
|
20030
|
+
// packages/omo-config-core/src/loader/types.ts
|
|
20031
|
+
import { existsSync as existsSync3, lstatSync, readFileSync as readFileSync2, realpathSync as realpathSync2 } from "node:fs";
|
|
20032
|
+
var MERGED_OMO_CONFIG_PATH = "(merged omo config)";
|
|
20033
|
+
var DEFAULT_READ_FILE_SYSTEM = {
|
|
20034
|
+
existsSync: existsSync3,
|
|
20035
|
+
lstatSync,
|
|
20036
|
+
readFileSync: readFileSync2,
|
|
20037
|
+
realpathSync: realpathSync2
|
|
20038
|
+
};
|
|
20039
|
+
|
|
20011
20040
|
// node_modules/.bun/jsonc-parser@3.3.1/node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
20012
20041
|
function createScanner(text, ignoreTrivia = false) {
|
|
20013
20042
|
const len = text.length;
|
|
@@ -20882,6 +20911,255 @@ function mergeOmoConfigRecords(base, override) {
|
|
|
20882
20911
|
return result;
|
|
20883
20912
|
}
|
|
20884
20913
|
|
|
20914
|
+
// packages/omo-config-core/src/loader/prune-invalid-leaves.ts
|
|
20915
|
+
var MAX_PRUNE_PASSES = 32;
|
|
20916
|
+
function isContainer(value) {
|
|
20917
|
+
return typeof value === "object" && value !== null;
|
|
20918
|
+
}
|
|
20919
|
+
function childOf(container, segment) {
|
|
20920
|
+
return Array.isArray(container) ? container[Number(segment)] : container[String(segment)];
|
|
20921
|
+
}
|
|
20922
|
+
function hasChild(container, segment) {
|
|
20923
|
+
if (Array.isArray(container)) {
|
|
20924
|
+
const index = Number(segment);
|
|
20925
|
+
return Number.isInteger(index) && index >= 0 && index < container.length;
|
|
20926
|
+
}
|
|
20927
|
+
return Object.hasOwn(container, String(segment));
|
|
20928
|
+
}
|
|
20929
|
+
function segmentsOf(path) {
|
|
20930
|
+
return path.map((segment) => typeof segment === "number" ? segment : String(segment));
|
|
20931
|
+
}
|
|
20932
|
+
function targetPaths(root, issue) {
|
|
20933
|
+
const base = segmentsOf(issue.path);
|
|
20934
|
+
if (issue.code === "unrecognized_keys")
|
|
20935
|
+
return issue.keys.map((key) => [...base, key]);
|
|
20936
|
+
let node = root;
|
|
20937
|
+
let depth = 0;
|
|
20938
|
+
for (const segment of base) {
|
|
20939
|
+
if (!isContainer(node) || !hasChild(node, segment))
|
|
20940
|
+
break;
|
|
20941
|
+
node = childOf(node, segment);
|
|
20942
|
+
depth += 1;
|
|
20943
|
+
}
|
|
20944
|
+
return [base.slice(0, depth)];
|
|
20945
|
+
}
|
|
20946
|
+
function isAncestor(ancestor, path) {
|
|
20947
|
+
return ancestor.length < path.length && ancestor.every((segment, index) => segment === path[index]);
|
|
20948
|
+
}
|
|
20949
|
+
function compareDescending(left, right) {
|
|
20950
|
+
const length = Math.min(left.length, right.length);
|
|
20951
|
+
for (let index = 0;index < length; index += 1) {
|
|
20952
|
+
const a = left[index];
|
|
20953
|
+
const b = right[index];
|
|
20954
|
+
if (a === b)
|
|
20955
|
+
continue;
|
|
20956
|
+
if (typeof a === "number" && typeof b === "number")
|
|
20957
|
+
return b - a;
|
|
20958
|
+
return String(b).localeCompare(String(a));
|
|
20959
|
+
}
|
|
20960
|
+
return right.length - left.length;
|
|
20961
|
+
}
|
|
20962
|
+
function removeChild(container, segment) {
|
|
20963
|
+
if (Array.isArray(container))
|
|
20964
|
+
container.splice(Number(segment), 1);
|
|
20965
|
+
else
|
|
20966
|
+
delete container[String(segment)];
|
|
20967
|
+
}
|
|
20968
|
+
function isEmpty(container) {
|
|
20969
|
+
return Array.isArray(container) ? container.length === 0 : Object.keys(container).length === 0;
|
|
20970
|
+
}
|
|
20971
|
+
function removePathAndEmptiedAncestors(root, path) {
|
|
20972
|
+
const chain = [root];
|
|
20973
|
+
for (const segment of path.slice(0, -1)) {
|
|
20974
|
+
const current = chain[chain.length - 1];
|
|
20975
|
+
if (current === undefined)
|
|
20976
|
+
return;
|
|
20977
|
+
const next = childOf(current, segment);
|
|
20978
|
+
if (!isContainer(next))
|
|
20979
|
+
return;
|
|
20980
|
+
chain.push(next);
|
|
20981
|
+
}
|
|
20982
|
+
for (let depth = path.length - 1;depth >= 0; depth -= 1) {
|
|
20983
|
+
const container = chain[depth];
|
|
20984
|
+
const segment = path[depth];
|
|
20985
|
+
if (container === undefined || segment === undefined)
|
|
20986
|
+
return;
|
|
20987
|
+
removeChild(container, segment);
|
|
20988
|
+
if (depth === 0 || !isEmpty(container))
|
|
20989
|
+
return;
|
|
20990
|
+
}
|
|
20991
|
+
}
|
|
20992
|
+
function prunePass(root, issues) {
|
|
20993
|
+
const byKey = new Map;
|
|
20994
|
+
for (const issue of issues) {
|
|
20995
|
+
for (const path of targetPaths(root, issue)) {
|
|
20996
|
+
if (path.length === 0)
|
|
20997
|
+
return null;
|
|
20998
|
+
const key = path.map((segment) => String(segment)).join(".");
|
|
20999
|
+
if (!byKey.has(key))
|
|
21000
|
+
byKey.set(key, { key, message: issue.message, path });
|
|
21001
|
+
}
|
|
21002
|
+
}
|
|
21003
|
+
const targets = [...byKey.values()];
|
|
21004
|
+
const outermost = targets.filter((target) => !targets.some((other) => isAncestor(other.path, target.path))).sort((left, right) => compareDescending(left.path, right.path));
|
|
21005
|
+
const next = structuredClone(root);
|
|
21006
|
+
for (const target of outermost)
|
|
21007
|
+
removePathAndEmptiedAncestors(next, target.path);
|
|
21008
|
+
return { dropped: outermost, next };
|
|
21009
|
+
}
|
|
21010
|
+
function pruneInvalidConfigPaths(config, issues, validate, maxPasses = MAX_PRUNE_PASSES) {
|
|
21011
|
+
const dropped = [];
|
|
21012
|
+
let current = config;
|
|
21013
|
+
let pending = issues;
|
|
21014
|
+
for (let pass = 0;pass < maxPasses; pass += 1) {
|
|
21015
|
+
const step = prunePass(current, pending);
|
|
21016
|
+
if (step === null || step.dropped.length === 0)
|
|
21017
|
+
return { ok: false, dropped };
|
|
21018
|
+
dropped.push(...step.dropped);
|
|
21019
|
+
current = step.next;
|
|
21020
|
+
if (Object.keys(current).length === 0)
|
|
21021
|
+
return { ok: false, dropped };
|
|
21022
|
+
const validation = validate(current);
|
|
21023
|
+
if (validation.success)
|
|
21024
|
+
return { ok: true, config: current, dropped };
|
|
21025
|
+
pending = validation.issues;
|
|
21026
|
+
}
|
|
21027
|
+
return { ok: false, dropped };
|
|
21028
|
+
}
|
|
21029
|
+
|
|
21030
|
+
// packages/omo-config-core/src/loader/layer-validation.ts
|
|
21031
|
+
function validationDiagnostic(path, issues) {
|
|
21032
|
+
const issuePaths = issues.map((issue) => issue.path.map((segment) => String(segment)).join("."));
|
|
21033
|
+
return {
|
|
21034
|
+
kind: "validation",
|
|
21035
|
+
message: `Invalid omo config at ${path}: ${issuePaths.join(", ")}`,
|
|
21036
|
+
path,
|
|
21037
|
+
issuePaths
|
|
21038
|
+
};
|
|
21039
|
+
}
|
|
21040
|
+
function invalidValueDiagnostics(path, dropped) {
|
|
21041
|
+
return dropped.map((entry) => ({
|
|
21042
|
+
kind: "invalid-value",
|
|
21043
|
+
message: `Ignored invalid value in ${path}: ${entry.key}: ${entry.message}`,
|
|
21044
|
+
path,
|
|
21045
|
+
issuePaths: [entry.key]
|
|
21046
|
+
}));
|
|
21047
|
+
}
|
|
21048
|
+
function unrecognizedKeyIssues(issues) {
|
|
21049
|
+
return issues.flatMap((issue) => issue.code === "unrecognized_keys" ? [{ keys: issue.keys, path: issue.path.map((segment) => String(segment)) }] : []);
|
|
21050
|
+
}
|
|
21051
|
+
function isRecord9(value) {
|
|
21052
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21053
|
+
}
|
|
21054
|
+
function sanitizeUnsafeKeys(value, path = []) {
|
|
21055
|
+
if (Array.isArray(value)) {
|
|
21056
|
+
const issues = [];
|
|
21057
|
+
const sanitized = value.map((entry, index) => {
|
|
21058
|
+
const nested = sanitizeUnsafeKeys(entry, [...path, String(index)]);
|
|
21059
|
+
issues.push(...nested.issues);
|
|
21060
|
+
return nested.value;
|
|
21061
|
+
});
|
|
21062
|
+
return { issues, value: sanitized };
|
|
21063
|
+
}
|
|
21064
|
+
if (!isRecord9(value))
|
|
21065
|
+
return { issues: [], value };
|
|
21066
|
+
const issues = [];
|
|
21067
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
|
|
21068
|
+
issues.push({ keys: ["__proto__"], path });
|
|
21069
|
+
}
|
|
21070
|
+
const sanitized = {};
|
|
21071
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
21072
|
+
if (isUnsafeObjectKey(key)) {
|
|
21073
|
+
issues.push({ keys: [key], path });
|
|
21074
|
+
continue;
|
|
21075
|
+
}
|
|
21076
|
+
const nested = sanitizeUnsafeKeys(entry, [...path, key]);
|
|
21077
|
+
issues.push(...nested.issues);
|
|
21078
|
+
sanitized[key] = nested.value;
|
|
21079
|
+
}
|
|
21080
|
+
return { issues, value: sanitized };
|
|
21081
|
+
}
|
|
21082
|
+
function containerAt(record, path) {
|
|
21083
|
+
let node = record;
|
|
21084
|
+
for (const segment of path) {
|
|
21085
|
+
if (Array.isArray(node)) {
|
|
21086
|
+
const index = Number(segment);
|
|
21087
|
+
if (!Number.isInteger(index) || index < 0 || index >= node.length)
|
|
21088
|
+
return null;
|
|
21089
|
+
node = node[index];
|
|
21090
|
+
} else if (isRecord9(node) && Object.hasOwn(node, segment)) {
|
|
21091
|
+
node = node[segment];
|
|
21092
|
+
} else {
|
|
21093
|
+
return null;
|
|
21094
|
+
}
|
|
21095
|
+
}
|
|
21096
|
+
return isRecord9(node) ? node : null;
|
|
21097
|
+
}
|
|
21098
|
+
function stripUnrecognizedKeys(record, issues) {
|
|
21099
|
+
const stripped = structuredClone(record);
|
|
21100
|
+
const issuePaths = [];
|
|
21101
|
+
for (const issue of issues) {
|
|
21102
|
+
const container = containerAt(stripped, issue.path);
|
|
21103
|
+
if (container === null)
|
|
21104
|
+
continue;
|
|
21105
|
+
for (const key of issue.keys) {
|
|
21106
|
+
delete container[key];
|
|
21107
|
+
issuePaths.push([...issue.path, key].join("."));
|
|
21108
|
+
}
|
|
21109
|
+
}
|
|
21110
|
+
return { issuePaths, stripped };
|
|
21111
|
+
}
|
|
21112
|
+
function toRecord(value) {
|
|
21113
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
21114
|
+
return null;
|
|
21115
|
+
const record = {};
|
|
21116
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
21117
|
+
record[key] = entry;
|
|
21118
|
+
}
|
|
21119
|
+
return record;
|
|
21120
|
+
}
|
|
21121
|
+
var validateLayerRecord = (record) => {
|
|
21122
|
+
const parsed = OmoConfigLayerSchema.safeParse(record);
|
|
21123
|
+
return parsed.success ? { success: true } : { success: false, issues: parsed.error.issues };
|
|
21124
|
+
};
|
|
21125
|
+
function validateConfigLayer(path, data) {
|
|
21126
|
+
const sanitized = sanitizeUnsafeKeys(data);
|
|
21127
|
+
const record = toRecord(sanitized.value);
|
|
21128
|
+
const unsafeIssuePaths = sanitized.issues.flatMap((issue) => issue.keys.map((key) => [...issue.path, key].join(".")));
|
|
21129
|
+
const unsafeDiagnostics = unsafeIssuePaths.length === 0 ? [] : [{ kind: "unknown-keys", message: `Ignored unknown keys in ${path}: ${unsafeIssuePaths.join(", ")}`, path, issuePaths: unsafeIssuePaths }];
|
|
21130
|
+
const validation = OmoConfigLayerSchema.safeParse(sanitized.value);
|
|
21131
|
+
if (validation.success) {
|
|
21132
|
+
if (record !== null)
|
|
21133
|
+
return { loaded: true, diagnostics: unsafeDiagnostics, value: record };
|
|
21134
|
+
return {
|
|
21135
|
+
loaded: false,
|
|
21136
|
+
diagnostics: [{ kind: "validation", message: `Invalid omo config at ${path}: root must be an object`, path }]
|
|
21137
|
+
};
|
|
21138
|
+
}
|
|
21139
|
+
const rejected = { loaded: false, diagnostics: [validationDiagnostic(path, validation.error.issues)] };
|
|
21140
|
+
const unknownIssues = unrecognizedKeyIssues(validation.error.issues);
|
|
21141
|
+
if (record === null)
|
|
21142
|
+
return rejected;
|
|
21143
|
+
let candidate = record;
|
|
21144
|
+
let issues = validation.error.issues;
|
|
21145
|
+
const diagnostics = [...unsafeDiagnostics];
|
|
21146
|
+
if (unknownIssues.length > 0) {
|
|
21147
|
+
const { issuePaths, stripped } = stripUnrecognizedKeys(record, unknownIssues);
|
|
21148
|
+
if (issuePaths.length > 0) {
|
|
21149
|
+
diagnostics.push({ kind: "unknown-keys", message: `Ignored unknown keys in ${path}: ${issuePaths.join(", ")}`, path, issuePaths });
|
|
21150
|
+
}
|
|
21151
|
+
const strippedValidation = validateLayerRecord(stripped);
|
|
21152
|
+
if (strippedValidation.success)
|
|
21153
|
+
return { loaded: true, diagnostics, value: stripped };
|
|
21154
|
+
candidate = stripped;
|
|
21155
|
+
issues = strippedValidation.issues;
|
|
21156
|
+
}
|
|
21157
|
+
const pruned = pruneInvalidConfigPaths(candidate, issues, validateLayerRecord);
|
|
21158
|
+
if (!pruned.ok)
|
|
21159
|
+
return rejected;
|
|
21160
|
+
return { loaded: true, diagnostics: [...diagnostics, ...invalidValueDiagnostics(path, pruned.dropped)], value: pruned.config };
|
|
21161
|
+
}
|
|
21162
|
+
|
|
20885
21163
|
// packages/omo-config-core/src/loader/paths.ts
|
|
20886
21164
|
import { userInfo } from "node:os";
|
|
20887
21165
|
import { dirname as dirname8, join as join18, posix, resolve as resolve7 } from "node:path";
|
|
@@ -20891,15 +21169,6 @@ function toPosixPath2(path) {
|
|
|
20891
21169
|
return path.split("\\").join("/");
|
|
20892
21170
|
}
|
|
20893
21171
|
|
|
20894
|
-
// packages/omo-config-core/src/loader/types.ts
|
|
20895
|
-
import { existsSync as existsSync3, lstatSync, readFileSync as readFileSync2, realpathSync as realpathSync2 } from "node:fs";
|
|
20896
|
-
var DEFAULT_READ_FILE_SYSTEM = {
|
|
20897
|
-
existsSync: existsSync3,
|
|
20898
|
-
lstatSync,
|
|
20899
|
-
readFileSync: readFileSync2,
|
|
20900
|
-
realpathSync: realpathSync2
|
|
20901
|
-
};
|
|
20902
|
-
|
|
20903
21172
|
// packages/omo-config-core/src/loader/paths.ts
|
|
20904
21173
|
var MAX_PROJECT_CONFIG_DIRECTORY_DEPTH = 256;
|
|
20905
21174
|
var ACCOUNT_HOME_DIR = userInfo().homedir;
|
|
@@ -20995,7 +21264,7 @@ function resolveOmoProfileName(options = {}) {
|
|
|
20995
21264
|
const env = options.env ?? process.env;
|
|
20996
21265
|
return profileName(options.profile) ?? profileName(env["OMO_PROFILE"]) ?? profileName(env["OCX_PROFILE"]) ?? profileNameFromOpenCodeConfigDir(env["OPENCODE_CONFIG_DIR"]);
|
|
20997
21266
|
}
|
|
20998
|
-
function
|
|
21267
|
+
function toRecord2(value) {
|
|
20999
21268
|
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
21000
21269
|
return;
|
|
21001
21270
|
return Object.fromEntries(Object.entries(value));
|
|
@@ -21016,13 +21285,13 @@ function harnessLayer(config, harness) {
|
|
|
21016
21285
|
const legacyKeys = Object.entries(OMO_CONFIG_LEGACY_HARNESS_ALIASES).filter(([, target]) => target === canonical).map(([legacy]) => harnessBlockKey(legacy));
|
|
21017
21286
|
let layer = {};
|
|
21018
21287
|
for (const key of [...legacyKeys, harnessBlockKey(canonical)]) {
|
|
21019
|
-
layer = mergeOmoConfigRecords(layer,
|
|
21288
|
+
layer = mergeOmoConfigRecords(layer, toRecord2(config[key]) ?? {});
|
|
21020
21289
|
}
|
|
21021
21290
|
return layer;
|
|
21022
21291
|
}
|
|
21023
21292
|
function resolveOmoConfigView(options) {
|
|
21024
|
-
const profiles =
|
|
21025
|
-
const profile = options.profile === undefined ? undefined :
|
|
21293
|
+
const profiles = toRecord2(options.config["profiles"]);
|
|
21294
|
+
const profile = options.profile === undefined ? undefined : toRecord2(profiles?.[options.profile]);
|
|
21026
21295
|
const diagnostics = profile === undefined && options.profile !== undefined ? [{
|
|
21027
21296
|
kind: "profile",
|
|
21028
21297
|
message: `Activated omo profile "${options.profile}" does not exist; using the base configuration`,
|
|
@@ -21077,70 +21346,9 @@ function stripResolutionControlKeys(config) {
|
|
|
21077
21346
|
} = config;
|
|
21078
21347
|
return resolved;
|
|
21079
21348
|
}
|
|
21080
|
-
function validationDiagnostic(path, issues) {
|
|
21081
|
-
const issuePaths = issues.map((issue) => issue.path.map((segment) => String(segment)).join("."));
|
|
21082
|
-
return {
|
|
21083
|
-
kind: "validation",
|
|
21084
|
-
message: `Invalid omo config at ${path}: ${issuePaths.join(", ")}`,
|
|
21085
|
-
path,
|
|
21086
|
-
issuePaths
|
|
21087
|
-
};
|
|
21088
|
-
}
|
|
21089
|
-
function unrecognizedKeyIssues(issues) {
|
|
21090
|
-
return issues.flatMap((issue) => issue.code === "unrecognized_keys" ? [{ keys: issue.keys, path: issue.path.map((segment) => String(segment)) }] : []);
|
|
21091
|
-
}
|
|
21092
|
-
function hasUnsafeUnrecognizedKey(issues) {
|
|
21093
|
-
return issues.some((issue) => issue.keys.some((key) => isUnsafeObjectKey(key)));
|
|
21094
|
-
}
|
|
21095
|
-
function hasTamperedPrototype(value) {
|
|
21096
|
-
if (Array.isArray(value))
|
|
21097
|
-
return value.some((entry) => hasTamperedPrototype(entry));
|
|
21098
|
-
if (!isRecord9(value))
|
|
21099
|
-
return false;
|
|
21100
|
-
const prototype = Object.getPrototypeOf(value);
|
|
21101
|
-
if (prototype !== Object.prototype && prototype !== null)
|
|
21102
|
-
return true;
|
|
21103
|
-
return Object.values(value).some((entry) => hasTamperedPrototype(entry));
|
|
21104
|
-
}
|
|
21105
|
-
function isRecord9(value) {
|
|
21106
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21107
|
-
}
|
|
21108
|
-
function containerAt(record, path) {
|
|
21109
|
-
let container = record;
|
|
21110
|
-
for (const segment of path) {
|
|
21111
|
-
const next = container[segment];
|
|
21112
|
-
if (!isRecord9(next))
|
|
21113
|
-
return null;
|
|
21114
|
-
container = next;
|
|
21115
|
-
}
|
|
21116
|
-
return container;
|
|
21117
|
-
}
|
|
21118
|
-
function stripUnrecognizedKeys(record, issues) {
|
|
21119
|
-
const stripped = structuredClone(record);
|
|
21120
|
-
const issuePaths = [];
|
|
21121
|
-
for (const issue of issues) {
|
|
21122
|
-
const container = containerAt(stripped, issue.path);
|
|
21123
|
-
if (container === null)
|
|
21124
|
-
continue;
|
|
21125
|
-
for (const key of issue.keys) {
|
|
21126
|
-
delete container[key];
|
|
21127
|
-
issuePaths.push([...issue.path, key].join("."));
|
|
21128
|
-
}
|
|
21129
|
-
}
|
|
21130
|
-
return { issuePaths, stripped };
|
|
21131
|
-
}
|
|
21132
|
-
function toRecord2(value) {
|
|
21133
|
-
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
21134
|
-
return null;
|
|
21135
|
-
const record = {};
|
|
21136
|
-
for (const [key, entry] of Object.entries(value)) {
|
|
21137
|
-
record[key] = entry;
|
|
21138
|
-
}
|
|
21139
|
-
return record;
|
|
21140
|
-
}
|
|
21141
21349
|
function readConfigSource(path, scope, fileSystem) {
|
|
21142
21350
|
if (!fileSystem.existsSync(path)) {
|
|
21143
|
-
return { source: { exists: false, loaded: false, path, scope } };
|
|
21351
|
+
return { diagnostics: [], source: { exists: false, loaded: false, path, scope } };
|
|
21144
21352
|
}
|
|
21145
21353
|
let content;
|
|
21146
21354
|
try {
|
|
@@ -21148,68 +21356,23 @@ function readConfigSource(path, scope, fileSystem) {
|
|
|
21148
21356
|
} catch (error) {
|
|
21149
21357
|
const message = error instanceof Error ? error.message : String(error);
|
|
21150
21358
|
return {
|
|
21151
|
-
|
|
21359
|
+
diagnostics: [{ kind: "read", message: `Failed to read ${path}: ${message}`, path }],
|
|
21152
21360
|
source: { exists: true, loaded: false, path, scope }
|
|
21153
21361
|
};
|
|
21154
21362
|
}
|
|
21155
21363
|
const parsed = parseJsoncSafe(content);
|
|
21156
21364
|
if (parsed.errors.length > 0) {
|
|
21157
21365
|
return {
|
|
21158
|
-
|
|
21366
|
+
diagnostics: [{
|
|
21159
21367
|
kind: "parse",
|
|
21160
21368
|
message: `JSONC parse error in ${path}: ${parsed.errors.map((error) => error.message).join(", ")}`,
|
|
21161
21369
|
path
|
|
21162
|
-
},
|
|
21370
|
+
}],
|
|
21163
21371
|
source: { exists: true, loaded: false, path, scope }
|
|
21164
21372
|
};
|
|
21165
21373
|
}
|
|
21166
|
-
|
|
21167
|
-
|
|
21168
|
-
diagnostic: { kind: "validation", message: `Invalid omo config at ${path}: "__proto__" member is not allowed`, path },
|
|
21169
|
-
source: { exists: true, loaded: false, path, scope }
|
|
21170
|
-
};
|
|
21171
|
-
}
|
|
21172
|
-
const parsedRecord = toRecord2(parsed.data);
|
|
21173
|
-
const validation = OmoConfigLayerSchema.safeParse(parsed.data);
|
|
21174
|
-
if (!validation.success) {
|
|
21175
|
-
const unrecognized = unrecognizedKeyIssues(validation.error.issues);
|
|
21176
|
-
if (hasUnsafeUnrecognizedKey(unrecognized)) {
|
|
21177
|
-
return {
|
|
21178
|
-
diagnostic: validationDiagnostic(path, validation.error.issues),
|
|
21179
|
-
source: { exists: true, loaded: false, path, scope }
|
|
21180
|
-
};
|
|
21181
|
-
}
|
|
21182
|
-
const rejected = {
|
|
21183
|
-
diagnostic: validationDiagnostic(path, validation.error.issues),
|
|
21184
|
-
source: { exists: true, loaded: false, path, scope }
|
|
21185
|
-
};
|
|
21186
|
-
const unknownIssues = unrecognizedKeyIssues(validation.error.issues);
|
|
21187
|
-
if (parsedRecord === null || unknownIssues.length === 0)
|
|
21188
|
-
return rejected;
|
|
21189
|
-
const { issuePaths, stripped } = stripUnrecognizedKeys(parsedRecord, unknownIssues);
|
|
21190
|
-
if (!OmoConfigLayerSchema.safeParse(stripped).success)
|
|
21191
|
-
return rejected;
|
|
21192
|
-
return {
|
|
21193
|
-
diagnostic: {
|
|
21194
|
-
kind: "unknown-keys",
|
|
21195
|
-
message: `Ignored unknown keys in ${path}: ${issuePaths.join(", ")}`,
|
|
21196
|
-
path,
|
|
21197
|
-
issuePaths
|
|
21198
|
-
},
|
|
21199
|
-
source: { exists: true, loaded: true, path, scope },
|
|
21200
|
-
value: stripped
|
|
21201
|
-
};
|
|
21202
|
-
}
|
|
21203
|
-
if (parsedRecord === null) {
|
|
21204
|
-
return {
|
|
21205
|
-
diagnostic: { kind: "validation", message: `Invalid omo config at ${path}: root must be an object`, path },
|
|
21206
|
-
source: { exists: true, loaded: false, path, scope }
|
|
21207
|
-
};
|
|
21208
|
-
}
|
|
21209
|
-
return {
|
|
21210
|
-
source: { exists: true, loaded: true, path, scope },
|
|
21211
|
-
value: parsedRecord
|
|
21212
|
-
};
|
|
21374
|
+
const layer = validateConfigLayer(path, parsed.data);
|
|
21375
|
+
return layer.loaded ? { diagnostics: layer.diagnostics, source: { exists: true, loaded: true, path, scope }, value: layer.value } : { diagnostics: layer.diagnostics, source: { exists: true, loaded: false, path, scope } };
|
|
21213
21376
|
}
|
|
21214
21377
|
function legacyCategoryDiagnostic(path, renames) {
|
|
21215
21378
|
const detail = renames.map((rename) => rename.dropped ? `${rename.path} ignored because ${rename.canonical} is also configured` : `${rename.path} renamed to ${rename.canonical}`).join(", ");
|
|
@@ -21244,8 +21407,7 @@ function loadOmoConfig(options = {}) {
|
|
|
21244
21407
|
})) {
|
|
21245
21408
|
const loaded = readConfigSource(candidate.path, candidate.scope, fileSystem);
|
|
21246
21409
|
sources.push(loaded.source);
|
|
21247
|
-
|
|
21248
|
-
diagnostics.push(loaded.diagnostic);
|
|
21410
|
+
diagnostics.push(...loaded.diagnostics);
|
|
21249
21411
|
if (loaded.value !== undefined) {
|
|
21250
21412
|
const canonicalized = canonicalizeLegacyCategoryNames(loaded.value);
|
|
21251
21413
|
if (canonicalized.renames.length > 0) {
|
|
@@ -21268,7 +21430,8 @@ function loadOmoConfig(options = {}) {
|
|
|
21268
21430
|
...options.harness === undefined ? {} : { harness: options.harness },
|
|
21269
21431
|
...requestedProfile === undefined ? {} : { profile: requestedProfile }
|
|
21270
21432
|
});
|
|
21271
|
-
const
|
|
21433
|
+
const finalInput = mergeOmoConfigRecords(DEFAULT_RAW_CONFIG, resolved.config);
|
|
21434
|
+
const finalConfig = OmoConfigSchema.safeParse(finalInput);
|
|
21272
21435
|
if (finalConfig.success) {
|
|
21273
21436
|
return {
|
|
21274
21437
|
config: stripResolutionControlKeys(finalConfig.data),
|
|
@@ -21278,9 +21441,22 @@ function loadOmoConfig(options = {}) {
|
|
|
21278
21441
|
sources
|
|
21279
21442
|
};
|
|
21280
21443
|
}
|
|
21444
|
+
const pruned = pruneInvalidConfigPaths(finalInput, finalConfig.error.issues, (record) => {
|
|
21445
|
+
const parsed = OmoConfigSchema.safeParse(record);
|
|
21446
|
+
return parsed.success ? { success: true } : { success: false, issues: parsed.error.issues };
|
|
21447
|
+
});
|
|
21448
|
+
if (pruned.ok) {
|
|
21449
|
+
return {
|
|
21450
|
+
config: stripResolutionControlKeys(OmoConfigSchema.parse(pruned.config)),
|
|
21451
|
+
diagnostics: [...diagnostics, ...resolved.diagnostics, ...invalidValueDiagnostics(MERGED_OMO_CONFIG_PATH, pruned.dropped)],
|
|
21452
|
+
layers,
|
|
21453
|
+
...resolved.profile === undefined ? {} : { profile: resolved.profile },
|
|
21454
|
+
sources
|
|
21455
|
+
};
|
|
21456
|
+
}
|
|
21281
21457
|
return {
|
|
21282
21458
|
config: stripResolutionControlKeys(OmoConfigSchema.parse(DEFAULT_RAW_CONFIG)),
|
|
21283
|
-
diagnostics: [...diagnostics, ...resolved.diagnostics, validationDiagnostic(
|
|
21459
|
+
diagnostics: [...diagnostics, ...resolved.diagnostics, validationDiagnostic(MERGED_OMO_CONFIG_PATH, finalConfig.error.issues)],
|
|
21284
21460
|
layers,
|
|
21285
21461
|
...resolved.profile === undefined ? {} : { profile: resolved.profile },
|
|
21286
21462
|
sources
|