Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
0fdffdb
feat(agentos): inspector status strip, transcript composer, and layer…
NicholasKissel Jul 15, 2026
2691e39
feat(agentos): inspector permission approvals, tool-call transcript, …
NicholasKissel Jul 15, 2026
ce818fb
feat(agentos): interactive terminal tab on the contracted PTY surface
NicholasKissel Jul 15, 2026
a0f544b
feat(agentos): merge software and mounts into a system inspector tab
NicholasKissel Jul 15, 2026
9b6fe00
docs(website): document the inspector and link it from quickstart, de…
NicholasKissel Jul 15, 2026
09ce6aa
feat(agentos): inspector filesystem workbench, session controls, and …
NicholasKissel Jul 15, 2026
5bfde22
feat(agentos): promote runtime health, live sessions, and cancelPromp…
NicholasKissel Jul 15, 2026
9a4e86d
docs(website): document the inspector status strip
NicholasKissel Jul 15, 2026
97c76b0
feat(agentos): pending-permission backfill and permissionResolved bro…
NicholasKissel Jul 15, 2026
7b64be8
fix(agentos): route legacy software/mounts tab ids to the system tab
NicholasKissel Jul 15, 2026
2f52dff
fix(agentos): gate filesystem and system inspector tabs behind VM boot
NicholasKissel Jul 15, 2026
ea75940
fix(agentos): drop redundant VM running label from the inspector stat…
NicholasKissel Jul 15, 2026
d570eb8
feat(agentos): consolidate inspector tabs into transcript, terminal, …
NicholasKissel Jul 15, 2026
5138efb
fix(agentos): move live-session count into the sessions column and hi…
NicholasKissel Jul 15, 2026
061868e
feat(agentos): keep inspector shells alive across tab switches and al…
NicholasKissel Jul 15, 2026
00f652d
test(agentos): assert shell stdout round-trips over the shellData bro…
NicholasKissel Jul 15, 2026
37cbe6b
feat(agentos): replace the status strip row with per-tab VM status ba…
NicholasKissel Jul 15, 2026
dcaceb5
feat(agentos): redesign the system tab with an overview grid and expa…
NicholasKissel Jul 15, 2026
8d15e47
fix(agentos): composer shows options only for new sessions and drops …
NicholasKissel Jul 15, 2026
e624460
fix(agentos): drop duplicated session header and actor id from inspec…
NicholasKissel Jul 15, 2026
8ca8950
feat(agentos): unify inspector tabs on a shared sidebar layout with n…
NicholasKissel Jul 15, 2026
cfb783f
feat(agentos): icon buttons for inspector chrome actions
NicholasKissel Jul 15, 2026
1f2b30b
fix(agentos): persistent new-session button, relocated warning chips,…
NicholasKissel Jul 15, 2026
5715737
feat(agentos): agentOS watermark on transcript empty states
NicholasKissel Jul 15, 2026
57f4d2b
feat(agentos): full agentOS wordmark on transcript empty states
NicholasKissel Jul 15, 2026
3b24902
fix(agentos): use the real hero logo asset for the transcript watermark
NicholasKissel Jul 15, 2026
9e1ce8b
fix(agentos): session rows lead with a copyable id
NicholasKissel Jul 15, 2026
02e04a7
feat(agentos): copy buttons for warning panel sections
NicholasKissel Jul 15, 2026
663d43f
feat(agentos): agentOS watermark on terminal, filesystem, and boot-ga…
NicholasKissel Jul 15, 2026
8556215
fix(sidecar): backpressure the stdin frame queue instead of exiting
NicholasKissel Jul 15, 2026
38af158
fix(agentos): persist filesystem root and open file across tab switches
NicholasKissel Jul 15, 2026
675c836
feat(agentos): path bar follows tree clicks so folder actions target …
NicholasKissel Jul 15, 2026
670a6e7
feat(agentos): create sessions directly from the sidebar plus button …
NicholasKissel Jul 16, 2026
92e9c98
feat(agentos): software logos, centered empty states, and accurate pe…
NicholasKissel Jul 16, 2026
e8731d1
feat(agentos): filesystem up-navigation arrow and quiet tree expansion
NicholasKissel Jul 16, 2026
e300486
fix(agentos): drop persistence caveats and split the overview softwar…
NicholasKissel Jul 16, 2026
9c5b617
fix(agentos): keep previous file on screen while switching and always…
NicholasKissel Jul 16, 2026
1f44fef
fix(agentos): skip reading device nodes and add a glyph to the empty-…
NicholasKissel Jul 16, 2026
2595400
feat(agentos): card layout for the system tab with counts folded into…
NicholasKissel Jul 16, 2026
9bdb485
fix(agentos): theme-aware software logo chips
NicholasKissel Jul 16, 2026
7086ab9
fix(agentos): hue-true dark-mode treatment per software logo
NicholasKissel Jul 16, 2026
0ebbc3b
feat(agentos): session search by id in the transcript sidebar
NicholasKissel Jul 16, 2026
ea22fcc
fix(sidecar): raise ACP initialize timeout to 60s and name the limit …
NicholasKissel Jul 16, 2026
a466d21
feat(agentos): persist terminal output and query cache across inspect…
NicholasKissel Jul 16, 2026
c0ebbc9
feat(agentos): realtime filesystem change events end-to-end
NicholasKissel Jul 17, 2026
7fb082f
wip: archive working tree before frontend-only port
NicholasKissel Jul 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
95 changes: 95 additions & 0 deletions crates/agentos-actor-plugin/src/actions/contract_surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,45 @@ pub const ACTION_CONTRACTS: &[ActionContract] = &[
reply_shape: ReplyShape::Array,
ts_signature: "listSoftware: (c: Ctx) => Promise<SoftwareInfo[]>;",
},
// Observe-only actions (`actions::OBSERVE_ONLY`): dispatched without
// booting a sleeping VM. See `dispatch_observe` in actions/mod.rs.
ActionContract {
name: "getRuntimeHealth",
reply_shape: ReplyShape::Object(&[
"agentExits",
"booted",
"sessions",
"sidecar",
"stderrTail",
"warnings",
]),
ts_signature: "getRuntimeHealth: (c: Ctx) => Promise<RuntimeHealth>;",
},
ActionContract {
name: "listSessions",
reply_shape: ReplyShape::Array,
ts_signature: "listSessions: (c: Ctx) => Promise<LiveSessionInfo[]>;",
},
ActionContract {
name: "cancelPrompt",
reply_shape: ReplyShape::Unit,
ts_signature: "cancelPrompt: (c: Ctx, sessionId: string) => Promise<void>;",
},
ActionContract {
name: "listPendingPermissions",
reply_shape: ReplyShape::Array,
ts_signature:
"listPendingPermissions: (c: Ctx) => Promise<PendingPermissionInfo[]>;",
},
];

#[allow(dead_code)]
pub const EVENT_CONTRACTS: &[EventContract] = &[
EventContract {
name: "fsChanged",
payload_shape: ReplyShape::Object(&["dirs", "overflow"]),
ts_signature: "fsChanged: FsChangedPayload;",
},
EventContract {
name: "sessionEvent",
payload_shape: ReplyShape::Object(&["event", "sessionId"]),
Expand All @@ -264,6 +299,11 @@ pub const EVENT_CONTRACTS: &[EventContract] = &[
payload_shape: ReplyShape::Object(&["request", "sessionId"]),
ts_signature: "permissionRequest: PermissionRequestPayload;",
},
EventContract {
name: "permissionResolved",
payload_shape: ReplyShape::Object(&["permissionId", "reply", "sessionId"]),
ts_signature: "permissionResolved: PermissionResolvedPayload;",
},
EventContract {
name: "agentCrashed",
payload_shape: ReplyShape::Object(&["event", "sessionId"]),
Expand Down Expand Up @@ -511,6 +551,61 @@ const DTO_INTERFACES: &[TsInterface] = &[
field("commands", "string[]"),
],
},
TsInterface {
name: "LiveSessionInfo",
fields: &[field("sessionId", "string"), field("agentType", "string")],
},
TsInterface {
name: "PendingPermissionInfo",
fields: &[
field("sessionId", "string"),
field("permissionId", "string"),
optional_field("description", "string"),
field("params", "Record<string, unknown>"),
field("requestedAt", "number"),
],
},
TsInterface {
name: "RuntimeLimitWarning",
fields: &[
field("ts", "number"),
field("limit", "string"),
field("category", "string"),
field("observed", "number"),
field("capacity", "number"),
field("fillPercent", "number"),
],
},
TsInterface {
name: "RuntimeAgentExit",
fields: &[
field("ts", "number"),
field("sessionId", "string"),
field("agentType", "string"),
field("exitCode", "number | null"),
field("restart", "string"),
field("restartCount", "number"),
],
},
TsInterface {
name: "RuntimeStderrLine",
fields: &[field("ts", "number"), field("line", "string")],
},
TsInterface {
name: "RuntimeSidecarInfo",
fields: &[field("state", "string"), field("activeVmCount", "number")],
},
TsInterface {
name: "RuntimeHealth",
fields: &[
field("booted", "boolean"),
field("sessions", "number | null"),
field("sidecar", "RuntimeSidecarInfo | null"),
field("warnings", "RuntimeLimitWarning[]"),
field("agentExits", "RuntimeAgentExit[]"),
field("stderrTail", "RuntimeStderrLine[]"),
],
},
];

const fn field(name: &'static str, ty: &'static str) -> TsField {
Expand Down
42 changes: 42 additions & 0 deletions crates/agentos-actor-plugin/src/actions/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,3 +264,45 @@ impl From<BatchReadResult> for BatchReadResultDto {
}
}
}

/// `fsChanged` broadcast payload: one coalesced guest filesystem change
/// window from the runtime's `filesystem.changed` events.
#[derive(Serialize)]
struct FsChangedEvent {
dirs: Vec<String>,
overflow: bool,
}

pub(crate) fn encode_fs_changed_event(dirs: Vec<String>, overflow: bool) -> Result<Vec<u8>> {
super::encode_event_arg(&FsChangedEvent { dirs, overflow })
}

/// One `fsChanged` pump per VM lifetime, spawned on fresh boot next to the
/// health pumps: fans the client's coalesced `on_fs_changed` stream out to
/// actor clients as `fsChanged` broadcasts (the inspector Filesystem tab's
/// realtime invalidation signal). Tracked in [`Vars::fs_change_task`] so VM
/// teardown aborts it; a lagged subscriber already degrades to
/// `overflow: true` inside the client stream, so nothing is lost silently.
pub(crate) fn spawn_fs_change_pump(host: &crate::host_ctx::HostCtx, vm: &AgentOs, vars: &mut super::Vars) {
use futures::StreamExt;

let (mut stream, subscription) = vm.on_fs_changed();
let host = host.clone();
vars.fs_change_task = Some(tokio::spawn(async move {
// RAII guard: dropping the stream on abort is the unsubscribe.
let _subscription = subscription;
while let Some(change) = stream.next().await {
match encode_fs_changed_event(change.dirs, change.overflow) {
Ok(bytes) => {
let status = host.broadcast(b"fsChanged".to_vec(), bytes);
if status != rivet_actor_plugin_abi::AbiStatus::Ok {
tracing::warn!(?status, "fsChanged broadcast failed");
}
}
Err(error) => {
tracing::warn!(?error, "failed to encode fsChanged broadcast");
}
}
}
}));
}
Loading