/** * Pre-wire validation helpers for `task.start { agent: InlineAgentSpec }` * (Pattern B). The wire types themselves live in `./specs.ts`; this * module carries the SDK-side intake guard plus a re-export of the * `InlineAgentSpec` symbol under the `AgentSpec` alias. * * **Why an SDK-side intake guard?** QAR's `validate_spec_payload` is the * single source of truth for spec rule_ids; the SDK never tries to * reimplement the full ruleset. But two classes of failure are worth * catching client-side without paying the round-trip: * * 1. **Forbidden keys.** `custom_code: { ... }` and unknown top-level * fields (`hooks`, `lifecycle`, anything not in the safe subset) * are deterministically rejected by `D10-R1` / `D10-R3` / `D10-R5`. * Catching them in TypeScript at intake means the consumer's stack * trace points at their call site; QAR's per-rule `path` is * preserved so the error message is identical to the wire envelope. * 2. **Discriminator + required-field hygiene.** Missing * `apiVersion` / `instructions` / `model` (the only required * fields) gets a typed reject before the wire write so consumers * don't see a `task.done(failed)` 200ms later for a typo they * could have caught at edit time. * * Per-rule semantic checks (catalog name resolution, skill compatibility, * spawnable agent registry lookups, etc.) stay server-side — they need * tenant context the SDK doesn't have. */ import type { InlineAgentSpec } from './specs.js'; /** * Pre-wire validation outcome — one entry per detected violation. Matches * the per-rule shape QAR emits via `agent_spec_rejected` envelopes so * consumers handling both paths can branch on the same `(rule_id, path, * message)` triple. */ export interface InlineAgentSpecValidationIssue { readonly rule_id: string; /** JSON Pointer (RFC 6901) into the spec — `""` for root. */ readonly path: string; readonly message: string; } /** * Walk an `unknown` value asserted to be an `InlineAgentSpec`, returning * the list of detected pre-wire violations. Empty list = pre-wire-clean * (still subject to the server's per-rule pass at `task.start` and the * pre-flight endpoint). * * Field-shape validation is intentionally shallow: we check the rules a * dumb JSON walker can verify (forbidden keys, missing required scalars, * `custom_code !== null`). Deeper composition rules (skill version * resolution, spawnable agent registry, tool-name collisions) need * tenant context and stay server-side under `validate_spec_payload`. */ export declare function collectInlineAgentSpecPreWireIssues(spec: unknown): readonly InlineAgentSpecValidationIssue[]; /** * Type-guard form of `collectInlineAgentSpecPreWireIssues`. Throws * `QodoInlineAgentValidationError` from `../client/errors.js` when any * pre-wire issue is detected. Caller is `TaskClient.start` — * `assertInlineAgentSpecPreWire(payload.agent)` runs before any wire * write so the consumer's stack trace points at the call site, not at a * `task.done(failed)` arriving over the wire. * * Lives in this module (not in the central `errors.ts`) because circular * imports are easier to avoid when the assertion sits next to the rule * walker that produces its message body. */ export declare function assertInlineAgentSpecPreWire(spec: unknown): asserts spec is InlineAgentSpec; /** * Fill in the wire-canonical `kind: 'AgentSpec'` discriminator when the * consumer's spec omits it. `InlineAgentSpec.kind` is optional in TypeScript * — required server-side, but the SDK is permissive at the type level so * consumers can write `{ apiVersion, instructions, model }` literally. * Both `task.start` dispatch and `specs.validate` need the discriminator * on the wire, so this normalizer runs at every wire boundary. * * Doesn't mutate the consumer's input object — returns the same reference if * `kind` is already set so the spread cost is paid only when needed. */ export declare function normalizeInlineAgentSpec(spec: InlineAgentSpec): InlineAgentSpec; /** * The inline `AgentSpec` symbol — exported here so consumers can * `import { AgentSpec }` for the wire shape, even though * `QarRegistryClient.AgentSpec` (the local-registry shape) owns the * unqualified `AgentSpec` export at the package index. Two layers, two * types — see `./specs.ts` header for the longer rationale. * * Marked deprecated only as a hint that direct use should prefer * `InlineAgentSpec` to keep the wire-vs-local distinction visible at the * call site; the alias itself isn't going anywhere. * * @see {@link InlineAgentSpec} */ export type AgentSpec = InlineAgentSpec; //# sourceMappingURL=agentSpec.d.ts.map