@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.
Files changed (158) hide show
  1. package/dist/abort-controller.d.ts +19 -0
  2. package/dist/abort-controller.d.ts.map +1 -0
  3. package/dist/abort-controller.js +53 -0
  4. package/dist/activity-tracker.d.ts +48 -0
  5. package/dist/activity-tracker.d.ts.map +1 -0
  6. package/dist/activity-tracker.js +80 -0
  7. package/dist/analytics.d.ts +49 -0
  8. package/dist/analytics.d.ts.map +1 -0
  9. package/dist/analytics.js +88 -0
  10. package/dist/array.d.ts +12 -0
  11. package/dist/array.d.ts.map +1 -0
  12. package/dist/array.js +20 -0
  13. package/dist/async-context.d.ts +20 -0
  14. package/dist/async-context.d.ts.map +1 -0
  15. package/dist/async-context.js +25 -0
  16. package/dist/binary-check.d.ts +16 -0
  17. package/dist/binary-check.d.ts.map +1 -0
  18. package/dist/binary-check.js +43 -0
  19. package/dist/buffered-writer.d.ts +30 -0
  20. package/dist/buffered-writer.d.ts.map +1 -0
  21. package/dist/buffered-writer.js +87 -0
  22. package/dist/circular-buffer.d.ts +28 -0
  23. package/dist/circular-buffer.d.ts.map +1 -0
  24. package/dist/circular-buffer.js +61 -0
  25. package/dist/cleanup-registry.d.ts +23 -0
  26. package/dist/cleanup-registry.d.ts.map +1 -0
  27. package/dist/cleanup-registry.js +34 -0
  28. package/dist/client.d.ts +4 -0
  29. package/dist/client.d.ts.map +1 -1
  30. package/dist/client.js +32 -10
  31. package/dist/combined-abort-signal.d.ts +25 -0
  32. package/dist/combined-abort-signal.d.ts.map +1 -0
  33. package/dist/combined-abort-signal.js +47 -0
  34. package/dist/cron-lock.d.ts +29 -0
  35. package/dist/cron-lock.d.ts.map +1 -0
  36. package/dist/cron-lock.js +127 -0
  37. package/dist/cron-scheduler.d.ts +41 -0
  38. package/dist/cron-scheduler.d.ts.map +1 -0
  39. package/dist/cron-scheduler.js +189 -0
  40. package/dist/cron-tasks.d.ts +86 -0
  41. package/dist/cron-tasks.d.ts.map +1 -0
  42. package/dist/cron-tasks.js +205 -0
  43. package/dist/cron.d.ts +35 -0
  44. package/dist/cron.d.ts.map +1 -0
  45. package/dist/cron.js +215 -0
  46. package/dist/env.d.ts +26 -0
  47. package/dist/env.d.ts.map +1 -0
  48. package/dist/env.js +50 -0
  49. package/dist/errors.d.ts +99 -0
  50. package/dist/errors.d.ts.map +1 -0
  51. package/dist/errors.js +214 -0
  52. package/dist/format.d.ts +21 -0
  53. package/dist/format.d.ts.map +1 -0
  54. package/dist/format.js +48 -0
  55. package/dist/fps-tracker.d.ts +22 -0
  56. package/dist/fps-tracker.d.ts.map +1 -0
  57. package/dist/fps-tracker.js +44 -0
  58. package/dist/graceful-shutdown.d.ts +35 -0
  59. package/dist/graceful-shutdown.d.ts.map +1 -0
  60. package/dist/graceful-shutdown.js +89 -0
  61. package/dist/hash.d.ts +21 -0
  62. package/dist/hash.d.ts.map +1 -0
  63. package/dist/hash.js +31 -0
  64. package/dist/heap-diagnostics.d.ts +68 -0
  65. package/dist/heap-diagnostics.d.ts.map +1 -0
  66. package/dist/heap-diagnostics.js +110 -0
  67. package/dist/idle-timeout.d.ts +21 -0
  68. package/dist/idle-timeout.d.ts.map +1 -0
  69. package/dist/idle-timeout.js +42 -0
  70. package/dist/index.d.ts +2 -1
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +5 -0
  73. package/dist/intl.d.ts +18 -0
  74. package/dist/intl.d.ts.map +1 -0
  75. package/dist/intl.js +75 -0
  76. package/dist/jsonl.d.ts +16 -0
  77. package/dist/jsonl.d.ts.map +1 -0
  78. package/dist/jsonl.js +60 -0
  79. package/dist/lazy-schema.d.ts +6 -0
  80. package/dist/lazy-schema.d.ts.map +1 -0
  81. package/dist/lazy-schema.js +8 -0
  82. package/dist/memo.d.ts +64 -0
  83. package/dist/memo.d.ts.map +1 -0
  84. package/dist/memo.js +162 -0
  85. package/dist/pkce.d.ts +13 -0
  86. package/dist/pkce.d.ts.map +1 -0
  87. package/dist/pkce.js +28 -0
  88. package/dist/priority-queue.d.ts +36 -0
  89. package/dist/priority-queue.d.ts.map +1 -0
  90. package/dist/priority-queue.js +97 -0
  91. package/dist/process-utils.d.ts +20 -0
  92. package/dist/process-utils.d.ts.map +1 -0
  93. package/dist/process-utils.js +54 -0
  94. package/dist/query-guard.d.ts +34 -0
  95. package/dist/query-guard.d.ts.map +1 -0
  96. package/dist/query-guard.js +74 -0
  97. package/dist/retry.d.ts +60 -0
  98. package/dist/retry.d.ts.map +1 -0
  99. package/dist/retry.js +89 -0
  100. package/dist/schemas.d.ts +6 -6
  101. package/dist/secrets.d.ts +44 -0
  102. package/dist/secrets.d.ts.map +1 -0
  103. package/dist/secrets.js +115 -0
  104. package/dist/semantic-types.d.ts +39 -0
  105. package/dist/semantic-types.d.ts.map +1 -0
  106. package/dist/semantic-types.js +49 -0
  107. package/dist/sequential.d.ts +21 -0
  108. package/dist/sequential.d.ts.map +1 -0
  109. package/dist/sequential.js +49 -0
  110. package/dist/signal.d.ts +29 -0
  111. package/dist/signal.d.ts.map +1 -0
  112. package/dist/signal.js +39 -0
  113. package/dist/sleep.d.ts +21 -0
  114. package/dist/sleep.d.ts.map +1 -0
  115. package/dist/sleep.js +58 -0
  116. package/dist/slow-ops.d.ts +41 -0
  117. package/dist/slow-ops.d.ts.map +1 -0
  118. package/dist/slow-ops.js +133 -0
  119. package/dist/store.d.ts +20 -0
  120. package/dist/store.d.ts.map +1 -0
  121. package/dist/store.js +34 -0
  122. package/dist/stream.d.ts +29 -0
  123. package/dist/stream.d.ts.map +1 -0
  124. package/dist/stream.js +92 -0
  125. package/dist/string-utils.d.ts +46 -0
  126. package/dist/string-utils.d.ts.map +1 -0
  127. package/dist/string-utils.js +69 -0
  128. package/dist/strip-bom.d.ts +8 -0
  129. package/dist/strip-bom.d.ts.map +1 -0
  130. package/dist/strip-bom.js +10 -0
  131. package/dist/subprocess-env.d.ts +25 -0
  132. package/dist/subprocess-env.d.ts.map +1 -0
  133. package/dist/subprocess-env.js +55 -0
  134. package/dist/temp-file.d.ts +18 -0
  135. package/dist/temp-file.d.ts.map +1 -0
  136. package/dist/temp-file.js +26 -0
  137. package/dist/tool-contract.d.ts +85 -0
  138. package/dist/tool-contract.d.ts.map +1 -0
  139. package/dist/tool-contract.js +101 -0
  140. package/dist/tools/read.d.ts +2 -10
  141. package/dist/tools/read.d.ts.map +1 -1
  142. package/dist/tools/read.js +662 -537
  143. package/dist/tools/write.d.ts +3 -2
  144. package/dist/tools/write.d.ts.map +1 -1
  145. package/dist/tools/write.js +329 -177
  146. package/dist/uuid.d.ts +20 -0
  147. package/dist/uuid.d.ts.map +1 -0
  148. package/dist/uuid.js +28 -0
  149. package/dist/validation.d.ts +64 -0
  150. package/dist/validation.d.ts.map +1 -0
  151. package/dist/validation.js +236 -0
  152. package/dist/with-resolvers.d.ts +12 -0
  153. package/dist/with-resolvers.d.ts.map +1 -0
  154. package/dist/with-resolvers.js +14 -0
  155. package/dist/xml-escape.d.ts +12 -0
  156. package/dist/xml-escape.d.ts.map +1 -0
  157. package/dist/xml-escape.js +15 -0
  158. 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
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
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.get(`/api/learnings/context/${encodeURIComponent(topic)}?${params}`).catch(() => ({ topic, learnings: [], total_matched: 0 }));
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.get(`/api/learnings/semantic/${encodeURIComponent(query)}?${params}`).catch(() => ({ query, results: [], total: 0 }));
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.get(`/api/learnings/query/${encodeURIComponent(query)}?${params}`).catch(() => ({
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
- throw new Error(response.status === 401
332
- ? "HTTP 401: authentication failed — run mcp__oka__login to re-authenticate"
333
- : `HTTP ${response.status}`);
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 post(path, body, timeout) {
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 Error("HTTP 401: authentication failed — run mcp__oka__login to re-authenticate");
375
+ throw new AuthenticationError("Authentication failed — run mcp__oka__login to re-authenticate");
355
376
  }
356
- const text = await response.text().catch(() => "");
357
- throw new Error(`HTTP ${response.status}: ${text}`);
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"}