Skip to content

refactor: extract copy-to-clipboard logic into reusable hook#2379

Merged
akshaydeo merged 3 commits intomainfrom
03-30-refactor_moved_copy-to-clipboard_functionality_to_a_centralized_hook
Mar 30, 2026
Merged

refactor: extract copy-to-clipboard logic into reusable hook#2379
akshaydeo merged 3 commits intomainfrom
03-30-refactor_moved_copy-to-clipboard_functionality_to_a_centralized_hook

Conversation

@impoiler
Copy link
Copy Markdown
Contributor

@impoiler impoiler commented Mar 30, 2026

Summary

Refactored clipboard copy functionality across the UI by creating a reusable useCopyToClipboard hook to replace duplicate clipboard handling code.

Changes

  • Created a new useCopyToClipboard hook that provides consistent clipboard functionality with customizable success/error messages and automatic reset of copied state
  • Replaced inline clipboard handling code across 11 components with the new hook
  • Removed direct navigator.clipboard.writeText() calls and manual toast notifications
  • Added support for customizable messages and reset delays in the hook

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (Next.js)
  • Docs

How to test

Test clipboard functionality across the affected components:

# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
  1. Navigate to API Keys page and test copying curl examples
  2. Open log details and test copying request IDs and request bodies
  3. Test copy functionality in routing rules CEL builder
  4. Test copy functionality in virtual keys table
  5. Test copy functionality in Prometheus configuration
  6. Verify all copy actions show appropriate toast messages

Screenshots/Recordings

No visual changes - functionality remains the same with improved code organization.

Breaking changes

  • Yes
  • No

Related issues

N/A

Security considerations

No security implications - maintains existing clipboard functionality without changes to security model.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 30, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ec86118f-2f27-4ed3-8c5f-ed4a976d1fc5

📥 Commits

Reviewing files that changed from the base of the PR and between ff789b8 and fd6ed11.

📒 Files selected for processing (10)
  • ui/app/_fallbacks/enterprise/components/api-keys/apiKeysIndexView.tsx
  • ui/app/workspace/logs/sheets/logDetailsSheet.tsx
  • ui/app/workspace/logs/views/collapsibleBox.tsx
  • ui/app/workspace/logs/views/emptyState.tsx
  • ui/app/workspace/mcp-logs/views/emptyState.tsx
  • ui/app/workspace/observability/fragments/prometheusFormFragment.tsx
  • ui/app/workspace/routing-rules/components/celBuilder/celRuleBuilder.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
  • ui/components/ui/input.tsx
  • ui/hooks/useCopyToClipboard.ts
✅ Files skipped from review due to trivial changes (2)
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
  • ui/app/workspace/mcp-logs/views/emptyState.tsx
🚧 Files skipped from review as they are similar to previous changes (7)
  • ui/app/workspace/routing-rules/components/celBuilder/celRuleBuilder.tsx
  • ui/app/workspace/observability/fragments/prometheusFormFragment.tsx
  • ui/app/workspace/logs/views/emptyState.tsx
  • ui/app/workspace/logs/views/collapsibleBox.tsx
  • ui/app/_fallbacks/enterprise/components/api-keys/apiKeysIndexView.tsx
  • ui/hooks/useCopyToClipboard.ts
  • ui/components/ui/input.tsx

📝 Walkthrough

Summary by CodeRabbit

  • Refactor
    • Consolidated copy-to-clipboard behavior across the app, centralizing success/error handling and "copied" state so copy actions behave consistently.
    • Updated copy buttons and copy-related UI (logs, code blocks, inputs, tables, forms, and detail views) to use the shared clipboard behavior, improving reliability and uniform user feedback.

Walkthrough

Introduces a new client-only useCopyToClipboard hook and replaces inline clipboard write + toast logic with the hook across multiple UI components, centralizing copy behavior and copied-state management.

Changes

Cohort / File(s) Summary
New Hook
ui/hooks/useCopyToClipboard.ts
Adds exported useCopyToClipboard(options?) returning { copy(text): Promise<void>, copied: boolean }; handles navigator.clipboard.writeText, success/error toasts, and auto-reset of copied.
Enterprise UI
ui/app/_fallbacks/enterprise/components/api-keys/apiKeysIndexView.tsx
Replaced inline clipboard logic and sonner toast usage with hook copy call; component no longer directly emits toasts for copy success.
Core UI Input
ui/components/ui/input.tsx
Wire showCopyButton behavior to hook copy; derive text from props.value and delegate copy/toast to hook.
Virtual Keys
ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
Replaced local copyToClipboard function and immediate toast with hook-based copy.
Logs — Details & Views
ui/app/workspace/logs/sheets/logDetailsSheet.tsx, ui/app/workspace/logs/views/collapsibleBox.tsx, ui/app/workspace/logs/views/emptyState.tsx
Switched from inline navigator.clipboard.writeText + local toast/state to useCopyToClipboard; updated call sites to accept/inject copy where needed.
MCP Logs Empty State
ui/app/workspace/mcp-logs/views/emptyState.tsx
Replaced inline clipboard + toast with hook copy; adjusted click handlers to pass current code into copy.
Observability
ui/app/workspace/observability/fragments/prometheusFormFragment.tsx
Removed local copied state and timeout; use hook copy(metricsEndpoint) and rely on hook-managed reset.
Routing Rules (CEL)
ui/app/workspace/routing-rules/components/celBuilder/celRuleBuilder.tsx
Replaced local copied state and timeout-based reset with hook-provided copied and copy(celExpression); UI reads copied from hook.
Log Copy Flow Adjustments
ui/app/workspace/logs/sheets/logDetailsSheet.tsx (call-site)
Updated copyRequestBody to accept injected async copy(text) and use await copy(requestBodyJson) instead of direct clipboard calls.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐇 I nibble keys and hop with glee,

One little hook to set them free,
Copies swift and toasts that sing,
No more duplicate coding bling,
Happy hops — unified clipboard spree!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: extracting copy-to-clipboard logic into a reusable hook, which matches the primary objective of the PR.
Description check ✅ Passed The description includes all required sections with appropriate detail: summary, changes, type of change (refactor), affected areas (UI), testing instructions, breaking changes, and security considerations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 03-30-refactor_moved_copy-to-clipboard_functionality_to_a_centralized_hook

Comment @coderabbitai help to get the list of available commands and usage tips.

@impoiler impoiler changed the title refactor/Moved copy-to-clipboard functionality to a centralized hook refactor: extract copy-to-clipboard logic into reusable hook Mar 30, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 30, 2026

Confidence Score: 5/5

Safe to merge; all remaining findings are P2 style suggestions with no correctness impact.

All substantive concerns were either already flagged in prior threads or are minor style notes. No logic regressions introduced.

ui/components/ui/input.tsx — hook instantiated unconditionally for all Input instances

Important Files Changed

Filename Overview
ui/hooks/useCopyToClipboard.ts New hook centralizing clipboard logic with configurable messages and auto-reset; missing unmount cleanup flagged in prior thread.
ui/components/ui/input.tsx Hook instantiated unconditionally for every Input, including those without showCopyButton; harmless but adds unnecessary state per instance.
ui/app/workspace/observability/fragments/prometheusFormFragment.tsx Replaces local copied state with hook; now emits a toast where the original only toggled a button label — flagged in prior thread.
ui/app/workspace/logs/sheets/logDetailsSheet.tsx Two hook instances correctly scoped with specific messages; outer catch still handles pre-clipboard errors correctly.
ui/app/workspace/logs/views/collapsibleBox.tsx Straightforward replacement; unawaited Promise is harmless since errors are caught inside the hook.

Reviews (2): Last reviewed commit: "refactor/Moved copy-to-clipboard functio..." | Re-trigger Greptile

Comment thread ui/hooks/useCopyToClipboard.ts
Comment thread ui/app/workspace/observability/fragments/prometheusFormFragment.tsx
@impoiler impoiler self-assigned this Mar 30, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
ui/app/workspace/logs/sheets/logDetailsSheet.tsx (1)

899-1011: ⚠️ Potential issue | 🟡 Minor

Remove the redundant try-catch block or clarify its purpose.

The useCopyToClipboard hook is configured with errorMessage: "Failed to copy request body" and handles clipboard errors internally without re-throwing. This means the catch block in copyRequestBody will not catch clipboard failures—only pre-clipboard errors (e.g., JSON.stringify failures). Either remove the catch block since the hook handles clipboard errors, or refactor it to distinguish between clipboard failures and request body construction failures.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/sheets/logDetailsSheet.tsx` around lines 899 - 1011,
The try-catch in copyRequestBody is redundant because useCopyToClipboard already
handles clipboard errors; remove the outer try-catch in the copyRequestBody
function (leave the function body logic intact) so any clipboard errors are
handled by the hook's errorMessage and only true construction/runtime errors
bubble naturally; update function copyRequestBody accordingly and ensure no
empty catch is left behind.
🧹 Nitpick comments (7)
ui/app/workspace/observability/fragments/prometheusFormFragment.tsx (1)

117-120: Consider adding data-testid to the copy button for testability.

As per coding guidelines, new interactive UI elements should have data-testid attributes following the <entity>-<element>-<qualifier> pattern.

🧪 Proposed fix
-							<Button type="button" variant="outline" size="sm" onClick={handleCopyEndpoint} className="shrink-0">
+							<Button type="button" variant="outline" size="sm" onClick={handleCopyEndpoint} className="shrink-0" data-testid="prometheus-endpoint-copy-btn">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/observability/fragments/prometheusFormFragment.tsx` around
lines 117 - 120, Add a data-testid to the copy Button so tests can reliably
target it: update the Button element that uses onClick={handleCopyEndpoint} and
renders {copied ? "Copied!" : "Copy"} to include a data-testid attribute
following the <entity>-<element>-<qualifier> pattern (e.g.,
"prometheus-endpoint-copy-button" or similar consistent with project naming) so
testing frameworks can select it; ensure the attribute is added to the same
Button component referenced in this fragment.
ui/app/_fallbacks/enterprise/components/api-keys/apiKeysIndexView.tsx (1)

87-89: Consider adding data-testid to the copy button.

🧪 Proposed fix
-						<Button variant="ghost" size="sm" onClick={() => copyToClipboard(curlExample)} className="absolute top-2 right-2 z-10 h-8">
+						<Button variant="ghost" size="sm" onClick={() => copyToClipboard(curlExample)} className="absolute top-2 right-2 z-10 h-8" data-testid="api-keys-curl-copy-btn">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/_fallbacks/enterprise/components/api-keys/apiKeysIndexView.tsx` around
lines 87 - 89, Add a data-testid attribute to the copy button so tests can
reliably target it: update the Button element used to trigger
copyToClipboard(curlExample) (the Button with onClick={() =>
copyToClipboard(curlExample)} and Copy icon) to include a unique data-testid
like data-testid="copy-curl-button" (or similar) to enable stable test selectors
without changing runtime behavior.
ui/app/workspace/routing-rules/components/celBuilder/celRuleBuilder.tsx (1)

122-134: Consider adding data-testid to the copy button.

The copy button is an interactive element that would benefit from a test identifier.

🧪 Proposed fix
-				<Button variant="outline" size="sm" onClick={handleCopy} disabled={!celExpression} className="gap-2" type="button">
+				<Button variant="outline" size="sm" onClick={handleCopy} disabled={!celExpression} className="gap-2" type="button" data-testid="cel-expression-copy-btn">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/routing-rules/components/celBuilder/celRuleBuilder.tsx`
around lines 122 - 134, Add a test id attribute to the copy Button so tests can
reliably select it: update the Button component rendering in celRuleBuilder (the
Button with onClick={handleCopy}, disabled={!celExpression} and conditional
copied UI) to include a data-testid like data-testid="cel-copy-button" (or
similar), ensuring the identifier is unique and stable for test suites.
ui/app/workspace/mcp-logs/views/emptyState.tsx (1)

64-66: Consider adding data-testid to the copy button.

While the button has a good aria-label, adding a data-testid would improve testability.

🧪 Proposed fix
-			<Button variant="ghost" size="icon" onClick={() => copyToClipboard(code)} aria-label="Copy to clipboard">
+			<Button variant="ghost" size="icon" onClick={() => copyToClipboard(code)} aria-label="Copy to clipboard" data-testid="code-block-copy-btn">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/mcp-logs/views/emptyState.tsx` around lines 64 - 66, Add a
data-testid to the copy button to improve testability: update the Button element
that calls copyToClipboard (the Button with onClick={() =>
copyToClipboard(code)} and aria-label="Copy to clipboard") to include a unique
data-testid attribute (e.g., data-testid="copy-log-button" or similar) so tests
can reliably select it while keeping the existing aria-label and behavior
intact.
ui/components/ui/input.tsx (1)

38-48: Consider adding data-testid to the copy button.

The Input component's copy button is a reusable interactive element that would benefit from a test identifier.

🧪 Proposed fix
 				<Button
 					className="ml-auto"
 					variant="ghost"
 					size="icon"
+					data-testid="input-copy-btn"
 					onClick={() => {
 						const text = typeof props.value === "string" ? props.value : JSON.stringify(props.value);
 						copy(text);
 					}}
 				>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/components/ui/input.tsx` around lines 38 - 48, Add a data-testid to the
copy button in the Input component: update the Button element (the one rendering
CopyIcon and using props.value in the onClick) to include a data-testid
attribute (for example data-testid="input-copy-button"); alternatively, expose a
prop (e.g., testId or dataTestId) on the Input component and pass it into that
Button so tests can set a unique identifier when needed.
ui/hooks/useCopyToClipboard.ts (1)

15-25: Consider cleaning up the timeout on unmount to prevent state updates on unmounted components.

If the component unmounts while the reset timeout is pending, setCopied(false) will still fire. While React 19 handles this more gracefully, adding cleanup is a good practice.

♻️ Optional: Add cleanup effect
 const timeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined);

+useEffect(() => {
+	return () => {
+		if (timeoutRef.current) clearTimeout(timeoutRef.current);
+	};
+}, []);
+
 const copy = useCallback(

Note: You'll need to add useEffect to the imports.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/hooks/useCopyToClipboard.ts` around lines 15 - 25, Add a cleanup effect to
useCopyToClipboard to clear the pending reset timeout on unmount: import
useEffect, then add a useEffect in the useCopyToClipboard hook that returns a
cleanup function which checks timeoutRef.current and calls
clearTimeout(timeoutRef.current) (and sets timeoutRef.current = undefined) to
prevent setCopied(false) after unmount; keep existing logic in the copy function
intact and reference timeoutRef, setCopied, and resetDelay.
ui/app/workspace/logs/views/emptyState.tsx (1)

65-67: Consider adding data-testid to the copy button.

🧪 Proposed fix
-			<Button variant="ghost" size="icon" onClick={() => copyToClipboard(code)}>
+			<Button variant="ghost" size="icon" onClick={() => copyToClipboard(code)} data-testid="code-block-copy-btn">
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/app/workspace/logs/views/emptyState.tsx` around lines 65 - 67, Add a
data-testid to the copy button in the EmptyState component so tests can reliably
target it: update the Button element that calls copyToClipboard(code) (the
Button wrapping the <Copy /> icon) to include a stable data-testid attribute
(e.g. data-testid="copy-clipboard-button" or data-testid="emptystate-copy-btn")
and keep the existing onClick and props unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/app/workspace/logs/sheets/logDetailsSheet.tsx`:
- Around line 151-154: Replace the non-interactive <code> element used for
copying the request id with a proper keyboard-accessible <button> element that
calls copyRequestId(displayLog.id) on click; ensure the button has
type="button", an appropriate aria-label (e.g., "Copy request ID"), preserves
the existing className styling, and add a data-testid following the pattern used
in this file such as data-testid="logdetails-copy-request-id-button" so tests
can target it.

---

Outside diff comments:
In `@ui/app/workspace/logs/sheets/logDetailsSheet.tsx`:
- Around line 899-1011: The try-catch in copyRequestBody is redundant because
useCopyToClipboard already handles clipboard errors; remove the outer try-catch
in the copyRequestBody function (leave the function body logic intact) so any
clipboard errors are handled by the hook's errorMessage and only true
construction/runtime errors bubble naturally; update function copyRequestBody
accordingly and ensure no empty catch is left behind.

---

Nitpick comments:
In `@ui/app/_fallbacks/enterprise/components/api-keys/apiKeysIndexView.tsx`:
- Around line 87-89: Add a data-testid attribute to the copy button so tests can
reliably target it: update the Button element used to trigger
copyToClipboard(curlExample) (the Button with onClick={() =>
copyToClipboard(curlExample)} and Copy icon) to include a unique data-testid
like data-testid="copy-curl-button" (or similar) to enable stable test selectors
without changing runtime behavior.

In `@ui/app/workspace/logs/views/emptyState.tsx`:
- Around line 65-67: Add a data-testid to the copy button in the EmptyState
component so tests can reliably target it: update the Button element that calls
copyToClipboard(code) (the Button wrapping the <Copy /> icon) to include a
stable data-testid attribute (e.g. data-testid="copy-clipboard-button" or
data-testid="emptystate-copy-btn") and keep the existing onClick and props
unchanged.

In `@ui/app/workspace/mcp-logs/views/emptyState.tsx`:
- Around line 64-66: Add a data-testid to the copy button to improve
testability: update the Button element that calls copyToClipboard (the Button
with onClick={() => copyToClipboard(code)} and aria-label="Copy to clipboard")
to include a unique data-testid attribute (e.g., data-testid="copy-log-button"
or similar) so tests can reliably select it while keeping the existing
aria-label and behavior intact.

In `@ui/app/workspace/observability/fragments/prometheusFormFragment.tsx`:
- Around line 117-120: Add a data-testid to the copy Button so tests can
reliably target it: update the Button element that uses
onClick={handleCopyEndpoint} and renders {copied ? "Copied!" : "Copy"} to
include a data-testid attribute following the <entity>-<element>-<qualifier>
pattern (e.g., "prometheus-endpoint-copy-button" or similar consistent with
project naming) so testing frameworks can select it; ensure the attribute is
added to the same Button component referenced in this fragment.

In `@ui/app/workspace/routing-rules/components/celBuilder/celRuleBuilder.tsx`:
- Around line 122-134: Add a test id attribute to the copy Button so tests can
reliably select it: update the Button component rendering in celRuleBuilder (the
Button with onClick={handleCopy}, disabled={!celExpression} and conditional
copied UI) to include a data-testid like data-testid="cel-copy-button" (or
similar), ensuring the identifier is unique and stable for test suites.

In `@ui/components/ui/input.tsx`:
- Around line 38-48: Add a data-testid to the copy button in the Input
component: update the Button element (the one rendering CopyIcon and using
props.value in the onClick) to include a data-testid attribute (for example
data-testid="input-copy-button"); alternatively, expose a prop (e.g., testId or
dataTestId) on the Input component and pass it into that Button so tests can set
a unique identifier when needed.

In `@ui/hooks/useCopyToClipboard.ts`:
- Around line 15-25: Add a cleanup effect to useCopyToClipboard to clear the
pending reset timeout on unmount: import useEffect, then add a useEffect in the
useCopyToClipboard hook that returns a cleanup function which checks
timeoutRef.current and calls clearTimeout(timeoutRef.current) (and sets
timeoutRef.current = undefined) to prevent setCopied(false) after unmount; keep
existing logic in the copy function intact and reference timeoutRef, setCopied,
and resetDelay.
🪄 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: CHILL

Plan: Pro

Run ID: bd031b4b-9124-497e-8f93-cf28e03c2352

📥 Commits

Reviewing files that changed from the base of the PR and between 506c038 and ff789b8.

📒 Files selected for processing (10)
  • ui/app/_fallbacks/enterprise/components/api-keys/apiKeysIndexView.tsx
  • ui/app/workspace/logs/sheets/logDetailsSheet.tsx
  • ui/app/workspace/logs/views/collapsibleBox.tsx
  • ui/app/workspace/logs/views/emptyState.tsx
  • ui/app/workspace/mcp-logs/views/emptyState.tsx
  • ui/app/workspace/observability/fragments/prometheusFormFragment.tsx
  • ui/app/workspace/routing-rules/components/celBuilder/celRuleBuilder.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
  • ui/components/ui/input.tsx
  • ui/hooks/useCopyToClipboard.ts

Comment thread ui/app/workspace/logs/sheets/logDetailsSheet.tsx
coderabbitai[bot]
coderabbitai Bot previously approved these changes Mar 30, 2026
@impoiler impoiler force-pushed the 03-30-refactor_moved_copy-to-clipboard_functionality_to_a_centralized_hook branch from ff789b8 to fd6ed11 Compare March 30, 2026 08:10
@impoiler impoiler force-pushed the 03-30-fix_stop_click_propagation_on_action_buttons_in_prompt_messages_to_prevent_them_from_triggering_message_edit_mode branch from 506c038 to 153f5cf Compare March 30, 2026 08:10
Copy link
Copy Markdown
Contributor

akshaydeo commented Mar 30, 2026

Merge activity

  • Mar 30, 9:25 AM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Mar 30, 9:27 AM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo akshaydeo changed the base branch from 03-30-fix_stop_click_propagation_on_action_buttons_in_prompt_messages_to_prevent_them_from_triggering_message_edit_mode to graphite-base/2379 March 30, 2026 09:26
@akshaydeo akshaydeo changed the base branch from graphite-base/2379 to main March 30, 2026 09:26
@akshaydeo akshaydeo dismissed coderabbitai[bot]’s stale review March 30, 2026 09:26

The base branch was changed.

@akshaydeo akshaydeo merged commit a1bd263 into main Mar 30, 2026
15 of 16 checks passed
@akshaydeo akshaydeo deleted the 03-30-refactor_moved_copy-to-clipboard_functionality_to_a_centralized_hook branch March 30, 2026 09:27
akshaydeo added a commit that referenced this pull request Mar 30, 2026
* v1.4.17-release-cut (#2368)

* fixed helm schema fix (#2369)

## Summary

Remove Bullfrog security monitoring from GitHub Actions workflows and update Helm chart schema validation requirements.

## Changes

- Removed `bullfrogsec/bullfrog@7bc9b6e13e2dd9cbe5861f33bc26dc6bdb9d9ed2` action with `egress-policy: audit` from all GitHub Actions workflows
- Updated Helm chart values schema to only require `dimension` field instead of `dimension`, `keys`, and `provider` for config objects

## Type of change

- [ ] Bug fix
- [ ] Feature
- [x] Refactor
- [ ] Documentation
- [x] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (Next.js)
- [ ] Docs

## How to test

Verify that GitHub Actions workflows execute successfully without the Bullfrog security step:

```sh
# Trigger any workflow to ensure it runs without errors
# Check that Helm chart validation accepts configs with only dimension field
helm lint helm-charts/bifrost/
```

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

This change removes network egress monitoring from CI/CD pipelines. Ensure alternative security measures are in place if network monitoring is still required.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* fix migration tests (#2371)

* framework: bump core to v1.4.15 --skip-pipeline

* plugins/governance: bump core to v1.4.15 and framework to v1.2.34 --skip-pipeline

* plugins/jsonparser: bump core to v1.4.15 and framework to v1.2.34 --skip-pipeline

* plugins/litellmcompat: bump core to v1.4.15 and framework to v1.2.34 --skip-pipeline

* plugins/logging: bump core to v1.4.15 and framework to v1.2.34 --skip-pipeline

* plugins/maxim: bump core to v1.4.15 and framework to v1.2.34 --skip-pipeline

* plugins/mocker: bump core to v1.4.15 and framework to v1.2.34 --skip-pipeline

* plugins/otel: bump core to v1.4.15 and framework to v1.2.34 --skip-pipeline

* plugins/semanticcache: bump core to v1.4.15 and framework to v1.2.34 --skip-pipeline

* plugins/telemetry: bump core to v1.4.15 and framework to v1.2.34 --skip-pipeline

* test fixes (#2374)

## Summary

Adds support for testing streaming multiple tool calls functionality across LLM providers. This addresses the need to differentiate between providers that support multiple tool calls in streaming mode versus those that only return one tool call at a time during streaming.

## Changes

- Added `MultipleToolCallsStreaming` field to `TestScenarios` struct to track streaming multiple tool calls capability
- Updated all provider test configurations to enable the new streaming multiple tool calls feature
- Added conditional test skipping in multiple tool calls streaming tests when providers don't support this functionality
- Refined streaming response validation expectations to handle consolidated responses from chunks more accurately
- Updated provider-specific validation expectations for Cohere and Parasail to reflect their actual response formats

## Type of change

- [x] Feature
- [x] Refactor

## Affected areas

- [x] Core (Go)
- [x] Providers/Integrations

## How to test

Run the LLM provider tests to validate streaming multiple tool calls functionality:

```sh
# Core/Transports
go version
go test ./...

# Test specific provider streaming multiple tool calls
go test ./core/providers/openai -v -run TestOpenAI
go test ./core/providers/anthropic -v -run TestAnthropic
```

The tests will automatically skip streaming multiple tool calls scenarios for providers that don't support this feature.

## Screenshots/Recordings

N/A - Backend testing enhancement only.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

No security implications - this is a testing infrastructure enhancement.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* transports: update dependencies --skip-pipeline

* Adds changelog for v1.4.18 --skip-pipeline

* [StepSecurity] Apply security best practices (#2372)

* [StepSecurity] Apply security best practices

Signed-off-by: StepSecurity Bot <bot@stepsecurity.io>

* Update .github/workflows/codeql.yml

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* cr fixes

* fixed cr comments 2

---------

Signed-off-by: StepSecurity Bot <bot@stepsecurity.io>
Co-authored-by: Akshay Deo <akshay@akshaydeo.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* removed codeql to fallback on default setup (#2376)

## Summary

Removes the CodeQL security analysis workflow from the GitHub Actions configuration. This eliminates automated static code analysis for Go, JavaScript, and Python languages that was previously running on pushes, pull requests, and weekly schedules.

## Changes

- Deleted `.github/workflows/codeql.yml` which contained the complete CodeQL workflow configuration
- Removed automated security scanning for Go, JavaScript, and Python codebases
- Eliminated the scheduled weekly security analysis runs

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [x] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (Next.js)
- [ ] Docs

## How to test

Verify that CodeQL workflow is no longer present in the repository:

```sh
# Confirm the workflow file has been removed
ls -la .github/workflows/
# Should not show codeql.yml

# Check GitHub Actions tab to ensure CodeQL runs are no longer scheduled
# Navigate to repository Actions tab and verify no CodeQL workflows appear
```

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

This change removes automated security analysis from the CI/CD pipeline. The repository will no longer benefit from CodeQL's static analysis capabilities for detecting security vulnerabilities, code quality issues, and potential bugs in Go, JavaScript, and Python code. Consider alternative security scanning solutions if this workflow was providing valuable security insights.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* Update snyk.yml (#2380)

* fips base image (#2310)

## Summary

Updates the transports Docker configuration to use a FIPS-compliant base image and removes the built-in health check mechanism.

## Changes

- Replaced `alpine:3.23.3` base image with `dhi.io/alpine-base:3.23-alpine3.23-fips` for FIPS compliance
- Removed the Docker HEALTHCHECK directive that was monitoring the `/health` endpoint

## Type of change

- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [x] Chore/CI

## Affected areas

- [ ] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (Next.js)
- [ ] Docs

## How to test

Verify the Docker image builds successfully with the new base image and that the application starts correctly without the health check.

```sh
# Build the Docker image
docker build -t transports-test ./transports

# Run the container
docker run -p 8080:8080 transports-test

# Verify the application is running
curl http://localhost:8080/health
```

## Screenshots/Recordings

N/A

## Breaking changes

- [x] Yes
- [ ] No

The removal of the Docker HEALTHCHECK may affect container orchestration systems that rely on Docker's built-in health checking. External health monitoring will need to be configured if required.

## Related issues

N/A

## Security considerations

This change enhances security by adopting a FIPS-compliant base image, which provides cryptographic modules that meet Federal Information Processing Standards.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

* fixed snyk failure and enterprise update (#2382)

## Summary

Enhances the model catalog to extract and cache max output tokens from pricing data, improves Snyk workflow reliability by checking for SARIF file existence before upload, and updates security documentation to reflect full SHA pinning for the enterprise repository.

## Changes

- Added `MaxOutputTokens` field to `PricingEntry` struct to capture model parameter limits from pricing datasheet
- Implemented `populateModelParamsFromPricing()` function to extract max output tokens and populate the model params cache
- Refactored model name extraction logic into reusable `extractModelName()` utility function
- Enhanced Snyk workflow conditions to only upload SARIF files when they exist, preventing upload failures
- Updated security documentation to reflect that bifrost-enterprise now uses full SHA pinning (100% coverage)

## Type of change

- [x] Feature
- [x] Chore/CI
- [x] Documentation

## Affected areas

- [x] Core (Go)
- [x] Docs

## How to test

Verify model catalog functionality and pricing data processing:

```sh
# Core functionality
go version
go test ./framework/modelcatalog/...

# Test pricing sync with max_output_tokens
go test -v ./framework/modelcatalog/ -run TestSyncPricing

# Verify Snyk workflow changes in CI
# Check that SARIF upload steps only run when files exist
```

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

- Improves CI security by preventing potential failures in SARIF upload steps
- Documents enhanced security posture with full SHA pinning in enterprise repository

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* fix snyk failures (#2385)

## Summary

Improves Docker container security and reliability by migrating from custom base image to standard Alpine, adding health checks, and enhancing Snyk security scanning.

## Changes

- **Docker base image migration**: Replaced `bifrosthq/dhi-alpine-base:3.22-fips_bifrost-v27032026` with standard `alpine:3.23.3` for better security and maintainability
- **Added health checks**: Implemented HTTP health check endpoint monitoring with 30s intervals and proper retry logic
- **Enhanced user management**: Consolidated user creation and permission setup into single RUN command for better layer optimization
- **Improved Snyk scanning**: Added build step before security scanning and excluded `examples` and `tests/scripts` directories from vulnerability analysis
- **Runtime dependencies**: Explicitly installed required CGO runtime libraries (musl, libgcc, ca-certificates, wget)

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [x] Chore/CI

## Affected areas

- [ ] Core (Go)
- [x] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [ ] UI (Next.js)
- [ ] Docs

## How to test

Validate Docker builds and container health:

```sh
# Build and test standard Dockerfile
docker build -f transports/Dockerfile -t bifrost:test .
docker run -d --name bifrost-test -p 8080:8080 bifrost:test
docker ps  # Should show healthy status after ~35s
curl http://localhost:8080/health  # Should return 200 OK

# Build and test local development Dockerfile
docker build -f transports/Dockerfile.local -t bifrost:local .
docker run -d --name bifrost-local -p 8081:8080 bifrost:local
docker ps  # Should show healthy status after ~35s

# Test Snyk workflow
make build  # Verify build step works
# Run Snyk scan (requires SNYK_TOKEN)
```

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

- Migrated from custom base image to well-maintained Alpine Linux for better security patching
- Enhanced Snyk scanning excludes test directories to focus on production code vulnerabilities
- Health check endpoint provides better container monitoring capabilities
- Explicit runtime dependency management reduces attack surface

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* fix: add explicit type="button" to navigation and action buttons (#2353)

## Summary

Added explicit `type="button"` attributes to Button components in log detail sheets and plugin sequence forms to prevent unintended form submissions when these buttons are clicked.

## Changes

- Added `type="button"` to navigation buttons (Previous/Next) in log detail sheets
- Added `type="button"` to dropdown menu trigger buttons in log detail sheets  
- Added `type="button"` to the Save Sequence button in plugin sequence sheet
- Added `type="button"` to the Copy button in CEL rule builder

This prevents these buttons from accidentally triggering form submissions when used within forms, ensuring they only perform their intended click actions.

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (Next.js)
- [ ] Docs

## How to test

Verify that buttons in log detail sheets and plugin forms work correctly without triggering form submissions:

1. Open log detail sheets and test navigation buttons
2. Test dropdown menu triggers in log sheets
3. Test plugin sequence save functionality
4. Test CEL rule builder copy button

```sh
# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

## Screenshots/Recordings

N/A - This is a behavioral fix without visual changes.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

None - this change only affects button behavior to prevent unintended form submissions.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* fix: prevent edit mode activation when clicking interactive elements in message views (#2377)

## Summary

Prevents edit mode from being triggered when clicking on interactive elements (buttons, links, or elements with button role) within message views. This fixes the issue where clicking on buttons or links inside messages would unintentionally activate edit mode.

## Changes

- Added event target checking in onClick handlers for assistant, system, and user message views
- Modified click handlers to check if the clicked element is within a button, link, or element with button role using `closest()` method
- Restructured conditional logic for better readability and early returns

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (Next.js)
- [ ] Docs

## How to test

1. Navigate to a message view with interactive elements (buttons, links)
2. Click on buttons or links within the message content
3. Verify that edit mode is not triggered when clicking interactive elements
4. Click on non-interactive areas of the message to confirm edit mode still works
5. Test across all message types (assistant, system, user)

```sh
# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

No security implications - this is a UI interaction improvement.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* refactor: extract copy-to-clipboard logic into reusable hook (#2379)

## Summary

Refactored clipboard copy functionality across the UI by creating a reusable `useCopyToClipboard` hook to replace duplicate clipboard handling code.

## Changes

- Created a new `useCopyToClipboard` hook that provides consistent clipboard functionality with customizable success/error messages and automatic reset of copied state
- Replaced inline clipboard handling code across 11 components with the new hook
- Removed direct `navigator.clipboard.writeText()` calls and manual toast notifications
- Added support for customizable messages and reset delays in the hook

## Type of change

- [ ] Bug fix
- [ ] Feature
- [x] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (Next.js)
- [ ] Docs

## How to test

Test clipboard functionality across the affected components:

```sh
# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

1. Navigate to API Keys page and test copying curl examples
2. Open log details and test copying request IDs and request bodies
3. Test copy functionality in routing rules CEL builder
4. Test copy functionality in virtual keys table
5. Test copy functionality in Prometheus configuration
6. Verify all copy actions show appropriate toast messages

## Screenshots/Recordings

No visual changes - functionality remains the same with improved code organization.

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

No security implications - maintains existing clipboard functionality without changes to security model.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* refactor: replace lazy query with polling query and fix overflow in log details sheet (#2381)

## Summary

Improves log detail sheet reliability by switching from lazy loading to automatic polling for failed log fetches and fixes UI overflow issues in the sheet header.

## Changes

- Replaced `useLazyGetLogByIdQuery` with `useGetLogByIdQuery` for automatic data fetching when the sheet opens
- Added polling mechanism that retries every 2 seconds when log fetch fails, stopping when successful
- Fixed horizontal overflow issues in the sheet header by adding `overflow-x-hidden` classes
- Exported `useGetLogByIdQuery` hook from the logs API

## Type of change

- [x] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (Next.js)
- [ ] Docs

## How to test

1. Open the logs page and click on a log entry to view details
2. Verify the log details load automatically without manual triggering
3. Test with network issues or slow responses to confirm polling retry behavior
4. Check that long request IDs don't cause horizontal overflow in the sheet header

```sh
# UI
cd ui
pnpm i || npm i
pnpm test || npm test
pnpm build || npm run build
```

## Screenshots/Recordings

N/A

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

N/A

## Security considerations

None - this change only affects UI data fetching patterns and styling.

## Checklist

- [x] I read `docs/contributing/README.md` and followed the guidelines
- [x] I added/updated tests where appropriate
- [x] I updated documentation where needed
- [x] I verified builds succeed (Go and UI)
- [x] I verified the CI pipeline passes locally if applicable

* merge-branch-main-into-v-1-5-0 resolve

* merge-branch-main-into-v-1-5-0 resolve

---------

Signed-off-by: StepSecurity Bot <bot@stepsecurity.io>
Co-authored-by: Akshay Deo <akshay@akshaydeo.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: StepSecurity Bot <bot@stepsecurity.io>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants