@volcengine/tls-observer-claude-code 0.0.1 → 0.0.3

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tls-observer-claude-code",
3
3
  "description": "Export Claude Code prompts, assistant responses, tool calls, and token usage to Volcengine TLS as OTLP traces.",
4
- "version": "0.0.1",
4
+ "version": "0.0.3",
5
5
  "author": {
6
6
  "name": "Volcengine"
7
7
  },
package/dist/index.js CHANGED
@@ -222,7 +222,7 @@ async function closeTraceLogProducers() {
222
222
  }));
223
223
  }
224
224
  var package_namespaceObject = {
225
- rE: "0.0.1"
225
+ rE: "0.0.3"
226
226
  };
227
227
  function toOtlpAnyValue(value) {
228
228
  if ('string' == typeof value) return {
@@ -687,11 +687,11 @@ const SESSION_MAX_AGE_MS = 86400000;
687
687
  function sleep(ms) {
688
688
  return new Promise((resolve)=>setTimeout(resolve, ms));
689
689
  }
690
- function lockPath(stateFilePath) {
690
+ function state_lockPath(stateFilePath) {
691
691
  return `${stateFilePath}.lock`;
692
692
  }
693
693
  async function acquireLock(stateFilePath) {
694
- const lock = lockPath(stateFilePath);
694
+ const lock = state_lockPath(stateFilePath);
695
695
  const deadline = Date.now() + LOCK_TIMEOUT_MS;
696
696
  __rspack_external_node_fs_5ea92f0c.mkdirSync(__rspack_external_node_path_c5b9b54f.dirname(stateFilePath), {
697
697
  recursive: true
@@ -711,7 +711,7 @@ async function acquireLock(stateFilePath) {
711
711
  }
712
712
  function releaseLock(stateFilePath) {
713
713
  try {
714
- __rspack_external_node_fs_5ea92f0c.unlinkSync(lockPath(stateFilePath));
714
+ __rspack_external_node_fs_5ea92f0c.unlinkSync(state_lockPath(stateFilePath));
715
715
  } catch {}
716
716
  }
717
717
  function loadState(stateFilePath) {
@@ -1218,6 +1218,10 @@ async function writeTextFileAtomic(filePath, text, options = {}) {
1218
1218
  async function writeJsonFileAtomic(filePath, value, options = {}) {
1219
1219
  await writeTextFileAtomic(filePath, `${JSON.stringify(value, null, 2)}\n`, options);
1220
1220
  }
1221
+ const DEFAULT_MAX_FILES = 3;
1222
+ const LOCK_STALE_MS = 30000;
1223
+ const jsonl_LOCK_TIMEOUT_MS = 5000;
1224
+ const jsonl_LOCK_RETRY_MS = 25;
1221
1225
  async function appendJsonlFile(filePath, values) {
1222
1226
  const entries = Array.isArray(values) ? values : [
1223
1227
  values
@@ -1228,6 +1232,79 @@ async function appendJsonlFile(filePath, values) {
1228
1232
  });
1229
1233
  await __rspack_external_node_fs_promises_153e37e0.appendFile(filePath, `${entries.map((entry)=>JSON.stringify(entry)).join('\n')}\n`, 'utf8');
1230
1234
  }
1235
+ async function delay(ms) {
1236
+ await new Promise((resolve)=>setTimeout(resolve, ms));
1237
+ }
1238
+ async function withJsonlFileLock(filePath, action) {
1239
+ await __rspack_external_node_fs_promises_153e37e0.mkdir(__rspack_external_node_path_c5b9b54f.dirname(filePath), {
1240
+ recursive: true
1241
+ });
1242
+ const lockPath = `${filePath}.lock`;
1243
+ const startedAt = Date.now();
1244
+ while(true)try {
1245
+ const handle = await __rspack_external_node_fs_promises_153e37e0.open(lockPath, 'wx');
1246
+ try {
1247
+ await handle.writeFile(`${process.pid}:${new Date().toISOString()}\n`, 'utf8');
1248
+ return await action();
1249
+ } finally{
1250
+ await handle.close().catch(()=>void 0);
1251
+ await __rspack_external_node_fs_promises_153e37e0.rm(lockPath, {
1252
+ force: true
1253
+ }).catch(()=>void 0);
1254
+ }
1255
+ } catch (error) {
1256
+ if ('EEXIST' !== error.code) throw error;
1257
+ try {
1258
+ const stat = await __rspack_external_node_fs_promises_153e37e0.stat(lockPath);
1259
+ if (Date.now() - stat.mtimeMs > LOCK_STALE_MS) {
1260
+ await __rspack_external_node_fs_promises_153e37e0.rm(lockPath, {
1261
+ force: true
1262
+ }).catch(()=>void 0);
1263
+ continue;
1264
+ }
1265
+ } catch (statError) {
1266
+ if ('ENOENT' === statError.code) continue;
1267
+ throw statError;
1268
+ }
1269
+ if (Date.now() - startedAt > jsonl_LOCK_TIMEOUT_MS) throw new Error(`Timed out waiting for JSONL file lock: ${lockPath}`);
1270
+ await delay(jsonl_LOCK_RETRY_MS);
1271
+ }
1272
+ }
1273
+ function rotatedFileName(filePath, now = new Date()) {
1274
+ const dir = __rspack_external_node_path_c5b9b54f.dirname(filePath);
1275
+ const ext = __rspack_external_node_path_c5b9b54f.extname(filePath);
1276
+ const base = __rspack_external_node_path_c5b9b54f.basename(filePath, ext);
1277
+ const stamp = now.toISOString().replace(/[-:.TZ]/g, '').slice(0, 17);
1278
+ return __rspack_external_node_path_c5b9b54f.join(dir, `${base}.${stamp}.${process.pid}.${randomUUID()}${ext || '.jsonl'}`);
1279
+ }
1280
+ function rotatedFilePattern(filePath) {
1281
+ const ext = __rspack_external_node_path_c5b9b54f.extname(filePath);
1282
+ const base = __rspack_external_node_path_c5b9b54f.basename(filePath, ext).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1283
+ const escapedExt = (ext || '.jsonl').replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
1284
+ return new RegExp(`^${base}\\.\\d{17}\\.\\d+\\.[0-9a-f-]+${escapedExt}$`);
1285
+ }
1286
+ async function pruneRotatedJsonlFiles(filePath, maxFiles) {
1287
+ const maxRotatedFiles = Math.max(0, maxFiles - 1);
1288
+ const dir = __rspack_external_node_path_c5b9b54f.dirname(filePath);
1289
+ const pattern = rotatedFilePattern(filePath);
1290
+ let entries;
1291
+ try {
1292
+ entries = await __rspack_external_node_fs_promises_153e37e0.readdir(dir);
1293
+ } catch (error) {
1294
+ if ('ENOENT' === error.code) return;
1295
+ throw error;
1296
+ }
1297
+ const rotated = entries.filter((entry)=>pattern.test(entry)).sort((left, right)=>right.localeCompare(left)).map((entry)=>__rspack_external_node_path_c5b9b54f.join(dir, entry));
1298
+ await Promise.all(rotated.slice(maxRotatedFiles).map((target)=>__rspack_external_node_fs_promises_153e37e0.rm(target, {
1299
+ force: true
1300
+ })));
1301
+ }
1302
+ async function rotateActiveJsonlFile(filePath, maxFiles) {
1303
+ await __rspack_external_node_fs_promises_153e37e0.rename(filePath, rotatedFileName(filePath)).catch(async (error)=>{
1304
+ if ('ENOENT' !== error.code) throw error;
1305
+ });
1306
+ await pruneRotatedJsonlFiles(filePath, maxFiles);
1307
+ }
1231
1308
  async function trimJsonlFileByBytes(filePath, maxBytes) {
1232
1309
  if (maxBytes <= 0) return void await __rspack_external_node_fs_promises_153e37e0.rm(filePath, {
1233
1310
  force: true
@@ -1253,9 +1330,42 @@ async function trimJsonlFileByBytes(filePath, maxBytes) {
1253
1330
  }
1254
1331
  await writeTextFileAtomic(filePath, kept.length ? `${kept.reverse().join('\n')}\n` : '');
1255
1332
  }
1256
- async function appendBoundedJsonlFile(filePath, values, maxBytes) {
1257
- await appendJsonlFile(filePath, values);
1258
- await trimJsonlFileByBytes(filePath, maxBytes);
1333
+ async function appendBoundedJsonlFile(filePath, values, maxBytes, options = {}) {
1334
+ const entries = Array.isArray(values) ? values : [
1335
+ values
1336
+ ];
1337
+ if (0 === entries.length) return;
1338
+ if ('rotate' !== options.strategy) return void await withJsonlFileLock(filePath, async ()=>{
1339
+ await appendJsonlFile(filePath, entries);
1340
+ await trimJsonlFileByBytes(filePath, maxBytes);
1341
+ });
1342
+ await withJsonlFileLock(filePath, async ()=>{
1343
+ const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
1344
+ if (maxBytes <= 0 || maxFiles <= 0) {
1345
+ await __rspack_external_node_fs_promises_153e37e0.rm(filePath, {
1346
+ force: true
1347
+ }).catch(()=>void 0);
1348
+ await pruneRotatedJsonlFiles(filePath, 0);
1349
+ return;
1350
+ }
1351
+ let currentBytes = 0;
1352
+ try {
1353
+ currentBytes = (await __rspack_external_node_fs_promises_153e37e0.stat(filePath)).size;
1354
+ } catch (error) {
1355
+ if ('ENOENT' !== error.code) throw error;
1356
+ }
1357
+ for (const entry of entries){
1358
+ const line = `${JSON.stringify(entry)}\n`;
1359
+ const lineBytes = Buffer.byteLength(line, 'utf8');
1360
+ if (currentBytes > 0 && currentBytes + lineBytes > maxBytes) {
1361
+ await rotateActiveJsonlFile(filePath, maxFiles);
1362
+ currentBytes = 0;
1363
+ }
1364
+ await __rspack_external_node_fs_promises_153e37e0.appendFile(filePath, line, 'utf8');
1365
+ currentBytes += lineBytes;
1366
+ }
1367
+ await pruneRotatedJsonlFiles(filePath, maxFiles);
1368
+ });
1259
1369
  }
1260
1370
  function readTranscript(filePath, afterLine = -1, afterOffset = 0) {
1261
1371
  let size;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volcengine/tls-observer-claude-code",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Export Claude Code hook telemetry to Volcengine TLS with OTLP traces.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -11,19 +11,6 @@
11
11
  }
12
12
  },
13
13
  "types": "./dist/index.d.ts",
14
- "files": [
15
- "dist",
16
- "hooks",
17
- ".claude-plugin",
18
- "README.md",
19
- "LICENSE"
20
- ],
21
- "scripts": {
22
- "build": "rslib build",
23
- "dev": "rslib build --watch",
24
- "test": "jest --runInBand",
25
- "test:coverage": "jest --runInBand --coverage"
26
- },
27
14
  "engines": {
28
15
  "node": ">=18"
29
16
  },
@@ -34,21 +21,7 @@
34
21
  "opentelemetry",
35
22
  "tls"
36
23
  ],
37
- "publishConfig": {
38
- "registry": "https://registry.npmjs.org/",
39
- "access": "public"
40
- },
41
24
  "dependencies": {
42
25
  "@volcengine/openapi": "^1.36.1"
43
- },
44
- "devDependencies": {
45
- "@rslib/core": "^0.21.5",
46
- "@swc/core": "1.15.41",
47
- "@swc/jest": "0.2.39",
48
- "@types/jest": "^30.0.0",
49
- "@types/node": "^24.10.9",
50
- "@volcengine/tls-observer-shared": "workspace:*",
51
- "jest": "30.4.2",
52
- "typescript": "^6.0.3"
53
26
  }
54
- }
27
+ }