@karmaniverous/jeeves 0.4.3 → 0.4.5
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/jeeves/index.js +21 -9
- package/dist/cli/plugin/index.js +15 -4
- package/dist/cli/service/index.js +33 -25
- package/dist/index.d.ts +20 -139
- package/dist/index.js +54 -34
- package/package.json +26 -26
package/dist/cli/jeeves/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import * as commander from 'commander';
|
|
3
3
|
import { execSync, spawnSync } from 'node:child_process';
|
|
4
|
-
import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync, cpSync, rmSync } from 'node:fs';
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, renameSync, unlinkSync, mkdirSync, cpSync, rmSync } from 'node:fs';
|
|
5
5
|
import { join, dirname } from 'node:path';
|
|
6
|
-
import { gte } from 'semver';
|
|
6
|
+
import { valid, gte } from 'semver';
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { lock } from 'proper-lockfile';
|
|
9
9
|
import { fileURLToPath } from 'node:url';
|
|
@@ -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.
|
|
264
|
+
* The `0.4.4` 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.
|
|
271
|
+
const CORE_VERSION = '0.4.4';
|
|
272
272
|
|
|
273
273
|
/**
|
|
274
274
|
* Dynamic discovery of installed Jeeves component CLIs.
|
|
@@ -409,7 +409,7 @@ var init$1 = /*#__PURE__*/Object.freeze({
|
|
|
409
409
|
/** Zod schema for a service entry in core config. */
|
|
410
410
|
const serviceEntrySchema = z.object({
|
|
411
411
|
/** Service URL (must be a valid URL). */
|
|
412
|
-
url: z.
|
|
412
|
+
url: z.url().describe('Service URL'),
|
|
413
413
|
});
|
|
414
414
|
/** Default bind address for all Jeeves services. */
|
|
415
415
|
const DEFAULT_BIND_ADDRESS = '0.0.0.0';
|
|
@@ -443,7 +443,7 @@ const coreConfigSchema = z.object({
|
|
|
443
443
|
.default(3600)
|
|
444
444
|
.describe('Cache TTL in seconds'),
|
|
445
445
|
})
|
|
446
|
-
.
|
|
446
|
+
.prefault({})
|
|
447
447
|
.describe('Registry cache settings'),
|
|
448
448
|
});
|
|
449
449
|
/**
|
|
@@ -598,7 +598,18 @@ function atomicWrite(filePath, content) {
|
|
|
598
598
|
const dir = dirname(filePath);
|
|
599
599
|
const tempPath = join(dir, `.${String(Date.now())}.tmp`);
|
|
600
600
|
writeFileSync(tempPath, content, 'utf-8');
|
|
601
|
-
|
|
601
|
+
try {
|
|
602
|
+
renameSync(tempPath, filePath);
|
|
603
|
+
}
|
|
604
|
+
catch (err) {
|
|
605
|
+
try {
|
|
606
|
+
unlinkSync(tempPath);
|
|
607
|
+
}
|
|
608
|
+
catch {
|
|
609
|
+
/* best-effort cleanup */
|
|
610
|
+
}
|
|
611
|
+
throw err;
|
|
612
|
+
}
|
|
602
613
|
}
|
|
603
614
|
/**
|
|
604
615
|
* Execute a callback while holding a file lock.
|
|
@@ -1460,8 +1471,9 @@ function formatEndMarker(markerText) {
|
|
|
1460
1471
|
* @returns `true` if the writer should proceed with the write.
|
|
1461
1472
|
*/
|
|
1462
1473
|
function shouldWrite(myVersion, existing, stalenessThresholdMs = STALENESS_THRESHOLD_MS) {
|
|
1463
|
-
//
|
|
1464
|
-
|
|
1474
|
+
// Always write when version comparison is impossible: invalid/placeholder
|
|
1475
|
+
// versions (dev/test mode) or no existing stamp to compare against.
|
|
1476
|
+
if (!valid(myVersion) || !existing || !valid(existing.version))
|
|
1465
1477
|
return true;
|
|
1466
1478
|
// My version >= stamped version — always write (I'm current or newer)
|
|
1467
1479
|
if (gte(myVersion, existing.version))
|
package/dist/cli/plugin/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { writeFileSync, renameSync, existsSync, readFileSync, rmSync, mkdirSync, readdirSync, copyFileSync } from 'node:fs';
|
|
2
|
+
import { writeFileSync, renameSync, unlinkSync, existsSync, readFileSync, rmSync, mkdirSync, readdirSync, copyFileSync } from 'node:fs';
|
|
3
3
|
import { dirname, join, resolve } from 'node:path';
|
|
4
4
|
import * as commander from 'commander';
|
|
5
5
|
import { lock } from 'proper-lockfile';
|
|
@@ -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.
|
|
122
|
+
* The `0.4.4` 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.
|
|
129
|
+
const CORE_VERSION = '0.4.4';
|
|
130
130
|
|
|
131
131
|
/**
|
|
132
132
|
* Shared file I/O helpers for managed section operations.
|
|
@@ -152,7 +152,18 @@ function atomicWrite(filePath, content) {
|
|
|
152
152
|
const dir = dirname(filePath);
|
|
153
153
|
const tempPath = join(dir, `.${String(Date.now())}.tmp`);
|
|
154
154
|
writeFileSync(tempPath, content, 'utf-8');
|
|
155
|
-
|
|
155
|
+
try {
|
|
156
|
+
renameSync(tempPath, filePath);
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
try {
|
|
160
|
+
unlinkSync(tempPath);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
/* best-effort cleanup */
|
|
164
|
+
}
|
|
165
|
+
throw err;
|
|
166
|
+
}
|
|
156
167
|
}
|
|
157
168
|
/**
|
|
158
169
|
* Execute a callback while holding a file lock.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { execSync, spawn } from 'node:child_process';
|
|
3
2
|
import { existsSync, unlinkSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
|
|
4
3
|
import { join } from 'node:path';
|
|
5
4
|
import * as commander from 'commander';
|
|
6
5
|
import { z } from 'zod';
|
|
6
|
+
import { execSync } from 'node:child_process';
|
|
7
7
|
import { homedir } from 'node:os';
|
|
8
8
|
|
|
9
9
|
function getDefaultExportFromCjs (x) {
|
|
@@ -151,16 +151,20 @@ z.object({
|
|
|
151
151
|
/** Config file name (e.g., 'jeeves-watcher.config.json'). */
|
|
152
152
|
configFileName: z.string().min(1),
|
|
153
153
|
/** Returns a default config object for `init`. */
|
|
154
|
-
initTemplate: z.function(
|
|
154
|
+
initTemplate: z.function({
|
|
155
|
+
input: [],
|
|
156
|
+
output: z.record(z.string(), z.unknown()),
|
|
157
|
+
}),
|
|
155
158
|
/**
|
|
156
159
|
* Service-side callback after config apply. Receives the merged,
|
|
157
160
|
* validated config (not the raw patch). Optional — if omitted,
|
|
158
161
|
* write-only (service picks up changes on restart).
|
|
159
162
|
*/
|
|
160
163
|
onConfigApply: z
|
|
161
|
-
.function(
|
|
162
|
-
.
|
|
163
|
-
|
|
164
|
+
.function({
|
|
165
|
+
input: [z.record(z.string(), z.unknown())],
|
|
166
|
+
output: z.promise(z.void()),
|
|
167
|
+
})
|
|
164
168
|
.optional(),
|
|
165
169
|
/**
|
|
166
170
|
* Custom merge function for config apply. Receives the existing config
|
|
@@ -171,15 +175,27 @@ z.object({
|
|
|
171
175
|
* name-based array merging for inference rules.
|
|
172
176
|
*/
|
|
173
177
|
customMerge: z
|
|
174
|
-
.function(
|
|
175
|
-
|
|
176
|
-
|
|
178
|
+
.function({
|
|
179
|
+
input: [
|
|
180
|
+
z.record(z.string(), z.unknown()),
|
|
181
|
+
z.record(z.string(), z.unknown()),
|
|
182
|
+
],
|
|
183
|
+
output: z.record(z.string(), z.unknown()),
|
|
184
|
+
})
|
|
177
185
|
.optional(),
|
|
178
186
|
/**
|
|
179
187
|
* Returns command + args for launching the service process.
|
|
180
|
-
* Consumed by `
|
|
188
|
+
* Consumed by `service install`.
|
|
181
189
|
*/
|
|
182
|
-
startCommand: z.function(
|
|
190
|
+
startCommand: z.function({
|
|
191
|
+
input: [z.string()],
|
|
192
|
+
output: z.array(z.string()),
|
|
193
|
+
}),
|
|
194
|
+
/** In-process service entry point for the CLI `start` command. */
|
|
195
|
+
run: z.function({
|
|
196
|
+
input: [z.string()],
|
|
197
|
+
output: z.promise(z.void()),
|
|
198
|
+
}),
|
|
183
199
|
/** TOOLS.md section name (e.g., 'Watcher'). */
|
|
184
200
|
sectionId: z.string().min(1, 'sectionId must be a non-empty string'),
|
|
185
201
|
/** Refresh interval in seconds (must be a prime number). */
|
|
@@ -187,25 +203,23 @@ z.object({
|
|
|
187
203
|
message: 'refreshIntervalSeconds must be a prime number',
|
|
188
204
|
}),
|
|
189
205
|
/** Produce the component's TOOLS.md section content. */
|
|
190
|
-
generateToolsContent: z.function(
|
|
206
|
+
generateToolsContent: z.function({ input: [], output: z.string() }),
|
|
191
207
|
/** Component dependencies for HEARTBEAT alert suppression. */
|
|
192
208
|
dependencies: z
|
|
193
209
|
.object({
|
|
210
|
+
/** Components that must be healthy for this component to function. */
|
|
194
211
|
hard: z.array(z.string()),
|
|
212
|
+
/** Components that improve behavior but are not strictly required. */
|
|
195
213
|
soft: z.array(z.string()),
|
|
196
214
|
})
|
|
197
215
|
.optional(),
|
|
198
216
|
/** Extension point: add custom CLI commands to the service CLI. */
|
|
199
217
|
customCliCommands: z
|
|
200
|
-
.function()
|
|
201
|
-
.args(z.custom())
|
|
202
|
-
.returns(z.void())
|
|
218
|
+
.function({ input: [z.custom()], output: z.void() })
|
|
203
219
|
.optional(),
|
|
204
220
|
/** Extension point: return additional plugin tool descriptors. */
|
|
205
221
|
customPluginTools: z
|
|
206
|
-
.function()
|
|
207
|
-
.args(z.custom())
|
|
208
|
-
.returns(z.array(z.unknown()))
|
|
222
|
+
.function({ input: [z.custom()], output: z.array(z.unknown()) })
|
|
209
223
|
.optional(),
|
|
210
224
|
});
|
|
211
225
|
/**
|
|
@@ -701,14 +715,8 @@ function createServiceCli(descriptor) {
|
|
|
701
715
|
.command('start')
|
|
702
716
|
.description('Launch the service process (foreground)')
|
|
703
717
|
.requiredOption('-c, --config <path>', 'Config file path')
|
|
704
|
-
.action((opts) => {
|
|
705
|
-
|
|
706
|
-
const proc = spawn(cmdArgs[0], cmdArgs.slice(1), {
|
|
707
|
-
stdio: 'inherit',
|
|
708
|
-
});
|
|
709
|
-
proc.on('exit', (code) => {
|
|
710
|
-
process.exit(code ?? 1);
|
|
711
|
-
});
|
|
718
|
+
.action(async (opts) => {
|
|
719
|
+
await descriptor.run(opts.config);
|
|
712
720
|
});
|
|
713
721
|
// --- status ---
|
|
714
722
|
program
|
package/dist/index.d.ts
CHANGED
|
@@ -106,110 +106,29 @@ declare function isPrime(n: number): boolean;
|
|
|
106
106
|
* plugin tools, and HTTP handlers.
|
|
107
107
|
*/
|
|
108
108
|
declare const jeevesComponentDescriptorSchema: z.ZodObject<{
|
|
109
|
-
/** Component name (e.g., 'watcher', 'runner', 'server', 'meta'). */
|
|
110
109
|
name: z.ZodString;
|
|
111
|
-
/** Component version (from package.json). */
|
|
112
110
|
version: z.ZodString;
|
|
113
|
-
/** npm package name for the service. */
|
|
114
111
|
servicePackage: z.ZodString;
|
|
115
|
-
/** npm package name for the plugin. */
|
|
116
112
|
pluginPackage: z.ZodString;
|
|
117
|
-
/** System service name. Defaults to `jeeves-${name}` when not provided. */
|
|
118
113
|
serviceName: z.ZodOptional<z.ZodString>;
|
|
119
|
-
/** Default port for the service's HTTP API. */
|
|
120
114
|
defaultPort: z.ZodNumber;
|
|
121
|
-
|
|
122
|
-
configSchema: z.ZodType<z.ZodTypeAny, z.ZodTypeDef, z.ZodTypeAny>;
|
|
123
|
-
/** Config file name (e.g., 'jeeves-watcher.config.json'). */
|
|
115
|
+
configSchema: z.ZodCustom<z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>, z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
124
116
|
configFileName: z.ZodString;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
* write-only (service picks up changes on restart).
|
|
131
|
-
*/
|
|
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>>>;
|
|
142
|
-
/**
|
|
143
|
-
* Returns command + args for launching the service process.
|
|
144
|
-
* Consumed by `start` CLI command and `service install`.
|
|
145
|
-
*/
|
|
146
|
-
startCommand: z.ZodFunction<z.ZodTuple<[z.ZodString], z.ZodUnknown>, z.ZodArray<z.ZodString, "many">>;
|
|
147
|
-
/** TOOLS.md section name (e.g., 'Watcher'). */
|
|
117
|
+
initTemplate: z.ZodFunction<z.ZodTuple<readonly [], null>, z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
118
|
+
onConfigApply: z.ZodOptional<z.ZodFunction<z.ZodTuple<readonly [z.ZodRecord<z.ZodString, z.ZodUnknown>], null>, z.ZodPromise<z.ZodVoid>>>;
|
|
119
|
+
customMerge: z.ZodOptional<z.ZodFunction<z.ZodTuple<readonly [z.ZodRecord<z.ZodString, z.ZodUnknown>, z.ZodRecord<z.ZodString, z.ZodUnknown>], null>, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
120
|
+
startCommand: z.ZodFunction<z.ZodTuple<readonly [z.ZodString], null>, z.ZodArray<z.ZodString>>;
|
|
121
|
+
run: z.ZodFunction<z.ZodTuple<readonly [z.ZodString], null>, z.ZodPromise<z.ZodVoid>>;
|
|
148
122
|
sectionId: z.ZodString;
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
/** Produce the component's TOOLS.md section content. */
|
|
152
|
-
generateToolsContent: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodString>;
|
|
153
|
-
/** Component dependencies for HEARTBEAT alert suppression. */
|
|
123
|
+
refreshIntervalSeconds: z.ZodNumber;
|
|
124
|
+
generateToolsContent: z.ZodFunction<z.ZodTuple<readonly [], null>, z.ZodString>;
|
|
154
125
|
dependencies: z.ZodOptional<z.ZodObject<{
|
|
155
|
-
hard: z.ZodArray<z.ZodString
|
|
156
|
-
soft: z.ZodArray<z.ZodString
|
|
157
|
-
},
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
hard: string[];
|
|
162
|
-
soft: string[];
|
|
163
|
-
}>>;
|
|
164
|
-
/** Extension point: add custom CLI commands to the service CLI. */
|
|
165
|
-
customCliCommands: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodType<Command<[], {}, {}>, z.ZodTypeDef, Command<[], {}, {}>>], z.ZodUnknown>, z.ZodVoid>>;
|
|
166
|
-
/** Extension point: return additional plugin tool descriptors. */
|
|
167
|
-
customPluginTools: z.ZodOptional<z.ZodFunction<z.ZodTuple<[z.ZodType<PluginApi, z.ZodTypeDef, PluginApi>], z.ZodUnknown>, z.ZodArray<z.ZodUnknown, "many">>>;
|
|
168
|
-
}, "strip", z.ZodTypeAny, {
|
|
169
|
-
name: string;
|
|
170
|
-
version: string;
|
|
171
|
-
servicePackage: string;
|
|
172
|
-
pluginPackage: string;
|
|
173
|
-
defaultPort: number;
|
|
174
|
-
configSchema: z.ZodTypeAny;
|
|
175
|
-
configFileName: string;
|
|
176
|
-
initTemplate: (...args: unknown[]) => Record<string, unknown>;
|
|
177
|
-
startCommand: (args_0: string, ...args: unknown[]) => string[];
|
|
178
|
-
sectionId: string;
|
|
179
|
-
refreshIntervalSeconds: number;
|
|
180
|
-
generateToolsContent: (...args: unknown[]) => string;
|
|
181
|
-
serviceName?: string | undefined;
|
|
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;
|
|
184
|
-
dependencies?: {
|
|
185
|
-
hard: string[];
|
|
186
|
-
soft: string[];
|
|
187
|
-
} | undefined;
|
|
188
|
-
customCliCommands?: ((args_0: Command<[], {}, {}>, ...args: unknown[]) => void) | undefined;
|
|
189
|
-
customPluginTools?: ((args_0: PluginApi, ...args: unknown[]) => unknown[]) | undefined;
|
|
190
|
-
}, {
|
|
191
|
-
name: string;
|
|
192
|
-
version: string;
|
|
193
|
-
servicePackage: string;
|
|
194
|
-
pluginPackage: string;
|
|
195
|
-
defaultPort: number;
|
|
196
|
-
configSchema: z.ZodTypeAny;
|
|
197
|
-
configFileName: string;
|
|
198
|
-
initTemplate: (...args: unknown[]) => Record<string, unknown>;
|
|
199
|
-
startCommand: (args_0: string, ...args: unknown[]) => string[];
|
|
200
|
-
sectionId: string;
|
|
201
|
-
refreshIntervalSeconds: number;
|
|
202
|
-
generateToolsContent: (...args: unknown[]) => string;
|
|
203
|
-
serviceName?: string | undefined;
|
|
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;
|
|
206
|
-
dependencies?: {
|
|
207
|
-
hard: string[];
|
|
208
|
-
soft: string[];
|
|
209
|
-
} | undefined;
|
|
210
|
-
customCliCommands?: ((args_0: Command<[], {}, {}>, ...args: unknown[]) => void) | undefined;
|
|
211
|
-
customPluginTools?: ((args_0: PluginApi, ...args: unknown[]) => unknown[]) | undefined;
|
|
212
|
-
}>;
|
|
126
|
+
hard: z.ZodArray<z.ZodString>;
|
|
127
|
+
soft: z.ZodArray<z.ZodString>;
|
|
128
|
+
}, z.core.$strip>>;
|
|
129
|
+
customCliCommands: z.ZodOptional<z.ZodFunction<z.ZodTuple<readonly [z.ZodCustom<Command<[], {}, {}>, Command<[], {}, {}>>], null>, z.ZodVoid>>;
|
|
130
|
+
customPluginTools: z.ZodOptional<z.ZodFunction<z.ZodTuple<readonly [z.ZodCustom<PluginApi, PluginApi>], null>, z.ZodArray<z.ZodUnknown>>>;
|
|
131
|
+
}, z.core.$strip>;
|
|
213
132
|
/** Inferred TypeScript type for the component descriptor. */
|
|
214
133
|
type JeevesComponentDescriptor = z.infer<typeof jeevesComponentDescriptorSchema>;
|
|
215
134
|
/**
|
|
@@ -871,54 +790,16 @@ declare const CORE_VERSION: string;
|
|
|
871
790
|
declare const DEFAULT_BIND_ADDRESS = "0.0.0.0";
|
|
872
791
|
/** Zod schema for the core config file. */
|
|
873
792
|
declare const coreConfigSchema: z.ZodObject<{
|
|
874
|
-
/** JSON Schema pointer for IDE autocomplete. */
|
|
875
793
|
$schema: z.ZodOptional<z.ZodString>;
|
|
876
|
-
|
|
877
|
-
owners: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
878
|
-
/**
|
|
879
|
-
* Bind address for all Jeeves services. Default: `0.0.0.0` (all interfaces).
|
|
880
|
-
* Individual components can override in their own config.
|
|
881
|
-
*/
|
|
794
|
+
owners: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
882
795
|
bindAddress: z.ZodDefault<z.ZodString>;
|
|
883
|
-
/** Service URL overrides keyed by service name. */
|
|
884
796
|
services: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
url: string;
|
|
889
|
-
}, {
|
|
890
|
-
url: string;
|
|
891
|
-
}>>>;
|
|
892
|
-
/** Registry cache configuration. */
|
|
893
|
-
registryCache: z.ZodDefault<z.ZodObject<{
|
|
894
|
-
/** Cache TTL in seconds for npm registry queries. */
|
|
797
|
+
url: z.ZodURL;
|
|
798
|
+
}, z.core.$strip>>>;
|
|
799
|
+
registryCache: z.ZodPrefault<z.ZodObject<{
|
|
895
800
|
ttlSeconds: z.ZodDefault<z.ZodNumber>;
|
|
896
|
-
},
|
|
897
|
-
|
|
898
|
-
}, {
|
|
899
|
-
ttlSeconds?: number | undefined;
|
|
900
|
-
}>>;
|
|
901
|
-
}, "strip", z.ZodTypeAny, {
|
|
902
|
-
owners: string[];
|
|
903
|
-
bindAddress: string;
|
|
904
|
-
services: Record<string, {
|
|
905
|
-
url: string;
|
|
906
|
-
}>;
|
|
907
|
-
registryCache: {
|
|
908
|
-
ttlSeconds: number;
|
|
909
|
-
};
|
|
910
|
-
$schema?: string | undefined;
|
|
911
|
-
}, {
|
|
912
|
-
$schema?: string | undefined;
|
|
913
|
-
owners?: string[] | undefined;
|
|
914
|
-
bindAddress?: string | undefined;
|
|
915
|
-
services?: Record<string, {
|
|
916
|
-
url: string;
|
|
917
|
-
}> | undefined;
|
|
918
|
-
registryCache?: {
|
|
919
|
-
ttlSeconds?: number | undefined;
|
|
920
|
-
} | undefined;
|
|
921
|
-
}>;
|
|
801
|
+
}, z.core.$strip>>;
|
|
802
|
+
}, z.core.$strip>;
|
|
922
803
|
/** Core config type derived from the Zod schema. */
|
|
923
804
|
type CoreConfig = z.infer<typeof coreConfigSchema>;
|
|
924
805
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { writeFileSync, renameSync, existsSync, readFileSync, mkdirSync, rmSync, readdirSync, copyFileSync,
|
|
1
|
+
import { writeFileSync, renameSync, unlinkSync, existsSync, readFileSync, mkdirSync, rmSync, readdirSync, copyFileSync, cpSync } from 'node:fs';
|
|
2
2
|
import { join, dirname, resolve } from 'node:path';
|
|
3
3
|
import { lock } from 'proper-lockfile';
|
|
4
4
|
import { JSONPath } from 'jsonpath-plus';
|
|
5
5
|
import * as commander from 'commander';
|
|
6
|
-
import { gte, gt } from 'semver';
|
|
6
|
+
import { valid, gte, gt } from 'semver';
|
|
7
7
|
import { homedir } from 'node:os';
|
|
8
|
-
import { execSync, spawn } from 'node:child_process';
|
|
9
8
|
import { z } from 'zod';
|
|
9
|
+
import { execSync } from 'node:child_process';
|
|
10
10
|
import { fileURLToPath } from 'node:url';
|
|
11
11
|
import { packageDirectorySync } from 'package-directory';
|
|
12
12
|
|
|
@@ -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.
|
|
179
|
+
* The `0.4.4` 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.
|
|
186
|
+
const CORE_VERSION = '0.4.4';
|
|
187
187
|
|
|
188
188
|
/**
|
|
189
189
|
* Workspace and config root initialization.
|
|
@@ -291,7 +291,18 @@ function atomicWrite(filePath, content) {
|
|
|
291
291
|
const dir = dirname(filePath);
|
|
292
292
|
const tempPath = join(dir, `.${String(Date.now())}.tmp`);
|
|
293
293
|
writeFileSync(tempPath, content, 'utf-8');
|
|
294
|
-
|
|
294
|
+
try {
|
|
295
|
+
renameSync(tempPath, filePath);
|
|
296
|
+
}
|
|
297
|
+
catch (err) {
|
|
298
|
+
try {
|
|
299
|
+
unlinkSync(tempPath);
|
|
300
|
+
}
|
|
301
|
+
catch {
|
|
302
|
+
/* best-effort cleanup */
|
|
303
|
+
}
|
|
304
|
+
throw err;
|
|
305
|
+
}
|
|
295
306
|
}
|
|
296
307
|
/**
|
|
297
308
|
* Execute a callback while holding a file lock.
|
|
@@ -1002,8 +1013,9 @@ function formatEndMarker(markerText) {
|
|
|
1002
1013
|
* @returns `true` if the writer should proceed with the write.
|
|
1003
1014
|
*/
|
|
1004
1015
|
function shouldWrite(myVersion, existing, stalenessThresholdMs = STALENESS_THRESHOLD_MS) {
|
|
1005
|
-
//
|
|
1006
|
-
|
|
1016
|
+
// Always write when version comparison is impossible: invalid/placeholder
|
|
1017
|
+
// versions (dev/test mode) or no existing stamp to compare against.
|
|
1018
|
+
if (!valid(myVersion) || !existing || !valid(existing.version))
|
|
1007
1019
|
return true;
|
|
1008
1020
|
// My version >= stamped version — always write (I'm current or newer)
|
|
1009
1021
|
if (gte(myVersion, existing.version))
|
|
@@ -1491,16 +1503,20 @@ const jeevesComponentDescriptorSchema = z.object({
|
|
|
1491
1503
|
/** Config file name (e.g., 'jeeves-watcher.config.json'). */
|
|
1492
1504
|
configFileName: z.string().min(1),
|
|
1493
1505
|
/** Returns a default config object for `init`. */
|
|
1494
|
-
initTemplate: z.function(
|
|
1506
|
+
initTemplate: z.function({
|
|
1507
|
+
input: [],
|
|
1508
|
+
output: z.record(z.string(), z.unknown()),
|
|
1509
|
+
}),
|
|
1495
1510
|
/**
|
|
1496
1511
|
* Service-side callback after config apply. Receives the merged,
|
|
1497
1512
|
* validated config (not the raw patch). Optional — if omitted,
|
|
1498
1513
|
* write-only (service picks up changes on restart).
|
|
1499
1514
|
*/
|
|
1500
1515
|
onConfigApply: z
|
|
1501
|
-
.function(
|
|
1502
|
-
.
|
|
1503
|
-
|
|
1516
|
+
.function({
|
|
1517
|
+
input: [z.record(z.string(), z.unknown())],
|
|
1518
|
+
output: z.promise(z.void()),
|
|
1519
|
+
})
|
|
1504
1520
|
.optional(),
|
|
1505
1521
|
/**
|
|
1506
1522
|
* Custom merge function for config apply. Receives the existing config
|
|
@@ -1511,15 +1527,27 @@ const jeevesComponentDescriptorSchema = z.object({
|
|
|
1511
1527
|
* name-based array merging for inference rules.
|
|
1512
1528
|
*/
|
|
1513
1529
|
customMerge: z
|
|
1514
|
-
.function(
|
|
1515
|
-
|
|
1516
|
-
|
|
1530
|
+
.function({
|
|
1531
|
+
input: [
|
|
1532
|
+
z.record(z.string(), z.unknown()),
|
|
1533
|
+
z.record(z.string(), z.unknown()),
|
|
1534
|
+
],
|
|
1535
|
+
output: z.record(z.string(), z.unknown()),
|
|
1536
|
+
})
|
|
1517
1537
|
.optional(),
|
|
1518
1538
|
/**
|
|
1519
1539
|
* Returns command + args for launching the service process.
|
|
1520
|
-
* Consumed by `
|
|
1540
|
+
* Consumed by `service install`.
|
|
1521
1541
|
*/
|
|
1522
|
-
startCommand: z.function(
|
|
1542
|
+
startCommand: z.function({
|
|
1543
|
+
input: [z.string()],
|
|
1544
|
+
output: z.array(z.string()),
|
|
1545
|
+
}),
|
|
1546
|
+
/** In-process service entry point for the CLI `start` command. */
|
|
1547
|
+
run: z.function({
|
|
1548
|
+
input: [z.string()],
|
|
1549
|
+
output: z.promise(z.void()),
|
|
1550
|
+
}),
|
|
1523
1551
|
/** TOOLS.md section name (e.g., 'Watcher'). */
|
|
1524
1552
|
sectionId: z.string().min(1, 'sectionId must be a non-empty string'),
|
|
1525
1553
|
/** Refresh interval in seconds (must be a prime number). */
|
|
@@ -1527,25 +1555,23 @@ const jeevesComponentDescriptorSchema = z.object({
|
|
|
1527
1555
|
message: 'refreshIntervalSeconds must be a prime number',
|
|
1528
1556
|
}),
|
|
1529
1557
|
/** Produce the component's TOOLS.md section content. */
|
|
1530
|
-
generateToolsContent: z.function(
|
|
1558
|
+
generateToolsContent: z.function({ input: [], output: z.string() }),
|
|
1531
1559
|
/** Component dependencies for HEARTBEAT alert suppression. */
|
|
1532
1560
|
dependencies: z
|
|
1533
1561
|
.object({
|
|
1562
|
+
/** Components that must be healthy for this component to function. */
|
|
1534
1563
|
hard: z.array(z.string()),
|
|
1564
|
+
/** Components that improve behavior but are not strictly required. */
|
|
1535
1565
|
soft: z.array(z.string()),
|
|
1536
1566
|
})
|
|
1537
1567
|
.optional(),
|
|
1538
1568
|
/** Extension point: add custom CLI commands to the service CLI. */
|
|
1539
1569
|
customCliCommands: z
|
|
1540
|
-
.function()
|
|
1541
|
-
.args(z.custom())
|
|
1542
|
-
.returns(z.void())
|
|
1570
|
+
.function({ input: [z.custom()], output: z.void() })
|
|
1543
1571
|
.optional(),
|
|
1544
1572
|
/** Extension point: return additional plugin tool descriptors. */
|
|
1545
1573
|
customPluginTools: z
|
|
1546
|
-
.function()
|
|
1547
|
-
.args(z.custom())
|
|
1548
|
-
.returns(z.array(z.unknown()))
|
|
1574
|
+
.function({ input: [z.custom()], output: z.array(z.unknown()) })
|
|
1549
1575
|
.optional(),
|
|
1550
1576
|
});
|
|
1551
1577
|
/**
|
|
@@ -2032,14 +2058,8 @@ function createServiceCli(descriptor) {
|
|
|
2032
2058
|
.command('start')
|
|
2033
2059
|
.description('Launch the service process (foreground)')
|
|
2034
2060
|
.requiredOption('-c, --config <path>', 'Config file path')
|
|
2035
|
-
.action((opts) => {
|
|
2036
|
-
|
|
2037
|
-
const proc = spawn(cmdArgs[0], cmdArgs.slice(1), {
|
|
2038
|
-
stdio: 'inherit',
|
|
2039
|
-
});
|
|
2040
|
-
proc.on('exit', (code) => {
|
|
2041
|
-
process.exit(code ?? 1);
|
|
2042
|
-
});
|
|
2061
|
+
.action(async (opts) => {
|
|
2062
|
+
await descriptor.run(opts.config);
|
|
2043
2063
|
});
|
|
2044
2064
|
// --- status ---
|
|
2045
2065
|
program
|
|
@@ -2972,7 +2992,7 @@ async function refreshPlatformContent(options) {
|
|
|
2972
2992
|
/** Zod schema for a service entry in core config. */
|
|
2973
2993
|
const serviceEntrySchema = z.object({
|
|
2974
2994
|
/** Service URL (must be a valid URL). */
|
|
2975
|
-
url: z.
|
|
2995
|
+
url: z.url().describe('Service URL'),
|
|
2976
2996
|
});
|
|
2977
2997
|
/** Default bind address for all Jeeves services. */
|
|
2978
2998
|
const DEFAULT_BIND_ADDRESS = '0.0.0.0';
|
|
@@ -3006,7 +3026,7 @@ const coreConfigSchema = z.object({
|
|
|
3006
3026
|
.default(3600)
|
|
3007
3027
|
.describe('Cache TTL in seconds'),
|
|
3008
3028
|
})
|
|
3009
|
-
.
|
|
3029
|
+
.prefault({})
|
|
3010
3030
|
.describe('Registry cache settings'),
|
|
3011
3031
|
});
|
|
3012
3032
|
/**
|
package/package.json
CHANGED
|
@@ -13,52 +13,52 @@
|
|
|
13
13
|
"url": "https://github.com/karmaniverous/jeeves/issues"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"commander": "^14.0.
|
|
16
|
+
"commander": "^14.0.3",
|
|
17
17
|
"jsonpath-plus": "^10.4.0",
|
|
18
18
|
"package-directory": "^8.2.0",
|
|
19
19
|
"proper-lockfile": "^4.1.2",
|
|
20
|
-
"semver": "^7.7.
|
|
21
|
-
"zod": "^3.
|
|
20
|
+
"semver": "^7.7.4",
|
|
21
|
+
"zod": "^4.3.6"
|
|
22
22
|
},
|
|
23
23
|
"description": "Shared library and CLI for the Jeeves AI assistant platform.",
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@commander-js/extra-typings": "^14.0.0",
|
|
26
|
-
"@dotenvx/dotenvx": "^1.
|
|
27
|
-
"@eslint/js": "^
|
|
26
|
+
"@dotenvx/dotenvx": "^1.59.1",
|
|
27
|
+
"@eslint/js": "^10.0.1",
|
|
28
28
|
"@rollup/plugin-alias": "^6.0.0",
|
|
29
|
-
"@rollup/plugin-commonjs": "^29.0.
|
|
29
|
+
"@rollup/plugin-commonjs": "^29.0.2",
|
|
30
30
|
"@rollup/plugin-json": "^6.1.0",
|
|
31
31
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
32
32
|
"@rollup/plugin-replace": "^6.0.3",
|
|
33
33
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
34
34
|
"@types/fs-extra": "^11.0.4",
|
|
35
|
-
"@types/node": "^25.0
|
|
35
|
+
"@types/node": "^25.5.0",
|
|
36
36
|
"@types/proper-lockfile": "^4.1.4",
|
|
37
|
-
"@types/semver": "^7.7.
|
|
38
|
-
"@vitest/coverage-v8": "^4.
|
|
39
|
-
"@vitest/eslint-plugin": "^1.6.
|
|
37
|
+
"@types/semver": "^7.7.1",
|
|
38
|
+
"@vitest/coverage-v8": "^4.1.2",
|
|
39
|
+
"@vitest/eslint-plugin": "^1.6.13",
|
|
40
40
|
"auto-changelog": "^2.5.0",
|
|
41
41
|
"cross-env": "^10.1.0",
|
|
42
|
-
"eslint": "^
|
|
42
|
+
"eslint": "^10.1.0",
|
|
43
43
|
"eslint-config-prettier": "^10.1.8",
|
|
44
|
-
"eslint-plugin-prettier": "^5.5.
|
|
44
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
45
45
|
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
46
|
-
"eslint-plugin-tsdoc": "^0.5.
|
|
47
|
-
"fs-extra": "^11.3.
|
|
48
|
-
"knip": "^
|
|
49
|
-
"lefthook": "^2.
|
|
50
|
-
"prettier": "^3.
|
|
51
|
-
"release-it": "^19.2.
|
|
52
|
-
"rimraf": "^6.1.
|
|
53
|
-
"rollup": "^4.
|
|
54
|
-
"rollup-plugin-dts": "^6.
|
|
46
|
+
"eslint-plugin-tsdoc": "^0.5.2",
|
|
47
|
+
"fs-extra": "^11.3.4",
|
|
48
|
+
"knip": "^6.1.0",
|
|
49
|
+
"lefthook": "^2.1.4",
|
|
50
|
+
"prettier": "^3.8.1",
|
|
51
|
+
"release-it": "^19.2.4",
|
|
52
|
+
"rimraf": "^6.1.3",
|
|
53
|
+
"rollup": "^4.60.1",
|
|
54
|
+
"rollup-plugin-dts": "^6.4.1",
|
|
55
55
|
"tslib": "^2.8.1",
|
|
56
|
-
"typedoc": "^0.28.
|
|
57
|
-
"typedoc-plugin-mdn-links": "^5.
|
|
56
|
+
"typedoc": "^0.28.18",
|
|
57
|
+
"typedoc-plugin-mdn-links": "^5.1.1",
|
|
58
58
|
"typedoc-plugin-replace-text": "^4.2.0",
|
|
59
59
|
"typescript": "^5.9.3",
|
|
60
|
-
"typescript-eslint": "^8.
|
|
61
|
-
"vitest": "^4.
|
|
60
|
+
"typescript-eslint": "^8.57.2",
|
|
61
|
+
"vitest": "^4.1.2"
|
|
62
62
|
},
|
|
63
63
|
"engines": {
|
|
64
64
|
"node": ">=20"
|
|
@@ -139,5 +139,5 @@
|
|
|
139
139
|
},
|
|
140
140
|
"type": "module",
|
|
141
141
|
"types": "dist/index.d.ts",
|
|
142
|
-
"version": "0.4.
|
|
142
|
+
"version": "0.4.5"
|
|
143
143
|
}
|