@karmaniverous/jeeves-meta 0.16.1 → 0.16.2
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/README.md +2 -0
- package/dist/cli/jeeves-meta/index.js +31 -2
- package/dist/executor/GatewayExecutor.d.ts +6 -0
- package/dist/index.js +31 -2
- package/dist/schema/config.d.ts +4 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -14,6 +14,8 @@ HTTP service for the Jeeves knowledge synthesis engine. Provides a Fastify API,
|
|
|
14
14
|
- **Cross-meta references** — `_crossRefs` declares relationships to other metas; referenced `_content` included as architect/builder context
|
|
15
15
|
- **Archive management** — timestamped snapshots with configurable pruning
|
|
16
16
|
- **Lock staging** — write to `.lock` → copy to `meta.json` → archive (crash-safe)
|
|
17
|
+
- **Staging file retry** — configurable retries (`stagingRetries`, `stagingRetryDelayMs`) when sub-agent output file is not yet visible after session completion (network/NFS latency)
|
|
18
|
+
- **Preview delta cap** — `/preview` response includes `deltaFilesTruncated` flag and `deltaCount` total when delta files exceed `previewDeltaFilesCap`
|
|
17
19
|
- **Virtual rule registration** — registers 3 watcher inference rules at startup with retry
|
|
18
20
|
- **Progress reporting** — real-time synthesis events via gateway channel messages
|
|
19
21
|
- **Graceful shutdown** — stop scheduler, release locks, close server
|
|
@@ -806,6 +806,14 @@ const serviceConfigSchema = metaConfigSchema.extend({
|
|
|
806
806
|
* Rules are evaluated in order; last match wins for steer/crossRefs.
|
|
807
807
|
*/
|
|
808
808
|
autoSeed: z.array(autoSeedRuleSchema).optional().default([]),
|
|
809
|
+
/** Optional workspace directory for synthesis staging files. Defaults to `os.tmpdir() + '/jeeves-meta'`. */
|
|
810
|
+
workspaceDir: z.string().optional(),
|
|
811
|
+
/** Max retries when staging file not yet visible after session completion. Default: 10. */
|
|
812
|
+
stagingRetries: z.number().int().min(0).default(10),
|
|
813
|
+
/** Delay between staging file retries in ms. Default: 250. */
|
|
814
|
+
stagingRetryDelayMs: z.number().int().min(0).default(250),
|
|
815
|
+
/** Maximum number of delta files returned in /preview response. Default: 50. */
|
|
816
|
+
previewDeltaFilesCap: z.number().int().min(1).default(50),
|
|
809
817
|
});
|
|
810
818
|
|
|
811
819
|
/**
|
|
@@ -933,12 +941,16 @@ class GatewayExecutor {
|
|
|
933
941
|
apiKey;
|
|
934
942
|
pollIntervalMs;
|
|
935
943
|
workspaceDir;
|
|
944
|
+
stagingRetries;
|
|
945
|
+
stagingRetryDelayMs;
|
|
936
946
|
controller = new AbortController();
|
|
937
947
|
constructor(options = {}) {
|
|
938
948
|
this.gatewayUrl = (options.gatewayUrl ?? 'http://127.0.0.1:18789').replace(/\/+$/, '');
|
|
939
949
|
this.apiKey = options.apiKey;
|
|
940
950
|
this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
941
951
|
this.workspaceDir = options.workspaceDir ?? join(tmpdir(), 'jeeves-meta');
|
|
952
|
+
this.stagingRetries = options.stagingRetries ?? 10;
|
|
953
|
+
this.stagingRetryDelayMs = options.stagingRetryDelayMs ?? 250;
|
|
942
954
|
}
|
|
943
955
|
/** Remove a temp output file if it exists. */
|
|
944
956
|
cleanupOutputFile(outputPath) {
|
|
@@ -1168,10 +1180,23 @@ class GatewayExecutor {
|
|
|
1168
1180
|
// No output or partial output — throw for _state recovery (§3.16.6)
|
|
1169
1181
|
throw new SpawnTimeoutError('Gateway-side timeout detected (session status: timeout)', outputPath);
|
|
1170
1182
|
}
|
|
1171
|
-
// Normal completion — read
|
|
1183
|
+
// Normal completion — read staging file with retry for delayed visibility
|
|
1172
1184
|
const output = this.readStagingFile(outputPath);
|
|
1173
1185
|
if (output !== undefined)
|
|
1174
1186
|
return { output, tokens };
|
|
1187
|
+
// Staging file not yet visible — retry with bounded grace window
|
|
1188
|
+
for (let i = 0; i < this.stagingRetries; i++) {
|
|
1189
|
+
await sleepAsync(this.stagingRetryDelayMs);
|
|
1190
|
+
// Check abort after yield point — signal may have been
|
|
1191
|
+
// set externally (e.g. operator abort) during the sleep.
|
|
1192
|
+
if (this.aborted) {
|
|
1193
|
+
this.cleanupOutputFile(outputPath);
|
|
1194
|
+
throw new SpawnAbortedError();
|
|
1195
|
+
}
|
|
1196
|
+
const retryOutput = this.readStagingFile(outputPath);
|
|
1197
|
+
if (retryOutput !== undefined)
|
|
1198
|
+
return { output: retryOutput, tokens };
|
|
1199
|
+
}
|
|
1175
1200
|
// Fallback: extract from message content if file wasn't written.
|
|
1176
1201
|
// Skip ANNOUNCE_SKIP sentinel messages — the real output is in
|
|
1177
1202
|
// a preceding assistant message (the file write).
|
|
@@ -4452,9 +4477,10 @@ function registerPreviewRoute(app, deps) {
|
|
|
4452
4477
|
ownedFiles: scopeFiles.length,
|
|
4453
4478
|
childMetas: targetNode.children.length,
|
|
4454
4479
|
deltaFiles: deltaFiles
|
|
4455
|
-
.slice(0,
|
|
4480
|
+
.slice(0, config.previewDeltaFilesCap)
|
|
4456
4481
|
.map((f) => ({ path: f, action: 'modified' })),
|
|
4457
4482
|
deltaCount: deltaFiles.length,
|
|
4483
|
+
deltaFilesTruncated: deltaFiles.length > config.previewDeltaFilesCap,
|
|
4458
4484
|
},
|
|
4459
4485
|
estimatedTokens,
|
|
4460
4486
|
// New phase-state fields (additive)
|
|
@@ -5156,6 +5182,9 @@ async function startService(config, configPath) {
|
|
|
5156
5182
|
const executor = new GatewayExecutor({
|
|
5157
5183
|
gatewayUrl: config.gatewayUrl,
|
|
5158
5184
|
apiKey: config.gatewayApiKey,
|
|
5185
|
+
workspaceDir: config.workspaceDir,
|
|
5186
|
+
stagingRetries: config.stagingRetries,
|
|
5187
|
+
stagingRetryDelayMs: config.stagingRetryDelayMs,
|
|
5159
5188
|
});
|
|
5160
5189
|
// Runtime stats (mutable, shared with routes)
|
|
5161
5190
|
const stats = {
|
|
@@ -18,6 +18,10 @@ export interface GatewayExecutorOptions {
|
|
|
18
18
|
pollIntervalMs?: number;
|
|
19
19
|
/** Workspace directory for output staging. Default: OS temp dir + /jeeves-meta. */
|
|
20
20
|
workspaceDir?: string;
|
|
21
|
+
/** Max retries when staging file not yet visible after session completion. Default: 10. */
|
|
22
|
+
stagingRetries?: number;
|
|
23
|
+
/** Delay between retries in ms. Default: 250. */
|
|
24
|
+
stagingRetryDelayMs?: number;
|
|
21
25
|
}
|
|
22
26
|
/**
|
|
23
27
|
* MetaExecutor that spawns OpenClaw sessions via the gateway's
|
|
@@ -32,6 +36,8 @@ export declare class GatewayExecutor implements MetaExecutor {
|
|
|
32
36
|
private readonly apiKey;
|
|
33
37
|
private readonly pollIntervalMs;
|
|
34
38
|
private readonly workspaceDir;
|
|
39
|
+
private readonly stagingRetries;
|
|
40
|
+
private readonly stagingRetryDelayMs;
|
|
35
41
|
private controller;
|
|
36
42
|
constructor(options?: GatewayExecutorOptions);
|
|
37
43
|
/** Remove a temp output file if it exists. */
|
package/dist/index.js
CHANGED
|
@@ -1295,6 +1295,14 @@ const serviceConfigSchema = metaConfigSchema.extend({
|
|
|
1295
1295
|
* Rules are evaluated in order; last match wins for steer/crossRefs.
|
|
1296
1296
|
*/
|
|
1297
1297
|
autoSeed: z.array(autoSeedRuleSchema).optional().default([]),
|
|
1298
|
+
/** Optional workspace directory for synthesis staging files. Defaults to `os.tmpdir() + '/jeeves-meta'`. */
|
|
1299
|
+
workspaceDir: z.string().optional(),
|
|
1300
|
+
/** Max retries when staging file not yet visible after session completion. Default: 10. */
|
|
1301
|
+
stagingRetries: z.number().int().min(0).default(10),
|
|
1302
|
+
/** Delay between staging file retries in ms. Default: 250. */
|
|
1303
|
+
stagingRetryDelayMs: z.number().int().min(0).default(250),
|
|
1304
|
+
/** Maximum number of delta files returned in /preview response. Default: 50. */
|
|
1305
|
+
previewDeltaFilesCap: z.number().int().min(1).default(50),
|
|
1298
1306
|
});
|
|
1299
1307
|
|
|
1300
1308
|
/**
|
|
@@ -1467,12 +1475,16 @@ class GatewayExecutor {
|
|
|
1467
1475
|
apiKey;
|
|
1468
1476
|
pollIntervalMs;
|
|
1469
1477
|
workspaceDir;
|
|
1478
|
+
stagingRetries;
|
|
1479
|
+
stagingRetryDelayMs;
|
|
1470
1480
|
controller = new AbortController();
|
|
1471
1481
|
constructor(options = {}) {
|
|
1472
1482
|
this.gatewayUrl = (options.gatewayUrl ?? 'http://127.0.0.1:18789').replace(/\/+$/, '');
|
|
1473
1483
|
this.apiKey = options.apiKey;
|
|
1474
1484
|
this.pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
|
|
1475
1485
|
this.workspaceDir = options.workspaceDir ?? join(tmpdir(), 'jeeves-meta');
|
|
1486
|
+
this.stagingRetries = options.stagingRetries ?? 10;
|
|
1487
|
+
this.stagingRetryDelayMs = options.stagingRetryDelayMs ?? 250;
|
|
1476
1488
|
}
|
|
1477
1489
|
/** Remove a temp output file if it exists. */
|
|
1478
1490
|
cleanupOutputFile(outputPath) {
|
|
@@ -1702,10 +1714,23 @@ class GatewayExecutor {
|
|
|
1702
1714
|
// No output or partial output — throw for _state recovery (§3.16.6)
|
|
1703
1715
|
throw new SpawnTimeoutError('Gateway-side timeout detected (session status: timeout)', outputPath);
|
|
1704
1716
|
}
|
|
1705
|
-
// Normal completion — read
|
|
1717
|
+
// Normal completion — read staging file with retry for delayed visibility
|
|
1706
1718
|
const output = this.readStagingFile(outputPath);
|
|
1707
1719
|
if (output !== undefined)
|
|
1708
1720
|
return { output, tokens };
|
|
1721
|
+
// Staging file not yet visible — retry with bounded grace window
|
|
1722
|
+
for (let i = 0; i < this.stagingRetries; i++) {
|
|
1723
|
+
await sleepAsync(this.stagingRetryDelayMs);
|
|
1724
|
+
// Check abort after yield point — signal may have been
|
|
1725
|
+
// set externally (e.g. operator abort) during the sleep.
|
|
1726
|
+
if (this.aborted) {
|
|
1727
|
+
this.cleanupOutputFile(outputPath);
|
|
1728
|
+
throw new SpawnAbortedError();
|
|
1729
|
+
}
|
|
1730
|
+
const retryOutput = this.readStagingFile(outputPath);
|
|
1731
|
+
if (retryOutput !== undefined)
|
|
1732
|
+
return { output: retryOutput, tokens };
|
|
1733
|
+
}
|
|
1709
1734
|
// Fallback: extract from message content if file wasn't written.
|
|
1710
1735
|
// Skip ANNOUNCE_SKIP sentinel messages — the real output is in
|
|
1711
1736
|
// a preceding assistant message (the file write).
|
|
@@ -4710,9 +4735,10 @@ function registerPreviewRoute(app, deps) {
|
|
|
4710
4735
|
ownedFiles: scopeFiles.length,
|
|
4711
4736
|
childMetas: targetNode.children.length,
|
|
4712
4737
|
deltaFiles: deltaFiles
|
|
4713
|
-
.slice(0,
|
|
4738
|
+
.slice(0, config.previewDeltaFilesCap)
|
|
4714
4739
|
.map((f) => ({ path: f, action: 'modified' })),
|
|
4715
4740
|
deltaCount: deltaFiles.length,
|
|
4741
|
+
deltaFilesTruncated: deltaFiles.length > config.previewDeltaFilesCap,
|
|
4716
4742
|
},
|
|
4717
4743
|
estimatedTokens,
|
|
4718
4744
|
// New phase-state fields (additive)
|
|
@@ -5386,6 +5412,9 @@ async function startService(config, configPath) {
|
|
|
5386
5412
|
const executor = new GatewayExecutor({
|
|
5387
5413
|
gatewayUrl: config.gatewayUrl,
|
|
5388
5414
|
apiKey: config.gatewayApiKey,
|
|
5415
|
+
workspaceDir: config.workspaceDir,
|
|
5416
|
+
stagingRetries: config.stagingRetries,
|
|
5417
|
+
stagingRetryDelayMs: config.stagingRetryDelayMs,
|
|
5389
5418
|
});
|
|
5390
5419
|
// Runtime stats (mutable, shared with routes)
|
|
5391
5420
|
const stats = {
|
package/dist/schema/config.d.ts
CHANGED
|
@@ -49,6 +49,10 @@ export declare const serviceConfigSchema: z.ZodObject<{
|
|
|
49
49
|
crossRefs: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
50
50
|
parentDepth: z.ZodOptional<z.ZodNumber>;
|
|
51
51
|
}, z.core.$strip>>>>;
|
|
52
|
+
workspaceDir: z.ZodOptional<z.ZodString>;
|
|
53
|
+
stagingRetries: z.ZodDefault<z.ZodNumber>;
|
|
54
|
+
stagingRetryDelayMs: z.ZodDefault<z.ZodNumber>;
|
|
55
|
+
previewDeltaFilesCap: z.ZodDefault<z.ZodNumber>;
|
|
52
56
|
}, z.core.$strip>;
|
|
53
57
|
/** Inferred type for service configuration. */
|
|
54
58
|
export type ServiceConfig = z.infer<typeof serviceConfigSchema>;
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@karmaniverous/jeeves": "^0.5.12",
|
|
11
|
-
"@karmaniverous/jeeves-meta-core": "^0.2.
|
|
11
|
+
"@karmaniverous/jeeves-meta-core": "^0.2.1",
|
|
12
12
|
"commander": "^14",
|
|
13
13
|
"croner": "^10",
|
|
14
14
|
"fastify": "^5.8",
|
|
@@ -110,5 +110,5 @@
|
|
|
110
110
|
},
|
|
111
111
|
"type": "module",
|
|
112
112
|
"types": "dist/index.d.ts",
|
|
113
|
-
"version": "0.16.
|
|
113
|
+
"version": "0.16.2"
|
|
114
114
|
}
|