mthds 0.6.3 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/binaries.js +2 -2
- package/dist/agent/commands/bootstrap.js +2 -10
- package/dist/agent/commands/bootstrap.js.map +1 -1
- package/dist/agent/commands/codex-config.d.ts +29 -15
- package/dist/agent/commands/codex-config.js +206 -127
- package/dist/agent/commands/codex-config.js.map +1 -1
- package/dist/agent/commands/codex-hook.d.ts +4 -6
- package/dist/agent/commands/codex-hook.js +6 -8
- package/dist/agent/commands/codex-hook.js.map +1 -1
- package/dist/agent/commands/codex.d.ts +32 -19
- package/dist/agent/commands/codex.js +87 -134
- package/dist/agent/commands/codex.js.map +1 -1
- package/dist/agent/commands/doctor.js +49 -13
- package/dist/agent/commands/doctor.js.map +1 -1
- package/dist/agent/commands/update-check.js +1 -30
- package/dist/agent/commands/update-check.js.map +1 -1
- package/dist/agent/commands/upgrade.js +3 -12
- package/dist/agent/commands/upgrade.js.map +1 -1
- package/dist/agent/plugin-version.d.ts +19 -17
- package/dist/agent/plugin-version.js +21 -20
- package/dist/agent/plugin-version.js.map +1 -1
- package/dist/agent/snooze.d.ts +30 -4
- package/dist/agent/snooze.js +99 -35
- package/dist/agent/snooze.js.map +1 -1
- package/dist/agent/update-cache.d.ts +59 -15
- package/dist/agent/update-cache.js +178 -24
- package/dist/agent/update-cache.js.map +1 -1
- package/dist/agent-cli.js +2 -10
- package/dist/agent-cli.js.map +1 -1
- package/package.json +1 -1
package/dist/agent/binaries.js
CHANGED
|
@@ -22,7 +22,7 @@ const VERSION_RE = /^[\w-]+\s+(\d+\.\d+\.\d+)/;
|
|
|
22
22
|
const PIPELEX_PKG = {
|
|
23
23
|
package: "pipelex",
|
|
24
24
|
uv_package: "pipelex",
|
|
25
|
-
version_constraint: ">=0.
|
|
25
|
+
version_constraint: ">=0.28.0",
|
|
26
26
|
version_extract: VERSION_RE,
|
|
27
27
|
install_url: "https://pypi.org/project/pipelex/",
|
|
28
28
|
auto_installable: true,
|
|
@@ -31,7 +31,7 @@ const PIPELEX_PKG = {
|
|
|
31
31
|
const PIPELEX_TOOLS_PKG = {
|
|
32
32
|
package: "pipelex-tools",
|
|
33
33
|
uv_package: "pipelex-tools",
|
|
34
|
-
version_constraint: ">=0.
|
|
34
|
+
version_constraint: ">=0.4.0",
|
|
35
35
|
version_extract: VERSION_RE,
|
|
36
36
|
install_url: "https://pypi.org/project/pipelex-tools/",
|
|
37
37
|
auto_installable: true,
|
|
@@ -12,13 +12,11 @@
|
|
|
12
12
|
* - BOOTSTRAP_PARTIAL <json> -- some targets installed, some failed
|
|
13
13
|
* - BOOTSTRAP_FAILED <json> -- all targets failed
|
|
14
14
|
*/
|
|
15
|
-
import { writeFileSync } from "node:fs";
|
|
16
|
-
import { join } from "node:path";
|
|
17
15
|
import { isUvInstalled, installUv, uvToolInstallSync } from "../../installer/runtime/installer.js";
|
|
18
16
|
import { checkBinaryVersion } from "../../installer/runtime/version-check.js";
|
|
19
17
|
import { BINARY_RECOVERY } from "../binaries.js";
|
|
20
18
|
import { agentError, AGENT_ERROR_DOMAINS } from "../output.js";
|
|
21
|
-
import { clearCache,
|
|
19
|
+
import { clearCache, writeUpgradeMarker } from "../update-cache.js";
|
|
22
20
|
import { clearSnooze } from "../snooze.js";
|
|
23
21
|
import { loadConfig } from "../../config/config.js";
|
|
24
22
|
import { Runners } from "../../runners/types.js";
|
|
@@ -136,13 +134,7 @@ export async function agentBootstrap(options = {}) {
|
|
|
136
134
|
const allSucceeded = failed.size === 0;
|
|
137
135
|
const allFailed = succeeded.size === 0;
|
|
138
136
|
if (allSucceeded) {
|
|
139
|
-
|
|
140
|
-
ensureStateDir();
|
|
141
|
-
writeFileSync(join(STATE_DIR, "just-upgraded-from"), JSON.stringify(markerData), "utf-8");
|
|
142
|
-
}
|
|
143
|
-
catch (err) {
|
|
144
|
-
process.stderr.write(`Warning: could not write upgrade marker: ${errorMsg(err)}.\n`);
|
|
145
|
-
}
|
|
137
|
+
writeUpgradeMarker(markerData);
|
|
146
138
|
clearCache();
|
|
147
139
|
clearSnooze();
|
|
148
140
|
process.stdout.write("BOOTSTRAP_COMPLETE " + JSON.stringify({ installed: installedEntries }) + "\n");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../src/agent/commands/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../src/agent/commands/bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,31 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* mthds-agent codex apply-config —
|
|
3
|
-
* settings into ~/.codex/config.toml so the mthds PostToolUse hook can run
|
|
4
|
-
* without being blocked by Codex's default workspace-write sandbox.
|
|
2
|
+
* mthds-agent codex apply-config — make ~/.codex/ correct for the mthds plugin.
|
|
5
3
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Two jobs:
|
|
5
|
+
* 1. Additively merge required keys into ~/.codex/config.toml:
|
|
6
|
+
* [sandbox_workspace_write] network_access = true
|
|
7
|
+
* — Codex's default workspace-write sandbox blocks outbound network for
|
|
8
|
+
* hook commands; without it any remote fetch hangs/fails.
|
|
9
|
+
* [features] plugin_hooks = true
|
|
10
|
+
* — plugin-bundled hooks are opt-in; without it Codex never loads the
|
|
11
|
+
* mthds validation hook shipped inside the plugin.
|
|
12
|
+
* 2. Remove any obsolete mthds entry left in ~/.codex/hooks.json by the retired
|
|
13
|
+
* `install-hook` command (see codex.ts) — it would double-fire alongside the
|
|
14
|
+
* plugin-bundled hook.
|
|
9
15
|
*
|
|
10
|
-
* Warning-only checks (
|
|
11
|
-
* - `[features]
|
|
12
|
-
*
|
|
13
|
-
* - `sandbox_mode = "read-only"` —
|
|
16
|
+
* Warning-only checks (never modified — too high-risk):
|
|
17
|
+
* - `[features] hooks = false` (or its alias `codex_hooks = false`) disables
|
|
18
|
+
* hooks entirely; we check both keys defensively.
|
|
19
|
+
* - `sandbox_mode = "read-only"` — apply_patch can't run, so the hook can't
|
|
20
|
+
* either.
|
|
14
21
|
*
|
|
15
22
|
* Output statuses (via agentSuccess):
|
|
16
|
-
* - { status: "ALREADY_OK",
|
|
17
|
-
* - { status: "APPLIED",
|
|
18
|
-
* - { status: "WOULD_APPLY",
|
|
23
|
+
* - { status: "ALREADY_OK", ... } — nothing needed changing
|
|
24
|
+
* - { status: "APPLIED", ... } — config.toml merged and/or stale hook removed
|
|
25
|
+
* - { status: "WOULD_APPLY", ... } — --dry-run only
|
|
19
26
|
*
|
|
20
27
|
* Flags:
|
|
21
28
|
* --check exits non-zero if anything would change (no writes, no warnings demoted)
|
|
22
|
-
* --dry-run prints proposed diff and exits 0 without touching
|
|
29
|
+
* --dry-run prints proposed diff and exits 0 without touching any file
|
|
23
30
|
*/
|
|
24
31
|
export interface AppliedChange {
|
|
25
32
|
table: string;
|
|
26
33
|
key: string;
|
|
27
34
|
value: string;
|
|
28
35
|
}
|
|
36
|
+
export interface SettingConflict {
|
|
37
|
+
table: string;
|
|
38
|
+
key: string;
|
|
39
|
+
current: string;
|
|
40
|
+
required: string;
|
|
41
|
+
}
|
|
29
42
|
export interface CodexConfigWarning {
|
|
30
43
|
code: string;
|
|
31
44
|
message: string;
|
|
@@ -33,7 +46,8 @@ export interface CodexConfigWarning {
|
|
|
33
46
|
export interface CodexConfigInspection {
|
|
34
47
|
config_file: string;
|
|
35
48
|
exists: boolean;
|
|
36
|
-
|
|
49
|
+
needs_changes: AppliedChange[];
|
|
50
|
+
conflicts: SettingConflict[];
|
|
37
51
|
warnings: CodexConfigWarning[];
|
|
38
52
|
parse_error?: string;
|
|
39
53
|
}
|
|
@@ -1,41 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* mthds-agent codex apply-config —
|
|
3
|
-
* settings into ~/.codex/config.toml so the mthds PostToolUse hook can run
|
|
4
|
-
* without being blocked by Codex's default workspace-write sandbox.
|
|
2
|
+
* mthds-agent codex apply-config — make ~/.codex/ correct for the mthds plugin.
|
|
5
3
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Two jobs:
|
|
5
|
+
* 1. Additively merge required keys into ~/.codex/config.toml:
|
|
6
|
+
* [sandbox_workspace_write] network_access = true
|
|
7
|
+
* — Codex's default workspace-write sandbox blocks outbound network for
|
|
8
|
+
* hook commands; without it any remote fetch hangs/fails.
|
|
9
|
+
* [features] plugin_hooks = true
|
|
10
|
+
* — plugin-bundled hooks are opt-in; without it Codex never loads the
|
|
11
|
+
* mthds validation hook shipped inside the plugin.
|
|
12
|
+
* 2. Remove any obsolete mthds entry left in ~/.codex/hooks.json by the retired
|
|
13
|
+
* `install-hook` command (see codex.ts) — it would double-fire alongside the
|
|
14
|
+
* plugin-bundled hook.
|
|
9
15
|
*
|
|
10
|
-
* Warning-only checks (
|
|
11
|
-
* - `[features]
|
|
12
|
-
*
|
|
13
|
-
* - `sandbox_mode = "read-only"` —
|
|
16
|
+
* Warning-only checks (never modified — too high-risk):
|
|
17
|
+
* - `[features] hooks = false` (or its alias `codex_hooks = false`) disables
|
|
18
|
+
* hooks entirely; we check both keys defensively.
|
|
19
|
+
* - `sandbox_mode = "read-only"` — apply_patch can't run, so the hook can't
|
|
20
|
+
* either.
|
|
14
21
|
*
|
|
15
22
|
* Output statuses (via agentSuccess):
|
|
16
|
-
* - { status: "ALREADY_OK",
|
|
17
|
-
* - { status: "APPLIED",
|
|
18
|
-
* - { status: "WOULD_APPLY",
|
|
23
|
+
* - { status: "ALREADY_OK", ... } — nothing needed changing
|
|
24
|
+
* - { status: "APPLIED", ... } — config.toml merged and/or stale hook removed
|
|
25
|
+
* - { status: "WOULD_APPLY", ... } — --dry-run only
|
|
19
26
|
*
|
|
20
27
|
* Flags:
|
|
21
28
|
* --check exits non-zero if anything would change (no writes, no warnings demoted)
|
|
22
|
-
* --dry-run prints proposed diff and exits 0 without touching
|
|
29
|
+
* --dry-run prints proposed diff and exits 0 without touching any file
|
|
23
30
|
*/
|
|
24
31
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
25
32
|
import { dirname, join } from "node:path";
|
|
26
33
|
import { homedir } from "node:os";
|
|
27
34
|
import { parse as parseToml } from "smol-toml";
|
|
28
35
|
import { agentError, agentSuccess, AGENT_ERROR_DOMAINS } from "../output.js";
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// second required key (e.g. a sandbox_mode default), both will need to
|
|
35
|
-
// fan out to a list rather than the singleton structure used here.
|
|
36
|
-
const REQUIRED_TABLE = "sandbox_workspace_write";
|
|
37
|
-
const REQUIRED_KEY = "network_access";
|
|
38
|
-
const REQUIRED_VALUE = true;
|
|
36
|
+
import { inspectLegacyCodexHook, removeLegacyCodexHook } from "./codex.js";
|
|
37
|
+
const REQUIRED_SETTINGS = [
|
|
38
|
+
{ table: "sandbox_workspace_write", key: "network_access", value: true },
|
|
39
|
+
{ table: "features", key: "plugin_hooks", value: true },
|
|
40
|
+
];
|
|
39
41
|
// ── Helpers ────────────────────────────────────────────────────────
|
|
40
42
|
function configFilePath() {
|
|
41
43
|
return join(homedir(), ".codex", "config.toml");
|
|
@@ -46,9 +48,13 @@ function writeAtomic(path, contents) {
|
|
|
46
48
|
writeFileSync(tmp, contents, { encoding: "utf8", mode: 0o644 });
|
|
47
49
|
renameSync(tmp, path);
|
|
48
50
|
}
|
|
51
|
+
/** Parse TOML text, treating empty/whitespace-only input as an empty table. */
|
|
52
|
+
function parseTomlOrEmpty(text) {
|
|
53
|
+
return text.trim().length === 0 ? {} : parseToml(text);
|
|
54
|
+
}
|
|
49
55
|
/**
|
|
50
|
-
* Append a [table] section with key=value to existing TOML text. Used when
|
|
51
|
-
*
|
|
56
|
+
* Append a [table] section with key=value to existing TOML text. Used when the
|
|
57
|
+
* table is missing entirely. We append rather than re-serialize so user
|
|
52
58
|
* formatting/comments elsewhere in the file are preserved verbatim.
|
|
53
59
|
*/
|
|
54
60
|
function appendTomlTable(existing, table, key, value) {
|
|
@@ -57,22 +63,22 @@ function appendTomlTable(existing, table, key, value) {
|
|
|
57
63
|
return `${trimmed}${sep}[${table}]\n${key} = ${value}\n`;
|
|
58
64
|
}
|
|
59
65
|
/**
|
|
60
|
-
* Insert key=value into an existing [table] section without re-serializing
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
66
|
+
* Insert key=value into an existing [table] section without re-serializing the
|
|
67
|
+
* document. Locates the table header line, finds the end of its body (next
|
|
68
|
+
* [section] header or EOF), and inserts the line just before that boundary.
|
|
69
|
+
* This preserves comments and ordering of every other table.
|
|
64
70
|
*/
|
|
65
71
|
function insertIntoExistingTable(existing, table, key, value) {
|
|
66
72
|
const lines = existing.split("\n");
|
|
67
|
-
const headerRegex = new RegExp(`^\\s*\\[\\s*${table.replace(/[.*+?^${}()|[\\]
|
|
68
|
-
// Treat both `[table]` and `[[array_of_tables]]` as section boundaries —
|
|
69
|
-
//
|
|
73
|
+
const headerRegex = new RegExp(`^\\s*\\[\\s*${table.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\s*\\]\\s*(#.*)?$`);
|
|
74
|
+
// Treat both `[table]` and `[[array_of_tables]]` as section boundaries — the
|
|
75
|
+
// inner `\[\[?...\]\]?` lets the boundary scan stop at array-of-tables
|
|
70
76
|
// headers too, so we don't accidentally insert into one.
|
|
71
77
|
const anyHeaderRegex = /^\s*\[\[?[^\]]+\]\]?\s*(#.*)?$/;
|
|
72
78
|
let tableStart = -1;
|
|
73
|
-
for (let
|
|
74
|
-
if (headerRegex.test(lines[
|
|
75
|
-
tableStart =
|
|
79
|
+
for (let index = 0; index < lines.length; index++) {
|
|
80
|
+
if (headerRegex.test(lines[index])) {
|
|
81
|
+
tableStart = index;
|
|
76
82
|
break;
|
|
77
83
|
}
|
|
78
84
|
}
|
|
@@ -81,9 +87,9 @@ function insertIntoExistingTable(existing, table, key, value) {
|
|
|
81
87
|
return appendTomlTable(existing, table, key, value);
|
|
82
88
|
}
|
|
83
89
|
let insertAt = lines.length;
|
|
84
|
-
for (let
|
|
85
|
-
if (anyHeaderRegex.test(lines[
|
|
86
|
-
insertAt =
|
|
90
|
+
for (let index = tableStart + 1; index < lines.length; index++) {
|
|
91
|
+
if (anyHeaderRegex.test(lines[index])) {
|
|
92
|
+
insertAt = index;
|
|
87
93
|
break;
|
|
88
94
|
}
|
|
89
95
|
}
|
|
@@ -93,40 +99,61 @@ function insertIntoExistingTable(existing, table, key, value) {
|
|
|
93
99
|
}
|
|
94
100
|
const before = lines.slice(0, insertAt);
|
|
95
101
|
const after = lines.slice(insertAt);
|
|
96
|
-
|
|
97
|
-
|
|
102
|
+
return [...before, `${key} = ${value}`, ...after].join("\n");
|
|
103
|
+
}
|
|
104
|
+
function readSettingValue(parsed, setting) {
|
|
105
|
+
const table = parsed[setting.table];
|
|
106
|
+
if (table && typeof table === "object" && !Array.isArray(table)) {
|
|
107
|
+
return table[setting.key];
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
98
110
|
}
|
|
99
111
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
112
|
+
* Compare the parsed config against REQUIRED_SETTINGS:
|
|
113
|
+
* - missing key → an AppliedChange to add it
|
|
114
|
+
* - wrong value → a SettingConflict (the user must hand-fix; we never flip
|
|
115
|
+
* a key that is explicitly set)
|
|
116
|
+
* - right value → satisfied, ignored
|
|
103
117
|
*/
|
|
104
|
-
function
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
118
|
+
function evaluateSettings(parsed) {
|
|
119
|
+
const changes = [];
|
|
120
|
+
const conflicts = [];
|
|
121
|
+
for (const setting of REQUIRED_SETTINGS) {
|
|
122
|
+
const current = readSettingValue(parsed, setting);
|
|
123
|
+
if (current === setting.value)
|
|
124
|
+
continue;
|
|
125
|
+
if (current === undefined) {
|
|
126
|
+
changes.push({ table: setting.table, key: setting.key, value: String(setting.value) });
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
conflicts.push({
|
|
130
|
+
table: setting.table,
|
|
131
|
+
key: setting.key,
|
|
132
|
+
current: JSON.stringify(current),
|
|
133
|
+
required: String(setting.value),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
111
136
|
}
|
|
112
|
-
return {
|
|
113
|
-
table: REQUIRED_TABLE,
|
|
114
|
-
key: REQUIRED_KEY,
|
|
115
|
-
value: String(REQUIRED_VALUE),
|
|
116
|
-
};
|
|
137
|
+
return { changes, conflicts };
|
|
117
138
|
}
|
|
118
139
|
/** Collect non-fatal warnings about the user's config without modifying it. */
|
|
119
140
|
function collectWarnings(parsed) {
|
|
120
141
|
const warnings = [];
|
|
121
142
|
const features = parsed.features;
|
|
122
|
-
if (features &&
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
143
|
+
if (features && typeof features === "object" && !Array.isArray(features)) {
|
|
144
|
+
const featuresTable = features;
|
|
145
|
+
// Check both `hooks` and its alias `codex_hooks` defensively. Either being
|
|
146
|
+
// explicitly false disables hooks entirely and breaks the mthds hook. When
|
|
147
|
+
// both are false, name both so neither is silently omitted.
|
|
148
|
+
const disabledKeys = ["hooks", "codex_hooks"].filter((key) => featuresTable[key] === false);
|
|
149
|
+
if (disabledKeys.length > 0) {
|
|
150
|
+
const keyList = disabledKeys.map((key) => `[features] ${key}`).join(" and ");
|
|
151
|
+
const plural = disabledKeys.length > 1;
|
|
152
|
+
warnings.push({
|
|
153
|
+
code: "CODEX_HOOKS_DISABLED",
|
|
154
|
+
message: `${keyList} ${plural ? "are" : "is"} explicitly set to false; the mthds hook will not load. Remove ${plural ? "these keys" : "this key"} — hooks are enabled by default.`,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
130
157
|
}
|
|
131
158
|
if (parsed.sandbox_mode === "read-only") {
|
|
132
159
|
warnings.push({
|
|
@@ -136,6 +163,27 @@ function collectWarnings(parsed) {
|
|
|
136
163
|
}
|
|
137
164
|
return warnings;
|
|
138
165
|
}
|
|
166
|
+
function legacyHookWarning(parseError) {
|
|
167
|
+
return {
|
|
168
|
+
code: "LEGACY_HOOK_UNREADABLE",
|
|
169
|
+
message: `Could not read ~/.codex/hooks.json to remove any obsolete mthds hook entry (${parseError}). If you previously ran \`mthds-agent codex install-hook\`, delete that entry by hand so the validation hook does not run twice.`,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/** Apply each change to the TOML text in sequence, re-parsing between changes
|
|
173
|
+
* so the table-exists decision reflects edits already made. */
|
|
174
|
+
function applyChanges(raw, changes) {
|
|
175
|
+
let next = raw;
|
|
176
|
+
for (const change of changes) {
|
|
177
|
+
const parsed = parseTomlOrEmpty(next);
|
|
178
|
+
const table = parsed[change.table];
|
|
179
|
+
const tableExists = table !== undefined && typeof table === "object" && !Array.isArray(table);
|
|
180
|
+
next = tableExists
|
|
181
|
+
? insertIntoExistingTable(next, change.table, change.key, change.value)
|
|
182
|
+
: appendTomlTable(next, change.table, change.key, change.value);
|
|
183
|
+
}
|
|
184
|
+
return next;
|
|
185
|
+
}
|
|
186
|
+
// ── Read-only inspection ───────────────────────────────────────────
|
|
139
187
|
/**
|
|
140
188
|
* Read-only inspection of ~/.codex/config.toml. Used by doctor to surface
|
|
141
189
|
* issues without writing anything. Never throws — parse errors are reported
|
|
@@ -145,15 +193,16 @@ export function inspectCodexConfig() {
|
|
|
145
193
|
const file = configFilePath();
|
|
146
194
|
const exists = existsSync(file);
|
|
147
195
|
if (!exists) {
|
|
148
|
-
// No config file ⇒
|
|
196
|
+
// No config file ⇒ every required key is missing.
|
|
149
197
|
return {
|
|
150
198
|
config_file: file,
|
|
151
199
|
exists: false,
|
|
152
|
-
|
|
153
|
-
table:
|
|
154
|
-
key:
|
|
155
|
-
value: String(
|
|
156
|
-
},
|
|
200
|
+
needs_changes: REQUIRED_SETTINGS.map((setting) => ({
|
|
201
|
+
table: setting.table,
|
|
202
|
+
key: setting.key,
|
|
203
|
+
value: String(setting.value),
|
|
204
|
+
})),
|
|
205
|
+
conflicts: [],
|
|
157
206
|
warnings: [],
|
|
158
207
|
};
|
|
159
208
|
}
|
|
@@ -165,20 +214,22 @@ export function inspectCodexConfig() {
|
|
|
165
214
|
return {
|
|
166
215
|
config_file: file,
|
|
167
216
|
exists: true,
|
|
168
|
-
|
|
217
|
+
needs_changes: [],
|
|
218
|
+
conflicts: [],
|
|
169
219
|
warnings: [],
|
|
170
220
|
parse_error: `Failed to read ${file}: ${err.message}`,
|
|
171
221
|
};
|
|
172
222
|
}
|
|
173
223
|
let parsed;
|
|
174
224
|
try {
|
|
175
|
-
parsed =
|
|
225
|
+
parsed = parseTomlOrEmpty(raw);
|
|
176
226
|
}
|
|
177
227
|
catch (err) {
|
|
178
228
|
return {
|
|
179
229
|
config_file: file,
|
|
180
230
|
exists: true,
|
|
181
|
-
|
|
231
|
+
needs_changes: [],
|
|
232
|
+
conflicts: [],
|
|
182
233
|
warnings: [],
|
|
183
234
|
parse_error: err.message,
|
|
184
235
|
};
|
|
@@ -187,15 +238,18 @@ export function inspectCodexConfig() {
|
|
|
187
238
|
return {
|
|
188
239
|
config_file: file,
|
|
189
240
|
exists: true,
|
|
190
|
-
|
|
241
|
+
needs_changes: [],
|
|
242
|
+
conflicts: [],
|
|
191
243
|
warnings: [],
|
|
192
244
|
parse_error: "Top-level value is not a TOML table",
|
|
193
245
|
};
|
|
194
246
|
}
|
|
247
|
+
const { changes, conflicts } = evaluateSettings(parsed);
|
|
195
248
|
return {
|
|
196
249
|
config_file: file,
|
|
197
250
|
exists: true,
|
|
198
|
-
|
|
251
|
+
needs_changes: changes,
|
|
252
|
+
conflicts,
|
|
199
253
|
warnings: collectWarnings(parsed),
|
|
200
254
|
};
|
|
201
255
|
}
|
|
@@ -210,92 +264,117 @@ export async function agentCodexApplyConfig(options = {}) {
|
|
|
210
264
|
raw = readFileSync(file, "utf8");
|
|
211
265
|
}
|
|
212
266
|
catch (err) {
|
|
213
|
-
agentError(`Failed to read ${file}: ${err.message}`, "IOError", {
|
|
267
|
+
agentError(`Failed to read ${file}: ${err.message}`, "IOError", {
|
|
268
|
+
error_domain: AGENT_ERROR_DOMAINS.IO,
|
|
269
|
+
});
|
|
214
270
|
return;
|
|
215
271
|
}
|
|
216
272
|
}
|
|
217
273
|
let parsed;
|
|
218
274
|
try {
|
|
219
|
-
parsed =
|
|
275
|
+
parsed = parseTomlOrEmpty(raw);
|
|
220
276
|
}
|
|
221
277
|
catch (err) {
|
|
222
278
|
agentError(`Invalid TOML in ${file}: ${err.message}. Fix the file by hand or delete it and re-run.`, "ConfigError", { error_domain: AGENT_ERROR_DOMAINS.CONFIG });
|
|
223
279
|
return;
|
|
224
280
|
}
|
|
225
281
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
226
|
-
agentError(`${file} does not contain a TOML table at the top level.`, "ConfigError", {
|
|
282
|
+
agentError(`${file} does not contain a TOML table at the top level.`, "ConfigError", {
|
|
283
|
+
error_domain: AGENT_ERROR_DOMAINS.CONFIG,
|
|
284
|
+
});
|
|
227
285
|
return;
|
|
228
286
|
}
|
|
229
|
-
const
|
|
287
|
+
const { changes, conflicts } = evaluateSettings(parsed);
|
|
230
288
|
const warnings = collectWarnings(parsed);
|
|
231
|
-
//
|
|
232
|
-
//
|
|
289
|
+
// A key explicitly set to a conflicting value is a hard error in every mode:
|
|
290
|
+
// apply-config never overrides an explicit user choice.
|
|
291
|
+
if (conflicts.length > 0) {
|
|
292
|
+
const lines = conflicts.map((conflict) => ` [${conflict.table}] ${conflict.key} = ${conflict.current} (the mthds plugin needs ${conflict.required})`);
|
|
293
|
+
agentError(`~/.codex/config.toml has settings that conflict with the mthds plugin:\n${lines.join("\n")}\nChange them by hand, then re-run \`mthds-agent codex apply-config\`.`, "ConfigError", { error_domain: AGENT_ERROR_DOMAINS.CONFIG });
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
// ── --check mode: report only, exit non-zero if anything needs attention ──
|
|
233
297
|
if (checkMode) {
|
|
234
|
-
|
|
298
|
+
const legacy = inspectLegacyCodexHook();
|
|
299
|
+
const needsAttention = changes.length > 0 ||
|
|
300
|
+
warnings.length > 0 ||
|
|
301
|
+
legacy.has_legacy_entry ||
|
|
302
|
+
legacy.parse_error !== undefined;
|
|
303
|
+
if (needsAttention) {
|
|
235
304
|
agentError(`Codex config needs attention. Run 'mthds-agent codex apply-config' (and review warnings).`, "ConfigError", { error_domain: AGENT_ERROR_DOMAINS.CONFIG });
|
|
236
305
|
return;
|
|
237
306
|
}
|
|
238
|
-
agentSuccess({ status: "ALREADY_OK", config_file: file });
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
if (!change) {
|
|
242
307
|
agentSuccess({
|
|
243
308
|
status: "ALREADY_OK",
|
|
244
309
|
config_file: file,
|
|
245
|
-
|
|
310
|
+
applied: [],
|
|
311
|
+
legacy_hook: { hooks_file: legacy.hooks_file, status: "absent" },
|
|
312
|
+
warnings: [],
|
|
246
313
|
});
|
|
247
314
|
return;
|
|
248
315
|
}
|
|
249
|
-
//
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (tableExists) {
|
|
265
|
-
nextRaw = insertIntoExistingTable(raw, change.table, change.key, change.value);
|
|
266
|
-
}
|
|
267
|
-
else {
|
|
268
|
-
nextRaw = appendTomlTable(raw, change.table, change.key, change.value);
|
|
269
|
-
}
|
|
270
|
-
// Sanity-parse the new contents before committing.
|
|
271
|
-
try {
|
|
272
|
-
parseToml(nextRaw);
|
|
273
|
-
}
|
|
274
|
-
catch (err) {
|
|
275
|
-
agentError(`Generated config would not re-parse: ${err.message}`, "ConfigError", { error_domain: AGENT_ERROR_DOMAINS.CONFIG });
|
|
276
|
-
return;
|
|
316
|
+
// Validate the prospective config.toml contents before any write.
|
|
317
|
+
let nextRaw = raw;
|
|
318
|
+
if (changes.length > 0) {
|
|
319
|
+
try {
|
|
320
|
+
nextRaw = applyChanges(raw, changes);
|
|
321
|
+
// Sanity-parse: an implicit table created by a dotted-key header can make
|
|
322
|
+
// appendTomlTable emit a duplicate header that smol-toml rejects.
|
|
323
|
+
// applyChanges itself re-parses between changes, so a malformed
|
|
324
|
+
// intermediate state throws here too — caught the same way.
|
|
325
|
+
parseToml(nextRaw);
|
|
326
|
+
}
|
|
327
|
+
catch (err) {
|
|
328
|
+
agentError(`Generated config would not re-parse: ${err.message}`, "ConfigError", { error_domain: AGENT_ERROR_DOMAINS.CONFIG });
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
277
331
|
}
|
|
332
|
+
// ── --dry-run mode: report the proposed diff, write nothing ──
|
|
278
333
|
if (dryRunMode) {
|
|
334
|
+
const legacy = inspectLegacyCodexHook();
|
|
335
|
+
const allWarnings = legacy.parse_error !== undefined
|
|
336
|
+
? [...warnings, legacyHookWarning(legacy.parse_error)]
|
|
337
|
+
: warnings;
|
|
338
|
+
const wouldChange = changes.length > 0 || legacy.has_legacy_entry;
|
|
279
339
|
agentSuccess({
|
|
280
|
-
status: "WOULD_APPLY",
|
|
340
|
+
status: wouldChange ? "WOULD_APPLY" : "ALREADY_OK",
|
|
281
341
|
config_file: file,
|
|
282
|
-
applied:
|
|
283
|
-
|
|
342
|
+
applied: changes,
|
|
343
|
+
legacy_hook: {
|
|
344
|
+
hooks_file: legacy.hooks_file,
|
|
345
|
+
status: legacy.has_legacy_entry
|
|
346
|
+
? "would-remove"
|
|
347
|
+
: legacy.parse_error !== undefined
|
|
348
|
+
? "error"
|
|
349
|
+
: "absent",
|
|
350
|
+
},
|
|
351
|
+
warnings: allWarnings,
|
|
284
352
|
});
|
|
285
353
|
return;
|
|
286
354
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
355
|
+
// ── Apply ──
|
|
356
|
+
if (changes.length > 0) {
|
|
357
|
+
try {
|
|
358
|
+
writeAtomic(file, nextRaw);
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
agentError(`Failed to write ${file}: ${err.message}`, "IOError", {
|
|
362
|
+
error_domain: AGENT_ERROR_DOMAINS.IO,
|
|
363
|
+
});
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
293
366
|
}
|
|
367
|
+
const removal = removeLegacyCodexHook();
|
|
368
|
+
const allWarnings = removal.status === "error" && removal.error !== undefined
|
|
369
|
+
? [...warnings, legacyHookWarning(removal.error)]
|
|
370
|
+
: warnings;
|
|
371
|
+
const didChange = changes.length > 0 || removal.status === "removed";
|
|
294
372
|
agentSuccess({
|
|
295
|
-
status: "APPLIED",
|
|
373
|
+
status: didChange ? "APPLIED" : "ALREADY_OK",
|
|
296
374
|
config_file: file,
|
|
297
|
-
applied:
|
|
298
|
-
|
|
375
|
+
applied: changes,
|
|
376
|
+
legacy_hook: { hooks_file: removal.hooks_file, status: removal.status },
|
|
377
|
+
warnings: allWarnings,
|
|
299
378
|
});
|
|
300
379
|
}
|
|
301
380
|
//# sourceMappingURL=codex-config.js.map
|