@pdpp/local-collector 0.1.0-beta.6 → 0.1.0-beta.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/dist/local-collector/bin/pdpp-local-collector.js +580 -22
- package/dist/local-collector/src/runner.d.ts +1 -1
- package/dist/local-collector/src/runner.js +15 -1
- package/dist/polyfill-connectors/connectors/claude_code/index.js +85 -48
- package/dist/polyfill-connectors/connectors/codex/index.js +390 -108
- package/dist/polyfill-connectors/connectors/codex/parsers.js +5 -3
- package/dist/polyfill-connectors/src/bounded-file-preview.js +76 -0
- package/dist/polyfill-connectors/src/browser-handoff.js +38 -5
- package/dist/polyfill-connectors/src/collector-build-info.d.ts +8 -0
- package/dist/polyfill-connectors/src/collector-build-info.js +10 -0
- package/dist/polyfill-connectors/src/collector-runner.d.ts +54 -0
- package/dist/polyfill-connectors/src/collector-runner.js +250 -18
- package/dist/polyfill-connectors/src/connector-exit.js +62 -0
- package/dist/polyfill-connectors/src/connector-runtime-protocol.d.ts +41 -21
- package/dist/polyfill-connectors/src/connector-runtime.js +241 -30
- package/dist/polyfill-connectors/src/fingerprint-cursor.js +107 -0
- package/dist/polyfill-connectors/src/local-device-client.d.ts +17 -0
- package/dist/polyfill-connectors/src/local-device-client.js +69 -9
- package/dist/polyfill-connectors/src/local-device-outbox.d.ts +59 -0
- package/dist/polyfill-connectors/src/local-device-outbox.js +394 -5
- package/dist/polyfill-connectors/src/local-source-inventory.js +8 -1
- package/dist/polyfill-connectors/src/runner/index.d.ts +4 -3
- package/dist/polyfill-connectors/src/runner/index.js +4 -3
- package/dist/polyfill-connectors/src/safe-text-preview.js +13 -0
- package/dist/polyfill-connectors/src/static-secret-injection.js +155 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type RuntimeCapabilityProfile } from "../../polyfill-connectors/src/runner/index.js";
|
|
2
|
-
export { buildCollectorStartMessage, COLLECTOR_PROTOCOL_VERSION, CollectorStateReadError, drainCollectorQueue, emitToStdout, enrollCollector, evaluatePlacement, isMainModule, LocalDeviceClient, LocalDeviceHttpError, LocalDeviceOutbox, LocalDeviceQueue, PROVIDER_RUNTIME_CAPABILITIES, RUNTIME_CAPABILITY_MISMATCH_CODE, RuntimeCapabilityMismatchError, assertPlacementOrThrow, buildLocalDeviceRecordEnvelope, buildLocalDeviceOutboxId, canonicalJson, diffRequiredBindings, hashCanonicalJson, parseJsonlLine, resourceSet, runCollectorConnector, stringifyForJsonl, transformRecordsToCollectorEnvelopes, type CollectorChildContext, type CollectorConnectorSpec, type CollectorEnrollmentConfig, type CollectorRunConfig, type CollectorRunResult, type ConnectorPlacementInput, type ConnectorRuntimeRequirements, type EmittedMessage, type EnrollmentExchangeResponse, type LocalDeviceRecordEnvelope, type BuildLocalDeviceOutboxIdInput, type LocalDeviceOutboxClaimInput, type LocalDeviceOutboxDeadLetterInput, type LocalDeviceOutboxEnqueueInput, type LocalDeviceOutboxFailInput, type LocalDeviceOutboxItem, type LocalDeviceOutboxKind, type LocalDeviceOutboxLeaseInput, type LocalDeviceOutboxOptions, type LocalDeviceOutboxStatus, type LocalDeviceOutboxSummary, type PlacementDecision, type RuntimeBindingName, type RuntimeCapabilityProfile, type StartMessage, type StreamScope, } from "../../polyfill-connectors/src/runner/index.js";
|
|
2
|
+
export { buildCollectorStartMessage, COLLECTOR_COVERAGE_STATUSES, COLLECTOR_PROTOCOL_VERSION, CollectorStateReadError, drainCollectorQueue, emitToStdout, enrollCollector, evaluatePlacement, isMainModule, LocalDeviceClient, LocalDeviceHttpError, LocalDeviceOutbox, LocalDeviceQueue, PROVIDER_RUNTIME_CAPABILITIES, RUNTIME_CAPABILITY_MISMATCH_CODE, RuntimeCapabilityMismatchError, assertPlacementOrThrow, buildLocalDeviceRecordEnvelope, buildLocalDeviceOutboxId, canonicalJson, classifyDeadLetterError, deriveLocalCollectorLifecycleState, diffRequiredBindings, hashCanonicalJson, LOCAL_COLLECTOR_LIFECYCLE_STATES, parseJsonlLine, resourceSet, runCollectorConnector, stringifyForJsonl, summarizeCollectorCompleteness, transformRecordsToCollectorEnvelopes, type CollectorChildContext, type CollectorCompletenessSummary, type CollectorConnectorSpec, type CollectorCoverageStatus, type CollectorEnrollmentConfig, type CollectorRunConfig, type CollectorRunResult, type ConnectorPlacementInput, type ConnectorRuntimeRequirements, type EmittedMessage, type EnrollmentExchangeResponse, type LocalCollectorLifecycleInput, type LocalCollectorLifecycleState, type LocalDeviceRecordEnvelope, type BuildLocalDeviceOutboxIdInput, type LocalDeviceOutboxClaimInput, type LocalDeviceOutboxCompactResult, type LocalDeviceOutboxDeadLetterErrorClass, type LocalDeviceOutboxDeadLetterErrorSummary, type LocalDeviceOutboxDeadLetterErrorSummaryInput, type LocalDeviceOutboxDeadLetterInput, type LocalDeviceOutboxEnqueueInput, type LocalDeviceOutboxFailInput, type LocalDeviceOutboxItem, type LocalDeviceOutboxKind, type LocalDeviceOutboxLeaseInput, type LocalDeviceOutboxOptions, type LocalDeviceOutboxPageStats, type LocalDeviceOutboxPruneSentInput, type LocalDeviceOutboxPruneSentResult, type LocalDeviceOutboxRequeueDeadLettersInput, type LocalDeviceOutboxRequeueDeadLettersResult, type LocalDeviceOutboxStatus, type LocalDeviceOutboxSummary, type PlacementDecision, type RuntimeBindingName, type RuntimeCapabilityProfile, type StartMessage, type StreamScope, } from "../../polyfill-connectors/src/runner/index.js";
|
|
3
3
|
export declare const COLLECTOR_RUNTIME_CAPABILITIES: RuntimeCapabilityProfile;
|
|
4
4
|
export interface BundledConnectorEntry {
|
|
5
5
|
readonly connector_id: string;
|
|
@@ -2,7 +2,7 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { extname } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { COLLECTOR_PROTOCOL_VERSION as PROTOCOL_VERSION, COLLECTOR_RUNTIME_CAPABILITIES as POLYFILL_COLLECTOR_RUNTIME_CAPABILITIES, } from "../../polyfill-connectors/src/runner/index.js";
|
|
5
|
-
export { buildCollectorStartMessage, COLLECTOR_PROTOCOL_VERSION, CollectorStateReadError, drainCollectorQueue, emitToStdout, enrollCollector, evaluatePlacement, isMainModule, LocalDeviceClient, LocalDeviceHttpError, LocalDeviceOutbox, LocalDeviceQueue, PROVIDER_RUNTIME_CAPABILITIES, RUNTIME_CAPABILITY_MISMATCH_CODE, RuntimeCapabilityMismatchError, assertPlacementOrThrow, buildLocalDeviceRecordEnvelope, buildLocalDeviceOutboxId, canonicalJson, diffRequiredBindings, hashCanonicalJson, parseJsonlLine, resourceSet, runCollectorConnector, stringifyForJsonl, transformRecordsToCollectorEnvelopes, } from "../../polyfill-connectors/src/runner/index.js";
|
|
5
|
+
export { buildCollectorStartMessage, COLLECTOR_COVERAGE_STATUSES, COLLECTOR_PROTOCOL_VERSION, CollectorStateReadError, drainCollectorQueue, emitToStdout, enrollCollector, evaluatePlacement, isMainModule, LocalDeviceClient, LocalDeviceHttpError, LocalDeviceOutbox, LocalDeviceQueue, PROVIDER_RUNTIME_CAPABILITIES, RUNTIME_CAPABILITY_MISMATCH_CODE, RuntimeCapabilityMismatchError, assertPlacementOrThrow, buildLocalDeviceRecordEnvelope, buildLocalDeviceOutboxId, canonicalJson, classifyDeadLetterError, deriveLocalCollectorLifecycleState, diffRequiredBindings, hashCanonicalJson, LOCAL_COLLECTOR_LIFECYCLE_STATES, parseJsonlLine, resourceSet, runCollectorConnector, stringifyForJsonl, summarizeCollectorCompleteness, transformRecordsToCollectorEnvelopes, } from "../../polyfill-connectors/src/runner/index.js";
|
|
6
6
|
export const COLLECTOR_RUNTIME_CAPABILITIES = {
|
|
7
7
|
id: POLYFILL_COLLECTOR_RUNTIME_CAPABILITIES.id,
|
|
8
8
|
bindings: new Set(["network", "filesystem", "local_device"]),
|
|
@@ -32,6 +32,13 @@ export const BUNDLED_CONNECTORS = Object.freeze({
|
|
|
32
32
|
"memory_notes",
|
|
33
33
|
"skills",
|
|
34
34
|
"slash_commands",
|
|
35
|
+
"file_history",
|
|
36
|
+
"cache_inventory",
|
|
37
|
+
"coverage_diagnostics",
|
|
38
|
+
"debug_artifacts",
|
|
39
|
+
"downloads",
|
|
40
|
+
"backup_inventory",
|
|
41
|
+
"config_inventory",
|
|
35
42
|
]),
|
|
36
43
|
}),
|
|
37
44
|
codex: Object.freeze({
|
|
@@ -46,6 +53,13 @@ export const BUNDLED_CONNECTORS = Object.freeze({
|
|
|
46
53
|
"rules",
|
|
47
54
|
"prompts",
|
|
48
55
|
"skills",
|
|
56
|
+
"history",
|
|
57
|
+
"session_index",
|
|
58
|
+
"logs",
|
|
59
|
+
"shell_snapshots",
|
|
60
|
+
"config_inventory",
|
|
61
|
+
"cache_inventory",
|
|
62
|
+
"coverage_diagnostics",
|
|
49
63
|
]),
|
|
50
64
|
}),
|
|
51
65
|
});
|
|
@@ -4,9 +4,10 @@ import { readdir, readFile, 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";
|
|
7
|
+
import { readBoundedFilePreview } from "../../src/bounded-file-preview.js";
|
|
7
8
|
import { runConnector } from "../../src/connector-runtime.js";
|
|
8
9
|
import { isMainModule } from "../../src/is-main-module.js";
|
|
9
|
-
import { buildLocalSourceInventory, listDirectoryInventory, } from "../../src/local-source-inventory.js";
|
|
10
|
+
import { buildLocalSourceInventory, listDirectoryInventory, openInventoryFingerprintCursor, } from "../../src/local-source-inventory.js";
|
|
10
11
|
import { safeTextPreview } from "../../src/safe-text-preview.js";
|
|
11
12
|
import { ATTACHMENT_PREVIEW_CHARS, applyProjectDirScope, BYTES_PER_MB, buildMemoryNoteRecord, buildSkillRecord, buildSlashCommandRecord, extractContent, LINE_PROGRESS_INTERVAL, MESSAGE_CONTENT_PREVIEW_CHARS, makeEmptySessionAccumulator, mergeSessionObservations, parseCsvEnv, parseFrontmatter, SESSION_DIR_PREFIX_RE, TOOL_RESULT_PREVIEW_CHARS, textPreview, widenSessionTimeRange, } from "./parsers.js";
|
|
12
13
|
import { validateRecord } from "./schemas.js";
|
|
@@ -148,6 +149,17 @@ export function observeJsonlFields(obj, obs, forcedSessionId) {
|
|
|
148
149
|
}
|
|
149
150
|
}
|
|
150
151
|
}
|
|
152
|
+
function updateSessionAccumulatorFromCurrentLine(sessionAccumulators, projectDir, obs, obj, messageCountDelta) {
|
|
153
|
+
if (!obs.sessionId) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
updateSessionAccumulator(sessionAccumulators, projectDir, {
|
|
157
|
+
...obs,
|
|
158
|
+
firstTimestamp: obj.timestamp ?? null,
|
|
159
|
+
lastTimestamp: obj.timestamp ?? null,
|
|
160
|
+
messageCount: messageCountDelta,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
151
163
|
export function isMessageType(type) {
|
|
152
164
|
return type === "user" || type === "assistant";
|
|
153
165
|
}
|
|
@@ -211,16 +223,13 @@ export async function emitSessionsFromAccumulators({ emitRecord, requested, sess
|
|
|
211
223
|
await emitRecord("sessions", { ...session });
|
|
212
224
|
}
|
|
213
225
|
}
|
|
214
|
-
async function emitToolResultFile(args) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
buf = await readFile(args.full, "utf8");
|
|
218
|
-
}
|
|
219
|
-
catch {
|
|
226
|
+
export async function emitToolResultFile(args) {
|
|
227
|
+
const bounded = await readBoundedFilePreview(args.full);
|
|
228
|
+
if (bounded === null) {
|
|
220
229
|
return;
|
|
221
230
|
}
|
|
222
231
|
const rel = args.full.slice(args.toolResultsDir.length + 1);
|
|
223
|
-
const previewResult = safeTextPreview(
|
|
232
|
+
const previewResult = safeTextPreview(bounded.buffer, TOOL_RESULT_PREVIEW_CHARS);
|
|
224
233
|
await args.emitRecord("attachments", {
|
|
225
234
|
id: `tool_result_file:${args.projectDir}/${args.sessionId}/${rel}`,
|
|
226
235
|
session_id: args.sessionId,
|
|
@@ -354,14 +363,15 @@ async function parseJsonlFile(args) {
|
|
|
354
363
|
if (!buildOnly && lineCount % LINE_PROGRESS_INTERVAL === 0) {
|
|
355
364
|
await emit({
|
|
356
365
|
type: "PROGRESS",
|
|
357
|
-
message: `
|
|
366
|
+
message: `Claude Code phase=emit pass=emit lines_parsed=${lineCount}`,
|
|
358
367
|
});
|
|
359
368
|
}
|
|
369
|
+
const messageCountBeforeLine = obs.messageCount;
|
|
360
370
|
observeJsonlFields(obj, obs, forcedSessionId);
|
|
361
371
|
await processJsonlLine({ buildOnly, deps: { emitRecord, requested }, obj, obs });
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
372
|
+
if (buildOnly) {
|
|
373
|
+
updateSessionAccumulatorFromCurrentLine(sessionAccumulators, projectDir, obs, obj, obs.messageCount - messageCountBeforeLine);
|
|
374
|
+
}
|
|
365
375
|
}
|
|
366
376
|
return obs.sessionId;
|
|
367
377
|
}
|
|
@@ -494,7 +504,7 @@ async function emitProjectMemoryNotes({ emitRecord, fileMtimes, newMtimes, proje
|
|
|
494
504
|
await emitRecord("memory_notes", buildMemoryNoteRecord({ projectDir, relPath, frontmatter, body, path: fullPath, mtimeMs: st.mtimeMs }));
|
|
495
505
|
}
|
|
496
506
|
}
|
|
497
|
-
async function processJsonlFile({ args, forcedSessionId, path,
|
|
507
|
+
async function processJsonlFile({ args, forcedSessionId, path, projectDir }) {
|
|
498
508
|
let st;
|
|
499
509
|
try {
|
|
500
510
|
st = statSync(path);
|
|
@@ -509,7 +519,7 @@ async function processJsonlFile({ args, forcedSessionId, path, progressLabel, pr
|
|
|
509
519
|
}
|
|
510
520
|
await args.emit({
|
|
511
521
|
type: "PROGRESS",
|
|
512
|
-
message:
|
|
522
|
+
message: `Claude Code phase=${args.buildOnly ? "index" : "emit"} pass=${args.buildOnly ? "index" : "emit"} file_size_mb=${(st.size / BYTES_PER_MB).toFixed(1)}`,
|
|
513
523
|
});
|
|
514
524
|
await parseJsonlFile({
|
|
515
525
|
buildOnly: args.buildOnly,
|
|
@@ -530,7 +540,6 @@ async function processTopLevelJsonl(entries, projectPath, projectDir, args) {
|
|
|
530
540
|
args,
|
|
531
541
|
forcedSessionId: null,
|
|
532
542
|
path: join(projectPath, f),
|
|
533
|
-
progressLabel: `${projectDir}/${f}`,
|
|
534
543
|
projectDir,
|
|
535
544
|
});
|
|
536
545
|
}
|
|
@@ -549,7 +558,6 @@ async function processSessionDir(sessEnt, projectPath, projectDir, args) {
|
|
|
549
558
|
args,
|
|
550
559
|
forcedSessionId: sessionId,
|
|
551
560
|
path: join(subagentsDir, f),
|
|
552
|
-
progressLabel: `${projectDir}/${sessionId}/subagents/${f}`,
|
|
553
561
|
projectDir,
|
|
554
562
|
});
|
|
555
563
|
}
|
|
@@ -594,13 +602,12 @@ async function listProjectDirs(baseDir, emit) {
|
|
|
594
602
|
try {
|
|
595
603
|
projectDirs = (await readdir(baseDir)).filter((name) => !name.startsWith("."));
|
|
596
604
|
}
|
|
597
|
-
catch
|
|
598
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
605
|
+
catch {
|
|
599
606
|
await emit({
|
|
600
607
|
type: "SKIP_RESULT",
|
|
601
608
|
stream: "sessions",
|
|
602
609
|
reason: "claude_dir_not_found",
|
|
603
|
-
message:
|
|
610
|
+
message: "Claude Code projects directory not readable",
|
|
604
611
|
});
|
|
605
612
|
return null;
|
|
606
613
|
}
|
|
@@ -613,9 +620,10 @@ export async function scanProjectDirs(args) {
|
|
|
613
620
|
if (projectDirs === null) {
|
|
614
621
|
return;
|
|
615
622
|
}
|
|
623
|
+
const totalProjectDirs = projectDirs.length;
|
|
616
624
|
await args.emit({
|
|
617
625
|
type: "PROGRESS",
|
|
618
|
-
message:
|
|
626
|
+
message: `Claude Code phase=index pass=index total_project_dirs=${totalProjectDirs}`,
|
|
619
627
|
});
|
|
620
628
|
for (const projectDir of projectDirs) {
|
|
621
629
|
await scanProjectDir(projectDir, args);
|
|
@@ -649,15 +657,40 @@ async function assertRequestedClaudeSources(input) {
|
|
|
649
657
|
throw new Error(`requested Claude Code local source path(s) are missing or unreadable: ${missing.join(", ")}`);
|
|
650
658
|
}
|
|
651
659
|
}
|
|
660
|
+
async function emitCoverageDiagnostics(input) {
|
|
661
|
+
if (!input.requested.has("coverage_diagnostics")) {
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
for (const record of input.inventory.coverage) {
|
|
665
|
+
await input.emitRecord("coverage_diagnostics", record);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
async function emitGatedInventoryStream(input) {
|
|
669
|
+
const cursor = openInventoryFingerprintCursor(input.priorState);
|
|
670
|
+
for (const record of input.records) {
|
|
671
|
+
if (cursor.shouldEmit(record)) {
|
|
672
|
+
await input.emitRecord(input.stream, record);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
cursor.pruneStale();
|
|
676
|
+
const inventoryCursor = { fetched_at: nowIso() };
|
|
677
|
+
if (cursor.size() > 0) {
|
|
678
|
+
inventoryCursor.fingerprints = cursor.toState();
|
|
679
|
+
}
|
|
680
|
+
await input.emit({ type: "STATE", stream: input.stream, cursor: inventoryCursor });
|
|
681
|
+
}
|
|
652
682
|
async function emitLocalInventoryStreams(input) {
|
|
653
|
-
const
|
|
654
|
-
for (const [stream, records] of inventory.recordsByStream) {
|
|
683
|
+
for (const [stream, records] of input.inventory.recordsByStream) {
|
|
655
684
|
if (!input.requested.has(stream)) {
|
|
656
685
|
continue;
|
|
657
686
|
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
687
|
+
await emitGatedInventoryStream({
|
|
688
|
+
emit: input.emit,
|
|
689
|
+
emitRecord: input.emitRecord,
|
|
690
|
+
priorState: input.state[stream],
|
|
691
|
+
records,
|
|
692
|
+
stream,
|
|
693
|
+
});
|
|
661
694
|
}
|
|
662
695
|
if (input.requested.has("file_history")) {
|
|
663
696
|
const records = await listDirectoryInventory({
|
|
@@ -668,14 +701,13 @@ async function emitLocalInventoryStreams(input) {
|
|
|
668
701
|
stream: "file_history",
|
|
669
702
|
reason: "metadata-only until payload contract is approved",
|
|
670
703
|
});
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
}
|
|
704
|
+
await emitGatedInventoryStream({
|
|
705
|
+
emit: input.emit,
|
|
706
|
+
emitRecord: input.emitRecord,
|
|
707
|
+
priorState: input.state.file_history,
|
|
708
|
+
records,
|
|
709
|
+
stream: "file_history",
|
|
710
|
+
});
|
|
679
711
|
}
|
|
680
712
|
}
|
|
681
713
|
async function runSkillsAndCommands(claudeHome, requested, emit, emitRecord, state) {
|
|
@@ -688,9 +720,8 @@ async function runSkillsAndCommands(claudeHome, requested, emit, emitRecord, sta
|
|
|
688
720
|
newMtimes: state.newSkillsMtimes,
|
|
689
721
|
});
|
|
690
722
|
}
|
|
691
|
-
catch
|
|
692
|
-
|
|
693
|
-
await emit({ type: "PROGRESS", message: `skills scan skipped: ${msg}` });
|
|
723
|
+
catch {
|
|
724
|
+
await emit({ type: "PROGRESS", message: "Claude Code phase=index pass=index stream=skills scan_skipped=true" });
|
|
694
725
|
}
|
|
695
726
|
try {
|
|
696
727
|
await emitSlashCommands({
|
|
@@ -701,9 +732,11 @@ async function runSkillsAndCommands(claudeHome, requested, emit, emitRecord, sta
|
|
|
701
732
|
newMtimes: state.newSlashCommandMtimes,
|
|
702
733
|
});
|
|
703
734
|
}
|
|
704
|
-
catch
|
|
705
|
-
|
|
706
|
-
|
|
735
|
+
catch {
|
|
736
|
+
await emit({
|
|
737
|
+
type: "PROGRESS",
|
|
738
|
+
message: "Claude Code phase=index pass=index stream=slash_commands scan_skipped=true",
|
|
739
|
+
});
|
|
707
740
|
}
|
|
708
741
|
if (requested.has("skills")) {
|
|
709
742
|
await emit({
|
|
@@ -730,16 +763,19 @@ if (isMainModule(import.meta.url)) {
|
|
|
730
763
|
async collect({ state, requested, emit, emitRecord }) {
|
|
731
764
|
const claudeHome = process.env.CLAUDE_CODE_HOME || join(homedir(), ".claude");
|
|
732
765
|
const baseDir = process.env.CLAUDE_CODE_PROJECTS_DIR || join(claudeHome, "projects");
|
|
766
|
+
const inventory = await buildLocalSourceInventory("claude_code", claudeHome, CLAUDE_CODE_KNOWN_LOCAL_STORES);
|
|
767
|
+
await emitCoverageDiagnostics({ emitRecord, inventory, requested });
|
|
733
768
|
await assertRequestedClaudeSources({ baseDir, claudeHome, requested });
|
|
734
769
|
const typedState = state;
|
|
735
|
-
const
|
|
770
|
+
const messageFileMtimes = streamFileMtimes(typedState, "messages") ?? typedState.file_mtimes ?? {};
|
|
771
|
+
const sessionFileMtimes = streamFileMtimes(typedState, "sessions") ?? {};
|
|
736
772
|
const skillsMtimes = streamFileMtimes(typedState, "skills") ?? {};
|
|
737
773
|
const slashCommandMtimes = streamFileMtimes(typedState, "slash_commands") ?? {};
|
|
738
774
|
const memoryNoteMtimes = streamFileMtimes(typedState, "memory_notes") ?? {};
|
|
739
775
|
const newSkillsMtimes = { ...skillsMtimes };
|
|
740
776
|
const newSlashCommandMtimes = { ...slashCommandMtimes };
|
|
741
777
|
const newMemoryNoteMtimes = { ...memoryNoteMtimes };
|
|
742
|
-
await emitLocalInventoryStreams({ claudeHome,
|
|
778
|
+
await emitLocalInventoryStreams({ claudeHome, emit, emitRecord, inventory, requested, state: typedState });
|
|
743
779
|
await runSkillsAndCommands(claudeHome, requested, emit, emitRecord, {
|
|
744
780
|
skillsMtimes,
|
|
745
781
|
newSkillsMtimes,
|
|
@@ -753,15 +789,16 @@ if (isMainModule(import.meta.url)) {
|
|
|
753
789
|
if (!needsProjects) {
|
|
754
790
|
return;
|
|
755
791
|
}
|
|
756
|
-
const
|
|
792
|
+
const newMessageFileMtimes = { ...messageFileMtimes };
|
|
793
|
+
const newSessionFileMtimes = { ...sessionFileMtimes };
|
|
757
794
|
const sessionAccumulators = new Map();
|
|
758
795
|
await scanProjectDirs({
|
|
759
796
|
baseDir,
|
|
760
797
|
buildOnly: true,
|
|
761
798
|
emit,
|
|
762
799
|
emitRecord,
|
|
763
|
-
fileMtimes,
|
|
764
|
-
newMtimes,
|
|
800
|
+
fileMtimes: sessionFileMtimes,
|
|
801
|
+
newMtimes: newSessionFileMtimes,
|
|
765
802
|
memoryNoteMtimes,
|
|
766
803
|
newMemoryNoteMtimes,
|
|
767
804
|
requested,
|
|
@@ -772,7 +809,7 @@ if (isMainModule(import.meta.url)) {
|
|
|
772
809
|
await emit({
|
|
773
810
|
type: "STATE",
|
|
774
811
|
stream: "sessions",
|
|
775
|
-
cursor: { fetched_at: nowIso() },
|
|
812
|
+
cursor: { file_mtimes: newSessionFileMtimes, fetched_at: nowIso() },
|
|
776
813
|
});
|
|
777
814
|
}
|
|
778
815
|
if (requested.has("memory_notes")) {
|
|
@@ -788,8 +825,8 @@ if (isMainModule(import.meta.url)) {
|
|
|
788
825
|
buildOnly: false,
|
|
789
826
|
emit,
|
|
790
827
|
emitRecord,
|
|
791
|
-
fileMtimes,
|
|
792
|
-
newMtimes,
|
|
828
|
+
fileMtimes: messageFileMtimes,
|
|
829
|
+
newMtimes: newMessageFileMtimes,
|
|
793
830
|
requested,
|
|
794
831
|
sessionAccumulators,
|
|
795
832
|
});
|
|
@@ -798,7 +835,7 @@ if (isMainModule(import.meta.url)) {
|
|
|
798
835
|
await emit({
|
|
799
836
|
type: "STATE",
|
|
800
837
|
stream: "messages",
|
|
801
|
-
cursor: { file_mtimes:
|
|
838
|
+
cursor: { file_mtimes: newMessageFileMtimes, fetched_at: nowIso() },
|
|
802
839
|
});
|
|
803
840
|
}
|
|
804
841
|
},
|