@agent-surface/core 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/explain.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { D as DiscoveryDecision, A as AgentRouteInfo, a as AgentConsumer, b as AgentSurfaceRegistry, S as SnapshotContext } from './registry-BSwS05Xq.js';
1
+ import { D as DiscoveryDecision, A as AgentRouteInfo, a as AgentConsumer, b as AgentSurfaceRegistry, S as SnapshotContext } from './registry-XD1QsGQ4.js';
2
+ export { m as matchesScope } from './registry-XD1QsGQ4.js';
2
3
 
3
4
  /**
4
5
  * `explainSurface()` — the developer projection.
@@ -24,7 +25,6 @@ import { D as DiscoveryDecision, A as AgentRouteInfo, a as AgentConsumer, b as A
24
25
  * CLIs only.
25
26
  */
26
27
 
27
- /** Which layer of the chain contributed a policy (docs/06 §composition). */
28
28
  type PolicyScope = "registry" | "component" | "capability";
29
29
  interface PolicyAttribution {
30
30
  /** `AgentPolicy.name` — built-ins are `authenticated`, `rate-limit`, … */
package/dist/explain.js CHANGED
@@ -118,6 +118,7 @@ function explainSurface(registry, ctx) {
118
118
  });
119
119
  }
120
120
  export {
121
- explainSurface
121
+ explainSurface,
122
+ matchesScope
122
123
  };
123
124
  //# sourceMappingURL=explain.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/explain.ts"],"sourcesContent":["/**\n * `explainSurface()` — the developer projection.\n *\n * `snapshot()` answers \"what may this agent call right now\". It bakes policy\n * *outcomes*: a `hide` decision deletes the capability outright, leaving no\n * trace of which policy did it. That is correct for the agent boundary — the\n * existence of a hidden capability is itself information (docs/06) — and it is\n * exactly wrong for the developer staring at a surface that is missing a\n * capability they know they registered.\n *\n * This module answers the other question: *why*. It reports every capability\n * the registry holds, including the ones the snapshot omits, each with the\n * policy chain that judged it and that chain's per-policy votes.\n *\n * ## This is never agent-facing\n *\n * It lives behind its own entry point (`@agent-surface/core/explain`) and is\n * deliberately absent from the package root, so no adapter can reach it by\n * importing `@agent-surface/core` (AS-EXPLAIN-004). Nothing here may be piped\n * into a toolset, a transport, or a model prompt: doing so re-leaks precisely\n * the existence that `hide` exists to withhold. Developer tools, tests, and\n * CLIs only.\n */\nimport type { AgentConsumer, AgentRouteInfo } from \"./types.js\";\nimport type { AgentSurfaceRegistry } from \"./registry.js\";\nimport type { DiscoveryDecision, AgentPolicy, AgentPolicyContext } from \"./policy.js\";\nimport { CONFIRMATION_ESCALATION, type AgentPolicyWithEscalation } from \"./policy.js\";\nimport {\n INTERNALS,\n buildPolicyContext,\n computeAvailability,\n type CapabilityRuntime,\n type InternalRegistration,\n type InternalsCarrier,\n type RegistryInternals,\n} from \"./internal.js\";\nimport { DEFAULT_CONSUMER, matchesScope, sortRegistrations, type SnapshotContext } from \"./snapshot.js\";\nimport { deepFreeze } from \"./utils.js\";\n\n/** Which layer of the chain contributed a policy (docs/06 §composition). */\nexport type PolicyScope = \"registry\" | \"component\" | \"capability\";\n\nexport interface PolicyAttribution {\n /** `AgentPolicy.name` — built-ins are `authenticated`, `rate-limit`, … */\n name: string;\n scope: PolicyScope;\n /** Which pipeline hooks this policy implements. */\n phases: Array<\"discovery\" | \"authorize\" | \"invoke\">;\n /** This policy's own vote. Absent when it has no `onDiscovery`. */\n discovery?: DiscoveryDecision;\n /**\n * `onDiscovery` threw. `evaluateDiscovery` fails closed, so the vote is\n * recorded as `hide` — but a throwing discovery policy is a defect, and the\n * snapshot alone cannot tell you it happened.\n */\n threw?: boolean;\n /** Carries the `requireConfirmation` escalation marker. */\n confirmationEscalation?: boolean;\n}\n\nexport interface CapabilityExplanation {\n capabilityId: string;\n kind: \"observation\" | \"action\" | \"procedure\";\n plane: \"view\" | \"domain\";\n /**\n * The manifest description. Carried here because a hidden capability has no\n * snapshot entry to read it from, and an id alone does not tell a developer\n * which of their capabilities went missing.\n */\n description: string;\n registrationId: string;\n component: { type: string; instanceId: string };\n /**\n * What `snapshot()` did with this capability for the same context:\n * `hide` means absent from the snapshot entirely.\n */\n outcome: \"expose\" | \"disable\" | \"hide\";\n /** The reason a non-exposed capability carries, matching the snapshot's. */\n reason?: string;\n /** The full chain, registry-outermost first — the order policies run in. */\n policies: PolicyAttribution[];\n /**\n * The `when()`/override verdict on its own. Authority hides, state discloses\n * (D11/D12): keeping these apart is what lets you tell \"a policy removed it\"\n * from \"the UI says not right now\".\n */\n availability: { available: boolean; reason?: string };\n}\n\nexport interface SurfaceExplanation {\n surfaceId: string;\n surfaceVersion: string;\n capturedAt: string; // ISO-8601\n route?: AgentRouteInfo;\n /** The consumer this explanation was computed for. */\n consumer: AgentConsumer;\n /** Every capability held by the registry, hidden ones included. */\n capabilities: CapabilityExplanation[];\n}\n\nfunction phasesOf(policy: AgentPolicy): Array<\"discovery\" | \"authorize\" | \"invoke\"> {\n const phases: Array<\"discovery\" | \"authorize\" | \"invoke\"> = [];\n if (policy.onDiscovery) phases.push(\"discovery\");\n if (policy.onAuthorize) phases.push(\"authorize\");\n if (policy.onInvoke) phases.push(\"invoke\");\n return phases;\n}\n\n/**\n * Per-policy attribution plus the composed decision.\n *\n * `evaluateDiscovery` short-circuits on the first `hide`, so it cannot be\n * reused here — we need every vote, not the verdict. The composition below is\n * a faithful restatement of it (first `hide` wins; otherwise the *first*\n * `disable` is kept; otherwise `expose`), and AS-EXPLAIN-003 pins the two\n * together against a real snapshot. Re-running `onDiscovery` is safe by\n * contract: it MUST be synchronous, cheap, and side-effect free (docs/06).\n */\nfunction attribute(\n chain: AgentPolicy[],\n boundaries: { registry: number; component: number },\n ctx: AgentPolicyContext,\n): { policies: PolicyAttribution[]; decision: DiscoveryDecision } {\n const policies: PolicyAttribution[] = [];\n let hidden = false;\n let disable: { decision: \"disable\"; reason: string } | undefined;\n\n chain.forEach((policy, index) => {\n const scope: PolicyScope =\n index < boundaries.registry\n ? \"registry\"\n : index < boundaries.registry + boundaries.component\n ? \"component\"\n : \"capability\";\n\n const attribution: PolicyAttribution = {\n name: policy.name,\n scope,\n phases: phasesOf(policy),\n };\n if ((policy as AgentPolicyWithEscalation)[CONFIRMATION_ESCALATION]) {\n attribution.confirmationEscalation = true;\n }\n\n if (policy.onDiscovery) {\n let decision: DiscoveryDecision;\n try {\n decision = policy.onDiscovery(ctx);\n } catch {\n decision = { decision: \"hide\" }; // fail closed, exactly as evaluateDiscovery does\n attribution.threw = true;\n }\n attribution.discovery = decision;\n if (decision.decision === \"hide\") hidden = true;\n else if (decision.decision === \"disable\" && !disable) disable = decision;\n }\n\n policies.push(attribution);\n });\n\n return {\n policies,\n decision: hidden ? { decision: \"hide\" } : (disable ?? { decision: \"expose\" }),\n };\n}\n\nfunction explainCapability(\n internals: RegistryInternals,\n reg: InternalRegistration,\n cap: CapabilityRuntime,\n consumer: AgentConsumer,\n host: Record<string, unknown>,\n): CapabilityExplanation {\n const chain = [...internals.registryPolicies, ...reg.componentPolicies, ...cap.policies];\n const ctx = buildPolicyContext(internals, reg, cap, consumer, host);\n const { policies, decision } = attribute(\n chain,\n { registry: internals.registryPolicies.length, component: reg.componentPolicies.length },\n ctx,\n );\n const availability = computeAvailability(internals, reg, cap);\n\n // Mirrors createSnapshot exactly: a policy `disable` reason wins over the\n // availability reason, and availability only matters once discovery exposed.\n const available = availability.available && decision.decision === \"expose\";\n const reason = decision.decision === \"disable\" ? decision.reason : availability.reason;\n const outcome: CapabilityExplanation[\"outcome\"] =\n decision.decision === \"hide\" ? \"hide\" : available ? \"expose\" : \"disable\";\n\n return {\n capabilityId: cap.capabilityId,\n kind: cap.kind,\n plane: cap.kind === \"procedure\" ? \"domain\" : \"view\",\n description: cap.kind === \"procedure\" ? cap.baseDescription : cap.description,\n registrationId: reg.id,\n component: { type: reg.type, instanceId: reg.instanceId },\n outcome,\n ...(outcome === \"expose\" ? {} : reason !== undefined ? { reason } : {}),\n policies,\n availability: {\n available: availability.available,\n ...(availability.reason !== undefined ? { reason: availability.reason } : {}),\n },\n };\n}\n\n/**\n * Developer projection of the surface: every capability, hidden included, with\n * the policy chain that judged it.\n *\n * Honours `ctx.scope` and `ctx.consumer` so it lines up with the snapshot you\n * are debugging. `includeUnavailable` and `budget` are ignored by design —\n * withholding from an explanation is the one thing it must never do.\n *\n * @throws if `registry` was not produced by `createAgentSurfaceRegistry`, or\n * has been disposed.\n */\nexport function explainSurface(\n registry: AgentSurfaceRegistry,\n ctx?: SnapshotContext,\n): SurfaceExplanation {\n const internals = (registry as unknown as InternalsCarrier)[INTERNALS];\n if (!internals) {\n throw new Error(\n \"explainSurface() requires a registry created by createAgentSurfaceRegistry()\",\n );\n }\n if (internals.disposed) throw new Error(\"explainSurface() called on a disposed registry\");\n\n const consumer = ctx?.consumer ?? DEFAULT_CONSUMER;\n const host = internals.host();\n const regs = sortRegistrations(\n [...internals.registrations.values()].filter((r) => r.status === \"active\"),\n );\n\n const capabilities: CapabilityExplanation[] = [];\n for (const reg of regs) {\n if (!reg.procedureOnly && matchesScope(reg.type, ctx?.scope)) {\n for (const obs of reg.observations.values()) {\n capabilities.push(explainCapability(internals, reg, obs, consumer, host));\n }\n for (const act of reg.actions.values()) {\n capabilities.push(explainCapability(internals, reg, act, consumer, host));\n }\n }\n for (const proc of reg.procedures) {\n const inScope = proc.contextLink\n ? matchesScope(proc.contextLink.type, ctx?.scope)\n : matchesScope(proc.path, ctx?.scope);\n if (!inScope) continue;\n capabilities.push(explainCapability(internals, reg, proc, consumer, host));\n }\n }\n\n const route = internals.routeFn?.();\n return deepFreeze({\n surfaceId: internals.surfaceId,\n surfaceVersion: String(internals.version),\n capturedAt: new Date(internals.now()).toISOString(),\n ...(route ? { route } : {}),\n consumer,\n capabilities,\n });\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/explain.ts"],"sourcesContent":["/**\n * `explainSurface()` — the developer projection.\n *\n * `snapshot()` answers \"what may this agent call right now\". It bakes policy\n * *outcomes*: a `hide` decision deletes the capability outright, leaving no\n * trace of which policy did it. That is correct for the agent boundary — the\n * existence of a hidden capability is itself information (docs/06) — and it is\n * exactly wrong for the developer staring at a surface that is missing a\n * capability they know they registered.\n *\n * This module answers the other question: *why*. It reports every capability\n * the registry holds, including the ones the snapshot omits, each with the\n * policy chain that judged it and that chain's per-policy votes.\n *\n * ## This is never agent-facing\n *\n * It lives behind its own entry point (`@agent-surface/core/explain`) and is\n * deliberately absent from the package root, so no adapter can reach it by\n * importing `@agent-surface/core` (AS-EXPLAIN-004). Nothing here may be piped\n * into a toolset, a transport, or a model prompt: doing so re-leaks precisely\n * the existence that `hide` exists to withhold. Developer tools, tests, and\n * CLIs only.\n */\nimport type { AgentConsumer, AgentRouteInfo } from \"./types.js\";\nimport type { AgentSurfaceRegistry } from \"./registry.js\";\nimport type { DiscoveryDecision, AgentPolicy, AgentPolicyContext } from \"./policy.js\";\nimport { CONFIRMATION_ESCALATION, type AgentPolicyWithEscalation } from \"./policy.js\";\nimport {\n INTERNALS,\n buildPolicyContext,\n computeAvailability,\n type CapabilityRuntime,\n type InternalRegistration,\n type InternalsCarrier,\n type RegistryInternals,\n} from \"./internal.js\";\nimport { DEFAULT_CONSUMER, matchesScope, sortRegistrations, type SnapshotContext } from \"./snapshot.js\";\nimport { deepFreeze } from \"./utils.js\";\n\n/** Which layer of the chain contributed a policy (docs/06 §composition). */\n/**\n * Re-exported for developer tooling that has to line a *static* view of the\n * codebase up with a scoped projection — `@agent-surface/cli`'s coverage join,\n * where an authored capability outside the active scope must not be reported as\n * one no scenario reaches. A second copy of this predicate would drift, and the\n * drift would present as a false finding.\n *\n * It lives on this subpath rather than the package root for the reason\n * `AS-EXPLAIN-004` gives: the root is the agent-facing API, and this is not\n * part of the agent contract.\n */\nexport { matchesScope } from \"./snapshot.js\";\n\nexport type PolicyScope = \"registry\" | \"component\" | \"capability\";\n\nexport interface PolicyAttribution {\n /** `AgentPolicy.name` — built-ins are `authenticated`, `rate-limit`, … */\n name: string;\n scope: PolicyScope;\n /** Which pipeline hooks this policy implements. */\n phases: Array<\"discovery\" | \"authorize\" | \"invoke\">;\n /** This policy's own vote. Absent when it has no `onDiscovery`. */\n discovery?: DiscoveryDecision;\n /**\n * `onDiscovery` threw. `evaluateDiscovery` fails closed, so the vote is\n * recorded as `hide` — but a throwing discovery policy is a defect, and the\n * snapshot alone cannot tell you it happened.\n */\n threw?: boolean;\n /** Carries the `requireConfirmation` escalation marker. */\n confirmationEscalation?: boolean;\n}\n\nexport interface CapabilityExplanation {\n capabilityId: string;\n kind: \"observation\" | \"action\" | \"procedure\";\n plane: \"view\" | \"domain\";\n /**\n * The manifest description. Carried here because a hidden capability has no\n * snapshot entry to read it from, and an id alone does not tell a developer\n * which of their capabilities went missing.\n */\n description: string;\n registrationId: string;\n component: { type: string; instanceId: string };\n /**\n * What `snapshot()` did with this capability for the same context:\n * `hide` means absent from the snapshot entirely.\n */\n outcome: \"expose\" | \"disable\" | \"hide\";\n /** The reason a non-exposed capability carries, matching the snapshot's. */\n reason?: string;\n /** The full chain, registry-outermost first — the order policies run in. */\n policies: PolicyAttribution[];\n /**\n * The `when()`/override verdict on its own. Authority hides, state discloses\n * (D11/D12): keeping these apart is what lets you tell \"a policy removed it\"\n * from \"the UI says not right now\".\n */\n availability: { available: boolean; reason?: string };\n}\n\nexport interface SurfaceExplanation {\n surfaceId: string;\n surfaceVersion: string;\n capturedAt: string; // ISO-8601\n route?: AgentRouteInfo;\n /** The consumer this explanation was computed for. */\n consumer: AgentConsumer;\n /** Every capability held by the registry, hidden ones included. */\n capabilities: CapabilityExplanation[];\n}\n\nfunction phasesOf(policy: AgentPolicy): Array<\"discovery\" | \"authorize\" | \"invoke\"> {\n const phases: Array<\"discovery\" | \"authorize\" | \"invoke\"> = [];\n if (policy.onDiscovery) phases.push(\"discovery\");\n if (policy.onAuthorize) phases.push(\"authorize\");\n if (policy.onInvoke) phases.push(\"invoke\");\n return phases;\n}\n\n/**\n * Per-policy attribution plus the composed decision.\n *\n * `evaluateDiscovery` short-circuits on the first `hide`, so it cannot be\n * reused here — we need every vote, not the verdict. The composition below is\n * a faithful restatement of it (first `hide` wins; otherwise the *first*\n * `disable` is kept; otherwise `expose`), and AS-EXPLAIN-003 pins the two\n * together against a real snapshot. Re-running `onDiscovery` is safe by\n * contract: it MUST be synchronous, cheap, and side-effect free (docs/06).\n */\nfunction attribute(\n chain: AgentPolicy[],\n boundaries: { registry: number; component: number },\n ctx: AgentPolicyContext,\n): { policies: PolicyAttribution[]; decision: DiscoveryDecision } {\n const policies: PolicyAttribution[] = [];\n let hidden = false;\n let disable: { decision: \"disable\"; reason: string } | undefined;\n\n chain.forEach((policy, index) => {\n const scope: PolicyScope =\n index < boundaries.registry\n ? \"registry\"\n : index < boundaries.registry + boundaries.component\n ? \"component\"\n : \"capability\";\n\n const attribution: PolicyAttribution = {\n name: policy.name,\n scope,\n phases: phasesOf(policy),\n };\n if ((policy as AgentPolicyWithEscalation)[CONFIRMATION_ESCALATION]) {\n attribution.confirmationEscalation = true;\n }\n\n if (policy.onDiscovery) {\n let decision: DiscoveryDecision;\n try {\n decision = policy.onDiscovery(ctx);\n } catch {\n decision = { decision: \"hide\" }; // fail closed, exactly as evaluateDiscovery does\n attribution.threw = true;\n }\n attribution.discovery = decision;\n if (decision.decision === \"hide\") hidden = true;\n else if (decision.decision === \"disable\" && !disable) disable = decision;\n }\n\n policies.push(attribution);\n });\n\n return {\n policies,\n decision: hidden ? { decision: \"hide\" } : (disable ?? { decision: \"expose\" }),\n };\n}\n\nfunction explainCapability(\n internals: RegistryInternals,\n reg: InternalRegistration,\n cap: CapabilityRuntime,\n consumer: AgentConsumer,\n host: Record<string, unknown>,\n): CapabilityExplanation {\n const chain = [...internals.registryPolicies, ...reg.componentPolicies, ...cap.policies];\n const ctx = buildPolicyContext(internals, reg, cap, consumer, host);\n const { policies, decision } = attribute(\n chain,\n { registry: internals.registryPolicies.length, component: reg.componentPolicies.length },\n ctx,\n );\n const availability = computeAvailability(internals, reg, cap);\n\n // Mirrors createSnapshot exactly: a policy `disable` reason wins over the\n // availability reason, and availability only matters once discovery exposed.\n const available = availability.available && decision.decision === \"expose\";\n const reason = decision.decision === \"disable\" ? decision.reason : availability.reason;\n const outcome: CapabilityExplanation[\"outcome\"] =\n decision.decision === \"hide\" ? \"hide\" : available ? \"expose\" : \"disable\";\n\n return {\n capabilityId: cap.capabilityId,\n kind: cap.kind,\n plane: cap.kind === \"procedure\" ? \"domain\" : \"view\",\n description: cap.kind === \"procedure\" ? cap.baseDescription : cap.description,\n registrationId: reg.id,\n component: { type: reg.type, instanceId: reg.instanceId },\n outcome,\n ...(outcome === \"expose\" ? {} : reason !== undefined ? { reason } : {}),\n policies,\n availability: {\n available: availability.available,\n ...(availability.reason !== undefined ? { reason: availability.reason } : {}),\n },\n };\n}\n\n/**\n * Developer projection of the surface: every capability, hidden included, with\n * the policy chain that judged it.\n *\n * Honours `ctx.scope` and `ctx.consumer` so it lines up with the snapshot you\n * are debugging. `includeUnavailable` and `budget` are ignored by design —\n * withholding from an explanation is the one thing it must never do.\n *\n * @throws if `registry` was not produced by `createAgentSurfaceRegistry`, or\n * has been disposed.\n */\nexport function explainSurface(\n registry: AgentSurfaceRegistry,\n ctx?: SnapshotContext,\n): SurfaceExplanation {\n const internals = (registry as unknown as InternalsCarrier)[INTERNALS];\n if (!internals) {\n throw new Error(\n \"explainSurface() requires a registry created by createAgentSurfaceRegistry()\",\n );\n }\n if (internals.disposed) throw new Error(\"explainSurface() called on a disposed registry\");\n\n const consumer = ctx?.consumer ?? DEFAULT_CONSUMER;\n const host = internals.host();\n const regs = sortRegistrations(\n [...internals.registrations.values()].filter((r) => r.status === \"active\"),\n );\n\n const capabilities: CapabilityExplanation[] = [];\n for (const reg of regs) {\n if (!reg.procedureOnly && matchesScope(reg.type, ctx?.scope)) {\n for (const obs of reg.observations.values()) {\n capabilities.push(explainCapability(internals, reg, obs, consumer, host));\n }\n for (const act of reg.actions.values()) {\n capabilities.push(explainCapability(internals, reg, act, consumer, host));\n }\n }\n for (const proc of reg.procedures) {\n const inScope = proc.contextLink\n ? matchesScope(proc.contextLink.type, ctx?.scope)\n : matchesScope(proc.path, ctx?.scope);\n if (!inScope) continue;\n capabilities.push(explainCapability(internals, reg, proc, consumer, host));\n }\n }\n\n const route = internals.routeFn?.();\n return deepFreeze({\n surfaceId: internals.surfaceId,\n surfaceVersion: String(internals.version),\n capturedAt: new Date(internals.now()).toISOString(),\n ...(route ? { route } : {}),\n consumer,\n capabilities,\n });\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { J as JsonSchema, c as JsonValue, d as AgentInvocationResult, U as Unsubscribe, a as AgentConsumer, b as AgentSurfaceRegistry } from './registry-BSwS05Xq.js';
2
- export { e as AGENT_CAPABILITY_ERROR_CODES, f as AgentActionContext, g as AgentActionDefinition, h as AgentActionDescriptor, i as AgentAuthorizationContext, j as AgentCapabilityDescriptorUnion, k as AgentCapabilityErrorCode, l as AgentCapabilityErrorPayload, m as AgentComponentDefinition, n as AgentComponentDescriptor, o as AgentConcurrency, p as AgentEffect, q as AgentEnvironment, r as AgentErrorRetry, s as AgentInvocation, t as AgentInvocationPolicyContext, u as AgentObservationDefinition, v as AgentObservationDescriptor, w as AgentPolicy, x as AgentPolicyContext, y as AgentProcedureBinding, z as AgentProcedureBindingRuntimeConfig, B as AgentProcedureDescriptor, C as AgentProcedureEffect, E as AgentProcedureExecutor, F as AgentProcedureRefDescriptor, G as AgentReadContext, H as AgentRegistrationHandle, A as AgentRouteInfo, I as AgentSchema, K as AgentSchemaError, L as AgentSchemaIssue, M as AgentSurfaceDefinitionError, N as AgentSurfaceDefinitionErrorCode, O as AgentSurfaceError, P as AgentSurfaceEvent, Q as AgentSurfaceLimits, R as AgentSurfaceSnapshot, T as AuditEvent, V as AuditSink, W as CONFIRMATION_ESCALATION, X as ConfirmationController, Y as ConfirmationEscalation, Z as DEFAULT_LIMITS, D as DiscoveryDecision, _ as InvokeOptions, $ as PendingConfirmation, a0 as PreconditionFailure, a1 as ProcedureCallInfo, a2 as RegistrationCandidate, a3 as RegistryOptions, S as SnapshotContext, a4 as StandardSchemaV1, a5 as action, a6 as audit, a7 as authenticated, a8 as composeInvokeChain, a9 as consoleAuditSink, aa as createAgentSurfaceRegistry, ab as defineAgentComponent, ac as emptyObjectSchema, ad as environment, ae as evaluateDiscovery, af as fromJsonSchema, ag as fromStandardSchema, ah as hasPermission, ai as isAgentSurfaceError, aj as memoryAuditSink, ak as observation, al as rateLimit, am as requireConfirmation, an as tenantBoundary, ao as validateComponentDefinition, ap as validateJsonSchemaDocument, aq as validateValueAgainstSchema } from './registry-BSwS05Xq.js';
1
+ import { J as JsonSchema, c as JsonValue, d as AgentInvocationResult, U as Unsubscribe, a as AgentConsumer, b as AgentSurfaceRegistry } from './registry-XD1QsGQ4.js';
2
+ export { e as AGENT_CAPABILITY_ERROR_CODES, f as AgentActionContext, g as AgentActionDefinition, h as AgentActionDescriptor, i as AgentAuthorizationContext, j as AgentCapabilityDescriptorUnion, k as AgentCapabilityErrorCode, l as AgentCapabilityErrorPayload, n as AgentComponentDefinition, o as AgentComponentDescriptor, p as AgentConcurrency, q as AgentEffect, r as AgentEnvironment, s as AgentErrorRetry, t as AgentInvocation, u as AgentInvocationPolicyContext, v as AgentObservationDefinition, w as AgentObservationDescriptor, x as AgentPolicy, y as AgentPolicyContext, z as AgentProcedureBinding, B as AgentProcedureBindingRuntimeConfig, C as AgentProcedureDescriptor, E as AgentProcedureEffect, F as AgentProcedureExecutor, G as AgentProcedureRefDescriptor, H as AgentReadContext, I as AgentRegistrationHandle, A as AgentRouteInfo, K as AgentSchema, L as AgentSchemaError, M as AgentSchemaIssue, N as AgentSurfaceDefinitionError, O as AgentSurfaceDefinitionErrorCode, P as AgentSurfaceError, Q as AgentSurfaceEvent, R as AgentSurfaceLimits, T as AgentSurfaceSnapshot, V as AuditEvent, W as AuditSink, X as CONFIRMATION_ESCALATION, Y as ConfirmationController, Z as ConfirmationEscalation, _ as DEFAULT_LIMITS, D as DiscoveryDecision, $ as InvokeOptions, a0 as PendingConfirmation, a1 as PreconditionFailure, a2 as ProcedureCallInfo, a3 as RegistrationCandidate, a4 as RegistryOptions, S as SnapshotContext, a5 as StandardSchemaV1, a6 as action, a7 as audit, a8 as authenticated, a9 as composeInvokeChain, aa as consoleAuditSink, ab as createAgentSurfaceRegistry, ac as defineAgentComponent, ad as emptyObjectSchema, ae as environment, af as evaluateDiscovery, ag as fromJsonSchema, ah as fromStandardSchema, ai as hasPermission, aj as isAgentSurfaceError, ak as memoryAuditSink, al as observation, am as rateLimit, an as requireConfirmation, ao as tenantBoundary, ap as validateComponentDefinition, aq as validateJsonSchemaDocument, ar as validateValueAgainstSchema } from './registry-XD1QsGQ4.js';
3
3
 
4
4
  /**
5
5
  * Canonical ID grammar (docs/01 §identity):
@@ -717,6 +717,7 @@ interface AgentProcedureDescriptor {
717
717
  meta?: Record<string, JsonValue>;
718
718
  }
719
719
  type AgentCapabilityDescriptorUnion = AgentObservationDescriptor | AgentActionDescriptor | AgentProcedureDescriptor;
720
+ declare function matchesScope(type: string, scope: string[] | undefined): boolean;
720
721
 
721
722
  interface RegistrationCandidate {
722
723
  definition: AgentComponentDefinition;
@@ -773,4 +774,4 @@ interface AgentSurfaceRegistry {
773
774
  }
774
775
  declare function createAgentSurfaceRegistry(options?: RegistryOptions): AgentSurfaceRegistry;
775
776
 
776
- export { type PendingConfirmation as $, type AgentRouteInfo as A, type AgentProcedureDescriptor as B, type AgentProcedureEffect as C, type DiscoveryDecision as D, type AgentProcedureExecutor as E, type AgentProcedureRefDescriptor as F, type AgentReadContext as G, type AgentRegistrationHandle as H, type AgentSchema as I, type JsonSchema as J, AgentSchemaError as K, type AgentSchemaIssue as L, AgentSurfaceDefinitionError as M, type AgentSurfaceDefinitionErrorCode as N, AgentSurfaceError as O, type AgentSurfaceEvent as P, type AgentSurfaceLimits as Q, type AgentSurfaceSnapshot as R, type SnapshotContext as S, type AuditEvent as T, type Unsubscribe as U, type AuditSink as V, CONFIRMATION_ESCALATION as W, type ConfirmationController as X, type ConfirmationEscalation as Y, DEFAULT_LIMITS as Z, type InvokeOptions as _, type AgentConsumer as a, type PreconditionFailure as a0, type ProcedureCallInfo as a1, type RegistrationCandidate as a2, type RegistryOptions as a3, type StandardSchemaV1 as a4, action as a5, audit as a6, authenticated as a7, composeInvokeChain as a8, consoleAuditSink as a9, createAgentSurfaceRegistry as aa, defineAgentComponent as ab, emptyObjectSchema as ac, environment as ad, evaluateDiscovery as ae, fromJsonSchema as af, fromStandardSchema as ag, hasPermission as ah, isAgentSurfaceError as ai, memoryAuditSink as aj, observation as ak, rateLimit as al, requireConfirmation as am, tenantBoundary as an, validateComponentDefinition as ao, validateJsonSchemaDocument as ap, validateValueAgainstSchema as aq, type AgentSurfaceRegistry as b, type JsonValue as c, type AgentInvocationResult as d, AGENT_CAPABILITY_ERROR_CODES as e, type AgentActionContext as f, type AgentActionDefinition as g, type AgentActionDescriptor as h, type AgentAuthorizationContext as i, type AgentCapabilityDescriptorUnion as j, type AgentCapabilityErrorCode as k, type AgentCapabilityErrorPayload as l, type AgentComponentDefinition as m, type AgentComponentDescriptor as n, type AgentConcurrency as o, type AgentEffect as p, type AgentEnvironment as q, type AgentErrorRetry as r, type AgentInvocation as s, type AgentInvocationPolicyContext as t, type AgentObservationDefinition as u, type AgentObservationDescriptor as v, type AgentPolicy as w, type AgentPolicyContext as x, type AgentProcedureBinding as y, type AgentProcedureBindingRuntimeConfig as z };
777
+ export { type InvokeOptions as $, type AgentRouteInfo as A, type AgentProcedureBindingRuntimeConfig as B, type AgentProcedureDescriptor as C, type DiscoveryDecision as D, type AgentProcedureEffect as E, type AgentProcedureExecutor as F, type AgentProcedureRefDescriptor as G, type AgentReadContext as H, type AgentRegistrationHandle as I, type JsonSchema as J, type AgentSchema as K, AgentSchemaError as L, type AgentSchemaIssue as M, AgentSurfaceDefinitionError as N, type AgentSurfaceDefinitionErrorCode as O, AgentSurfaceError as P, type AgentSurfaceEvent as Q, type AgentSurfaceLimits as R, type SnapshotContext as S, type AgentSurfaceSnapshot as T, type Unsubscribe as U, type AuditEvent as V, type AuditSink as W, CONFIRMATION_ESCALATION as X, type ConfirmationController as Y, type ConfirmationEscalation as Z, DEFAULT_LIMITS as _, type AgentConsumer as a, type PendingConfirmation as a0, type PreconditionFailure as a1, type ProcedureCallInfo as a2, type RegistrationCandidate as a3, type RegistryOptions as a4, type StandardSchemaV1 as a5, action as a6, audit as a7, authenticated as a8, composeInvokeChain as a9, consoleAuditSink as aa, createAgentSurfaceRegistry as ab, defineAgentComponent as ac, emptyObjectSchema as ad, environment as ae, evaluateDiscovery as af, fromJsonSchema as ag, fromStandardSchema as ah, hasPermission as ai, isAgentSurfaceError as aj, memoryAuditSink as ak, observation as al, rateLimit as am, requireConfirmation as an, tenantBoundary as ao, validateComponentDefinition as ap, validateJsonSchemaDocument as aq, validateValueAgainstSchema as ar, type AgentSurfaceRegistry as b, type JsonValue as c, type AgentInvocationResult as d, AGENT_CAPABILITY_ERROR_CODES as e, type AgentActionContext as f, type AgentActionDefinition as g, type AgentActionDescriptor as h, type AgentAuthorizationContext as i, type AgentCapabilityDescriptorUnion as j, type AgentCapabilityErrorCode as k, type AgentCapabilityErrorPayload as l, matchesScope as m, type AgentComponentDefinition as n, type AgentComponentDescriptor as o, type AgentConcurrency as p, type AgentEffect as q, type AgentEnvironment as r, type AgentErrorRetry as s, type AgentInvocation as t, type AgentInvocationPolicyContext as u, type AgentObservationDefinition as v, type AgentObservationDescriptor as w, type AgentPolicy as x, type AgentPolicyContext as y, type AgentProcedureBinding as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-surface/core",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Framework-agnostic registry, types, policies, errors, snapshot, invocation for frontend agent surfaces",
5
5
  "license": "MIT",
6
6
  "type": "module",