/** * The Agent Manager write bundle — package mutation, diffing and import. * * Kept out of `inspect-tools.ts` deliberately: that file is the READ surface * and its grep-guard reasons about session-scoped reads. These tools are * package-scoped and mutating, with a different authorization story * (creator-or-admin on the package, not visibility on a session), and mixing * the two would blur which rule applies where. * * **Authorization is not implemented here.** Every mutation calls the same * `agent-package-service` / catalog functions the Web API calls, which enforce * creator-or-admin inside the database with a row lock. That is the whole * point of §4: one authz implementation serving portal, CLI, MCP and the * manager, so a tool cannot become a side door. * * @module */ import type { Tool } from "@github/copilot-sdk"; import type { SessionCatalog, AgentPackageSelector } from "./cms.js"; import type { ArtifactStore } from "./session-store.js"; import { type ImportPolicy } from "./agent-package-import-policy.js"; import { type AdminScope } from "../api/src/admin-scope.js"; /** * Staging lives in ONE session artifact rather than N. * * Durable (so it survives the session moving workers), atomic (a half-written * edit is not a thing), and visible to a human in the portal's artifact list * while they are deciding whether to approve it. */ export declare const STAGING_ARTIFACT = "agent-package-staging.json"; /** * Agent ids that hold the manager bundle. * * Lives here rather than in inspect-tools so BOTH halves of a manager tool can * gate on one list: the declaration (this bundle) and the per-turn handler * (managed-session). Declaring a tool the model cannot see but whose handler is * still registered is a latent capability, so the two must agree. * * Per §15 A10 a name must never GRANT: this selects which agents BEHAVE like * managers, not what a manager may do. Every one of these tools re-checks * authority against the live catalog (owner-or-admin, system sessions * refused), so a package declaring this id gains nothing its owner did not * already have. */ export declare const MANAGER_AGENT_IDS: Set; /** * May the calling principal act on `target`? * * The DECISION only — the caller does the IO and hands in what it read. Kept * pure and exported so the rule is directly testable: it is the gate on * messaging a session as its user and on completing/cancelling/deleting one, * and a gate nobody can unit-test is a gate nobody can trust. * * Owner-or-admin, deliberately narrower than "can read". Visibility includes * sessions shared WITH you, and being allowed to watch a run is not being * allowed to type into it or end it. */ export declare function decideSessionControl(args: { /** The target session row, or null when it was not found. */ target: { isSystem?: boolean; owner?: { provider?: string; subject?: string; } | null; } | null; /** Short id, for the message only. */ targetIdLabel: string; /** The calling session's owner, or null when it could not be resolved. */ caller: { provider?: string; subject?: string; } | null; callerIsAdmin: boolean; adminScope?: AdminScope; /** Lifecycle operations refuse system sessions; messaging does not use this. */ refuseSystem?: boolean; }): { ok: true; } | { ok: false; reason: string; }; /** Does this agent identity hold the manager bundle? */ export declare function holdsManagerBundle(agentIdentity?: string | null): boolean; /** The changelog every package carries. Read before editing, appended on publish. */ export declare const CHANGELOG_PATH = "CHANGELOG.md"; export interface AgentManagerViewer { provider: string; subject: string; isAdmin: boolean; adminScope?: AdminScope; isSystemPrincipal: boolean; } export interface CreateAgentManagerToolsOptions { catalog: SessionCatalog; artifactStore?: ArtifactStore | null; /** Resolved per invocation, exactly as the read bundle does. */ resolveViewer: () => Promise; /** Injectable for tests; loaded from the deployment config otherwise. */ importPolicy?: ImportPolicy; /** Session id used to attach patch artifacts. */ sessionId?: string; /** Agent names a package may not shadow. Defaults to bundled agents. */ reservedAgentNames?: string[]; /** Deployment MCP catalog names restricted with `allowedAgents`; a package may not define them. */ reservedMcpServerNames?: string[]; } /** Turn an FQN into a registry selector, or explain why it cannot be one. */ export declare function selectorFromReference(reference: string, viewer: AgentManagerViewer): { name: string; selector: AgentPackageSelector | null; semver?: string; error?: string; }; /** * Resolve a reference, including one naming ANOTHER owner. * * `selectorFromReference` stays sync and directory-free, so it can only ever * resolve the viewer's own copy. That is the right answer for a normal user — * their manager reaches their own packages and the shared ones, nothing else. * * An administrator is a different case: their manager is meant to reach the * whole fleet, and refusing `:` left admins able to LIST * another user's package (`cms_list_agent_packages` returns everything when * `p_is_admin`) while being unable to open it. The database already accepts an * owner selector and already gates on `p_is_admin`; only this layer said no. * * The owner is resolved through the users table — by subject, email, or * display name — so an admin can name a person the way a person is named. * Resolution is by lookup, never by trusting the string: a non-admin keeps the * original refusal, and an unmatched name is an error rather than a fallback * to the viewer's own copy. */ export declare function resolveReference(reference: string, viewer: AgentManagerViewer, catalog: Pick): Promise<{ name: string; selector: AgentPackageSelector | null; semver?: string; error?: string; }>; export declare function createAgentManagerTools(opts: CreateAgentManagerToolsOptions): Tool[]; //# sourceMappingURL=agent-manager-tools.d.ts.map