This repository was archived by the owner on Jun 8, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
FEA-1504: Gate embedded agent dashboard #264
Merged
Merged
Changes from 18 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
a6427ce
FEA: Replace agent-monitor sidecar with in-process SQLite database + …
mikeangstadt de59efd
FEA: Address PR #264 review feedback + feature parity + performance
mikeangstadt 132c2d3
FEA: Hoist prepared statements, fix nav labels, reorder nav
mikeangstadt 6d4b957
FEA: Fix query perf on large databases (2.7M events)
mikeangstadt cd526af
FEA: Fix rowid index crash + add manual chunk splitting
mikeangstadt bfd25a0
FEA: Add covering indexes for 2.8M event table + decouple dashboard load
mikeangstadt 9272a7e
FEA: Consolidate nav — merge Analytics+Workflows into Agents, Activit…
mikeangstadt d623034
FEA-1497: Merge main + fix build (Phase 0)
thadeusb 5342e2b
FEA-1497: Green the test suite after main-merge (Phase 0)
thadeusb 3911766
FEA-1497: Re-merge main (#265, #266) to clear PR conflict (Phase 0)
thadeusb 09e9df4
FEA-1497: Fix pre-existing lint errors blocking CI (Phase 0)
thadeusb 617b9a7
FEA-1497: In-process hook listener + write engine (Phase 1 S1+S2)
thadeusb e9972e7
FEA-1497: Codex hook ingestion opt-in (Phase 1 S3)
thadeusb 5165ecf
FEA-1497: Renderer typed IPC + session drill-down + live updates (Pha…
thadeusb 1b6230d
FEA-1497: Atomic sidecar cutover + relay/recon repoint + boot migrati…
thadeusb a0a7b2b
FEA-1497: Address Phase 1 review findings (migration FK abort + harde…
thadeusb 9f357c4
FEA-1497: Reference breaking-change ticket IDs (FEA-1500, FEA-1501) i…
thadeusb cd8e6d5
FEA-1497: Address PR #264 review findings (validation, packaging, typ…
thadeusb 26259a7
FEA: consume published design-system package
mikeangstadt d589c41
FEA: avoid broken design-system root provider
mikeangstadt e366306
FEA: patch published design-system bundle in vite
mikeangstadt fd3c992
FEA: switch desktop to published design-system package
mikeangstadt 0280eed
FEA: avoid analytics fetch on dashboard load
mikeangstadt 846bb40
FEA: tighten sessions dashboard layout
mikeangstadt 5c47688
FEA: defer to design-system renderer globals
mikeangstadt 3a20dad
FEA: cache historical sessions and preserve views
mikeangstadt eb8157a
FEA: defer heavy analytics sections
mikeangstadt a876313
FEA-1503: In-process multi-harness collection + vendor removal
thadeusb ca3855c
Merge remote-tracking branch 'origin/feat/in-process-agent-database' …
thadeusb 1da1146
FEA-1503: Fix CI 403 on @closedloop-ai/design-system via org-scoped a…
thadeusb 6847025
FEA-1503: Revert CI app-token plumbing; grant-based package access
thadeusb b4ba906
FEA-1497: Address PR #264 review findings (DS pinning, Topbar labels,…
mikeangstadt f40b4d1
FEA-1497: Address remaining PR #264 review findings (settings parity,…
shafty023 143dc11
Merge remote-tracking branch 'origin/feat/in-process-agent-database' …
shafty023 0372f26
FEA-1504: Finalize gated agent dashboard
shafty023 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| node_modules | ||
| dist | ||
| !apps/desktop/vendor/design-system/dist/ | ||
| .DS_Store | ||
| .idea | ||
| .vscode | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export default { | ||
| plugins: { | ||
| "@tailwindcss/postcss": {}, | ||
| }, | ||
| }; |
80 changes: 80 additions & 0 deletions
80
apps/desktop/scripts/agent-monitor-codex/codex-hook-handler.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| #!/usr/bin/env node | ||
|
|
||
| /** | ||
| * @file codex-hook-handler.js | ||
| * @description Codex CLI hook handler. Mirrors the upstream Claude | ||
| * `hook-handler.js` (provider-agnostic, POSTs to `/api/hooks/event` on the | ||
| * fixed agent-monitor sidecar port 4820) but injects `__provider: "codex"` | ||
| * into the forwarded payload so the sidecar can stamp the session row with | ||
| * `harness='codex'` via the existing `setSessionHarness` statement. | ||
| * | ||
| * Zero-dep, plain JS, fail-silent — same constraints as the upstream Claude | ||
| * handler so a hook never blocks a Codex turn. Codex calls this once per | ||
| * lifecycle event (SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, | ||
| * Stop) with the event name as the single argv arg. | ||
| * | ||
| * Part of FEA-1444 (opt-in Codex hook ingestion). | ||
| */ | ||
|
|
||
| const http = require("http"); | ||
|
|
||
| const hookType = process.argv[2] || "unknown"; | ||
| const port = parseInt(process.env.CLAUDE_DASHBOARD_PORT || "4820", 10); | ||
|
|
||
| let input = ""; | ||
|
|
||
| process.stdin.setEncoding("utf8"); | ||
| process.stdin.on("data", (chunk) => (input += chunk)); | ||
| process.stdin.on("end", () => { | ||
| let parsedData; | ||
| try { | ||
| parsedData = JSON.parse(input); | ||
| } catch { | ||
| parsedData = { raw: input }; | ||
| } | ||
|
|
||
| // Mark the payload as Codex-sourced so the sidecar's hooks-route patch | ||
| // (build-agent-monitor.mjs `patchHooksRouteCodexHarness`) can stamp the | ||
| // session's `harness` column. Field name is dunder-prefixed to make it | ||
| // obvious this is a transport hint, not a Codex-native field. | ||
| const enrichedData = | ||
| parsedData && typeof parsedData === "object" && !Array.isArray(parsedData) | ||
| ? { ...parsedData, __provider: "codex" } | ||
| : { raw: parsedData, __provider: "codex" }; | ||
|
|
||
| const payload = JSON.stringify({ | ||
| hook_type: hookType, | ||
| data: enrichedData, | ||
| }); | ||
|
|
||
| const req = http.request( | ||
| { | ||
| hostname: "127.0.0.1", | ||
| port, | ||
| path: "/api/hooks/event", | ||
| method: "POST", | ||
| headers: { | ||
| "Content-Type": "application/json", | ||
| "Content-Length": Buffer.byteLength(payload), | ||
| }, | ||
| timeout: 3000, | ||
| }, | ||
| (res) => { | ||
| res.resume(); | ||
| process.exit(0); | ||
| }, | ||
| ); | ||
|
|
||
| req.on("error", () => process.exit(0)); | ||
| req.on("timeout", () => { | ||
| req.destroy(); | ||
| process.exit(0); | ||
| }); | ||
|
|
||
| req.write(payload); | ||
| req.end(); | ||
| }); | ||
|
|
||
| // Safety net timeout — Codex's default hook timeout is around 5s; never let | ||
| // this process linger longer than that. | ||
| setTimeout(() => process.exit(0), 5000); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| // Patches vendored @closedloop-ai/design-system dist files that reference | ||
| // `React` as a bare global (missing/incorrect import/require statements). | ||
| // Run after pnpm install or by build:renderer. | ||
|
|
||
| import { readFileSync, writeFileSync, readdirSync, statSync } from "node:fs"; | ||
| import { join, extname } from "node:path"; | ||
|
|
||
| const VENDOR_DIST = new URL( | ||
| "../vendor/design-system/dist", | ||
| import.meta.url, | ||
| ).pathname; | ||
|
|
||
| const REACT_CJS_LINE = 'var React = require("react");\n'; | ||
| const REACT_ESM_LINE = 'import React from "react";\n'; | ||
|
|
||
| function hasScopeImport(code) { | ||
| return ( | ||
| /\bvar\s+React\b\s*=/.test(code) || | ||
| /import\s+(?:\*\s+as\s+)?React\s+from\s/.test(code) || | ||
| /\bimport\s+\{[^}]*\bReact\b[^}]*\}\s+from\s/.test(code) | ||
| ); | ||
| } | ||
|
|
||
| function walk(dir) { | ||
| const entries = readdirSync(dir); | ||
| for (const entry of entries) { | ||
| const full = join(dir, entry); | ||
| if (statSync(full).isDirectory()) { | ||
| walk(full); | ||
| } else if (entry.endsWith(".js") || entry.endsWith(".cjs") || entry.endsWith(".mjs")) { | ||
| patch(full); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| function patch(file) { | ||
| let code = readFileSync(file, "utf-8"); | ||
| const ext = extname(file); | ||
|
|
||
| // --- Step 1: Deduplicate stale patches from earlier tool runs --- | ||
| // If our patch line is present AND there's already a proper React import, | ||
| // remove the stale patch line. | ||
| const lines = code.split("\n"); | ||
| let changed = false; | ||
|
|
||
| // For ESM: check if line 1 is our patch and another React import exists | ||
| if ( | ||
| ext === ".mjs" && | ||
| (lines[0] === 'import React from "react"' || lines[0] === 'import React from "react";') && | ||
| hasScopeImport(code.slice(code.indexOf("\n") + 1)) | ||
| ) { | ||
| code = lines.slice(1).join("\n"); | ||
| changed = true; | ||
| } | ||
|
|
||
| // For CJS: check if line 2 (after "use strict") is our patch | ||
| if ( | ||
| ext !== ".mjs" && | ||
| lines[0] === '"use strict"' && | ||
| (lines[1] === 'var React = require("react")' || lines[1] === 'var React = require("react");') && | ||
| hasScopeImport(code.slice(code.indexOf("\n", code.indexOf("\n") + 1) + 1)) | ||
| ) { | ||
| code = '"use strict";\n' + lines.slice(2).join("\n"); | ||
| changed = true; | ||
| } | ||
|
|
||
| // --- Step 2: Re-check if already patched (dedup may have just cleaned it) --- | ||
| if (code.includes(REACT_ESM_LINE) || code.includes(REACT_CJS_LINE)) { | ||
| if (changed) { | ||
| writeFileSync(file, code); | ||
| console.log(` dedup: ${file.replace(VENDOR_DIST, "")}`); | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| // If dedup removed our patch but the file already has its own React import, we're done. | ||
| if (changed && hasScopeImport(code)) { | ||
| writeFileSync(file, code); | ||
| console.log(` dedup: ${file.replace(VENDOR_DIST, "")}`); | ||
| return; | ||
| } | ||
|
|
||
| // --- Step 3: Check if file needs patching --- | ||
| if (!/\bReact\s*[\.\(]/.test(code)) { | ||
| return; | ||
| } | ||
|
|
||
| // Skip if React is already properly in scope | ||
| if (hasScopeImport(code)) { | ||
| return; | ||
| } | ||
|
|
||
| const line = ext === ".mjs" ? REACT_ESM_LINE : REACT_CJS_LINE; | ||
| if (code.startsWith('"use strict";\n')) { | ||
| code = code.replace('"use strict";\n', '"use strict";\n' + line); | ||
| } else { | ||
| code = line + code; | ||
| } | ||
| writeFileSync(file, code); | ||
| console.log(` patched: ${file.replace(VENDOR_DIST, "")}`); | ||
| } | ||
|
|
||
| walk(VENDOR_DIST); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.