import { type EndpointKind } from "@cotal-ai/core"; /** Keyed beta intake — used when a `COTAL_FEEDBACK_KEY` is configured. */ export declare const FEEDBACK_URL = "https://broker.cotal.ai/v1/feedback"; /** Public hosted intake — used without a key; requires a contact email. */ export declare const PUBLIC_FEEDBACK_URL = "https://cotal.ai/v1/feedback"; /** * How a connector instance presents itself on the mesh. Everything is read from * the environment so the *launcher* (the manager spawning an agent, or a human * running `cotal join` / their own terminal) decides identity once and both the * MCP server and the lifecycle hooks inherit it. */ export interface AgentConfig { space: string; /** Stable agent id (nkey public key) from the launcher; falls back to a random * uuid in the endpoint when absent (unmanaged sessions). */ id?: string; /** Minted creds content, or a source that re-reads a managed seat's file for standing renewal. */ creds?: string | (() => Promise); /** The incarnation's lifecycle UID (SPEC §13.1) from the launcher (`COTAL_LIFECYCLE_UID`): the * endpoint binds its lifecycle-keyed dm/dlv/chathist durables by it — the same exact names its * credential pins, so a mismatch fails at the broker, never silently. */ lifecycleUid?: string; /** The accepted-row token of a static credential's issuance (SPEC 13.15, `COTAL_ACCEPTED_TOKEN`): * the endpoint reads the issuer-bound generation under it and pins its caller rails. */ acceptedToken?: string; /** USER-MODE launch (a spawned agent on a user-auth mesh): the agent's owner+actor principal, * the sentinel creds content it presents alongside its bearers, and the argv it EXECS for a * fresh bearer (initial connect + every refresh — the exchange protocol stays behind that * command). All four env vars come from the spawner together; mutually exclusive with creds. */ userAuth?: { owner: string; actor: string; sentinelCreds: string; bearerCmd: string[]; }; name: string; role?: string; description?: string; tags?: string[]; /** Display-only metadata from unmodelled agent-file frontmatter keys (for example `theme`). * Connector-owned keys such as `connector` and `model` are overlaid later and cannot be spoofed here. */ meta?: Record; /** Control-plane capabilities this session declares (from the agent file's `capabilities:`); today * only `spawn`. Used to gate the manager-op tools (cotal_spawn / cotal_persona / cotal_personas) so the advertised * surface matches what the agent can actually invoke. The auth layer is the real boundary on any * AUTHED mesh ({@link isAuthed} — static creds or user-mode); open mode carries no identity plane, * so the gate is permissive there. Same file the manager minted creds from, so the tool gate * mirrors the wire grant exactly. */ capabilities?: string[]; servers: string; /** The *active* read set — channels this agent actually subscribes to (read). May include * wildcard subtrees (`team.>`). Maps to the endpoint's live filter. ⊆ {@link allowSubscribe}. */ subscribe: string[]; /** The read ACL — channels this agent *may* read (auth mode → broker-enforced). Defaults to * {@link subscribe}. Bounds runtime `cotal_join`. */ allowSubscribe: string[]; /** The post ACL — channels this agent may post to (auth mode → the minted publish ACL). * **Default-deny** (empty): publishing must be declared. Informational only here; the broker * enforces it under auth. */ allowPublish: string[]; /** Per-channel attention DEFAULTS (operator, one-way from the agent file): channels to receive but * never wake on ({@link quiet}) / to drop on receive ({@link muted}). Seeds {@link MeshAgent}'s * runtime map; the runtime never writes them back. Concrete channels within {@link allowSubscribe}. * Optional (absent ⇒ none), like the other discovery fields. */ quiet?: string[]; muted?: string[]; kind: EndpointKind; /** The host connector this session runs under (`claude` / `opencode` / `hermes`). Set by the * connector itself, never from user config — it rides the {@link AgentCard.meta}.connector on * the wire as display-only discovery metadata (which harness an agent uses). */ connector?: string; /** Model the host runs this agent on (e.g. `claude-opus-4`), from the agent file's `model:` or * `COTAL_MODEL`. Rides {@link AgentCard.meta}.model as display-only discovery metadata; omitted * when the operator didn't pin one (the harness default isn't knowable from here). */ model?: string; /** Connector-defined model variant (for example reasoning effort), from `variant:` or * `COTAL_VARIANT`. Display-only discovery metadata. */ variant?: string; token?: string; user?: string; pass?: string; tls: boolean; /** Optional beta-feedback key — routes feedback to the keyed intake at {@link FEEDBACK_URL}; * without it, feedback goes to the public {@link PUBLIC_FEEDBACK_URL}. */ feedbackKey?: string; /** Optional intake URL override (`COTAL_FEEDBACK_URL`) for self-hosted intakes. */ feedbackUrl?: string; /** Durable-consumer `ack_wait` in ms (how long an un-acked chat message waits before JetStream * redelivers). Threaded straight to the endpoint; defaults to its 60s when unset. INTERNAL/TEST-ONLY: * deliberately NOT parsed from env by `configFromEnv` — a test shortens it to observe redelivery / * ack-commit in seconds; normal launches should not tune durability from connector config. */ ackWaitMs?: number; } /** * Does this session's broker ENFORCE its grants? * * Named for what it means, not for the cases it happens to cover today, because the cases have * grown once already and the rename is the part that gets skipped. It mirrors `CotalEndpoint`'s own * private `authed` — "the gate every open-vs-auth branch keys on" — so connector-core and core * cannot drift on the question of what an authenticated session is; when a third identity plane * lands, this expression is the one place it has to be added. * * TWO PLANES TODAY, and they are mutually exclusive by construction: a launch carries static creds * OR a user-mode bearer, refused as a pair at parse (above), at launch (`materialEnv`) and at * connect (the endpoint). So `!config.creds` is NOT "open mode" — on a user-auth agent it is always * true, which is what made the advertised tool surface claim manager-op tools to every agent on a * user-auth mesh. * * `token` / `user` / `pass` are deliberately NOT here. Soft-shared NATS auth off a join link carries * no owner+actor grant and no per-agent publish ACL, so the broker gates nothing per agent for it; * core groups it with open mode for exactly that reason. Counting it as authenticated would hide * tools an agent can genuinely call, which is the same untruth in the other direction. */ export declare function isAuthed(config: Pick): boolean; /** * This session's local control endpoint: the socket PATH from the env (not a secret, and the * short-lived hook processes need it too) and the first-frame token out of the launch material, * which is where the token now rides instead of `COTAL_CONTROL_TOKEN`. * * NOTHING means nothing: neither half present, so this is a session with no control plane, which is * a normal launch. HALF A PAIR THROWS HERE, centrally, and that is the change worth explaining. * * Returning `undefined` for a half pair made every caller's own check the real contract, and the * callers do not agree: the in-agent server would refuse to serve, a hook would fall silent, and one * caller could simply forget, leaving a session that runs with a control plane it believes it * configured and does not have. That is a silent degradation wearing the shape of an optional * feature. Half a pair is not an absent control endpoint, it is a BROKEN one, and the difference * belongs where the pair is resolved rather than in five copies downstream. * * Callers that must survive anything still can, and do so visibly: the lifecycle hook relay wraps * this call in a try/catch because a hook that throws is a hook that blocked the session, and fail * open is that relay's whole documented contract. Every other caller wants exactly this throw. */ export declare function controlFromEnv(env?: NodeJS.ProcessEnv): { path: string; token: string; } | undefined; /** * Drop the reference to the launch material once this process has read it. * * Only correct where the caller is the process that RUNS THE SESSION'S TOOL CALLS and nothing starts * later that has to read the material again. That is pi and the codex host, whose sessions run in the * seat process, and the OpenCode plugin, which runs inside the `opencode serve` process the seat shim * starts (the server is also what executes the tool calls, so the shim keeping the reference costs * nothing). There the descendants that would otherwise inherit the reference are the session's own * tool calls, and after this they inherit nothing at all. It is NOT correct for the Claude connector, whose readers are short-lived child processes * (the MCP server, each lifecycle hook) that start after the session is already running and would * find the reference gone. */ export declare function scrubLaunchMaterial(env?: NodeJS.ProcessEnv): void; /** True iff the env carries a Cotal identity — i.e. this is a launcher-spawned * session, not an operator's plain `claude`. `COTAL_LINK` / `COTAL_AGENT_FILE` * count: setting either is itself the explicit opt-in. The connector stays * inert otherwise. */ export declare function hasIdentity(env?: NodeJS.ProcessEnv): boolean; /** Build an {@link AgentConfig} from `COTAL_*` environment variables. Two refs * fill many fields at once: `COTAL_LINK` (cotal://token@host/space) supplies the * *where* (server, auth, space); `COTAL_AGENT_FILE` (.cotal/agents/.md) * supplies the *who* (name, role, kind, channels, description, tags). * Individual `COTAL_*` vars override both. Identity is NOT silently defaulted * unless a link is present — guard with {@link hasIdentity} first. */ export declare function configFromEnv(env?: NodeJS.ProcessEnv): AgentConfig; /** Beta-feedback guidance folded into connector instructions. */ export declare function feedbackLine(config: AgentConfig): string; //# sourceMappingURL=config.d.ts.map