Skip to content

feat(console): register-trigger + state tool views; fix duplicated request pane - #392

Merged
andersonleal merged 3 commits into
mainfrom
feat/console-trigger-state-views
Jul 2, 2026
Merged

feat(console): register-trigger + state tool views; fix duplicated request pane#392
andersonleal merged 3 commits into
mainfrom
feat/console-trigger-state-views

Conversation

@andersonleal

@andersonleal andersonleal commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

What

Adds two custom tool-views to the console chat transcript and fixes a rendering bug.

1. Fix duplicated REQUEST pane

For any completed, generic tool call (one without a custom view), the request JSON pane rendered twice. showRequestPaneAbove only excluded the completed-with-custom-view case, so the top pane and the generic completed branch both emitted REQUEST. Now it's suppressed for every completed state — a one-line root-cause fix that repairs every generic tool card.

2. engine::register_trigger view (rich, react-aware)

Legible view for trigger registration. Handles both wire shapes seen under this id:

  • engine RegisterTriggerInput{ trigger_type, function_id, config, metadata }
  • harness SubscribeArgs{ trigger_type, config?, label?, once?, function_id? } (no function_id ⇒ "notify session")

Surfaces trigger_type → function_id, config chips for state triggers, label/once (one-shot vs persistent), the registration/subscription id, and for harness::react the model, options.functions.allow, join summary (id · key · expect[] · rearm), and task. Falls back to raw request JSON so the terminal pane is never blank.

3. state::* view (new family)

Minimal, uniform view for get / set / delete / update / list / list_groups: scope/key chips + the unwrapped result rendered as one highlighted JSON block.

Tests / verification

  • pnpm typecheck clean · pnpm test 817 pass (new engine + state parser tests) · biome lint clean · storybook build succeeds.
  • Storybook: RegisterTriggerView under EngineFamily (react/cron/subscribe/running fixtures); StateView under the new StateFamily gallery.

https://claude.ai/code/session_01SB8sknFhJLojcaBdQazmPH

Summary by CodeRabbit

  • New Features

    • Added support for viewing state-related chat actions, including request details, running status, and formatted output.
    • Added a new trigger registration view with clearer status, IDs, modes, and configuration details.
    • Expanded Storybook coverage with new state and trigger examples.
  • Bug Fixes

    • Improved how request and response details are shown for state and trigger messages.
    • Better handling of empty, missing, or running outputs in the chat UI.
  • Tests

    • Added parser coverage for state and trigger message formats.

Post-review hardening (follow-up commit 8e76e77d)

Ran /review + /ship on the branch. Two informational findings, both fixed:

  • State view no longer misreports success as error. state::* results are arbitrary JSON, but the view ran every result through the shared sandbox error parser — so a successful state::get returning { status: "denied" } / { denied_by: … } rendered as a red "Denied" error. Now error-parsing is skipped for success envelopes ({ content, details }); genuine errors ({ error: { kind: "function_error" } }, wire/denial shapes) still surface. Matters for this feature's gate/deploy domain, where denial-shaped state values are realistic. Added state/__tests__/view.test.tsx (3 tests) locking both directions.
  • harness::react allow-list chips now dedupe so the React key stays unique on repeated function ids.

Verified: pnpm test 840 pass, tsc -b clean, biome clean on changed files.

Heads-up (not this PR): after merging main, biome check src reports 15 pre-existing errors in pages/Workers/** and Configuration/tabs/WorkersTab/schema-form/** (inherited from main, not gated by console CI). Worth a separate cleanup pass.

…quest pane

- FunctionCallMessage: suppress the top request pane for every completed call,
  fixing REQUEST rendering twice on generic (no-custom-view) tool cards.
- engine::register_trigger: new rich view — trigger_type → function_id, config
  chips for state triggers, harness::react model/join(id·key·expect·rearm)/task,
  plus the harness subscribe variant (label, once, no function_id → "notify
  session"). Falls back to raw request JSON so the terminal pane is never blank.
- state::* : new family view for get/set/delete/update/list/list_groups —
  scope/key chips + the unwrapped result as one highlighted JSON block.
- Tests (engine + state parsers) and Storybook fixtures (EngineFamily, new
  StateFamily gallery).

Claude-Session: https://claude.ai/code/session_01SB8sknFhJLojcaBdQazmPH
@vercel

vercel Bot commented Jul 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workers Ready Ready Preview, Comment Jul 2, 2026 8:00pm
workers-tech-spec Ready Ready Preview, Comment Jul 2, 2026 8:00pm

Request Review

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

skill-check — worker

0 verified, 30 skipped (no docs/).

Layer Result
structure
vale
ai
render

Four for four. Nicely done.

@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a new state::* function-call rendering family (parsers, StateView, StateToolView, fixtures, story, tests) wired into FunctionCallMessage, and adds an engine::register_trigger schema and RegisterTriggerView component wired into the engine renderer with fixtures and tests.

Changes

State function family

Layer / File(s) Summary
State parsers and schema
console/web/src/components/chat/state/parsers.ts, console/web/src/components/chat/state/__tests__/parsers.test.ts
Adds isStateFunction, stateRequestSchema, safeParseRequest, re-exports unwrapEnvelope, and tests all of it.
StateView rendering component
console/web/src/components/chat/state/StateView.tsx
Renders running/empty/JSON views by parsing input/output via the new schemas.
StateToolView and label wiring
console/web/src/components/chat/state/index.tsx
Adds StateFunctionIdLabel, tryRender/tryRenderPreview, and exported StateToolView.
FunctionCallMessage integration and fixtures
console/web/src/components/chat/FunctionCallMessage.tsx, console/web/src/components/chat/FunctionCallMessage.stories.tsx, console/web/src/stories/fixtures/state-fixtures.ts
Wires StateToolView into label/preview/terminal dispatch, tweaks showRequestPaneAbove, adds state fixtures and a StateFamily story.

Engine register_trigger view

Layer / File(s) Summary
register_trigger schemas and function id
console/web/src/components/chat/engine/parsers.ts, console/web/src/components/chat/engine/__tests__/parsers.test.ts
Adds engine::register_trigger to ENGINE_FUNCTION_IDS and defines request/response/config Zod schemas with tests.
RegisterTriggerView component
console/web/src/components/chat/engine/RegisterTriggerView.tsx
Renders trigger status/config using parsed request/response and helper functions/components.
Dispatcher wiring and fixtures
console/web/src/components/chat/engine/index.tsx, console/web/src/stories/fixtures/engine-fixtures.ts
Wires RegisterTriggerView into the engine tryRender switch and adds engineRegisterTrigger* fixtures.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FunctionCallMessage
  participant StateToolView
  participant StateView
  participant StateParsers

  FunctionCallMessage->>StateToolView: isStateFunction(functionId)
  StateToolView->>StateParsers: safeParseRequest(input)
  StateToolView->>StateView: tryRender(functionId, input, output, running)
  StateView->>StateParsers: unwrapEnvelope(output)
  StateView-->>FunctionCallMessage: rendered JSON/running/empty view
Loading
sequenceDiagram
  participant EngineIndex
  participant RegisterTriggerView
  participant Parsers

  EngineIndex->>RegisterTriggerView: tryRender(input, output, running)
  RegisterTriggerView->>Parsers: parse RegisterTriggerRequest(input)
  RegisterTriggerView->>Parsers: parse RegisterTriggerResponse(output)
  RegisterTriggerView-->>EngineIndex: rendered trigger status/details UI
Loading

Possibly related PRs

  • iii-hq/workers#190: Both PRs modify FunctionCallMessage.tsx's preview/terminal rendering and showRequestPaneAbove gating logic.
  • iii-hq/workers#201: Extends the same custom function-call renderer dispatcher framework with the new state::* family and register_trigger wiring.
  • iii-hq/workers#204: Builds on the same Storybook fixture gallery setup by adding the StateFamily story.

Suggested reviewers: sergiofilhowz

Poem

A rabbit hops through state and trigger trees,
New views bloom soft as JSON leaves,
Parsers hum a schema tune,
Fixtures gather 'neath the moon,
Hop, hop, hooray — the tests all pass with ease! 🐇✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main additions and the rendering fix in the console chat views.
✨ 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 feat/console-trigger-state-views

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.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
console/web/src/components/chat/engine/RegisterTriggerView.tsx (1)

26-167: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Solid fallback-first design; consider adding a component test.

The parse-then-fallback pattern (raw JSON if request doesn't parse, raw JSON for unmatched config/metadata) is a good defensive default for the "always render something" requirement. This component has several conditional render branches (state chips vs raw config, react vs raw metadata, join details, running vs registered) that aren't covered by any dedicated component test in this slice — only the underlying schemas are unit-tested. A rendering test (e.g. with the new fixtures) would catch regressions in the branch logic itself.

🤖 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 `@console/web/src/components/chat/engine/RegisterTriggerView.tsx` around lines
26 - 167, Add a dedicated rendering test for RegisterTriggerView to cover the
fallback-first branch logic. Use RegisterTriggerView and its existing
parse/fallback paths to verify that invalid input renders raw JSON, state
triggers render chips instead of raw config, react triggers render
model/allow/join/task sections, and unmatched metadata/config fall back
correctly. Keep the test fixture-driven so it exercises the same branches gated
by safeParseRequest, safeParseResponse, hasStateChips, and react rather than
only the schema validators.
console/web/src/components/chat/engine/parsers.ts (1)

302-307: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Clarify the Zod object behavior z.object() strips unknown keys by default, so this comment should say extra option keys are tolerated, not passed through.

🤖 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 `@console/web/src/components/chat/engine/parsers.ts` around lines 302 - 307,
Update the comment on reactOptionsSchema to match Zod’s actual behavior:
z.object() strips unknown keys by default, so describe that extra option keys
are tolerated/ignored rather than passed through. Keep the note focused on
reactOptionsSchema and ReactOptions so it accurately reflects what the parser
accepts.
🤖 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.

Nitpick comments:
In `@console/web/src/components/chat/engine/parsers.ts`:
- Around line 302-307: Update the comment on reactOptionsSchema to match Zod’s
actual behavior: z.object() strips unknown keys by default, so describe that
extra option keys are tolerated/ignored rather than passed through. Keep the
note focused on reactOptionsSchema and ReactOptions so it accurately reflects
what the parser accepts.

In `@console/web/src/components/chat/engine/RegisterTriggerView.tsx`:
- Around line 26-167: Add a dedicated rendering test for RegisterTriggerView to
cover the fallback-first branch logic. Use RegisterTriggerView and its existing
parse/fallback paths to verify that invalid input renders raw JSON, state
triggers render chips instead of raw config, react triggers render
model/allow/join/task sections, and unmatched metadata/config fall back
correctly. Keep the test fixture-driven so it exercises the same branches gated
by safeParseRequest, safeParseResponse, hasStateChips, and react rather than
only the schema validators.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c7c47473-0352-4e7e-bfe0-f700103227c7

📥 Commits

Reviewing files that changed from the base of the PR and between 9607559 and 0295d91.

📒 Files selected for processing (12)
  • console/web/src/components/chat/FunctionCallMessage.stories.tsx
  • console/web/src/components/chat/FunctionCallMessage.tsx
  • console/web/src/components/chat/engine/RegisterTriggerView.tsx
  • console/web/src/components/chat/engine/__tests__/parsers.test.ts
  • console/web/src/components/chat/engine/index.tsx
  • console/web/src/components/chat/engine/parsers.ts
  • console/web/src/components/chat/state/StateView.tsx
  • console/web/src/components/chat/state/__tests__/parsers.test.ts
  • console/web/src/components/chat/state/index.tsx
  • console/web/src/components/chat/state/parsers.ts
  • console/web/src/stories/fixtures/engine-fixtures.ts
  • console/web/src/stories/fixtures/state-fixtures.ts

…values

state::* results are arbitrary JSON, so running every result through the
shared sandbox error parser flagged a successful get of a value like
{ status: "denied" } / { denied_by: … } as a red "Denied" error, hiding
the real JSON on the default tab. Only run the parser for non-success
envelopes; genuine errors ({ error: { kind: "function_error" } }, wire/
denial shapes) still surface since they are never { content, details }.

Also dedupe the harness::react allow-list chips so the React key stays
unique when the engine-supplied allow list repeats a function id.

Adds state view render tests covering both directions.
@andersonleal
andersonleal merged commit 86ab88d into main Jul 2, 2026
13 checks passed
@andersonleal
andersonleal deleted the feat/console-trigger-state-views branch July 2, 2026 20:02
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.

3 participants