atabey 0.1.1-beta → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -78
- package/dist/atabey/src/cli/commands/coverage.js +17 -12
- package/dist/atabey/src/cli/commands/coverage.js.map +1 -1
- package/dist/atabey/src/cli/commands/lint.d.ts +2 -1
- package/dist/atabey/src/cli/commands/lint.js +20 -1
- package/dist/atabey/src/cli/commands/lint.js.map +1 -1
- package/dist/atabey/src/cli/commands/mcp.js +56 -23
- package/dist/atabey/src/cli/commands/mcp.js.map +1 -1
- package/dist/atabey/src/cli/commands/orchestrate.d.ts +6 -6
- package/dist/shared/src/agent-identity.d.ts +1 -34
- package/dist/shared/src/agent-identity.js +1 -76
- package/dist/shared/src/agent-identity.js.map +1 -1
- package/dist/shared/src/api-catalog.d.ts +1 -57
- package/dist/shared/src/api-catalog.js +1 -253
- package/dist/shared/src/api-catalog.js.map +1 -1
- package/dist/shared/src/audit-chain.d.ts +1 -80
- package/dist/shared/src/audit-chain.js +1 -261
- package/dist/shared/src/audit-chain.js.map +1 -1
- package/dist/shared/src/audit.d.ts +1 -121
- package/dist/shared/src/audit.js +1 -321
- package/dist/shared/src/audit.js.map +1 -1
- package/dist/shared/src/constants.d.ts +1 -150
- package/dist/shared/src/constants.js +1 -211
- package/dist/shared/src/constants.js.map +1 -1
- package/dist/shared/src/database.d.ts +1 -6
- package/dist/shared/src/database.js +1 -15
- package/dist/shared/src/database.js.map +1 -1
- package/dist/shared/src/errors.d.ts +1 -46
- package/dist/shared/src/errors.js +1 -68
- package/dist/shared/src/errors.js.map +1 -1
- package/dist/shared/src/file-lock.d.ts +1 -93
- package/dist/shared/src/file-lock.js +1 -239
- package/dist/shared/src/file-lock.js.map +1 -1
- package/dist/shared/src/fs.d.ts +1 -9
- package/dist/shared/src/fs.js +1 -53
- package/dist/shared/src/fs.js.map +1 -1
- package/dist/shared/src/index.d.ts +2 -31
- package/dist/shared/src/index.js +2 -31
- package/dist/shared/src/index.js.map +1 -1
- package/dist/shared/src/job-queue.d.ts +1 -76
- package/dist/shared/src/job-queue.js +1 -199
- package/dist/shared/src/job-queue.js.map +1 -1
- package/dist/shared/src/lock.d.ts +1 -82
- package/dist/shared/src/lock.js +1 -158
- package/dist/shared/src/lock.js.map +1 -1
- package/dist/shared/src/logger.d.ts +1 -31
- package/dist/shared/src/logger.js +1 -152
- package/dist/shared/src/logger.js.map +1 -1
- package/dist/shared/src/memory-prune.d.ts +1 -18
- package/dist/shared/src/memory-prune.js +1 -47
- package/dist/shared/src/memory-prune.js.map +1 -1
- package/dist/shared/src/migrations.d.ts +1 -69
- package/dist/shared/src/migrations.js +1 -393
- package/dist/shared/src/migrations.js.map +1 -1
- package/dist/shared/src/modules/agent/agent-identity.d.ts +34 -0
- package/dist/shared/src/modules/agent/agent-identity.js +77 -0
- package/dist/shared/src/modules/agent/agent-identity.js.map +1 -0
- package/dist/shared/src/modules/agent/api-catalog.d.ts +57 -0
- package/dist/shared/src/modules/agent/api-catalog.js +254 -0
- package/dist/shared/src/modules/agent/api-catalog.js.map +1 -0
- package/dist/shared/src/modules/agent/index.d.ts +3 -0
- package/dist/shared/src/modules/agent/index.js +4 -0
- package/dist/shared/src/modules/agent/index.js.map +1 -0
- package/dist/shared/src/modules/agent/tokenizer.d.ts +54 -0
- package/dist/shared/src/modules/agent/tokenizer.js +272 -0
- package/dist/shared/src/modules/agent/tokenizer.js.map +1 -0
- package/dist/shared/src/modules/concurrency/file-lock.d.ts +93 -0
- package/dist/shared/src/modules/concurrency/file-lock.js +240 -0
- package/dist/shared/src/modules/concurrency/file-lock.js.map +1 -0
- package/dist/shared/src/modules/concurrency/index.d.ts +6 -0
- package/dist/shared/src/modules/concurrency/index.js +7 -0
- package/dist/shared/src/modules/concurrency/index.js.map +1 -0
- package/dist/shared/src/modules/concurrency/job-queue.d.ts +76 -0
- package/dist/shared/src/modules/concurrency/job-queue.js +200 -0
- package/dist/shared/src/modules/concurrency/job-queue.js.map +1 -0
- package/dist/shared/src/modules/concurrency/lock.d.ts +82 -0
- package/dist/shared/src/modules/concurrency/lock.js +159 -0
- package/dist/shared/src/modules/concurrency/lock.js.map +1 -0
- package/dist/shared/src/modules/concurrency/resilience.d.ts +84 -0
- package/dist/shared/src/modules/concurrency/resilience.js +217 -0
- package/dist/shared/src/modules/concurrency/resilience.js.map +1 -0
- package/dist/shared/src/modules/concurrency/worker-pool.d.ts +52 -0
- package/dist/shared/src/modules/concurrency/worker-pool.js +229 -0
- package/dist/shared/src/modules/concurrency/worker-pool.js.map +1 -0
- package/dist/shared/src/modules/concurrency/worker-thread.d.ts +21 -0
- package/dist/shared/src/modules/concurrency/worker-thread.js +67 -0
- package/dist/shared/src/modules/concurrency/worker-thread.js.map +1 -0
- package/dist/shared/src/modules/index.d.ts +14 -0
- package/dist/shared/src/modules/index.js +15 -0
- package/dist/shared/src/modules/index.js.map +1 -0
- package/dist/shared/src/modules/observability/audit-chain.d.ts +80 -0
- package/dist/shared/src/modules/observability/audit-chain.js +262 -0
- package/dist/shared/src/modules/observability/audit-chain.js.map +1 -0
- package/dist/shared/src/modules/observability/audit.d.ts +121 -0
- package/dist/shared/src/modules/observability/audit.js +322 -0
- package/dist/shared/src/modules/observability/audit.js.map +1 -0
- package/dist/shared/src/modules/observability/index.d.ts +4 -0
- package/dist/shared/src/modules/observability/index.js +5 -0
- package/dist/shared/src/modules/observability/index.js.map +1 -0
- package/dist/shared/src/modules/observability/logger.d.ts +31 -0
- package/dist/shared/src/modules/observability/logger.js +153 -0
- package/dist/shared/src/modules/observability/logger.js.map +1 -0
- package/dist/shared/src/modules/observability/otel.d.ts +39 -0
- package/dist/shared/src/modules/observability/otel.js +93 -0
- package/dist/shared/src/modules/observability/otel.js.map +1 -0
- package/dist/shared/src/modules/primitives/constants.d.ts +150 -0
- package/dist/shared/src/modules/primitives/constants.js +212 -0
- package/dist/shared/src/modules/primitives/constants.js.map +1 -0
- package/dist/shared/src/modules/primitives/errors.d.ts +46 -0
- package/dist/shared/src/modules/primitives/errors.js +69 -0
- package/dist/shared/src/modules/primitives/errors.js.map +1 -0
- package/dist/shared/src/modules/primitives/fs.d.ts +9 -0
- package/dist/shared/src/modules/primitives/fs.js +54 -0
- package/dist/shared/src/modules/primitives/fs.js.map +1 -0
- package/dist/shared/src/modules/primitives/index.d.ts +7 -0
- package/dist/shared/src/modules/primitives/index.js +8 -0
- package/dist/shared/src/modules/primitives/index.js.map +1 -0
- package/dist/shared/src/modules/primitives/outbound-http.d.ts +32 -0
- package/dist/shared/src/modules/primitives/outbound-http.js +88 -0
- package/dist/shared/src/modules/primitives/outbound-http.js.map +1 -0
- package/dist/shared/src/modules/primitives/string.d.ts +1 -0
- package/dist/shared/src/modules/primitives/string.js +30 -0
- package/dist/shared/src/modules/primitives/string.js.map +1 -0
- package/dist/shared/src/modules/primitives/time.d.ts +5 -0
- package/dist/shared/src/modules/primitives/time.js +35 -0
- package/dist/shared/src/modules/primitives/time.js.map +1 -0
- package/dist/shared/src/modules/primitives/types.d.ts +27 -0
- package/dist/shared/src/modules/primitives/types.js +17 -0
- package/dist/shared/src/modules/primitives/types.js.map +1 -0
- package/dist/shared/src/modules/sandbox/index.d.ts +3 -0
- package/dist/shared/src/modules/sandbox/index.js +4 -0
- package/dist/shared/src/modules/sandbox/index.js.map +1 -0
- package/dist/shared/src/modules/sandbox/sandbox-fs.d.ts +28 -0
- package/dist/shared/src/modules/sandbox/sandbox-fs.js +143 -0
- package/dist/shared/src/modules/sandbox/sandbox-fs.js.map +1 -0
- package/dist/shared/src/modules/sandbox/sandbox-runtime.d.ts +78 -0
- package/dist/shared/src/modules/sandbox/sandbox-runtime.js +282 -0
- package/dist/shared/src/modules/sandbox/sandbox-runtime.js.map +1 -0
- package/dist/shared/src/modules/sandbox/sandbox.d.ts +54 -0
- package/dist/shared/src/modules/sandbox/sandbox.js +179 -0
- package/dist/shared/src/modules/sandbox/sandbox.js.map +1 -0
- package/dist/shared/src/modules/security/index.d.ts +5 -0
- package/dist/shared/src/modules/security/index.js +6 -0
- package/dist/shared/src/modules/security/index.js.map +1 -0
- package/dist/shared/src/modules/security/pii.d.ts +70 -0
- package/dist/shared/src/modules/security/pii.js +276 -0
- package/dist/shared/src/modules/security/pii.js.map +1 -0
- package/dist/shared/src/modules/security/policy-gate.d.ts +42 -0
- package/dist/shared/src/modules/security/policy-gate.js +172 -0
- package/dist/shared/src/modules/security/policy-gate.js.map +1 -0
- package/dist/shared/src/modules/security/retention.d.ts +68 -0
- package/dist/shared/src/modules/security/retention.js +218 -0
- package/dist/shared/src/modules/security/retention.js.map +1 -0
- package/dist/shared/src/modules/security/secrets.d.ts +99 -0
- package/dist/shared/src/modules/security/secrets.js +371 -0
- package/dist/shared/src/modules/security/secrets.js.map +1 -0
- package/dist/shared/src/modules/security/tls.d.ts +87 -0
- package/dist/shared/src/modules/security/tls.js +154 -0
- package/dist/shared/src/modules/security/tls.js.map +1 -0
- package/dist/shared/src/modules/storage/database.d.ts +6 -0
- package/dist/shared/src/modules/storage/database.js +16 -0
- package/dist/shared/src/modules/storage/database.js.map +1 -0
- package/dist/shared/src/modules/storage/index.d.ts +4 -0
- package/dist/shared/src/modules/storage/index.js +5 -0
- package/dist/shared/src/modules/storage/index.js.map +1 -0
- package/dist/shared/src/modules/storage/memory-prune.d.ts +18 -0
- package/dist/shared/src/modules/storage/memory-prune.js +48 -0
- package/dist/shared/src/modules/storage/memory-prune.js.map +1 -0
- package/dist/shared/src/modules/storage/migrations.d.ts +69 -0
- package/dist/shared/src/modules/storage/migrations.js +394 -0
- package/dist/shared/src/modules/storage/migrations.js.map +1 -0
- package/dist/shared/src/modules/storage/storage.d.ts +341 -0
- package/dist/shared/src/modules/storage/storage.js +1004 -0
- package/dist/shared/src/modules/storage/storage.js.map +1 -0
- package/dist/shared/src/otel.d.ts +1 -39
- package/dist/shared/src/otel.js +1 -92
- package/dist/shared/src/otel.js.map +1 -1
- package/dist/shared/src/outbound-http.d.ts +1 -32
- package/dist/shared/src/outbound-http.js +1 -87
- package/dist/shared/src/outbound-http.js.map +1 -1
- package/dist/shared/src/pii.d.ts +1 -70
- package/dist/shared/src/pii.js +1 -275
- package/dist/shared/src/pii.js.map +1 -1
- package/dist/shared/src/policy-gate.d.ts +1 -42
- package/dist/shared/src/policy-gate.js +1 -171
- package/dist/shared/src/policy-gate.js.map +1 -1
- package/dist/shared/src/resilience.d.ts +1 -84
- package/dist/shared/src/resilience.js +1 -216
- package/dist/shared/src/resilience.js.map +1 -1
- package/dist/shared/src/retention.d.ts +1 -68
- package/dist/shared/src/retention.js +1 -217
- package/dist/shared/src/retention.js.map +1 -1
- package/dist/shared/src/sandbox-fs.d.ts +1 -28
- package/dist/shared/src/sandbox-fs.js +1 -142
- package/dist/shared/src/sandbox-fs.js.map +1 -1
- package/dist/shared/src/sandbox-runtime.d.ts +1 -78
- package/dist/shared/src/sandbox-runtime.js +1 -281
- package/dist/shared/src/sandbox-runtime.js.map +1 -1
- package/dist/shared/src/sandbox.d.ts +1 -54
- package/dist/shared/src/sandbox.js +1 -178
- package/dist/shared/src/sandbox.js.map +1 -1
- package/dist/shared/src/secrets.d.ts +1 -99
- package/dist/shared/src/secrets.js +1 -370
- package/dist/shared/src/secrets.js.map +1 -1
- package/dist/shared/src/storage.d.ts +1 -341
- package/dist/shared/src/storage.js +1 -1003
- package/dist/shared/src/storage.js.map +1 -1
- package/dist/shared/src/string.d.ts +1 -1
- package/dist/shared/src/string.js +1 -29
- package/dist/shared/src/string.js.map +1 -1
- package/dist/shared/src/time.d.ts +1 -5
- package/dist/shared/src/time.js +1 -34
- package/dist/shared/src/time.js.map +1 -1
- package/dist/shared/src/tls.d.ts +1 -87
- package/dist/shared/src/tls.js +1 -153
- package/dist/shared/src/tls.js.map +1 -1
- package/dist/shared/src/tokenizer.d.ts +1 -54
- package/dist/shared/src/tokenizer.js +1 -271
- package/dist/shared/src/tokenizer.js.map +1 -1
- package/dist/shared/src/types.d.ts +1 -27
- package/dist/shared/src/types.js +1 -16
- package/dist/shared/src/types.js.map +1 -1
- package/dist/shared/src/worker-pool.d.ts +1 -52
- package/dist/shared/src/worker-pool.js +1 -228
- package/dist/shared/src/worker-pool.js.map +1 -1
- package/dist/shared/src/worker-thread.d.ts +1 -21
- package/dist/shared/src/worker-thread.js +1 -66
- package/dist/shared/src/worker-thread.js.map +1 -1
- package/package.json +4 -4
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token Counter & Pricing Catalog (Phase 1.5)
|
|
3
|
+
*
|
|
4
|
+
* Uses the REAL `cl100k_base` BPE tokenizer via `js-tiktoken` (lite build +
|
|
5
|
+
* cl100k ranks ≈ ±2% vs provider tokenizers). If the BPE table cannot be
|
|
6
|
+
* loaded, it falls back to a cl100k-style pre-tokenization heuristic.
|
|
7
|
+
*
|
|
8
|
+
* Model-specific tokenizers (o200k_base, Claude, Gemini) are not applied yet;
|
|
9
|
+
* `_model` is accepted for API compatibility. Use counts for token awareness
|
|
10
|
+
* and token-awareness guardrails, not exact billing.
|
|
11
|
+
*/
|
|
12
|
+
import { Tiktoken } from "js-tiktoken/lite";
|
|
13
|
+
import cl100kRanks from "js-tiktoken/ranks/cl100k_base";
|
|
14
|
+
/**
|
|
15
|
+
* Up-to-date model pricing catalog (USD per 1M tokens).
|
|
16
|
+
*/
|
|
17
|
+
export const MODEL_PRICING_CATALOG = {
|
|
18
|
+
"claude-sonnet-4": {
|
|
19
|
+
provider: "anthropic",
|
|
20
|
+
model: "claude-sonnet-4",
|
|
21
|
+
inputPer1MUsd: 3.0,
|
|
22
|
+
outputPer1MUsd: 15.0,
|
|
23
|
+
tokenizer: "claude_bpe",
|
|
24
|
+
},
|
|
25
|
+
"claude-opus-4": {
|
|
26
|
+
provider: "anthropic",
|
|
27
|
+
model: "claude-opus-4",
|
|
28
|
+
inputPer1MUsd: 15.0,
|
|
29
|
+
outputPer1MUsd: 75.0,
|
|
30
|
+
tokenizer: "claude_bpe",
|
|
31
|
+
},
|
|
32
|
+
"claude-3-7-sonnet": {
|
|
33
|
+
provider: "anthropic",
|
|
34
|
+
model: "claude-3-7-sonnet",
|
|
35
|
+
inputPer1MUsd: 3.0,
|
|
36
|
+
outputPer1MUsd: 15.0,
|
|
37
|
+
tokenizer: "claude_bpe",
|
|
38
|
+
},
|
|
39
|
+
"claude-3-5-sonnet": {
|
|
40
|
+
provider: "anthropic",
|
|
41
|
+
model: "claude-3-5-sonnet",
|
|
42
|
+
inputPer1MUsd: 3.0,
|
|
43
|
+
outputPer1MUsd: 15.0,
|
|
44
|
+
tokenizer: "claude_bpe",
|
|
45
|
+
},
|
|
46
|
+
"claude-3-5-haiku": {
|
|
47
|
+
provider: "anthropic",
|
|
48
|
+
model: "claude-3-5-haiku",
|
|
49
|
+
inputPer1MUsd: 0.8,
|
|
50
|
+
outputPer1MUsd: 4.0,
|
|
51
|
+
tokenizer: "claude_bpe",
|
|
52
|
+
},
|
|
53
|
+
"gpt-4o": {
|
|
54
|
+
provider: "openai",
|
|
55
|
+
model: "gpt-4o",
|
|
56
|
+
inputPer1MUsd: 2.5,
|
|
57
|
+
outputPer1MUsd: 10.0,
|
|
58
|
+
tokenizer: "o200k_base",
|
|
59
|
+
},
|
|
60
|
+
"gpt-4o-mini": {
|
|
61
|
+
provider: "openai",
|
|
62
|
+
model: "gpt-4o-mini",
|
|
63
|
+
inputPer1MUsd: 0.15,
|
|
64
|
+
outputPer1MUsd: 0.6,
|
|
65
|
+
tokenizer: "o200k_base",
|
|
66
|
+
},
|
|
67
|
+
"gpt-4.1": {
|
|
68
|
+
provider: "openai",
|
|
69
|
+
model: "gpt-4.1",
|
|
70
|
+
inputPer1MUsd: 2.0,
|
|
71
|
+
outputPer1MUsd: 8.0,
|
|
72
|
+
tokenizer: "o200k_base",
|
|
73
|
+
},
|
|
74
|
+
"o3-mini": {
|
|
75
|
+
provider: "openai",
|
|
76
|
+
model: "o3-mini",
|
|
77
|
+
inputPer1MUsd: 1.1,
|
|
78
|
+
outputPer1MUsd: 4.4,
|
|
79
|
+
tokenizer: "o200k_base",
|
|
80
|
+
},
|
|
81
|
+
"gemini-2.5-pro": {
|
|
82
|
+
provider: "google",
|
|
83
|
+
model: "gemini-2.5-pro",
|
|
84
|
+
inputPer1MUsd: 1.25,
|
|
85
|
+
outputPer1MUsd: 10.0,
|
|
86
|
+
tokenizer: "gemini_spm",
|
|
87
|
+
},
|
|
88
|
+
"gemini-2.5-flash": {
|
|
89
|
+
provider: "google",
|
|
90
|
+
model: "gemini-2.5-flash",
|
|
91
|
+
inputPer1MUsd: 0.15,
|
|
92
|
+
outputPer1MUsd: 0.6,
|
|
93
|
+
tokenizer: "gemini_spm",
|
|
94
|
+
},
|
|
95
|
+
"deepseek-chat": {
|
|
96
|
+
provider: "deepseek",
|
|
97
|
+
model: "deepseek-chat",
|
|
98
|
+
inputPer1MUsd: 0.27,
|
|
99
|
+
outputPer1MUsd: 1.1,
|
|
100
|
+
tokenizer: "cl100k_base",
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Official cl100k_base pre-tokenization pattern:
|
|
105
|
+
* - English contractions ('s, 'd, 'm, 't, 'll, 've, 're)
|
|
106
|
+
* - Optional space + Unicode letters
|
|
107
|
+
* - Optional space + 1..3 Unicode digits (numbers split every 3 digits in cl100k)
|
|
108
|
+
* - Optional space + non-whitespace/non-alphanumeric punctuation
|
|
109
|
+
* - Newlines / trailing whitespace runs
|
|
110
|
+
*/
|
|
111
|
+
const CL100K_PRETOKEN_REGEX = /'(?:[sdmt]|ll|ve|re)| ?\p{L}+| ?\p{N}{1,3}| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+/gu;
|
|
112
|
+
/**
|
|
113
|
+
* Common high-frequency programming/English tokens that map 1:1 to a single BPE token
|
|
114
|
+
* in cl100k_base / o200k_base.
|
|
115
|
+
*/
|
|
116
|
+
const SINGLE_BPE_WORDS = new Set([
|
|
117
|
+
"function", "return", "const", "let", "var", "import", "export", "from", "async", "await",
|
|
118
|
+
"interface", "type", "class", "public", "private", "protected", "static", "readonly",
|
|
119
|
+
"string", "number", "boolean", "object", "undefined", "null", "true", "false", "void",
|
|
120
|
+
"promise", "record", "array", "error", "default", "switch", "case", "break", "continue",
|
|
121
|
+
"throw", "catch", "finally", "typeof", "instanceof", "extends", "implements", "constructor",
|
|
122
|
+
"package", "module", "require", "process", "console", "Buffer", "Math", "JSON", "Date",
|
|
123
|
+
"SELECT", "INSERT", "UPDATE", "DELETE", "FROM", "WHERE", "CREATE", "TABLE", "INDEX",
|
|
124
|
+
]);
|
|
125
|
+
/**
|
|
126
|
+
* Estimate how many BPE subword tokens a single pre-token chunk splits into.
|
|
127
|
+
*/
|
|
128
|
+
function countChunkBpeTokens(chunk) {
|
|
129
|
+
const trimmed = chunk.trimStart();
|
|
130
|
+
if (!trimmed) {
|
|
131
|
+
// Pure whitespace run: 1 token per ~4 spaces or per newline group
|
|
132
|
+
return Math.max(1, Math.ceil(chunk.length / 4));
|
|
133
|
+
}
|
|
134
|
+
// 1-3 digit numbers are guaranteed 1 token by CL100K_PRETOKEN_REGEX
|
|
135
|
+
if (/^\p{N}{1,3}$/u.test(trimmed)) {
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
138
|
+
// Punctuation runs: common 1-3 char operators (===, !==, =>, ->, ::, ..., etc.) are 1 token
|
|
139
|
+
if (/^[^\s\p{L}\p{N}]+$/u.test(trimmed)) {
|
|
140
|
+
if (trimmed.length <= 3)
|
|
141
|
+
return 1;
|
|
142
|
+
return Math.ceil(trimmed.length / 2.5);
|
|
143
|
+
}
|
|
144
|
+
// ASCII word/identifier
|
|
145
|
+
if (/^[A-Za-z]+$/.test(trimmed)) {
|
|
146
|
+
if (trimmed.length <= 6 || SINGLE_BPE_WORDS.has(trimmed) || SINGLE_BPE_WORDS.has(trimmed.toLowerCase())) {
|
|
147
|
+
return 1;
|
|
148
|
+
}
|
|
149
|
+
// Split camelCase / PascalCase subwords first
|
|
150
|
+
const camelParts = trimmed.split(/(?=[A-Z][a-z])|(?<=[a-z])(?=[A-Z])/);
|
|
151
|
+
if (camelParts.length > 1) {
|
|
152
|
+
let subTokens = 0;
|
|
153
|
+
for (const part of camelParts) {
|
|
154
|
+
subTokens += part.length <= 6 ? 1 : Math.ceil(part.length / 4.5);
|
|
155
|
+
}
|
|
156
|
+
return subTokens;
|
|
157
|
+
}
|
|
158
|
+
// Longer natural word: BPE averages ~4.5 chars per subword token
|
|
159
|
+
return Math.ceil(trimmed.length / 4.5);
|
|
160
|
+
}
|
|
161
|
+
// Non-ASCII Unicode (Turkish diacritics, CJK, emoji, etc.) — count UTF-8 byte density
|
|
162
|
+
const byteLength = Buffer.byteLength(trimmed, "utf8");
|
|
163
|
+
// In BPE, 2-byte UTF-8 chars (e.g. ş, ğ, ı, ö, ü, ç) take ~1 token per 2.8 bytes
|
|
164
|
+
return Math.max(1, Math.ceil(byteLength / 2.8));
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Estimate BPE tokens in a string using cl100k-style pre-tokenization.
|
|
168
|
+
* NOTE: approximate — see file header. `_model` is accepted for API
|
|
169
|
+
* compatibility but per-model tokenizer differences are not yet applied.
|
|
170
|
+
*/
|
|
171
|
+
/** Heuristic fallback used only if the real BPE encoder cannot be initialised. */
|
|
172
|
+
function approximateCountTokens(text) {
|
|
173
|
+
const matches = text.match(CL100K_PRETOKEN_REGEX);
|
|
174
|
+
if (!matches)
|
|
175
|
+
return 0;
|
|
176
|
+
let total = 0;
|
|
177
|
+
for (const chunk of matches) {
|
|
178
|
+
total += countChunkBpeTokens(chunk);
|
|
179
|
+
}
|
|
180
|
+
return total;
|
|
181
|
+
}
|
|
182
|
+
/** Lazily-initialised real cl100k_base BPE encoder (js-tiktoken, lite build). */
|
|
183
|
+
let realEncoder = null;
|
|
184
|
+
let realEncoderFailed = false;
|
|
185
|
+
function getRealEncoder() {
|
|
186
|
+
if (realEncoder)
|
|
187
|
+
return realEncoder;
|
|
188
|
+
if (realEncoderFailed)
|
|
189
|
+
return null;
|
|
190
|
+
try {
|
|
191
|
+
realEncoder = new Tiktoken(cl100kRanks);
|
|
192
|
+
return realEncoder;
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
realEncoderFailed = true;
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Count BPE tokens in a string.
|
|
201
|
+
*
|
|
202
|
+
* Uses the REAL `cl100k_base` tokenizer (js-tiktoken) for ~±2% accuracy.
|
|
203
|
+
* Falls back to a cl100k-style heuristic only if the BPE table cannot load.
|
|
204
|
+
*/
|
|
205
|
+
export function countTokens(text, _model) {
|
|
206
|
+
if (!text)
|
|
207
|
+
return 0;
|
|
208
|
+
const encoder = getRealEncoder();
|
|
209
|
+
if (encoder) {
|
|
210
|
+
try {
|
|
211
|
+
return encoder.encode(text).length;
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
/* fall through to heuristic */
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return approximateCountTokens(text);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Resolve pricing for a given model name (supports partial matches and env overrides).
|
|
221
|
+
*/
|
|
222
|
+
export function resolveModelPricing(model) {
|
|
223
|
+
const requested = (model || process.env.ATABEY_MODEL || "claude-sonnet-4").toLowerCase().trim();
|
|
224
|
+
if (MODEL_PRICING_CATALOG[requested]) {
|
|
225
|
+
return MODEL_PRICING_CATALOG[requested];
|
|
226
|
+
}
|
|
227
|
+
for (const [key, pricing] of Object.entries(MODEL_PRICING_CATALOG)) {
|
|
228
|
+
if (requested.includes(key) || key.includes(requested)) {
|
|
229
|
+
return pricing;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const envPer1k = parseFloat(process.env.ATABEY_COST_PER_1K_TOKENS_USD || "");
|
|
233
|
+
if (Number.isFinite(envPer1k) && envPer1k > 0) {
|
|
234
|
+
return {
|
|
235
|
+
provider: "generic",
|
|
236
|
+
model: requested || "custom",
|
|
237
|
+
inputPer1MUsd: envPer1k * 1000,
|
|
238
|
+
outputPer1MUsd: envPer1k * 1000,
|
|
239
|
+
tokenizer: "cl100k_base",
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return MODEL_PRICING_CATALOG["claude-sonnet-4"];
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Calculate USD cost from separate input and output token counts.
|
|
246
|
+
*/
|
|
247
|
+
export function calculateModelCost(inputTokens, outputTokens, model) {
|
|
248
|
+
const pricing = resolveModelPricing(model);
|
|
249
|
+
const inputCost = (Math.max(0, inputTokens) / 1_000_000) * pricing.inputPer1MUsd;
|
|
250
|
+
const outputCost = (Math.max(0, outputTokens) / 1_000_000) * pricing.outputPer1MUsd;
|
|
251
|
+
const costUsd = Number((inputCost + outputCost).toFixed(8));
|
|
252
|
+
return { costUsd, pricing };
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Compute full input/output token and estimated-cost breakdown for an MCP tool invocation.
|
|
256
|
+
*/
|
|
257
|
+
export function measureToolCallUsage(toolName, args, resultText, model) {
|
|
258
|
+
const argsSerialized = typeof args === "string" ? args : JSON.stringify(args ?? {});
|
|
259
|
+
// Include MCP tool framing overhead (+8 tokens for tool call envelope)
|
|
260
|
+
const inputTokens = countTokens(toolName, model) + countTokens(argsSerialized, model) + 8;
|
|
261
|
+
const outputTokens = countTokens(resultText || "", model);
|
|
262
|
+
const { costUsd, pricing } = calculateModelCost(inputTokens, outputTokens, model);
|
|
263
|
+
return {
|
|
264
|
+
inputTokens,
|
|
265
|
+
outputTokens,
|
|
266
|
+
totalTokens: inputTokens + outputTokens,
|
|
267
|
+
estimatedCostUsd: costUsd,
|
|
268
|
+
model: pricing.model,
|
|
269
|
+
provider: pricing.provider,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=tokenizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tokenizer.js","sourceRoot":"","sources":["../../../../../../shared/src/modules/agent/tokenizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic File-Based Locking — OS-level exclusive create via open('wx').
|
|
3
|
+
*
|
|
4
|
+
* Replaces check-then-act lock races. No Redis/Redlock required.
|
|
5
|
+
*
|
|
6
|
+
* Pattern:
|
|
7
|
+
* resource → .atabey/locks/<relative>.lock (created with O_EXCL / 'wx')
|
|
8
|
+
* holder writes JSON metadata after exclusive create
|
|
9
|
+
* release unlinks the lock file
|
|
10
|
+
*
|
|
11
|
+
* Stale locks (TTL exceeded) are reclaimed atomically when possible.
|
|
12
|
+
*/
|
|
13
|
+
export interface FileLockOptions {
|
|
14
|
+
/** Base directory for lock files. Default: `.atabey/locks` under cwd or projectRoot. */
|
|
15
|
+
locksDir?: string;
|
|
16
|
+
/** Project root used to relativize resource paths. Default: process.cwd(). */
|
|
17
|
+
projectRoot?: string;
|
|
18
|
+
/** Lock TTL in ms. Stale locks may be stolen after this. Default: 5 minutes. */
|
|
19
|
+
ttlMs?: number;
|
|
20
|
+
/** Retry interval when waiting for a lock. Default: 50ms. */
|
|
21
|
+
retryMs?: number;
|
|
22
|
+
/** Max wait when using acquireAsync. Default: 10s. */
|
|
23
|
+
timeoutMs?: number;
|
|
24
|
+
}
|
|
25
|
+
export interface FileLockMeta {
|
|
26
|
+
ownerId: string;
|
|
27
|
+
resource: string;
|
|
28
|
+
acquiredAt: string;
|
|
29
|
+
expiresAt: string;
|
|
30
|
+
reason?: string;
|
|
31
|
+
pid: number;
|
|
32
|
+
hostname: string;
|
|
33
|
+
}
|
|
34
|
+
export declare class AtomicFileLock {
|
|
35
|
+
private readonly locksDir;
|
|
36
|
+
private readonly projectRoot;
|
|
37
|
+
private readonly ttlMs;
|
|
38
|
+
private readonly retryMs;
|
|
39
|
+
private readonly timeoutMs;
|
|
40
|
+
constructor(options?: FileLockOptions);
|
|
41
|
+
/** Absolute path of the lock file for a resource. */
|
|
42
|
+
getLockPath(resource: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Try to acquire a lock once (non-blocking).
|
|
45
|
+
* Uses atomic exclusive file create (`wx` = O_CREAT | O_EXCL | O_WRONLY).
|
|
46
|
+
*/
|
|
47
|
+
tryAcquire(resource: string, ownerId: string, reason?: string, _reclaimDepth?: number): {
|
|
48
|
+
acquired: boolean;
|
|
49
|
+
meta?: FileLockMeta;
|
|
50
|
+
heldBy?: FileLockMeta;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Acquire with async retry until timeout.
|
|
54
|
+
*/
|
|
55
|
+
acquireAsync(resource: string, ownerId: string, options?: {
|
|
56
|
+
reason?: string;
|
|
57
|
+
timeoutMs?: number;
|
|
58
|
+
retryMs?: number;
|
|
59
|
+
}): Promise<FileLockMeta>;
|
|
60
|
+
/**
|
|
61
|
+
* Release lock only if owned by ownerId (or force=true).
|
|
62
|
+
*/
|
|
63
|
+
release(resource: string, ownerId: string, force?: boolean): boolean;
|
|
64
|
+
isLocked(resource: string): FileLockMeta | null;
|
|
65
|
+
/**
|
|
66
|
+
* Run `fn` while holding the lock.
|
|
67
|
+
* ALWAYS releases in `finally` even if `fn` throws (disk full, parse errors, etc.).
|
|
68
|
+
* Without this, a leftover `.lock` file would deadlock every subsequent writer until TTL.
|
|
69
|
+
*
|
|
70
|
+
* Prefer this API over bare acquire/release for any mutating work.
|
|
71
|
+
*/
|
|
72
|
+
withLock<T>(resource: string, ownerId: string, fn: () => Promise<T> | T, options?: {
|
|
73
|
+
reason?: string;
|
|
74
|
+
timeoutMs?: number;
|
|
75
|
+
}): Promise<T>;
|
|
76
|
+
/**
|
|
77
|
+
* Synchronous withLock — same try/finally release guarantee.
|
|
78
|
+
*/
|
|
79
|
+
withLockSync<T>(resource: string, ownerId: string, fn: () => T, options?: {
|
|
80
|
+
reason?: string;
|
|
81
|
+
}): T;
|
|
82
|
+
private reclaimIfStale;
|
|
83
|
+
/**
|
|
84
|
+
* True when an existing lock file may be safely stolen: unparseable/empty
|
|
85
|
+
* (corrupt, e.g. crashed mid-write) or past its TTL.
|
|
86
|
+
*/
|
|
87
|
+
private isReclaimable;
|
|
88
|
+
private isExpired;
|
|
89
|
+
private readMeta;
|
|
90
|
+
private forceRemove;
|
|
91
|
+
}
|
|
92
|
+
/** Convenience: lock under project `.atabey/locks`. */
|
|
93
|
+
export declare function createProjectFileLock(projectRoot: string, options?: Omit<FileLockOptions, "projectRoot">): AtomicFileLock;
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic File-Based Locking — OS-level exclusive create via open('wx').
|
|
3
|
+
*
|
|
4
|
+
* Replaces check-then-act lock races. No Redis/Redlock required.
|
|
5
|
+
*
|
|
6
|
+
* Pattern:
|
|
7
|
+
* resource → .atabey/locks/<relative>.lock (created with O_EXCL / 'wx')
|
|
8
|
+
* holder writes JSON metadata after exclusive create
|
|
9
|
+
* release unlinks the lock file
|
|
10
|
+
*
|
|
11
|
+
* Stale locks (TTL exceeded) are reclaimed atomically when possible.
|
|
12
|
+
*/
|
|
13
|
+
import fs from "fs";
|
|
14
|
+
import os from "os";
|
|
15
|
+
import path from "path";
|
|
16
|
+
export class AtomicFileLock {
|
|
17
|
+
locksDir;
|
|
18
|
+
projectRoot;
|
|
19
|
+
ttlMs;
|
|
20
|
+
retryMs;
|
|
21
|
+
timeoutMs;
|
|
22
|
+
constructor(options = {}) {
|
|
23
|
+
this.projectRoot = options.projectRoot ?? process.cwd();
|
|
24
|
+
this.locksDir = options.locksDir
|
|
25
|
+
? path.resolve(options.locksDir)
|
|
26
|
+
: path.join(this.projectRoot, ".atabey", "locks");
|
|
27
|
+
this.ttlMs = options.ttlMs ?? 5 * 60 * 1000;
|
|
28
|
+
this.retryMs = options.retryMs ?? 50;
|
|
29
|
+
this.timeoutMs = options.timeoutMs ?? 10_000;
|
|
30
|
+
}
|
|
31
|
+
/** Absolute path of the lock file for a resource. */
|
|
32
|
+
getLockPath(resource) {
|
|
33
|
+
const abs = path.isAbsolute(resource)
|
|
34
|
+
? resource
|
|
35
|
+
: path.resolve(this.projectRoot, resource);
|
|
36
|
+
let relative = path.relative(this.projectRoot, abs);
|
|
37
|
+
if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
38
|
+
// Outside project root — hash path to avoid escaping locks dir
|
|
39
|
+
relative = `_ext/${Buffer.from(abs).toString("base64url")}`;
|
|
40
|
+
}
|
|
41
|
+
// Normalize separators for cross-platform lock paths
|
|
42
|
+
relative = relative.split(path.sep).join("/");
|
|
43
|
+
return path.join(this.locksDir, `${relative}.lock`);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Try to acquire a lock once (non-blocking).
|
|
47
|
+
* Uses atomic exclusive file create (`wx` = O_CREAT | O_EXCL | O_WRONLY).
|
|
48
|
+
*/
|
|
49
|
+
tryAcquire(resource, ownerId, reason, _reclaimDepth = 0) {
|
|
50
|
+
const lockPath = this.getLockPath(resource);
|
|
51
|
+
fs.mkdirSync(path.dirname(lockPath), { recursive: true });
|
|
52
|
+
// Reclaim stale lock first (best-effort, still atomic on create)
|
|
53
|
+
this.reclaimIfStale(lockPath);
|
|
54
|
+
const now = Date.now();
|
|
55
|
+
const meta = {
|
|
56
|
+
ownerId,
|
|
57
|
+
resource,
|
|
58
|
+
acquiredAt: new Date(now).toISOString(),
|
|
59
|
+
expiresAt: new Date(now + this.ttlMs).toISOString(),
|
|
60
|
+
reason,
|
|
61
|
+
pid: process.pid,
|
|
62
|
+
hostname: os.hostname(),
|
|
63
|
+
};
|
|
64
|
+
try {
|
|
65
|
+
// Atomic exclusive create WITH content in one syscall sequence
|
|
66
|
+
// (writeFileSync + flag 'wx' = O_CREAT|O_EXCL|O_WRONLY): there is no
|
|
67
|
+
// window where the lock file exists empty for a reader to misread.
|
|
68
|
+
fs.writeFileSync(lockPath, JSON.stringify(meta, null, 2), { encoding: "utf8", flag: "wx" });
|
|
69
|
+
return { acquired: true, meta };
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
const code = err.code;
|
|
73
|
+
if (code === "EEXIST") {
|
|
74
|
+
// Another process holds it. Reclaim only if corrupt/empty or expired.
|
|
75
|
+
const heldBy = this.readMeta(lockPath) ?? undefined;
|
|
76
|
+
if ((!heldBy || this.isExpired(heldBy)) && _reclaimDepth < 1) {
|
|
77
|
+
this.forceRemove(lockPath, heldBy ?? null);
|
|
78
|
+
return this.tryAcquire(resource, ownerId, reason, _reclaimDepth + 1);
|
|
79
|
+
}
|
|
80
|
+
return { acquired: false, heldBy };
|
|
81
|
+
}
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Acquire with async retry until timeout.
|
|
87
|
+
*/
|
|
88
|
+
async acquireAsync(resource, ownerId, options) {
|
|
89
|
+
const timeoutMs = options?.timeoutMs ?? this.timeoutMs;
|
|
90
|
+
const retryMs = options?.retryMs ?? this.retryMs;
|
|
91
|
+
const start = Date.now();
|
|
92
|
+
while (true) {
|
|
93
|
+
const result = this.tryAcquire(resource, ownerId, options?.reason);
|
|
94
|
+
if (result.acquired && result.meta) {
|
|
95
|
+
return result.meta;
|
|
96
|
+
}
|
|
97
|
+
if (Date.now() - start >= timeoutMs) {
|
|
98
|
+
const holder = result.heldBy?.ownerId ?? "unknown";
|
|
99
|
+
throw new Error(`[AtomicFileLock] Timeout acquiring lock for "${resource}" after ${timeoutMs}ms (held by ${holder})`);
|
|
100
|
+
}
|
|
101
|
+
await sleep(retryMs);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Release lock only if owned by ownerId (or force=true).
|
|
106
|
+
*/
|
|
107
|
+
release(resource, ownerId, force = false) {
|
|
108
|
+
const lockPath = this.getLockPath(resource);
|
|
109
|
+
if (!fs.existsSync(lockPath))
|
|
110
|
+
return true;
|
|
111
|
+
const meta = this.readMeta(lockPath);
|
|
112
|
+
if (!meta) {
|
|
113
|
+
// Corrupt/empty lock — safe to drop (atomic create means a real
|
|
114
|
+
// holder always has readable meta).
|
|
115
|
+
this.forceRemove(lockPath, null);
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
if (!force && meta.ownerId !== ownerId) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
this.forceRemove(lockPath, meta);
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
isLocked(resource) {
|
|
125
|
+
const lockPath = this.getLockPath(resource);
|
|
126
|
+
if (!fs.existsSync(lockPath))
|
|
127
|
+
return null;
|
|
128
|
+
const meta = this.readMeta(lockPath);
|
|
129
|
+
if (!meta)
|
|
130
|
+
return null;
|
|
131
|
+
if (this.isExpired(meta)) {
|
|
132
|
+
this.forceRemove(lockPath, meta);
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
return meta;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Run `fn` while holding the lock.
|
|
139
|
+
* ALWAYS releases in `finally` even if `fn` throws (disk full, parse errors, etc.).
|
|
140
|
+
* Without this, a leftover `.lock` file would deadlock every subsequent writer until TTL.
|
|
141
|
+
*
|
|
142
|
+
* Prefer this API over bare acquire/release for any mutating work.
|
|
143
|
+
*/
|
|
144
|
+
async withLock(resource, ownerId, fn, options) {
|
|
145
|
+
await this.acquireAsync(resource, ownerId, options);
|
|
146
|
+
try {
|
|
147
|
+
return await fn();
|
|
148
|
+
}
|
|
149
|
+
finally {
|
|
150
|
+
// Never let release errors mask the original failure or leave a lock.
|
|
151
|
+
try {
|
|
152
|
+
this.release(resource, ownerId);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
this.forceRemove(this.getLockPath(resource), null);
|
|
156
|
+
}
|
|
157
|
+
// Belt-and-suspenders: if our lock is somehow still present, force drop it.
|
|
158
|
+
const stillHeld = this.isLocked(resource);
|
|
159
|
+
if (stillHeld && stillHeld.ownerId === ownerId) {
|
|
160
|
+
this.forceRemove(this.getLockPath(resource), stillHeld);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Synchronous withLock — same try/finally release guarantee.
|
|
166
|
+
*/
|
|
167
|
+
withLockSync(resource, ownerId, fn, options) {
|
|
168
|
+
const result = this.tryAcquire(resource, ownerId, options?.reason);
|
|
169
|
+
if (!result.acquired) {
|
|
170
|
+
const holder = result.heldBy?.ownerId ?? "unknown";
|
|
171
|
+
throw new Error(`[AtomicFileLock] Could not acquire lock for "${resource}" (held by ${holder})`);
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
return fn();
|
|
175
|
+
}
|
|
176
|
+
finally {
|
|
177
|
+
try {
|
|
178
|
+
this.release(resource, ownerId);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
this.forceRemove(this.getLockPath(resource), null);
|
|
182
|
+
}
|
|
183
|
+
const stillHeld = this.isLocked(resource);
|
|
184
|
+
if (stillHeld && stillHeld.ownerId === ownerId) {
|
|
185
|
+
this.forceRemove(this.getLockPath(resource), stillHeld);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
reclaimIfStale(lockPath) {
|
|
190
|
+
if (!fs.existsSync(lockPath))
|
|
191
|
+
return;
|
|
192
|
+
if (this.isReclaimable(lockPath)) {
|
|
193
|
+
this.forceRemove(lockPath, this.readMeta(lockPath));
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* True when an existing lock file may be safely stolen: unparseable/empty
|
|
198
|
+
* (corrupt, e.g. crashed mid-write) or past its TTL.
|
|
199
|
+
*/
|
|
200
|
+
isReclaimable(lockPath) {
|
|
201
|
+
const meta = this.readMeta(lockPath);
|
|
202
|
+
if (!meta)
|
|
203
|
+
return true;
|
|
204
|
+
return this.isExpired(meta);
|
|
205
|
+
}
|
|
206
|
+
isExpired(meta) {
|
|
207
|
+
const exp = Date.parse(meta.expiresAt);
|
|
208
|
+
if (Number.isNaN(exp)) {
|
|
209
|
+
// Fallback: acquiredAt + ttl
|
|
210
|
+
const acq = Date.parse(meta.acquiredAt);
|
|
211
|
+
return Number.isNaN(acq) ? true : Date.now() - acq > this.ttlMs;
|
|
212
|
+
}
|
|
213
|
+
return Date.now() > exp;
|
|
214
|
+
}
|
|
215
|
+
readMeta(lockPath) {
|
|
216
|
+
try {
|
|
217
|
+
const raw = fs.readFileSync(lockPath, "utf8");
|
|
218
|
+
return JSON.parse(raw);
|
|
219
|
+
}
|
|
220
|
+
catch {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
forceRemove(lockPath, _meta) {
|
|
225
|
+
try {
|
|
226
|
+
fs.unlinkSync(lockPath);
|
|
227
|
+
}
|
|
228
|
+
catch {
|
|
229
|
+
// ignore ENOENT races
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
function sleep(ms) {
|
|
234
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
235
|
+
}
|
|
236
|
+
/** Convenience: lock under project `.atabey/locks`. */
|
|
237
|
+
export function createProjectFileLock(projectRoot, options) {
|
|
238
|
+
return new AtomicFileLock({ ...options, projectRoot });
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=file-lock.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-lock.js","sourceRoot":"","sources":["../../../../../../shared/src/modules/concurrency/file-lock.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../shared/src/modules/concurrency/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC"}
|