@niadra/sdk 0.1.1 → 0.9.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.
Files changed (133) hide show
  1. package/CHANGELOG.md +200 -62
  2. package/README.md +462 -24
  3. package/dist/ai-sdk.cjs +1036 -0
  4. package/dist/ai-sdk.cjs.map +1 -0
  5. package/dist/ai-sdk.d.cts +118 -0
  6. package/dist/ai-sdk.d.ts +118 -0
  7. package/dist/ai-sdk.js +1029 -0
  8. package/dist/ai-sdk.js.map +1 -0
  9. package/dist/anthropic.cjs +528 -0
  10. package/dist/anthropic.cjs.map +1 -0
  11. package/dist/anthropic.d.cts +35 -0
  12. package/dist/anthropic.d.ts +35 -0
  13. package/dist/anthropic.js +523 -0
  14. package/dist/anthropic.js.map +1 -0
  15. package/dist/bedrock.cjs +392 -0
  16. package/dist/bedrock.cjs.map +1 -0
  17. package/dist/bedrock.d.cts +25 -0
  18. package/dist/bedrock.d.ts +25 -0
  19. package/dist/bedrock.js +388 -0
  20. package/dist/bedrock.js.map +1 -0
  21. package/dist/cli.js +11101 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/client-B_ip8T2o.d.cts +6960 -0
  24. package/dist/client-B_ip8T2o.d.ts +6960 -0
  25. package/dist/cloudflare-agents.cjs +626 -0
  26. package/dist/cloudflare-agents.cjs.map +1 -0
  27. package/dist/cloudflare-agents.d.cts +113 -0
  28. package/dist/cloudflare-agents.d.ts +113 -0
  29. package/dist/cloudflare-agents.js +622 -0
  30. package/dist/cloudflare-agents.js.map +1 -0
  31. package/dist/elevenlabs.cjs +738 -0
  32. package/dist/elevenlabs.cjs.map +1 -0
  33. package/dist/elevenlabs.d.cts +86 -0
  34. package/dist/elevenlabs.d.ts +86 -0
  35. package/dist/elevenlabs.js +733 -0
  36. package/dist/elevenlabs.js.map +1 -0
  37. package/dist/genkit.cjs +323 -0
  38. package/dist/genkit.cjs.map +1 -0
  39. package/dist/genkit.d.cts +67 -0
  40. package/dist/genkit.d.ts +67 -0
  41. package/dist/genkit.js +318 -0
  42. package/dist/genkit.js.map +1 -0
  43. package/dist/google-adk.cjs +705 -0
  44. package/dist/google-adk.cjs.map +1 -0
  45. package/dist/google-adk.d.cts +91 -0
  46. package/dist/google-adk.d.ts +91 -0
  47. package/dist/google-adk.js +701 -0
  48. package/dist/google-adk.js.map +1 -0
  49. package/dist/google-genai.cjs +422 -0
  50. package/dist/google-genai.cjs.map +1 -0
  51. package/dist/google-genai.d.cts +26 -0
  52. package/dist/google-genai.d.ts +26 -0
  53. package/dist/google-genai.js +418 -0
  54. package/dist/google-genai.js.map +1 -0
  55. package/dist/index.cjs +11494 -1910
  56. package/dist/index.cjs.map +1 -1
  57. package/dist/index.d.cts +957 -1294
  58. package/dist/index.d.ts +957 -1294
  59. package/dist/index.js +11441 -1911
  60. package/dist/index.js.map +1 -1
  61. package/dist/intercept-CBaPK_-k.d.ts +20 -0
  62. package/dist/intercept-CxmBLfoj.d.cts +20 -0
  63. package/dist/langchain.cjs +1076 -0
  64. package/dist/langchain.cjs.map +1 -0
  65. package/dist/langchain.d.cts +102 -0
  66. package/dist/langchain.d.ts +102 -0
  67. package/dist/langchain.js +1067 -0
  68. package/dist/langchain.js.map +1 -0
  69. package/dist/livekit.cjs +404 -0
  70. package/dist/livekit.cjs.map +1 -0
  71. package/dist/livekit.d.cts +113 -0
  72. package/dist/livekit.d.ts +113 -0
  73. package/dist/livekit.js +398 -0
  74. package/dist/livekit.js.map +1 -0
  75. package/dist/llamaindex.cjs +349 -0
  76. package/dist/llamaindex.cjs.map +1 -0
  77. package/dist/llamaindex.d.cts +92 -0
  78. package/dist/llamaindex.d.ts +92 -0
  79. package/dist/llamaindex.js +344 -0
  80. package/dist/llamaindex.js.map +1 -0
  81. package/dist/mastra.cjs +1081 -0
  82. package/dist/mastra.cjs.map +1 -0
  83. package/dist/mastra.d.cts +86 -0
  84. package/dist/mastra.d.ts +86 -0
  85. package/dist/mastra.js +1074 -0
  86. package/dist/mastra.js.map +1 -0
  87. package/dist/openai-agents.cjs +465 -0
  88. package/dist/openai-agents.cjs.map +1 -0
  89. package/dist/openai-agents.d.cts +75 -0
  90. package/dist/openai-agents.d.ts +75 -0
  91. package/dist/openai-agents.js +459 -0
  92. package/dist/openai-agents.js.map +1 -0
  93. package/dist/retell.cjs +846 -0
  94. package/dist/retell.cjs.map +1 -0
  95. package/dist/retell.d.cts +161 -0
  96. package/dist/retell.d.ts +161 -0
  97. package/dist/retell.js +841 -0
  98. package/dist/retell.js.map +1 -0
  99. package/dist/shared-BLkAbvuf.d.ts +39 -0
  100. package/dist/shared-DEkF2Y_z.d.cts +39 -0
  101. package/dist/strands.cjs +352 -0
  102. package/dist/strands.cjs.map +1 -0
  103. package/dist/strands.d.cts +72 -0
  104. package/dist/strands.d.ts +72 -0
  105. package/dist/strands.js +347 -0
  106. package/dist/strands.js.map +1 -0
  107. package/dist/twilio.cjs +174 -0
  108. package/dist/twilio.cjs.map +1 -0
  109. package/dist/twilio.d.cts +64 -0
  110. package/dist/twilio.d.ts +64 -0
  111. package/dist/twilio.js +167 -0
  112. package/dist/twilio.js.map +1 -0
  113. package/dist/vapi.cjs +661 -0
  114. package/dist/vapi.cjs.map +1 -0
  115. package/dist/vapi.d.cts +78 -0
  116. package/dist/vapi.d.ts +78 -0
  117. package/dist/vapi.js +656 -0
  118. package/dist/vapi.js.map +1 -0
  119. package/dist/voltagent.cjs +509 -0
  120. package/dist/voltagent.cjs.map +1 -0
  121. package/dist/voltagent.d.cts +70 -0
  122. package/dist/voltagent.d.ts +70 -0
  123. package/dist/voltagent.js +503 -0
  124. package/dist/voltagent.js.map +1 -0
  125. package/dist/webhook-BaraTaA9.d.ts +37 -0
  126. package/dist/webhook-CuR0Wckd.d.cts +37 -0
  127. package/dist/whatsapp.cjs +214 -0
  128. package/dist/whatsapp.cjs.map +1 -0
  129. package/dist/whatsapp.d.cts +81 -0
  130. package/dist/whatsapp.d.ts +81 -0
  131. package/dist/whatsapp.js +207 -0
  132. package/dist/whatsapp.js.map +1 -0
  133. package/package.json +351 -6
package/CHANGELOG.md CHANGED
@@ -2,76 +2,214 @@
2
2
 
3
3
  All notable changes to this package are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the package follows [Semantic Versioning](https://semver.org/).
4
4
 
5
- ## [0.1.1] - 2026-09-24
5
+ ## [Unreleased]
6
+
7
+ ## [0.9.0] - 2026-09-30
6
8
 
7
9
  ### Added
8
10
 
9
- - The agent's turn carries the usage the model provider reported for the call behind it, as
10
- `usage` (`ModelUsage`: provider, model, prompt tokens with the cached ones included, cached
11
- tokens, tokens written to the cache). `wrap()` reads it from every OpenAI-compatible response
12
- and from the last chunk of a stream that asked for it (`stream_options: { include_usage: true }`),
13
- and never changes the request. Niadra sums it per agent, vendor and model, and the Console shows
14
- the prompt cache's hit rate and estimated savings.
15
- - `agent(text, { usage })` on conversations and tasks takes the provider's response (OpenAI chat
16
- completions or Responses, Anthropic messages) or a `ModelUsage`, for agents that do not use
17
- `wrap()`; `modelUsage()` reads one yourself. A response without usage is left out; the turn is
18
- recorded either way.
19
- - CI runs the build on Deno (with no permissions), Bun, workerd (Cloudflare Workers) and the Vercel
20
- Edge Runtime (`pnpm runtimes`), and the README names them.
21
-
22
- ### Changed
23
-
24
- - `engines` asks for Node 20 or later, the versions the CI tests. The README no longer claims Node 18.
25
- - A conversation turn (a message with a `conversation_id`) leaves the queue at most 200 ms after it
26
- was queued, taking whatever else is waiting along, instead of up to a second: it is what the other
27
- agents read in `live`. `queue.turnFlushIntervalMs` sets it; other items still wait for
28
- `flushIntervalMs` (1 s) or `flushAt` (15).
29
- - The timeline tool says the history comes newest first, as the server returns it, instead of
30
- "in chronological order".
31
- - The search tool no longer offers the model a `system_event` item kind, and its description names
32
- business objects instead of system events: a system event is never an item, it changes its object,
33
- so the filter is `object`. The server still reads `system_event` from 0.1.0 as `object`.
34
- - `open()` sends `POST /v1/history/open` with the item id, the level and the conversation id in the
35
- body, instead of `GET /v1/history/items/{id}` with the conversation id in the query: a
36
- conversation id may be a phone number or an e-mail, and a URL reaches access logs.
37
- - `open()` takes `subject`, the customer the item must belong to; the server opens any other item
38
- as 404. The tool kit passes its bound customer, so `open_history_item` opens only that
39
- customer's items.
40
- - `task_id` on `open()` is no longer sent: the server never read it on this route. The field stays
41
- in `OpenParams` for code written against 0.1.0.
42
- - The `excerpt` field of an opened item says the server no longer sends it.
11
+ - `ContextResult.ageMs`: how long ago Niadra sent or confirmed the pack a read served. It is 0 for an answer
12
+ just received and grows while the cache serves the pack (`cache`, `stale`, or `fallback` with Niadra down).
13
+ - The chaos test (`test/chaos.test.ts`): Niadra's process killed, its network gone silent, answering 503 and
14
+ answering past the deadline, in the middle of a conversation.
15
+ - A state read's objects carry `derived`: the type's derived fields over its related objects (a look's
16
+ `all_pieces_available`), computed at the read, each with `v`, `logic`, `over` and `unknown`
17
+ (`DerivedState`). A shared object of a derived type carries `derived_status`, and its push's `inputs` name
18
+ shared objects.
43
19
 
44
20
  ### Fixed
45
21
 
46
- - Building a client on Deno without `--allow-env` no longer throws: a runtime that refuses to read
47
- the environment now counts as one without `NIADRA_API_KEY` and `NIADRA_BASE_URL`.
48
- - `feedback()` and the reservation in `uploadMedia()` end within `timeouts.write` (5 s) in total,
49
- retries and backoff included, instead of 5 s per attempt.
50
- - The transfer in `uploadMedia()` ends within `timeouts.upload` (60 s) in total instead of per attempt.
51
- - `identify()`, `verify()` and `handoff()` resolve by `timeouts.write` with a `NiadraTimeoutError`
52
- when the queue could not confirm them in time; the item stays queued and is still sent.
22
+ - The local copy of the suppression list is read to its end against the server: a page shorter than the limit
23
+ ends a read, and its cursor is where the next read starts. The server names the cursor on the last page
24
+ too, so the copy read 50 pages of nothing and was never held: `mayContact()` and a check that Niadra did not
25
+ answer fell back on the purpose's direction. The stand-in cell answers as the server does.
26
+ - A batch of events that still fails after its attempts with an error that may pass goes back to the front of
27
+ the queue and leaves again after a pause, doubling up to a minute, instead of being dropped: what an agent
28
+ said during an outage longer than a few seconds reached Niadra only in part.
29
+ - A check about an outbound contact keeps the local copy of the suppression list, read in the background once
30
+ a minute. Before, only `mayContact()` read it, so an agent that only called `check()` had no copy when Niadra
31
+ went down, and a purpose that fails open (`service`, `transactional`) went out to a customer who had opted
32
+ out of it.
33
+
34
+ ## [0.8.0] - 2026-09-30
35
+
36
+ ### Added
37
+
38
+ - The claim guard takes the offers a context read served as evidence: each object in the constraints block's
39
+ `already_presented` carries the numbers it was last shown with (`values`: price, total, discount,
40
+ installment), each with its role and whether it may be claimed now, and `blockValues()` turns them into
41
+ values the guard checks a number against, as it checks a tool's result. An offer shown too long ago to claim makes the
42
+ number `stale`, and a price only the pack's text states is still `unsupported`. The constraints block's
43
+ `Shown` model gains `values` (`ShownValue`).
44
+
45
+ ### Removed
46
+
47
+ - `tool(..., { binding })`, `new Counterfactual(..., { bindings })` and `niadra counterfactual --bindings`: a
48
+ tool's binding comes only from the space's `tool-bindings` document, which the SDK profile serves. A
49
+ counterfactual for a tool the space does not bind stops before calling it.
50
+
51
+ ## [0.7.0] - 2026-09-30
53
52
 
54
- ## [0.1.0] - 2026-09-23
53
+ The agent core. Every turn an agent takes is recorded in its own process; what it says is checked against
54
+ what its tools returned; agents, people and systems coordinate before they contact a customer or act; the
55
+ objects a company's systems push reach the agent as typed state with the freshness to say them; each agent
56
+ keeps its working state; and a company replays turns, derives its types and measures a tool's
57
+ counterfactual in its own CI. The framework adapters record turns. Every feature is off until the space
58
+ turns it on, and a space that did not ask sees no change.
55
59
 
56
- First public release, with the same surface as the Python SDK.
60
+ The versions published before it were previews: nothing of theirs carries over, and none of their names,
61
+ options or fallbacks is kept.
57
62
 
58
63
  ### Added
59
64
 
60
- - `Niadra` client with the endpoint derived from the source key (`https://<space>.<region>.api.niadra.com`), overridable with `baseURL`.
61
- - `context()` with a per-conversation cache: TTL, stale-while-revalidate with one deduplicated refresh per pack, last good value on failure, and ETag revalidation through `known_etag`. 401 and 403 drop cached packs, and a `degraded` answer never replaces a good one. Plain and delta reads of a conversation share one entry, and each delta is handed out once.
62
- - History navigation: `search()`, `timeline()` and `open()`.
63
- - `tools(subject)`: the navigation kit as function-calling definitions, with the customer bound outside the model.
64
- - `subjectToken()` for binding a customer to an MCP session.
65
- - Writes: `track()`, `action()`, `identify()`, `verify()` and `handoff()`, through a bounded queue that batches by count and time, retries with backoff and sends a coverage heartbeat once a minute.
66
- - `conversation()` helper that reads the pack the server pins, asks for deltas after the first read and keeps them until the pack changes, captures turns and emits `conversation.ended`.
67
- - `task()` helper for internal agents that centers its pack on its object, keeps deltas and stamps like a conversation, captures the agent's answers and emits `task.ended`; `verify()` on a task, whose `tools()` follow its level.
68
- - `markInjected()` and `contextStamp` on conversations and tasks: the agent's turns and actions carry the etag of the pack its prompt held and when it went in, as the event's `context_stamp`.
69
- - `wrap()` for OpenAI-compatible clients: injects the pack and the suffix into `chat.completions.create` and `parse` (also under `beta`), stamps the injection, records the answer, streams included, keeps `.withResponse()` working, and never lets a capture failure reach the caller. `injectContext()` places a pack in a message list by the same rule.
70
- - `objectState()` and `objectTimeline()` for business objects.
71
- - `feedback()` to retract or correct a fact, resolve an open item or record a conversation's outcome.
72
- - `uploadMedia()`: reserves an upload, sends the bytes to the signed URL with exactly the headers it names (HTTPS
73
- only, never the key) and resolves with `media_ref` and `media_sha256`; optionally bound to a `subject`.
74
- - Fail-open behavior on every public method, and `strict: true` to throw instead.
75
- - Per-method time budgets, 421 retries for moved spaces, and `problem+json` errors mapped to typed classes.
76
- - Flush on `beforeExit` in Node, `flush()` and `shutdown()` everywhere else.
77
- - Handle builders and wire types for every contract model.
65
+ - `Niadra`, with the endpoint derived from the source key and fail-open behavior on every public method
66
+ (`strict: true` to throw instead), in Node, Deno, Bun, Cloudflare Workers and edge runtimes.
67
+ - `context()` before the model call, cached per conversation and revalidated by ETag, with the customer's
68
+ last turn as `query` (the turn's `slots`), `prefetch()` while the customer speaks, the voice read path,
69
+ `format: "json"` for the pack as data (`context-pack.v1`) and `explain: true` for why each slot was chosen.
70
+ - History navigation (`search()`, `timeline()`, `open()`) and `tools()`, the same navigation as
71
+ function-calling tools bound to one customer, with `subjectToken()` for MCP.
72
+ - Writes through a bounded queue with one batch in flight (`track()`, `action()`, `identify()`, `verify()`,
73
+ `handoff()`), `conversation()` and `task()`, `feedback()`, `feedbackBatch()`, `uploadMedia()`,
74
+ `ingestStatus()`, `whoami()`, `objectState()` (the object as a state read serves it, `ObjectRead`) and
75
+ `objectTimeline()`.
76
+ - Agent memory (`agentMemory()`, `searchAgentMemory()`, `remember()`), backed answers and the guard lines a
77
+ read carries; `niadra.admin` for a key with the `admin` scope.
78
+ - `wrap()` for OpenAI-compatible clients and the adapters under `@niadra/sdk/<integration>`; the n8n and
79
+ Flowise nodes in `packages/`.
80
+ - `niadra.api` (`Api`): one method per route of turn records, replay and scenarios, typed state and the
81
+ agent's working state, subject signals and measurement, and coordination, named in camelCase as the
82
+ server names the operation. Unlike the rest of the client they never fail open.
83
+ - The types of those routes (`TurnRecord`, `StateReadRequest`, `CheckResult` and the rest), generated
84
+ from the server's OpenAPI document by `scripts/sync-spec.ts`.
85
+ - Turn records: `conversation.turn()` records what one turn read, called and said, with the build it ran
86
+ on (`Niadra.build()`), and `tool()` wraps a tool of yours so each call inside a turn is recorded, copied
87
+ as JSON at the moment, with the objects its result showed. The turn in progress follows the async
88
+ context (`AsyncLocalStorage`; `useAsyncLocalStorage()` supplies one where `node:async_hooks` is missing),
89
+ so parallel sub-agents keep their own turns. A bounded queue keeps the closed turns (values of unflagged
90
+ turns go first when it is full) and a background sender posts them to `POST /v1/turns` in the space's
91
+ content mode, with the values in your own bucket in `pointer` mode (`niadra.turns.store()`). Closing a
92
+ turn never waits for the network, and a recorded tool call costs under 2 ms at the 95th percentile.
93
+ - The warm cache for when Niadra is down: `niadra.profile()` keeps the SDK profile (features, claim
94
+ contract); `context({ include: ["constraints", "state"] })` reads the constraints block and the state view
95
+ with the pack, and a failed read serves the last good ones; `niadra.mayContact()` checks an outbound
96
+ contact against the local copy of the suppression list, which keeps applying with Niadra out of reach.
97
+ - The claim contract inside a turn: what the agent says is checked against what its tools returned and
98
+ each claim goes to the turn record with its verdict (count mode never changes an output).
99
+ `conversation.claims.guard(stream)` holds what could start a claim until its sentence ends (150 ms at
100
+ most, 300 ms a message) and lets it go as the contract's actions say: a blocked sentence gives way to the
101
+ category's caveat, a stale copy of one field becomes its fresh value only when that is unequivocal, a
102
+ warning marks the claim. `claims.guardText()` does the same on a whole output. An immutable output never
103
+ changes: a block sends it to a person.
104
+ - Coordination: `conversation.check()` asks before acting and, when Niadra does not answer within 200 ms,
105
+ decides by the purpose's direction (a customer's message and service go, marketing, retention,
106
+ collection and an effect with a key wait, the local opt-out always holds); `conversation.declare` sends
107
+ what happened in the background until Niadra takes it; `conversation.claim()` holds a lease or a task
108
+ lock. `task()` takes the same calls.
109
+ - `niadra.contactGateway()` and `verifyContactToken()`: the contact token's offline check at your gateway
110
+ (Ed25519 through Web Crypto), with the space's public keys kept while Niadra is down and each token let
111
+ through once.
112
+ - The agent's working state: `conversation.agentState.get()` and `put()`, compare-and-swap or merge by key
113
+ (`DELETE` removes a key), reading its own writes, kept and sent again while Niadra is down.
114
+ - `niadra.resolvers` and `verifyClaim()`: a value not safe to claim is read again by your resolver, inside
115
+ your boundary and within 300 ms, and the fresh value decides. `ContentResolver` puts back the text a
116
+ pointer-mode space keeps in your storage, and `ResolverWorker` serves the space's refresh requests with
117
+ your resolvers.
118
+ - Replay inside your boundary: `Replayer` runs the turns of a scenario N times with the build you pin,
119
+ answers your tools from the record (`tool(name, fn, { dryRun: true })` lets one run for real when the
120
+ record has no answer), keeps everything the agent sends from leaving, evaluates the assertions and
121
+ reports the run, and Niadra answers with the statistical verdict. Runs are numbered from 1, as the
122
+ replay spec numbers them.
123
+ - `overlapAtK()`: the depth-weighted overlap of two ranked lists that the tool counterfactual reports
124
+ (`spec/counterfactual.md`, 4); it passes the `counterfactual-overlap` vectors.
125
+ - The recording the SDK profile serves: a turn leaves in the content mode the space names for the source,
126
+ and a turn without a pin the space requires for replay is kept with a warning, once.
127
+ - Turn records from the framework adapters. LangChain.js and LangGraph.js:
128
+ `new NiadraCallbackHandler(conversation, { turns: true })` records each top-level run as a turn, with its
129
+ tool calls (the provider's call ids) and its model calls with their tokens. Mastra:
130
+ `niadraProcessor({ turns: true })` records each request as a turn. Vercel AI SDK: `niadraMiddleware`
131
+ records each model call in the turn in progress, `recordTools(tools)` records each tool call with the
132
+ provider's call id, and `niadraTurn()` keeps a `streamText` turn open until the stream finishes. A run
133
+ inside a turn in progress records into it, and a function wrapped with `tool()` inside a framework's tool
134
+ takes over its call, so a replay answers it from the record.
135
+ - `conversation.activeTurn()`: the turn in progress, from the async context or the newest the session
136
+ opened and has not closed; `tool()` takes `callId` and `frame` for frameworks that run tools elsewhere.
137
+ - `canonicalJson()` and `jsonDigest()`: the digest of a turn record's value, SHA-256 over its canonical
138
+ JSON (RFC 8785), as every producer computes it.
139
+ - `expr`: niadra-expr, the language of the type registry's conditions, timers, keys and readings.
140
+ `expr.parse()` reads an expression, `expr.compileExpression()` resolves its names against a type's
141
+ declarations, and `expr.evaluate()` computes it over an object's slots with the four logical values,
142
+ as the server does; it passes every case of `spec/vectors/niadra-expr.v0.json`. Dates and times are
143
+ integers (days, milliseconds), never the machine's time zone.
144
+ - The conformance vectors of the open specifications, run by `test/vectors.test.ts`, and the design of
145
+ the turn capture (`docs/design/turn-capture.md`).
146
+ - `canonicalDestination()` and `suppressionKey()`: a handle's canonical destination (`phone:+<E.164>`
147
+ with the Brazilian ninth digit, `email:<address>`) and its key per reader,
148
+ `base64url(HMAC-SHA256(salt, ...))`, as the suppression list and the contact token compute them.
149
+ `suppressionKey()` is async (Web Crypto); errors are `NiadraDestinationError`.
150
+ - `exposureToken()` and `parseExposureToken()`: the exposure token a card carries,
151
+ `nx1.<id>.<position>.<verifier>`, built synchronously and read with the refusals of its spec
152
+ (`NiadraExposureTokenError`).
153
+ - `renderConstraints()` and `honoredConstraints()`: the constraints block rendered for one tool call
154
+ through the tool's binding, in advisory or apply mode, and the count of what the call's results
155
+ honored.
156
+ - `claims`: the claim contract's reference checker, pure and without a model. `mentions()` reads the
157
+ numbers of an output in Portuguese, English or Spanish (class, normalized value, span in code points),
158
+ `rolesOf()` their roles, `check()` the claims each category of a contract detects with their nature,
159
+ verdict and action, `detected()` what a phrase of the negative corpus must never trigger, and `score()`
160
+ the text anchor. It passes the claim-parser, claim-detect and claim-anchor vectors and finds nothing in
161
+ the negative corpus of the three example contracts.
162
+ - The `niadra` command for Node (`npx niadra`): `resolver-worker`, `replay`, `counterfactual`,
163
+ `types derive` (with `--check`) and `contract test`, with the Python command's arguments and exit codes.
164
+ `types derive` reads one PostgreSQL table's catalog (never a row), computes the same fingerprint as the
165
+ Python SDK and passes the `type-derive` vectors; `--check` sends Niadra only the fingerprint and the
166
+ counts.
167
+ - The blocks a read asks for reach the model: with `include`, the state view's lines and the constraints
168
+ block go in `suffix` after the slots, inside one `<niadra>` section in the pack's language, byte for byte
169
+ what the Python SDK writes; a read without blocks keeps its suffix. The context answer also carries the
170
+ coordination block.
171
+ - `niadra.internalText`: fingerprints of the company's own prompt (the same SHA-256 shingles as the Python
172
+ SDK); a repeated passage gives way to the claim contract's `redact` line and is recorded with
173
+ `internal_text_found`, never the text.
174
+ - `tool(name, fn, { binding })` records what a call did with the constraints block, and `maskOutput: true`
175
+ keeps the fields the key may not read from the model (the last profile read while Niadra is down,
176
+ `onUnknown: "block"` to fail closed). A turn keeps the pack, the block and the working state it read, and
177
+ what the person was shown or engaged with (`frame.interact`).
178
+ - The tool counterfactual: `Counterfactual` behaves as the Python runner, sending Niadra only overlaps and
179
+ positions.
180
+ - A replay starts from the working state the recorded turn read, and a sub-turn of a replayed turn is
181
+ replayed and never sent. Mastra tools answer from the record; LangChain tools passed through
182
+ `recordTools()` too, and the handler refuses any other with `NiadraReplayRefusedError` before it runs.
183
+ - Turn records from OpenAI Agents JS, Google ADK and VoltAgent with `turns: true`: each run is a turn, with
184
+ each tool call (the framework's own call id) and each model call. ADK tools answer from the record in a
185
+ replay; OpenAI Agents JS and VoltAgent cannot stop a tool from their hooks, so wrap those tools with
186
+ `tool()` to replay them.
187
+ - One example per concept of the agent core (`examples/claim-guard.ts`, `coordination.ts`, `object-state.ts`,
188
+ `working-state.ts`, `masked-tool.ts`, `tool-counterfactual.ts`) and `examples/ci/niadra-checks.yml`, each
189
+ run by the tests.
190
+ - `ContextResponse.budget` (`BudgetBlock`, with `BudgetPack`, `BudgetUse` and `BudgetCut`): with
191
+ `include: ["budget"]`, what the pack costs per section, what this agent already spent in the conversation
192
+ and the case, and the units the measurement says it leaves unused. Shown, never enforced.
193
+ - `niadra.api.overview()`: the coordination overview in counts (`GET /v1/coordination/overview`).
194
+ - `pnpm sync-spec --spec` also copies the Context Pack schema (`spec/context-pack.v1.json`), and
195
+ `test/spec.test.ts` holds `ContextResponse` and every include block to it.
196
+ - The tool bindings the space declares come in the SDK profile (`SdkProfile.tool_bindings`, typed
197
+ `ToolBinding`), for this source's tools. A tool without a binding in code measures the constraints block
198
+ and runs its counterfactual through the binding served for its name, and `binding` in code wins.
199
+ Left unset, `maskOutput` follows the served binding's `capabilities.mask_output`. `api.constraints()` with
200
+ `tool` answers the block rendered for that tool, as advice.
201
+ - Watch revalidation in `ResolverWorker` and `npx niadra resolver-worker`: a watch fires only on a value its
202
+ source confirmed. The worker serves `watch_revalidation` requests first, pushes every object it read with
203
+ the `request_id` it answers (which settles the request and decides the object's due watches even when the
204
+ value did not change), and releases a request it cannot answer
205
+ (`POST /v1/state/refresh-requests/{id}/release`), as `not_found` when the resolver returns `NOT_FOUND` and
206
+ `failed` when it fails. A type without a resolver, or whose resolver's circuit is open, still waits out its
207
+ lease. `Resolvers.fetch()` says why a read brought no object.
208
+ - `ConstraintsBlock.text`: the constraints block as the server writes it for a model, each field by its
209
+ type's label and each operator in words, in the space's language. The suffix places it as it places the
210
+ state view's text.
211
+ - The claim contract reads the computed values a state read serves as evidence, by their name, while they
212
+ are claim-safe, and the claim guard takes as evidence every value the include blocks placed in the turn
213
+ block. A value that is not claim-safe backs nothing.
214
+ - A hedged number is no claim (the claim contract spec, 5.4): "I can't confirm the $24.90 still applies" or
215
+ "$689.00, not $612.00" state no such price.