(MOT-4208) feat(database): console function-calls view + UNKNOWN_DB handle enumeration - #580
Conversation
An agent that guesses a wrong db handle got only the bad name echoed
back — in a live scan run, sub-agents burned 25 failed database::execute
calls each brute-forcing 23 handle names before landing on "primary".
UnknownDb now carries the registered handle names, filled from the pools
map at the miss site, so one failure teaches the right name:
{"code":"UNKNOWN_DB","db":"scans","available":["primary"]}
The code field and existing fields are unchanged; `available` is
additive. listDatabases already exposes the same names to any caller
that can reach the worker, so no new information surface.
…derer Ship the SOP scaffold (docs/sops/injectable-console-ui.md, state worker template) and a function-trigger renderer covering all 13 database::* functions, so calls render as real cards in chat and traces instead of raw JSON: - query/transactionQuery/runStatement: highlighted SQL, params, result rows as a table (capped at 50 with a +N note) - execute/transactionExecute: SQL + affected rows + returned rows - executeBatch/transaction: numbered step list, failed step marked, committed/rolled-back chip - prepareStatement/beginTransaction/commit/rollback: handle + status - listDatabases: name/driver/url/pool table - FunctionIdLabel dims the database:: prefix on every card header Error outputs return null and fall through to the console's built-in error card. Assets are esbuild outputs embedded via include_str! and registered through the shared iii-console-ui crate (content function database::ui-content, III_DATABASE_UI_WATCH dev watcher). main.rs now Arc-wraps the client — ConsoleUi::register needs &Arc<IIIClient>; deref coercion keeps every existing call site unchanged.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
skill-check — worker0 verified, 48 skipped (no docs/).
Four for four. Nicely done. |
|
Warning Review limit reached
Next review available in: 49 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe database worker now builds and embeds a console UI that renders database function triggers, registers the UI during worker startup, and reports available database handles in unknown-database errors. ChangesDatabase Console UI
Sequence Diagram(s)sequenceDiagram
participant ConsoleHost
participant DatabaseTriggerRenderer
participant DatabaseParsers
participant DatabaseWorker
ConsoleHost->>DatabaseTriggerRenderer: register database function-trigger renderer
DatabaseTriggerRenderer->>DatabaseParsers: parse request and output envelope
DatabaseParsers-->>DatabaseTriggerRenderer: normalized operation data
DatabaseTriggerRenderer->>DatabaseWorker: render database operation state
DatabaseWorker-->>ConsoleHost: display embedded database UI
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
database/build.rs now shells out to pnpm to build ui/dist before embedding it; the e2e job installed Node but not pnpm, so the cargo build died in locate_pnpm() (build.rs:168). ci.yml's rust job already sets up pnpm via the hashFiles(ui/package.json) condition, and the release path auto-detects ui/ (web_bundle) — this was the one job missing the toolchain.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@database/ui/src/function-trigger-message/index.tsx`:
- Around line 18-24: Update the imports in function-trigger-message to import
React before the existing React.ReactNode type references, preserving the
current CodeHighlight and renderer imports and component 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: CHILL
Plan: Pro Plus
Run ID: 7139fac8-7b4b-414b-b8fc-e9601a407d74
⛔ Files ignored due to path filters (2)
database/Cargo.lockis excluded by!**/*.lockpnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (18)
database/Cargo.tomldatabase/build.rsdatabase/src/driver/sqlite.rsdatabase/src/error.rsdatabase/src/handlers/mod.rsdatabase/src/handlers/query.rsdatabase/src/handlers/transaction.rsdatabase/src/lib.rsdatabase/src/main.rsdatabase/src/ui.rsdatabase/ui/build.mjsdatabase/ui/package.jsondatabase/ui/page.tsxdatabase/ui/src/function-trigger-message/index.tsxdatabase/ui/src/function-trigger-message/parsers.tsdatabase/ui/styles.cssdatabase/ui/tsconfig.jsonpnpm-workspace.yaml
| import { | ||
| CodeHighlight, | ||
| type FunctionTriggerMessage, | ||
| type FunctionTriggerRenderer, | ||
| type Host, | ||
| JsonHighlight, | ||
| } from '@iii-dev/console-ui' |
There was a problem hiding this comment.
🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Confirm no react import exists despite React.ReactNode usage
rg -n "React\." database/ui/src/function-trigger-message/index.tsx
rg -n "^import" database/ui/src/function-trigger-message/index.tsx
cat -n database/ui/tsconfig.jsonRepository: iii-hq/workers
Length of output: 671
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== package scripts =="
node - <<'JS'
const fs = require('fs');
for (const p of ['package.json','database/ui/package.json']) {
if (fs.existsSync(p)) {
const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));
console.log(p, pkg.scripts || {});
}
}
JS
echo "== dependency availability =="
if [ -d node_modules/typescript/lib ]; then
tslib=$(find node_modules/typescript/lib -maxdepth 1 -name 'typescript*.d.ts' | head -1)
echo "typescript d.ts: ${tslib:-missing}"
else
echo "node_modules/typescript/lib missing"
fi
echo "== exact file excerpt =="
sed -n '1,40p;65,78p;338,350p' database/ui/src/function-trigger-message/index.tsx | cat -n
echo "== behavioral probe against repository TypeScript config (if tsc is available) =="
node - <<'JS'
const {existsSync, readFileSync, writeFileSync} = require('fs');
const {execFileSync} = require('child_process');
if (!existsSync('node_modules/.bin/tsc')) {
console.log('tsc not available in node_modules/.bin');
process.exit(0);
}
const tsconfig = JSON.parse(readFileSync('database/ui/tsconfig.json','utf8'));
tsconfig.include = ['src/function-trigger-message/index.tsx'];
writeFileSync('/tmp/probe-tsconfig.json', JSON.stringify(tsconfig, null, 2));
const probe = `import { CodeHighlight } from '`@iii-dev/console-ui`';
type T1 = React.ReactNode;
declare const x: T1;
`;
writeFileSync('/tmp/probe.tsx', probe);
writeFileSync('/tmp/probe-package.json', JSON.stringify({type:'module'}));
try {
execFileSync('node_modules/.bin/tsc', ['/tmp/probe.tsx', '--project', '/tmp/probe-tsconfig.json', '--noEmit'], {stdio:'inherit'});
console.log('RESULT: tsc no error');
} catch (e) {
console.log('RESULT: tsc failed with exit', e.status);
}
JSRepository: iii-hq/workers
Length of output: 3145
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate `@types/react` availability =="
fd -a "^index\.d\.ts$" node_modules 2>/dev/null | rg '/@types/react/.*/index\.d\.ts$|react.*index\.d\.ts' | head -5 || true
echo "== package manifests mentioning react and deps =="
python3 - <<'PY'
import json, pathlib
for p in pathlib.Path('.').rglob('package.json'):
if 'node_modules' in p.parts:
continue
try:
pkg=json.loads(p.read_text())
except Exception:
continue
deps={}
for k in ['dependencies','devDependencies','peerDependencies','optionalDependencies']:
if k in pkg:
deps.update(pkg[k])
if 'react' in deps or 'react-dom' in deps:
print(p, {dep: deps.get(dep) for deg, dep in enumerate(deps) if dep in ('react','react-dom')})
PY
echo "== local package lock react entries (if present) =="
for f in package-lock.json npm-shrinkwrap.json pnpm-lock.yaml yarn.lock bun.lockb bun.lock; do
[ -f "$f" ] && echo "--- $f" && rg -n '"?react"?:|react@|react-dom' "$f" | head -20 || true
doneRepository: iii-hq/workers
Length of output: 2612
🏁 Script executed:
#!/bin/bash
set -euo pipefail
node - <<'JS'
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('database/ui/package.json', 'utf8'));
const entries = [
...Object.entries(pkg.dependencies || {}),
...Object.entries(pkg.devDependencies || {}),
...Object.entries(pkg.peerDependencies || {}),
];
const reactRelevant = entries.filter(([name]) => name === 'react' || name === 'react-dom' || name === '`@types/react`' || name === '`@types/react-dom`' || name.includes('console-ui'));
console.log(JSON.stringify({name: pkg.name, scripts: pkg.scripts, reactRelevant}, null, 2));
JSRepository: iii-hq/workers
Length of output: 437
🌐 Web query:
TypeScript MDX @mdx-js/react v3 React.ReactNode without import JSX namespace react-jsx
💡 Result:
To use TypeScript with @mdx-js/react v3 and React.ReactNode without explicitly importing the global JSX namespace or react-jsx, you must ensure that your TypeScript environment is correctly configured to recognize the React types [1][2]. 1. Install React Types: The foundational requirement is to have @types/react installed in your project [1][3]. npm install --save-dev @types/react 2. Understanding the JSX Namespace: The MDX documentation explicitly states that for types to function correctly, the TypeScript JSX namespace must be typed [2][4]. This is achieved by including @types/react in your project's dependencies [1][5]. TypeScript automatically merges JSX types into the global namespace when these types are present [6][7]. You do not need to manually import a "JSX namespace" or "react-jsx" in your individual files; rather, you rely on the presence of the @types/react package to provide these definitions globally for your project [1][3]. 3. Type Usage: When defining components that use React.ReactNode, you can import it directly from 'react' to avoid relying on implicit globals [7]. import type { ReactNode } from 'react'; // Using it in a component interface MyProps { children?: ReactNode; } 4. MDX Integration: When using @mdx-js/react, ensure your MDX compiler (e.g., in Webpack, Vite, or Rollup) is configured with providerImportSource: '@mdx-js/react' [2][4]. This allows MDX to use the React context provider for components [8][9]. If you are encountering errors regarding "ReactNode" not being found or JSX types missing, it is typically because @types/react is either missing or your tsconfig.json is not including the necessary type definitions. Ensure your tsconfig.json includes "compilerOptions": { "types": ["react", "react-dom"] } if automatic detection fails, though this is rarely necessary in modern setups [1][5].
Citations:
- 1: https://github.com/mdx-js/mdx/blob/main/packages/react/readme.md
- 2: https://mdxjs.com/packages/react/
- 3: https://registry.npmjs.org/@mdx-js/react
- 4: https://mdxjs.com/packages/mdx/
- 5: https://mdxjs.com/docs/getting-started/
- 6: Avoid making React JSX types global, to play well with other JSX frameworks. DefinitelyTyped/DefinitelyTyped#52321
- 7: https://stackoverflow.com/questions/79073169/property-reactnode-does-not-exist-on-type-typeof-react
- 8: https://tessl.io/registry/tessl/npm-mdx-js--react/3.1.0
- 9: https://github.com/mdx-js/mdx/blob/main/docs/docs/using-mdx.mdx
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== console-ui package metadata =="
node - <<'JS'
const fs = require('fs');
for (const rel of ['packages/console-ui/package.json','console/package/package.json','console/web/package.json','database/ui/package.json']) {
try {
const data = JSON.parse(fs.readFileSync(rel, 'utf8'));
console.log('---', rel);
console.log(JSON.stringify({name:data.name, version:data.version, scripts:data.scripts, dependencies:data.dependencies, devDependencies:data.devDependencies, peerDependencies:data.peerDependencies, exports:data.exports, types:data.types, main:data.main}, null, 2));
} catch (e) {
console.log('---', rel, e.message);
}
}
JS
echo "== tsconfig resolution in relevant packages =="
for f in database/ui/tsconfig.json packages/console-ui/tsconfig.json console/web/tsconfig.json console/package/tsconfig.json; do
[ -f "$f" ] && { echo "--- $f"; cat -n "$f"; }
done
echo "== deterministic TypeScript JSX namespace probe from scratch =="
cd "$(mktemp -d)"
export HOME="$(mktemp -d)"
cat > tsconfig.json <<'JSON'
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "bundler",
"jsx": "react-jsx",
"strict": true,
"skipLibCheck": true,
"noEmit": true,
"types": []
},
"include": ["probe.tsx"]
}
JSON
cat > package.json <<'JSON'
{"type":"module"}
JSON
mkdir -p node_modules/@types/react
cat > node_modules/@types/react/index.d.ts <<'DTS'
export as namespace React;
export type ReactNode = null | boolean | string | number | ReactElement;
interface JSX {
createElement(type: any, props?: any, ...children: any[]): ReactElement;
}
export interface ReactElement {}
DTS
cat > probe.tsx <<'TSX'
import { Component } from '`@iii-dev/console-ui`';
type Props = { head?: React.ReactNode; children?: React.ReactNode };
const render = (): React.ReactNode | null => null;
TSX
npm install --no-save --no-audit --no-fund typescript 1>/dev/null
./node_modules/.bin/tsc --project tsconfig.json 2>&1 || trueRepository: iii-hq/workers
Length of output: 4468
Import React before referencing React.ReactNode.
This file references React.ReactNode three times, but has no react/React import. With this module containing top-level import/export and the UI build running tsc --noEmit, these React namespace references fail TypeScript type-checking.
🐛 Proposed fix
import {
CodeHighlight,
type FunctionTriggerMessage,
type FunctionTriggerRenderer,
type Host,
JsonHighlight,
} from '`@iii-dev/console-ui`'
+import type React from 'react'
import {
DB_PREFIX,
type DbRequest,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import { | |
| CodeHighlight, | |
| type FunctionTriggerMessage, | |
| type FunctionTriggerRenderer, | |
| type Host, | |
| JsonHighlight, | |
| } from '@iii-dev/console-ui' | |
| import { | |
| CodeHighlight, | |
| type FunctionTriggerMessage, | |
| type FunctionTriggerRenderer, | |
| type Host, | |
| JsonHighlight, | |
| } from '`@iii-dev/console-ui`' | |
| import type React from 'react' |
🤖 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 `@database/ui/src/function-trigger-message/index.tsx` around lines 18 - 24,
Update the imports in function-trigger-message to import React before the
existing React.ReactNode type references, preserving the current CodeHighlight
and renderer imports and component behavior.
…ndency pnpm@11 (repo packageManager) needs the node:sqlite builtin (Node >=22.5) for its store; the job pinned Node 20 so pnpm install died with ERR_UNKNOWN_BUILTIN_MODULE inside build.rs. ci.yml's pnpm jobs already standardize on 22; the e2e harness has no engines pin (only a @types/node ^20 dev dependency, which is types-only).
What
Two changes to the
databaseworker, motivated by watching a live agent scan run (secaas-7k3m) in the console:1.
UNKNOWN_DBerrors enumerate the available handles (fix)Sub-agents in that run each burned 25 failed
database::executecalls brute-forcing 23 db-handle names (scans,secaas,default,app.db, …) before landing onprimary— the error only echoed the bad name back. Now:{"code":"UNKNOWN_DB","db":"scans","available":["primary"]}One failure teaches the right name. Additive on the wire (
codeand existing fields unchanged);listDatabasesalready exposes the same names to any caller that can reach the worker.2. Injectable console UI: database function-calls view (
feat)Per
docs/sops/injectable-console-ui.md(state worker template): the worker now ships a function-trigger renderer covering all 13database::*functions, so calls render as real cards in chat and traces instead of raw JSON —query/transactionQuery/runStatement: highlighted SQL, params, result-row table (capped at 50,+N more)execute/transactionExecute: SQL + affected rows + returned rowsexecuteBatch/transaction: numbered step list, failed step marked, committed/rolled-back chipprepareStatement/beginTransaction/commit/rollback: handle + status lineslistDatabases: name/driver/url/pool tableFunctionIdLabeldims thedatabase::prefix on every card headerError outputs fall through to the console's built-in error card (which renders the new
availablelist from change 1). Renderer only — no page, no config form; those slots can be added later without rework.How
stateworker:build.rs(pnpm→esbuild→ui/dist),src/ui.rs(include_str!+iii-console-uicrate registration,III_DATABASE_UI_WATCHdev watcher),database/ui/pnpm project joined to the root UI workspace.main.rsnow Arc-wraps the client (ConsoleUi::registerneeds&Arc<IIIClient>; deref coercion keeps every existing call site unchanged).Verification
cargo testin a fresh worktree (no prebuiltui/dist— exercises the full build.rs→pnpm→esbuild→embed path): 228 passed, 0 failed (incl. 3 newui.rsasset tests + extendedUNKNOWN_DBtests pinning the wire envelope).pnpm buildindatabase/ui: tsc strict clean,page.js13.4kb /styles.css3.3kb.GET /uimanifest lists both assets with emptywarnings(scoped-CSS lint clean); opened a live scan session in the console — custom cards render (QUERY pill,db primarychip, highlighted SQL, results table), error-status cards correctly fall through to the built-in error view,FunctionIdLabelstyles everydatabase::*header.No version bump / changelog per repo convention (workers-ci handles versions post-merge).
Summary by CodeRabbit