docks-kit 0.17.0 → 0.17.2
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.md +37 -33
- package/README.md +1 -0
- package/cli/docs/omp-models.md +114 -58
- package/cli/src/argv.ts +38 -469
- package/cli/src/argvSurface.ts +371 -0
- package/cli/src/argvValidate.ts +122 -0
- package/cli/src/commands/docs.ts +57 -42
- package/cli/src/commands/harnesses.ts +38 -45
- package/cli/src/commands/model.ts +48 -53
- package/cli/src/commands/models.ts +24 -26
- package/cli/src/commands/omp.ts +178 -88
- package/cli/src/commands/plugins.ts +20 -20
- package/cli/src/commands/skills.ts +22 -20
- package/cli/src/commands/status.ts +87 -80
- package/cli/src/commands/sync.ts +113 -87
- package/cli/src/commands/toolchain.ts +21 -21
- package/cli/src/commands/update.ts +139 -117
- package/cli/src/efforts.ts +35 -34
- package/cli/src/engine-native/DESIGN.md +30 -30
- package/cli/src/engine-native/bun.ts +77 -55
- package/cli/src/engine-native/claudeLsp.ts +154 -0
- package/cli/src/engine-native/claudeOptionalPlugins.ts +113 -0
- package/cli/src/engine-native/claudePluginPasses.ts +348 -0
- package/cli/src/engine-native/claudeRemovals.ts +195 -0
- package/cli/src/engine-native/claudeRetired.ts +4 -4
- package/cli/src/engine-native/claudeRuntime.ts +94 -68
- package/cli/src/engine-native/claudeSettings.ts +174 -0
- package/cli/src/engine-native/claudeSettingsModifiers.ts +50 -54
- package/cli/src/engine-native/claudeSync.ts +176 -456
- package/cli/src/engine-native/codexConfig.ts +158 -0
- package/cli/src/engine-native/codexHooks.ts +91 -0
- package/cli/src/engine-native/codexPlugins.ts +290 -0
- package/cli/src/engine-native/codexStatus.ts +24 -0
- package/cli/src/engine-native/codexSync.ts +110 -568
- package/cli/src/engine-native/codexToml.ts +140 -138
- package/cli/src/engine-native/deps.ts +144 -107
- package/cli/src/engine-native/engineCtx.ts +126 -0
- package/cli/src/engine-native/exec.ts +98 -87
- package/cli/src/engine-native/failures.ts +3 -3
- package/cli/src/engine-native/harnesses.ts +62 -72
- package/cli/src/engine-native/index.ts +34 -315
- package/cli/src/engine-native/jq.ts +25 -24
- package/cli/src/engine-native/logger.ts +98 -100
- package/cli/src/engine-native/models.ts +50 -45
- package/cli/src/engine-native/modes.ts +83 -80
- package/cli/src/engine-native/ompFileDeploy.ts +111 -0
- package/cli/src/engine-native/ompMarketplace.ts +136 -0
- package/cli/src/engine-native/ompOverlay.ts +93 -53
- package/cli/src/engine-native/ompPaths.ts +49 -38
- package/cli/src/engine-native/ompPlugins.ts +170 -0
- package/cli/src/engine-native/ompSync.ts +64 -408
- package/cli/src/engine-native/ompYaml.ts +43 -41
- package/cli/src/engine-native/os/darwin.ts +5 -5
- package/cli/src/engine-native/os/index.ts +15 -15
- package/cli/src/engine-native/os/linux.ts +5 -5
- package/cli/src/engine-native/os/posix.ts +28 -24
- package/cli/src/engine-native/os/targets.ts +17 -17
- package/cli/src/engine-native/os/types.ts +31 -31
- package/cli/src/engine-native/os/windows.ts +61 -61
- package/cli/src/engine-native/parseArgs.ts +122 -372
- package/cli/src/engine-native/parseHelp.ts +66 -0
- package/cli/src/engine-native/parseModifiers.ts +222 -0
- package/cli/src/engine-native/services.ts +34 -34
- package/cli/src/engine-native/settings.ts +15 -15
- package/cli/src/engine-native/sharedTypes.d.ts +46 -0
- package/cli/src/engine-native/skillsInstall.ts +105 -0
- package/cli/src/engine-native/skillsLinks.ts +203 -0
- package/cli/src/engine-native/skillsManifest.ts +16 -0
- package/cli/src/engine-native/skillsPrune.ts +108 -0
- package/cli/src/engine-native/skillsSync.ts +28 -362
- package/cli/src/engine-native/syncConcurrency.ts +55 -0
- package/cli/src/engine-native/syncDispatch.ts +141 -0
- package/cli/src/engine-native/toolchain.ts +65 -62
- package/cli/src/engine.ts +65 -57
- package/cli/src/generated/sotPayload.ts +7 -7
- package/cli/src/kitHome.ts +44 -40
- package/cli/src/main.ts +63 -56
- package/cli/src/manifests.ts +53 -54
- package/cli/src/md.d.ts +2 -2
- package/cli/src/payload.ts +9 -9
- package/cli/src/services.ts +21 -13
- package/cli/tsconfig.json +4 -1
- package/package.json +9 -2
- package/cli/src/engine-native/claudePlugins.ts +0 -510
|
@@ -5,102 +5,101 @@
|
|
|
5
5
|
* golden contract. The key is used as a raw regex fragment, preserving the
|
|
6
6
|
* historical record-oriented behavior.
|
|
7
7
|
*/
|
|
8
|
-
import { p } from "./exec"
|
|
9
|
-
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs"
|
|
8
|
+
import { p } from "./exec";
|
|
9
|
+
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
10
10
|
|
|
11
|
-
import { resolveEffort } from "../efforts"
|
|
12
|
-
import type { Ctx } from "./index"
|
|
11
|
+
import { resolveEffort } from "../efforts";
|
|
12
|
+
import type { Ctx } from "./index";
|
|
13
|
+
import type { SettingEdit } from "./sharedTypes";
|
|
13
14
|
|
|
14
15
|
export function replaceTopLevelSetting(content: string, key: string, replacement: string): string {
|
|
15
|
-
const lines = content.split("\n")
|
|
16
|
-
if (lines[lines.length - 1] === "") lines.pop() // awk records exclude a trailing empty split artifact
|
|
17
|
-
const keyRe = new RegExp(`^${key}[ \\t]*=`)
|
|
18
|
-
const out: Array<string> = []
|
|
19
|
-
let inTable = false
|
|
20
|
-
let replaced = false
|
|
16
|
+
const lines = content.split("\n");
|
|
17
|
+
if (lines[lines.length - 1] === "") lines.pop(); // awk records exclude a trailing empty split artifact
|
|
18
|
+
const keyRe = new RegExp(`^${key}[ \\t]*=`);
|
|
19
|
+
const out: Array<string> = [];
|
|
20
|
+
let inTable = false;
|
|
21
|
+
let replaced = false;
|
|
21
22
|
for (const line of lines) {
|
|
22
23
|
if (line.startsWith("[")) {
|
|
23
24
|
if (!replaced) {
|
|
24
|
-
out.push(replacement)
|
|
25
|
-
replaced = true
|
|
25
|
+
out.push(replacement);
|
|
26
|
+
replaced = true;
|
|
26
27
|
}
|
|
27
|
-
inTable = true
|
|
28
|
-
out.push(line)
|
|
29
|
-
continue
|
|
28
|
+
inTable = true;
|
|
29
|
+
out.push(line);
|
|
30
|
+
continue;
|
|
30
31
|
}
|
|
31
32
|
if (!inTable && keyRe.test(line)) {
|
|
32
33
|
if (!replaced) {
|
|
33
|
-
out.push(replacement)
|
|
34
|
-
replaced = true
|
|
34
|
+
out.push(replacement);
|
|
35
|
+
replaced = true;
|
|
35
36
|
}
|
|
36
|
-
continue
|
|
37
|
+
continue;
|
|
37
38
|
}
|
|
38
|
-
out.push(line)
|
|
39
|
+
out.push(line);
|
|
39
40
|
}
|
|
40
|
-
if (!replaced) out.push(replacement)
|
|
41
|
-
return `${out.join("\n")}\n
|
|
41
|
+
if (!replaced) out.push(replacement);
|
|
42
|
+
return `${out.join("\n")}\n`;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
export function replaceTopLevelSettingInFile(
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
export function replaceTopLevelSettingInFile(
|
|
46
|
+
file: string,
|
|
47
|
+
key: string,
|
|
48
|
+
replacement: string,
|
|
49
|
+
): boolean {
|
|
50
|
+
const before = readFileSync(file, "utf8");
|
|
51
|
+
const next = replaceTopLevelSetting(before, key, replacement);
|
|
52
|
+
if (next === before) return false;
|
|
53
|
+
writeFileSync(`${file}.tmp`, next);
|
|
54
|
+
renameSync(`${file}.tmp`, file);
|
|
55
|
+
return true;
|
|
51
56
|
}
|
|
52
57
|
|
|
53
|
-
|
|
54
|
-
readonly tag: string
|
|
55
|
-
readonly key: "model" | "model_reasoning_effort"
|
|
56
|
-
readonly value: string
|
|
57
|
-
readonly changed: string
|
|
58
|
-
readonly unchanged: string
|
|
59
|
-
}
|
|
58
|
+
type CodexSettingEdit = SettingEdit<"model" | "model_reasoning_effort">;
|
|
60
59
|
|
|
61
60
|
function syncCodexSetting(ctx: Ctx, edit: CodexSettingEdit): void {
|
|
62
|
-
const { change, echo, verbose, warn } = ctx.services.logger
|
|
63
|
-
const userCodexSettings = p(ctx.home, ".codex", "config.toml")
|
|
61
|
+
const { change, echo, verbose, warn } = ctx.services.logger;
|
|
62
|
+
const userCodexSettings = p(ctx.home, ".codex", "config.toml");
|
|
64
63
|
|
|
65
64
|
if (!existsSync(userCodexSettings)) {
|
|
66
65
|
// A dry-run sync already previewed installing the file, so the edit is not skipped.
|
|
67
66
|
// The `docks-kit model codex <m>` command creates no file, so the skip stands.
|
|
68
67
|
if (ctx.dryRun && ctx.syncCodex) {
|
|
69
|
-
echo(`[dry-run] (${edit.tag}) set ${edit.key} = "${edit.value}" in ${userCodexSettings}`)
|
|
70
|
-
return
|
|
68
|
+
echo(`[dry-run] (${edit.tag}) set ${edit.key} = "${edit.value}" in ${userCodexSettings}`);
|
|
69
|
+
return;
|
|
71
70
|
}
|
|
72
|
-
warn(`(${edit.tag}) ${userCodexSettings} missing — skipped`)
|
|
73
|
-
return
|
|
71
|
+
warn(`(${edit.tag}) ${userCodexSettings} missing — skipped`);
|
|
72
|
+
return;
|
|
74
73
|
}
|
|
75
74
|
|
|
76
75
|
if (ctx.dryRun) {
|
|
77
|
-
echo(`[dry-run] (${edit.tag}) set ${edit.key} = "${edit.value}" in ${userCodexSettings}`)
|
|
78
|
-
return
|
|
76
|
+
echo(`[dry-run] (${edit.tag}) set ${edit.key} = "${edit.value}" in ${userCodexSettings}`);
|
|
77
|
+
return;
|
|
79
78
|
}
|
|
80
79
|
|
|
81
80
|
if (replaceTopLevelSettingInFile(userCodexSettings, edit.key, `${edit.key} = "${edit.value}"`)) {
|
|
82
|
-
change(edit.changed)
|
|
83
|
-
ctx.nextStepTriggers.codexRestart = true
|
|
81
|
+
change(edit.changed);
|
|
82
|
+
ctx.nextStepTriggers.codexRestart = true;
|
|
84
83
|
} else {
|
|
85
|
-
verbose(edit.unchanged)
|
|
84
|
+
verbose(edit.unchanged);
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
87
|
|
|
89
88
|
export function syncCodexModel(ctx: Ctx, model: string): void {
|
|
90
|
-
if (model === "") return
|
|
89
|
+
if (model === "") return;
|
|
91
90
|
syncCodexSetting(ctx, {
|
|
92
91
|
tag: "--codex-model",
|
|
93
92
|
key: "model",
|
|
94
93
|
value: model,
|
|
95
94
|
changed: `Model: deployed Codex model set to ${model} (SoT unchanged; flag-less sync reverts)`,
|
|
96
|
-
unchanged: `Model: deployed Codex model already ${model}
|
|
97
|
-
})
|
|
95
|
+
unchanged: `Model: deployed Codex model already ${model}`,
|
|
96
|
+
});
|
|
98
97
|
}
|
|
99
98
|
|
|
100
99
|
export function syncCodexEffort(ctx: Ctx, effort: string): void {
|
|
101
|
-
if (effort === "") return
|
|
102
|
-
const resolved = resolveEffort("codex", effort)
|
|
103
|
-
const useDefault = effort === "default"
|
|
100
|
+
if (effort === "") return;
|
|
101
|
+
const resolved = resolveEffort("codex", effort);
|
|
102
|
+
const useDefault = effort === "default";
|
|
104
103
|
syncCodexSetting(ctx, {
|
|
105
104
|
tag: "--codex-effort",
|
|
106
105
|
key: "model_reasoning_effort",
|
|
@@ -108,22 +107,22 @@ export function syncCodexEffort(ctx: Ctx, effort: string): void {
|
|
|
108
107
|
changed: useDefault
|
|
109
108
|
? `Effort: deployed Codex model_reasoning_effort set to ${resolved} (SoT default)`
|
|
110
109
|
: `Effort: deployed Codex model_reasoning_effort set to ${resolved} (SoT unchanged; flag-less sync reverts)`,
|
|
111
|
-
unchanged: `Effort: deployed Codex model_reasoning_effort already ${resolved}
|
|
112
|
-
})
|
|
110
|
+
unchanged: `Effort: deployed Codex model_reasoning_effort already ${resolved}`,
|
|
111
|
+
});
|
|
113
112
|
}
|
|
114
113
|
|
|
115
114
|
export function mergeTopLevelSettings(sotConfigText: string, userConfig: string): void {
|
|
116
115
|
for (const line of sotConfigText.split("\n")) {
|
|
117
|
-
if (line.startsWith("[")) break
|
|
118
|
-
if (/^[ \t]*($|#)/.test(line)) continue
|
|
119
|
-
if (!/^[A-Za-z0-9_.-]+[ \t]*=/.test(line)) continue
|
|
120
|
-
const key = line.slice(0, line.indexOf("=")).replace(/[ \t]+$/, "")
|
|
121
|
-
replaceTopLevelSettingInFile(userConfig, key, line)
|
|
116
|
+
if (line.startsWith("[")) break;
|
|
117
|
+
if (/^[ \t]*($|#)/.test(line)) continue;
|
|
118
|
+
if (!/^[A-Za-z0-9_.-]+[ \t]*=/.test(line)) continue;
|
|
119
|
+
const key = line.slice(0, line.indexOf("=")).replace(/[ \t]+$/, "");
|
|
120
|
+
replaceTopLevelSettingInFile(userConfig, key, line);
|
|
122
121
|
}
|
|
123
122
|
}
|
|
124
123
|
|
|
125
124
|
interface TomlTableHeader {
|
|
126
|
-
readonly path: string
|
|
125
|
+
readonly path: string;
|
|
127
126
|
}
|
|
128
127
|
|
|
129
128
|
const TOML_BASIC_ESCAPES: Readonly<Record<string, string>> = {
|
|
@@ -133,121 +132,124 @@ const TOML_BASIC_ESCAPES: Readonly<Record<string, string>> = {
|
|
|
133
132
|
f: "\f",
|
|
134
133
|
r: "\r",
|
|
135
134
|
'"': '"',
|
|
136
|
-
"\\": "\\"
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function tomlBasicEscape(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
135
|
+
"\\": "\\",
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
function tomlBasicEscape(
|
|
139
|
+
line: string,
|
|
140
|
+
offset: number,
|
|
141
|
+
): { readonly next: number; readonly value: string } | undefined {
|
|
142
|
+
const escaped = line[offset];
|
|
143
|
+
const simple = escaped === undefined ? undefined : TOML_BASIC_ESCAPES[escaped];
|
|
144
|
+
if (simple !== undefined) return { next: offset + 1, value: simple };
|
|
145
|
+
const digits = escaped === "u" ? 4 : escaped === "U" ? 8 : 0;
|
|
146
|
+
if (digits === 0) return undefined;
|
|
147
|
+
const hex = line.slice(offset + 1, offset + 1 + digits);
|
|
148
|
+
if (hex.length !== digits || !/^[0-9A-Fa-f]+$/.test(hex)) return undefined;
|
|
149
|
+
const codePoint = Number.parseInt(hex, 16);
|
|
150
|
+
if (codePoint > 0x10ffff || (codePoint >= 0xd800 && codePoint <= 0xdfff)) return undefined;
|
|
151
|
+
return { next: offset + 1 + digits, value: String.fromCodePoint(codePoint) };
|
|
150
152
|
}
|
|
151
153
|
|
|
152
154
|
/** Decode a table header to the TOML path that determines managed ownership. */
|
|
153
155
|
function tomlTableHeader(line: string): TomlTableHeader | undefined {
|
|
154
|
-
let offset = 0
|
|
156
|
+
let offset = 0;
|
|
155
157
|
const skipWhitespace = (): void => {
|
|
156
|
-
while (line[offset] === " " || line[offset] === "\t") offset
|
|
157
|
-
}
|
|
158
|
+
while (line[offset] === " " || line[offset] === "\t") offset++;
|
|
159
|
+
};
|
|
158
160
|
|
|
159
|
-
skipWhitespace()
|
|
160
|
-
if (line[offset] !== "[") return undefined
|
|
161
|
-
offset
|
|
162
|
-
const array = line[offset] === "["
|
|
163
|
-
if (array) offset
|
|
161
|
+
skipWhitespace();
|
|
162
|
+
if (line[offset] !== "[") return undefined;
|
|
163
|
+
offset++;
|
|
164
|
+
const array = line[offset] === "[";
|
|
165
|
+
if (array) offset++;
|
|
164
166
|
|
|
165
|
-
const keys: Array<string> = []
|
|
167
|
+
const keys: Array<string> = [];
|
|
166
168
|
while (true) {
|
|
167
|
-
skipWhitespace()
|
|
168
|
-
const quote = line[offset]
|
|
169
|
-
let key = ""
|
|
169
|
+
skipWhitespace();
|
|
170
|
+
const quote = line[offset];
|
|
171
|
+
let key = "";
|
|
170
172
|
if (quote === '"' || quote === "'") {
|
|
171
|
-
offset
|
|
172
|
-
let closed = false
|
|
173
|
+
offset++;
|
|
174
|
+
let closed = false;
|
|
173
175
|
while (offset < line.length) {
|
|
174
|
-
const char = line[offset]
|
|
176
|
+
const char = line[offset]!;
|
|
175
177
|
if (char === quote) {
|
|
176
|
-
offset
|
|
177
|
-
closed = true
|
|
178
|
-
break
|
|
178
|
+
offset++;
|
|
179
|
+
closed = true;
|
|
180
|
+
break;
|
|
179
181
|
}
|
|
180
182
|
if (quote === '"' && char === "\\") {
|
|
181
|
-
const escape = tomlBasicEscape(line, offset + 1)
|
|
182
|
-
if (escape === undefined) return undefined
|
|
183
|
-
key += escape.value
|
|
184
|
-
offset = escape.next
|
|
185
|
-
continue
|
|
183
|
+
const escape = tomlBasicEscape(line, offset + 1);
|
|
184
|
+
if (escape === undefined) return undefined;
|
|
185
|
+
key += escape.value;
|
|
186
|
+
offset = escape.next;
|
|
187
|
+
continue;
|
|
186
188
|
}
|
|
187
|
-
if (char === "\n" || char === "\r") return undefined
|
|
188
|
-
key += char
|
|
189
|
-
offset
|
|
189
|
+
if (char === "\n" || char === "\r") return undefined;
|
|
190
|
+
key += char;
|
|
191
|
+
offset++;
|
|
190
192
|
}
|
|
191
|
-
if (!closed) return undefined
|
|
193
|
+
if (!closed) return undefined;
|
|
192
194
|
} else {
|
|
193
|
-
const start = offset
|
|
194
|
-
while (offset < line.length && /[A-Za-z0-9_-]/.test(line[offset]!)) offset
|
|
195
|
-
if (offset === start) return undefined
|
|
196
|
-
key = line.slice(start, offset)
|
|
195
|
+
const start = offset;
|
|
196
|
+
while (offset < line.length && /[A-Za-z0-9_-]/.test(line[offset]!)) offset++;
|
|
197
|
+
if (offset === start) return undefined;
|
|
198
|
+
key = line.slice(start, offset);
|
|
197
199
|
}
|
|
198
|
-
keys.push(key)
|
|
200
|
+
keys.push(key);
|
|
199
201
|
|
|
200
|
-
skipWhitespace()
|
|
202
|
+
skipWhitespace();
|
|
201
203
|
if (line[offset] === ".") {
|
|
202
|
-
offset
|
|
203
|
-
continue
|
|
204
|
+
offset++;
|
|
205
|
+
continue;
|
|
204
206
|
}
|
|
205
|
-
if (line[offset] !== "]") return undefined
|
|
206
|
-
offset
|
|
207
|
+
if (line[offset] !== "]") return undefined;
|
|
208
|
+
offset++;
|
|
207
209
|
if (array) {
|
|
208
|
-
if (line[offset] !== "]") return undefined
|
|
209
|
-
offset
|
|
210
|
+
if (line[offset] !== "]") return undefined;
|
|
211
|
+
offset++;
|
|
210
212
|
}
|
|
211
|
-
skipWhitespace()
|
|
212
|
-
if (offset < line.length && line[offset] !== "#") return undefined
|
|
213
|
-
return { path: JSON.stringify(keys) }
|
|
213
|
+
skipWhitespace();
|
|
214
|
+
if (offset < line.length && line[offset] !== "#") return undefined;
|
|
215
|
+
return { path: JSON.stringify(keys) };
|
|
214
216
|
}
|
|
215
217
|
}
|
|
216
218
|
|
|
217
219
|
function mergeTableSettingsText(sotConfigText: string, userConfigText: string): string {
|
|
218
|
-
const sotLines = sotConfigText.split("\n")
|
|
219
|
-
let merged = userConfigText
|
|
220
|
+
const sotLines = sotConfigText.split("\n");
|
|
221
|
+
let merged = userConfigText;
|
|
220
222
|
for (let tableOffset = 0; tableOffset < sotLines.length; tableOffset++) {
|
|
221
|
-
const managedHeader = tomlTableHeader(sotLines[tableOffset]!)
|
|
222
|
-
if (managedHeader === undefined) continue
|
|
223
|
+
const managedHeader = tomlTableHeader(sotLines[tableOffset]!);
|
|
224
|
+
if (managedHeader === undefined) continue;
|
|
223
225
|
|
|
224
|
-
const block: Array<string> = []
|
|
226
|
+
const block: Array<string> = [];
|
|
225
227
|
for (let blockOffset = tableOffset; blockOffset < sotLines.length; blockOffset++) {
|
|
226
|
-
const line = sotLines[blockOffset]
|
|
227
|
-
if (blockOffset !== tableOffset && tomlTableHeader(line) !== undefined) break
|
|
228
|
-
block.push(line)
|
|
228
|
+
const line = sotLines[blockOffset]!;
|
|
229
|
+
if (blockOffset !== tableOffset && tomlTableHeader(line) !== undefined) break;
|
|
230
|
+
block.push(line);
|
|
229
231
|
}
|
|
230
|
-
const tableBlock = block.join("\n").replace(/\n+$/, "")
|
|
232
|
+
const tableBlock = block.join("\n").replace(/\n+$/, "");
|
|
231
233
|
|
|
232
|
-
const userLines = merged.split("\n")
|
|
233
|
-
if (userLines[userLines.length - 1] === "") userLines.pop()
|
|
234
|
-
let skip = false
|
|
235
|
-
const kept: Array<string> = []
|
|
234
|
+
const userLines = merged.split("\n");
|
|
235
|
+
if (userLines[userLines.length - 1] === "") userLines.pop();
|
|
236
|
+
let skip = false;
|
|
237
|
+
const kept: Array<string> = [];
|
|
236
238
|
for (const line of userLines) {
|
|
237
|
-
const header = tomlTableHeader(line)
|
|
239
|
+
const header = tomlTableHeader(line);
|
|
238
240
|
if (header !== undefined) {
|
|
239
|
-
skip = header.path === managedHeader.path
|
|
240
|
-
if (skip) continue
|
|
241
|
+
skip = header.path === managedHeader.path;
|
|
242
|
+
if (skip) continue;
|
|
241
243
|
}
|
|
242
|
-
if (!skip) kept.push(line)
|
|
244
|
+
if (!skip) kept.push(line);
|
|
243
245
|
}
|
|
244
|
-
merged = `${kept.join("\n")}\n\n${tableBlock}\n
|
|
246
|
+
merged = `${kept.join("\n")}\n\n${tableBlock}\n`;
|
|
245
247
|
}
|
|
246
|
-
return merged
|
|
248
|
+
return merged;
|
|
247
249
|
}
|
|
248
250
|
|
|
249
251
|
export function mergeTableSettings(sotConfigText: string, userConfig: string): void {
|
|
250
|
-
const next = mergeTableSettingsText(sotConfigText, readFileSync(userConfig, "utf8"))
|
|
251
|
-
writeFileSync(`${userConfig}.tmp`, next)
|
|
252
|
-
renameSync(`${userConfig}.tmp`, userConfig)
|
|
252
|
+
const next = mergeTableSettingsText(sotConfigText, readFileSync(userConfig, "utf8"));
|
|
253
|
+
writeFileSync(`${userConfig}.tmp`, next);
|
|
254
|
+
renameSync(`${userConfig}.tmp`, userConfig);
|
|
253
255
|
}
|