SDK surface
@meridian/shared (libs/shared/package.json) is the one package a plugin compiles
against. It is browser-safe: no filesystem access, no host internals, no dependency on
apps/api. A plugin's runtime code imports it as import type wherever possible, so the
import is erased at compile/bundle time — see
Bundling and distribution.
This page is the exhaustive map of what the package exports, file by file. It does not explain how to author a manifest, a behavior, or a workflow — see Plugin manifest, Autonomy and packaging, and the how-to guides linked from each section below.
Package identity
| Name | @meridian/shared |
| Version | 0.6.0 (libs/shared/package.json) |
| Runtime dependencies | @opentelemetry/api, croner, zod |
exports (dev) |
"./*": "./src/*.ts" — every subpath resolves 1:1 to a .ts source file |
exports (publishConfig, published) |
"./*": { "types": "./dist/*.d.ts", "default": "./dist/*.js" } |
| Build | npm run build → tsc -p tsconfig.build.json (declaration, declarationMap, sourceMap, outDir: dist, rootDir: src) |
Two resolution paths coexist:
- The repository's plugins (
external-plugins/<name>/) resolve@meridian/shared/*via the path alias"@meridian/shared/*": ["../libs/shared/src/*"](external-plugins/tsconfig.json) — straight to source, no build step. - Out-of-repo plugins resolve the published npm package, whose
exportsonly take effect throughpublishConfig— a fieldpnpm publish/pnpm packapply andnpmignores. See Bundling and distribution.
PLUGIN_CONTRACT_VERSION (below) is a hand-maintained constant that is decoupled
from the @meridian/shared package version: it is bumped only on a real break of the
plugin-facing surface, not on every library release.
Directory layout
libs/shared/src/
version.ts PLUGIN_CONTRACT_VERSION
plugin/ the plugin-authoring contract
behavior.ts
source.ts
mapping.ts
manifest.ts
instance.ts
i18n.ts
domain/ shared platform vocabulary
types.ts
object-types.ts
value-sets.ts
dimensions.ts
context-kinds.ts
validation.ts
terminology.ts
agent-spec.ts
agent-tools.ts
ports.ts
workflow-spec.ts
engine/ type-system & catalog helpers
type-system.ts
conversions.ts
catalog-metadata.ts
dynamic-ports.ts
agent-tool-eligibility.ts
schedule.ts
observability/
trace.ts
Every file above is a real, committed source file (git ls-files libs/shared/src); there
is no generated or build-manifest step involved in producing this list.
plugin/* — the plugin-authoring contract
| Import | Exports | Purpose |
|---|---|---|
@meridian/shared/plugin/behavior |
NodeBehavior<I,O,C>, RunArgs<I,C>, Proposal<O>, NodeBehaviorFactory<I,O>, PluginNodeContext, ValidationResolution, PortSandboxFactory |
The node behavior contract — what a behavior.module (and a portSandboxes module) exports. Full contract at Behavior contract. |
@meridian/shared/plugin/source |
SourceFactory, SourceFactoryOpts, SourceFeed, SourceHandle |
The event-source mechanism contract (polling, sockets…) — see Contribute an event source and binding. |
@meridian/shared/plugin/mapping |
MapExprSchema (zod), MapExpr |
Raw-record → event field projection grammar, used by eventBindings.map. Full grammar at MapExpr. |
@meridian/shared/plugin/manifest |
TypeRefSchema, PluginManifest (zod schema + type), NodeContribution, TypeContribution, ConversionContribution, AgentContribution, AdapterContribution, ContextKindContribution, PortSandboxContribution, EventSourceContribution, EventBindingContribution |
The plugin.yaml schema. Full field reference at Plugin manifest. |
@meridian/shared/plugin/instance |
InstanceManifest (zod schema + type), PortBinding, PluginRequirement, EMPTY_INSTANCE |
The instance manifest schema (deployment configuration, not a plugin contribution). Full field reference at Instance manifest. |
@meridian/shared/plugin/i18n |
I18nEntry, I18nBundle, PluginBundles, manifestI18nEntries(), bundleLookup(), interpolate(), resolveRuntimeKey(), localizeManifest() |
The key-derivation walker shared by the host (resolution) and the CLI (i18n extract/i18n check) — see Translate a plugin. |
domain/* — shared platform vocabulary
| Import | Exports | Purpose |
|---|---|---|
@meridian/shared/domain/types |
PrimitiveName, TypeRef (union), t (TypeRef builder helpers), typeLabel(), ContextKey, ContextEnvelope |
The TypeRef vocabulary every port type is expressed in. Full kind-by-kind reference at TypeRef. |
@meridian/shared/domain/object-types |
FieldDescriptor, TypeDescriptor, ObjectTypeName, OBJECT_TYPES, registerType(), getType(), isObjectType() |
The open registry of object-kind types ({ kind: "object", name }). Starts empty — the core contributes no domain type; plugins populate it via registerType. |
@meridian/shared/domain/value-sets |
ValueSetConcept, ValueSetDef, VALUE_SETS, registerValueSet(), hasValueSet(), isExternalValueSet(), valueSetConcepts(), codeInValueSet(), displayOfCode(), subsumes() |
The open registry backing coded types. Starts empty; external: true value-sets are not enumerated here (resolved by a terminology port instead). |
@meridian/shared/domain/dimensions |
Dimension (union of 11 built-in dimensions), UnitDef, DimensionDef, DIMENSIONS, registerDimension(), dimensionOfUnit(), unitInDimension(), convertUnit() |
The open registry backing quantity types (UCUM-style unit checking + conversion). Seeded with dimensionless, fraction, mass, volume, time, amount-of-substance, mass-concentration, molar-concentration, filtration-rate, pressure, temperature. |
@meridian/shared/domain/context-kinds |
ContextKindDescriptor, CONTEXT_KINDS, registerContextKind(), getContextKind(), isContextKind(), contextIdField(), listContextKinds(), contextKindForEntity() |
The open registry of ambient-context kinds (context:/establishes: keys, ref entities, subject id fields). Starts empty — the core knows no kind; plugins contribute them via contributes.contextKinds (@posos/common contributes patient/encounter/order/document). |
@meridian/shared/domain/validation |
PendingValidationRecord |
The platform human-in-the-loop concept: the request published to a subject's record when a run suspends (runId/pendingId correlate and resume the run). |
@meridian/shared/domain/terminology |
TerminologyPort (interface), InternalTerminology, FhirTerminologyServer, RoutingTerminology, defaultTerminology() |
The terminology port and its three implementations: the in-registry resolver, a FHIR $validate-code/$expand client, and a per-value-set router (used when several plugins each own a code system). |
@meridian/shared/domain/agent-spec |
LLM_PROVIDERS, AgentPortSchema/AgentPort, AgentSpec (zod, with legacy input/output → inputs/outputs coercion), AgentDef, coerceLegacyAgentIo(), resolveTypeName(), agentPortType(), agentPortTypeLabel(), selectableTypeNames() |
The agent specification schema (apiVersion: meridian/agent-v1) and its TypeRef resolution helpers. See Author an agent. |
@meridian/shared/domain/ports |
AgentToolHandle, AgentRunRequest, AgentRunnerPort, SubjectRecordPort, Ports (open bag, [pluginPort: string]: unknown), requirePort() |
The hexagonal port bundle a behavior reaches through ctx.ports. The SDK types only the ports the core calls (agent, terminology) plus the SubjectRecordPort platform capability; business port contracts live with their owning plugin, which augments Ports via declare module. requirePort<T>(ports, name) is the common runtime guard. Full contract at Port contracts. |
@meridian/shared/domain/agent-tools |
AgentToolResolution, AgentToolSource, ResolvedAgentTools, resolveAgentTools() |
The shared resolution loop turning an agent's tools references into invocable handles, composed from per-executor sources. |
@meridian/shared/domain/workflow-spec |
WorkflowNodeInstance, Connection, WorkflowSpec (zod, apiVersion: meridian/v3), parsePortRef() |
The workflow DSL schema. Full grammar at Workflow DSL. |
Terminology port
TerminologyPort is the one domain contract with more than a data shape: has,
validateCode, expand, display, subsumes — each implementation may answer
synchronously (InternalTerminology) or asynchronously (FhirTerminologyServer,
RoutingTerminology). See Configure terminology.
engine/* — type-system & catalog helpers
| Import | Exports | Purpose |
|---|---|---|
@meridian/shared/engine/type-system |
objectFields(), isAssignable(), validateValue(), exampleValue(), describeCatalogTypes() |
Structural connection compatibility (design-time) and value validation (runtime, port boundaries), crossing TypeRef against the OBJECT_TYPES/VALUE_SETS/DIMENSIONS registries. |
@meridian/shared/engine/conversions |
Conversion (interface), CONVERSIONS, registerConversion(), findConversion(), listConversions() |
The From/Into conversion registry backing the transform.convert node and the editor's auto-insert. Starts empty — the core knows no conversion; plugins contribute declarative entries via contributes.conversions (JEXL over value). |
@meridian/shared/engine/catalog-metadata |
NodeKind, PortDef, ConfigFieldDef, NodeTypeMeta, CATALOG_META, registerNodeMeta() |
The node-type registry (kind, ports, category). Seeded with only the core dataflow primitives (flow.*, transform.*, value.*); every domain node is registered by a plugin via registerNodeMeta. |
@meridian/shared/engine/dynamic-ports |
DynamicKind, templateVariables(), resolveDynamicPorts() |
Resolves the ports of dynamic nodes (break/make/convert/switch/map/guard/format) from their config — engine primitives a plugin never implements directly. |
@meridian/shared/engine/agent-tool-eligibility |
AgentToolEligibility, agentToolEligibility() |
Whether a catalog node may be exposed as a tool of an out-of-workflow agent — judged from its meta (kind, dynamic, agentTool opt-in) and the composability of its context against the context-kind registry (a kind with an idField is composable by the caller). |
@meridian/shared/engine/schedule |
ScheduleRuleSchema/ScheduleRule, ScheduleConfigSchema/ScheduleConfig, MIN_PERIOD_SECONDS, helpers |
The trigger.schedule rule grammar (cron/period) and its validation helpers. |
observability/trace
| Export | Purpose |
|---|---|
tracer |
The single OpenTelemetry tracer instance (meridian), shared by proxy, engine and plugins so spans assemble into one end-to-end trace. |
TraceCarrier |
Record<string, string> — a W3C traceparent/tracestate carrier for out-of-band propagation (e.g. a Restate invocation payload). |
withSpan() |
Runs a function inside an active span; records exceptions and sets ERROR status on throw. |
injectTraceContext() |
Captures the active trace context into a serializable carrier. |
runWithRemoteContext() |
Restores a carrier's trace context and runs a function under it. |
Depends only on @opentelemetry/api — a no-op API when no SDK is registered, so this
module costs nothing unless observability is enabled. See
Enable observability and
Observability signals.
version
| Export | Value |
|---|---|
PLUGIN_CONTRACT_VERSION |
"0.1.0" (libs/shared/src/version.ts) |
A plugin declares the SDK range it needs in its manifest (sdk: "^0.1.0"). At plugin
discovery the host (apps/api/src/plugins.ts) checks that range against PLUGIN_CONTRACT_VERSION
using satisfies() from the npm semver package (no hand-rolled semver comparison); a
plugin whose range does not match is logged and skipped, the others still load. See the
sdk field in Plugin manifest.
What is not exported
The SDK exposes contracts and pure/registry helpers only. It has no CLI (that is
@meridian/plugin-cli, see meridian-plugin CLI), no plugin loader or
filesystem discovery (that is the API host's PluginHost), and no bundler (plugins are
built with meridian-plugin build, an esbuild bundle — see
Bundling and distribution and
Build and bundle). Publishing and registry resolution
(meridian-plugin publish, the instance manifest's registry:/plugins: fields, the
MERIDIAN_REGISTRY environment variable) are documented in
Publish to the registry and
Set up a plugin registry.