@karmaniverous/jeeves 0.5.4 → 0.5.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.
- package/dist/cli/jeeves/index.js +27 -21
- package/dist/cli/plugin/index.js +26 -20
- package/dist/index.d.ts +5 -2
- package/dist/index.js +116 -61
- package/package.json +1 -1
package/dist/cli/jeeves/index.js
CHANGED
|
@@ -269,14 +269,14 @@ const PLATFORM_COMPONENTS = [
|
|
|
269
269
|
* Core library version, inlined at build time.
|
|
270
270
|
*
|
|
271
271
|
* @remarks
|
|
272
|
-
* The `0.5.
|
|
272
|
+
* The `0.5.5` placeholder is replaced by
|
|
273
273
|
* `@rollup/plugin-replace` during the build with the actual version
|
|
274
274
|
* from `package.json`. This ensures the correct version survives
|
|
275
275
|
* when consumers bundle core into their own dist (where runtime
|
|
276
276
|
* `import.meta.url`-based resolution would find the wrong package.json).
|
|
277
277
|
*/
|
|
278
278
|
/** The core library version from package.json (inlined at build time). */
|
|
279
|
-
const CORE_VERSION = '0.5.
|
|
279
|
+
const CORE_VERSION = '0.5.5';
|
|
280
280
|
|
|
281
281
|
/**
|
|
282
282
|
* Runtime Node.js version floor check.
|
|
@@ -868,7 +868,7 @@ const STALE_LOCK_MS = 120_000;
|
|
|
868
868
|
/** Default core version when none provided. */
|
|
869
869
|
const DEFAULT_CORE_VERSION = CORE_VERSION;
|
|
870
870
|
/** Lock retry options. */
|
|
871
|
-
const LOCK_RETRIES = { retries:
|
|
871
|
+
const LOCK_RETRIES = { retries: 0 };
|
|
872
872
|
/** Maximum rename retry attempts on EPERM. */
|
|
873
873
|
const ATOMIC_WRITE_MAX_RETRIES = 3;
|
|
874
874
|
/** Delay between EPERM retries in milliseconds. */
|
|
@@ -911,26 +911,15 @@ function atomicWrite(filePath, content) {
|
|
|
911
911
|
}
|
|
912
912
|
}
|
|
913
913
|
}
|
|
914
|
-
|
|
915
|
-
* Execute a callback while holding a file lock.
|
|
916
|
-
*
|
|
917
|
-
* @remarks
|
|
918
|
-
* Acquires a lock on the file, executes the callback, and releases
|
|
919
|
-
* the lock in a finally block. The lock uses a 2-minute stale threshold
|
|
920
|
-
* and retries up to 5 times.
|
|
921
|
-
*
|
|
922
|
-
* @param filePath - Absolute path to the file to lock.
|
|
923
|
-
* @param fn - Async callback to execute while holding the lock.
|
|
924
|
-
*/
|
|
925
|
-
async function withFileLock(filePath, fn) {
|
|
914
|
+
async function withLock(targetPath, fn, options, onLockError) {
|
|
926
915
|
let release;
|
|
927
916
|
try {
|
|
928
|
-
release = await lock(
|
|
929
|
-
stale: STALE_LOCK_MS,
|
|
930
|
-
retries: LOCK_RETRIES,
|
|
931
|
-
});
|
|
917
|
+
release = await lock(targetPath, options);
|
|
932
918
|
await fn();
|
|
933
919
|
}
|
|
920
|
+
catch (error) {
|
|
921
|
+
throw error;
|
|
922
|
+
}
|
|
934
923
|
finally {
|
|
935
924
|
if (release) {
|
|
936
925
|
try {
|
|
@@ -942,6 +931,23 @@ async function withFileLock(filePath, fn) {
|
|
|
942
931
|
}
|
|
943
932
|
}
|
|
944
933
|
}
|
|
934
|
+
/**
|
|
935
|
+
* Execute a callback while holding a file lock.
|
|
936
|
+
*
|
|
937
|
+
* @remarks
|
|
938
|
+
* Acquires a lock on the file, executes the callback, and releases
|
|
939
|
+
* the lock in a finally block. The lock uses a 2-minute stale threshold
|
|
940
|
+
* and retries up to 5 times.
|
|
941
|
+
*
|
|
942
|
+
* @param filePath - Absolute path to the file to lock.
|
|
943
|
+
* @param fn - Async callback to execute while holding the lock.
|
|
944
|
+
*/
|
|
945
|
+
async function withFileLock(filePath, fn) {
|
|
946
|
+
await withLock(filePath, fn, {
|
|
947
|
+
stale: STALE_LOCK_MS,
|
|
948
|
+
retries: LOCK_RETRIES,
|
|
949
|
+
});
|
|
950
|
+
}
|
|
945
951
|
|
|
946
952
|
/**
|
|
947
953
|
* Shared component version state file management.
|
|
@@ -1099,7 +1105,7 @@ function buildHeartbeatSection(entries) {
|
|
|
1099
1105
|
*
|
|
1100
1106
|
* @remarks
|
|
1101
1107
|
* Replaces everything from `# Jeeves Platform Status` to EOF.
|
|
1102
|
-
* Preserves user content above the heading.
|
|
1108
|
+
* Preserves user content above the heading.
|
|
1103
1109
|
*
|
|
1104
1110
|
* @param filePath - Absolute path to HEARTBEAT.md.
|
|
1105
1111
|
* @param entries - Component entries to write.
|
|
@@ -1755,7 +1761,7 @@ function shouldWrite(myVersion, existing, stalenessThresholdMs = STALENESS_THRES
|
|
|
1755
1761
|
* - `block`: Replaces the entire managed block (SOUL.md, AGENTS.md).
|
|
1756
1762
|
* - `section`: Upserts a named H2 section within the managed block (TOOLS.md).
|
|
1757
1763
|
*
|
|
1758
|
-
* Provides
|
|
1764
|
+
* Provides version-stamp convergence and atomic writes.
|
|
1759
1765
|
*/
|
|
1760
1766
|
/**
|
|
1761
1767
|
* Update a managed section in a file.
|
package/dist/cli/plugin/index.js
CHANGED
|
@@ -130,14 +130,14 @@ const COMPONENT_VERSIONS_FILE = 'component-versions.json';
|
|
|
130
130
|
* Core library version, inlined at build time.
|
|
131
131
|
*
|
|
132
132
|
* @remarks
|
|
133
|
-
* The `0.5.
|
|
133
|
+
* The `0.5.5` placeholder is replaced by
|
|
134
134
|
* `@rollup/plugin-replace` during the build with the actual version
|
|
135
135
|
* from `package.json`. This ensures the correct version survives
|
|
136
136
|
* when consumers bundle core into their own dist (where runtime
|
|
137
137
|
* `import.meta.url`-based resolution would find the wrong package.json).
|
|
138
138
|
*/
|
|
139
139
|
/** The core library version from package.json (inlined at build time). */
|
|
140
|
-
const CORE_VERSION = '0.5.
|
|
140
|
+
const CORE_VERSION = '0.5.5';
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
143
|
* Shared file I/O helpers for managed section operations.
|
|
@@ -152,7 +152,7 @@ const STALE_LOCK_MS = 120_000;
|
|
|
152
152
|
/** Default core version when none provided. */
|
|
153
153
|
const DEFAULT_CORE_VERSION = CORE_VERSION;
|
|
154
154
|
/** Lock retry options. */
|
|
155
|
-
const LOCK_RETRIES = { retries:
|
|
155
|
+
const LOCK_RETRIES = { retries: 0 };
|
|
156
156
|
/** Maximum rename retry attempts on EPERM. */
|
|
157
157
|
const ATOMIC_WRITE_MAX_RETRIES = 3;
|
|
158
158
|
/** Delay between EPERM retries in milliseconds. */
|
|
@@ -195,26 +195,15 @@ function atomicWrite(filePath, content) {
|
|
|
195
195
|
}
|
|
196
196
|
}
|
|
197
197
|
}
|
|
198
|
-
|
|
199
|
-
* Execute a callback while holding a file lock.
|
|
200
|
-
*
|
|
201
|
-
* @remarks
|
|
202
|
-
* Acquires a lock on the file, executes the callback, and releases
|
|
203
|
-
* the lock in a finally block. The lock uses a 2-minute stale threshold
|
|
204
|
-
* and retries up to 5 times.
|
|
205
|
-
*
|
|
206
|
-
* @param filePath - Absolute path to the file to lock.
|
|
207
|
-
* @param fn - Async callback to execute while holding the lock.
|
|
208
|
-
*/
|
|
209
|
-
async function withFileLock(filePath, fn) {
|
|
198
|
+
async function withLock(targetPath, fn, options, onLockError) {
|
|
210
199
|
let release;
|
|
211
200
|
try {
|
|
212
|
-
release = await lock(
|
|
213
|
-
stale: STALE_LOCK_MS,
|
|
214
|
-
retries: LOCK_RETRIES,
|
|
215
|
-
});
|
|
201
|
+
release = await lock(targetPath, options);
|
|
216
202
|
await fn();
|
|
217
203
|
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
throw error;
|
|
206
|
+
}
|
|
218
207
|
finally {
|
|
219
208
|
if (release) {
|
|
220
209
|
try {
|
|
@@ -226,6 +215,23 @@ async function withFileLock(filePath, fn) {
|
|
|
226
215
|
}
|
|
227
216
|
}
|
|
228
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* Execute a callback while holding a file lock.
|
|
220
|
+
*
|
|
221
|
+
* @remarks
|
|
222
|
+
* Acquires a lock on the file, executes the callback, and releases
|
|
223
|
+
* the lock in a finally block. The lock uses a 2-minute stale threshold
|
|
224
|
+
* and retries up to 5 times.
|
|
225
|
+
*
|
|
226
|
+
* @param filePath - Absolute path to the file to lock.
|
|
227
|
+
* @param fn - Async callback to execute while holding the lock.
|
|
228
|
+
*/
|
|
229
|
+
async function withFileLock(filePath, fn) {
|
|
230
|
+
await withLock(filePath, fn, {
|
|
231
|
+
stale: STALE_LOCK_MS,
|
|
232
|
+
retries: LOCK_RETRIES,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
229
235
|
|
|
230
236
|
/**
|
|
231
237
|
* Shared component version state file management.
|
|
@@ -1265,7 +1271,7 @@ function createPluginCli(options) {
|
|
|
1265
1271
|
throw new Error(`Plugin dist directory not found: ${distDir}. Ensure the plugin is built before installing.`);
|
|
1266
1272
|
}
|
|
1267
1273
|
console.log(`Copying dist to ${extensionsDir}...`);
|
|
1268
|
-
copyDistFiles(distDir, extensionsDir);
|
|
1274
|
+
copyDistFiles(distDir, join(extensionsDir, 'dist'));
|
|
1269
1275
|
// Copy package.json and openclaw.plugin.json from package root
|
|
1270
1276
|
for (const file of ['package.json', 'openclaw.plugin.json']) {
|
|
1271
1277
|
const src = join(pkgRoot, file);
|
package/dist/index.d.ts
CHANGED
|
@@ -575,6 +575,7 @@ declare class ComponentWriter {
|
|
|
575
575
|
private readonly configDir;
|
|
576
576
|
private readonly gatewayUrl;
|
|
577
577
|
private readonly pendingCleanups;
|
|
578
|
+
private cyclePromise;
|
|
578
579
|
/** @internal */
|
|
579
580
|
constructor(component: JeevesComponentDescriptor, options?: ComponentWriterOptions);
|
|
580
581
|
/** The component's config directory path. */
|
|
@@ -592,6 +593,7 @@ declare class ComponentWriter {
|
|
|
592
593
|
start(): void;
|
|
593
594
|
/** Stop the writer timer. */
|
|
594
595
|
stop(): void;
|
|
596
|
+
private scheduleNextCycle;
|
|
595
597
|
/**
|
|
596
598
|
* Execute a single write cycle.
|
|
597
599
|
*
|
|
@@ -602,6 +604,7 @@ declare class ComponentWriter {
|
|
|
602
604
|
* 4. Run HEARTBEAT health orchestration.
|
|
603
605
|
*/
|
|
604
606
|
cycle(): Promise<void>;
|
|
607
|
+
private runCycle;
|
|
605
608
|
}
|
|
606
609
|
|
|
607
610
|
/**
|
|
@@ -735,7 +738,7 @@ declare function buildHeartbeatSection(entries: HeartbeatEntry[]): string;
|
|
|
735
738
|
*
|
|
736
739
|
* @remarks
|
|
737
740
|
* Replaces everything from `# Jeeves Platform Status` to EOF.
|
|
738
|
-
* Preserves user content above the heading.
|
|
741
|
+
* Preserves user content above the heading.
|
|
739
742
|
*
|
|
740
743
|
* @param filePath - Absolute path to HEARTBEAT.md.
|
|
741
744
|
* @param entries - Component entries to write.
|
|
@@ -1268,7 +1271,7 @@ declare function removeManagedSection(filePath: string, options?: RemoveManagedS
|
|
|
1268
1271
|
* - `block`: Replaces the entire managed block (SOUL.md, AGENTS.md).
|
|
1269
1272
|
* - `section`: Upserts a named H2 section within the managed block (TOOLS.md).
|
|
1270
1273
|
*
|
|
1271
|
-
* Provides
|
|
1274
|
+
* Provides version-stamp convergence and atomic writes.
|
|
1272
1275
|
*/
|
|
1273
1276
|
|
|
1274
1277
|
/** Options for updateManagedSection. */
|
package/dist/index.js
CHANGED
|
@@ -183,14 +183,14 @@ const PLATFORM_COMPONENTS = [
|
|
|
183
183
|
* Core library version, inlined at build time.
|
|
184
184
|
*
|
|
185
185
|
* @remarks
|
|
186
|
-
* The `0.5.
|
|
186
|
+
* The `0.5.5` placeholder is replaced by
|
|
187
187
|
* `@rollup/plugin-replace` during the build with the actual version
|
|
188
188
|
* from `package.json`. This ensures the correct version survives
|
|
189
189
|
* when consumers bundle core into their own dist (where runtime
|
|
190
190
|
* `import.meta.url`-based resolution would find the wrong package.json).
|
|
191
191
|
*/
|
|
192
192
|
/** The core library version from package.json (inlined at build time). */
|
|
193
|
-
const CORE_VERSION = '0.5.
|
|
193
|
+
const CORE_VERSION = '0.5.5';
|
|
194
194
|
|
|
195
195
|
/**
|
|
196
196
|
* Workspace and config root initialization.
|
|
@@ -287,7 +287,11 @@ const STALE_LOCK_MS = 120_000;
|
|
|
287
287
|
/** Default core version when none provided. */
|
|
288
288
|
const DEFAULT_CORE_VERSION = CORE_VERSION;
|
|
289
289
|
/** Lock retry options. */
|
|
290
|
-
const LOCK_RETRIES = { retries:
|
|
290
|
+
const LOCK_RETRIES = { retries: 0 };
|
|
291
|
+
/** Workspace lock retry options. */
|
|
292
|
+
const WORKSPACE_LOCK_RETRIES = { retries: 0 };
|
|
293
|
+
/** Workspace lock file name. */
|
|
294
|
+
const WORKSPACE_LOCK_FILE = 'jeeves.lock';
|
|
291
295
|
/** Maximum rename retry attempts on EPERM. */
|
|
292
296
|
const ATOMIC_WRITE_MAX_RETRIES = 3;
|
|
293
297
|
/** Delay between EPERM retries in milliseconds. */
|
|
@@ -330,26 +334,18 @@ function atomicWrite(filePath, content) {
|
|
|
330
334
|
}
|
|
331
335
|
}
|
|
332
336
|
}
|
|
333
|
-
|
|
334
|
-
* Execute a callback while holding a file lock.
|
|
335
|
-
*
|
|
336
|
-
* @remarks
|
|
337
|
-
* Acquires a lock on the file, executes the callback, and releases
|
|
338
|
-
* the lock in a finally block. The lock uses a 2-minute stale threshold
|
|
339
|
-
* and retries up to 5 times.
|
|
340
|
-
*
|
|
341
|
-
* @param filePath - Absolute path to the file to lock.
|
|
342
|
-
* @param fn - Async callback to execute while holding the lock.
|
|
343
|
-
*/
|
|
344
|
-
async function withFileLock(filePath, fn) {
|
|
337
|
+
async function withLock(targetPath, fn, options, onLockError) {
|
|
345
338
|
let release;
|
|
346
339
|
try {
|
|
347
|
-
release = await lock(
|
|
348
|
-
stale: STALE_LOCK_MS,
|
|
349
|
-
retries: LOCK_RETRIES,
|
|
350
|
-
});
|
|
340
|
+
release = await lock(targetPath, options);
|
|
351
341
|
await fn();
|
|
352
342
|
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
if (onLockError?.(error)) {
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
throw error;
|
|
348
|
+
}
|
|
353
349
|
finally {
|
|
354
350
|
if (release) {
|
|
355
351
|
try {
|
|
@@ -361,6 +357,44 @@ async function withFileLock(filePath, fn) {
|
|
|
361
357
|
}
|
|
362
358
|
}
|
|
363
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* Execute a callback while holding a file lock.
|
|
362
|
+
*
|
|
363
|
+
* @remarks
|
|
364
|
+
* Acquires a lock on the file, executes the callback, and releases
|
|
365
|
+
* the lock in a finally block. The lock uses a 2-minute stale threshold
|
|
366
|
+
* and retries up to 5 times.
|
|
367
|
+
*
|
|
368
|
+
* @param filePath - Absolute path to the file to lock.
|
|
369
|
+
* @param fn - Async callback to execute while holding the lock.
|
|
370
|
+
*/
|
|
371
|
+
async function withFileLock(filePath, fn) {
|
|
372
|
+
await withLock(filePath, fn, {
|
|
373
|
+
stale: STALE_LOCK_MS,
|
|
374
|
+
retries: LOCK_RETRIES,
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Execute a callback while holding the workspace cycle lock.
|
|
379
|
+
*
|
|
380
|
+
* @remarks
|
|
381
|
+
* Acquires a lock on `{workspacePath}/jeeves.lock`, executes the callback,
|
|
382
|
+
* and releases the lock in a finally block. If the lock is already held,
|
|
383
|
+
* returns silently so the caller can skip this cycle.
|
|
384
|
+
*
|
|
385
|
+
* @param workspacePath - Absolute workspace path.
|
|
386
|
+
* @param fn - Async callback to execute while holding the lock.
|
|
387
|
+
*/
|
|
388
|
+
async function withWorkspaceLock(workspacePath, fn) {
|
|
389
|
+
const lockPath = join(workspacePath, WORKSPACE_LOCK_FILE);
|
|
390
|
+
writeFileSync(lockPath, '', { flag: 'a' });
|
|
391
|
+
await withLock(lockPath, fn, {
|
|
392
|
+
stale: STALE_LOCK_MS,
|
|
393
|
+
retries: WORKSPACE_LOCK_RETRIES,
|
|
394
|
+
}, (error) => error instanceof Error &&
|
|
395
|
+
'code' in error &&
|
|
396
|
+
error.code === 'ELOCKED');
|
|
397
|
+
}
|
|
364
398
|
|
|
365
399
|
/**
|
|
366
400
|
* Shared internal utility functions.
|
|
@@ -1094,7 +1128,7 @@ function buildHeartbeatSection(entries) {
|
|
|
1094
1128
|
*
|
|
1095
1129
|
* @remarks
|
|
1096
1130
|
* Replaces everything from `# Jeeves Platform Status` to EOF.
|
|
1097
|
-
* Preserves user content above the heading.
|
|
1131
|
+
* Preserves user content above the heading.
|
|
1098
1132
|
*
|
|
1099
1133
|
* @param filePath - Absolute path to HEARTBEAT.md.
|
|
1100
1134
|
* @param entries - Component entries to write.
|
|
@@ -2706,7 +2740,7 @@ function createPluginCli(options) {
|
|
|
2706
2740
|
throw new Error(`Plugin dist directory not found: ${distDir}. Ensure the plugin is built before installing.`);
|
|
2707
2741
|
}
|
|
2708
2742
|
console.log(`Copying dist to ${extensionsDir}...`);
|
|
2709
|
-
copyDistFiles(distDir, extensionsDir);
|
|
2743
|
+
copyDistFiles(distDir, join(extensionsDir, 'dist'));
|
|
2710
2744
|
// Copy package.json and openclaw.plugin.json from package root
|
|
2711
2745
|
for (const file of ['package.json', 'openclaw.plugin.json']) {
|
|
2712
2746
|
const src = join(pkgRoot, file);
|
|
@@ -3236,7 +3270,7 @@ function stripForeignMarkers(content, currentMarkers) {
|
|
|
3236
3270
|
* - `block`: Replaces the entire managed block (SOUL.md, AGENTS.md).
|
|
3237
3271
|
* - `section`: Upserts a named H2 section within the managed block (TOOLS.md).
|
|
3238
3272
|
*
|
|
3239
|
-
* Provides
|
|
3273
|
+
* Provides version-stamp convergence and atomic writes.
|
|
3240
3274
|
*/
|
|
3241
3275
|
/**
|
|
3242
3276
|
* Update a managed section in a file.
|
|
@@ -4673,6 +4707,7 @@ class ComponentWriter {
|
|
|
4673
4707
|
configDir;
|
|
4674
4708
|
gatewayUrl;
|
|
4675
4709
|
pendingCleanups = new Set();
|
|
4710
|
+
cyclePromise;
|
|
4676
4711
|
/** @internal */
|
|
4677
4712
|
constructor(component, options) {
|
|
4678
4713
|
this.component = component;
|
|
@@ -4685,7 +4720,9 @@ class ComponentWriter {
|
|
|
4685
4720
|
}
|
|
4686
4721
|
/** Whether the writer timer is currently running or pending its first cycle. */
|
|
4687
4722
|
get isRunning() {
|
|
4688
|
-
return this.jitterTimeout !== undefined ||
|
|
4723
|
+
return (this.jitterTimeout !== undefined ||
|
|
4724
|
+
this.timer !== undefined ||
|
|
4725
|
+
this.cyclePromise !== undefined);
|
|
4689
4726
|
}
|
|
4690
4727
|
/**
|
|
4691
4728
|
* Start the writer timer.
|
|
@@ -4703,8 +4740,7 @@ class ComponentWriter {
|
|
|
4703
4740
|
const jitterMs = Math.floor(Math.random() * intervalMs);
|
|
4704
4741
|
this.jitterTimeout = setTimeout(() => {
|
|
4705
4742
|
this.jitterTimeout = undefined;
|
|
4706
|
-
|
|
4707
|
-
this.timer = setInterval(() => void this.cycle(), intervalMs);
|
|
4743
|
+
this.scheduleNextCycle(0, intervalMs);
|
|
4708
4744
|
}, jitterMs);
|
|
4709
4745
|
}
|
|
4710
4746
|
/** Stop the writer timer. */
|
|
@@ -4714,10 +4750,19 @@ class ComponentWriter {
|
|
|
4714
4750
|
this.jitterTimeout = undefined;
|
|
4715
4751
|
}
|
|
4716
4752
|
if (this.timer) {
|
|
4717
|
-
|
|
4753
|
+
clearTimeout(this.timer);
|
|
4718
4754
|
this.timer = undefined;
|
|
4719
4755
|
}
|
|
4720
4756
|
}
|
|
4757
|
+
scheduleNextCycle(delayMs, intervalMs) {
|
|
4758
|
+
this.timer = setTimeout(() => {
|
|
4759
|
+
this.timer = undefined;
|
|
4760
|
+
void this.cycle().finally(() => {
|
|
4761
|
+
if (this.isRunning)
|
|
4762
|
+
this.scheduleNextCycle(intervalMs, intervalMs);
|
|
4763
|
+
});
|
|
4764
|
+
}, delayMs);
|
|
4765
|
+
}
|
|
4721
4766
|
/**
|
|
4722
4767
|
* Execute a single write cycle.
|
|
4723
4768
|
*
|
|
@@ -4728,44 +4773,54 @@ class ComponentWriter {
|
|
|
4728
4773
|
* 4. Run HEARTBEAT health orchestration.
|
|
4729
4774
|
*/
|
|
4730
4775
|
async cycle() {
|
|
4776
|
+
if (this.cyclePromise)
|
|
4777
|
+
return this.cyclePromise;
|
|
4778
|
+
this.cyclePromise = this.runCycle().finally(() => {
|
|
4779
|
+
this.cyclePromise = undefined;
|
|
4780
|
+
});
|
|
4781
|
+
return this.cyclePromise;
|
|
4782
|
+
}
|
|
4783
|
+
async runCycle() {
|
|
4731
4784
|
try {
|
|
4732
4785
|
const workspacePath = getWorkspacePath();
|
|
4733
4786
|
const toolsPath = join(workspacePath, WORKSPACE_FILES.tools);
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
|
|
4765
|
-
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4787
|
+
await withWorkspaceLock(workspacePath, async () => {
|
|
4788
|
+
// 1. Write the component's TOOLS.md section
|
|
4789
|
+
const toolsContent = this.component.generateToolsContent();
|
|
4790
|
+
await updateManagedSection(toolsPath, toolsContent, {
|
|
4791
|
+
mode: 'section',
|
|
4792
|
+
sectionId: this.component.sectionId,
|
|
4793
|
+
markers: TOOLS_MARKERS,
|
|
4794
|
+
coreVersion: CORE_VERSION,
|
|
4795
|
+
});
|
|
4796
|
+
// 2. Platform content maintenance
|
|
4797
|
+
await refreshPlatformContent({
|
|
4798
|
+
coreVersion: CORE_VERSION,
|
|
4799
|
+
componentName: this.component.name,
|
|
4800
|
+
componentVersion: this.component.version,
|
|
4801
|
+
servicePackage: this.component.servicePackage,
|
|
4802
|
+
pluginPackage: this.component.pluginPackage,
|
|
4803
|
+
});
|
|
4804
|
+
// 3. Cleanup escalation
|
|
4805
|
+
if (this.gatewayUrl) {
|
|
4806
|
+
scanAndEscalateCleanup([
|
|
4807
|
+
{ filePath: toolsPath, markerIdentity: 'TOOLS' },
|
|
4808
|
+
{
|
|
4809
|
+
filePath: join(workspacePath, WORKSPACE_FILES.soul),
|
|
4810
|
+
markerIdentity: 'SOUL',
|
|
4811
|
+
},
|
|
4812
|
+
{
|
|
4813
|
+
filePath: join(workspacePath, WORKSPACE_FILES.agents),
|
|
4814
|
+
markerIdentity: 'AGENTS',
|
|
4815
|
+
},
|
|
4816
|
+
], this.gatewayUrl, this.pendingCleanups);
|
|
4817
|
+
}
|
|
4818
|
+
// 4. HEARTBEAT orchestration
|
|
4819
|
+
await runHeartbeatCycle({
|
|
4820
|
+
workspacePath,
|
|
4821
|
+
coreConfigDir: getCoreConfigDir(),
|
|
4822
|
+
configRoot: getConfigRoot(),
|
|
4823
|
+
});
|
|
4769
4824
|
});
|
|
4770
4825
|
}
|
|
4771
4826
|
catch (err) {
|
package/package.json
CHANGED