feat(main): opt-in prompt logging#95
Conversation
|
Warning Review limit reached
Next review available in: 55 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughAdds a ChangesPrompt capture config and telemetry
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Thanks for adding this. I think the feature is useful, but I want to clarify the behavior before we merge because prompts are already exported today in trace data. Currently prompt text is attached to OTel spans via OpenInference attributes:
So this PR does not add prompt capture for the first time. It adds an opt-in copy of the prompt into the That distinction matters for privacy/security expectations. With this change, Could you update the README/startup wording to make that explicit? Something like:
Also, repo convention is that config values are available both as I’m supportive of the feature as log enrichment, but I’d like the naming/docs to avoid implying this is the only control for prompt export. |
|
fair point, I'll modify the naming and documentation to make that clearer |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/config.ts`:
- Around line 13-16: The config naming for prompt capture is inconsistent
between the code and docs, so align the feature name across `PluginConfig`, the
env var parsing in the config module, and any related README references. Update
the `capturePromptInLogs`/`OPENCODE_CAPTURE_PROMPT_IN_LOGS` naming to the agreed
`capturePrompt` convention everywhere it is defined or consumed, and make sure
the option-to-env mapping matches what users are told to set.
In `@tests/config.test.ts`:
- Around line 337-469: Add a loadConfig precedence test for capturePromptInLogs
in the loadConfig options describe block, mirroring the existing option-over-env
coverage for enabled, endpoint, and protocol. Verify that when the env var is
set and the option is explicitly provided, the option value wins, using the
loadConfig symbol and the capturePromptInLogs field so the new test stays
aligned with the rest of this suite.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 46a48332-ba0e-4b60-bb07-409fbf68cb40
📒 Files selected for processing (4)
README.mdsrc/config.tssrc/index.tstests/config.test.ts
✅ Files skipped from review due to trivial changes (1)
- README.md
🚧 Files skipped from review as they are similar to previous changes (1)
- src/index.ts
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/config.ts`:
- Around line 13-16: The config naming for prompt capture is inconsistent
between the code and docs, so align the feature name across `PluginConfig`, the
env var parsing in the config module, and any related README references. Update
the `capturePromptInLogs`/`OPENCODE_CAPTURE_PROMPT_IN_LOGS` naming to the agreed
`capturePrompt` convention everywhere it is defined or consumed, and make sure
the option-to-env mapping matches what users are told to set.
In `@tests/config.test.ts`:
- Around line 337-469: Add a loadConfig precedence test for capturePromptInLogs
in the loadConfig options describe block, mirroring the existing option-over-env
coverage for enabled, endpoint, and protocol. Verify that when the env var is
set and the option is explicitly provided, the option value wins, using the
loadConfig symbol and the capturePromptInLogs field so the new test stays
aligned with the rest of this suite.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 46a48332-ba0e-4b60-bb07-409fbf68cb40
📒 Files selected for processing (4)
README.mdsrc/config.tssrc/index.tstests/config.test.ts
✅ Files skipped from review due to trivial changes (1)
- README.md
🚧 Files skipped from review as they are similar to previous changes (1)
- src/index.ts
🛑 Comments failed to post (2)
src/config.ts (1)
13-16: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Env var/option name mismatches README docs.
Code uses
capturePromptInLogs/OPENCODE_CAPTURE_PROMPT_IN_LOGS, but the README (per cross-file evidence) documentsOPENCODE_CAPTURE_PROMPTfor the same feature. Per the PR objectives, the reviewer requestedcapturePromptnaming for parity with repo conventions, and the author agreed to align naming/docs — this file doesn't yet reflect that update. Users following the README will set the wrong env var and see no effect.Also applies to: 56-59, 190-190
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/config.ts` around lines 13 - 16, The config naming for prompt capture is inconsistent between the code and docs, so align the feature name across `PluginConfig`, the env var parsing in the config module, and any related README references. Update the `capturePromptInLogs`/`OPENCODE_CAPTURE_PROMPT_IN_LOGS` naming to the agreed `capturePrompt` convention everywhere it is defined or consumed, and make sure the option-to-env mapping matches what users are told to set.tests/config.test.ts (1)
337-469: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Missing option→env precedence test for
capturePromptInLogs.Every other field in this describe block (
enabled,logsEnabled,endpoint,protocol, etc.) has a test confirming the option value overrides the env var.capturePromptInLogshas no equivalent test here — only the default/env-set cases are covered above. This is explicitly called out in the PR objectives as a requested addition.✅ Suggested test to add
+ test("option capturePromptInLogs overrides an enabling env var", () => { + process.env["OPENCODE_CAPTURE_PROMPT_IN_LOGS"] = "1" + expect(loadConfig({ capturePromptInLogs: false }).capturePromptInLogs).toBe(false) + })📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.describe("loadConfig options", () => { const vars = [ "OPENCODE_ENABLE_TELEMETRY", "OPENCODE_OTLP_ENDPOINT", "OPENCODE_OTLP_PROTOCOL", "OPENCODE_OTLP_METRICS_INTERVAL", "OPENCODE_OTLP_LOGS_INTERVAL", "OPENCODE_METRIC_PREFIX", "OPENCODE_OTLP_HEADERS", "OPENCODE_RESOURCE_ATTRIBUTES", "OPENCODE_OTLP_METRICS_TEMPORALITY", "OPENCODE_DISABLE_METRICS", "OPENCODE_DISABLE_LOGS", "OPENCODE_DISABLE_TRACES", "OTEL_EXPORTER_OTLP_HEADERS", "OTEL_RESOURCE_ATTRIBUTES", "OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE", ] beforeEach(() => vars.forEach((k) => delete process.env[k])) afterEach(() => vars.forEach((k) => delete process.env[k])) test("enabled via option without any env var", () => { expect(loadConfig({ enabled: true }).enabled).toBe(true) }) test("option enabled:false overrides an enabling env var", () => { process.env["OPENCODE_ENABLE_TELEMETRY"] = "1" expect(loadConfig({ enabled: false }).enabled).toBe(false) }) test("option logsEnabled:false disables logs", () => { expect(loadConfig({ logsEnabled: false }).logsEnabled).toBe(false) }) test("option capturePromptInLogs overrides an enabling env var", () => { process.env["OPENCODE_CAPTURE_PROMPT_IN_LOGS"] = "1" expect(loadConfig({ capturePromptInLogs: false }).capturePromptInLogs).toBe(false) }) test("option endpoint overrides env var", () => { process.env["OPENCODE_OTLP_ENDPOINT"] = "http://from-env:4317" expect(loadConfig({ endpoint: "http://from-option:4317" }).endpoint).toBe("http://from-option:4317") }) test("env endpoint used when option is absent", () => { process.env["OPENCODE_OTLP_ENDPOINT"] = "http://from-env:4317" expect(loadConfig({ metricPrefix: "x." }).endpoint).toBe("http://from-env:4317") }) test("option protocol overrides env var", () => { process.env["OPENCODE_OTLP_PROTOCOL"] = "grpc" expect(loadConfig({ protocol: "http/protobuf" }).protocol).toBe("http/protobuf") }) test("option intervals override env vars", () => { process.env["OPENCODE_OTLP_METRICS_INTERVAL"] = "30000" const cfg = loadConfig({ metricsInterval: 15000, logsInterval: 2500 }) expect(cfg.metricsInterval).toBe(15000) expect(cfg.logsInterval).toBe(2500) }) test("invalid option interval falls back to env then default", () => { process.env["OPENCODE_OTLP_METRICS_INTERVAL"] = "45000" const cfg = loadConfig({ metricsInterval: 0, logsInterval: -1 }) expect(cfg.metricsInterval).toBe(45000) expect(cfg.logsInterval).toBe(5000) }) test("non-number option interval is ignored", () => { const cfg = loadConfig({ metricsInterval: "soon" } as unknown as Parameters<typeof loadConfig>[0]) expect(cfg.metricsInterval).toBe(60000) }) test("null options are handled safely", () => { expect(() => loadConfig(null as unknown as Parameters<typeof loadConfig>[0])).not.toThrow() expect(loadConfig(null as unknown as Parameters<typeof loadConfig>[0]).endpoint).toBe("http://localhost:4317") }) test("option metricPrefix overrides env var", () => { process.env["OPENCODE_METRIC_PREFIX"] = "env." expect(loadConfig({ metricPrefix: "claude_code." }).metricPrefix).toBe("claude_code.") }) test("option otlpHeaders is copied to OTEL_EXPORTER_OTLP_HEADERS", () => { const cfg = loadConfig({ otlpHeaders: "api-key=opt" }) expect(cfg.otlpHeaders).toBe("api-key=opt") expect(process.env["OTEL_EXPORTER_OTLP_HEADERS"]).toBe("api-key=opt") }) test("option resourceAttributes is copied to OTEL_RESOURCE_ATTRIBUTES", () => { const cfg = loadConfig({ resourceAttributes: "team=platform" }) expect(cfg.resourceAttributes).toBe("team=platform") expect(process.env["OTEL_RESOURCE_ATTRIBUTES"]).toBe("team=platform") }) test("option metricsTemporality is normalized and copied to OTEL preference", () => { const cfg = loadConfig({ metricsTemporality: "delta" }) expect(cfg.metricsTemporality).toBe("delta") expect(process.env["OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE"]).toBe("delta") }) test("invalid protocol option falls back to env then default", () => { process.env["OPENCODE_OTLP_PROTOCOL"] = "http/json" expect(loadConfig({ protocol: "ftp" as never }).protocol).toBe("http/json") delete process.env["OPENCODE_OTLP_PROTOCOL"] expect(loadConfig({ protocol: "ftp" as never }).protocol).toBe("grpc") }) test("invalid metricsTemporality option falls back to env then default", () => { process.env["OPENCODE_OTLP_METRICS_TEMPORALITY"] = "lowmemory" expect(loadConfig({ metricsTemporality: "weekly" as never }).metricsTemporality).toBe("lowmemory") delete process.env["OPENCODE_OTLP_METRICS_TEMPORALITY"] expect(loadConfig({ metricsTemporality: "weekly" as never }).metricsTemporality).toBeUndefined() }) test("option disabledMetrics array overrides env var", () => { process.env["OPENCODE_DISABLE_METRICS"] = "session.count" const { disabledMetrics } = loadConfig({ disabledMetrics: ["cache.count", "retry.count"] }) expect(disabledMetrics).toEqual(new Set(["cache.count", "retry.count"])) }) test("option disabledTraces array expands all to every trace type", () => { expect(loadConfig({ disabledTraces: ["all"] }).disabledTraces).toEqual(new Set(TRACE_TYPES)) }) test("option disabledTraces array trims and lowercases entries", () => { const { disabledTraces } = loadConfig({ disabledTraces: [" LLM ", "Tool"] }) expect(disabledTraces).toEqual(new Set(["llm", "tool"])) }) test("env values still apply when no options are passed", () => { process.env["OPENCODE_ENABLE_TELEMETRY"] = "1" process.env["OPENCODE_OTLP_ENDPOINT"] = "http://env:4317" const cfg = loadConfig() expect(cfg.enabled).toBe(true) expect(cfg.endpoint).toBe("http://env:4317") }) })🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/config.test.ts` around lines 337 - 469, Add a loadConfig precedence test for capturePromptInLogs in the loadConfig options describe block, mirroring the existing option-over-env coverage for enabled, endpoint, and protocol. Verify that when the env var is set and the option is explicitly provided, the option value wins, using the loadConfig symbol and the capturePromptInLogs field so the new test stays aligned with the rest of this suite.
Description
Add the opt-in ability to log prompts.
Type of change
Checklist
bun run lintpasses with no errorsbun run check:jsdoc-coveragepasses with no errorsbun run typecheckpasses with no errorsbun testpasses with no errorsRelated issues
None related found
Additional context
N/A
Summary by CodeRabbit
New Features
user_prompttelemetry events.OPENCODE_CAPTURE_PROMPT_IN_LOGSto control this behavior (off by default).Bug Fixes
user_promptevents now include the full prompt only when prompt capture is enabled.Documentation
Tests