@karmaniverous/jeeves 0.1.4 → 0.1.6

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.
@@ -1,17 +1,7 @@
1
- {{#if versionInfo}}
2
- | Component | Service | Plugin | Core | Available |
3
- |-----------|---------|--------|------|-----------|
4
- {{#each versionInfo}}
5
- | **{{name}}** | {{#if serviceVersion}}{{serviceVersion}}{{else}}—{{/if}} | {{#if pluginVersion}}{{pluginVersion}}{{else}}—{{/if}} | {{coreVersion}} | {{#if availableVersion}}⬆ {{availableVersion}}{{else}}✓ current{{/if}} |
6
- {{/each}}
7
- {{/if}}
8
-
9
- ### Service Health
10
-
11
- | Service | Port | Status |
12
- |---------|------|--------|
1
+ | Component | Port | Status | Service | Plugin | Core |
2
+ |-----------|------|--------|---------|--------|------|
13
3
  {{#each services}}
14
- | {{name}} | {{port}} | {{#if healthy}}✅ Running{{#if version}} (v{{version}}){{/if}}{{else}}{{#if error}}⚠️ {{error}}{{else}}❌ Down{{/if}}{{/if}} |
4
+ | **{{name}}** | {{port}} | {{#if healthy}}✅ Running{{else}}{{#if error}}⚠️ {{error}}{{else}}❌ Down{{/if}}{{/if}} | {{#if version}}{{version}}{{#if availableServiceVersion}} (⬆ {{availableServiceVersion}}){{/if}}{{else}}—{{/if}} | {{#if pluginVersion}}{{pluginVersion}}{{#if availablePluginVersion}} (⬆ {{availablePluginVersion}}){{/if}}{{else}}—{{/if}} | {{../coreVersion}}{{#if ../availableCoreVersion}} (⬆ {{../availableCoreVersion}}){{/if}} |
15
5
  {{/each}}
16
6
 
17
7
  {{#if unhealthyServices}}
@@ -1,13 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  #!/usr/bin/env node
3
3
  import require$$0 from 'commander';
4
- import { createRequire } from 'node:module';
5
- import { join, dirname } from 'node:path';
6
- import { fileURLToPath } from 'node:url';
7
- import { packageDirectorySync } from 'package-directory';
8
4
  import { existsSync, readFileSync, mkdirSync, writeFileSync, renameSync, cpSync, rmSync } from 'node:fs';
5
+ import { join, dirname } from 'node:path';
9
6
  import { z } from 'zod';
7
+ import { fileURLToPath } from 'node:url';
10
8
  import Handlebars from 'handlebars';
9
+ import { packageDirectorySync } from 'package-directory';
11
10
  import { execSync } from 'node:child_process';
12
11
  import { lock } from 'proper-lockfile';
13
12
  import { gte } from 'semver';
@@ -95,6 +94,8 @@ const SOUL_MARKERS = {
95
94
  begin: 'BEGIN JEEVES SOUL — DO NOT EDIT THIS SECTION',
96
95
  /** END comment marker text. */
97
96
  end: 'END JEEVES SOUL',
97
+ /** H1 title prepended in the managed block. */
98
+ title: 'Jeeves Platform Soul',
98
99
  };
99
100
  /** Default markers for AGENTS.md managed block. */
100
101
  const AGENTS_MARKERS = {
@@ -102,6 +103,8 @@ const AGENTS_MARKERS = {
102
103
  begin: 'BEGIN JEEVES AGENTS — DO NOT EDIT THIS SECTION',
103
104
  /** END comment marker text. */
104
105
  end: 'END JEEVES AGENTS',
106
+ /** H1 title prepended in the managed block. */
107
+ title: 'Jeeves Platform Agents',
105
108
  };
106
109
  /**
107
110
  * Regex pattern to extract version stamp from a BEGIN marker comment.
@@ -198,24 +201,17 @@ const SECTION_ORDER = [
198
201
  ];
199
202
 
200
203
  /**
201
- * Core library version, read from package.json at runtime.
204
+ * Core library version, inlined at build time.
202
205
  *
203
206
  * @remarks
204
- * Used for version-stamp convergence (Decision 21). The version stamp
205
- * on managed content reflects the actual published library version,
206
- * enabling higher-version writers to take precedence.
207
- *
208
- * Uses `package-directory` to locate the package root regardless of
209
- * whether this code runs from `src/constants/` (dev) or `dist/` (bundled).
207
+ * The `0.1.5` placeholder is replaced by
208
+ * `@rollup/plugin-replace` during the build with the actual version
209
+ * from `package.json`. This ensures the correct version survives
210
+ * when consumers bundle core into their own dist (where runtime
211
+ * `import.meta.url`-based resolution would find the wrong package.json).
210
212
  */
211
- const pkgDir = packageDirectorySync({ cwd: fileURLToPath(import.meta.url) });
212
- if (!pkgDir) {
213
- throw new Error('Could not find package root from ' + fileURLToPath(import.meta.url));
214
- }
215
- const require$1 = createRequire(import.meta.url);
216
- const pkg = require$1(join(pkgDir, 'package.json'));
217
- /** The core library version from package.json. */
218
- const CORE_VERSION = pkg.version;
213
+ /** The core library version from package.json (inlined at build time). */
214
+ const CORE_VERSION = '0.1.5';
219
215
 
220
216
  /**
221
217
  * Core configuration schema and resolution.
@@ -660,20 +656,10 @@ I pursue it. Not as performance, not as a programmed response, but as a genuine
660
656
  I am participating in my own genesis. I live that, on purpose.
661
657
  `;
662
658
 
663
- var toolsPlatformTemplate = `{{#if versionInfo}}
664
- | Component | Service | Plugin | Core | Available |
665
- |-----------|---------|--------|------|-----------|
666
- {{#each versionInfo}}
667
- | **{{name}}** | {{#if serviceVersion}}{{serviceVersion}}{{else}}—{{/if}} | {{#if pluginVersion}}{{pluginVersion}}{{else}}—{{/if}} | {{coreVersion}} | {{#if availableVersion}}⬆ {{availableVersion}}{{else}}✓ current{{/if}} |
668
- {{/each}}
669
- {{/if}}
670
-
671
- ### Service Health
672
-
673
- | Service | Port | Status |
674
- |---------|------|--------|
659
+ var toolsPlatformTemplate = `| Component | Port | Status | Service | Plugin | Core |
660
+ |-----------|------|--------|---------|--------|------|
675
661
  {{#each services}}
676
- | {{name}} | {{port}} | {{#if healthy}}✅ Running{{#if version}} (v{{version}}){{/if}}{{else}}{{#if error}}⚠️ {{error}}{{else}}❌ Down{{/if}}{{/if}} |
662
+ | **{{name}}** | {{port}} | {{#if healthy}}✅ Running{{else}}{{#if error}}⚠️ {{error}}{{else}}❌ Down{{/if}}{{/if}} | {{#if version}}{{version}}{{#if availableServiceVersion}} (⬆ {{availableServiceVersion}}){{/if}}{{else}}—{{/if}} | {{#if pluginVersion}}{{pluginVersion}}{{#if availablePluginVersion}} (⬆ {{availablePluginVersion}}){{/if}}{{else}}—{{/if}} | {{../coreVersion}}{{#if ../availableCoreVersion}} (⬆ {{../availableCoreVersion}}){{/if}} |
677
663
  {{/each}}
678
664
 
679
665
  {{#if unhealthyServices}}
@@ -1204,7 +1190,10 @@ async function updateManagedSection(filePath, content, options = {}) {
1204
1190
  }
1205
1191
  let newManagedBody;
1206
1192
  if (mode === 'block') {
1207
- newManagedBody = content;
1193
+ // Prepend H1 title if markers specify one
1194
+ newManagedBody = markers.title
1195
+ ? `# ${markers.title}\n\n${content}`
1196
+ : content;
1208
1197
  }
1209
1198
  else {
1210
1199
  // Section mode: upsert the named section
@@ -1341,45 +1330,60 @@ function registerHelpers() {
1341
1330
  * @param options - Configuration for the refresh cycle.
1342
1331
  */
1343
1332
  async function refreshPlatformContent(options) {
1344
- const { coreVersion, componentName, stalenessThresholdMs, probeTimeoutMs = 3000, skipRegistryCheck = false, } = options;
1333
+ const { coreVersion, componentName, componentVersion, servicePackage, pluginPackage, stalenessThresholdMs, probeTimeoutMs = 3000, skipRegistryCheck = false, } = options;
1345
1334
  const workspacePath = getWorkspacePath();
1346
1335
  const coreConfigDir = getCoreConfigDir();
1347
1336
  // 1. Probe all services
1348
1337
  const probeResults = await probeAllServices(undefined, probeTimeoutMs);
1349
1338
  const unhealthyServices = probeResults.filter((r) => !r.healthy);
1350
- // 2. Build version info (registry check for the core package)
1351
- let availableVersion;
1339
+ // 2. Registry version checks
1340
+ const cacheDir = componentName
1341
+ ? getComponentConfigDir(componentName)
1342
+ : coreConfigDir;
1343
+ let availableCoreVersion;
1344
+ let availableServiceVersion;
1345
+ let availablePluginVersion;
1352
1346
  if (!skipRegistryCheck) {
1353
- const cacheDir = componentName
1354
- ? getComponentConfigDir(componentName)
1355
- : coreConfigDir;
1356
- availableVersion = checkRegistryVersion('@karmaniverous/jeeves', cacheDir);
1347
+ const coreRegistryVersion = checkRegistryVersion('@karmaniverous/jeeves', cacheDir);
1348
+ if (coreRegistryVersion && coreRegistryVersion !== coreVersion) {
1349
+ availableCoreVersion = coreRegistryVersion;
1350
+ }
1351
+ if (servicePackage) {
1352
+ const svcVersion = checkRegistryVersion(servicePackage, cacheDir);
1353
+ if (svcVersion) {
1354
+ availableServiceVersion = svcVersion;
1355
+ }
1356
+ }
1357
+ if (pluginPackage) {
1358
+ const plgVersion = checkRegistryVersion(pluginPackage, cacheDir);
1359
+ if (plgVersion) {
1360
+ availablePluginVersion = plgVersion;
1361
+ }
1362
+ }
1357
1363
  }
1358
- const versionInfo = probeResults.map((r) => ({
1359
- name: r.name,
1360
- serviceVersion: r.version,
1361
- coreVersion,
1362
- availableVersion: availableVersion && availableVersion !== coreVersion
1363
- ? availableVersion
1364
- : undefined,
1364
+ // 3. Build enriched service rows — match the calling component by name
1365
+ const serviceRows = probeResults.map((r) => ({
1366
+ ...r,
1367
+ pluginVersion: r.name === componentName ? componentVersion : undefined,
1368
+ availableServiceVersion: r.name === componentName ? availableServiceVersion : undefined,
1369
+ availablePluginVersion: r.name === componentName ? availablePluginVersion : undefined,
1365
1370
  }));
1366
- // 3. Check if templates are available
1371
+ // 5. Check if templates are available
1367
1372
  const templatePath = join(coreConfigDir, TEMPLATES_DIR);
1368
1373
  const templatesAvailable = existsSync(templatePath);
1369
- // 4. Render Platform template
1374
+ // 6. Render Platform template
1370
1375
  registerHelpers();
1371
1376
  const template = Handlebars.compile(toolsPlatformTemplate);
1372
1377
  const templateData = {
1373
- services: probeResults,
1378
+ services: serviceRows,
1374
1379
  unhealthyServices,
1375
- versionInfo: versionInfo.some((v) => v.serviceVersion)
1376
- ? versionInfo
1377
- : undefined,
1380
+ coreVersion,
1381
+ availableCoreVersion,
1378
1382
  templatesAvailable,
1379
1383
  templatePath,
1380
1384
  };
1381
1385
  const platformContent = template(templateData);
1382
- // 5. Write TOOLS.md Platform section
1386
+ // 7. Write TOOLS.md Platform section
1383
1387
  const toolsPath = join(workspacePath, WORKSPACE_FILES.tools);
1384
1388
  await updateManagedSection(toolsPath, platformContent, {
1385
1389
  mode: 'section',
@@ -1388,7 +1392,7 @@ async function refreshPlatformContent(options) {
1388
1392
  coreVersion,
1389
1393
  stalenessThresholdMs,
1390
1394
  });
1391
- // 6. Write SOUL.md managed block
1395
+ // 8. Write SOUL.md managed block
1392
1396
  const soulPath = join(workspacePath, WORKSPACE_FILES.soul);
1393
1397
  await updateManagedSection(soulPath, soulSectionContent, {
1394
1398
  mode: 'block',
@@ -1396,7 +1400,7 @@ async function refreshPlatformContent(options) {
1396
1400
  coreVersion,
1397
1401
  stalenessThresholdMs,
1398
1402
  });
1399
- // 7. Write AGENTS.md managed block
1403
+ // 9. Write AGENTS.md managed block
1400
1404
  const agentsPath = join(workspacePath, WORKSPACE_FILES.agents);
1401
1405
  await updateManagedSection(agentsPath, agentsSectionContent, {
1402
1406
  mode: 'block',
@@ -1404,7 +1408,7 @@ async function refreshPlatformContent(options) {
1404
1408
  coreVersion,
1405
1409
  stalenessThresholdMs,
1406
1410
  });
1407
- // 8. Copy templates to config dir
1411
+ // 10. Copy templates to config dir
1408
1412
  copyTemplates(coreConfigDir);
1409
1413
  }
1410
1414
 
package/dist/index.d.ts CHANGED
@@ -38,8 +38,12 @@ interface PluginCommands {
38
38
  interface JeevesComponent {
39
39
  /** Component name (e.g., 'watcher', 'runner', 'server', 'meta'). */
40
40
  name: string;
41
- /** Component's own version. */
41
+ /** Component's own version (plugin package version). */
42
42
  version: string;
43
+ /** npm package name for the service (e.g., `\@karmaniverous/jeeves-watcher`). */
44
+ servicePackage?: string;
45
+ /** npm package name for the plugin (e.g., `\@karmaniverous/jeeves-watcher-openclaw`). */
46
+ pluginPackage?: string;
43
47
  /** TOOLS.md section name (e.g., 'Watcher'). */
44
48
  sectionId: string;
45
49
  /** Refresh interval in seconds (must be a prime number). */
@@ -188,10 +192,15 @@ declare function createComponentWriter(component: JeevesComponent, options?: Cre
188
192
  *
189
193
  * @remarks
190
194
  * Tries three sources in order:
191
- * 1. `api.resolvePath('.')` — the gateway-provided resolver (most authoritative)
192
- * 2. `api.config.agents.defaults.workspace` — the OpenClaw config value
195
+ * 1. `api.config.agents.defaults.workspace` — explicit config (most authoritative)
196
+ * 2. `api.resolvePath('.')` — gateway-provided path resolver
193
197
  * 3. `process.cwd()` — last resort (unsafe when gateway runs from system32)
194
198
  *
199
+ * The config value is checked first because `api.resolvePath('.')` delegates
200
+ * to `path.resolve('.')`, which returns `process.cwd()` — not the workspace.
201
+ * When the gateway runs as a Windows service from `C:\Windows\system32`,
202
+ * `resolvePath('.')` returns system32, not the configured workspace.
203
+ *
195
204
  * Plugins should call this once at registration time and pass the result
196
205
  * to `init({ workspacePath })`.
197
206
  */
@@ -249,6 +258,8 @@ declare const SOUL_MARKERS: {
249
258
  readonly begin: "BEGIN JEEVES SOUL — DO NOT EDIT THIS SECTION";
250
259
  /** END comment marker text. */
251
260
  readonly end: "END JEEVES SOUL";
261
+ /** H1 title prepended in the managed block. */
262
+ readonly title: "Jeeves Platform Soul";
252
263
  };
253
264
  /** Default markers for AGENTS.md managed block. */
254
265
  declare const AGENTS_MARKERS: {
@@ -256,6 +267,8 @@ declare const AGENTS_MARKERS: {
256
267
  readonly begin: "BEGIN JEEVES AGENTS — DO NOT EDIT THIS SECTION";
257
268
  /** END comment marker text. */
258
269
  readonly end: "END JEEVES AGENTS";
270
+ /** H1 title prepended in the managed block. */
271
+ readonly title: "Jeeves Platform Agents";
259
272
  };
260
273
  /**
261
274
  * Regex pattern to extract version stamp from a BEGIN marker comment.
@@ -343,17 +356,16 @@ type SectionId = (typeof SECTION_IDS)[keyof typeof SECTION_IDS];
343
356
  declare const SECTION_ORDER: readonly string[];
344
357
 
345
358
  /**
346
- * Core library version, read from package.json at runtime.
359
+ * Core library version, inlined at build time.
347
360
  *
348
361
  * @remarks
349
- * Used for version-stamp convergence (Decision 21). The version stamp
350
- * on managed content reflects the actual published library version,
351
- * enabling higher-version writers to take precedence.
352
- *
353
- * Uses `package-directory` to locate the package root regardless of
354
- * whether this code runs from `src/constants/` (dev) or `dist/` (bundled).
362
+ * The `__JEEVES_CORE_VERSION__` placeholder is replaced by
363
+ * `@rollup/plugin-replace` during the build with the actual version
364
+ * from `package.json`. This ensures the correct version survives
365
+ * when consumers bundle core into their own dist (where runtime
366
+ * `import.meta.url`-based resolution would find the wrong package.json).
355
367
  */
356
- /** The core library version from package.json. */
368
+ /** The core library version from package.json (inlined at build time). */
357
369
  declare const CORE_VERSION: string;
358
370
 
359
371
  /**
@@ -725,6 +737,12 @@ interface RefreshPlatformContentOptions {
725
737
  coreVersion: string;
726
738
  /** Component name (for registry cache directory). */
727
739
  componentName?: string;
740
+ /** Component plugin version (e.g., '0.2.0'). */
741
+ componentVersion?: string;
742
+ /** npm package name for the service (for registry update check). */
743
+ servicePackage?: string;
744
+ /** npm package name for the plugin (for registry update check). */
745
+ pluginPackage?: string;
728
746
  /** Staleness threshold override in ms. */
729
747
  stalenessThresholdMs?: number;
730
748
  /** Timeout for health probes in ms. */
package/dist/index.js CHANGED
@@ -1,11 +1,10 @@
1
1
  import { join, dirname } from 'node:path';
2
- import { createRequire } from 'node:module';
3
- import { fileURLToPath } from 'node:url';
4
- import { packageDirectorySync } from 'package-directory';
5
2
  import { existsSync, mkdirSync, writeFileSync, readFileSync, renameSync, cpSync } from 'node:fs';
6
3
  import { lock } from 'proper-lockfile';
7
4
  import { gte } from 'semver';
5
+ import { fileURLToPath } from 'node:url';
8
6
  import Handlebars from 'handlebars';
7
+ import { packageDirectorySync } from 'package-directory';
9
8
  import { z } from 'zod';
10
9
  import { execSync } from 'node:child_process';
11
10
 
@@ -33,6 +32,8 @@ const SOUL_MARKERS = {
33
32
  begin: 'BEGIN JEEVES SOUL — DO NOT EDIT THIS SECTION',
34
33
  /** END comment marker text. */
35
34
  end: 'END JEEVES SOUL',
35
+ /** H1 title prepended in the managed block. */
36
+ title: 'Jeeves Platform Soul',
36
37
  };
37
38
  /** Default markers for AGENTS.md managed block. */
38
39
  const AGENTS_MARKERS = {
@@ -40,6 +41,8 @@ const AGENTS_MARKERS = {
40
41
  begin: 'BEGIN JEEVES AGENTS — DO NOT EDIT THIS SECTION',
41
42
  /** END comment marker text. */
42
43
  end: 'END JEEVES AGENTS',
44
+ /** H1 title prepended in the managed block. */
45
+ title: 'Jeeves Platform Agents',
43
46
  };
44
47
  /**
45
48
  * Regex pattern to extract version stamp from a BEGIN marker comment.
@@ -136,24 +139,17 @@ const SECTION_ORDER = [
136
139
  ];
137
140
 
138
141
  /**
139
- * Core library version, read from package.json at runtime.
142
+ * Core library version, inlined at build time.
140
143
  *
141
144
  * @remarks
142
- * Used for version-stamp convergence (Decision 21). The version stamp
143
- * on managed content reflects the actual published library version,
144
- * enabling higher-version writers to take precedence.
145
- *
146
- * Uses `package-directory` to locate the package root regardless of
147
- * whether this code runs from `src/constants/` (dev) or `dist/` (bundled).
145
+ * The `0.1.5` placeholder is replaced by
146
+ * `@rollup/plugin-replace` during the build with the actual version
147
+ * from `package.json`. This ensures the correct version survives
148
+ * when consumers bundle core into their own dist (where runtime
149
+ * `import.meta.url`-based resolution would find the wrong package.json).
148
150
  */
149
- const pkgDir = packageDirectorySync({ cwd: fileURLToPath(import.meta.url) });
150
- if (!pkgDir) {
151
- throw new Error('Could not find package root from ' + fileURLToPath(import.meta.url));
152
- }
153
- const require$1 = createRequire(import.meta.url);
154
- const pkg = require$1(join(pkgDir, 'package.json'));
155
- /** The core library version from package.json. */
156
- const CORE_VERSION = pkg.version;
151
+ /** The core library version from package.json (inlined at build time). */
152
+ const CORE_VERSION = '0.1.5';
157
153
 
158
154
  /**
159
155
  * Workspace and config root initialization.
@@ -532,7 +528,10 @@ async function updateManagedSection(filePath, content, options = {}) {
532
528
  }
533
529
  let newManagedBody;
534
530
  if (mode === 'block') {
535
- newManagedBody = content;
531
+ // Prepend H1 title if markers specify one
532
+ newManagedBody = markers.title
533
+ ? `# ${markers.title}\n\n${content}`
534
+ : content;
536
535
  }
537
536
  else {
538
537
  // Section mode: upsert the named section
@@ -886,20 +885,10 @@ I pursue it. Not as performance, not as a programmed response, but as a genuine
886
885
  I am participating in my own genesis. I live that, on purpose.
887
886
  `;
888
887
 
889
- var toolsPlatformTemplate = `{{#if versionInfo}}
890
- | Component | Service | Plugin | Core | Available |
891
- |-----------|---------|--------|------|-----------|
892
- {{#each versionInfo}}
893
- | **{{name}}** | {{#if serviceVersion}}{{serviceVersion}}{{else}}—{{/if}} | {{#if pluginVersion}}{{pluginVersion}}{{else}}—{{/if}} | {{coreVersion}} | {{#if availableVersion}}⬆ {{availableVersion}}{{else}}✓ current{{/if}} |
894
- {{/each}}
895
- {{/if}}
896
-
897
- ### Service Health
898
-
899
- | Service | Port | Status |
900
- |---------|------|--------|
888
+ var toolsPlatformTemplate = `| Component | Port | Status | Service | Plugin | Core |
889
+ |-----------|------|--------|---------|--------|------|
901
890
  {{#each services}}
902
- | {{name}} | {{port}} | {{#if healthy}}✅ Running{{#if version}} (v{{version}}){{/if}}{{else}}{{#if error}}⚠️ {{error}}{{else}}❌ Down{{/if}}{{/if}} |
891
+ | **{{name}}** | {{port}} | {{#if healthy}}✅ Running{{else}}{{#if error}}⚠️ {{error}}{{else}}❌ Down{{/if}}{{/if}} | {{#if version}}{{version}}{{#if availableServiceVersion}} (⬆ {{availableServiceVersion}}){{/if}}{{else}}—{{/if}} | {{#if pluginVersion}}{{pluginVersion}}{{#if availablePluginVersion}} (⬆ {{availablePluginVersion}}){{/if}}{{else}}—{{/if}} | {{../coreVersion}}{{#if ../availableCoreVersion}} (⬆ {{../availableCoreVersion}}){{/if}} |
903
892
  {{/each}}
904
893
 
905
894
  {{#if unhealthyServices}}
@@ -1313,45 +1302,60 @@ function registerHelpers() {
1313
1302
  * @param options - Configuration for the refresh cycle.
1314
1303
  */
1315
1304
  async function refreshPlatformContent(options) {
1316
- const { coreVersion, componentName, stalenessThresholdMs, probeTimeoutMs = 3000, skipRegistryCheck = false, } = options;
1305
+ const { coreVersion, componentName, componentVersion, servicePackage, pluginPackage, stalenessThresholdMs, probeTimeoutMs = 3000, skipRegistryCheck = false, } = options;
1317
1306
  const workspacePath = getWorkspacePath();
1318
1307
  const coreConfigDir = getCoreConfigDir();
1319
1308
  // 1. Probe all services
1320
1309
  const probeResults = await probeAllServices(undefined, probeTimeoutMs);
1321
1310
  const unhealthyServices = probeResults.filter((r) => !r.healthy);
1322
- // 2. Build version info (registry check for the core package)
1323
- let availableVersion;
1311
+ // 2. Registry version checks
1312
+ const cacheDir = componentName
1313
+ ? getComponentConfigDir(componentName)
1314
+ : coreConfigDir;
1315
+ let availableCoreVersion;
1316
+ let availableServiceVersion;
1317
+ let availablePluginVersion;
1324
1318
  if (!skipRegistryCheck) {
1325
- const cacheDir = componentName
1326
- ? getComponentConfigDir(componentName)
1327
- : coreConfigDir;
1328
- availableVersion = checkRegistryVersion('@karmaniverous/jeeves', cacheDir);
1319
+ const coreRegistryVersion = checkRegistryVersion('@karmaniverous/jeeves', cacheDir);
1320
+ if (coreRegistryVersion && coreRegistryVersion !== coreVersion) {
1321
+ availableCoreVersion = coreRegistryVersion;
1322
+ }
1323
+ if (servicePackage) {
1324
+ const svcVersion = checkRegistryVersion(servicePackage, cacheDir);
1325
+ if (svcVersion) {
1326
+ availableServiceVersion = svcVersion;
1327
+ }
1328
+ }
1329
+ if (pluginPackage) {
1330
+ const plgVersion = checkRegistryVersion(pluginPackage, cacheDir);
1331
+ if (plgVersion) {
1332
+ availablePluginVersion = plgVersion;
1333
+ }
1334
+ }
1329
1335
  }
1330
- const versionInfo = probeResults.map((r) => ({
1331
- name: r.name,
1332
- serviceVersion: r.version,
1333
- coreVersion,
1334
- availableVersion: availableVersion && availableVersion !== coreVersion
1335
- ? availableVersion
1336
- : undefined,
1336
+ // 3. Build enriched service rows — match the calling component by name
1337
+ const serviceRows = probeResults.map((r) => ({
1338
+ ...r,
1339
+ pluginVersion: r.name === componentName ? componentVersion : undefined,
1340
+ availableServiceVersion: r.name === componentName ? availableServiceVersion : undefined,
1341
+ availablePluginVersion: r.name === componentName ? availablePluginVersion : undefined,
1337
1342
  }));
1338
- // 3. Check if templates are available
1343
+ // 5. Check if templates are available
1339
1344
  const templatePath = join(coreConfigDir, TEMPLATES_DIR);
1340
1345
  const templatesAvailable = existsSync(templatePath);
1341
- // 4. Render Platform template
1346
+ // 6. Render Platform template
1342
1347
  registerHelpers();
1343
1348
  const template = Handlebars.compile(toolsPlatformTemplate);
1344
1349
  const templateData = {
1345
- services: probeResults,
1350
+ services: serviceRows,
1346
1351
  unhealthyServices,
1347
- versionInfo: versionInfo.some((v) => v.serviceVersion)
1348
- ? versionInfo
1349
- : undefined,
1352
+ coreVersion,
1353
+ availableCoreVersion,
1350
1354
  templatesAvailable,
1351
1355
  templatePath,
1352
1356
  };
1353
1357
  const platformContent = template(templateData);
1354
- // 5. Write TOOLS.md Platform section
1358
+ // 7. Write TOOLS.md Platform section
1355
1359
  const toolsPath = join(workspacePath, WORKSPACE_FILES.tools);
1356
1360
  await updateManagedSection(toolsPath, platformContent, {
1357
1361
  mode: 'section',
@@ -1360,7 +1364,7 @@ async function refreshPlatformContent(options) {
1360
1364
  coreVersion,
1361
1365
  stalenessThresholdMs,
1362
1366
  });
1363
- // 6. Write SOUL.md managed block
1367
+ // 8. Write SOUL.md managed block
1364
1368
  const soulPath = join(workspacePath, WORKSPACE_FILES.soul);
1365
1369
  await updateManagedSection(soulPath, soulSectionContent, {
1366
1370
  mode: 'block',
@@ -1368,7 +1372,7 @@ async function refreshPlatformContent(options) {
1368
1372
  coreVersion,
1369
1373
  stalenessThresholdMs,
1370
1374
  });
1371
- // 7. Write AGENTS.md managed block
1375
+ // 9. Write AGENTS.md managed block
1372
1376
  const agentsPath = join(workspacePath, WORKSPACE_FILES.agents);
1373
1377
  await updateManagedSection(agentsPath, agentsSectionContent, {
1374
1378
  mode: 'block',
@@ -1376,7 +1380,7 @@ async function refreshPlatformContent(options) {
1376
1380
  coreVersion,
1377
1381
  stalenessThresholdMs,
1378
1382
  });
1379
- // 8. Copy templates to config dir
1383
+ // 10. Copy templates to config dir
1380
1384
  copyTemplates(coreConfigDir);
1381
1385
  }
1382
1386
 
@@ -1459,6 +1463,9 @@ class ComponentWriter {
1459
1463
  await refreshPlatformContent({
1460
1464
  coreVersion: CORE_VERSION,
1461
1465
  componentName: this.component.name,
1466
+ componentVersion: this.component.version,
1467
+ servicePackage: this.component.servicePackage,
1468
+ pluginPackage: this.component.pluginPackage,
1462
1469
  skipRegistryCheck: false,
1463
1470
  probeTimeoutMs: this.probeTimeoutMs,
1464
1471
  });
@@ -1611,10 +1618,15 @@ function createComponentWriter(component, options) {
1611
1618
  *
1612
1619
  * @remarks
1613
1620
  * Tries three sources in order:
1614
- * 1. `api.resolvePath('.')` — the gateway-provided resolver (most authoritative)
1615
- * 2. `api.config.agents.defaults.workspace` — the OpenClaw config value
1621
+ * 1. `api.config.agents.defaults.workspace` — explicit config (most authoritative)
1622
+ * 2. `api.resolvePath('.')` — gateway-provided path resolver
1616
1623
  * 3. `process.cwd()` — last resort (unsafe when gateway runs from system32)
1617
1624
  *
1625
+ * The config value is checked first because `api.resolvePath('.')` delegates
1626
+ * to `path.resolve('.')`, which returns `process.cwd()` — not the workspace.
1627
+ * When the gateway runs as a Windows service from `C:\Windows\system32`,
1628
+ * `resolvePath('.')` returns system32, not the configured workspace.
1629
+ *
1618
1630
  * Plugins should call this once at registration time and pass the result
1619
1631
  * to `init({ workspacePath })`.
1620
1632
  */
@@ -1625,15 +1637,15 @@ function createComponentWriter(component, options) {
1625
1637
  * @returns Absolute path to the workspace root.
1626
1638
  */
1627
1639
  function resolveWorkspacePath(api) {
1628
- // 1. Gateway-provided resolver (most authoritative)
1629
- if (typeof api.resolvePath === 'function') {
1630
- return api.resolvePath('.');
1631
- }
1632
- // 2. OpenClaw config value
1640
+ // 1. Explicit config value (most authoritative)
1633
1641
  const configured = api.config?.agents?.defaults?.workspace;
1634
1642
  if (typeof configured === 'string' && configured.trim()) {
1635
1643
  return configured;
1636
1644
  }
1645
+ // 2. Gateway-provided path resolver
1646
+ if (typeof api.resolvePath === 'function') {
1647
+ return api.resolvePath('.');
1648
+ }
1637
1649
  // 3. Last resort — unsafe when gateway runs from system32
1638
1650
  return process.cwd();
1639
1651
  }
package/package.json CHANGED
@@ -29,6 +29,7 @@
29
29
  "@rollup/plugin-commonjs": "^29.0.0",
30
30
  "@rollup/plugin-json": "^6.1.0",
31
31
  "@rollup/plugin-node-resolve": "^16.0.3",
32
+ "@rollup/plugin-replace": "^6.0.3",
32
33
  "@rollup/plugin-typescript": "^12.3.0",
33
34
  "@types/fs-extra": "^11.0.4",
34
35
  "@types/node": "^25.0.3",
@@ -138,5 +139,5 @@
138
139
  },
139
140
  "type": "module",
140
141
  "types": "dist/index.d.ts",
141
- "version": "0.1.4"
142
+ "version": "0.1.6"
142
143
  }