aicodeman 0.2.8
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/LICENSE +21 -0
- package/README.md +403 -0
- package/dist/ai-checker-base.d.ts +175 -0
- package/dist/ai-checker-base.d.ts.map +1 -0
- package/dist/ai-checker-base.js +424 -0
- package/dist/ai-checker-base.js.map +1 -0
- package/dist/ai-idle-checker.d.ts +53 -0
- package/dist/ai-idle-checker.d.ts.map +1 -0
- package/dist/ai-idle-checker.js +141 -0
- package/dist/ai-idle-checker.js.map +1 -0
- package/dist/ai-plan-checker.d.ts +52 -0
- package/dist/ai-plan-checker.d.ts.map +1 -0
- package/dist/ai-plan-checker.js +103 -0
- package/dist/ai-plan-checker.js.map +1 -0
- package/dist/bash-tool-parser.d.ts +191 -0
- package/dist/bash-tool-parser.d.ts.map +1 -0
- package/dist/bash-tool-parser.js +598 -0
- package/dist/bash-tool-parser.js.map +1 -0
- package/dist/cli.d.ts +12 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +460 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/buffer-limits.d.ts +59 -0
- package/dist/config/buffer-limits.d.ts.map +1 -0
- package/dist/config/buffer-limits.js +74 -0
- package/dist/config/buffer-limits.js.map +1 -0
- package/dist/config/map-limits.d.ts +40 -0
- package/dist/config/map-limits.d.ts.map +1 -0
- package/dist/config/map-limits.js +52 -0
- package/dist/config/map-limits.js.map +1 -0
- package/dist/file-stream-manager.d.ts +148 -0
- package/dist/file-stream-manager.d.ts.map +1 -0
- package/dist/file-stream-manager.js +351 -0
- package/dist/file-stream-manager.js.map +1 -0
- package/dist/hooks-config.d.ts +31 -0
- package/dist/hooks-config.d.ts.map +1 -0
- package/dist/hooks-config.js +115 -0
- package/dist/hooks-config.js.map +1 -0
- package/dist/image-watcher.d.ts +86 -0
- package/dist/image-watcher.d.ts.map +1 -0
- package/dist/image-watcher.js +275 -0
- package/dist/image-watcher.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/mux-factory.d.ts +13 -0
- package/dist/mux-factory.d.ts.map +1 -0
- package/dist/mux-factory.js +19 -0
- package/dist/mux-factory.js.map +1 -0
- package/dist/mux-interface.d.ts +145 -0
- package/dist/mux-interface.d.ts.map +1 -0
- package/dist/mux-interface.js +9 -0
- package/dist/mux-interface.js.map +1 -0
- package/dist/plan-orchestrator.d.ts +123 -0
- package/dist/plan-orchestrator.d.ts.map +1 -0
- package/dist/plan-orchestrator.js +500 -0
- package/dist/plan-orchestrator.js.map +1 -0
- package/dist/prompts/index.d.ts +9 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +9 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/planner.d.ts +14 -0
- package/dist/prompts/planner.d.ts.map +1 -0
- package/dist/prompts/planner.js +83 -0
- package/dist/prompts/planner.js.map +1 -0
- package/dist/prompts/research-agent.d.ts +10 -0
- package/dist/prompts/research-agent.d.ts.map +1 -0
- package/dist/prompts/research-agent.js +143 -0
- package/dist/prompts/research-agent.js.map +1 -0
- package/dist/push-store.d.ts +41 -0
- package/dist/push-store.d.ts.map +1 -0
- package/dist/push-store.js +168 -0
- package/dist/push-store.js.map +1 -0
- package/dist/ralph-config.d.ts +67 -0
- package/dist/ralph-config.d.ts.map +1 -0
- package/dist/ralph-config.js +134 -0
- package/dist/ralph-config.js.map +1 -0
- package/dist/ralph-loop.d.ts +124 -0
- package/dist/ralph-loop.d.ts.map +1 -0
- package/dist/ralph-loop.js +418 -0
- package/dist/ralph-loop.js.map +1 -0
- package/dist/ralph-tracker.d.ts +1081 -0
- package/dist/ralph-tracker.d.ts.map +1 -0
- package/dist/ralph-tracker.js +3343 -0
- package/dist/ralph-tracker.js.map +1 -0
- package/dist/respawn-controller.d.ts +1182 -0
- package/dist/respawn-controller.d.ts.map +1 -0
- package/dist/respawn-controller.js +2754 -0
- package/dist/respawn-controller.js.map +1 -0
- package/dist/run-summary.d.ts +123 -0
- package/dist/run-summary.d.ts.map +1 -0
- package/dist/run-summary.js +325 -0
- package/dist/run-summary.js.map +1 -0
- package/dist/session-lifecycle-log.d.ts +36 -0
- package/dist/session-lifecycle-log.d.ts.map +1 -0
- package/dist/session-lifecycle-log.js +101 -0
- package/dist/session-lifecycle-log.js.map +1 -0
- package/dist/session-manager.d.ts +97 -0
- package/dist/session-manager.d.ts.map +1 -0
- package/dist/session-manager.js +224 -0
- package/dist/session-manager.js.map +1 -0
- package/dist/session.d.ts +686 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +2025 -0
- package/dist/session.js.map +1 -0
- package/dist/state-store.d.ts +189 -0
- package/dist/state-store.d.ts.map +1 -0
- package/dist/state-store.js +730 -0
- package/dist/state-store.js.map +1 -0
- package/dist/subagent-watcher.d.ts +345 -0
- package/dist/subagent-watcher.d.ts.map +1 -0
- package/dist/subagent-watcher.js +1469 -0
- package/dist/subagent-watcher.js.map +1 -0
- package/dist/task-queue.d.ts +108 -0
- package/dist/task-queue.d.ts.map +1 -0
- package/dist/task-queue.js +235 -0
- package/dist/task-queue.js.map +1 -0
- package/dist/task-tracker.d.ts +306 -0
- package/dist/task-tracker.d.ts.map +1 -0
- package/dist/task-tracker.js +488 -0
- package/dist/task-tracker.js.map +1 -0
- package/dist/task.d.ts +73 -0
- package/dist/task.d.ts.map +1 -0
- package/dist/task.js +177 -0
- package/dist/task.js.map +1 -0
- package/dist/team-watcher.d.ts +53 -0
- package/dist/team-watcher.d.ts.map +1 -0
- package/dist/team-watcher.js +313 -0
- package/dist/team-watcher.js.map +1 -0
- package/dist/templates/case-template.md +461 -0
- package/dist/templates/claude-md.d.ts +26 -0
- package/dist/templates/claude-md.d.ts.map +1 -0
- package/dist/templates/claude-md.js +74 -0
- package/dist/templates/claude-md.js.map +1 -0
- package/dist/tmux-manager.d.ts +181 -0
- package/dist/tmux-manager.d.ts.map +1 -0
- package/dist/tmux-manager.js +1405 -0
- package/dist/tmux-manager.js.map +1 -0
- package/dist/transcript-watcher.d.ts +110 -0
- package/dist/transcript-watcher.d.ts.map +1 -0
- package/dist/transcript-watcher.js +338 -0
- package/dist/transcript-watcher.js.map +1 -0
- package/dist/tunnel-manager.d.ts +54 -0
- package/dist/tunnel-manager.d.ts.map +1 -0
- package/dist/tunnel-manager.js +251 -0
- package/dist/tunnel-manager.js.map +1 -0
- package/dist/types.d.ts +1139 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +215 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/buffer-accumulator.d.ts +111 -0
- package/dist/utils/buffer-accumulator.d.ts.map +1 -0
- package/dist/utils/buffer-accumulator.js +172 -0
- package/dist/utils/buffer-accumulator.js.map +1 -0
- package/dist/utils/claude-cli-resolver.d.ts +26 -0
- package/dist/utils/claude-cli-resolver.d.ts.map +1 -0
- package/dist/utils/claude-cli-resolver.js +78 -0
- package/dist/utils/claude-cli-resolver.js.map +1 -0
- package/dist/utils/cleanup-manager.d.ts +165 -0
- package/dist/utils/cleanup-manager.d.ts.map +1 -0
- package/dist/utils/cleanup-manager.js +274 -0
- package/dist/utils/cleanup-manager.js.map +1 -0
- package/dist/utils/index.d.ts +19 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/lru-map.d.ts +140 -0
- package/dist/utils/lru-map.d.ts.map +1 -0
- package/dist/utils/lru-map.js +234 -0
- package/dist/utils/lru-map.js.map +1 -0
- package/dist/utils/nice-wrapper.d.ts +13 -0
- package/dist/utils/nice-wrapper.d.ts.map +1 -0
- package/dist/utils/nice-wrapper.js +17 -0
- package/dist/utils/nice-wrapper.js.map +1 -0
- package/dist/utils/opencode-cli-resolver.d.ts +21 -0
- package/dist/utils/opencode-cli-resolver.d.ts.map +1 -0
- package/dist/utils/opencode-cli-resolver.js +67 -0
- package/dist/utils/opencode-cli-resolver.js.map +1 -0
- package/dist/utils/regex-patterns.d.ts +64 -0
- package/dist/utils/regex-patterns.d.ts.map +1 -0
- package/dist/utils/regex-patterns.js +74 -0
- package/dist/utils/regex-patterns.js.map +1 -0
- package/dist/utils/stale-expiration-map.d.ts +159 -0
- package/dist/utils/stale-expiration-map.d.ts.map +1 -0
- package/dist/utils/stale-expiration-map.js +277 -0
- package/dist/utils/stale-expiration-map.js.map +1 -0
- package/dist/utils/string-similarity.d.ts +108 -0
- package/dist/utils/string-similarity.d.ts.map +1 -0
- package/dist/utils/string-similarity.js +189 -0
- package/dist/utils/string-similarity.js.map +1 -0
- package/dist/utils/token-validation.d.ts +39 -0
- package/dist/utils/token-validation.d.ts.map +1 -0
- package/dist/utils/token-validation.js +59 -0
- package/dist/utils/token-validation.js.map +1 -0
- package/dist/utils/type-safety.d.ts +33 -0
- package/dist/utils/type-safety.d.ts.map +1 -0
- package/dist/utils/type-safety.js +35 -0
- package/dist/utils/type-safety.js.map +1 -0
- package/dist/web/public/app.js +491 -0
- package/dist/web/public/app.js.br +0 -0
- package/dist/web/public/app.js.gz +0 -0
- package/dist/web/public/index.html +1675 -0
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/manifest.json +8 -0
- package/dist/web/public/mobile.css +1 -0
- package/dist/web/public/mobile.css.br +0 -0
- package/dist/web/public/mobile.css.gz +0 -0
- package/dist/web/public/ralph-wizard.js +1037 -0
- package/dist/web/public/ralph-wizard.js.br +0 -0
- package/dist/web/public/ralph-wizard.js.gz +0 -0
- package/dist/web/public/styles.css +1 -0
- package/dist/web/public/styles.css.br +0 -0
- package/dist/web/public/styles.css.gz +0 -0
- package/dist/web/public/sw.js +67 -0
- package/dist/web/public/sw.js.br +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/upload.html +155 -0
- package/dist/web/public/upload.html.br +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js +1 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js +1 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js +2 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css +209 -0
- package/dist/web/public/vendor/xterm.css.br +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js +9 -0
- package/dist/web/public/vendor/xterm.min.js.br +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/schemas.d.ts +479 -0
- package/dist/web/schemas.d.ts.map +1 -0
- package/dist/web/schemas.js +448 -0
- package/dist/web/schemas.js.map +1 -0
- package/dist/web/server.d.ts +207 -0
- package/dist/web/server.d.ts.map +1 -0
- package/dist/web/server.js +5784 -0
- package/dist/web/server.js.map +1 -0
- package/package.json +110 -0
- package/scripts/postinstall.js +390 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Map with automatic TTL-based entry expiration.
|
|
3
|
+
*
|
|
4
|
+
* StaleExpirationMap automatically removes entries that haven't been accessed
|
|
5
|
+
* within a configurable TTL (time-to-live). Useful for caches and tracking
|
|
6
|
+
* ephemeral data that should be cleaned up after a period of inactivity.
|
|
7
|
+
*
|
|
8
|
+
* @module utils/stale-expiration-map
|
|
9
|
+
*/
|
|
10
|
+
import type { Disposable } from '../types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Configuration options for StaleExpirationMap.
|
|
13
|
+
*/
|
|
14
|
+
export interface StaleExpirationMapOptions<K, V> {
|
|
15
|
+
/** Time-to-live in milliseconds before entries expire */
|
|
16
|
+
ttlMs: number;
|
|
17
|
+
/** How often to run cleanup (default: ttlMs / 2) */
|
|
18
|
+
cleanupIntervalMs?: number;
|
|
19
|
+
/** Optional callback when an entry expires */
|
|
20
|
+
onExpire?: (key: K, value: V) => void;
|
|
21
|
+
/** Whether to refresh TTL on get (default: true) */
|
|
22
|
+
refreshOnGet?: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A Map that automatically expires entries after a TTL.
|
|
26
|
+
*
|
|
27
|
+
* Entries are removed if not accessed within the TTL period.
|
|
28
|
+
* Periodic cleanup runs to remove expired entries.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* const cache = new StaleExpirationMap<string, object>({
|
|
33
|
+
* ttlMs: 5 * 60 * 1000, // 5 minutes
|
|
34
|
+
* onExpire: (key, value) => console.log(`Expired: ${key}`)
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* cache.set('key1', { data: 'value' });
|
|
38
|
+
* // After 5 minutes of no access, 'key1' will be automatically removed
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare class StaleExpirationMap<K, V> implements Disposable {
|
|
42
|
+
private entries;
|
|
43
|
+
private cleanupTimer;
|
|
44
|
+
private _isDisposed;
|
|
45
|
+
private readonly ttlMs;
|
|
46
|
+
private readonly cleanupIntervalMs;
|
|
47
|
+
private readonly onExpire?;
|
|
48
|
+
private readonly refreshOnGet;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a new StaleExpirationMap.
|
|
51
|
+
*
|
|
52
|
+
* @param options - Configuration options
|
|
53
|
+
*/
|
|
54
|
+
constructor(options: StaleExpirationMapOptions<K, V>);
|
|
55
|
+
/**
|
|
56
|
+
* Whether this map has been disposed.
|
|
57
|
+
*/
|
|
58
|
+
get isDisposed(): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Number of entries in the map.
|
|
61
|
+
*/
|
|
62
|
+
get size(): number;
|
|
63
|
+
/**
|
|
64
|
+
* Set a value with automatic TTL tracking.
|
|
65
|
+
*
|
|
66
|
+
* @param key - Key to set
|
|
67
|
+
* @param value - Value to associate
|
|
68
|
+
* @returns this (for chaining)
|
|
69
|
+
*/
|
|
70
|
+
set(key: K, value: V): this;
|
|
71
|
+
/**
|
|
72
|
+
* Get a value, optionally refreshing its TTL.
|
|
73
|
+
*
|
|
74
|
+
* @param key - Key to look up
|
|
75
|
+
* @returns Value if found and not expired, undefined otherwise
|
|
76
|
+
*/
|
|
77
|
+
get(key: K): V | undefined;
|
|
78
|
+
/**
|
|
79
|
+
* Check if a key exists and is not expired.
|
|
80
|
+
*
|
|
81
|
+
* @param key - Key to check
|
|
82
|
+
* @returns True if key exists and is not expired
|
|
83
|
+
*/
|
|
84
|
+
has(key: K): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Peek at a value without refreshing its TTL.
|
|
87
|
+
*
|
|
88
|
+
* @param key - Key to peek
|
|
89
|
+
* @returns Value if found and not expired, undefined otherwise
|
|
90
|
+
*/
|
|
91
|
+
peek(key: K): V | undefined;
|
|
92
|
+
/**
|
|
93
|
+
* Delete an entry.
|
|
94
|
+
*
|
|
95
|
+
* @param key - Key to delete
|
|
96
|
+
* @returns True if entry existed and was deleted
|
|
97
|
+
*/
|
|
98
|
+
delete(key: K): boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Clear all entries.
|
|
101
|
+
*/
|
|
102
|
+
clear(): void;
|
|
103
|
+
/**
|
|
104
|
+
* Touch an entry to refresh its TTL without returning the value.
|
|
105
|
+
*
|
|
106
|
+
* @param key - Key to touch
|
|
107
|
+
* @returns True if entry exists
|
|
108
|
+
*/
|
|
109
|
+
touch(key: K): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Get the age of an entry in milliseconds.
|
|
112
|
+
*
|
|
113
|
+
* @param key - Key to check
|
|
114
|
+
* @returns Age in ms, or undefined if not found
|
|
115
|
+
*/
|
|
116
|
+
getAge(key: K): number | undefined;
|
|
117
|
+
/**
|
|
118
|
+
* Get remaining TTL for an entry in milliseconds.
|
|
119
|
+
*
|
|
120
|
+
* @param key - Key to check
|
|
121
|
+
* @returns Remaining TTL in ms, or undefined if not found/expired
|
|
122
|
+
*/
|
|
123
|
+
getRemainingTtl(key: K): number | undefined;
|
|
124
|
+
/**
|
|
125
|
+
* Iterate over all non-expired entries.
|
|
126
|
+
*/
|
|
127
|
+
[Symbol.iterator](): IterableIterator<[K, V]>;
|
|
128
|
+
/**
|
|
129
|
+
* Get all keys (non-expired).
|
|
130
|
+
*/
|
|
131
|
+
keys(): IterableIterator<K>;
|
|
132
|
+
/**
|
|
133
|
+
* Get all values (non-expired).
|
|
134
|
+
*/
|
|
135
|
+
values(): IterableIterator<V>;
|
|
136
|
+
/**
|
|
137
|
+
* Run cleanup immediately, removing all expired entries.
|
|
138
|
+
*
|
|
139
|
+
* @returns Number of entries removed
|
|
140
|
+
*/
|
|
141
|
+
cleanup(): number;
|
|
142
|
+
/**
|
|
143
|
+
* Dispose the map, stopping cleanup timer and clearing entries.
|
|
144
|
+
*/
|
|
145
|
+
dispose(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Check if an entry has expired.
|
|
148
|
+
*/
|
|
149
|
+
private isExpired;
|
|
150
|
+
/**
|
|
151
|
+
* Start the periodic cleanup timer.
|
|
152
|
+
*/
|
|
153
|
+
private startCleanup;
|
|
154
|
+
/**
|
|
155
|
+
* Stop the periodic cleanup timer.
|
|
156
|
+
*/
|
|
157
|
+
private stopCleanup;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=stale-expiration-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale-expiration-map.d.ts","sourceRoot":"","sources":["../../src/utils/stale-expiration-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAW9C;;GAEG;AACH,MAAM,WAAW,yBAAyB,CAAC,CAAC,EAAE,CAAC;IAC7C,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IACtC,oDAAoD;IACpD,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,kBAAkB,CAAC,CAAC,EAAE,CAAC,CAAE,YAAW,UAAU;IACzD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,YAAY,CAA+B;IACnD,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAA6B;IACvD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAU;IAEvC;;;;OAIG;gBACS,OAAO,EAAE,yBAAyB,CAAC,CAAC,EAAE,CAAC,CAAC;IAUpD;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAExB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;;;OAMG;IACH,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAY3B;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS;IAkB1B;;;;;OAKG;IACH,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAYpB;;;;;OAKG;IACH,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,SAAS;IAY3B;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IASvB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;;;;OAKG;IACH,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO;IAQtB;;;;;OAKG;IACH,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,SAAS;IAMlC;;;;;OAKG;IACH,eAAe,CAAC,GAAG,EAAE,CAAC,GAAG,MAAM,GAAG,SAAS;IAS3C;;OAEG;IACF,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAQ9C;;OAEG;IACF,IAAI,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAQ5B;;OAEG;IACF,MAAM,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAQ9B;;;;OAIG;IACH,OAAO,IAAI,MAAM;IAejB;;OAEG;IACH,OAAO,IAAI,IAAI;IAQf;;OAEG;IACH,OAAO,CAAC,SAAS;IAIjB;;OAEG;IACH,OAAO,CAAC,YAAY;IAapB;;OAEG;IACH,OAAO,CAAC,WAAW;CAMpB"}
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Map with automatic TTL-based entry expiration.
|
|
3
|
+
*
|
|
4
|
+
* StaleExpirationMap automatically removes entries that haven't been accessed
|
|
5
|
+
* within a configurable TTL (time-to-live). Useful for caches and tracking
|
|
6
|
+
* ephemeral data that should be cleaned up after a period of inactivity.
|
|
7
|
+
*
|
|
8
|
+
* @module utils/stale-expiration-map
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* A Map that automatically expires entries after a TTL.
|
|
12
|
+
*
|
|
13
|
+
* Entries are removed if not accessed within the TTL period.
|
|
14
|
+
* Periodic cleanup runs to remove expired entries.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const cache = new StaleExpirationMap<string, object>({
|
|
19
|
+
* ttlMs: 5 * 60 * 1000, // 5 minutes
|
|
20
|
+
* onExpire: (key, value) => console.log(`Expired: ${key}`)
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* cache.set('key1', { data: 'value' });
|
|
24
|
+
* // After 5 minutes of no access, 'key1' will be automatically removed
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export class StaleExpirationMap {
|
|
28
|
+
entries = new Map();
|
|
29
|
+
cleanupTimer = null;
|
|
30
|
+
_isDisposed = false;
|
|
31
|
+
ttlMs;
|
|
32
|
+
cleanupIntervalMs;
|
|
33
|
+
onExpire;
|
|
34
|
+
refreshOnGet;
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new StaleExpirationMap.
|
|
37
|
+
*
|
|
38
|
+
* @param options - Configuration options
|
|
39
|
+
*/
|
|
40
|
+
constructor(options) {
|
|
41
|
+
this.ttlMs = options.ttlMs;
|
|
42
|
+
this.cleanupIntervalMs = options.cleanupIntervalMs ?? Math.floor(options.ttlMs / 2);
|
|
43
|
+
this.onExpire = options.onExpire;
|
|
44
|
+
this.refreshOnGet = options.refreshOnGet ?? true;
|
|
45
|
+
// Start periodic cleanup
|
|
46
|
+
this.startCleanup();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Whether this map has been disposed.
|
|
50
|
+
*/
|
|
51
|
+
get isDisposed() {
|
|
52
|
+
return this._isDisposed;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Number of entries in the map.
|
|
56
|
+
*/
|
|
57
|
+
get size() {
|
|
58
|
+
return this.entries.size;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Set a value with automatic TTL tracking.
|
|
62
|
+
*
|
|
63
|
+
* @param key - Key to set
|
|
64
|
+
* @param value - Value to associate
|
|
65
|
+
* @returns this (for chaining)
|
|
66
|
+
*/
|
|
67
|
+
set(key, value) {
|
|
68
|
+
if (this._isDisposed)
|
|
69
|
+
return this;
|
|
70
|
+
const now = Date.now();
|
|
71
|
+
this.entries.set(key, {
|
|
72
|
+
value,
|
|
73
|
+
lastAccessedAt: now,
|
|
74
|
+
createdAt: now,
|
|
75
|
+
});
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Get a value, optionally refreshing its TTL.
|
|
80
|
+
*
|
|
81
|
+
* @param key - Key to look up
|
|
82
|
+
* @returns Value if found and not expired, undefined otherwise
|
|
83
|
+
*/
|
|
84
|
+
get(key) {
|
|
85
|
+
const entry = this.entries.get(key);
|
|
86
|
+
if (!entry)
|
|
87
|
+
return undefined;
|
|
88
|
+
// Check if expired
|
|
89
|
+
if (this.isExpired(entry)) {
|
|
90
|
+
this.delete(key);
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
// Refresh access time if configured
|
|
94
|
+
if (this.refreshOnGet) {
|
|
95
|
+
entry.lastAccessedAt = Date.now();
|
|
96
|
+
}
|
|
97
|
+
return entry.value;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if a key exists and is not expired.
|
|
101
|
+
*
|
|
102
|
+
* @param key - Key to check
|
|
103
|
+
* @returns True if key exists and is not expired
|
|
104
|
+
*/
|
|
105
|
+
has(key) {
|
|
106
|
+
const entry = this.entries.get(key);
|
|
107
|
+
if (!entry)
|
|
108
|
+
return false;
|
|
109
|
+
if (this.isExpired(entry)) {
|
|
110
|
+
this.delete(key);
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Peek at a value without refreshing its TTL.
|
|
117
|
+
*
|
|
118
|
+
* @param key - Key to peek
|
|
119
|
+
* @returns Value if found and not expired, undefined otherwise
|
|
120
|
+
*/
|
|
121
|
+
peek(key) {
|
|
122
|
+
const entry = this.entries.get(key);
|
|
123
|
+
if (!entry)
|
|
124
|
+
return undefined;
|
|
125
|
+
if (this.isExpired(entry)) {
|
|
126
|
+
this.delete(key);
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
return entry.value;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Delete an entry.
|
|
133
|
+
*
|
|
134
|
+
* @param key - Key to delete
|
|
135
|
+
* @returns True if entry existed and was deleted
|
|
136
|
+
*/
|
|
137
|
+
delete(key) {
|
|
138
|
+
const entry = this.entries.get(key);
|
|
139
|
+
if (!entry)
|
|
140
|
+
return false;
|
|
141
|
+
this.entries.delete(key);
|
|
142
|
+
// Don't call onExpire for manual deletes
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Clear all entries.
|
|
147
|
+
*/
|
|
148
|
+
clear() {
|
|
149
|
+
this.entries.clear();
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Touch an entry to refresh its TTL without returning the value.
|
|
153
|
+
*
|
|
154
|
+
* @param key - Key to touch
|
|
155
|
+
* @returns True if entry exists
|
|
156
|
+
*/
|
|
157
|
+
touch(key) {
|
|
158
|
+
const entry = this.entries.get(key);
|
|
159
|
+
if (!entry || this.isExpired(entry))
|
|
160
|
+
return false;
|
|
161
|
+
entry.lastAccessedAt = Date.now();
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Get the age of an entry in milliseconds.
|
|
166
|
+
*
|
|
167
|
+
* @param key - Key to check
|
|
168
|
+
* @returns Age in ms, or undefined if not found
|
|
169
|
+
*/
|
|
170
|
+
getAge(key) {
|
|
171
|
+
const entry = this.entries.get(key);
|
|
172
|
+
if (!entry)
|
|
173
|
+
return undefined;
|
|
174
|
+
return Date.now() - entry.createdAt;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get remaining TTL for an entry in milliseconds.
|
|
178
|
+
*
|
|
179
|
+
* @param key - Key to check
|
|
180
|
+
* @returns Remaining TTL in ms, or undefined if not found/expired
|
|
181
|
+
*/
|
|
182
|
+
getRemainingTtl(key) {
|
|
183
|
+
const entry = this.entries.get(key);
|
|
184
|
+
if (!entry)
|
|
185
|
+
return undefined;
|
|
186
|
+
const elapsed = Date.now() - entry.lastAccessedAt;
|
|
187
|
+
const remaining = this.ttlMs - elapsed;
|
|
188
|
+
return remaining > 0 ? remaining : 0;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Iterate over all non-expired entries.
|
|
192
|
+
*/
|
|
193
|
+
*[Symbol.iterator]() {
|
|
194
|
+
for (const [key, entry] of this.entries) {
|
|
195
|
+
if (!this.isExpired(entry)) {
|
|
196
|
+
yield [key, entry.value];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get all keys (non-expired).
|
|
202
|
+
*/
|
|
203
|
+
*keys() {
|
|
204
|
+
for (const [key, entry] of this.entries) {
|
|
205
|
+
if (!this.isExpired(entry)) {
|
|
206
|
+
yield key;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Get all values (non-expired).
|
|
212
|
+
*/
|
|
213
|
+
*values() {
|
|
214
|
+
for (const [, entry] of this.entries) {
|
|
215
|
+
if (!this.isExpired(entry)) {
|
|
216
|
+
yield entry.value;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Run cleanup immediately, removing all expired entries.
|
|
222
|
+
*
|
|
223
|
+
* @returns Number of entries removed
|
|
224
|
+
*/
|
|
225
|
+
cleanup() {
|
|
226
|
+
let removed = 0;
|
|
227
|
+
const now = Date.now();
|
|
228
|
+
for (const [key, entry] of this.entries) {
|
|
229
|
+
if (now - entry.lastAccessedAt > this.ttlMs) {
|
|
230
|
+
this.entries.delete(key);
|
|
231
|
+
this.onExpire?.(key, entry.value);
|
|
232
|
+
removed++;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return removed;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Dispose the map, stopping cleanup timer and clearing entries.
|
|
239
|
+
*/
|
|
240
|
+
dispose() {
|
|
241
|
+
if (this._isDisposed)
|
|
242
|
+
return;
|
|
243
|
+
this._isDisposed = true;
|
|
244
|
+
this.stopCleanup();
|
|
245
|
+
this.entries.clear();
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Check if an entry has expired.
|
|
249
|
+
*/
|
|
250
|
+
isExpired(entry) {
|
|
251
|
+
return Date.now() - entry.lastAccessedAt > this.ttlMs;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Start the periodic cleanup timer.
|
|
255
|
+
*/
|
|
256
|
+
startCleanup() {
|
|
257
|
+
if (this.cleanupTimer)
|
|
258
|
+
return;
|
|
259
|
+
this.cleanupTimer = setInterval(() => {
|
|
260
|
+
if (!this._isDisposed) {
|
|
261
|
+
this.cleanup();
|
|
262
|
+
}
|
|
263
|
+
}, this.cleanupIntervalMs);
|
|
264
|
+
// Don't prevent process exit
|
|
265
|
+
this.cleanupTimer.unref();
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Stop the periodic cleanup timer.
|
|
269
|
+
*/
|
|
270
|
+
stopCleanup() {
|
|
271
|
+
if (this.cleanupTimer) {
|
|
272
|
+
clearInterval(this.cleanupTimer);
|
|
273
|
+
this.cleanupTimer = null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=stale-expiration-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stale-expiration-map.js","sourceRoot":"","sources":["../../src/utils/stale-expiration-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview String similarity utilities for fuzzy matching.
|
|
3
|
+
*
|
|
4
|
+
* Provides Levenshtein distance and similarity scoring for:
|
|
5
|
+
* - Completion phrase fuzzy matching
|
|
6
|
+
* - Todo content deduplication
|
|
7
|
+
*
|
|
8
|
+
* @module utils/string-similarity
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Calculate the Levenshtein (edit) distance between two strings.
|
|
12
|
+
* This is the minimum number of single-character edits (insertions,
|
|
13
|
+
* deletions, or substitutions) required to change one string into the other.
|
|
14
|
+
*
|
|
15
|
+
* Uses Wagner-Fischer algorithm with O(min(m,n)) space optimization.
|
|
16
|
+
*
|
|
17
|
+
* @param a - First string
|
|
18
|
+
* @param b - Second string
|
|
19
|
+
* @returns The edit distance (0 = identical)
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* levenshteinDistance('hello', 'hello') // 0
|
|
23
|
+
* levenshteinDistance('hello', 'helo') // 1 (one deletion)
|
|
24
|
+
* levenshteinDistance('COMPLETE', 'COMPLET') // 1 (one deletion)
|
|
25
|
+
*/
|
|
26
|
+
export declare function levenshteinDistance(a: string, b: string): number;
|
|
27
|
+
/**
|
|
28
|
+
* Calculate similarity ratio between two strings (0 to 1).
|
|
29
|
+
* Uses Levenshtein distance normalized by the longer string's length.
|
|
30
|
+
*
|
|
31
|
+
* @param a - First string
|
|
32
|
+
* @param b - Second string
|
|
33
|
+
* @returns Similarity ratio (1.0 = identical, 0.0 = completely different)
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* stringSimilarity('hello', 'hello') // 1.0
|
|
37
|
+
* stringSimilarity('hello', 'helo') // 0.8 (4/5 similar)
|
|
38
|
+
* stringSimilarity('abc', 'xyz') // 0.0 (3 edits, length 3)
|
|
39
|
+
*/
|
|
40
|
+
export declare function stringSimilarity(a: string, b: string): number;
|
|
41
|
+
/**
|
|
42
|
+
* Check if two strings are similar within a given threshold.
|
|
43
|
+
*
|
|
44
|
+
* @param a - First string
|
|
45
|
+
* @param b - Second string
|
|
46
|
+
* @param threshold - Minimum similarity ratio (default: 0.85 = 85% similar)
|
|
47
|
+
* @returns True if similarity >= threshold
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* isSimilar('COMPLETE', 'COMPLET', 0.85) // true (87.5% similar)
|
|
51
|
+
* isSimilar('COMPLETE', 'DONE', 0.85) // false (0% similar)
|
|
52
|
+
*/
|
|
53
|
+
export declare function isSimilar(a: string, b: string, threshold?: number): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Check if two strings are similar with edit distance tolerance.
|
|
56
|
+
* More intuitive for short strings than percentage-based threshold.
|
|
57
|
+
*
|
|
58
|
+
* @param a - First string
|
|
59
|
+
* @param b - Second string
|
|
60
|
+
* @param maxDistance - Maximum allowed edit distance (default: 2)
|
|
61
|
+
* @returns True if edit distance <= maxDistance
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* isSimilarByDistance('COMPLETE', 'COMPLET', 2) // true (distance 1)
|
|
65
|
+
* isSimilarByDistance('COMPLETE', 'COMP', 2) // false (distance 4)
|
|
66
|
+
*/
|
|
67
|
+
export declare function isSimilarByDistance(a: string, b: string, maxDistance?: number): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Normalize a completion phrase for comparison.
|
|
70
|
+
* Handles variations in case, whitespace, and separators.
|
|
71
|
+
*
|
|
72
|
+
* @param phrase - Raw completion phrase
|
|
73
|
+
* @returns Normalized phrase (uppercase, no separators)
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* normalizePhrase('task_done') // 'TASKDONE'
|
|
77
|
+
* normalizePhrase('TASK-DONE') // 'TASKDONE'
|
|
78
|
+
* normalizePhrase('Task Done') // 'TASKDONE'
|
|
79
|
+
*/
|
|
80
|
+
export declare function normalizePhrase(phrase: string): string;
|
|
81
|
+
/**
|
|
82
|
+
* Check if two completion phrases match with fuzzy tolerance.
|
|
83
|
+
*
|
|
84
|
+
* First normalizes both phrases, then checks:
|
|
85
|
+
* 1. Exact match after normalization
|
|
86
|
+
* 2. Edit distance <= maxDistance for typo tolerance
|
|
87
|
+
*
|
|
88
|
+
* @param phrase1 - First phrase to compare
|
|
89
|
+
* @param phrase2 - Second phrase to compare
|
|
90
|
+
* @param maxDistance - Maximum edit distance for fuzzy match (default: 2)
|
|
91
|
+
* @returns True if phrases match (exact or fuzzy)
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* fuzzyPhraseMatch('COMPLETE', 'COMPLETE') // true (exact)
|
|
95
|
+
* fuzzyPhraseMatch('COMPLETE', 'COMPLET') // true (typo)
|
|
96
|
+
* fuzzyPhraseMatch('TASK_DONE', 'TASKDONE') // true (separator)
|
|
97
|
+
* fuzzyPhraseMatch('COMPLETE', 'FINISHED') // false (different word)
|
|
98
|
+
*/
|
|
99
|
+
export declare function fuzzyPhraseMatch(phrase1: string, phrase2: string, maxDistance?: number): boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Generate a content hash for todo deduplication.
|
|
102
|
+
* Normalizes content and generates a simple hash.
|
|
103
|
+
*
|
|
104
|
+
* @param content - Todo item content
|
|
105
|
+
* @returns Normalized hash string for comparison
|
|
106
|
+
*/
|
|
107
|
+
export declare function todoContentHash(content: string): string;
|
|
108
|
+
//# sourceMappingURL=string-similarity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"string-similarity.d.ts","sourceRoot":"","sources":["../../src/utils/string-similarity.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA0ChE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ7D;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,SAAO,GAAG,OAAO,CAEzE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,WAAW,SAAI,GAAG,OAAO,CAElF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKtD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,SAAI,GAAG,OAAO,CAe3F;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAgBvD"}
|