@songsid/agend 2.1.0-beta.10 → 2.1.0-beta.12
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/config-validator.js +7 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.d.ts +3 -1
- package/dist/config.js +13 -1
- package/dist/config.js.map +1 -1
- package/dist/fleet-manager.d.ts +11 -2
- package/dist/fleet-manager.js +88 -66
- package/dist/fleet-manager.js.map +1 -1
- package/dist/logger.d.ts +6 -0
- package/dist/logger.js +23 -7
- package/dist/logger.js.map +1 -1
- package/dist/settings-api.d.ts +2 -1
- package/dist/settings-api.js +10 -1
- package/dist/settings-api.js.map +1 -1
- package/dist/types.d.ts +13 -0
- package/dist/ui/settings.html +25 -3
- package/package.json +2 -1
package/dist/config-validator.js
CHANGED
|
@@ -22,6 +22,11 @@ export function validateFleetConfig(config) {
|
|
|
22
22
|
const warnings = [];
|
|
23
23
|
const err = (path, message) => errors.push({ path, message });
|
|
24
24
|
const warn = (path, message) => warnings.push({ path, message });
|
|
25
|
+
const validateAutoPause = (value, path) => {
|
|
26
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isFinite(value) || value < 0)) {
|
|
27
|
+
err(path, "must be a non-negative finite number of minutes (0 disables auto-pause)");
|
|
28
|
+
}
|
|
29
|
+
};
|
|
25
30
|
if (!isObj(config)) {
|
|
26
31
|
return { valid: false, errors: [{ path: "", message: "config must be a mapping" }], warnings: [] };
|
|
27
32
|
}
|
|
@@ -86,6 +91,7 @@ export function validateFleetConfig(config) {
|
|
|
86
91
|
if (b !== undefined && (typeof b !== "string" || !KNOWN_BACKENDS.includes(b))) {
|
|
87
92
|
err("defaults.backend", `unknown backend "${String(b)}" (known: ${KNOWN_BACKENDS.join(", ")})`);
|
|
88
93
|
}
|
|
94
|
+
validateAutoPause(config.defaults.auto_pause_after, "defaults.auto_pause_after");
|
|
89
95
|
}
|
|
90
96
|
// ── Instances ─────────────────────────────────────────────
|
|
91
97
|
let generalCount = 0;
|
|
@@ -114,6 +120,7 @@ export function validateFleetConfig(config) {
|
|
|
114
120
|
if (inst.working_directory !== undefined && typeof inst.working_directory !== "string") {
|
|
115
121
|
err(`instances.${name}.working_directory`, "must be a string path");
|
|
116
122
|
}
|
|
123
|
+
validateAutoPause(inst.auto_pause_after, `instances.${name}.auto_pause_after`);
|
|
117
124
|
}
|
|
118
125
|
}
|
|
119
126
|
if (generalCount === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-validator.js","sourceRoot":"","sources":["../src/config-validator.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,mFAAmF;AACnF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,CAAC,CAAC;AAEpH,MAAM,KAAK,GAAG,CAAC,CAAU,EAAgC,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAErH,4EAA4E;AAC5E,SAAS,SAAS,CAAC,CAAU;IAC3B,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;AAC5G,CAAC;AAED,yEAAyE;AACzE,SAAS,WAAW,CAAC,EAA2B;IAC9C,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,IAAI,CAAC;IAC5B,OAAO,OAAO,EAAE,KAAK,QAAQ,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAe;IACjD,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC9E,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,OAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config-validator.js","sourceRoot":"","sources":["../src/config-validator.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CostGuardConfig, HangDetectorConfig, DailySummaryConfig, FleetConfig, InstanceConfig } from "./types.js";
|
|
1
|
+
import type { CostGuardConfig, HangDetectorConfig, DailySummaryConfig, FleetConfig, InstanceConfig, RawFleetConfig } from "./types.js";
|
|
2
2
|
export declare function getTmuxSession(): string;
|
|
3
3
|
export declare const DEFAULT_COST_GUARD: CostGuardConfig;
|
|
4
4
|
export declare const DEFAULT_HANG_DETECTOR: HangDetectorConfig;
|
|
@@ -7,3 +7,5 @@ export declare const DEFAULT_INSTANCE_CONFIG: Omit<InstanceConfig, "working_dire
|
|
|
7
7
|
/** Validate IANA timezone string. Throws if invalid. */
|
|
8
8
|
export declare function validateTimezone(tz: string, field: string): void;
|
|
9
9
|
export declare function loadFleetConfig(configPath: string): FleetConfig;
|
|
10
|
+
/** Read the user-authored config without applying defaults or normalization. */
|
|
11
|
+
export declare function loadRawFleetConfig(configPath: string): RawFleetConfig;
|
package/dist/config.js
CHANGED
|
@@ -40,7 +40,7 @@ export const DEFAULT_DAILY_SUMMARY = {
|
|
|
40
40
|
minute: 0,
|
|
41
41
|
};
|
|
42
42
|
export const DEFAULT_INSTANCE_CONFIG = {
|
|
43
|
-
auto_pause_after: 0, //
|
|
43
|
+
auto_pause_after: 0, // minutes; 0 = disabled (opt-in)
|
|
44
44
|
restart_policy: {
|
|
45
45
|
max_retries: 10,
|
|
46
46
|
backoff: "exponential",
|
|
@@ -117,4 +117,16 @@ export function loadFleetConfig(configPath) {
|
|
|
117
117
|
health_port: parsed.health_port,
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
|
+
/** Read the user-authored config without applying defaults or normalization. */
|
|
121
|
+
export function loadRawFleetConfig(configPath) {
|
|
122
|
+
if (!existsSync(configPath))
|
|
123
|
+
return {};
|
|
124
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
125
|
+
// Match loadFleetConfig(): preserve platform IDs that exceed MAX_SAFE_INTEGER.
|
|
126
|
+
const safeRaw = raw.replace(/(?<=:\s+|[-]\s+)(\d{16,})(?=\s*$)/gm, (_, d) => `"${d}"`);
|
|
127
|
+
const parsed = yaml.load(safeRaw);
|
|
128
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
|
129
|
+
? parsed
|
|
130
|
+
: {};
|
|
131
|
+
}
|
|
120
132
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGlF,SAAS,gBAAgB,CAAmB,MAAS,EAAE,MAAkB;IACvE,MAAM,MAAM,GAAG,EAAE,GAAG,MAAM,EAA6B,CAAC;IACxD,MAAM,YAAY,GAAG,MAAiC,CAAC;IAEvD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;QAC5C,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC9B,IACE,SAAS,KAAK,IAAI;YAClB,OAAO,SAAS,KAAK,QAAQ;YAC7B,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACzB,OAAO,SAAS,KAAK,QAAQ;YAC7B,SAAS,KAAK,IAAI;YAClB,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EACzB,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAC5B,SAAmB,EACnB,SAA4B,CAC7B,CAAC;QACJ,CAAC;aAAM,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,OAAO,MAAsB,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,kBAAkB,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAoB;IACjD,eAAe,EAAE,CAAC,EAAE,eAAe;IACnC,kBAAkB,EAAE,EAAE;IACtB,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,CAAC,eAAe,EAAE,CAAC,QAAQ;CAC3D,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAuB;IACvD,OAAO,EAAE,IAAI;IACb,eAAe,EAAE,EAAE;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAuB;IACvD,OAAO,EAAE,IAAI;IACb,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,CAAC;CACV,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAA8C;IAChF,gBAAgB,EAAE,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/fleet-manager.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FleetConfig, InstanceConfig } from "./types.js";
|
|
1
|
+
import type { FleetConfig, RawFleetConfig, InstanceConfig } from "./types.js";
|
|
2
2
|
import { type RouteTarget } from "./fleet-context.js";
|
|
3
3
|
import { EventLog } from "./event-log.js";
|
|
4
4
|
import { AdapterWorld } from "./adapter-world.js";
|
|
@@ -25,6 +25,9 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
25
25
|
/** @deprecated Use lifecycle.daemons — kept for backward compat */
|
|
26
26
|
get daemons(): Map<string, import("./daemon.js").Daemon>;
|
|
27
27
|
fleetConfig: FleetConfig | null;
|
|
28
|
+
private rawFleetConfig;
|
|
29
|
+
private rawFleetDocument;
|
|
30
|
+
private savedFleetConfigSnapshot;
|
|
28
31
|
adapter: ChannelAdapter | null;
|
|
29
32
|
readonly worlds: Map<string, AdapterWorld>;
|
|
30
33
|
readonly adapters: Map<string, ChannelAdapter>;
|
|
@@ -79,6 +82,8 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
79
82
|
getSysInfo(): import("./fleet-context.js").SysInfo;
|
|
80
83
|
/** Load fleet.yaml and build routing table */
|
|
81
84
|
loadConfig(configPath: string): FleetConfig;
|
|
85
|
+
/** User-authored fleet.yaml, before defaults are merged into instances. */
|
|
86
|
+
getRawFleetConfig(): RawFleetConfig;
|
|
82
87
|
/** Build topic routing table: { topicId -> RouteTarget } */
|
|
83
88
|
buildRoutingTable(): Map<string, RouteTarget>;
|
|
84
89
|
/**
|
|
@@ -203,8 +208,12 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
|
|
|
203
208
|
private botUserId;
|
|
204
209
|
/** Periodically check if bound topics still exist */
|
|
205
210
|
private startTopicCleanupPoller;
|
|
206
|
-
/**
|
|
211
|
+
/**
|
|
212
|
+
* Patch only values changed in the effective config into the original YAML
|
|
213
|
+
* document. Unknown keys, explicit overrides and comments remain untouched.
|
|
214
|
+
*/
|
|
207
215
|
saveFleetConfig(): void;
|
|
216
|
+
private patchFleetDocument;
|
|
208
217
|
removeInstance(name: string): Promise<void>;
|
|
209
218
|
startStatuslineWatcher(name: string): void;
|
|
210
219
|
stopStatuslineWatcher(name: string): void;
|
package/dist/fleet-manager.js
CHANGED
|
@@ -5,13 +5,13 @@ import { join, dirname, basename } from "node:path";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { getAgendHome, ensureWorkspaceGit } from "./paths.js";
|
|
7
7
|
import { sdNotify } from "./sd-notify.js";
|
|
8
|
-
import
|
|
8
|
+
import { isScalar, parseDocument } from "yaml";
|
|
9
9
|
const __filename = fileURLToPath(import.meta.url);
|
|
10
10
|
const __dirname = dirname(__filename);
|
|
11
11
|
/** Fallback access policy for a channel with no `access:` block — open (no gate). */
|
|
12
12
|
const DEFAULT_OPEN_ACCESS = { mode: "open", allowed_users: [], max_pending_codes: 0, code_expiry_minutes: 0 };
|
|
13
13
|
import { isProbeableRouteTarget } from "./fleet-context.js";
|
|
14
|
-
import { loadFleetConfig, DEFAULT_COST_GUARD, DEFAULT_DAILY_SUMMARY, DEFAULT_INSTANCE_CONFIG } from "./config.js";
|
|
14
|
+
import { loadFleetConfig, loadRawFleetConfig, DEFAULT_COST_GUARD, DEFAULT_DAILY_SUMMARY, DEFAULT_INSTANCE_CONFIG } from "./config.js";
|
|
15
15
|
import { EventLog } from "./event-log.js";
|
|
16
16
|
import { AdapterWorld } from "./adapter-world.js";
|
|
17
17
|
import { CostGuard, formatCents } from "./cost-guard.js";
|
|
@@ -65,6 +65,9 @@ export class FleetManager {
|
|
|
65
65
|
/** @deprecated Use lifecycle.daemons — kept for backward compat */
|
|
66
66
|
get daemons() { return this.lifecycle.daemons; }
|
|
67
67
|
fleetConfig = null;
|
|
68
|
+
rawFleetConfig = {};
|
|
69
|
+
rawFleetDocument = null;
|
|
70
|
+
savedFleetConfigSnapshot = null;
|
|
68
71
|
adapter = null;
|
|
69
72
|
worlds = new Map();
|
|
70
73
|
adapters = new Map(); // derived view for backward compat
|
|
@@ -177,9 +180,21 @@ export class FleetManager {
|
|
|
177
180
|
}
|
|
178
181
|
/** Load fleet.yaml and build routing table */
|
|
179
182
|
loadConfig(configPath) {
|
|
183
|
+
this.configPath = configPath;
|
|
184
|
+
const source = existsSync(configPath) ? readFileSync(configPath, "utf-8") : "{}\n";
|
|
185
|
+
this.rawFleetDocument = parseDocument(source, { keepSourceTokens: true });
|
|
186
|
+
if (this.rawFleetDocument.errors.length > 0) {
|
|
187
|
+
throw new Error(`Invalid fleet.yaml: ${this.rawFleetDocument.errors[0].message}`);
|
|
188
|
+
}
|
|
189
|
+
this.rawFleetConfig = loadRawFleetConfig(configPath);
|
|
180
190
|
this.fleetConfig = loadFleetConfig(configPath);
|
|
191
|
+
this.savedFleetConfigSnapshot = structuredClone(this.fleetConfig);
|
|
181
192
|
return this.fleetConfig;
|
|
182
193
|
}
|
|
194
|
+
/** User-authored fleet.yaml, before defaults are merged into instances. */
|
|
195
|
+
getRawFleetConfig() {
|
|
196
|
+
return structuredClone(this.rawFleetConfig);
|
|
197
|
+
}
|
|
183
198
|
/** Build topic routing table: { topicId -> RouteTarget } */
|
|
184
199
|
buildRoutingTable() {
|
|
185
200
|
if (this.fleetConfig) {
|
|
@@ -2698,73 +2713,80 @@ export class FleetManager {
|
|
|
2698
2713
|
}
|
|
2699
2714
|
}, 5 * 60_000);
|
|
2700
2715
|
}
|
|
2701
|
-
/**
|
|
2716
|
+
/**
|
|
2717
|
+
* Patch only values changed in the effective config into the original YAML
|
|
2718
|
+
* document. Unknown keys, explicit overrides and comments remain untouched.
|
|
2719
|
+
*/
|
|
2702
2720
|
saveFleetConfig() {
|
|
2703
2721
|
if (!this.fleetConfig || !this.configPath)
|
|
2704
2722
|
return;
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
}
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
}
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2723
|
+
if (!this.savedFleetConfigSnapshot)
|
|
2724
|
+
this.savedFleetConfigSnapshot = structuredClone(this.fleetConfig);
|
|
2725
|
+
// Re-read immediately before patching so an unrelated concurrent/manual
|
|
2726
|
+
// edit is retained. Invalid concurrent YAML is never overwritten.
|
|
2727
|
+
const source = existsSync(this.configPath) ? readFileSync(this.configPath, "utf-8") : "{}\n";
|
|
2728
|
+
this.rawFleetDocument = parseDocument(source, { keepSourceTokens: true });
|
|
2729
|
+
if (this.rawFleetDocument.errors.length > 0) {
|
|
2730
|
+
throw new Error(`Refusing to overwrite invalid fleet.yaml: ${this.rawFleetDocument.errors[0].message}`);
|
|
2731
|
+
}
|
|
2732
|
+
this.rawFleetConfig = loadRawFleetConfig(this.configPath);
|
|
2733
|
+
this.patchFleetDocument(this.rawFleetDocument, [], this.savedFleetConfigSnapshot, this.fleetConfig);
|
|
2734
|
+
const output = String(this.rawFleetDocument);
|
|
2735
|
+
const tempPath = `${this.configPath}.tmp-${process.pid}`;
|
|
2736
|
+
writeFileSync(tempPath, output, "utf-8");
|
|
2737
|
+
if (existsSync(this.configPath))
|
|
2738
|
+
chmodSync(tempPath, statSync(this.configPath).mode);
|
|
2739
|
+
renameSync(tempPath, this.configPath);
|
|
2740
|
+
this.rawFleetConfig = loadRawFleetConfig(this.configPath);
|
|
2741
|
+
this.savedFleetConfigSnapshot = structuredClone(this.fleetConfig);
|
|
2742
|
+
this.logger.info({ path: this.configPath }, "Saved fleet config (lossless patch)");
|
|
2743
|
+
}
|
|
2744
|
+
patchFleetDocument(document, path, before, after) {
|
|
2745
|
+
if (Object.is(before, after))
|
|
2746
|
+
return;
|
|
2747
|
+
if (Array.isArray(before) && Array.isArray(after)) {
|
|
2748
|
+
const shared = Math.min(before.length, after.length);
|
|
2749
|
+
for (let i = 0; i < shared; i++) {
|
|
2750
|
+
this.patchFleetDocument(document, [...path, i], before[i], after[i]);
|
|
2751
|
+
}
|
|
2752
|
+
// Remove from the end so YAML sequence indexes do not shift underneath us.
|
|
2753
|
+
for (let i = before.length - 1; i >= after.length; i--)
|
|
2754
|
+
document.deleteIn([...path, i]);
|
|
2755
|
+
for (let i = shared; i < after.length; i++)
|
|
2756
|
+
document.setIn([...path, i], after[i]);
|
|
2757
|
+
return;
|
|
2758
|
+
}
|
|
2759
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
2760
|
+
if (isRecord(before) && isRecord(after)) {
|
|
2761
|
+
const keys = new Set([...Object.keys(before), ...Object.keys(after)]);
|
|
2762
|
+
for (const key of keys) {
|
|
2763
|
+
// `channel` is a derived alias when the raw file uses `channels`.
|
|
2764
|
+
if (path.length === 0 && key === "channel" && this.rawFleetConfig.channels)
|
|
2765
|
+
continue;
|
|
2766
|
+
// Conversely, `channels` is a normalized alias for a legacy `channel`.
|
|
2767
|
+
// Keep the user's original shape unless the caller explicitly removed
|
|
2768
|
+
// `channel` (the Settings channels endpoint intentionally migrates it).
|
|
2769
|
+
if (path.length === 0 && key === "channels" && this.rawFleetConfig.channel && !this.rawFleetConfig.channels && after.channel !== undefined)
|
|
2770
|
+
continue;
|
|
2771
|
+
this.patchFleetDocument(document, [...path, key], before[key], after[key]);
|
|
2772
|
+
}
|
|
2773
|
+
return;
|
|
2774
|
+
}
|
|
2775
|
+
if (after === undefined) {
|
|
2776
|
+
document.deleteIn(path);
|
|
2777
|
+
}
|
|
2778
|
+
else if (path.length === 0) {
|
|
2779
|
+
document.contents = document.createNode(after);
|
|
2780
|
+
}
|
|
2781
|
+
else {
|
|
2782
|
+
const currentNode = document.getIn(path, true);
|
|
2783
|
+
if (isScalar(currentNode) && (after === null || typeof after !== "object")) {
|
|
2784
|
+
currentNode.value = after;
|
|
2785
|
+
}
|
|
2786
|
+
else {
|
|
2787
|
+
document.setIn(path, after);
|
|
2788
|
+
}
|
|
2789
|
+
}
|
|
2768
2790
|
}
|
|
2769
2791
|
async removeInstance(name) {
|
|
2770
2792
|
// Clean up schedules (scheduler is fleet-level, not lifecycle-level)
|