@ironbee-ai/cli 0.6.2 → 0.7.1
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/CHANGELOG.md +12 -0
- package/README.md +167 -39
- package/dist/analysis/code-changes.js.map +1 -1
- package/dist/analysis/cross-session.js.map +1 -1
- package/dist/analysis/fix-effectiveness.js.map +1 -1
- package/dist/analysis/time-analysis.js.map +1 -1
- package/dist/analysis/verdict-details.js.map +1 -1
- package/dist/analysis/verification-quality.js.map +1 -1
- package/dist/analytics/classifier.d.ts +99 -0
- package/dist/analytics/classifier.d.ts.map +1 -0
- package/dist/analytics/classifier.js +380 -0
- package/dist/analytics/classifier.js.map +1 -0
- package/dist/analytics/emit.d.ts +67 -0
- package/dist/analytics/emit.d.ts.map +1 -0
- package/dist/analytics/emit.js +901 -0
- package/dist/analytics/emit.js.map +1 -0
- package/dist/analytics/errors.d.ts +33 -0
- package/dist/analytics/errors.d.ts.map +1 -0
- package/dist/analytics/errors.js +93 -0
- package/dist/analytics/errors.js.map +1 -0
- package/dist/analytics/hook-trigger.d.ts +39 -0
- package/dist/analytics/hook-trigger.d.ts.map +1 -0
- package/dist/analytics/hook-trigger.js +127 -0
- package/dist/analytics/hook-trigger.js.map +1 -0
- package/dist/analytics/log.d.ts +44 -0
- package/dist/analytics/log.d.ts.map +1 -0
- package/dist/analytics/log.js +158 -0
- package/dist/analytics/log.js.map +1 -0
- package/dist/analytics/merge.d.ts +40 -0
- package/dist/analytics/merge.d.ts.map +1 -0
- package/dist/analytics/merge.js +527 -0
- package/dist/analytics/merge.js.map +1 -0
- package/dist/analytics/pricing.d.ts +149 -0
- package/dist/analytics/pricing.d.ts.map +1 -0
- package/dist/analytics/pricing.js +179 -0
- package/dist/analytics/pricing.js.map +1 -0
- package/dist/analytics/projection.d.ts +356 -0
- package/dist/analytics/projection.d.ts.map +1 -0
- package/dist/analytics/projection.js +2281 -0
- package/dist/analytics/projection.js.map +1 -0
- package/dist/analytics/spawn.d.ts +28 -0
- package/dist/analytics/spawn.d.ts.map +1 -0
- package/dist/analytics/spawn.js +57 -0
- package/dist/analytics/spawn.js.map +1 -0
- package/dist/analytics/state.d.ts +58 -0
- package/dist/analytics/state.d.ts.map +1 -0
- package/dist/analytics/state.js +329 -0
- package/dist/analytics/state.js.map +1 -0
- package/dist/analytics/transcript.d.ts +150 -0
- package/dist/analytics/transcript.d.ts.map +1 -0
- package/dist/analytics/transcript.js +276 -0
- package/dist/analytics/transcript.js.map +1 -0
- package/dist/analytics/types.d.ts +875 -0
- package/dist/analytics/types.d.ts.map +1 -0
- package/dist/analytics/types.js +31 -0
- package/dist/analytics/types.js.map +1 -0
- package/dist/clients/base.d.ts +21 -2
- package/dist/clients/base.d.ts.map +1 -1
- package/dist/clients/claude/commands/ironbee-verify.md +15 -7
- package/dist/clients/claude/fragments/command-verify.node.md +33 -0
- package/dist/clients/claude/fragments/rule.node.md +29 -0
- package/dist/clients/claude/fragments/skill.node.md +77 -0
- package/dist/clients/claude/hooks/activity-end.d.ts +13 -0
- package/dist/clients/claude/hooks/activity-end.d.ts.map +1 -0
- package/dist/clients/claude/hooks/activity-end.js +42 -0
- package/dist/clients/claude/hooks/activity-end.js.map +1 -0
- package/dist/clients/claude/hooks/require-verdict.d.ts +3 -2
- package/dist/clients/claude/hooks/require-verdict.d.ts.map +1 -1
- package/dist/clients/claude/hooks/require-verdict.js +6 -5
- package/dist/clients/claude/hooks/require-verdict.js.map +1 -1
- package/dist/clients/claude/hooks/require-verification.d.ts +7 -4
- package/dist/clients/claude/hooks/require-verification.d.ts.map +1 -1
- package/dist/clients/claude/hooks/require-verification.js +44 -22
- package/dist/clients/claude/hooks/require-verification.js.map +1 -1
- package/dist/clients/claude/hooks/session-end.d.ts.map +1 -1
- package/dist/clients/claude/hooks/session-end.js +17 -2
- package/dist/clients/claude/hooks/session-end.js.map +1 -1
- package/dist/clients/claude/hooks/session-start.d.ts.map +1 -1
- package/dist/clients/claude/hooks/session-start.js +2 -1
- package/dist/clients/claude/hooks/session-start.js.map +1 -1
- package/dist/clients/claude/hooks/track-action-monitor.d.ts +27 -0
- package/dist/clients/claude/hooks/track-action-monitor.d.ts.map +1 -0
- package/dist/clients/claude/hooks/track-action-monitor.js +126 -0
- package/dist/clients/claude/hooks/track-action-monitor.js.map +1 -0
- package/dist/clients/claude/hooks/track-action.d.ts.map +1 -1
- package/dist/clients/claude/hooks/track-action.js +29 -20
- package/dist/clients/claude/hooks/track-action.js.map +1 -1
- package/dist/clients/claude/hooks/verify-gate.d.ts.map +1 -1
- package/dist/clients/claude/hooks/verify-gate.js +18 -1
- package/dist/clients/claude/hooks/verify-gate.js.map +1 -1
- package/dist/clients/claude/index.d.ts +4 -1
- package/dist/clients/claude/index.d.ts.map +1 -1
- package/dist/clients/claude/index.js +171 -94
- package/dist/clients/claude/index.js.map +1 -1
- package/dist/clients/claude/rules/ironbee-verification.md +41 -33
- package/dist/clients/claude/skills/ironbee-verification.md +93 -76
- package/dist/clients/cursor/commands/ironbee-verify/SKILL.md +18 -10
- package/dist/clients/cursor/fragments/command-verify.node.md +33 -0
- package/dist/clients/cursor/fragments/rule.node.md +29 -0
- package/dist/clients/cursor/fragments/skill.node.md +77 -0
- package/dist/clients/cursor/hooks/activity-end.d.ts +14 -0
- package/dist/clients/cursor/hooks/activity-end.d.ts.map +1 -0
- package/dist/clients/cursor/hooks/activity-end.js +45 -0
- package/dist/clients/cursor/hooks/activity-end.js.map +1 -0
- package/dist/clients/cursor/hooks/require-verdict.d.ts +1 -1
- package/dist/clients/cursor/hooks/require-verdict.js +4 -4
- package/dist/clients/cursor/hooks/require-verification.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/require-verification.js +42 -16
- package/dist/clients/cursor/hooks/require-verification.js.map +1 -1
- package/dist/clients/cursor/hooks/session-end.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/session-end.js +18 -2
- package/dist/clients/cursor/hooks/session-end.js.map +1 -1
- package/dist/clients/cursor/hooks/session-start.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/session-start.js +2 -1
- package/dist/clients/cursor/hooks/session-start.js.map +1 -1
- package/dist/clients/cursor/hooks/track-action-monitor.d.ts +27 -0
- package/dist/clients/cursor/hooks/track-action-monitor.d.ts.map +1 -0
- package/dist/clients/cursor/hooks/track-action-monitor.js +133 -0
- package/dist/clients/cursor/hooks/track-action-monitor.js.map +1 -0
- package/dist/clients/cursor/hooks/track-action.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/track-action.js +51 -23
- package/dist/clients/cursor/hooks/track-action.js.map +1 -1
- package/dist/clients/cursor/hooks/verify-gate.d.ts.map +1 -1
- package/dist/clients/cursor/hooks/verify-gate.js +14 -1
- package/dist/clients/cursor/hooks/verify-gate.js.map +1 -1
- package/dist/clients/cursor/index.d.ts +4 -1
- package/dist/clients/cursor/index.d.ts.map +1 -1
- package/dist/clients/cursor/index.js +117 -71
- package/dist/clients/cursor/index.js.map +1 -1
- package/dist/clients/cursor/rules/ironbee-verification.mdc +37 -29
- package/dist/clients/cursor/skills/ironbee-verification.md +93 -76
- package/dist/clients/registry.d.ts +14 -0
- package/dist/clients/registry.d.ts.map +1 -1
- package/dist/clients/registry.js +34 -0
- package/dist/clients/registry.js.map +1 -1
- package/dist/commands/analyze.d.ts.map +1 -1
- package/dist/commands/analyze.js +40 -0
- package/dist/commands/analyze.js.map +1 -1
- package/dist/commands/backend-toggle.d.ts +45 -0
- package/dist/commands/backend-toggle.d.ts.map +1 -0
- package/dist/commands/backend-toggle.js +192 -0
- package/dist/commands/backend-toggle.js.map +1 -0
- package/dist/commands/disable-backend.d.ts +14 -0
- package/dist/commands/disable-backend.d.ts.map +1 -0
- package/dist/commands/disable-backend.js +34 -0
- package/dist/commands/disable-backend.js.map +1 -0
- package/dist/commands/disable-verification.d.ts +16 -0
- package/dist/commands/disable-verification.d.ts.map +1 -0
- package/dist/commands/disable-verification.js +36 -0
- package/dist/commands/disable-verification.js.map +1 -0
- package/dist/commands/enable-backend.d.ts +15 -0
- package/dist/commands/enable-backend.d.ts.map +1 -0
- package/dist/commands/enable-backend.js +35 -0
- package/dist/commands/enable-backend.js.map +1 -0
- package/dist/commands/enable-verification.d.ts +14 -0
- package/dist/commands/enable-verification.d.ts.map +1 -0
- package/dist/commands/enable-verification.js +34 -0
- package/dist/commands/enable-verification.js.map +1 -0
- package/dist/commands/hook.d.ts.map +1 -1
- package/dist/commands/hook.js +60 -0
- package/dist/commands/hook.js.map +1 -1
- package/dist/commands/import.d.ts +39 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +369 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/install.d.ts.map +1 -1
- package/dist/commands/install.js +15 -20
- package/dist/commands/install.js.map +1 -1
- package/dist/commands/process-analytics.d.ts +18 -0
- package/dist/commands/process-analytics.d.ts.map +1 -0
- package/dist/commands/process-analytics.js +57 -0
- package/dist/commands/process-analytics.js.map +1 -0
- package/dist/commands/queue.d.ts +2 -3
- package/dist/commands/queue.d.ts.map +1 -1
- package/dist/commands/queue.js +2 -3
- package/dist/commands/queue.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +29 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/verification-toggle.d.ts +47 -0
- package/dist/commands/verification-toggle.d.ts.map +1 -0
- package/dist/commands/verification-toggle.js +122 -0
- package/dist/commands/verification-toggle.js.map +1 -0
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +28 -0
- package/dist/commands/verify.js.map +1 -1
- package/dist/hooks/core/actions.d.ts +72 -70
- package/dist/hooks/core/actions.d.ts.map +1 -1
- package/dist/hooks/core/actions.js +191 -28
- package/dist/hooks/core/actions.js.map +1 -1
- package/dist/hooks/core/activity-end.d.ts +20 -0
- package/dist/hooks/core/activity-end.d.ts.map +1 -0
- package/dist/hooks/core/activity-end.js +23 -0
- package/dist/hooks/core/activity-end.js.map +1 -0
- package/dist/hooks/core/required-tools.d.ts +30 -0
- package/dist/hooks/core/required-tools.d.ts.map +1 -0
- package/dist/hooks/core/required-tools.js +70 -0
- package/dist/hooks/core/required-tools.js.map +1 -0
- package/dist/hooks/core/session-state.d.ts +12 -3
- package/dist/hooks/core/session-state.d.ts.map +1 -1
- package/dist/hooks/core/session-state.js +59 -0
- package/dist/hooks/core/session-state.js.map +1 -1
- package/dist/hooks/core/submit-verdict.d.ts.map +1 -1
- package/dist/hooks/core/submit-verdict.js +16 -12
- package/dist/hooks/core/submit-verdict.js.map +1 -1
- package/dist/hooks/core/verify-gate.d.ts +17 -3
- package/dist/hooks/core/verify-gate.d.ts.map +1 -1
- package/dist/hooks/core/verify-gate.js +312 -116
- package/dist/hooks/core/verify-gate.js.map +1 -1
- package/dist/import/claude/analytics-runner.d.ts +42 -0
- package/dist/import/claude/analytics-runner.d.ts.map +1 -0
- package/dist/import/claude/analytics-runner.js +213 -0
- package/dist/import/claude/analytics-runner.js.map +1 -0
- package/dist/import/claude/discovery.d.ts +22 -0
- package/dist/import/claude/discovery.d.ts.map +1 -0
- package/dist/import/claude/discovery.js +197 -0
- package/dist/import/claude/discovery.js.map +1 -0
- package/dist/import/claude/encoding.d.ts +50 -0
- package/dist/import/claude/encoding.d.ts.map +1 -0
- package/dist/import/claude/encoding.js +110 -0
- package/dist/import/claude/encoding.js.map +1 -0
- package/dist/import/claude/events/file-change.d.ts +28 -0
- package/dist/import/claude/events/file-change.d.ts.map +1 -0
- package/dist/import/claude/events/file-change.js +112 -0
- package/dist/import/claude/events/file-change.js.map +1 -0
- package/dist/import/claude/events/tool-call.d.ts +61 -0
- package/dist/import/claude/events/tool-call.d.ts.map +1 -0
- package/dist/import/claude/events/tool-call.js +119 -0
- package/dist/import/claude/events/tool-call.js.map +1 -0
- package/dist/import/claude/runner.d.ts +31 -0
- package/dist/import/claude/runner.d.ts.map +1 -0
- package/dist/import/claude/runner.js +280 -0
- package/dist/import/claude/runner.js.map +1 -0
- package/dist/import/claude/summary.d.ts +23 -0
- package/dist/import/claude/summary.d.ts.map +1 -0
- package/dist/import/claude/summary.js +186 -0
- package/dist/import/claude/summary.js.map +1 -0
- package/dist/import/claude/transcript-walk.d.ts +52 -0
- package/dist/import/claude/transcript-walk.d.ts.map +1 -0
- package/dist/import/claude/transcript-walk.js +187 -0
- package/dist/import/claude/transcript-walk.js.map +1 -0
- package/dist/import/concurrent-pool.d.ts +45 -0
- package/dist/import/concurrent-pool.d.ts.map +1 -0
- package/dist/import/concurrent-pool.js +95 -0
- package/dist/import/concurrent-pool.js.map +1 -0
- package/dist/import/emitter.d.ts +29 -0
- package/dist/import/emitter.d.ts.map +1 -0
- package/dist/import/emitter.js +66 -0
- package/dist/import/emitter.js.map +1 -0
- package/dist/import/events/activity.d.ts +23 -0
- package/dist/import/events/activity.d.ts.map +1 -0
- package/dist/import/events/activity.js +45 -0
- package/dist/import/events/activity.js.map +1 -0
- package/dist/import/events/session.d.ts +24 -0
- package/dist/import/events/session.d.ts.map +1 -0
- package/dist/import/events/session.js +47 -0
- package/dist/import/events/session.js.map +1 -0
- package/dist/import/filter.d.ts +47 -0
- package/dist/import/filter.d.ts.map +1 -0
- package/dist/import/filter.js +90 -0
- package/dist/import/filter.js.map +1 -0
- package/dist/import/ids.d.ts +56 -0
- package/dist/import/ids.d.ts.map +1 -0
- package/dist/import/ids.js +87 -0
- package/dist/import/ids.js.map +1 -0
- package/dist/import/index.d.ts +29 -0
- package/dist/import/index.d.ts.map +1 -0
- package/dist/import/index.js +52 -0
- package/dist/import/index.js.map +1 -0
- package/dist/import/marker.d.ts +20 -0
- package/dist/import/marker.d.ts.map +1 -0
- package/dist/import/marker.js +71 -0
- package/dist/import/marker.js.map +1 -0
- package/dist/import/pipeline.d.ts +41 -0
- package/dist/import/pipeline.d.ts.map +1 -0
- package/dist/import/pipeline.js +47 -0
- package/dist/import/pipeline.js.map +1 -0
- package/dist/import/progress.d.ts +20 -0
- package/dist/import/progress.d.ts.map +1 -0
- package/dist/import/progress.js +69 -0
- package/dist/import/progress.js.map +1 -0
- package/dist/import/skip.d.ts +13 -0
- package/dist/import/skip.d.ts.map +1 -0
- package/dist/import/skip.js +24 -0
- package/dist/import/skip.js.map +1 -0
- package/dist/import/types.d.ts +125 -0
- package/dist/import/types.d.ts.map +1 -0
- package/dist/import/types.js +28 -0
- package/dist/import/types.js.map +1 -0
- package/dist/index.js +21 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/collector.d.ts +29 -3
- package/dist/lib/collector.d.ts.map +1 -1
- package/dist/lib/collector.js +118 -8
- package/dist/lib/collector.js.map +1 -1
- package/dist/lib/config.d.ts +240 -83
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +482 -89
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/event.d.ts +72 -0
- package/dist/lib/event.d.ts.map +1 -0
- package/dist/lib/event.js +42 -0
- package/dist/lib/event.js.map +1 -0
- package/dist/lib/gitignore.d.ts +21 -0
- package/dist/lib/gitignore.d.ts.map +1 -0
- package/dist/lib/gitignore.js +54 -0
- package/dist/lib/gitignore.js.map +1 -0
- package/dist/lib/runtime-section.d.ts +118 -0
- package/dist/lib/runtime-section.d.ts.map +1 -0
- package/dist/lib/runtime-section.js +256 -0
- package/dist/lib/runtime-section.js.map +1 -0
- package/dist/lib/telemetry.d.ts +1 -1
- package/dist/lib/telemetry.d.ts.map +1 -1
- package/dist/lib/telemetry.js +4 -1
- package/dist/lib/telemetry.js.map +1 -1
- package/dist/queue/dead-letter.d.ts +5 -1
- package/dist/queue/dead-letter.d.ts.map +1 -1
- package/dist/queue/dead-letter.js +5 -1
- package/dist/queue/dead-letter.js.map +1 -1
- package/dist/queue/drain.d.ts +3 -2
- package/dist/queue/drain.d.ts.map +1 -1
- package/dist/queue/drain.js +3 -2
- package/dist/queue/drain.js.map +1 -1
- package/dist/queue/flush.d.ts +28 -12
- package/dist/queue/flush.d.ts.map +1 -1
- package/dist/queue/flush.js +43 -18
- package/dist/queue/flush.js.map +1 -1
- package/dist/queue/handlers/send-event.d.ts.map +1 -1
- package/dist/queue/handlers/send-event.js.map +1 -1
- package/dist/queue/index.d.ts +1 -2
- package/dist/queue/index.d.ts.map +1 -1
- package/dist/queue/index.js +2 -2
- package/dist/queue/index.js.map +1 -1
- package/dist/queue/paths.d.ts +4 -2
- package/dist/queue/paths.d.ts.map +1 -1
- package/dist/queue/paths.js +4 -2
- package/dist/queue/paths.js.map +1 -1
- package/dist/queue/process-file.d.ts +5 -1
- package/dist/queue/process-file.d.ts.map +1 -1
- package/dist/queue/process-file.js +5 -1
- package/dist/queue/process-file.js.map +1 -1
- package/dist/queue/snapshot.d.ts +4 -1
- package/dist/queue/snapshot.d.ts.map +1 -1
- package/dist/queue/snapshot.js +4 -1
- package/dist/queue/snapshot.js.map +1 -1
- package/dist/queue/spawn.d.ts +1 -3
- package/dist/queue/spawn.d.ts.map +1 -1
- package/dist/queue/spawn.js +1 -3
- package/dist/queue/spawn.js.map +1 -1
- package/dist/queue/submit.d.ts +6 -1
- package/dist/queue/submit.d.ts.map +1 -1
- package/dist/queue/submit.js +6 -1
- package/dist/queue/submit.js.map +1 -1
- package/dist/queue/types.d.ts +5 -1
- package/dist/queue/types.d.ts.map +1 -1
- package/dist/queue/types.js +5 -1
- package/dist/queue/types.js.map +1 -1
- package/dist/queue/worker-log.d.ts +3 -1
- package/dist/queue/worker-log.d.ts.map +1 -1
- package/dist/queue/worker-log.js +3 -1
- package/dist/queue/worker-log.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* IronBee CLI — Import Analytics Runner
|
|
4
|
+
*
|
|
5
|
+
* Orchestrates the analytics derivation primitives (`projection.ts`,
|
|
6
|
+
* `merge.ts`) for a full transcript read end-to-end. Mirrors the live
|
|
7
|
+
* `src/analytics/emit.ts:emitAnalytics` orchestrator BUT:
|
|
8
|
+
*
|
|
9
|
+
* - never reads `state.json` (initializes fresh in-memory state)
|
|
10
|
+
* - never writes `state.json` (no persistence)
|
|
11
|
+
* - always treats the slice as final (`is_final: true`)
|
|
12
|
+
* - skips reset detection / idempotency / carve-out paths (full re-parse)
|
|
13
|
+
*
|
|
14
|
+
* This module: fork rather than `if (importMode)` branching
|
|
15
|
+
* inside `emit.ts` to honor the isolation contract.
|
|
16
|
+
*
|
|
17
|
+
* Returns the full set of analytics events the pipeline should POST. The
|
|
18
|
+
* pipeline is responsible for batching POST and writing the marker.
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.runImportAnalytics = runImportAnalytics;
|
|
22
|
+
const fs_1 = require("fs");
|
|
23
|
+
const types_1 = require("../../analytics/types");
|
|
24
|
+
const transcript_1 = require("../../analytics/transcript");
|
|
25
|
+
const state_1 = require("../../analytics/state");
|
|
26
|
+
const merge_1 = require("../../analytics/merge");
|
|
27
|
+
const projection_1 = require("../../analytics/projection");
|
|
28
|
+
const event_1 = require("../../lib/event");
|
|
29
|
+
const config_1 = require("../../lib/config");
|
|
30
|
+
const logger_1 = require("../../lib/logger");
|
|
31
|
+
const TRANSCRIPT_SOURCE = "claude-code";
|
|
32
|
+
/**
|
|
33
|
+
* Run the full transcript through the analytics pipeline and return every
|
|
34
|
+
* derivable wire event. Throws on read/parse errors.
|
|
35
|
+
*/
|
|
36
|
+
function runImportAnalytics(input) {
|
|
37
|
+
const { sessionId, projectName, projectDir, transcriptPath } = input;
|
|
38
|
+
const endReason = input.endReason ?? "import";
|
|
39
|
+
// Per-event-type gates — independent of analytics.enable.
|
|
40
|
+
const turnEventsEnabled = (0, config_1.isAnalyticsTurnEventsEnabled)(projectDir);
|
|
41
|
+
const stepEventsEnabled = (0, config_1.isAnalyticsStepEventsEnabled)(projectDir);
|
|
42
|
+
const apiRequestEventsEnabled = (0, config_1.isAnalyticsApiRequestEventsEnabled)(projectDir);
|
|
43
|
+
// Fresh in-memory state — never touches disk.
|
|
44
|
+
const state = (0, state_1.initialState)(sessionId, transcriptPath, projectName, TRANSCRIPT_SOURCE);
|
|
45
|
+
// Read full transcript into memory. Single pass — no resume, no slice
|
|
46
|
+
// boundary, the entire file is one delta.
|
|
47
|
+
const fileBytes = (0, fs_1.readFileSync)(transcriptPath);
|
|
48
|
+
const transcriptOffset = fileBytes.length;
|
|
49
|
+
const parsed = (0, transcript_1.parseJsonl)(fileBytes, 0);
|
|
50
|
+
const linesForProjection = parsed.lines
|
|
51
|
+
.filter((ln) => ln.parsed !== null)
|
|
52
|
+
.map((ln) => ln.parsed);
|
|
53
|
+
const projectionInput = {
|
|
54
|
+
lines: linesForProjection,
|
|
55
|
+
startingTurnIndex: state.accumulated.turns.assistant_count + 1,
|
|
56
|
+
sessionId,
|
|
57
|
+
projectName,
|
|
58
|
+
transcriptSource: TRANSCRIPT_SOURCE,
|
|
59
|
+
priorLastAssistantTsMs: state.internal.last_assistant_ts_ms,
|
|
60
|
+
priorPendingToolUses: state.internal.pending_tool_uses,
|
|
61
|
+
priorLastActivityTsMs: undefined,
|
|
62
|
+
priorCurrentTurn: state.internal.current_turn,
|
|
63
|
+
priorNextTurnIndex: state.internal.next_turn_index,
|
|
64
|
+
priorSeenAssistantMessageIds: state.internal.seen_assistant_message_ids,
|
|
65
|
+
};
|
|
66
|
+
const delta = (0, projection_1.projectDelta)(projectionInput);
|
|
67
|
+
const deltaInternal = (0, projection_1.projectDeltaInternal)(projectionInput);
|
|
68
|
+
// Per-event-type gating BEFORE merge — drop completed turn / step /
|
|
69
|
+
// api_request records from the delta when their flag is off, so the
|
|
70
|
+
// pending queues never accumulate them. Session-level aggregation of
|
|
71
|
+
// those records (turns_with_retry, one_shot, category_breakdown) is
|
|
72
|
+
// unaffected — projection has already folded them into delta's
|
|
73
|
+
// session-level fields.
|
|
74
|
+
if (!turnEventsEnabled && delta.completed_turns.length > 0) {
|
|
75
|
+
delta.completed_turns = [];
|
|
76
|
+
}
|
|
77
|
+
if (!stepEventsEnabled && delta.completed_steps.length > 0) {
|
|
78
|
+
delta.completed_steps = [];
|
|
79
|
+
}
|
|
80
|
+
if (!apiRequestEventsEnabled && delta.api_request_events.length > 0) {
|
|
81
|
+
delta.api_request_events = [];
|
|
82
|
+
}
|
|
83
|
+
const mergeResult = (0, merge_1.mergeAccumulated)(state.accumulated, state.internal, delta, deltaInternal);
|
|
84
|
+
let merged = mergeResult.accumulated;
|
|
85
|
+
let internal = mergeResult.internal;
|
|
86
|
+
// Force-close the in-flight turn (Stop-closes-turn semantics — same as
|
|
87
|
+
// live emit's force-close path). Empty (0-asst) turns are dropped silently.
|
|
88
|
+
if (internal.current_turn !== undefined && internal.current_turn.assistant_messages > 0) {
|
|
89
|
+
const openTurnState = internal.current_turn;
|
|
90
|
+
const closeEndTime = openTurnState.last_activity_time !== ""
|
|
91
|
+
? openTurnState.last_activity_time
|
|
92
|
+
: merged.last_activity_time;
|
|
93
|
+
const closeResult = (0, projection_1.closeTurn)(openTurnState, {
|
|
94
|
+
endTime: closeEndTime,
|
|
95
|
+
endReason: "session_end",
|
|
96
|
+
sessionId,
|
|
97
|
+
projectName,
|
|
98
|
+
transcriptSource: TRANSCRIPT_SOURCE,
|
|
99
|
+
});
|
|
100
|
+
(0, projection_1.applyBreakdownDelta)(merged.classification.category_breakdown, closeResult);
|
|
101
|
+
merged.turns.with_retry += closeResult.turns_with_retry_inc;
|
|
102
|
+
merged.turns.one_shot += closeResult.one_shot_inc;
|
|
103
|
+
const finalTurnQueue = turnEventsEnabled
|
|
104
|
+
? [...(internal.pending_turn_events ?? []), closeResult.turn_event]
|
|
105
|
+
: (internal.pending_turn_events ?? []);
|
|
106
|
+
const finalStepQueue = stepEventsEnabled && closeResult.step_events.length > 0
|
|
107
|
+
? [...(internal.pending_step_events ?? []), ...closeResult.step_events]
|
|
108
|
+
: (internal.pending_step_events ?? []);
|
|
109
|
+
internal = {
|
|
110
|
+
...internal,
|
|
111
|
+
...(finalTurnQueue.length > 0 ? { pending_turn_events: finalTurnQueue } : {}),
|
|
112
|
+
...(finalStepQueue.length > 0 ? { pending_step_events: finalStepQueue } : {}),
|
|
113
|
+
};
|
|
114
|
+
delete internal.current_turn;
|
|
115
|
+
}
|
|
116
|
+
else if (internal.current_turn !== undefined) {
|
|
117
|
+
// 0-asst open turn — drop, decrement user_count to keep it in sync
|
|
118
|
+
// with the wire (mirrors live emit's behavior).
|
|
119
|
+
if (merged.turns.user_count > 0) {
|
|
120
|
+
merged.turns.user_count -= 1;
|
|
121
|
+
}
|
|
122
|
+
internal = { ...internal };
|
|
123
|
+
delete internal.current_turn;
|
|
124
|
+
}
|
|
125
|
+
// Compose the SessionAnalytics body and wrap as Event.
|
|
126
|
+
const baseFields = {
|
|
127
|
+
session_id: sessionId,
|
|
128
|
+
project_name: projectName,
|
|
129
|
+
};
|
|
130
|
+
const snapshot = {
|
|
131
|
+
session_id: merged.session_id,
|
|
132
|
+
project_name: merged.project_name,
|
|
133
|
+
schema_version: types_1.SCHEMA_VERSION,
|
|
134
|
+
transcript_source: merged.transcript_source,
|
|
135
|
+
is_final: true,
|
|
136
|
+
snapshot_at: new Date().toISOString(),
|
|
137
|
+
offset: transcriptOffset,
|
|
138
|
+
end_reason: endReason,
|
|
139
|
+
start_time: merged.start_time,
|
|
140
|
+
last_activity_time: merged.last_activity_time,
|
|
141
|
+
time: merged.time,
|
|
142
|
+
turns: merged.turns,
|
|
143
|
+
classification: merged.classification,
|
|
144
|
+
usage: merged.usage,
|
|
145
|
+
models: merged.models,
|
|
146
|
+
user_messages: merged.user_messages,
|
|
147
|
+
tools: merged.tools,
|
|
148
|
+
mcp_servers: merged.mcp_servers,
|
|
149
|
+
skills: merged.skills,
|
|
150
|
+
sub_agents: merged.sub_agents,
|
|
151
|
+
bash_binaries: merged.bash_binaries,
|
|
152
|
+
tool_meta: merged.tool_meta,
|
|
153
|
+
code_changes: merged.code_changes,
|
|
154
|
+
errors: merged.errors,
|
|
155
|
+
user_activity: merged.user_activity,
|
|
156
|
+
context_tokens: merged.context_tokens,
|
|
157
|
+
process_errors: merged.process_errors,
|
|
158
|
+
};
|
|
159
|
+
const sessionAnalytics = {
|
|
160
|
+
...baseFields,
|
|
161
|
+
id: (0, projection_1.deriveSessionAnalyticsEventId)(merged.session_id, transcriptOffset),
|
|
162
|
+
type: event_1.EventType.SESSION_ANALYTICS,
|
|
163
|
+
timestamp: Date.now(),
|
|
164
|
+
analytics: snapshot,
|
|
165
|
+
};
|
|
166
|
+
const pendingTurns = internal.pending_turn_events ?? [];
|
|
167
|
+
const pendingSteps = internal.pending_step_events ?? [];
|
|
168
|
+
const pendingApiRequests = internal.pending_api_request_events ?? [];
|
|
169
|
+
const turnEvents = pendingTurns.map((turn) => ({
|
|
170
|
+
...baseFields,
|
|
171
|
+
id: (0, projection_1.deriveTurnEventId)(sessionId, turn.turn_id),
|
|
172
|
+
type: event_1.EventType.SESSION_TURN,
|
|
173
|
+
timestamp: Date.now(),
|
|
174
|
+
turn,
|
|
175
|
+
}));
|
|
176
|
+
const stepEvents = pendingSteps.map((step) => ({
|
|
177
|
+
...baseFields,
|
|
178
|
+
id: (0, projection_1.deriveStepEventId)(sessionId, step.step_id),
|
|
179
|
+
type: event_1.EventType.SESSION_TURN_STEP,
|
|
180
|
+
timestamp: Date.now(),
|
|
181
|
+
step,
|
|
182
|
+
}));
|
|
183
|
+
const apiRequestEvents = pendingApiRequests.map((req) => ({
|
|
184
|
+
...baseFields,
|
|
185
|
+
id: req.id,
|
|
186
|
+
type: event_1.EventType.API_REQUEST,
|
|
187
|
+
timestamp: req.timestamp_ms,
|
|
188
|
+
request_id: req.request_id,
|
|
189
|
+
success: req.success,
|
|
190
|
+
error: req.error,
|
|
191
|
+
status_code: req.status_code,
|
|
192
|
+
model: req.model,
|
|
193
|
+
speed: req.speed,
|
|
194
|
+
input_tokens: req.input_tokens,
|
|
195
|
+
output_tokens: req.output_tokens,
|
|
196
|
+
cache_read_tokens: req.cache_read_tokens,
|
|
197
|
+
cache_creation_tokens: req.cache_creation_tokens,
|
|
198
|
+
cost_usd: req.cost_usd,
|
|
199
|
+
duration: req.duration,
|
|
200
|
+
}));
|
|
201
|
+
logger_1.logger.debug(`import analytics-runner: session=${sessionId} `
|
|
202
|
+
+ `turns=${pendingTurns.length} steps=${pendingSteps.length} `
|
|
203
|
+
+ `api_requests=${pendingApiRequests.length} cost_usd=${merged.usage.cost_usd.toFixed(4)} `
|
|
204
|
+
+ `wire_offset=${transcriptOffset}`);
|
|
205
|
+
return {
|
|
206
|
+
sessionAnalytics,
|
|
207
|
+
turnEvents,
|
|
208
|
+
stepEvents,
|
|
209
|
+
apiRequestEvents,
|
|
210
|
+
transcriptOffset,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=analytics-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics-runner.js","sourceRoot":"","sources":["../../../src/import/claude/analytics-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IronBee CLI — Import Module Transcript Discovery
|
|
3
|
+
*
|
|
4
|
+
* Resolves an `ImportScope` to a list of `ImportTarget`s by walking
|
|
5
|
+
* `~/.claude/projects/<encoded-cwd>/<session-uuid>.jsonl`.
|
|
6
|
+
*
|
|
7
|
+
* Discovery does NOT apply the time-range filter — that is `filter.ts`'s
|
|
8
|
+
* job, after a session is found. Discovery is purely about "where do
|
|
9
|
+
* candidate transcripts live on disk."
|
|
10
|
+
*
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
13
|
+
import { ImportScope, ImportTarget } from "../types";
|
|
14
|
+
/** Returns `~/.claude/projects/`. */
|
|
15
|
+
export declare function claudeProjectsDir(): string;
|
|
16
|
+
/**
|
|
17
|
+
* Resolve the scope flag to a list of candidate transcripts. Each returned
|
|
18
|
+
* `ImportTarget` is fully populated EXCEPT that no time-range filter has
|
|
19
|
+
* been applied yet — callers run `filter.ts` over this list.
|
|
20
|
+
*/
|
|
21
|
+
export declare function findClaudeTranscripts(scope: ImportScope): ImportTarget[];
|
|
22
|
+
//# sourceMappingURL=discovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../../src/import/claude/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGrD,qCAAqC;AACrC,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,EAAE,CA+DxE"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* IronBee CLI — Import Module Transcript Discovery
|
|
4
|
+
*
|
|
5
|
+
* Resolves an `ImportScope` to a list of `ImportTarget`s by walking
|
|
6
|
+
* `~/.claude/projects/<encoded-cwd>/<session-uuid>.jsonl`.
|
|
7
|
+
*
|
|
8
|
+
* Discovery does NOT apply the time-range filter — that is `filter.ts`'s
|
|
9
|
+
* job, after a session is found. Discovery is purely about "where do
|
|
10
|
+
* candidate transcripts live on disk."
|
|
11
|
+
*
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.claudeProjectsDir = claudeProjectsDir;
|
|
16
|
+
exports.findClaudeTranscripts = findClaudeTranscripts;
|
|
17
|
+
const fs_1 = require("fs");
|
|
18
|
+
const os_1 = require("os");
|
|
19
|
+
const path_1 = require("path");
|
|
20
|
+
const logger_1 = require("../../lib/logger");
|
|
21
|
+
const actions_1 = require("../../hooks/core/actions");
|
|
22
|
+
const encoding_1 = require("./encoding");
|
|
23
|
+
/** Returns `~/.claude/projects/`. */
|
|
24
|
+
function claudeProjectsDir() {
|
|
25
|
+
return (0, path_1.join)((0, os_1.homedir)(), ".claude", "projects");
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolve the scope flag to a list of candidate transcripts. Each returned
|
|
29
|
+
* `ImportTarget` is fully populated EXCEPT that no time-range filter has
|
|
30
|
+
* been applied yet — callers run `filter.ts` over this list.
|
|
31
|
+
*/
|
|
32
|
+
function findClaudeTranscripts(scope) {
|
|
33
|
+
if (scope.kind === "transcript") {
|
|
34
|
+
const target = singleTranscriptToTarget(scope.path);
|
|
35
|
+
return target !== null ? [target] : [];
|
|
36
|
+
}
|
|
37
|
+
const folderEntries = [];
|
|
38
|
+
if (scope.kind === "current-project") {
|
|
39
|
+
const cwd = process.cwd();
|
|
40
|
+
const folder = (0, encoding_1.encodeProjectFolder)(cwd);
|
|
41
|
+
// Use resolveProjectName so the wire `project_name` matches what
|
|
42
|
+
// live mode emits for the same project — walks up looking for `.git`,
|
|
43
|
+
// returns basename of the git root (or basename of the start dir if
|
|
44
|
+
// no .git is found). Same semantic as `src/hooks/core/actions.ts`.
|
|
45
|
+
folderEntries.push({ folder, projectDir: cwd, projectName: (0, actions_1.resolveProjectName)(cwd) });
|
|
46
|
+
}
|
|
47
|
+
else if (scope.kind === "projects") {
|
|
48
|
+
for (const p of scope.paths) {
|
|
49
|
+
const folder = (0, encoding_1.encodeProjectFolder)(p);
|
|
50
|
+
folderEntries.push({ folder, projectDir: p, projectName: (0, actions_1.resolveProjectName)(p) });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// all-projects
|
|
55
|
+
const projectsDir = claudeProjectsDir();
|
|
56
|
+
if (!(0, fs_1.existsSync)(projectsDir)) {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
let subdirs = [];
|
|
60
|
+
try {
|
|
61
|
+
subdirs = (0, fs_1.readdirSync)(projectsDir);
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
logger_1.logger.debug(`import discovery: readdir(${projectsDir}) failed: ${e instanceof Error ? e.message : e}`);
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
for (const sub of subdirs) {
|
|
68
|
+
const resolved = (0, encoding_1.resolveProjectFromFolder)(sub);
|
|
69
|
+
folderEntries.push({ folder: sub, projectDir: resolved.projectDir, projectName: resolved.projectName });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const targets = [];
|
|
73
|
+
for (const entry of folderEntries) {
|
|
74
|
+
const folderPath = (0, path_1.join)(claudeProjectsDir(), entry.folder);
|
|
75
|
+
if (!(0, fs_1.existsSync)(folderPath)) {
|
|
76
|
+
logger_1.logger.debug(`import discovery: folder ${folderPath} does not exist — skipping`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
let files = [];
|
|
80
|
+
try {
|
|
81
|
+
files = (0, fs_1.readdirSync)(folderPath).filter((f) => f.endsWith(".jsonl"));
|
|
82
|
+
}
|
|
83
|
+
catch (e) {
|
|
84
|
+
logger_1.logger.debug(`import discovery: readdir(${folderPath}) failed: ${e instanceof Error ? e.message : e}`);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
for (const fname of files) {
|
|
88
|
+
const sessionId = fname.slice(0, -".jsonl".length);
|
|
89
|
+
const transcriptPath = (0, path_1.join)(folderPath, fname);
|
|
90
|
+
const target = buildTarget(transcriptPath, sessionId, entry.projectDir, entry.projectName);
|
|
91
|
+
if (target !== null) {
|
|
92
|
+
targets.push(target);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return targets;
|
|
97
|
+
}
|
|
98
|
+
function singleTranscriptToTarget(absPath) {
|
|
99
|
+
if (!(0, fs_1.existsSync)(absPath)) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
if (!absPath.endsWith(".jsonl")) {
|
|
103
|
+
logger_1.logger.debug(`import discovery: --transcript ${absPath} is not a .jsonl file`);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
const fname = absPath.split("/").pop() ?? "";
|
|
107
|
+
const sessionId = fname.slice(0, -".jsonl".length);
|
|
108
|
+
// Try to recover (projectDir, projectName) from the parent folder.
|
|
109
|
+
const parts = absPath.split("/");
|
|
110
|
+
const folderName = parts.length >= 2 ? parts[parts.length - 2] : "";
|
|
111
|
+
const resolved = (0, encoding_1.resolveProjectFromFolder)(folderName);
|
|
112
|
+
return buildTarget(absPath, sessionId, resolved.projectDir, resolved.projectName);
|
|
113
|
+
}
|
|
114
|
+
function buildTarget(transcriptPath, sessionId, projectDir, projectName) {
|
|
115
|
+
let mtimeMs;
|
|
116
|
+
let sizeBytes;
|
|
117
|
+
try {
|
|
118
|
+
const s = (0, fs_1.statSync)(transcriptPath);
|
|
119
|
+
mtimeMs = s.mtimeMs;
|
|
120
|
+
sizeBytes = s.size;
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
logger_1.logger.debug(`import discovery: stat(${transcriptPath}) failed: ${e instanceof Error ? e.message : e}`);
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
const sessionStartMs = readSessionStartTimestamp(transcriptPath);
|
|
127
|
+
if (Number.isNaN(sessionStartMs)) {
|
|
128
|
+
logger_1.logger.debug(`import discovery: ${transcriptPath} has no parseable timestamp in header — skipping`);
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
return { sessionId, transcriptPath, projectDir, projectName, sessionStartMs, mtimeMs, sizeBytes };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Find the earliest top-level `timestamp` in the transcript header. Claude
|
|
135
|
+
* Code transcripts open with non-message lines that lack a top-level
|
|
136
|
+
* `timestamp` (`permission-mode`, `file-history-snapshot`, …); the first
|
|
137
|
+
* timestamped line is the first user/assistant message a few rows in. We
|
|
138
|
+
* therefore scan multiple lines, returning the first parseable
|
|
139
|
+
* `timestamp` value we encounter.
|
|
140
|
+
*
|
|
141
|
+
* Returns `NaN` when no line within the bounded read window carries a
|
|
142
|
+
* top-level `timestamp` string. Bounded at 64 KB so worst-case header
|
|
143
|
+
* scanning doesn't degrade discovery on huge transcripts — that's enough
|
|
144
|
+
* for ~100+ header rows in practice.
|
|
145
|
+
*/
|
|
146
|
+
function readSessionStartTimestamp(path) {
|
|
147
|
+
const READ_CAP = 65536;
|
|
148
|
+
let fd = -1;
|
|
149
|
+
try {
|
|
150
|
+
fd = (0, fs_1.openSync)(path, "r");
|
|
151
|
+
const buf = Buffer.alloc(READ_CAP);
|
|
152
|
+
const bytesRead = (0, fs_1.readSync)(fd, buf, 0, READ_CAP, 0);
|
|
153
|
+
const text = buf.subarray(0, bytesRead).toString("utf-8");
|
|
154
|
+
let cursor = 0;
|
|
155
|
+
while (cursor < text.length) {
|
|
156
|
+
const nl = text.indexOf("\n", cursor);
|
|
157
|
+
const lineEnd = nl >= 0 ? nl : text.length;
|
|
158
|
+
const line = text.slice(cursor, lineEnd);
|
|
159
|
+
cursor = nl >= 0 ? nl + 1 : text.length;
|
|
160
|
+
if (line.length === 0) {
|
|
161
|
+
if (nl < 0) {
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const parsed = JSON.parse(line);
|
|
168
|
+
if (typeof parsed.timestamp === "string") {
|
|
169
|
+
const ms = Date.parse(parsed.timestamp);
|
|
170
|
+
if (Number.isFinite(ms)) {
|
|
171
|
+
return ms;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// malformed line — skip and continue scanning
|
|
177
|
+
}
|
|
178
|
+
if (nl < 0) {
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return Number.NaN;
|
|
183
|
+
}
|
|
184
|
+
catch (e) {
|
|
185
|
+
logger_1.logger.debug(`import discovery: first-line parse failed for ${path}: ${e instanceof Error ? e.message : e}`);
|
|
186
|
+
return Number.NaN;
|
|
187
|
+
}
|
|
188
|
+
finally {
|
|
189
|
+
if (fd >= 0) {
|
|
190
|
+
try {
|
|
191
|
+
(0, fs_1.closeSync)(fd);
|
|
192
|
+
}
|
|
193
|
+
catch { /* ignore */ }
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../../src/import/claude/discovery.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IronBee CLI — Import Module Project-Path Encoding
|
|
3
|
+
*
|
|
4
|
+
* Forward + reverse mapping between absolute filesystem paths and Claude
|
|
5
|
+
* Code's transcript-folder convention.
|
|
6
|
+
*
|
|
7
|
+
* Forward (path → folder name): reuses `src/analytics/transcript.ts:sanitizeProjectPath`
|
|
8
|
+
* which replaces every non-alphanumeric character with `-`. This matches what
|
|
9
|
+
* Claude Code does in its own transcript writer.
|
|
10
|
+
*
|
|
11
|
+
* Reverse (folder name → path): the encoding is lossy — `/`, `.`, `_`, etc.
|
|
12
|
+
* all collapse to `-`, so we cannot recover the original path from the folder
|
|
13
|
+
* name alone. We try a small set of plausible interpretations against
|
|
14
|
+
* `fs.existsSync` and pick the first one that resolves to a real directory.
|
|
15
|
+
* On miss, we fall back to using the encoded folder name as a synthetic
|
|
16
|
+
* identifier (the only consumer past that point is the skip rule's
|
|
17
|
+
* `existsSync` check, which trivially returns false for synthetic paths).
|
|
18
|
+
*
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
/** Forward: absolute path → encoded folder name. */
|
|
22
|
+
export declare function encodeProjectFolder(absPath: string): string;
|
|
23
|
+
/**
|
|
24
|
+
* Reverse: encoded folder name → best-effort absolute path.
|
|
25
|
+
*
|
|
26
|
+
* Walks the encoded segments, trying each `-` as `/`, `.`, `_`, or literal `-`
|
|
27
|
+
* (in that priority order — `/` first because directory separators are by
|
|
28
|
+
* far the dominant case). Stops on the first interpretation whose path
|
|
29
|
+
* exists on disk. Returns `null` when nothing matches.
|
|
30
|
+
*
|
|
31
|
+
* The walk is depth-first and bounded: with N dashes the worst case is 4^N
|
|
32
|
+
* combinations, but in practice the first-existing-match short-circuit caps
|
|
33
|
+
* runtime to a handful of `existsSync` calls. We cap the dash count at 30 to
|
|
34
|
+
* defend against pathological input — encoded folders longer than that are
|
|
35
|
+
* highly unusual and we just decline to decode them.
|
|
36
|
+
*/
|
|
37
|
+
export declare function decodeProjectFolder(folderName: string): string | null;
|
|
38
|
+
/**
|
|
39
|
+
* Best-effort decode plus a `(projectDir, projectName)` resolver that always
|
|
40
|
+
* returns something. When the reverse-decode fails, returns the encoded
|
|
41
|
+
* folder name in both fields so downstream consumers (skip rule, marker
|
|
42
|
+
* write) can still proceed — they handle non-existent project dirs
|
|
43
|
+
* gracefully.
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveProjectFromFolder(folderName: string): {
|
|
46
|
+
projectDir: string;
|
|
47
|
+
projectName: string;
|
|
48
|
+
existsOnDisk: boolean;
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=encoding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoding.d.ts","sourceRoot":"","sources":["../../../src/import/claude/encoding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAMH,oDAAoD;AACpD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE3D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAgBrE;AA4BD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,OAAO,CAAA;CAAE,CAa/H"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* IronBee CLI — Import Module Project-Path Encoding
|
|
4
|
+
*
|
|
5
|
+
* Forward + reverse mapping between absolute filesystem paths and Claude
|
|
6
|
+
* Code's transcript-folder convention.
|
|
7
|
+
*
|
|
8
|
+
* Forward (path → folder name): reuses `src/analytics/transcript.ts:sanitizeProjectPath`
|
|
9
|
+
* which replaces every non-alphanumeric character with `-`. This matches what
|
|
10
|
+
* Claude Code does in its own transcript writer.
|
|
11
|
+
*
|
|
12
|
+
* Reverse (folder name → path): the encoding is lossy — `/`, `.`, `_`, etc.
|
|
13
|
+
* all collapse to `-`, so we cannot recover the original path from the folder
|
|
14
|
+
* name alone. We try a small set of plausible interpretations against
|
|
15
|
+
* `fs.existsSync` and pick the first one that resolves to a real directory.
|
|
16
|
+
* On miss, we fall back to using the encoded folder name as a synthetic
|
|
17
|
+
* identifier (the only consumer past that point is the skip rule's
|
|
18
|
+
* `existsSync` check, which trivially returns false for synthetic paths).
|
|
19
|
+
*
|
|
20
|
+
*
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.encodeProjectFolder = encodeProjectFolder;
|
|
24
|
+
exports.decodeProjectFolder = decodeProjectFolder;
|
|
25
|
+
exports.resolveProjectFromFolder = resolveProjectFromFolder;
|
|
26
|
+
const fs_1 = require("fs");
|
|
27
|
+
const actions_1 = require("../../hooks/core/actions");
|
|
28
|
+
const transcript_1 = require("../../analytics/transcript");
|
|
29
|
+
/** Forward: absolute path → encoded folder name. */
|
|
30
|
+
function encodeProjectFolder(absPath) {
|
|
31
|
+
return (0, transcript_1.sanitizeProjectPath)(absPath);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Reverse: encoded folder name → best-effort absolute path.
|
|
35
|
+
*
|
|
36
|
+
* Walks the encoded segments, trying each `-` as `/`, `.`, `_`, or literal `-`
|
|
37
|
+
* (in that priority order — `/` first because directory separators are by
|
|
38
|
+
* far the dominant case). Stops on the first interpretation whose path
|
|
39
|
+
* exists on disk. Returns `null` when nothing matches.
|
|
40
|
+
*
|
|
41
|
+
* The walk is depth-first and bounded: with N dashes the worst case is 4^N
|
|
42
|
+
* combinations, but in practice the first-existing-match short-circuit caps
|
|
43
|
+
* runtime to a handful of `existsSync` calls. We cap the dash count at 30 to
|
|
44
|
+
* defend against pathological input — encoded folders longer than that are
|
|
45
|
+
* highly unusual and we just decline to decode them.
|
|
46
|
+
*/
|
|
47
|
+
function decodeProjectFolder(folderName) {
|
|
48
|
+
if (folderName.length === 0) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
// Encoded folders always start with `-` (leading slash). Strip it before
|
|
52
|
+
// splitting so we don't materialize an empty leading segment.
|
|
53
|
+
const trimmed = folderName.startsWith("-") ? folderName.slice(1) : folderName;
|
|
54
|
+
// Split on consecutive dashes — runs of dashes in the encoded form
|
|
55
|
+
// typically represent path separators around alphanumeric segments.
|
|
56
|
+
// Single dashes are ambiguous; we walk them.
|
|
57
|
+
const parts = trimmed.split("-");
|
|
58
|
+
if (parts.length > 31) {
|
|
59
|
+
return null; // too many dashes — refuse to brute-force
|
|
60
|
+
}
|
|
61
|
+
const candidates = ["/", ".", "_", "-"];
|
|
62
|
+
return walk(parts, 0, "/", candidates);
|
|
63
|
+
}
|
|
64
|
+
function walk(parts, idx, accum, candidates) {
|
|
65
|
+
if (idx === parts.length - 1) {
|
|
66
|
+
const final = accum + parts[idx];
|
|
67
|
+
return (0, fs_1.existsSync)(final) ? final : null;
|
|
68
|
+
}
|
|
69
|
+
for (const sep of candidates) {
|
|
70
|
+
const next = accum + parts[idx] + sep;
|
|
71
|
+
// Eager prune: if the partial path's parent doesn't exist for `/`,
|
|
72
|
+
// there's no point recursing — same heuristic for the others, but
|
|
73
|
+
// we only enforce on `/` because non-`/` interpretations are inside
|
|
74
|
+
// the same parent directory and a partial-prefix existsSync isn't
|
|
75
|
+
// meaningful for them.
|
|
76
|
+
if (sep === "/" && !(0, fs_1.existsSync)(accum)) {
|
|
77
|
+
// accum is e.g. "/Users/" — even the parent is missing, give up
|
|
78
|
+
// on further `/` interpretations. But still try the same-dir
|
|
79
|
+
// alternatives below (`.`, `_`, `-`).
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const result = walk(parts, idx + 1, next, candidates);
|
|
83
|
+
if (result !== null) {
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Best-effort decode plus a `(projectDir, projectName)` resolver that always
|
|
91
|
+
* returns something. When the reverse-decode fails, returns the encoded
|
|
92
|
+
* folder name in both fields so downstream consumers (skip rule, marker
|
|
93
|
+
* write) can still proceed — they handle non-existent project dirs
|
|
94
|
+
* gracefully.
|
|
95
|
+
*/
|
|
96
|
+
function resolveProjectFromFolder(folderName) {
|
|
97
|
+
const decoded = decodeProjectFolder(folderName);
|
|
98
|
+
if (decoded !== null) {
|
|
99
|
+
// Use resolveProjectName so the wire `project_name` matches live
|
|
100
|
+
// mode for the same path — walks up looking for `.git`, falls back
|
|
101
|
+
// to basename. Important when the user ran Claude from a subdir of
|
|
102
|
+
// a git repo: live emits the repo basename, import must too.
|
|
103
|
+
return { projectDir: decoded, projectName: (0, actions_1.resolveProjectName)(decoded), existsOnDisk: true };
|
|
104
|
+
}
|
|
105
|
+
// No real path on disk — use the encoded folder name as a synthetic
|
|
106
|
+
// identifier in both fields. Skip rule and marker write handle the
|
|
107
|
+
// non-existent projectDir case downstream.
|
|
108
|
+
return { projectDir: folderName, projectName: folderName, existsOnDisk: false };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=encoding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encoding.js","sourceRoot":"","sources":["../../../src/import/claude/encoding.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;GAmBG;;AAOH,kDAEC;AAgBD,kDAgBC;AAmCD,4DAaC;AAvFD,2BAAgC;AAChC,sDAA8D;AAC9D,2DAAiE;AAEjE,oDAAoD;AACpD,SAAgB,mBAAmB,CAAC,OAAe;IAC/C,OAAO,IAAA,gCAAmB,EAAC,OAAO,CAAC,CAAC;AACxC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,mBAAmB,CAAC,UAAkB;IAClD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,yEAAyE;IACzE,8DAA8D;IAC9D,MAAM,OAAO,GAAW,UAAU,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;IACtF,mEAAmE;IACnE,oEAAoE;IACpE,6CAA6C;IAC7C,MAAM,KAAK,GAAa,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,CAAC,0CAA0C;IAC3D,CAAC;IACD,MAAM,UAAU,GAAa,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAClD,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,IAAI,CAAC,KAAe,EAAE,GAAW,EAAE,KAAa,EAAE,UAAoB;IAC3E,IAAI,GAAG,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAW,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;QACzC,OAAO,IAAA,eAAU,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC5C,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAW,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QAC9C,mEAAmE;QACnE,kEAAkE;QAClE,oEAAoE;QACpE,kEAAkE;QAClE,uBAAuB;QACvB,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC,IAAA,eAAU,EAAC,KAAK,CAAC,EAAE,CAAC;YACpC,gEAAgE;YAChE,6DAA6D;YAC7D,sCAAsC;YACtC,SAAS;QACb,CAAC;QACD,MAAM,MAAM,GAAkB,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;QACrE,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,MAAM,CAAC;QAClB,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,wBAAwB,CAAC,UAAkB;IACvD,MAAM,OAAO,GAAkB,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAC/D,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACnB,iEAAiE;QACjE,mEAAmE;QACnE,mEAAmE;QACnE,6DAA6D;QAC7D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,WAAW,EAAE,IAAA,4BAAkB,EAAC,OAAO,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACjG,CAAC;IACD,oEAAoE;IACpE,mEAAmE;IACnE,2CAA2C;IAC3C,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AACpF,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IronBee CLI — Import file_change derivation.
|
|
3
|
+
*
|
|
4
|
+
* One `file_change` event per `Write`/`Edit` tool_use. Filters via the
|
|
5
|
+
* current project config's verifyPatterns / ignoredVerifyPatterns (since
|
|
6
|
+
* historical config values are unrecoverable, we use the current snapshot).
|
|
7
|
+
*
|
|
8
|
+
* Operation heuristic: live mode uses pre-tool-use `existsSync`, which we
|
|
9
|
+
* cannot replay. We inspect the matched `tool_result.content` for a
|
|
10
|
+
* "created"/"updated" marker and default to "update" on miss.
|
|
11
|
+
*/
|
|
12
|
+
import { FileChangeAction } from "../../../hooks/core/actions";
|
|
13
|
+
import { IronBeeConfig } from "../../../lib/config";
|
|
14
|
+
import { RawToolUse, RawToolResult } from "./tool-call";
|
|
15
|
+
export interface BuildFileChangeOpts {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
projectName: string;
|
|
18
|
+
/** Parent turn's activity_id. */
|
|
19
|
+
activityId: string;
|
|
20
|
+
/** ISO timestamp from the assistant line. */
|
|
21
|
+
timestamp: string;
|
|
22
|
+
toolUse: RawToolUse;
|
|
23
|
+
toolResult: RawToolResult | null;
|
|
24
|
+
config: IronBeeConfig;
|
|
25
|
+
}
|
|
26
|
+
/** Returns null when the tool_use is not a Write/Edit, or the file is filtered. */
|
|
27
|
+
export declare function buildFileChange(opts: BuildFileChangeOpts): FileChangeAction | null;
|
|
28
|
+
//# sourceMappingURL=file-change.d.ts.map
|