@karmaniverous/jeeves 0.4.1 → 0.4.3

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.
@@ -261,14 +261,14 @@ const PLATFORM_COMPONENTS = [
261
261
  * Core library version, inlined at build time.
262
262
  *
263
263
  * @remarks
264
- * The `0.4.0` placeholder is replaced by
264
+ * The `0.4.2` placeholder is replaced by
265
265
  * `@rollup/plugin-replace` during the build with the actual version
266
266
  * from `package.json`. This ensures the correct version survives
267
267
  * when consumers bundle core into their own dist (where runtime
268
268
  * `import.meta.url`-based resolution would find the wrong package.json).
269
269
  */
270
270
  /** The core library version from package.json (inlined at build time). */
271
- const CORE_VERSION = '0.4.0';
271
+ const CORE_VERSION = '0.4.2';
272
272
 
273
273
  /**
274
274
  * Dynamic discovery of installed Jeeves component CLIs.
@@ -119,14 +119,14 @@ const COMPONENT_VERSIONS_FILE = 'component-versions.json';
119
119
  * Core library version, inlined at build time.
120
120
  *
121
121
  * @remarks
122
- * The `0.4.0` placeholder is replaced by
122
+ * The `0.4.2` placeholder is replaced by
123
123
  * `@rollup/plugin-replace` during the build with the actual version
124
124
  * from `package.json`. This ensures the correct version survives
125
125
  * when consumers bundle core into their own dist (where runtime
126
126
  * `import.meta.url`-based resolution would find the wrong package.json).
127
127
  */
128
128
  /** The core library version from package.json (inlined at build time). */
129
- const CORE_VERSION = '0.4.0';
129
+ const CORE_VERSION = '0.4.2';
130
130
 
131
131
  /**
132
132
  * Shared file I/O helpers for managed section operations.
@@ -162,6 +162,19 @@ z.object({
162
162
  .args(z.record(z.unknown()))
163
163
  .returns(z.promise(z.void()))
164
164
  .optional(),
165
+ /**
166
+ * Custom merge function for config apply. Receives the existing config
167
+ * and the patch, returns the merged result. Optional — if omitted,
168
+ * the default deep-merge (object-recursive, array-replacing) is used.
169
+ *
170
+ * Use this to implement domain-specific merge strategies such as
171
+ * name-based array merging for inference rules.
172
+ */
173
+ customMerge: z
174
+ .function()
175
+ .args(z.record(z.unknown()), z.record(z.unknown()))
176
+ .returns(z.record(z.unknown()))
177
+ .optional(),
165
178
  /**
166
179
  * Returns command + args for launching the service process.
167
180
  * Consumed by `start` CLI command and `service install`.
@@ -661,7 +674,7 @@ function createServiceManager(descriptor) {
661
674
  * Standard commands:
662
675
  * - `start -c <path>` - Launch the service process (foreground)
663
676
  * - `status [-p port]` - Probe service health
664
- * - `config [jsonpath] [-p port]` - Query running config
677
+ * - `config [jsonpath] [-p port]` - Query running config (jsonpath optional)
665
678
  * - `config validate -c <path>` - Validate a config file
666
679
  * - `config apply [-p port] [--file path] [--replace]` - Apply config patch
667
680
  * - `init [-o path]` - Generate default config
@@ -717,10 +730,7 @@ function createServiceCli(descriptor) {
717
730
  // --- config ---
718
731
  const configCmd = program
719
732
  .command('config')
720
- .description('Query or manage service configuration');
721
- configCmd
722
- .command('query')
723
- .description('Query running service config via JSONPath')
733
+ .description('Query or manage service configuration')
724
734
  .argument('[jsonpath]', 'JSONPath expression')
725
735
  .option('-p, --port <port>', 'Service port', String(descriptor.defaultPort))
726
736
  .action(async (jsonpath, opts) => {
@@ -777,9 +787,12 @@ function createServiceCli(descriptor) {
777
787
  patch = JSON.parse(input);
778
788
  }
779
789
  }
780
- const qs = opts.replace ? '?replace=true' : '';
790
+ const body = { patch };
791
+ if (opts.replace) {
792
+ body.replace = true;
793
+ }
781
794
  try {
782
- const result = await postJson(`${url}/config/apply${qs}`, patch);
795
+ const result = await postJson(`${url}/config/apply`, body);
783
796
  console.log(JSON.stringify(result, null, 2));
784
797
  }
785
798
  catch (err) {
package/dist/index.d.ts CHANGED
@@ -130,6 +130,15 @@ declare const jeevesComponentDescriptorSchema: z.ZodObject<{
130
130
  * write-only (service picks up changes on restart).
131
131
  */
132
132
  onConfigApply: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodRecord<z.ZodString, z.ZodUnknown>], z.ZodUnknown>, z.ZodPromise<z.ZodVoid>>>;
133
+ /**
134
+ * Custom merge function for config apply. Receives the existing config
135
+ * and the patch, returns the merged result. Optional — if omitted,
136
+ * the default deep-merge (object-recursive, array-replacing) is used.
137
+ *
138
+ * Use this to implement domain-specific merge strategies such as
139
+ * name-based array merging for inference rules.
140
+ */
141
+ customMerge: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodRecord<z.ZodString, z.ZodUnknown>], z.ZodUnknown>, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
133
142
  /**
134
143
  * Returns command + args for launching the service process.
135
144
  * Consumed by `start` CLI command and `service install`.
@@ -171,6 +180,7 @@ declare const jeevesComponentDescriptorSchema: z.ZodObject<{
171
180
  generateToolsContent: (...args: unknown[]) => string;
172
181
  serviceName?: string | undefined;
173
182
  onConfigApply?: ((args_0: Record<string, unknown>, ...args: unknown[]) => Promise<void>) | undefined;
183
+ customMerge?: ((args_0: Record<string, unknown>, args_1: Record<string, unknown>, ...args: unknown[]) => Record<string, unknown>) | undefined;
174
184
  dependencies?: {
175
185
  hard: string[];
176
186
  soft: string[];
@@ -192,6 +202,7 @@ declare const jeevesComponentDescriptorSchema: z.ZodObject<{
192
202
  generateToolsContent: (...args: unknown[]) => string;
193
203
  serviceName?: string | undefined;
194
204
  onConfigApply?: ((args_0: Record<string, unknown>, ...args: unknown[]) => Promise<void>) | undefined;
205
+ customMerge?: ((args_0: Record<string, unknown>, args_1: Record<string, unknown>, ...args: unknown[]) => Record<string, unknown>) | undefined;
195
206
  dependencies?: {
196
207
  hard: string[];
197
208
  soft: string[];
@@ -383,7 +394,7 @@ declare function createPluginCli(options: CreatePluginCliOptions): Command;
383
394
  * Standard commands:
384
395
  * - `start -c <path>` - Launch the service process (foreground)
385
396
  * - `status [-p port]` - Probe service health
386
- * - `config [jsonpath] [-p port]` - Query running config
397
+ * - `config [jsonpath] [-p port]` - Query running config (jsonpath optional)
387
398
  * - `config validate -c <path>` - Validate a config file
388
399
  * - `config apply [-p port] [--file path] [--replace]` - Apply config patch
389
400
  * - `init [-o path]` - Generate default config
package/dist/index.js CHANGED
@@ -176,14 +176,14 @@ const PLATFORM_COMPONENTS = [
176
176
  * Core library version, inlined at build time.
177
177
  *
178
178
  * @remarks
179
- * The `0.4.0` placeholder is replaced by
179
+ * The `0.4.2` placeholder is replaced by
180
180
  * `@rollup/plugin-replace` during the build with the actual version
181
181
  * from `package.json`. This ensures the correct version survives
182
182
  * when consumers bundle core into their own dist (where runtime
183
183
  * `import.meta.url`-based resolution would find the wrong package.json).
184
184
  */
185
185
  /** The core library version from package.json (inlined at build time). */
186
- const CORE_VERSION = '0.4.0';
186
+ const CORE_VERSION = '0.4.2';
187
187
 
188
188
  /**
189
189
  * Workspace and config root initialization.
@@ -405,7 +405,8 @@ function createConfigApplyHandler(descriptor) {
405
405
  // Read existing config
406
406
  const existing = readConfigFile(configPath);
407
407
  // Merge or replace
408
- const merged = replace ? { ...patch } : deepMerge(existing, patch);
408
+ const mergeFn = descriptor.customMerge ?? deepMerge;
409
+ const merged = replace ? { ...patch } : mergeFn(existing, patch);
409
410
  // Validate against schema
410
411
  const schema = descriptor.configSchema;
411
412
  const parseResult = schema.safeParse(merged);
@@ -1501,6 +1502,19 @@ const jeevesComponentDescriptorSchema = z.object({
1501
1502
  .args(z.record(z.unknown()))
1502
1503
  .returns(z.promise(z.void()))
1503
1504
  .optional(),
1505
+ /**
1506
+ * Custom merge function for config apply. Receives the existing config
1507
+ * and the patch, returns the merged result. Optional — if omitted,
1508
+ * the default deep-merge (object-recursive, array-replacing) is used.
1509
+ *
1510
+ * Use this to implement domain-specific merge strategies such as
1511
+ * name-based array merging for inference rules.
1512
+ */
1513
+ customMerge: z
1514
+ .function()
1515
+ .args(z.record(z.unknown()), z.record(z.unknown()))
1516
+ .returns(z.record(z.unknown()))
1517
+ .optional(),
1504
1518
  /**
1505
1519
  * Returns command + args for launching the service process.
1506
1520
  * Consumed by `start` CLI command and `service install`.
@@ -1991,7 +2005,7 @@ function createServiceManager(descriptor) {
1991
2005
  * Standard commands:
1992
2006
  * - `start -c <path>` - Launch the service process (foreground)
1993
2007
  * - `status [-p port]` - Probe service health
1994
- * - `config [jsonpath] [-p port]` - Query running config
2008
+ * - `config [jsonpath] [-p port]` - Query running config (jsonpath optional)
1995
2009
  * - `config validate -c <path>` - Validate a config file
1996
2010
  * - `config apply [-p port] [--file path] [--replace]` - Apply config patch
1997
2011
  * - `init [-o path]` - Generate default config
@@ -2047,10 +2061,7 @@ function createServiceCli(descriptor) {
2047
2061
  // --- config ---
2048
2062
  const configCmd = program
2049
2063
  .command('config')
2050
- .description('Query or manage service configuration');
2051
- configCmd
2052
- .command('query')
2053
- .description('Query running service config via JSONPath')
2064
+ .description('Query or manage service configuration')
2054
2065
  .argument('[jsonpath]', 'JSONPath expression')
2055
2066
  .option('-p, --port <port>', 'Service port', String(descriptor.defaultPort))
2056
2067
  .action(async (jsonpath, opts) => {
@@ -2107,9 +2118,12 @@ function createServiceCli(descriptor) {
2107
2118
  patch = JSON.parse(input);
2108
2119
  }
2109
2120
  }
2110
- const qs = opts.replace ? '?replace=true' : '';
2121
+ const body = { patch };
2122
+ if (opts.replace) {
2123
+ body.replace = true;
2124
+ }
2111
2125
  try {
2112
- const result = await postJson(`${url}/config/apply${qs}`, patch);
2126
+ const result = await postJson(`${url}/config/apply`, body);
2113
2127
  console.log(JSON.stringify(result, null, 2));
2114
2128
  }
2115
2129
  catch (err) {
@@ -3845,7 +3859,9 @@ function createPluginToolset(descriptor) {
3845
3859
  return fail('Missing required parameter: config');
3846
3860
  }
3847
3861
  try {
3848
- const result = await postJson(`${baseUrl}/config/apply`, config);
3862
+ const result = await postJson(`${baseUrl}/config/apply`, {
3863
+ patch: config,
3864
+ });
3849
3865
  return ok(result);
3850
3866
  }
3851
3867
  catch (err) {
package/package.json CHANGED
@@ -139,5 +139,5 @@
139
139
  },
140
140
  "type": "module",
141
141
  "types": "dist/index.d.ts",
142
- "version": "0.4.1"
142
+ "version": "0.4.3"
143
143
  }