1111 */
1212
1313import { readFileSync } from "node:fs" ;
14- import { join } from "node:path" ;
14+ import { dirname , join } from "node:path" ;
15+ import { fileURLToPath } from "node:url" ;
1516import common from "@agentos-software/common" ;
1617import {
1718 OPT_AGENTOS_BIN ,
@@ -399,6 +400,16 @@ function buildNativeFactoryBuilder<TConnParams>(
399400 // spawns the bundled binary rather than relying on `agentos-sidecar`
400401 // being on PATH.
401402 sidecarPath : getSidecarPath ( ) ,
403+ // Custom inspector tabs. The native-plugin path bypasses the normal
404+ // actor-config assembly (`buildActorConfig`/`inspectorTabs`), so the
405+ // tabs MUST ride on the plugin options: the Rust NAPI binding
406+ // `from_native_plugin` forwards `inspectorTabs` into the actor config so
407+ // the dashboard serves `/inspector/custom-tabs/<id>/` and advertises them
408+ // in `tab-config`. (Setting `actor({ inspector })` alone does nothing for
409+ // native-plugin actors.)
410+ inspectorTabs : AGENTOS_INSPECTOR_CONFIG . tabs ,
411+ } as NapiNativePluginOptions & {
412+ inspectorTabs : typeof AGENTOS_INSPECTOR_CONFIG . tabs ;
402413 } ;
403414 return runtime . createNativePluginFactory ( options ) ;
404415 } ;
@@ -465,6 +476,34 @@ export const DEFAULT_AGENTOS_ACTOR_OPTIONS = {
465476 maxQueueMessageSize : ACTOR_NEVER_HIT_MESSAGE_BYTES ,
466477} as const ;
467478
479+ // Absolute path to the built inspector-tabs app (the shared Vite bundle). All
480+ // custom tabs share this one `source` dir; the app routes on the
481+ // `/inspector/custom-tabs/<id>/` URL segment. Resolves from both `src/` (tsx dev
482+ // / the demo) and the published `dist/`, since `assets/` sits at the package
483+ // root in both layouts.
484+ const INSPECTOR_TABS_ASSET_DIR = join (
485+ dirname ( fileURLToPath ( import . meta. url ) ) ,
486+ ".." ,
487+ "assets" ,
488+ "inspector-tabs-app" ,
489+ ) ;
490+
491+ // Custom inspector tabs shipped by agent-os. Ids MUST match the `TABS` registry
492+ // in `src/inspector-tabs/main.tsx`. The built-in rivetkit tabs are hidden so the
493+ // dashboard shows only the agent-os tabs.
494+ const AGENTOS_INSPECTOR_CONFIG = {
495+ tabs : [
496+ { id : "transcript" , label : "Transcript" , source : INSPECTOR_TABS_ASSET_DIR , icon : "comments" } ,
497+ { id : "filesystem" , label : "Filesystem" , source : INSPECTOR_TABS_ASSET_DIR , icon : "folder-tree" } ,
498+ { id : "processes" , label : "Processes" , source : INSPECTOR_TABS_ASSET_DIR , icon : "microchip" } ,
499+ { id : "software" , label : "Software" , source : INSPECTOR_TABS_ASSET_DIR , icon : "box-archive" } ,
500+ { id : "mounts" , label : "Mounts" , source : INSPECTOR_TABS_ASSET_DIR , icon : "hard-drive" } ,
501+ ...( [ "workflow" , "database" , "state" , "queue" , "connections" , "console" ] . map (
502+ ( id ) => ( { id, hidden : true as const } ) ,
503+ ) ) ,
504+ ] ,
505+ } ;
506+
468507export function agentOs < TConnParams = undefined > (
469508 config : AgentOsActorConfigInput < TConnParams > ,
470509) : AgentOsActorDefinition < TConnParams > {
@@ -487,6 +526,10 @@ export function agentOs<TConnParams = undefined>(
487526 const definition = actor ( {
488527 actions : { } ,
489528 options : actorOptions ,
529+ // Register the custom agent-os inspector tabs (and hide the built-in
530+ // rivetkit tabs) so the dashboard renders the agent-os UI. Without this
531+ // the shipped tab assets are never surfaced.
532+ inspector : AGENTOS_INSPECTOR_CONFIG ,
490533 } as Parameters <
491534 typeof actor
492535 > [ 0 ] ) as unknown as AgentOsActorDefinition < TConnParams > ;
0 commit comments