@oka-core/reason 0.2.15 → 0.2.16
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/abort-controller.d.ts +19 -0
- package/dist/abort-controller.d.ts.map +1 -0
- package/dist/abort-controller.js +53 -0
- package/dist/activity-tracker.d.ts +48 -0
- package/dist/activity-tracker.d.ts.map +1 -0
- package/dist/activity-tracker.js +80 -0
- package/dist/analytics.d.ts +49 -0
- package/dist/analytics.d.ts.map +1 -0
- package/dist/analytics.js +88 -0
- package/dist/array.d.ts +12 -0
- package/dist/array.d.ts.map +1 -0
- package/dist/array.js +20 -0
- package/dist/async-context.d.ts +20 -0
- package/dist/async-context.d.ts.map +1 -0
- package/dist/async-context.js +25 -0
- package/dist/binary-check.d.ts +16 -0
- package/dist/binary-check.d.ts.map +1 -0
- package/dist/binary-check.js +43 -0
- package/dist/buffered-writer.d.ts +30 -0
- package/dist/buffered-writer.d.ts.map +1 -0
- package/dist/buffered-writer.js +87 -0
- package/dist/circular-buffer.d.ts +28 -0
- package/dist/circular-buffer.d.ts.map +1 -0
- package/dist/circular-buffer.js +61 -0
- package/dist/cleanup-registry.d.ts +23 -0
- package/dist/cleanup-registry.d.ts.map +1 -0
- package/dist/cleanup-registry.js +34 -0
- package/dist/client.d.ts +4 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +32 -10
- package/dist/combined-abort-signal.d.ts +25 -0
- package/dist/combined-abort-signal.d.ts.map +1 -0
- package/dist/combined-abort-signal.js +47 -0
- package/dist/cron-lock.d.ts +29 -0
- package/dist/cron-lock.d.ts.map +1 -0
- package/dist/cron-lock.js +127 -0
- package/dist/cron-scheduler.d.ts +41 -0
- package/dist/cron-scheduler.d.ts.map +1 -0
- package/dist/cron-scheduler.js +189 -0
- package/dist/cron-tasks.d.ts +86 -0
- package/dist/cron-tasks.d.ts.map +1 -0
- package/dist/cron-tasks.js +205 -0
- package/dist/cron.d.ts +35 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +215 -0
- package/dist/env.d.ts +26 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +50 -0
- package/dist/errors.d.ts +99 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +214 -0
- package/dist/format.d.ts +21 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +48 -0
- package/dist/fps-tracker.d.ts +22 -0
- package/dist/fps-tracker.d.ts.map +1 -0
- package/dist/fps-tracker.js +44 -0
- package/dist/graceful-shutdown.d.ts +35 -0
- package/dist/graceful-shutdown.d.ts.map +1 -0
- package/dist/graceful-shutdown.js +89 -0
- package/dist/hash.d.ts +21 -0
- package/dist/hash.d.ts.map +1 -0
- package/dist/hash.js +31 -0
- package/dist/heap-diagnostics.d.ts +68 -0
- package/dist/heap-diagnostics.d.ts.map +1 -0
- package/dist/heap-diagnostics.js +110 -0
- package/dist/idle-timeout.d.ts +21 -0
- package/dist/idle-timeout.d.ts.map +1 -0
- package/dist/idle-timeout.js +42 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/intl.d.ts +18 -0
- package/dist/intl.d.ts.map +1 -0
- package/dist/intl.js +75 -0
- package/dist/jsonl.d.ts +16 -0
- package/dist/jsonl.d.ts.map +1 -0
- package/dist/jsonl.js +60 -0
- package/dist/lazy-schema.d.ts +6 -0
- package/dist/lazy-schema.d.ts.map +1 -0
- package/dist/lazy-schema.js +8 -0
- package/dist/memo.d.ts +64 -0
- package/dist/memo.d.ts.map +1 -0
- package/dist/memo.js +162 -0
- package/dist/pkce.d.ts +13 -0
- package/dist/pkce.d.ts.map +1 -0
- package/dist/pkce.js +28 -0
- package/dist/priority-queue.d.ts +36 -0
- package/dist/priority-queue.d.ts.map +1 -0
- package/dist/priority-queue.js +97 -0
- package/dist/process-utils.d.ts +20 -0
- package/dist/process-utils.d.ts.map +1 -0
- package/dist/process-utils.js +54 -0
- package/dist/query-guard.d.ts +34 -0
- package/dist/query-guard.d.ts.map +1 -0
- package/dist/query-guard.js +74 -0
- package/dist/retry.d.ts +60 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +89 -0
- package/dist/schemas.d.ts +6 -6
- package/dist/secrets.d.ts +44 -0
- package/dist/secrets.d.ts.map +1 -0
- package/dist/secrets.js +115 -0
- package/dist/semantic-types.d.ts +39 -0
- package/dist/semantic-types.d.ts.map +1 -0
- package/dist/semantic-types.js +49 -0
- package/dist/sequential.d.ts +21 -0
- package/dist/sequential.d.ts.map +1 -0
- package/dist/sequential.js +49 -0
- package/dist/signal.d.ts +29 -0
- package/dist/signal.d.ts.map +1 -0
- package/dist/signal.js +39 -0
- package/dist/sleep.d.ts +21 -0
- package/dist/sleep.d.ts.map +1 -0
- package/dist/sleep.js +58 -0
- package/dist/slow-ops.d.ts +41 -0
- package/dist/slow-ops.d.ts.map +1 -0
- package/dist/slow-ops.js +133 -0
- package/dist/store.d.ts +20 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +34 -0
- package/dist/stream.d.ts +29 -0
- package/dist/stream.d.ts.map +1 -0
- package/dist/stream.js +92 -0
- package/dist/string-utils.d.ts +46 -0
- package/dist/string-utils.d.ts.map +1 -0
- package/dist/string-utils.js +69 -0
- package/dist/strip-bom.d.ts +8 -0
- package/dist/strip-bom.d.ts.map +1 -0
- package/dist/strip-bom.js +10 -0
- package/dist/subprocess-env.d.ts +25 -0
- package/dist/subprocess-env.d.ts.map +1 -0
- package/dist/subprocess-env.js +55 -0
- package/dist/temp-file.d.ts +18 -0
- package/dist/temp-file.d.ts.map +1 -0
- package/dist/temp-file.js +26 -0
- package/dist/tool-contract.d.ts +85 -0
- package/dist/tool-contract.d.ts.map +1 -0
- package/dist/tool-contract.js +101 -0
- package/dist/tools/read.d.ts +2 -10
- package/dist/tools/read.d.ts.map +1 -1
- package/dist/tools/read.js +662 -537
- package/dist/tools/write.d.ts +3 -2
- package/dist/tools/write.d.ts.map +1 -1
- package/dist/tools/write.js +329 -177
- package/dist/uuid.d.ts +20 -0
- package/dist/uuid.d.ts.map +1 -0
- package/dist/uuid.js +28 -0
- package/dist/validation.d.ts +64 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +236 -0
- package/dist/with-resolvers.d.ts +12 -0
- package/dist/with-resolvers.d.ts.map +1 -0
- package/dist/with-resolvers.js +14 -0
- package/dist/xml-escape.d.ts +12 -0
- package/dist/xml-escape.d.ts.map +1 -0
- package/dist/xml-escape.js +15 -0
- package/package.json +1 -1
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed-size circular buffer — zero external dependencies.
|
|
3
|
+
*
|
|
4
|
+
* O(1) add, automatic eviction of oldest entries when capacity is exceeded.
|
|
5
|
+
* Useful for metrics windows, log tailing, and recent-activity buffers.
|
|
6
|
+
*
|
|
7
|
+
* Inspired by Claude Code's `src/utils/CircularBuffer.ts`.
|
|
8
|
+
*/
|
|
9
|
+
export class CircularBuffer {
|
|
10
|
+
capacity;
|
|
11
|
+
buffer;
|
|
12
|
+
head = 0;
|
|
13
|
+
_size = 0;
|
|
14
|
+
constructor(capacity) {
|
|
15
|
+
this.capacity = capacity;
|
|
16
|
+
if (capacity < 1) {
|
|
17
|
+
throw new RangeError("CircularBuffer capacity must be >= 1");
|
|
18
|
+
}
|
|
19
|
+
this.buffer = new Array(capacity);
|
|
20
|
+
}
|
|
21
|
+
/** Add an item, evicting the oldest if at capacity. */
|
|
22
|
+
add(item) {
|
|
23
|
+
this.buffer[this.head] = item;
|
|
24
|
+
this.head = (this.head + 1) % this.capacity;
|
|
25
|
+
if (this._size < this.capacity) {
|
|
26
|
+
this._size++;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Add multiple items. */
|
|
30
|
+
addAll(items) {
|
|
31
|
+
for (const item of items) {
|
|
32
|
+
this.add(item);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** Get the most recent `count` items in insertion order (oldest first). */
|
|
36
|
+
getRecent(count) {
|
|
37
|
+
const n = Math.min(count ?? this._size, this._size);
|
|
38
|
+
if (n === 0)
|
|
39
|
+
return [];
|
|
40
|
+
const result = [];
|
|
41
|
+
// Start from (head - n) wrapped around
|
|
42
|
+
let start = (this.head - n + this.capacity) % this.capacity;
|
|
43
|
+
for (let i = 0; i < n; i++) {
|
|
44
|
+
result.push(this.buffer[(start + i) % this.capacity]);
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
/** Get all items in insertion order (oldest first). */
|
|
49
|
+
toArray() {
|
|
50
|
+
return this.getRecent(this._size);
|
|
51
|
+
}
|
|
52
|
+
/** Remove all items. */
|
|
53
|
+
clear() {
|
|
54
|
+
this.head = 0;
|
|
55
|
+
this._size = 0;
|
|
56
|
+
}
|
|
57
|
+
/** Current number of items (0 to capacity). */
|
|
58
|
+
get length() {
|
|
59
|
+
return this._size;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global cleanup function registry — zero external dependencies.
|
|
3
|
+
*
|
|
4
|
+
* Any module can register its cleanup handler without importing the shutdown
|
|
5
|
+
* controller. Call `runCleanupFunctions()` during graceful shutdown.
|
|
6
|
+
*
|
|
7
|
+
* Inspired by Claude Code's `src/utils/cleanupRegistry.ts`.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Register a cleanup function. Returns an unregister function.
|
|
11
|
+
*/
|
|
12
|
+
export declare function registerCleanup(fn: () => Promise<void>): () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Run all registered cleanup functions in parallel.
|
|
15
|
+
* Errors in individual functions don't block others.
|
|
16
|
+
* Clears the registry after execution.
|
|
17
|
+
*/
|
|
18
|
+
export declare function runCleanupFunctions(): Promise<void>;
|
|
19
|
+
/**
|
|
20
|
+
* Reset the registry (for testing only).
|
|
21
|
+
*/
|
|
22
|
+
export declare function _resetRegistryForTesting(): void;
|
|
23
|
+
//# sourceMappingURL=cleanup-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cleanup-registry.d.ts","sourceRoot":"","sources":["../src/cleanup-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAKnE;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAIzD;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global cleanup function registry — zero external dependencies.
|
|
3
|
+
*
|
|
4
|
+
* Any module can register its cleanup handler without importing the shutdown
|
|
5
|
+
* controller. Call `runCleanupFunctions()` during graceful shutdown.
|
|
6
|
+
*
|
|
7
|
+
* Inspired by Claude Code's `src/utils/cleanupRegistry.ts`.
|
|
8
|
+
*/
|
|
9
|
+
const registry = new Set();
|
|
10
|
+
/**
|
|
11
|
+
* Register a cleanup function. Returns an unregister function.
|
|
12
|
+
*/
|
|
13
|
+
export function registerCleanup(fn) {
|
|
14
|
+
registry.add(fn);
|
|
15
|
+
return () => {
|
|
16
|
+
registry.delete(fn);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Run all registered cleanup functions in parallel.
|
|
21
|
+
* Errors in individual functions don't block others.
|
|
22
|
+
* Clears the registry after execution.
|
|
23
|
+
*/
|
|
24
|
+
export async function runCleanupFunctions() {
|
|
25
|
+
const fns = [...registry];
|
|
26
|
+
registry.clear();
|
|
27
|
+
await Promise.allSettled(fns.map((fn) => fn()));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Reset the registry (for testing only).
|
|
31
|
+
*/
|
|
32
|
+
export function _resetRegistryForTesting() {
|
|
33
|
+
registry.clear();
|
|
34
|
+
}
|
package/dist/client.d.ts
CHANGED
|
@@ -188,6 +188,8 @@ export declare class OkaClient {
|
|
|
188
188
|
private readonly searchContext;
|
|
189
189
|
/** Reverse map: short ID prefix → full UUID */
|
|
190
190
|
private readonly idLookup;
|
|
191
|
+
/** Memoized search — deduplicates concurrent identical queries (30s TTL). */
|
|
192
|
+
private readonly cachedGet;
|
|
191
193
|
constructor(config?: OkaClientConfig);
|
|
192
194
|
updateApiKey(key: string): void;
|
|
193
195
|
ingest(event: IngestEvent): Promise<void>;
|
|
@@ -247,5 +249,7 @@ export declare class OkaClient {
|
|
|
247
249
|
private buildHeaders;
|
|
248
250
|
private get;
|
|
249
251
|
private post;
|
|
252
|
+
private rawGet;
|
|
253
|
+
private rawPost;
|
|
250
254
|
}
|
|
251
255
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/client.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { EventBuffer } from "./buffer.js";
|
|
2
2
|
import { McpTokenManager } from "./auth.js";
|
|
3
|
+
import { AuthenticationError, NetworkError } from "./errors.js";
|
|
4
|
+
import { withRetry } from "./retry.js";
|
|
5
|
+
import { memoizeAsync } from "./memo.js";
|
|
3
6
|
/**
|
|
4
7
|
* Unified HTTP client for Oka Reason API.
|
|
5
8
|
*
|
|
@@ -26,6 +29,8 @@ export class OkaClient {
|
|
|
26
29
|
searchContext = new Map();
|
|
27
30
|
/** Reverse map: short ID prefix → full UUID */
|
|
28
31
|
idLookup = new Map();
|
|
32
|
+
/** Memoized search — deduplicates concurrent identical queries (30s TTL). */
|
|
33
|
+
cachedGet;
|
|
29
34
|
constructor(config) {
|
|
30
35
|
this.apiUrl = (config?.apiUrl ||
|
|
31
36
|
process.env["OKA_API_URL"] ||
|
|
@@ -37,6 +42,11 @@ export class OkaClient {
|
|
|
37
42
|
this.buffer = new EventBuffer(100);
|
|
38
43
|
this.timeout = 15_000;
|
|
39
44
|
this.tokenManager = new McpTokenManager();
|
|
45
|
+
this.cachedGet = memoizeAsync((path) => this.get(path), {
|
|
46
|
+
ttlMs: 30_000,
|
|
47
|
+
keyFn: (path) => path,
|
|
48
|
+
maxEntries: 100,
|
|
49
|
+
});
|
|
40
50
|
}
|
|
41
51
|
updateApiKey(key) {
|
|
42
52
|
this.apiKey = key;
|
|
@@ -89,7 +99,7 @@ export class OkaClient {
|
|
|
89
99
|
params.set("include_events", String(options.include_events));
|
|
90
100
|
if (options?.visibility)
|
|
91
101
|
params.set("visibility", options.visibility);
|
|
92
|
-
return this.
|
|
102
|
+
return this.cachedGet(`/api/learnings/context/${encodeURIComponent(topic)}?${params}`).catch(() => ({ topic, learnings: [], total_matched: 0 }));
|
|
93
103
|
}
|
|
94
104
|
// ─── Event queries ──────────────────────────────────────────────
|
|
95
105
|
async query(params) {
|
|
@@ -189,7 +199,7 @@ export class OkaClient {
|
|
|
189
199
|
params.set("min_confidence", String(options.min_confidence));
|
|
190
200
|
if (options?.visibility)
|
|
191
201
|
params.set("visibility", options.visibility);
|
|
192
|
-
return this.
|
|
202
|
+
return this.cachedGet(`/api/learnings/semantic/${encodeURIComponent(query)}?${params}`).catch(() => ({ query, results: [], total: 0 }));
|
|
193
203
|
}
|
|
194
204
|
// ─── Hybrid search (unified pipeline) ───────────────────────────
|
|
195
205
|
/**
|
|
@@ -219,7 +229,7 @@ export class OkaClient {
|
|
|
219
229
|
params.set("rerank", "true");
|
|
220
230
|
if (options?.mode)
|
|
221
231
|
params.set("mode", options.mode);
|
|
222
|
-
const data = await this.
|
|
232
|
+
const data = await this.cachedGet(`/api/learnings/query/${encodeURIComponent(query)}?${params}`).catch(() => ({
|
|
223
233
|
query,
|
|
224
234
|
results: [],
|
|
225
235
|
total_candidates: 0,
|
|
@@ -318,6 +328,14 @@ export class OkaClient {
|
|
|
318
328
|
return headers;
|
|
319
329
|
}
|
|
320
330
|
async get(path) {
|
|
331
|
+
return withRetry(() => this.rawGet(path), { source: "foreground" });
|
|
332
|
+
}
|
|
333
|
+
async post(path, body, timeout) {
|
|
334
|
+
return withRetry(() => this.rawPost(path, body, timeout), {
|
|
335
|
+
source: "foreground",
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
async rawGet(path) {
|
|
321
339
|
const headers = await this.authHeaders();
|
|
322
340
|
const controller = new AbortController();
|
|
323
341
|
const timer = setTimeout(() => controller.abort(), this.timeout);
|
|
@@ -328,9 +346,12 @@ export class OkaClient {
|
|
|
328
346
|
signal: controller.signal,
|
|
329
347
|
});
|
|
330
348
|
if (!response.ok) {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
349
|
+
if (response.status === 401) {
|
|
350
|
+
throw new AuthenticationError("Authentication failed — run mcp__oka__login to re-authenticate");
|
|
351
|
+
}
|
|
352
|
+
throw new NetworkError(`HTTP ${response.status}`, {
|
|
353
|
+
statusCode: response.status,
|
|
354
|
+
});
|
|
334
355
|
}
|
|
335
356
|
return response.json();
|
|
336
357
|
}
|
|
@@ -338,7 +359,7 @@ export class OkaClient {
|
|
|
338
359
|
clearTimeout(timer);
|
|
339
360
|
}
|
|
340
361
|
}
|
|
341
|
-
async
|
|
362
|
+
async rawPost(path, body, timeout) {
|
|
342
363
|
const headers = await this.authHeaders();
|
|
343
364
|
const controller = new AbortController();
|
|
344
365
|
const timer = setTimeout(() => controller.abort(), timeout ?? this.timeout);
|
|
@@ -351,10 +372,11 @@ export class OkaClient {
|
|
|
351
372
|
});
|
|
352
373
|
if (!response.ok) {
|
|
353
374
|
if (response.status === 401) {
|
|
354
|
-
throw new
|
|
375
|
+
throw new AuthenticationError("Authentication failed — run mcp__oka__login to re-authenticate");
|
|
355
376
|
}
|
|
356
|
-
|
|
357
|
-
|
|
377
|
+
throw new NetworkError(`HTTP ${response.status}`, {
|
|
378
|
+
statusCode: response.status,
|
|
379
|
+
});
|
|
358
380
|
}
|
|
359
381
|
return response.json();
|
|
360
382
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compose multiple AbortSignals + optional timeout into a single signal.
|
|
3
|
+
*
|
|
4
|
+
* Uses setTimeout + clearTimeout instead of AbortSignal.timeout() to avoid
|
|
5
|
+
* the Bun memory issue where AbortSignal.timeout timers accumulate (~2.4KB
|
|
6
|
+
* per call) until they fire.
|
|
7
|
+
*
|
|
8
|
+
* Inspired by Claude Code's `src/utils/combinedAbortSignal.ts`.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Create a combined AbortSignal that aborts when:
|
|
12
|
+
* - The primary `signal` aborts, OR
|
|
13
|
+
* - The optional `signalB` aborts, OR
|
|
14
|
+
* - The optional `timeoutMs` elapses.
|
|
15
|
+
*
|
|
16
|
+
* Returns both the signal and a cleanup function to remove listeners / clear timer.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createCombinedAbortSignal(signal: AbortSignal | undefined, opts?: {
|
|
19
|
+
signalB?: AbortSignal;
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
}): {
|
|
22
|
+
signal: AbortSignal;
|
|
23
|
+
cleanup: () => void;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=combined-abort-signal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combined-abort-signal.d.ts","sourceRoot":"","sources":["../src/combined-abort-signal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,IAAI,CAAA;CAAE,CA+B9C"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compose multiple AbortSignals + optional timeout into a single signal.
|
|
3
|
+
*
|
|
4
|
+
* Uses setTimeout + clearTimeout instead of AbortSignal.timeout() to avoid
|
|
5
|
+
* the Bun memory issue where AbortSignal.timeout timers accumulate (~2.4KB
|
|
6
|
+
* per call) until they fire.
|
|
7
|
+
*
|
|
8
|
+
* Inspired by Claude Code's `src/utils/combinedAbortSignal.ts`.
|
|
9
|
+
*/
|
|
10
|
+
import { createAbortController } from "./abort-controller.js";
|
|
11
|
+
/**
|
|
12
|
+
* Create a combined AbortSignal that aborts when:
|
|
13
|
+
* - The primary `signal` aborts, OR
|
|
14
|
+
* - The optional `signalB` aborts, OR
|
|
15
|
+
* - The optional `timeoutMs` elapses.
|
|
16
|
+
*
|
|
17
|
+
* Returns both the signal and a cleanup function to remove listeners / clear timer.
|
|
18
|
+
*/
|
|
19
|
+
export function createCombinedAbortSignal(signal, opts) {
|
|
20
|
+
const { signalB, timeoutMs } = opts ?? {};
|
|
21
|
+
const combined = createAbortController();
|
|
22
|
+
if (signal?.aborted || signalB?.aborted) {
|
|
23
|
+
combined.abort();
|
|
24
|
+
return { signal: combined.signal, cleanup: () => { } };
|
|
25
|
+
}
|
|
26
|
+
let timer;
|
|
27
|
+
const abortCombined = () => {
|
|
28
|
+
if (timer !== undefined)
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
combined.abort();
|
|
31
|
+
};
|
|
32
|
+
if (timeoutMs !== undefined) {
|
|
33
|
+
timer = setTimeout(abortCombined, timeoutMs);
|
|
34
|
+
if (typeof timer === "object" && "unref" in timer) {
|
|
35
|
+
timer.unref();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
signal?.addEventListener("abort", abortCombined);
|
|
39
|
+
signalB?.addEventListener("abort", abortCombined);
|
|
40
|
+
const cleanup = () => {
|
|
41
|
+
if (timer !== undefined)
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
signal?.removeEventListener("abort", abortCombined);
|
|
44
|
+
signalB?.removeEventListener("abort", abortCombined);
|
|
45
|
+
};
|
|
46
|
+
return { signal: combined.signal, cleanup };
|
|
47
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler lease lock for cron task files.
|
|
3
|
+
*
|
|
4
|
+
* When multiple processes share the same task directory, only one should
|
|
5
|
+
* drive the cron scheduler. Uses O_EXCL atomic create, PID liveness probe,
|
|
6
|
+
* and stale-lock recovery.
|
|
7
|
+
*/
|
|
8
|
+
export type SchedulerLockOptions = {
|
|
9
|
+
/** Directory containing the lock file. */
|
|
10
|
+
dir: string;
|
|
11
|
+
/** Stable owner identity (e.g. session ID or random UUID). */
|
|
12
|
+
ownerId: string;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Try to acquire the scheduler lock.
|
|
16
|
+
*
|
|
17
|
+
* Returns true on success, false if another live process holds it.
|
|
18
|
+
*
|
|
19
|
+
* Uses O_EXCL for atomic test-and-set. If the file exists:
|
|
20
|
+
* - Already ours → true (idempotent)
|
|
21
|
+
* - Another live PID → false
|
|
22
|
+
* - Stale (PID dead / corrupt) → unlink and retry once
|
|
23
|
+
*/
|
|
24
|
+
export declare function tryAcquireSchedulerLock(opts: SchedulerLockOptions): Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Release the scheduler lock if we own it.
|
|
27
|
+
*/
|
|
28
|
+
export declare function releaseSchedulerLock(opts: SchedulerLockOptions): Promise<void>;
|
|
29
|
+
//# sourceMappingURL=cron-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-lock.d.ts","sourceRoot":"","sources":["../src/cron-lock.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAaH,MAAM,MAAM,oBAAoB,GAAG;IACjC,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAuEF;;;;;;;;;GASG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,OAAO,CAAC,CA8BlB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,oBAAoB,GACzB,OAAO,CAAC,IAAI,CAAC,CASf"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scheduler lease lock for cron task files.
|
|
3
|
+
*
|
|
4
|
+
* When multiple processes share the same task directory, only one should
|
|
5
|
+
* drive the cron scheduler. Uses O_EXCL atomic create, PID liveness probe,
|
|
6
|
+
* and stale-lock recovery.
|
|
7
|
+
*/
|
|
8
|
+
import { mkdir, readFile, unlink, writeFile } from "fs/promises";
|
|
9
|
+
import { dirname, join } from "path";
|
|
10
|
+
const LOCK_FILE_NAME = "scheduled_tasks.lock";
|
|
11
|
+
function getLockPath(dir) {
|
|
12
|
+
return join(dir, LOCK_FILE_NAME);
|
|
13
|
+
}
|
|
14
|
+
function isProcessRunning(pid) {
|
|
15
|
+
try {
|
|
16
|
+
process.kill(pid, 0);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function getErrnoCode(e) {
|
|
24
|
+
if (e && typeof e === "object" && "code" in e) {
|
|
25
|
+
return e.code;
|
|
26
|
+
}
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
async function readLock(dir) {
|
|
30
|
+
let raw;
|
|
31
|
+
try {
|
|
32
|
+
raw = await readFile(getLockPath(dir), "utf8");
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const parsed = JSON.parse(raw);
|
|
39
|
+
if (parsed &&
|
|
40
|
+
typeof parsed.ownerId === "string" &&
|
|
41
|
+
typeof parsed.pid === "number" &&
|
|
42
|
+
typeof parsed.acquiredAt === "number") {
|
|
43
|
+
return parsed;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// Corrupt file
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
async function tryCreateExclusive(lock, dir) {
|
|
52
|
+
const path = getLockPath(dir);
|
|
53
|
+
const body = JSON.stringify(lock);
|
|
54
|
+
try {
|
|
55
|
+
await writeFile(path, body, { flag: "wx" });
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
const code = getErrnoCode(e);
|
|
60
|
+
if (code === "EEXIST")
|
|
61
|
+
return false;
|
|
62
|
+
if (code === "ENOENT") {
|
|
63
|
+
await mkdir(dirname(path), { recursive: true });
|
|
64
|
+
try {
|
|
65
|
+
await writeFile(path, body, { flag: "wx" });
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch (retryErr) {
|
|
69
|
+
if (getErrnoCode(retryErr) === "EEXIST")
|
|
70
|
+
return false;
|
|
71
|
+
throw retryErr;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
throw e;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Try to acquire the scheduler lock.
|
|
79
|
+
*
|
|
80
|
+
* Returns true on success, false if another live process holds it.
|
|
81
|
+
*
|
|
82
|
+
* Uses O_EXCL for atomic test-and-set. If the file exists:
|
|
83
|
+
* - Already ours → true (idempotent)
|
|
84
|
+
* - Another live PID → false
|
|
85
|
+
* - Stale (PID dead / corrupt) → unlink and retry once
|
|
86
|
+
*/
|
|
87
|
+
export async function tryAcquireSchedulerLock(opts) {
|
|
88
|
+
const { dir, ownerId } = opts;
|
|
89
|
+
const lock = {
|
|
90
|
+
ownerId,
|
|
91
|
+
pid: process.pid,
|
|
92
|
+
acquiredAt: Date.now(),
|
|
93
|
+
};
|
|
94
|
+
if (await tryCreateExclusive(lock, dir)) {
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
const existing = await readLock(dir);
|
|
98
|
+
// Already ours (idempotent). Update PID if changed (e.g. after resume).
|
|
99
|
+
if (existing?.ownerId === ownerId) {
|
|
100
|
+
if (existing.pid !== process.pid) {
|
|
101
|
+
await writeFile(getLockPath(dir), JSON.stringify(lock));
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
// Another live process holds it.
|
|
106
|
+
if (existing && isProcessRunning(existing.pid)) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
// Stale — unlink and retry exclusive create once.
|
|
110
|
+
await unlink(getLockPath(dir)).catch(() => { });
|
|
111
|
+
return tryCreateExclusive(lock, dir);
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Release the scheduler lock if we own it.
|
|
115
|
+
*/
|
|
116
|
+
export async function releaseSchedulerLock(opts) {
|
|
117
|
+
const { dir, ownerId } = opts;
|
|
118
|
+
const existing = await readLock(dir);
|
|
119
|
+
if (!existing || existing.ownerId !== ownerId)
|
|
120
|
+
return;
|
|
121
|
+
try {
|
|
122
|
+
await unlink(getLockPath(dir));
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// Already gone.
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polling-based cron scheduler.
|
|
3
|
+
*
|
|
4
|
+
* Simplified extraction from CC's cronScheduler — strips chokidar file watching
|
|
5
|
+
* (uses polling), bootstrap state, analytics, and session tasks. Designed for
|
|
6
|
+
* standalone use with file-backed cron tasks.
|
|
7
|
+
*/
|
|
8
|
+
import { type CronJitterConfig, type CronTask } from "./cron-tasks.js";
|
|
9
|
+
/**
|
|
10
|
+
* True when a recurring task was created more than maxAgeMs ago.
|
|
11
|
+
* Permanent tasks never age. maxAgeMs === 0 means unlimited.
|
|
12
|
+
*/
|
|
13
|
+
export declare function isRecurringTaskAged(t: CronTask, nowMs: number, maxAgeMs: number): boolean;
|
|
14
|
+
export type CronSchedulerOptions = {
|
|
15
|
+
/** Directory containing scheduled_tasks.json. */
|
|
16
|
+
dir: string;
|
|
17
|
+
/** Stable owner identity for the scheduler lock. */
|
|
18
|
+
ownerId: string;
|
|
19
|
+
/** Called when a task fires. */
|
|
20
|
+
onFire: (prompt: string) => void;
|
|
21
|
+
/** Called with the full CronTask on fire (bypasses onFire). */
|
|
22
|
+
onFireTask?: (task: CronTask) => void;
|
|
23
|
+
/** Called with missed one-shot tasks on initial load. */
|
|
24
|
+
onMissed?: (tasks: CronTask[]) => void;
|
|
25
|
+
/** Per-task gate: tasks returning false are invisible to this scheduler. */
|
|
26
|
+
filter?: (t: CronTask) => boolean;
|
|
27
|
+
/** Jitter config (defaults to DEFAULT_CRON_JITTER_CONFIG). */
|
|
28
|
+
jitterConfig?: CronJitterConfig;
|
|
29
|
+
/** Killswitch: polled each tick. When true, check() bails. */
|
|
30
|
+
isKilled?: () => boolean;
|
|
31
|
+
/** Check interval in ms (default: 1000). */
|
|
32
|
+
checkIntervalMs?: number;
|
|
33
|
+
};
|
|
34
|
+
export type CronScheduler = {
|
|
35
|
+
start: () => void;
|
|
36
|
+
stop: () => void;
|
|
37
|
+
/** Epoch ms of the soonest scheduled fire, or null if nothing pending. */
|
|
38
|
+
getNextFireTime: () => number | null;
|
|
39
|
+
};
|
|
40
|
+
export declare function createCronScheduler(options: CronSchedulerOptions): CronScheduler;
|
|
41
|
+
//# sourceMappingURL=cron-scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron-scheduler.d.ts","sourceRoot":"","sources":["../src/cron-scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,QAAQ,EAUd,MAAM,iBAAiB,CAAC;AAMzB;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,CAAC,EAAE,QAAQ,EACX,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,GACf,OAAO,CAKT;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,gCAAgC;IAChC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;IACtC,yDAAyD;IACzD,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,IAAI,CAAC;IACvC,4EAA4E;IAC5E,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,KAAK,OAAO,CAAC;IAClC,8DAA8D;IAC9D,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC;IACzB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,0EAA0E;IAC1E,eAAe,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACtC,CAAC;AAEF,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,GAC5B,aAAa,CAqMf"}
|