/** * Inspect Tools — read-only inspection tools for agents. * * `read_agent_events` is available to every session. It lets an ancestor * read the durable event stream of a descendant in its spawn tree using * the existing `session_events.seq` cursor. * * A small read-only subset is exposed to permanent system agents so they can * inspect sessions and owner-scoped usage without mutating state. The deeper * diagnostic tools are the diagnostic bundle — historically the `agent-tuner` * system agent's alone, and soon an installable package's (see * docs/proposals/agent-authoring-capability.md). * * ── The viewer spine ────────────────────────────────────────────── * These tools used to take no principal at all: `agentIdentity` decided * everything, and the tuner bypassed the one scoping rule that existed. That * was sound only while the sole holder was an ownerless system session. The * moment a USER-owned session holds the diagnostic bundle, "no principal" * becomes "every principal", so every session-touching tool now resolves a * viewer from its session's OWNER and routes through one of three rules: * * scopeSessions(rows) — lists: filter to what the viewer may see * ensureVisible(id) — direct reads: refuse what they may not * requireAdmin(tool) — fleet aggregates, which have neither a * session id nor a session list to filter * * A tool that touches sessions and uses none of the three is a bug; the * inspect-viewer-spine test greps for exactly that. * * The decision itself is NOT reimplemented here — `evaluateSessionAccess` * comes from pilotswarm-sdk/api, the same function the portal's HTTP routes * call, so a rule change lands on both surfaces at once. * * Inspect tools never mutate state. * * @module * @internal */ import type { Tool } from "@github/copilot-sdk"; import type { SessionCatalog } from "./cms.js"; import { type AdminScope } from "../api/src/admin-scope.js"; /** * Who these tools act as. Derived from the SESSION OWNER — never from a tool * argument, or the model could name its own privileges. */ export interface InspectViewer { provider: string; subject: string; /** * Resolved fresh, not stamped at session creation: a session can outlive * the role that created it, and stamping would let a demoted admin keep * fleet-wide reach for as long as their session stayed alive. */ isAdmin: boolean; adminScope?: AdminScope; /** Server-resolved session classification; never inferred from the agent name. */ isSystemSession?: boolean; /** * The first-class System principal (ownerless platform sessions). Reaches * everything, as it does today — the sweeper cannot do its job otherwise. */ isSystemPrincipal: boolean; } /** * FAIL CLOSED. Every unknown becomes the least privilege, never the most: * an unresolvable owner is not an admin and owns nothing, so it can read * exactly nothing rather than everything. Returned whenever a resolver is * absent, throws, or yields an identity we cannot use. */ export declare const NO_VIEWER: InspectViewer; export interface CreateInspectToolsOptions { catalog: SessionCatalog; agentIdentity?: string; /** * Resolve the acting viewer. Called PER TOOL INVOCATION (implementations * should cache per turn) so a role change takes effect on the next turn * rather than the next session. * * Omitted → NO_VIEWER → session-touching tools refuse. That default is * deliberate: a caller that forgets to pass this gets a useless agent, * not a fleet-wide reader. */ resolveViewer?: () => Promise | InspectViewer | null; /** * Optional duroxide client used by tuner-only tools that read * orchestration stats and execution history. May be omitted for * non-tuner sessions; the corresponding tools simply don't get * registered. */ duroxideClient?: any; /** * Optional fact store used by tuner-only facts-stats tools. When * omitted, the facts-stats inspect tools are not registered and * the tuner falls back to the management API surface. */ factStore?: import("./facts-store.js").FactStore; /** * Artifact store, for the write bundle's patch artifacts. Omitted → * `propose_agent_patch` refuses with a clear message rather than throwing. */ artifactStore?: import("./session-store.js").ArtifactStore | null; /** The session these tools act in, used to attach patch artifacts. */ sessionId?: string; /** * Deployment MCP catalog entries restricted with `allowedAgents`. The * write bundle's publish refuses a package that defines one of these * names, since every worker would drop that definition at load. */ reservedMcpServerNames?: string[]; } export declare function createInspectTools(opts: CreateInspectToolsOptions): Tool[]; //# sourceMappingURL=inspect-tools.d.ts.map