feat: add evlog/eve integration#399
Conversation
Export defineEvlogHook and useTurnLogger for one wide event per Eve turn, share turn state across authored-module bundles, and harden finalizeAudit.
Ship a support-refund copilot with useEveAgent, tool latency, and evlog wide events; wire example:eve and eve>ai workspace override.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR adds eve-scoped turn logging and audit handling in Changesevlog/eve core integration
examples/eve support demo
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 |
|
Thank you for following the naming conventions! 🙏 |
evlog/eve integration
commit: |
evlog/eve integrationevlog/eve integration
There was a problem hiding this comment.
Actionable comments posted: 20
🤖 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 @.github/pull_request_template.md:
- Line 47: The scopes list in the pull request template is out of alphabetical
order because the `eve` entry is placed between `orpc` and `otlp`; move the `eve
(eve agent integration)` bullet so it sits between `elysia` and `express` in the
list, keeping the ordering consistent with the surrounding scope entries.
In `@apps/docs/content/4.use-cases/5.eve.md`:
- Around line 163-174: The keep example in defineEvlogHook is using the wrong
token field name, so update the snippet to read from the documented ai
inputTokens/outputTokens fields instead of totalTokens. In the keep callback,
derive the high-usage threshold from the available token counts on
ctx.context.ai, and keep the failed-tools check unchanged so the example remains
copy-pastable and consistent with the rest of the page.
In `@examples/eve/agent/channels/eve.ts`:
- Around line 1-2: Remove the stray semicolons to satisfy the ESLint semi rule
in this module; update the import statements in eve.ts and any other affected
statement in the same file so the syntax matches the project’s no-semicolon
style.
- Around line 5-13: Replace the placeholder auth in the eve channel config
before shipping this example. In `auth` within `eve.ts`, swap
`placeholderAuth()` for a real provider such as Auth.js or Clerk, or `none()` if
this is meant to be a public demo. Keep `localDev()` and `vercelOidc()` as-is,
and remove the placeholder so browser requests can authenticate in production.
In `@examples/eve/agent/tools/issue_refund.ts`:
- Around line 16-19: The approval-threshold check is duplicated between
needsApproval and the requiresApproval logic used in execute, which can drift
over time. Extract a shared helper in issue_refund.ts that computes whether an
order amount exceeds REFUND_APPROVAL_THRESHOLD_USD, and use that helper in both
the needsApproval callback and the execute audit logging so gating and logging
always stay consistent.
In `@examples/eve/app/layout.tsx`:
- Around line 28-36: The app root in RootLayout already provides
TooltipProvider, so the extra nested provider in MessageAction is redundant.
Update MessageAction in the message component to stop wrapping the button with
its own TooltipProvider when a tooltip exists, and rely on the provider
established by RootLayout instead; keep the tooltip content/trigger behavior
intact while removing the unnecessary inner provider.
In `@examples/eve/components/ai-elements/chain-of-thought.tsx`:
- Around line 50-55: The ChainOfThought header and content are currently
rendered under separate Collapsible roots, so their accessibility wiring is
disconnected even though they share isOpen. Update ChainOfThought to use a
single Collapsible root around both the header trigger and the content, and keep
the existing ChainOfThoughtContext/ChainOfThought components wired together so
the shared state drives one Radix instance.
In `@examples/eve/components/ai-elements/code-block.tsx`:
- Around line 137-141: The cache key in getTokensCacheKey is too weak because it
only uses language, length, prefix, and suffix, which can collide for different
code snippets. Update getTokensCacheKey in code-block.tsx to derive the key from
the full source text or a real hash of the entire code string so TokenizedCode
entries cannot be reused across different blocks with the same partial shape.
In `@examples/eve/components/ai-elements/message.tsx`:
- Around line 276-286: The custom comparator in MessageResponse is too narrow
and skips re-renders when className or other Streamdown props change. Update the
memo comparison logic for MessageResponse so it either compares all relevant
props passed through to Streamdown or remove the bespoke comparator and rely on
the default behavior. Keep the fix scoped to MessageResponse and ensure prop
changes besides children and isAnimating are not ignored.
In `@examples/eve/components/ai-elements/prompt-input.tsx`:
- Around line 802-806: The uncontrolled textarea is being cleared too early in
PromptInput, before the submit flow has actually succeeded. Update PromptInput
so the non-provider path does not call form.reset() immediately after capturing
the text; instead, mirror the provider branch by keeping the local text until
onSubmit/agent.send completes successfully, and only clear it after success.
Make sure the retry behavior in agent-chat preserves the typed prompt when a
send fails.
In `@examples/eve/components/ai-elements/reasoning.tsx`:
- Around line 146-154: The default thinking message used by
defaultGetThinkingMessage is rendering block-level elements inside
CollapsibleTrigger’s button, which creates invalid markup. Update the streaming
and non-streaming branches to return inline content only, and make sure Shimmer
in examples/eve/components/ai-elements/shimmer.tsx also renders inline when used
there so the trigger content stays button-safe.
In `@examples/eve/components/ai-elements/shimmer.tsx`:
- Around line 12-15: The shimmer component type annotation is referencing
React.ComponentType without importing React, so the file fails type-check.
Update the type usage in shimmer.tsx by importing ComponentType as a type from
react and replacing the React.ComponentType reference in motionComponentCache
with the imported ComponentType symbol.
In `@examples/eve/components/ai-elements/tool.tsx`:
- Around line 127-130: The ToolOutput component is treating valid falsy outputs
like 0, false, and empty string as missing because it relies on truthiness in
the early return. Update ToolOutput to check output and errorText for null or
undefined instead of using !(output || errorText), so legitimate falsy values
still render. Keep the fix localized to ToolOutput and preserve the existing
behavior for truly absent values.
- Around line 98-104: The CollapsibleContent styling in tool.tsx references
animation utilities that are not available in this example, so the open/close
transitions will not work. Either add the missing animation support used by the
className passed to CollapsibleContent (including animate-in, animate-out,
fade-out-0, and slide-* utilities), or remove those transition classes from the
cn() call so the component uses only supported Tailwind styles.
In `@examples/eve/components/ui/collapsible.tsx`:
- Around line 5-18: The Collapsible component types are referencing
React.ComponentProps without importing React, so update the type usage in
Collapsible, CollapsibleTrigger, and CollapsibleContent to use ComponentProps
imported from react. Add the type-only import at the top of the file and replace
the React.ComponentProps references so the file type-checks without relying on
an undeclared React identifier.
In `@examples/eve/components/ui/input-group.tsx`:
- Around line 69-74: The click handler in InputGroup currently focuses only an
input element, which misses other shared controls like InputGroupTextarea used
by the prompt composer. Update the onClick logic in InputGroup to target the
shared control slot instead of querySelector("input"), so clicking the addon
chrome focuses whichever control is rendered there. Keep the existing button
guard and use the InputGroup control container or equivalent shared selector
from the InputGroup component.
In `@examples/eve/lib/utils.ts`:
- Around line 1-6: The imports and function in cn currently use semicolons,
which conflicts with the repo’s no-semicolon style and triggers ESLint. Update
the statements in cn and its import lines to match the surrounding codebase
style by removing the extra semicolons, while keeping the exported cn helper and
its twMerge(clsx(inputs)) behavior unchanged.
In `@package.json`:
- Line 27: Update the example:eve script to run through Turbo like the other
example scripts instead of invoking pnpm directly. In package.json, change the
example:eve entry so it uses turbo run dev with the evlog-eve-example filter,
ensuring dev:prepare runs before startup. This keeps the script aligned with the
existing example script pattern and avoids the missing packages/evlog/dist issue
when importing evlog/* subpaths.
In `@packages/evlog/src/eve/index.ts`:
- Around line 247-261: Always clear per-turn state even when state.finish()
fails in finishTurn. Update finishTurn in eve/index.ts so the cleanup of
turnStates() and activeTurnBySession() happens in a finally path after
flushAi(state) and await state.finish(opts), ensuring turn.completed/turn.failed
callers do not leave stale entries on drain/enrich outages. Use the finishTurn
helper and the turnStates()/activeTurnBySession() maps as the main touchpoints.
- Around line 98-103: ensureInit() currently calls initLogger() unconditionally
on the first Eve setup, which can overwrite an app’s existing logger
configuration. Update ensureInit() in eve/index.ts to avoid reinitializing the
global logger: either skip initLogger() when logging is already configured, or
merge only the missing env.service value into the existing options before
calling initLogger(). Keep the existing isEveInitialized(), setEveInitialized(),
and initialized flow intact.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 5c6219d3-2f2b-43c3-84e1-db54ef9dd039
⛔ Files ignored due to path filters (5)
apps/docs/app/assets/icons/eve.svgis excluded by!**/*.svgapps/docs/public/eve-logo.svgis excluded by!**/*.svgexamples/eve/public/eve-logo.svgis excluded by!**/*.svgpackages/evlog/test/toolkit/__snapshots__/api-surface.test.ts.snapis excluded by!**/*.snappnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (66)
.changeset/eve-integration.md.github/pull_request_template.md.github/workflows/semantic-pull-request.yml.gitignoreapps/docs/config/redirects.tsapps/docs/content/4.use-cases/0.overview.mdapps/docs/content/4.use-cases/5.eve.mdapps/docs/nuxt.config.tsexamples/eve/.gitignoreexamples/eve/README.mdexamples/eve/agent/agent.tsexamples/eve/agent/channels/eve.tsexamples/eve/agent/hooks/evlog.tsexamples/eve/agent/instructions.mdexamples/eve/agent/lib/fake-latency.tsexamples/eve/agent/lib/support-data.tsexamples/eve/agent/tools/issue_refund.tsexamples/eve/agent/tools/lookup_customer.tsexamples/eve/agent/tools/lookup_order.tsexamples/eve/app/_components/agent-chat.tsxexamples/eve/app/_components/agent-message.tsxexamples/eve/app/_components/eve-logo.tsxexamples/eve/app/globals.cssexamples/eve/app/layout.tsxexamples/eve/app/page.tsxexamples/eve/components.jsonexamples/eve/components/ai-elements/chain-of-thought.tsxexamples/eve/components/ai-elements/code-block.tsxexamples/eve/components/ai-elements/conversation.tsxexamples/eve/components/ai-elements/message.tsxexamples/eve/components/ai-elements/prompt-input.tsxexamples/eve/components/ai-elements/reasoning.tsxexamples/eve/components/ai-elements/shimmer.tsxexamples/eve/components/ai-elements/tool.tsxexamples/eve/components/ui/badge.tsxexamples/eve/components/ui/button-group.tsxexamples/eve/components/ui/button.tsxexamples/eve/components/ui/collapsible.tsxexamples/eve/components/ui/command.tsxexamples/eve/components/ui/dialog.tsxexamples/eve/components/ui/dropdown-menu.tsxexamples/eve/components/ui/hover-card.tsxexamples/eve/components/ui/input-group.tsxexamples/eve/components/ui/input.tsxexamples/eve/components/ui/select.tsxexamples/eve/components/ui/separator.tsxexamples/eve/components/ui/spinner.tsxexamples/eve/components/ui/textarea.tsxexamples/eve/components/ui/tooltip.tsxexamples/eve/css.d.tsexamples/eve/lib/utils.tsexamples/eve/next-env.d.tsexamples/eve/next.config.tsexamples/eve/package.jsonexamples/eve/postcss.config.mjsexamples/eve/tsconfig.agent.jsonexamples/eve/tsconfig.jsonpackage.jsonpackages/evlog/README.mdpackages/evlog/package.jsonpackages/evlog/src/audit.tspackages/evlog/src/eve/index.tspackages/evlog/test/core/audit.test.tspackages/evlog/test/eve.test.tspackages/evlog/tsdown.config.tspnpm-workspace.yaml
| auth: [ | ||
| // Open on localhost for `eve dev` and the REPL; ignored in production. | ||
| localDev(), | ||
| // Lets the eve TUI and your Vercel deployments reach the deployed agent. | ||
| vercelOidc(), | ||
| // This placeholder will not allow browser requests in production. | ||
| // Replace it with your app's auth provider, like Auth.js or Clerk, | ||
| // or use none() for a public demo. | ||
| placeholderAuth(), |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== File outline ==\n'
ast-grep outline examples/eve/agent/channels/eve.ts --view expanded || true
printf '\n== File contents ==\n'
cat -n examples/eve/agent/channels/eve.ts
printf '\n== Search for placeholderAuth references ==\n'
rg -n "placeholderAuth\(|vercelOidc\(|localDev\(" examples/eve -S || true
printf '\n== Search for related docs/comments ==\n'
rg -n "placeholderAuth|public demo|browser requests in production|vercelOidc|localDev|eve dev|Next.js copilot" -S . || trueRepository: HugoRCD/evlog
Length of output: 1815
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== Auth helper definitions ==\n'
rg -n "placeholderAuth|localDev|vercelOidc|none\(" . -S --glob '!**/node_modules/**' || true
printf '\n== Lint / formatting config ==\n'
rg -n '"semi"|semi:|`@typescript-eslint/semi`|prettier|biome|eslint' . -S --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' || true
printf '\n== Example docs mentioning deploy/public demo ==\n'
rg -n "public demo|deploy|production|browser requests|auth provider|none\(\)" examples README.md . -S --glob '!**/node_modules/**' || trueRepository: HugoRCD/evlog
Length of output: 50369
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== Auth helper definition file(s) ==\n'
fd -a "auth.*" examples/eve packages . | sed -n '1,40p'
printf '\n== Relevant source slices ==\n'
for f in \
examples/eve/agent/channels/eve.ts \
eslint.config.mjs \
examples/eve/package.json
do
if [ -f "$f" ]; then
printf '\n--- %s ---\n' "$f"
cat -n "$f" | sed -n '1,220p'
fi
done
printf '\n== Semicolon-related lint config ==\n'
rg -n "semi|no-extra-semi|semi-style|`@typescript-eslint/semi`" eslint.config.mjs package.json examples/eve/package.json packages/evlog/package.json . -S --glob '!**/node_modules/**' || trueRepository: HugoRCD/evlog
Length of output: 21559
🌐 Web query:
Eve auth placeholderAuth localDev vercelOidc none public demo documentation
💡 Result:
In the Eve Agent Framework, authentication for channels is managed via the auth configuration in the eveChannel definition [1][2][3]. The framework is designed to be "fail-closed," meaning unconfigured channels default to a restrictive policy that rejects production browser traffic [1][4][3]. The components mentioned serve specific roles in this authentication lifecycle: 1. placeholderAuth: This is a guardrail provided by the eve init scaffolding [1]. It returns a structured 401 error, allowing the application to indicate that authentication is not yet configured rather than throwing an internal error [1]. It must be replaced with a real authentication policy before moving to production [1][4]. 2. localDev: This helper authenticates a synthetic local-dev principal [1]. It is designed for development and only functions when the request is addressed to a loopback hostname (such as localhost, 127.0.0.1, or::1) [1][3]. There is an exception for vercel dev environments when VERCEL=1 and VERCEL_ENV=development are both set [1]. 3. vercelOidc: This is a built-in helper used to verify Vercel OIDC tokens [1]. It is intended for production environments deployed on Vercel [4][3]. 4. none: For public-facing demos, the none() helper can be used to skip authentication entirely [3]. When setting up your agent/channels/eve.ts file, you typically define an array of these authenticators [1][3]. The default configuration for an unauthored file is [localDev(), vercelOidc()] [3]. To secure a production application, you should replace placeholderAuth() with a production-ready policy, such as httpBasic(), jwtHmac(), jwtEcdsa(), oidc(), or a custom AuthFn that validates your specific session or identity provider requirements [4]. Note that the Python Eve framework is a separate project (a REST API framework) and has its own distinct authentication system (e.g., BasicAuth, TokenAuth, HMAC) [5][6], which should not be confused with the Eve Agent Framework described here.
Citations:
- 1: https://unpkg.com/eve@0.13.3/docs/guides/auth-and-route-protection.md
- 2: https://eve.dev/docs/reference/typescript-api
- 3: https://eve.dev/docs/guides/frontend/nuxt
- 4: https://eve.dev/docs/guides/deployment
- 5: https://docs.python-eve.org/en/stable/authentication.html
- 6: https://docs.python-eve.org/en/latest/authentication.html
Replace placeholderAuth() before shipping this example.
It returns 401 for browser requests in production, so the deployed app won’t be able to talk to the agent unless you swap in a real auth provider or none() for a public demo.
🤖 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 `@examples/eve/agent/channels/eve.ts` around lines 5 - 13, Replace the
placeholder auth in the eve channel config before shipping this example. In
`auth` within `eve.ts`, swap `placeholderAuth()` for a real provider such as
Auth.js or Clerk, or `none()` if this is meant to be a public demo. Keep
`localDev()` and `vercelOidc()` as-is, and remove the placeholder so browser
requests can authenticate in production.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
examples/eve/components/ai-elements/tool.tsx (1)
124-135: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winExplicit
nulloutput still renders literal "null" alongside an error.
typeof null === "object"istruein JS, so whenoutputis explicitlynullanderrorTextis set, the early-return is skipped and the object branch runsJSON.stringify(null, null, 2), rendering the text"null"under the error message.🐛 Proposed fix
let Output = <div>{output as ReactNode}</div>; - if (typeof output === "object" && !isValidElement(output)) { + if (output !== null && typeof output === "object" && !isValidElement(output)) { Output = <CodeBlock code={JSON.stringify(output, null, 2)} language="json" />; } else if (typeof output === "string") { Output = <CodeBlock code={output} language="json" />; }🤖 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 `@examples/eve/components/ai-elements/tool.tsx` around lines 124 - 135, ToolOutput currently treats explicit null as an object, so when errorText is present it still renders JSON.stringify(null) and shows literal "null" in the UI. Update ToolOutput in tool.tsx to explicitly guard against null before the typeof output === "object" branch, and keep the existing early return behavior for null output when appropriate so the error display does not include a stray null.examples/eve/components/ai-elements/prompt-input.tsx (2)
682-737: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate drag/drop handler bodies across form-local and document-global effects.
onDragOver/onDropare defined identically in bothuseEffects, differing only by the target (formvsdocument). Extract a shared factory (e.g.,createDropHandlers(add)) to avoid keeping two copies in sync.♻️ Proposed refactor sketch
+ const createDropHandlers = useCallback( + () => ({ + onDragOver: (e: DragEvent) => { + if (e.dataTransfer?.types?.includes("Files")) { + e.preventDefault(); + } + }, + onDrop: (e: DragEvent) => { + if (e.dataTransfer?.types?.includes("Files")) { + e.preventDefault(); + } + if (e.dataTransfer?.files && e.dataTransfer.files.length > 0) { + add(e.dataTransfer.files); + } + }, + }), + [add], + );Both effects would then call
const { onDragOver, onDrop } = createDropHandlers();and only differ in theaddEventListenertarget.🤖 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 `@examples/eve/components/ai-elements/prompt-input.tsx` around lines 682 - 737, There are duplicated drag-and-drop handler bodies in the two useEffect blocks in prompt-input.tsx; extract the shared onDragOver/onDrop logic into a helper or factory such as createDropHandlers(add) so both the form-local and document-global effects reuse the same handlers. Keep the effects themselves focused on choosing the event target (formRef.current vs document) and wiring/unwiring listeners, while the shared helper owns the Files check, preventDefault behavior, and add(e.dataTransfer.files) call.
538-583: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicate file-validation logic in
addLocalandaddWithProviderValidation.Both functions repeat the same accept-type filtering, "No files match the accepted types" error, size filtering, and "All files exceed the maximum size" error. Extract a shared
validateFiles(fileList)helper returning the accepted/sized files (or emitting the appropriateonError) to avoid divergence.♻️ Proposed refactor sketch
+ const validateFiles = useCallback( + (fileList: File[] | FileList) => { + const incoming = [...fileList]; + const accepted = incoming.filter((f) => matchesAccept(f)); + if (incoming.length && accepted.length === 0) { + onError?.({ code: "accept", message: "No files match the accepted types." }); + return null; + } + const withinSize = (f: File) => (maxFileSize ? f.size <= maxFileSize : true); + const sized = accepted.filter(withinSize); + if (accepted.length > 0 && sized.length === 0) { + onError?.({ code: "max_file_size", message: "All files exceed the maximum size." }); + return null; + } + return sized; + }, + [matchesAccept, maxFileSize, onError], + );Then both
addLocalandaddWithProviderValidationcallvalidateFiles(fileList)and only implement the capacity-capping + storage logic that differs between them.Also applies to: 598-635
🤖 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 `@examples/eve/components/ai-elements/prompt-input.tsx` around lines 538 - 583, `addLocal` duplicates the same file-validation flow used by `addWithProviderValidation` (accept filtering, empty-accept error, size filtering, and max-size error). Extract that shared logic into a helper like `validateFiles(fileList)` in `prompt-input.tsx` that returns the accepted/sized files or triggers `onError`, then have both `addLocal` and `addWithProviderValidation` call it and keep only their differing capacity/storage behavior.
🤖 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 `@packages/evlog/src/eve/index.ts`:
- Line 4: `ensureInit()` in `eve/index.ts` still allows `initLogger()` to run
again on the first Eve turn because it only checks `isLoggerLocked()`, which is
not set in the Eve path. Add a real Eve-side initialization guard in
`ensureInit()` (or lock the logger during adapter setup) so `initLogger()` is
only called once and cannot overwrite existing env/drain/sampling configuration.
Use the existing `ensureInit`, `initLogger`, and `isLoggerLocked` symbols to
locate and update the guard logic.
---
Outside diff comments:
In `@examples/eve/components/ai-elements/prompt-input.tsx`:
- Around line 682-737: There are duplicated drag-and-drop handler bodies in the
two useEffect blocks in prompt-input.tsx; extract the shared onDragOver/onDrop
logic into a helper or factory such as createDropHandlers(add) so both the
form-local and document-global effects reuse the same handlers. Keep the effects
themselves focused on choosing the event target (formRef.current vs document)
and wiring/unwiring listeners, while the shared helper owns the Files check,
preventDefault behavior, and add(e.dataTransfer.files) call.
- Around line 538-583: `addLocal` duplicates the same file-validation flow used
by `addWithProviderValidation` (accept filtering, empty-accept error, size
filtering, and max-size error). Extract that shared logic into a helper like
`validateFiles(fileList)` in `prompt-input.tsx` that returns the accepted/sized
files or triggers `onError`, then have both `addLocal` and
`addWithProviderValidation` call it and keep only their differing
capacity/storage behavior.
In `@examples/eve/components/ai-elements/tool.tsx`:
- Around line 124-135: ToolOutput currently treats explicit null as an object,
so when errorText is present it still renders JSON.stringify(null) and shows
literal "null" in the UI. Update ToolOutput in tool.tsx to explicitly guard
against null before the typeof output === "object" branch, and keep the existing
early return behavior for null output when appropriate so the error display does
not include a stray null.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 6827f669-a0bd-4ae3-81d6-d2b027dd0f05
📒 Files selected for processing (18)
.github/pull_request_template.mdapps/docs/content/4.use-cases/5.eve.mdexamples/eve/README.mdexamples/eve/agent/channels/eve.tsexamples/eve/agent/tools/issue_refund.tsexamples/eve/components/ai-elements/chain-of-thought.tsxexamples/eve/components/ai-elements/code-block.tsxexamples/eve/components/ai-elements/message.tsxexamples/eve/components/ai-elements/prompt-input.tsxexamples/eve/components/ai-elements/reasoning.tsxexamples/eve/components/ai-elements/shimmer.tsxexamples/eve/components/ai-elements/tool.tsxexamples/eve/components/ui/collapsible.tsxexamples/eve/components/ui/input-group.tsxexamples/eve/lib/utils.tspackage.jsonpackages/evlog/src/eve/index.tspackages/evlog/test/eve.test.ts
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 `@examples/eve/components/ai-elements/prompt-input.tsx`:
- Line 593: The file validation flow in validateIncomingFiles and matchesAccept
only handles MIME-style accept rules, so extension-based patterns like ".pdf"
are rejected even though the input allows them. Update matchesAccept to also
recognize extension tokens (and any combined accept lists like ".pdf,image/*")
before the rejection path, and make sure the same logic is used for both
dropped/pasted files and the other validation call site referenced in this
change.
In `@examples/eve/components/ai-elements/tool.tsx`:
- Around line 131-133: Guard the object-to-JSON rendering path in tool.tsx so a
bad tool result cannot crash the component. In the output handling branch inside
the component that builds Output, wrap the JSON.stringify call in a safe
serialization path and fall back to a placeholder or string when serialization
fails for circular references or BigInt values. Keep the existing object check
and isValidElement logic, but ensure the CodeBlock only receives a serialized
string when it can be produced safely.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 3ce54784-d8f0-4bcc-aae0-5df605489ff6
📒 Files selected for processing (5)
examples/eve/components/ai-elements/prompt-input.tsxexamples/eve/components/ai-elements/tool.tsxpackages/evlog/src/eve/index.tspackages/evlog/src/logger.tspackages/evlog/test/eve.test.ts
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/eve/agent/hooks/evlog.ts (1)
17-29: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winRefund amount sampling is unreachable. Successful refunds always record
status: 'refunded'inexamples/eve/agent/tools/issue_refund.ts, so this||keeps every refunded order and the> 100check never matters. Remove the status branch if amount-based sampling is still intended.🤖 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 `@examples/eve/agent/hooks/evlog.ts` around lines 17 - 29, The refund sampling logic in keep() is effectively always enabled for refunded orders because issue_refund.ts always sets context.refund.status to refunded, making the amount-based condition unreachable. Update the refund check in evlog.ts to rely on amount-based sampling only, removing the status branch so ctx.shouldKeep is set based on refund.amount when intended, while keeping the existing tools and audit checks unchanged.
🤖 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 `@packages/evlog/src/eve/index.ts`:
- Around line 839-849: The exported resetEvlogEveForTests API is missing the
required JSDoc documentation. Add a JSDoc block for resetEvlogEveForTests,
matching the style used by nearby public exports like useLogger, and briefly
describe that it clears Eve/evlog test state and resets global initialization so
it is documented as a public API.
- Around line 441-455: The session approval lookup in consumeSessionApproval is
matching by toolName even when a callId is provided, which can consume the wrong
pending approval. Update the findIndex logic so that when callId is present it
only matches approvals with the same callId, and only fall back to toolName
matching when callId is absent. Keep the rest of the consumeSessionApproval flow
unchanged, including the splice and sessionApprovals cleanup.
- Around line 413-422: `trackPendingAction` in eve/index.ts violates the
max-params rule by taking five arguments. Refactor it to accept a single options
object for the call-specific fields (for example the turn, call, tool, and
timestamp data) while keeping the session identifier separate if needed, and
update the `actions.requested` handler call site to pass that object. Make sure
the `trackPendingAction` function and its caller use the new shape consistently
so the pending-action storage logic still writes the same values to
`getSessionPendingActions`.
In `@packages/evlog/test/eve.test.ts`:
- Around line 401-495: Add test coverage for concurrent approvals using the same
toolName but different callId values in the same session, since the current
approval tests in eve.test.ts only cover one pending/approved flow. Extend the
existing turn/step/event setup around defineEvlogHook and the approval
assertions to create two overlapping issue_refund tool-calls, then verify
consumeSessionApproval keeps each approval matched to the correct callId without
mismatch, and that both approval states and durations are recorded correctly.
---
Outside diff comments:
In `@examples/eve/agent/hooks/evlog.ts`:
- Around line 17-29: The refund sampling logic in keep() is effectively always
enabled for refunded orders because issue_refund.ts always sets
context.refund.status to refunded, making the amount-based condition
unreachable. Update the refund check in evlog.ts to rely on amount-based
sampling only, removing the status branch so ctx.shouldKeep is set based on
refund.amount when intended, while keeping the existing tools and audit checks
unchanged.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: f4d43372-c89a-46c8-ad77-b4d46c85d966
⛔ Files ignored due to path filters (1)
packages/evlog/test/toolkit/__snapshots__/api-surface.test.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (14)
.changeset/eve-integration.mdapps/docs/content/4.use-cases/5.eve.mdexamples/eve/README.mdexamples/eve/agent/hooks/evlog.tsexamples/eve/agent/tools/issue_refund.tsexamples/eve/agent/tools/lookup_customer.tsexamples/eve/agent/tools/lookup_order.tspackages/evlog/README.mdpackages/evlog/src/eve/index.tspackages/evlog/src/logger.tspackages/evlog/src/shared/nitroConfigBridge.tspackages/evlog/test/core/logger.test.tspackages/evlog/test/eve.test.tspackages/evlog/test/shared/nitroConfigBridge.test.ts
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
examples/eve/app/_components/agent-chat.tsx (1)
95-111: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSimplify the header-visibility ternary.
{!embedded && isEmpty ? null : !embedded ? (...) : null}is equivalent to!embedded && !isEmpty ? (...) : null— the current form re-checks!embeddedtwice and reads awkwardly.♻️ Suggested simplification
- {!embedded && isEmpty ? null : !embedded ? ( + {!embedded && !isEmpty ? ( <header className="flex h-14 shrink-0 items-center justify-center gap-3 pr-2 pl-4">🤖 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 `@examples/eve/app/_components/agent-chat.tsx` around lines 95 - 111, Simplify the conditional rendering in agent-chat.tsx around the header block so it only checks the non-embedded, non-empty case once. In the JSX near the header markup, replace the duplicated ternary logic using the existing embedded and isEmpty flags with the simpler equivalent form, keeping the same rendered header content and behavior.
🤖 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 `@examples/eve/app/api/demo/logs/route.ts`:
- Around line 7-22: The GET handler in the logs route buffers every entry from
readFsLogs() into events before trimming, which can waste memory on large logs.
Update GET to keep only the last MAX_EVENTS items while iterating, using a
bounded ring buffer or fixed-size queue instead of events.push plus slice at the
end. Keep the existing Response.json behavior and Cache-Control header, and
preserve readFsLogs() as the source of events.
---
Outside diff comments:
In `@examples/eve/app/_components/agent-chat.tsx`:
- Around line 95-111: Simplify the conditional rendering in agent-chat.tsx
around the header block so it only checks the non-embedded, non-empty case once.
In the JSX near the header markup, replace the duplicated ternary logic using
the existing embedded and isEmpty flags with the simpler equivalent form,
keeping the same rendered header content and behavior.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 767a3e72-5448-4248-97ea-1b5d9bff012a
⛔ Files ignored due to path filters (1)
packages/evlog/test/toolkit/__snapshots__/api-surface.test.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (17)
.changeset/stream-eve-proxy-fix.md.gitignoreexamples/eve/.gitignoreexamples/eve/agent/hooks/evlog.tsexamples/eve/app/_components/agent-chat.tsxexamples/eve/app/_components/demo-app.tsxexamples/eve/app/_components/evlog-events-panel.tsxexamples/eve/app/api/demo/logs/route.tsexamples/eve/app/layout.tsxexamples/eve/app/page.tsxexamples/eve/components/ai-elements/prompt-input.tsxexamples/eve/components/ai-elements/reasoning.tsxexamples/eve/components/ai-elements/tool.tsxpackages/evlog/src/eve/index.tspackages/evlog/src/stream.tspackages/evlog/test/eve.test.tspackages/evlog/test/http/stream-server.test.ts
Summary
evlog/evewithdefineEvlogHook()(one wide event per turn) anduseTurnLogger(ctx)for tool contextglobalThiswhen Eve bundles hooks/tools separately; hardenfinalizeAudit()against partial audit objectsexamples/eve— Clearbill support-refund copilot on Eve + Next.js (withEve,useEveAgent)evesemantic-PR scopeTest plan
pnpm run typecheckpnpm --filter evlog exec vitest run test/eve.test.ts test/core/audit.test.tspnpm run example:eve→ http://localhost:3000 → Acme Corp / order #4821 refund flowexamples/eve/.evlog/logs/via batched FS drainSummary by CodeRabbit
useLogger().