thoth-agents 0.1.0 → 0.1.1
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/codex-config-io.d.ts +5 -1
- package/dist/cli/index.js +70 -168
- package/package.json +1 -1
|
@@ -4,7 +4,10 @@ interface TomlTable {
|
|
|
4
4
|
[key: string]: TomlValue;
|
|
5
5
|
}
|
|
6
6
|
type TomlValue = TomlScalar | TomlArray | TomlTable;
|
|
7
|
-
|
|
7
|
+
declare const arrayTablePathsSymbol: unique symbol;
|
|
8
|
+
export type CodexTomlDocument = TomlTable & {
|
|
9
|
+
[arrayTablePathsSymbol]?: Set<string>;
|
|
10
|
+
};
|
|
8
11
|
export interface CodexConfigMergeResult {
|
|
9
12
|
success: boolean;
|
|
10
13
|
configPath: string;
|
|
@@ -23,6 +26,7 @@ export declare function mergeCodexManagedConfig(document: CodexTomlDocument, opt
|
|
|
23
26
|
diffSummary: string[];
|
|
24
27
|
warnings: string[];
|
|
25
28
|
};
|
|
29
|
+
export declare function patchCodexDefaultModeUserInputFeature(content: string): string;
|
|
26
30
|
export declare function writeCodexConfigMerge(options: {
|
|
27
31
|
configPath: string;
|
|
28
32
|
dryRun?: boolean;
|
package/dist/cli/index.js
CHANGED
|
@@ -2935,195 +2935,97 @@ import {
|
|
|
2935
2935
|
writeFileSync as writeFileSync2
|
|
2936
2936
|
} from "fs";
|
|
2937
2937
|
import { dirname as dirname3 } from "path";
|
|
2938
|
-
function
|
|
2939
|
-
return
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
for (const char of raw) {
|
|
2947
|
-
if (quote === "double" && escaped) {
|
|
2948
|
-
current += char;
|
|
2949
|
-
escaped = false;
|
|
2950
|
-
continue;
|
|
2951
|
-
}
|
|
2952
|
-
if (quote === "double" && char === "\\") {
|
|
2953
|
-
current += char;
|
|
2954
|
-
escaped = true;
|
|
2955
|
-
continue;
|
|
2956
|
-
}
|
|
2957
|
-
if (!quote && char === ",") {
|
|
2958
|
-
items.push(current.trim());
|
|
2959
|
-
current = "";
|
|
2960
|
-
continue;
|
|
2961
|
-
}
|
|
2962
|
-
if (!quote && char === "'") quote = "single";
|
|
2963
|
-
else if (quote === "single" && char === "'") quote = void 0;
|
|
2964
|
-
else if (!quote && char === '"') quote = "double";
|
|
2965
|
-
else if (quote === "double" && char === '"') quote = void 0;
|
|
2966
|
-
current += char;
|
|
2967
|
-
}
|
|
2968
|
-
if (current.trim()) items.push(current.trim());
|
|
2969
|
-
return items;
|
|
2970
|
-
}
|
|
2971
|
-
function parseBasicString(value) {
|
|
2972
|
-
return value.slice(1, -1).replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
2973
|
-
}
|
|
2974
|
-
function parseScalar(raw) {
|
|
2975
|
-
const value = raw.trim();
|
|
2976
|
-
if (value === "true") return true;
|
|
2977
|
-
if (value === "false") return false;
|
|
2978
|
-
if (/^-?\d+(\.\d+)?$/.test(value)) return Number(value);
|
|
2979
|
-
if (value.startsWith("[") && value.endsWith("]")) {
|
|
2980
|
-
const body = value.slice(1, -1).trim();
|
|
2981
|
-
if (!body) return [];
|
|
2982
|
-
return splitArrayItems(body).map(parseScalar);
|
|
2983
|
-
}
|
|
2984
|
-
if (value.startsWith('"') && value.endsWith('"')) {
|
|
2985
|
-
return parseBasicString(value);
|
|
2986
|
-
}
|
|
2987
|
-
if (value.startsWith("'") && value.endsWith("'")) {
|
|
2988
|
-
return value.slice(1, -1);
|
|
2989
|
-
}
|
|
2990
|
-
return value;
|
|
2991
|
-
}
|
|
2992
|
-
function parseTomlKeySegment(raw) {
|
|
2993
|
-
const segment = raw.trim();
|
|
2994
|
-
if (segment.startsWith('"') && segment.endsWith('"')) {
|
|
2995
|
-
return parseBasicString(segment);
|
|
2996
|
-
}
|
|
2997
|
-
if (segment.startsWith("'") && segment.endsWith("'")) {
|
|
2998
|
-
return segment.slice(1, -1);
|
|
2999
|
-
}
|
|
3000
|
-
return segment;
|
|
3001
|
-
}
|
|
3002
|
-
function parseTomlKeyPath(raw) {
|
|
3003
|
-
const segments = [];
|
|
3004
|
-
let current = "";
|
|
3005
|
-
let quote;
|
|
3006
|
-
let escaped = false;
|
|
3007
|
-
for (const char of raw) {
|
|
3008
|
-
if (quote === "double" && escaped) {
|
|
3009
|
-
current += char;
|
|
3010
|
-
escaped = false;
|
|
3011
|
-
continue;
|
|
3012
|
-
}
|
|
3013
|
-
if (quote === "double" && char === "\\") {
|
|
3014
|
-
current += char;
|
|
3015
|
-
escaped = true;
|
|
3016
|
-
continue;
|
|
3017
|
-
}
|
|
3018
|
-
if (!quote && char === ".") {
|
|
3019
|
-
segments.push(parseTomlKeySegment(current));
|
|
3020
|
-
current = "";
|
|
3021
|
-
continue;
|
|
3022
|
-
}
|
|
3023
|
-
if (!quote && char === "'") quote = "single";
|
|
3024
|
-
else if (quote === "single" && char === "'") quote = void 0;
|
|
3025
|
-
else if (!quote && char === '"') quote = "double";
|
|
3026
|
-
else if (quote === "double" && char === '"') quote = void 0;
|
|
3027
|
-
current += char;
|
|
3028
|
-
}
|
|
3029
|
-
segments.push(parseTomlKeySegment(current));
|
|
3030
|
-
return segments;
|
|
3031
|
-
}
|
|
3032
|
-
function ensureTable(root, path3) {
|
|
3033
|
-
let current = root;
|
|
3034
|
-
for (const segment of path3) {
|
|
3035
|
-
const existing = current[segment];
|
|
3036
|
-
if (!isRecord3(existing)) current[segment] = {};
|
|
3037
|
-
current = current[segment];
|
|
3038
|
-
}
|
|
3039
|
-
return current;
|
|
3040
|
-
}
|
|
3041
|
-
function parseCodexToml(content) {
|
|
3042
|
-
const root = {};
|
|
3043
|
-
let table = [];
|
|
3044
|
-
for (const rawLine of content.split(/\r?\n/)) {
|
|
3045
|
-
const trimmed = rawLine.trim();
|
|
3046
|
-
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
3047
|
-
const arrayTableMatch = /^\[\[([^\]]+)\]\]$/.exec(trimmed);
|
|
3048
|
-
const tableMatch = /^\[([^\]]+)\]$/.exec(trimmed);
|
|
3049
|
-
const tablePath = arrayTableMatch?.[1] ?? tableMatch?.[1];
|
|
3050
|
-
if (tablePath) {
|
|
3051
|
-
table = parseTomlKeyPath(tablePath);
|
|
3052
|
-
ensureTable(root, table);
|
|
3053
|
-
continue;
|
|
2938
|
+
function splitTomlLines(content) {
|
|
2939
|
+
return (content.match(/[^\r\n]*(?:\r\n|\n|\r)|[^\r\n]+$/g) ?? []).map(
|
|
2940
|
+
(rawLine) => {
|
|
2941
|
+
const eol = /(\r\n|\n|\r)$/.exec(rawLine)?.[1] ?? "";
|
|
2942
|
+
return {
|
|
2943
|
+
text: eol ? rawLine.slice(0, -eol.length) : rawLine,
|
|
2944
|
+
eol
|
|
2945
|
+
};
|
|
3054
2946
|
}
|
|
3055
|
-
|
|
3056
|
-
if (!assignment) throw new Error(`Unsupported TOML line: ${rawLine}`);
|
|
3057
|
-
ensureTable(root, table)[assignment[1].trim()] = parseScalar(assignment[2]);
|
|
3058
|
-
}
|
|
3059
|
-
return root;
|
|
2947
|
+
);
|
|
3060
2948
|
}
|
|
3061
|
-
function
|
|
3062
|
-
|
|
3063
|
-
const canUseLiteralString = value.includes("\\") && !value.includes("'") && [...value].every((char) => char.charCodeAt(0) >= 32);
|
|
3064
|
-
if (canUseLiteralString) {
|
|
3065
|
-
return `'${value}'`;
|
|
3066
|
-
}
|
|
3067
|
-
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
3068
|
-
}
|
|
3069
|
-
return String(value);
|
|
2949
|
+
function tomlLineBreak(content) {
|
|
2950
|
+
return /(\r\n|\n|\r)/.exec(content)?.[1] ?? "\n";
|
|
3070
2951
|
}
|
|
3071
|
-
function
|
|
3072
|
-
|
|
3073
|
-
return renderScalar2(value);
|
|
2952
|
+
function uncommentedTomlLine(line) {
|
|
2953
|
+
return line.split("#", 1)[0].trim();
|
|
3074
2954
|
}
|
|
3075
|
-
function
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
if (canUseLiteralKey) return `'${segment}'`;
|
|
3079
|
-
return `"${segment.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
2955
|
+
function isTomlTableHeader(line) {
|
|
2956
|
+
const trimmed = uncommentedTomlLine(line);
|
|
2957
|
+
return trimmed.startsWith("[[") && trimmed.endsWith("]]") || trimmed.startsWith("[") && trimmed.endsWith("]");
|
|
3080
2958
|
}
|
|
3081
|
-
function
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3085
|
-
|
|
3086
|
-
|
|
3087
|
-
|
|
3088
|
-
|
|
2959
|
+
function isFeaturesHeader(line) {
|
|
2960
|
+
return uncommentedTomlLine(line) === "[features]";
|
|
2961
|
+
}
|
|
2962
|
+
function renderTomlLines(lines) {
|
|
2963
|
+
return lines.map((line) => `${line.text}${line.eol}`).join("");
|
|
2964
|
+
}
|
|
2965
|
+
function ensureLineHasEol(lines, index, eol) {
|
|
2966
|
+
if (index >= 0 && lines[index]?.eol === "") lines[index].eol = eol;
|
|
2967
|
+
}
|
|
2968
|
+
function appendFeaturesSection(content) {
|
|
2969
|
+
const eol = tomlLineBreak(content);
|
|
2970
|
+
if (!content) {
|
|
2971
|
+
return `[features]${eol}default_mode_request_user_input = true${eol}`;
|
|
3089
2972
|
}
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
renderTomlSection(lines, entry, [...path3, key]);
|
|
2973
|
+
const separator = content.endsWith("\n") || content.endsWith("\r") ? content.endsWith(`${eol}${eol}`) ? "" : eol : `${eol}${eol}`;
|
|
2974
|
+
return `${content}${separator}[features]${eol}default_mode_request_user_input = true${eol}`;
|
|
3093
2975
|
}
|
|
3094
|
-
function
|
|
3095
|
-
const lines =
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
return
|
|
3099
|
-
|
|
2976
|
+
function patchCodexDefaultModeUserInputFeature(content) {
|
|
2977
|
+
const lines = splitTomlLines(content);
|
|
2978
|
+
const eol = tomlLineBreak(content);
|
|
2979
|
+
const featuresStart = lines.findIndex((line) => isFeaturesHeader(line.text));
|
|
2980
|
+
if (featuresStart === -1) return appendFeaturesSection(content);
|
|
2981
|
+
let featuresEnd = lines.length;
|
|
2982
|
+
for (let index = featuresStart + 1; index < lines.length; index++) {
|
|
2983
|
+
if (isTomlTableHeader(lines[index].text)) {
|
|
2984
|
+
featuresEnd = index;
|
|
2985
|
+
break;
|
|
2986
|
+
}
|
|
2987
|
+
}
|
|
2988
|
+
const flagPattern = /^(\s*default_mode_request_user_input\s*=\s*)(true|false)(\b.*)$/;
|
|
2989
|
+
for (let index = featuresStart + 1; index < featuresEnd; index++) {
|
|
2990
|
+
const match = flagPattern.exec(lines[index].text);
|
|
2991
|
+
if (!match) continue;
|
|
2992
|
+
if (match[2] === "true") return content;
|
|
2993
|
+
lines[index].text = `${match[1]}true${match[3]}`;
|
|
2994
|
+
return renderTomlLines(lines);
|
|
2995
|
+
}
|
|
2996
|
+
let insertAt = featuresEnd;
|
|
2997
|
+
while (insertAt > featuresStart + 1 && lines[insertAt - 1].text.trim() === "")
|
|
2998
|
+
insertAt--;
|
|
2999
|
+
ensureLineHasEol(lines, insertAt - 1, eol);
|
|
3000
|
+
lines.splice(insertAt, 0, {
|
|
3001
|
+
text: "default_mode_request_user_input = true",
|
|
3002
|
+
eol
|
|
3003
|
+
});
|
|
3004
|
+
return renderTomlLines(lines);
|
|
3100
3005
|
}
|
|
3101
|
-
function
|
|
3102
|
-
const
|
|
3103
|
-
|
|
3104
|
-
|
|
3006
|
+
function buildCodexManagedConfigPatch(content, options) {
|
|
3007
|
+
const diffSummary = [
|
|
3008
|
+
"ensure features.default_mode_request_user_input = true"
|
|
3009
|
+
];
|
|
3105
3010
|
if (options.pluginId) {
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3011
|
+
diffSummary.push(
|
|
3012
|
+
`plugin enablement for "${options.pluginId}" is not textually merged; use /plugins to enable it`
|
|
3013
|
+
);
|
|
3109
3014
|
} else {
|
|
3110
3015
|
diffSummary.push(
|
|
3111
3016
|
"plugin enablement left to /plugins; no guessed plugin id written"
|
|
3112
3017
|
);
|
|
3113
3018
|
}
|
|
3114
3019
|
return {
|
|
3115
|
-
content:
|
|
3020
|
+
content: patchCodexDefaultModeUserInputFeature(content),
|
|
3116
3021
|
diffSummary,
|
|
3117
|
-
warnings: [
|
|
3118
|
-
"Codex TOML comments and formatting may be rewritten; a backup is created before apply."
|
|
3119
|
-
]
|
|
3022
|
+
warnings: []
|
|
3120
3023
|
};
|
|
3121
3024
|
}
|
|
3122
3025
|
function writeCodexConfigMerge(options) {
|
|
3123
3026
|
try {
|
|
3124
3027
|
const before = existsSync6(options.configPath) ? readFileSync5(options.configPath, "utf8") : "";
|
|
3125
|
-
const
|
|
3126
|
-
const merged = mergeCodexManagedConfig(parsed, {
|
|
3028
|
+
const merged = buildCodexManagedConfigPatch(before, {
|
|
3127
3029
|
pluginId: options.pluginId
|
|
3128
3030
|
});
|
|
3129
3031
|
const changed = before !== merged.content;
|
package/package.json
CHANGED