@pdpp/local-collector 0.7.7 → 0.7.9
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,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createReadStream, statSync } from "node:fs";
|
|
3
|
-
import { readdir,
|
|
3
|
+
import { readdir, stat } from "node:fs/promises";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { basename, join } from "node:path";
|
|
6
6
|
import { createInterface as createFileReader } from "node:readline";
|
|
@@ -379,6 +379,10 @@ function markFileMtimeAndShouldSkip(fileMtimes, newMtimes, path, mtime) {
|
|
|
379
379
|
newMtimes[path] = mtime;
|
|
380
380
|
return fileMtimes[path] === mtime;
|
|
381
381
|
}
|
|
382
|
+
async function readBoundedUtf8(path) {
|
|
383
|
+
const preview = await readBoundedFilePreview(path);
|
|
384
|
+
return preview?.buffer.toString("utf8") ?? null;
|
|
385
|
+
}
|
|
382
386
|
async function emitSkills({ claudeHome, requested, emitRecord, fileMtimes, newMtimes }) {
|
|
383
387
|
if (!requested.has("skills")) {
|
|
384
388
|
return;
|
|
@@ -411,11 +415,14 @@ async function emitSkills({ claudeHome, requested, emitRecord, fileMtimes, newMt
|
|
|
411
415
|
continue;
|
|
412
416
|
}
|
|
413
417
|
try {
|
|
414
|
-
raw = await
|
|
418
|
+
raw = await readBoundedUtf8(skillPath);
|
|
415
419
|
}
|
|
416
420
|
catch {
|
|
417
421
|
continue;
|
|
418
422
|
}
|
|
423
|
+
if (raw === null) {
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
419
426
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
420
427
|
await emitRecord("skills", buildSkillRecord({ name: ent.name, frontmatter, body, path: skillPath, mtimeMs: st.mtimeMs }));
|
|
421
428
|
}
|
|
@@ -436,11 +443,14 @@ async function processSlashCommandFile(args) {
|
|
|
436
443
|
return;
|
|
437
444
|
}
|
|
438
445
|
try {
|
|
439
|
-
raw = await
|
|
446
|
+
raw = await readBoundedUtf8(args.full);
|
|
440
447
|
}
|
|
441
448
|
catch {
|
|
442
449
|
return;
|
|
443
450
|
}
|
|
451
|
+
if (raw === null) {
|
|
452
|
+
return;
|
|
453
|
+
}
|
|
444
454
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
445
455
|
const base = basename(args.name, ".md");
|
|
446
456
|
const idPath = args.prefix ? `${args.prefix}/${base}` : base;
|
|
@@ -495,11 +505,14 @@ async function emitProjectMemoryNotes({ emitRecord, fileMtimes, newMtimes, proje
|
|
|
495
505
|
continue;
|
|
496
506
|
}
|
|
497
507
|
try {
|
|
498
|
-
raw = await
|
|
508
|
+
raw = await readBoundedUtf8(fullPath);
|
|
499
509
|
}
|
|
500
510
|
catch {
|
|
501
511
|
continue;
|
|
502
512
|
}
|
|
513
|
+
if (raw === null) {
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
503
516
|
const { frontmatter, body } = parseFrontmatter(raw);
|
|
504
517
|
await emitRecord("memory_notes", buildMemoryNoteRecord({ projectDir, relPath, frontmatter, body, path: fullPath, mtimeMs: st.mtimeMs }));
|
|
505
518
|
}
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
|
-
import { createReadStream,
|
|
4
|
-
import { readdir,
|
|
3
|
+
import { createReadStream, statSync } from "node:fs";
|
|
4
|
+
import { readdir, stat } from "node:fs/promises";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
import { createInterface } from "node:readline";
|
|
8
8
|
import { DatabaseSync } from "node:sqlite";
|
|
9
|
+
import { readBoundedFilePreview } from "../../src/bounded-file-preview.js";
|
|
9
10
|
import { flushAndExitAfterRuntimeAck } from "../../src/connector-exit.js";
|
|
10
11
|
import { openCarryForwardCursor } from "../../src/fingerprint-cursor.js";
|
|
11
12
|
import { isMainModule } from "../../src/is-main-module.js";
|
|
@@ -17,6 +18,7 @@ import { validateRecord } from "./schemas.js";
|
|
|
17
18
|
const DEFAULT_ACTIVE_ROLLOUT_QUIET_MS = 120_000;
|
|
18
19
|
const ACTIVE_ROLLOUT_QUIET_MS_ENV = "PDPP_CODEX_ACTIVE_ROLLOUT_QUIET_MS";
|
|
19
20
|
const GUARD_PREFIX_BYTES = 64 * 1024;
|
|
21
|
+
const MAX_PENDING_FUNCTION_CALLS = 1024;
|
|
20
22
|
let stdoutDrainPromise = null;
|
|
21
23
|
const emit = (m) => {
|
|
22
24
|
const ok = process.stdout.write(stringifyForJsonl(m));
|
|
@@ -270,46 +272,32 @@ function openThreadsDb(dbPath) {
|
|
|
270
272
|
return null;
|
|
271
273
|
}
|
|
272
274
|
}
|
|
273
|
-
function
|
|
275
|
+
function isThreadRow(row) {
|
|
276
|
+
return typeof row === "object" && row !== null && typeof row.id === "string";
|
|
277
|
+
}
|
|
278
|
+
function* queryThreadsRows(db) {
|
|
274
279
|
try {
|
|
275
|
-
const
|
|
276
|
-
|
|
280
|
+
for (const row of db.prepare(THREADS_QUERY).iterate()) {
|
|
281
|
+
if (isThreadRow(row)) {
|
|
282
|
+
yield row;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
277
285
|
}
|
|
278
286
|
catch {
|
|
279
287
|
emit({
|
|
280
288
|
type: "PROGRESS",
|
|
281
289
|
message: "Codex phase=index pass=index state_db_query_failed=true fallback=rollouts_only",
|
|
282
290
|
});
|
|
283
|
-
return [];
|
|
284
291
|
}
|
|
285
292
|
}
|
|
286
|
-
function loadThreadsMap(dbPath) {
|
|
287
|
-
if (!existsSync(dbPath)) {
|
|
288
|
-
return { map: new Map(), present: false };
|
|
289
|
-
}
|
|
290
|
-
const db = openThreadsDb(dbPath);
|
|
291
|
-
if (!db) {
|
|
292
|
-
return { map: new Map(), present: false };
|
|
293
|
-
}
|
|
294
|
-
const map = new Map();
|
|
295
|
-
try {
|
|
296
|
-
for (const r of queryThreadsRows(db)) {
|
|
297
|
-
map.set(r.id, r);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
finally {
|
|
301
|
-
try {
|
|
302
|
-
db.close();
|
|
303
|
-
}
|
|
304
|
-
catch {
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return { map, present: true };
|
|
308
|
-
}
|
|
309
293
|
async function statAndRead(path) {
|
|
310
294
|
try {
|
|
311
295
|
const st = await stat(path);
|
|
312
|
-
const
|
|
296
|
+
const preview = await readBoundedFilePreview(path);
|
|
297
|
+
if (preview === null) {
|
|
298
|
+
return null;
|
|
299
|
+
}
|
|
300
|
+
const text = preview.buffer.toString("utf8");
|
|
313
301
|
return { mtimeMs: Number(st.mtimeMs), size: Number(st.size), text };
|
|
314
302
|
}
|
|
315
303
|
catch {
|
|
@@ -428,12 +416,21 @@ function emitMessageRecord(state, payload, ts, emitRecord) {
|
|
|
428
416
|
timestamp: ts,
|
|
429
417
|
});
|
|
430
418
|
}
|
|
431
|
-
function registerFunctionCall(state, payload, ts) {
|
|
419
|
+
function registerFunctionCall(state, payload, ts, emitRecord) {
|
|
432
420
|
const sessionId = state.sessionId;
|
|
433
421
|
if (!sessionId) {
|
|
434
422
|
return;
|
|
435
423
|
}
|
|
436
424
|
const callId = payload.call_id || `${sessionId}:${state.lineCount}`;
|
|
425
|
+
while (state.pendingCalls.size >= MAX_PENDING_FUNCTION_CALLS) {
|
|
426
|
+
const oldestEntry = state.pendingCalls.entries().next();
|
|
427
|
+
if (oldestEntry.done) {
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
const [oldestCallId, oldest] = oldestEntry.value;
|
|
431
|
+
emitRecord("function_calls", oldest);
|
|
432
|
+
state.pendingCalls.delete(oldestCallId);
|
|
433
|
+
}
|
|
437
434
|
state.pendingCalls.set(callId, {
|
|
438
435
|
id: callId,
|
|
439
436
|
session_id: sessionId,
|
|
@@ -485,7 +482,7 @@ export function processResponseItem({ deps, payload, state, ts }) {
|
|
|
485
482
|
if (payload.type === "function_call") {
|
|
486
483
|
state.functionCallCount++;
|
|
487
484
|
if (deps.requested.has("function_calls")) {
|
|
488
|
-
registerFunctionCall(state, payload, ts);
|
|
485
|
+
registerFunctionCall(state, payload, ts, deps.emitRecord);
|
|
489
486
|
}
|
|
490
487
|
return;
|
|
491
488
|
}
|
|
@@ -575,6 +572,20 @@ export function emitSessionsFromMaps({ threadsMap, rolloutAggregates, emitRecord
|
|
|
575
572
|
emitRecord("sessions", buildRolloutOnlySessionRecord(id, agg));
|
|
576
573
|
}
|
|
577
574
|
}
|
|
575
|
+
function emitSessionsFromRows({ threadsRows, rolloutAggregates, emitRecord, cursor }) {
|
|
576
|
+
for (const t of threadsRows) {
|
|
577
|
+
const agg = rolloutAggregates.get(t.id);
|
|
578
|
+
rolloutAggregates.delete(t.id);
|
|
579
|
+
const prior = cursor?.prior(t.id);
|
|
580
|
+
if (shouldReemitThreadSession(t, agg, prior)) {
|
|
581
|
+
emitRecord("sessions", buildThreadSessionRecord(t.id, t, agg, prior));
|
|
582
|
+
}
|
|
583
|
+
cursor?.note(t.id, makeThreadFingerprint(t, agg, prior));
|
|
584
|
+
}
|
|
585
|
+
for (const [id, agg] of rolloutAggregates) {
|
|
586
|
+
emitRecord("sessions", buildRolloutOnlySessionRecord(id, agg));
|
|
587
|
+
}
|
|
588
|
+
}
|
|
578
589
|
async function parseRolloutFile(args) {
|
|
579
590
|
const state = makeRolloutParseState(args.seed);
|
|
580
591
|
const deps = {
|
|
@@ -754,13 +765,24 @@ async function scanRollouts(args) {
|
|
|
754
765
|
return { parsedFiles: parsedRollouts };
|
|
755
766
|
}
|
|
756
767
|
function emitSessions({ stateDbPath, rolloutAggregates, emitRecord, cursor }) {
|
|
757
|
-
const
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
}
|
|
768
|
+
const db = openThreadsDb(stateDbPath);
|
|
769
|
+
if (!db) {
|
|
770
|
+
for (const [id, agg] of rolloutAggregates) {
|
|
771
|
+
emitRecord("sessions", buildRolloutOnlySessionRecord(id, agg));
|
|
772
|
+
}
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
try {
|
|
776
|
+
emitSessionsFromRows({
|
|
777
|
+
threadsRows: queryThreadsRows(db),
|
|
778
|
+
rolloutAggregates,
|
|
779
|
+
emitRecord,
|
|
780
|
+
cursor,
|
|
781
|
+
});
|
|
782
|
+
}
|
|
783
|
+
finally {
|
|
784
|
+
db.close();
|
|
785
|
+
}
|
|
764
786
|
}
|
|
765
787
|
async function readStartMessage() {
|
|
766
788
|
const rl = createInterface({ input: process.stdin, terminal: false });
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const COLLECTOR_BUILD_SOURCE_SENTINEL = "source";
|
|
2
2
|
const COLLECTOR_BUILD_INFO = {
|
|
3
|
-
builtAt: "2026-06-
|
|
4
|
-
revision: "
|
|
5
|
-
version: "0.7.
|
|
3
|
+
builtAt: "2026-06-17T18:00:24.313Z",
|
|
4
|
+
revision: "e5531179a760",
|
|
5
|
+
version: "0.7.9",
|
|
6
6
|
};
|
|
7
7
|
function buildAgentVersion(info = COLLECTOR_BUILD_INFO) {
|
|
8
8
|
return `${info.version}+${info.revision}`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pdpp/local-collector",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.9",
|
|
4
4
|
"description": "Publishable local collector runtime for PDPP: filesystem-class connectors (Claude Code, Codex) plus the device-exporter ingest client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|