@nifrajs/cli 2.14.1 → 3.2.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/README.md +10 -0
- package/dist/assure-hydration.d.ts.map +1 -1
- package/dist/assure-hydration.js +6 -1
- package/dist/assure-hydration.js.map +1 -1
- package/dist/assure.d.ts.map +1 -1
- package/dist/assure.js +3 -2
- package/dist/assure.js.map +1 -1
- package/dist/check-diagnostics.d.ts +165 -0
- package/dist/check-diagnostics.d.ts.map +1 -0
- package/dist/check-diagnostics.js +1009 -0
- package/dist/check-diagnostics.js.map +1 -0
- package/dist/check-scan.d.ts +245 -0
- package/dist/check-scan.d.ts.map +1 -0
- package/dist/check-scan.js +1599 -0
- package/dist/check-scan.js.map +1 -0
- package/dist/check.d.ts +4 -324
- package/dist/check.d.ts.map +1 -1
- package/dist/check.js +8 -2346
- package/dist/check.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +285 -10
- package/dist/cli.js.map +1 -1
- package/dist/command-catalog.d.ts +27 -1
- package/dist/command-catalog.d.ts.map +1 -1
- package/dist/command-catalog.js +142 -2
- package/dist/command-catalog.js.map +1 -1
- package/dist/doctor.d.ts +42 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +64 -7
- package/dist/doctor.js.map +1 -1
- package/dist/env-file.d.ts +17 -0
- package/dist/env-file.d.ts.map +1 -0
- package/dist/env-file.js +113 -0
- package/dist/env-file.js.map +1 -0
- package/dist/fix-recipes.d.ts.map +1 -1
- package/dist/fix-recipes.js +91 -15
- package/dist/fix-recipes.js.map +1 -1
- package/dist/frontend-guidance.d.ts +57 -0
- package/dist/frontend-guidance.d.ts.map +1 -0
- package/dist/frontend-guidance.js +195 -0
- package/dist/frontend-guidance.js.map +1 -0
- package/dist/internal/reserved-segment-codemod.d.ts +36 -0
- package/dist/internal/reserved-segment-codemod.d.ts.map +1 -0
- package/dist/internal/reserved-segment-codemod.js +134 -0
- package/dist/internal/reserved-segment-codemod.js.map +1 -0
- package/dist/internal/typescript-import.d.ts +1 -1
- package/dist/internal/typescript-import.d.ts.map +1 -1
- package/dist/internal/typescript-import.js +62 -11
- package/dist/internal/typescript-import.js.map +1 -1
- package/dist/introspect.d.ts +26 -1
- package/dist/introspect.d.ts.map +1 -1
- package/dist/introspect.js +74 -24
- package/dist/introspect.js.map +1 -1
- package/dist/levels-tool.d.ts.map +1 -1
- package/dist/levels-tool.js +6 -0
- package/dist/levels-tool.js.map +1 -1
- package/dist/load.d.ts.map +1 -1
- package/dist/load.js +4 -1
- package/dist/load.js.map +1 -1
- package/dist/mcp-context.d.ts +48 -0
- package/dist/mcp-context.d.ts.map +1 -0
- package/dist/mcp-context.js +215 -0
- package/dist/mcp-context.js.map +1 -0
- package/dist/mcp-docs-tools.d.ts.map +1 -1
- package/dist/mcp-docs-tools.js +31 -0
- package/dist/mcp-docs-tools.js.map +1 -1
- package/dist/mcp-exec.d.ts +74 -0
- package/dist/mcp-exec.d.ts.map +1 -0
- package/dist/mcp-exec.js +844 -0
- package/dist/mcp-exec.js.map +1 -0
- package/dist/mcp-http.js +1 -1
- package/dist/mcp-http.js.map +1 -1
- package/dist/mcp-io.d.ts +26 -0
- package/dist/mcp-io.d.ts.map +1 -0
- package/dist/mcp-io.js +100 -0
- package/dist/mcp-io.js.map +1 -0
- package/dist/mcp-reflect.d.ts +16 -0
- package/dist/mcp-reflect.d.ts.map +1 -0
- package/dist/mcp-reflect.js +101 -0
- package/dist/mcp-reflect.js.map +1 -0
- package/dist/mcp-root.d.ts +7 -0
- package/dist/mcp-root.d.ts.map +1 -1
- package/dist/mcp-root.js +51 -3
- package/dist/mcp-root.js.map +1 -1
- package/dist/mcp.d.ts +10 -84
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +13 -1170
- package/dist/mcp.js.map +1 -1
- package/dist/openapi-tool.d.ts +5 -10
- package/dist/openapi-tool.d.ts.map +1 -1
- package/dist/openapi-tool.js +21 -2
- package/dist/openapi-tool.js.map +1 -1
- package/dist/openapi-types.d.ts +21 -0
- package/dist/openapi-types.d.ts.map +1 -0
- package/dist/openapi-types.js +214 -0
- package/dist/openapi-types.js.map +1 -0
- package/dist/port.d.ts.map +1 -1
- package/dist/port.js +2 -1
- package/dist/port.js.map +1 -1
- package/dist/project-facts.d.ts +2 -1
- package/dist/project-facts.d.ts.map +1 -1
- package/dist/project-facts.js.map +1 -1
- package/dist/recipes/3.0.0.d.ts +10 -0
- package/dist/recipes/3.0.0.d.ts.map +1 -0
- package/dist/recipes/3.0.0.js +23 -0
- package/dist/recipes/3.0.0.js.map +1 -0
- package/dist/recipes/index.d.ts.map +1 -1
- package/dist/recipes/index.js +2 -0
- package/dist/recipes/index.js.map +1 -1
- package/dist/release-verification.d.ts +4 -1
- package/dist/release-verification.d.ts.map +1 -1
- package/dist/release-verification.js +6 -123
- package/dist/release-verification.js.map +1 -1
- package/dist/rules/codes.d.ts +4 -0
- package/dist/rules/codes.d.ts.map +1 -1
- package/dist/rules/codes.js +4 -0
- package/dist/rules/codes.js.map +1 -1
- package/dist/rules/islands.d.ts +4 -0
- package/dist/rules/islands.d.ts.map +1 -0
- package/dist/rules/islands.js +155 -0
- package/dist/rules/islands.js.map +1 -0
- package/dist/rules/nano.d.ts +6 -0
- package/dist/rules/nano.d.ts.map +1 -0
- package/dist/rules/nano.js +264 -0
- package/dist/rules/nano.js.map +1 -0
- package/dist/rules/routes.d.ts.map +1 -1
- package/dist/rules/routes.js +17 -30
- package/dist/rules/routes.js.map +1 -1
- package/dist/rules/security.d.ts.map +1 -1
- package/dist/rules/security.js +38 -4
- package/dist/rules/security.js.map +1 -1
- package/dist/scaffold.d.ts +12 -6
- package/dist/scaffold.d.ts.map +1 -1
- package/dist/scaffold.js +149 -10
- package/dist/scaffold.js.map +1 -1
- package/dist/search-terms.d.ts.map +1 -1
- package/dist/search-terms.js +5 -3
- package/dist/search-terms.js.map +1 -1
- package/dist/stylex-migrate.d.ts +38 -0
- package/dist/stylex-migrate.d.ts.map +1 -0
- package/dist/stylex-migrate.js +1052 -0
- package/dist/stylex-migrate.js.map +1 -0
- package/dist/sync-manifest.d.ts.map +1 -1
- package/dist/sync-manifest.js +2 -1
- package/dist/sync-manifest.js.map +1 -1
- package/dist/verification-plan.d.ts +24 -0
- package/dist/verification-plan.d.ts.map +1 -0
- package/dist/verification-plan.js +116 -0
- package/dist/verification-plan.js.map +1 -0
- package/dist/work-graph.d.ts.map +1 -1
- package/dist/work-graph.js +6 -3
- package/dist/work-graph.js.map +1 -1
- package/dist/workspace-link.d.ts +37 -0
- package/dist/workspace-link.d.ts.map +1 -0
- package/dist/workspace-link.js +72 -0
- package/dist/workspace-link.js.map +1 -0
- package/docs/examples.json +37 -1
- package/docs/llms-full.txt +1598 -44
- package/docs/types.json +5157 -172
- package/package.json +9 -9
- package/src/assure-hydration.ts +6 -1
- package/src/assure.ts +4 -2
- package/src/check-diagnostics.ts +1219 -0
- package/src/check-scan.ts +1825 -0
- package/src/check.ts +47 -2731
- package/src/cli.ts +291 -10
- package/src/command-catalog.ts +177 -2
- package/src/doctor.ts +99 -8
- package/src/env-file.ts +121 -0
- package/src/fix-recipes.ts +101 -15
- package/src/frontend-guidance.ts +259 -0
- package/src/internal/reserved-segment-codemod.ts +150 -0
- package/src/internal/typescript-import.ts +61 -11
- package/src/introspect.ts +82 -21
- package/src/levels-tool.ts +6 -0
- package/src/load.ts +4 -1
- package/src/mcp-context.ts +266 -0
- package/src/mcp-docs-tools.ts +37 -0
- package/src/mcp-exec.ts +1040 -0
- package/src/mcp-http.ts +1 -1
- package/src/mcp-io.ts +118 -0
- package/src/mcp-reflect.ts +140 -0
- package/src/mcp-root.ts +62 -4
- package/src/mcp.ts +61 -1436
- package/src/openapi-tool.ts +32 -2
- package/src/openapi-types.ts +261 -0
- package/src/port.ts +2 -1
- package/src/project-facts.ts +2 -4
- package/src/recipes/3.0.0.ts +24 -0
- package/src/recipes/index.ts +2 -0
- package/src/release-verification.ts +22 -147
- package/src/rules/codes.ts +4 -0
- package/src/rules/islands.ts +171 -0
- package/src/rules/nano.ts +295 -0
- package/src/rules/routes.ts +17 -30
- package/src/rules/security.ts +40 -4
- package/src/scaffold.ts +169 -9
- package/src/search-terms.ts +7 -3
- package/src/stylex-migrate.ts +1139 -0
- package/src/sync-manifest.ts +2 -1
- package/src/verification-plan.ts +242 -0
- package/src/work-graph.ts +6 -3
- package/src/workspace-link.ts +80 -0
package/docs/llms-full.txt
CHANGED
|
@@ -320,7 +320,7 @@ renders in its place, wrapped by the layouts at/above that segment, at status 50
|
|
|
320
320
|
non-hydrated). On the **client** - a render error during navigation/interaction is caught by
|
|
321
321
|
the nearest boundary, which renders `_error` in place (all five adapters). It
|
|
322
322
|
receives the serialized error as `{ data: { name, message } }` (never the
|
|
323
|
-
stack); a thrown
|
|
323
|
+
stack); a thrown control-flow value (e.g. a guard `redirect`) passes through.
|
|
324
324
|
|
|
325
325
|
```ts
|
|
326
326
|
routes/
|
|
@@ -1225,6 +1225,374 @@ if (document.documentElement.hasAttribute("data-nifra-hydrated")) start()
|
|
|
1225
1225
|
else document.addEventListener("nifra:hydrated", start, { once: true })
|
|
1226
1226
|
```
|
|
1227
1227
|
|
|
1228
|
+
## Nifra - Islands: the AI-safe interactivity lane
|
|
1229
|
+
|
|
1230
|
+
> Add interactivity to a zero-runtime vanilla page with islands - imperative DOM enhancers, no framework runtime, no hydration. Explicit code an AI (or a human) gets right first try: mount, coordinate over a typed bus, always return cleanup.
|
|
1231
|
+
|
|
1232
|
+
A `@nifrajs/web-vanilla` page ships zero framework runtime. When one corner needs
|
|
1233
|
+
to be interactive, you don't turn on hydration - you mount an **island**: a
|
|
1234
|
+
small, plain-DOM enhancer over a server-rendered element. Explicit imperative code with no
|
|
1235
|
+
hidden reactivity - the shape an AI agent (or a human) gets right on the first try.
|
|
1236
|
+
|
|
1237
|
+
### Why islands, not hydration
|
|
1238
|
+
|
|
1239
|
+
Vanilla routes set `export const hydrate = false` - there is no client framework
|
|
1240
|
+
to hydrate with, and that is the point. The five framework adapters give you a reactive
|
|
1241
|
+
runtime and pay for it in client JS and in the subtle failure modes (stale closures,
|
|
1242
|
+
hydration mismatch, what-re-runs-when) that trip up generated code. Islands take the other
|
|
1243
|
+
trade: no runtime, no reactivity to get wrong. You wire the DOM by hand and hand back a
|
|
1244
|
+
teardown. Reach for a framework adapter when you genuinely need a stateful app UI; reach for
|
|
1245
|
+
islands for widgets on an otherwise-static page.
|
|
1246
|
+
|
|
1247
|
+
### Mount an island
|
|
1248
|
+
|
|
1249
|
+
Render a `<nifra-island>` marker in your page (props are inline JSON), then
|
|
1250
|
+
bundle one entry that calls `mountIslands`. Load it via the route's
|
|
1251
|
+
`islandScripts`.
|
|
1252
|
+
|
|
1253
|
+
```ts
|
|
1254
|
+
// doc-check: skip - server-rendered island marker (HTML, not a checkable module).
|
|
1255
|
+
// In your @nifrajs/web-vanilla page, render the host element with inline JSON props:
|
|
1256
|
+
html`<nifra-island data-id="counter" data-props=${JSON.stringify({ start: 0 })}>
|
|
1257
|
+
<output>0</output>
|
|
1258
|
+
<button type="button">+1</button>
|
|
1259
|
+
</nifra-island>`
|
|
1260
|
+
```
|
|
1261
|
+
|
|
1262
|
+
```ts
|
|
1263
|
+
// doc-check: skip - browser DOM enhancer, typechecked in @nifrajs/web under its DOM lib.
|
|
1264
|
+
import { defineIsland, mountIslands } from "@nifrajs/web/islands"
|
|
1265
|
+
|
|
1266
|
+
// defineIsland pins the data-props type; the body is plain imperative DOM. ALWAYS return the
|
|
1267
|
+
// teardown for anything you wire - mountIslands calls it on soft-nav (NF-C020 warns if you forget).
|
|
1268
|
+
const counter = defineIsland<{ start: number }>((el, props) => {
|
|
1269
|
+
let n = props.start
|
|
1270
|
+
const out = el.querySelector("output")!
|
|
1271
|
+
const onClick = () => { out.textContent = String(++n) }
|
|
1272
|
+
el.querySelector("button")?.addEventListener("click", onClick)
|
|
1273
|
+
return () => el.querySelector("button")?.removeEventListener("click", onClick)
|
|
1274
|
+
})
|
|
1275
|
+
|
|
1276
|
+
// One bundle entry, loaded via the route's `islandScripts`.
|
|
1277
|
+
mountIslands({ counter })
|
|
1278
|
+
```
|
|
1279
|
+
|
|
1280
|
+
`defineIsland<Props>` is a zero-cost identity helper - its only job is to
|
|
1281
|
+
type `props` and `el` so the body needs no cast. Keep the body
|
|
1282
|
+
imperative: read the DOM, add listeners, **return the cleanup**. The returned
|
|
1283
|
+
function runs on soft-nav teardown; forget it and every navigation leaks the listener -
|
|
1284
|
+
`nifra check` flags exactly that as `NF-C020`.
|
|
1285
|
+
|
|
1286
|
+
### Coordinate islands with a typed bus
|
|
1287
|
+
|
|
1288
|
+
Islands are isolated by design - each enhances one element and shares no state. When two must
|
|
1289
|
+
talk (an “add to cart” button and a cart badge), use a
|
|
1290
|
+
`createIslandBus`: one typed channel, created once and closed over by each
|
|
1291
|
+
enhancer. No implicit global, so concurrent renders and tests never cross-talk.
|
|
1292
|
+
|
|
1293
|
+
```ts
|
|
1294
|
+
import { createIslandBus } from "@nifrajs/web/islands"
|
|
1295
|
+
|
|
1296
|
+
// One typed channel, created once and closed over by every enhancer that needs it.
|
|
1297
|
+
type CartEvents = { "cart:add": { sku: string }; "cart:count": number }
|
|
1298
|
+
const bus = createIslandBus<CartEvents>()
|
|
1299
|
+
|
|
1300
|
+
const off = bus.on("cart:count", (n) => console.log("cart now has", n, "items"))
|
|
1301
|
+
bus.emit("cart:add", { sku: "ABC-1" })
|
|
1302
|
+
off() // unsubscribe - also usable directly as an island's cleanup
|
|
1303
|
+
```
|
|
1304
|
+
|
|
1305
|
+
The bus is synchronous, in-memory, and carries no history - a subscriber sees only events
|
|
1306
|
+
emitted after it subscribes. A throwing handler is isolated from the others. Because
|
|
1307
|
+
`on()` returns its own unsubscribe, an enhancer whose only job is to listen can
|
|
1308
|
+
return it directly as its cleanup:
|
|
1309
|
+
|
|
1310
|
+
```ts
|
|
1311
|
+
// doc-check: skip - browser DOM enhancer, typechecked in @nifrajs/web under its DOM lib.
|
|
1312
|
+
import { createIslandBus, defineIsland, mountIslands } from "@nifrajs/web/islands"
|
|
1313
|
+
|
|
1314
|
+
type CartEvents = { "cart:add": { sku: string }; "cart:count": number }
|
|
1315
|
+
const bus = createIslandBus<CartEvents>()
|
|
1316
|
+
|
|
1317
|
+
// Two islands that never import each other - they meet only on the bus.
|
|
1318
|
+
const addButton = defineIsland<{ sku: string }>((el, props) => {
|
|
1319
|
+
const onClick = () => bus.emit("cart:add", { sku: props.sku })
|
|
1320
|
+
el.addEventListener("click", onClick)
|
|
1321
|
+
return () => el.removeEventListener("click", onClick)
|
|
1322
|
+
})
|
|
1323
|
+
|
|
1324
|
+
let count = 0
|
|
1325
|
+
const badge = defineIsland((el) => {
|
|
1326
|
+
const unsubscribe = bus.on("cart:add", () => {
|
|
1327
|
+
count += 1
|
|
1328
|
+
el.textContent = String(count)
|
|
1329
|
+
bus.emit("cart:count", count)
|
|
1330
|
+
})
|
|
1331
|
+
return unsubscribe // the on() unsubscribe IS the cleanup
|
|
1332
|
+
})
|
|
1333
|
+
|
|
1334
|
+
mountIslands({ addButton, badge })
|
|
1335
|
+
```
|
|
1336
|
+
|
|
1337
|
+
### Pattern: filter drives results
|
|
1338
|
+
|
|
1339
|
+
The same shape scales to any “one island changes, another reacts” case. Each
|
|
1340
|
+
island owns only its own DOM; they meet on the channel, never in a shared store.
|
|
1341
|
+
|
|
1342
|
+
```ts
|
|
1343
|
+
// doc-check: skip - browser DOM enhancer, typechecked in @nifrajs/web under its DOM lib.
|
|
1344
|
+
import { createIslandBus, defineIsland, mountIslands } from "@nifrajs/web/islands"
|
|
1345
|
+
|
|
1346
|
+
// filter -> results, one directional channel. The results island owns its own DOM; the filter
|
|
1347
|
+
// island owns none of it. No shared store, no reactive tree - a message and two enhancers.
|
|
1348
|
+
const bus = createIslandBus<{ "filter:set": string }>()
|
|
1349
|
+
|
|
1350
|
+
const filter = defineIsland((el) => {
|
|
1351
|
+
const input = el.querySelector("input")!
|
|
1352
|
+
const onInput = () => bus.emit("filter:set", input.value.toLowerCase())
|
|
1353
|
+
input.addEventListener("input", onInput)
|
|
1354
|
+
return () => input.removeEventListener("input", onInput)
|
|
1355
|
+
})
|
|
1356
|
+
|
|
1357
|
+
const results = defineIsland((el) =>
|
|
1358
|
+
bus.on("filter:set", (q) => {
|
|
1359
|
+
for (const row of el.querySelectorAll<HTMLElement>("[data-name]")) {
|
|
1360
|
+
const name = row.dataset.name ?? ""
|
|
1361
|
+
row.hidden = q !== "" && !name.toLowerCase().includes(q)
|
|
1362
|
+
}
|
|
1363
|
+
}),
|
|
1364
|
+
)
|
|
1365
|
+
|
|
1366
|
+
mountIslands({ filter, results })
|
|
1367
|
+
```
|
|
1368
|
+
|
|
1369
|
+
### Load strategies
|
|
1370
|
+
|
|
1371
|
+
A marker's `data-strategy` defers its enhancer: `load` (default),
|
|
1372
|
+
`idle`, `visible` (mount when it scrolls into view), or a
|
|
1373
|
+
`media` query. An island with no matching enhancer, or an invalid strategy, stays
|
|
1374
|
+
inert server-rendered HTML - forward-compatible, never a runtime error.
|
|
1375
|
+
|
|
1376
|
+
## Nifra - nano: explicit reactivity for small apps
|
|
1377
|
+
|
|
1378
|
+
> nano is the AI-safe small-app lane: signal + computed(fn, [deps]) + keyed bindList, no VDOM, no auto-tracking. Every reactive edge is a visible call, so its three mistakes are static lints (NF-C021/C022/C023) with a fix recipe - the same closed loop that makes the backend AI-safe, now on the frontend.
|
|
1379
|
+
|
|
1380
|
+
`@nifrajs/web/nano` is the middle lane between a static
|
|
1381
|
+
[island](/docs/islands) and a full framework adapter. It gives you a signal, a
|
|
1382
|
+
derived `computed`, and a keyed list - enough to build a small app with local
|
|
1383
|
+
state a human edits - and nothing else. No virtual DOM, no template compiler, no
|
|
1384
|
+
auto-tracking. Every reactive edge is a call you write, which is exactly what lets a tool
|
|
1385
|
+
catch the mistakes before runtime.
|
|
1386
|
+
|
|
1387
|
+
### Why a fourth lane
|
|
1388
|
+
|
|
1389
|
+
A framework fails generated code not because it is unfamiliar but because its reactivity is
|
|
1390
|
+
_implicit_: an effect silently tracks what it read, a stale closure captures the wrong
|
|
1391
|
+
value, a render mismatches hydration - all silent, all runtime. Preact fixes the
|
|
1392
|
+
**size** of that model (3 KB) but copies its footguns faithfully. nano
|
|
1393
|
+
fixes the **failure model** for the small-app band: dependencies are an explicit
|
|
1394
|
+
array, list keys are a required argument, cleanups are a returned value. Each of those is a
|
|
1395
|
+
thing a static check can see. Reach for nano when a page needs local state and a keyed list;
|
|
1396
|
+
reach for a [framework adapter](/docs/frameworks) the moment you need client
|
|
1397
|
+
routing, nested view state, or suspense.
|
|
1398
|
+
|
|
1399
|
+
### Signals and computed
|
|
1400
|
+
|
|
1401
|
+
A `signal` holds a value; `.get()` reads it and `.set(...)`
|
|
1402
|
+
replaces it (deduped with `Object.is`). A `computed` derives a value and
|
|
1403
|
+
declares its sources as an explicit deps array - it recomputes when a listed source changes,
|
|
1404
|
+
never by magic. Both are synchronous and framework-free.
|
|
1405
|
+
|
|
1406
|
+
```ts
|
|
1407
|
+
import { signal, computed } from "@nifrajs/web/nano"
|
|
1408
|
+
|
|
1409
|
+
// State is a signal: reads are .get(), writes are .set(...). Every edge is a call you can see.
|
|
1410
|
+
const count = signal(0)
|
|
1411
|
+
|
|
1412
|
+
// Derived state declares its dependencies EXPLICITLY - the array is the whole contract. It
|
|
1413
|
+
// recomputes when (and only when) a listed source changes. Object.is-deduped, like signal.
|
|
1414
|
+
const doubled = computed(() => count.get() * 2, [count])
|
|
1415
|
+
|
|
1416
|
+
const off = doubled.subscribe((v) => console.log("doubled is now", v))
|
|
1417
|
+
count.set(5) // logs: doubled is now 10
|
|
1418
|
+
off() // unsubscribe
|
|
1419
|
+
```
|
|
1420
|
+
|
|
1421
|
+
The deps array is the whole contract, and its one failure mode is catchable: a
|
|
1422
|
+
`computed` whose body reads a signal the array omits will never recompute when that
|
|
1423
|
+
signal changes. `nifra check` flags exactly that as `NF-C023` - the
|
|
1424
|
+
check reads which signals the body calls `.get()` on and compares them to the
|
|
1425
|
+
array. A framework's auto-tracked effect gives a tool nothing to compare, which is why
|
|
1426
|
+
the equivalent lint elsewhere is a best-effort warning, not a gate.
|
|
1427
|
+
|
|
1428
|
+
### Bind a signal to the DOM
|
|
1429
|
+
|
|
1430
|
+
`bind` is the one-value edge: it applies your function immediately and on every
|
|
1431
|
+
change, and returns a disposer. **Collect the disposer.** A bare
|
|
1432
|
+
`bind(...)` whose return value is discarded leaks its subscription on soft-nav -
|
|
1433
|
+
`nifra check` flags it as `NF-C021`.
|
|
1434
|
+
|
|
1435
|
+
```ts
|
|
1436
|
+
// doc-check: skip - browser DOM enhancer, typechecked in @nifrajs/web under its DOM lib.
|
|
1437
|
+
import { signal, bind } from "@nifrajs/web/nano"
|
|
1438
|
+
|
|
1439
|
+
const label = signal("hello")
|
|
1440
|
+
|
|
1441
|
+
// bind applies immediately AND on every change; it returns the disposer. COLLECT it - a bare
|
|
1442
|
+
// bind(...) that drops its return leaks the subscription on soft-nav (nifra check flags NF-C021).
|
|
1443
|
+
const off = bind(document.querySelector("h1")!, label, (el, v) => { el.textContent = v })
|
|
1444
|
+
label.set("world") // the <h1> updates synchronously
|
|
1445
|
+
// ...on teardown: off()
|
|
1446
|
+
```
|
|
1447
|
+
|
|
1448
|
+
### Keyed lists with bindList
|
|
1449
|
+
|
|
1450
|
+
`bindList` keeps a container's children in sync with an array by key - a keyed
|
|
1451
|
+
reconcile like a framework's list diff, but you spell the key out. Add, remove, and
|
|
1452
|
+
reorder reuse the matching node (preserving focus and scroll) instead of rebuilding the list.
|
|
1453
|
+
Key by a **stable id** on the item; keying by the array index reuses the wrong
|
|
1454
|
+
node on reorder, and `nifra check` flags it as `NF-C022`.
|
|
1455
|
+
|
|
1456
|
+
```ts
|
|
1457
|
+
// doc-check: skip - browser DOM enhancer, typechecked in @nifrajs/web under its DOM lib.
|
|
1458
|
+
import { signal, bindList } from "@nifrajs/web/nano"
|
|
1459
|
+
|
|
1460
|
+
interface Todo { id: string; text: string; done: boolean }
|
|
1461
|
+
const todos = signal<Todo[]>([])
|
|
1462
|
+
|
|
1463
|
+
// bindList keeps a container's children in sync with an array by KEY - a keyed reconcile, like a
|
|
1464
|
+
// framework's list diff, but explicit. Add/remove/reorder reuse the right node instead of rebuilding.
|
|
1465
|
+
const off = bindList(todos, document.querySelector("ul")!, {
|
|
1466
|
+
key: (t) => t.id, // a STABLE id on the item. Keying by the array index is NF-C022 - reorder breaks.
|
|
1467
|
+
create: (t) => { const li = document.createElement("li"); li.dataset.id = t.id; return li },
|
|
1468
|
+
update: (li, t) => { li.textContent = t.text; li.classList.toggle("done", t.done) },
|
|
1469
|
+
})
|
|
1470
|
+
|
|
1471
|
+
todos.set([...todos.get(), { id: crypto.randomUUID(), text: "buy milk", done: false }])
|
|
1472
|
+
// ...on teardown: off()
|
|
1473
|
+
```
|
|
1474
|
+
|
|
1475
|
+
### Async state with resource
|
|
1476
|
+
|
|
1477
|
+
`resource(fetcher, [deps])` is nano's answer to “suspense” - an
|
|
1478
|
+
async cell whose value is an explicit `{ status, value, error }` union.
|
|
1479
|
+
It runs the fetcher immediately and again whenever a declared dep changes, and it handles the
|
|
1480
|
+
two things people get wrong by hand: the fetcher receives an `AbortSignal`, and a
|
|
1481
|
+
superseded request is aborted with its late result dropped, so the newest fetch always wins -
|
|
1482
|
+
no stale-response flicker. There is no thrown promise and no magic boundary; it is a value you
|
|
1483
|
+
read or bind like any other.
|
|
1484
|
+
|
|
1485
|
+
```ts
|
|
1486
|
+
import { signal, resource } from "@nifrajs/web/nano"
|
|
1487
|
+
|
|
1488
|
+
const userId = signal(1)
|
|
1489
|
+
|
|
1490
|
+
// resource(fetcher, [deps]) is an async cell: it fetches immediately and again whenever a declared
|
|
1491
|
+
// dep changes. The fetcher gets an AbortSignal; a superseded fetch is aborted and its late result
|
|
1492
|
+
// dropped, so the newest request always wins - no stale-response flicker to hand-guard.
|
|
1493
|
+
const user = resource(async (sig) => {
|
|
1494
|
+
const res = await fetch(`/api/users/${userId.get()}`, { signal: sig })
|
|
1495
|
+
return (await res.json()) as { name: string }
|
|
1496
|
+
}, [userId])
|
|
1497
|
+
|
|
1498
|
+
// The value is an explicit union - status is "pending" | "error" | "ready", never a secret undefined.
|
|
1499
|
+
const off = user.subscribe((s) => {
|
|
1500
|
+
if (s.status === "ready") console.log("got", s.value.name)
|
|
1501
|
+
})
|
|
1502
|
+
userId.set(2) // refetches; the deps array is what NF-C023 checks against the fetcher's .get() reads
|
|
1503
|
+
// ...on teardown: off()
|
|
1504
|
+
```
|
|
1505
|
+
|
|
1506
|
+
The deps array is checked exactly like `computed`: a `resource` whose
|
|
1507
|
+
fetcher reads a signal the array omits won't refetch when it changes, and
|
|
1508
|
+
`nifra check` flags it as `NF-C023`. Bind it to the DOM with
|
|
1509
|
+
`bindResource`, which dispatches on `status` - one handler per state,
|
|
1510
|
+
`ready` required, so a still-loading value can never render as a stray
|
|
1511
|
+
`undefined`.
|
|
1512
|
+
|
|
1513
|
+
```ts
|
|
1514
|
+
// doc-check: skip - browser DOM enhancer, typechecked in @nifrajs/web under its DOM lib.
|
|
1515
|
+
import { signal, resource, bindResource } from "@nifrajs/web/nano"
|
|
1516
|
+
|
|
1517
|
+
const userId = signal(1)
|
|
1518
|
+
const user = resource(async (sig) => {
|
|
1519
|
+
const res = await fetch(`/api/users/${userId.get()}`, { signal: sig })
|
|
1520
|
+
return (await res.json()) as { name: string }
|
|
1521
|
+
}, [userId])
|
|
1522
|
+
|
|
1523
|
+
// bindResource dispatches on status - one handler per state, ready required. Like bind it returns a
|
|
1524
|
+
// disposer (a bare bindResource(...) that drops it is NF-C021).
|
|
1525
|
+
const off = bindResource(document.querySelector("[data-user]")!, user, {
|
|
1526
|
+
pending: (el) => { el.textContent = "Loading…" },
|
|
1527
|
+
ready: (el, u) => { el.textContent = u.name },
|
|
1528
|
+
error: (el) => { el.textContent = "Could not load user" },
|
|
1529
|
+
})
|
|
1530
|
+
// ...on teardown: off()
|
|
1531
|
+
```
|
|
1532
|
+
|
|
1533
|
+
### nano inside an island
|
|
1534
|
+
|
|
1535
|
+
nano owns state and DOM edges; an [island](/docs/islands) owns mount and teardown.
|
|
1536
|
+
Put the signals in the enhancer, collect every disposer, and return one cleanup that calls
|
|
1537
|
+
them all. Scaffold this shape with
|
|
1538
|
+
`nifra_scaffold { path, variant: "stateful" }` on a vanilla
|
|
1539
|
+
project - it emits the golden pattern below.
|
|
1540
|
+
|
|
1541
|
+
```ts
|
|
1542
|
+
// doc-check: skip - browser DOM enhancer, typechecked in @nifrajs/web under its DOM lib.
|
|
1543
|
+
import { defineIsland, mountIslands } from "@nifrajs/web/islands"
|
|
1544
|
+
import { signal, computed, bind, bindList } from "@nifrajs/web/nano"
|
|
1545
|
+
|
|
1546
|
+
interface Todo { id: string; text: string; done: boolean }
|
|
1547
|
+
|
|
1548
|
+
// nano lives INSIDE an island - the island owns mount/teardown, nano owns the state and the DOM edges.
|
|
1549
|
+
const todos = defineIsland<{ items: Todo[] }>((el, props) => {
|
|
1550
|
+
const items = signal<Todo[]>(props.items)
|
|
1551
|
+
const remaining = computed(() => items.get().filter((t) => !t.done).length, [items])
|
|
1552
|
+
|
|
1553
|
+
// Collect every disposer; the island's cleanup calls them all (this is what NF-C021 protects).
|
|
1554
|
+
const cleanups: Array<() => void> = []
|
|
1555
|
+
cleanups.push(bind(el.querySelector("[data-count]")!, remaining, (n, v) => {
|
|
1556
|
+
n.textContent = String(v) + " left"
|
|
1557
|
+
}))
|
|
1558
|
+
cleanups.push(bindList(items, el.querySelector("[data-list]")!, {
|
|
1559
|
+
key: (t) => t.id,
|
|
1560
|
+
create: (t) => { const li = document.createElement("li"); li.dataset.id = t.id; return li },
|
|
1561
|
+
update: (li, t) => { li.textContent = t.text; li.classList.toggle("done", t.done) },
|
|
1562
|
+
}))
|
|
1563
|
+
|
|
1564
|
+
const add = (text: string) =>
|
|
1565
|
+
items.set([...items.get(), { id: crypto.randomUUID(), text, done: false }])
|
|
1566
|
+
void add
|
|
1567
|
+
|
|
1568
|
+
return () => { for (const off of cleanups) off() }
|
|
1569
|
+
})
|
|
1570
|
+
|
|
1571
|
+
mountIslands({ todos })
|
|
1572
|
+
```
|
|
1573
|
+
|
|
1574
|
+
### The three checks
|
|
1575
|
+
|
|
1576
|
+
nano's explicitness is the whole point: because each reactive edge is a visible call, its
|
|
1577
|
+
three mistakes are static lints with a fix recipe - the same closed loop (`scaffold`
|
|
1578
|
+
→ `check` → `fix` → `verify`) that makes the
|
|
1579
|
+
backend AI-safe, now on the frontend.
|
|
1580
|
+
|
|
1581
|
+
-
|
|
1582
|
+
`NF-C021` - a `bind`/`bindList` whose disposer is
|
|
1583
|
+
discarded. Collect it; call it on teardown.
|
|
1584
|
+
|
|
1585
|
+
-
|
|
1586
|
+
`NF-C022` - a `bindList` keyed by the array index. Key by a stable id.
|
|
1587
|
+
|
|
1588
|
+
-
|
|
1589
|
+
`NF-C023` - a `computed` that reads a signal its deps omit. Add it to
|
|
1590
|
+
the deps array.
|
|
1591
|
+
|
|
1592
|
+
All three _warn_ - a false positive must never fail a build - and each carries a fix
|
|
1593
|
+
recipe an agent can apply. Where nano stops (client routing, nested views, suspense), stop
|
|
1594
|
+
adding nano and reach for `@nifrajs/web-preact` or another framework adapter.
|
|
1595
|
+
|
|
1228
1596
|
## Nifra - Streaming
|
|
1229
1597
|
|
|
1230
1598
|
> Streaming SSR, Suspense, and defer() in Nifra - on every runtime including the edge.
|
|
@@ -1607,6 +1975,8 @@ Node against the outcome's plain header record on the **direct socket writer**,
|
|
|
1607
1975
|
ever materializing Web `Request`/`Response` objects:
|
|
1608
1976
|
|
|
1609
1977
|
```ts
|
|
1978
|
+
import { responseObserver } from "@nifrajs/core/response-observer"
|
|
1979
|
+
import { server } from "@nifrajs/core/server"
|
|
1610
1980
|
import type { Middleware } from "@nifrajs/core/server"
|
|
1611
1981
|
|
|
1612
1982
|
// ONE implementation, fast on every runtime: on Bun/Deno it mutates the
|
|
@@ -1619,6 +1989,8 @@ export function serverName(value: string): Middleware {
|
|
|
1619
1989
|
},
|
|
1620
1990
|
}
|
|
1621
1991
|
}
|
|
1992
|
+
|
|
1993
|
+
const app = server().use(responseObserver()).use(serverName("nifra"))
|
|
1622
1994
|
```
|
|
1623
1995
|
|
|
1624
1996
|
Why this matters on Node: a full `onResponse(res: Response)` hook needs real Web
|
|
@@ -2799,9 +3171,10 @@ createWebApp({ /* … */ api: sessions }) // inject the manager
|
|
|
2799
3171
|
|
|
2800
3172
|
### Guard a route
|
|
2801
3173
|
|
|
2802
|
-
`requireSession` / `requireUser` throw a `
|
|
2803
|
-
`redirectTo`, or a 401) when the session is missing - Nifra
|
|
2804
|
-
as-is, so the guard short-circuits the loader.
|
|
3174
|
+
`requireSession` / `requireUser` throw a `status(...)` render
|
|
3175
|
+
(a 302 to `redirectTo`, or a 401) when the session is missing - Nifra renders a
|
|
3176
|
+
thrown control-flow value as-is, so the guard short-circuits the loader. It is plain data, not
|
|
3177
|
+
a `Response`: same bytes on the wire, on the lane an ordinary return takes.
|
|
2805
3178
|
|
|
2806
3179
|
```ts
|
|
2807
3180
|
// doc-check: skip - fragment: `api` is the session manager createWebApp injected (see setup above).
|
|
@@ -2962,6 +3335,7 @@ const image = createImageHandler({
|
|
|
2962
3335
|
root: "./public", // local sources resolve under here (traversal+symlink guarded)
|
|
2963
3336
|
allowedOrigins: ["https://cdn.example"], // remote sources: allowlist only (omit ⇒ none)
|
|
2964
3337
|
// maxWidth, maxSourceBytes, maxSourcePixels, concurrency, cacheMaxAge - all tunable
|
|
3338
|
+
// immutable: true, // only for content-versioned source URLs
|
|
2965
3339
|
})
|
|
2966
3340
|
|
|
2967
3341
|
// mount it in your router:
|
|
@@ -2984,9 +3358,10 @@ probe), and a concurrency semaphore bounding the CPU-heavy codec work.
|
|
|
2984
3358
|
|
|
2985
3359
|
-
|
|
2986
3360
|
**Correct + cacheable.** Never upscales past the intrinsic width; negotiates WebP via
|
|
2987
|
-
`Accept` (with `Vary: Accept`);
|
|
2988
|
-
`
|
|
2989
|
-
|
|
3361
|
+
`Accept` (with `Vary: Accept`); and hashes the emitted bytes for a strong
|
|
3362
|
+
`ETag`, so a changed source at the same URL cannot receive a false `304`.
|
|
3363
|
+
The mutable-safe default is a one-hour `max-age`; opt into `immutable` only
|
|
3364
|
+
when every source URL is content-versioned.
|
|
2990
3365
|
|
|
2991
3366
|
The handler reads the filesystem, so its _local-source_ path targets **Node/Bun servers**
|
|
2992
3367
|
- but the codec itself is a pluggable `ImageBackend`, so it runs anywhere (see below).
|
|
@@ -3422,6 +3797,28 @@ app.ws("/chat", {
|
|
|
3422
3797
|
})
|
|
3423
3798
|
```
|
|
3424
3799
|
|
|
3800
|
+
### Optional outbound validation
|
|
3801
|
+
|
|
3802
|
+
`sendSchema` is type-level by default: it documents and types what the client
|
|
3803
|
+
receives with no runtime cost. Set `validateSend: true` to check server-sent JSON
|
|
3804
|
+
text and UTF-8 binary frames before the native socket sends them. Invalid frames and async
|
|
3805
|
+
validators fail closed and route a diagnostic to `error` when present. This is a
|
|
3806
|
+
contract check for your own output, not an inbound security boundary; the flag requires a
|
|
3807
|
+
`sendSchema` and is intentionally off by default.
|
|
3808
|
+
|
|
3809
|
+
```ts
|
|
3810
|
+
// doc-check: skip - illustrative: outbound contract on an existing app.
|
|
3811
|
+
import { t } from "@nifrajs/schema"
|
|
3812
|
+
|
|
3813
|
+
app.ws("/events", {
|
|
3814
|
+
sendSchema: t.Object({ kind: t.Literal("ready"), id: t.String() }),
|
|
3815
|
+
validateSend: true, // opt in; default remains type-level only
|
|
3816
|
+
open(ws) {
|
|
3817
|
+
ws.send(JSON.stringify({ kind: "ready", id: "evt-1" }))
|
|
3818
|
+
},
|
|
3819
|
+
})
|
|
3820
|
+
```
|
|
3821
|
+
|
|
3425
3822
|
### Pub/sub - app.publish
|
|
3426
3823
|
|
|
3427
3824
|
`ws.subscribe(topic)` joins a topic; `app.publish(topic, data)`
|
|
@@ -3792,6 +4189,48 @@ export const vitePlugins = [react()] // dev HMR (Fast Refresh)
|
|
|
3792
4189
|
// define = { __VUE_OPTIONS_API__: "true", ... } // Vue feature flags
|
|
3793
4190
|
```
|
|
3794
4191
|
|
|
4192
|
+
### Tailwind to StyleX
|
|
4193
|
+
|
|
4194
|
+
Nifra includes a conservative codemod for moving static Tailwind classes to StyleX. It is a dry
|
|
4195
|
+
run by default, so inspect the proposed edits first:
|
|
4196
|
+
|
|
4197
|
+
Supported static `className` attributes become `stylex.props(...)` calls
|
|
4198
|
+
backed by a local `stylex.create(...)` table. Responsive breakpoints and
|
|
4199
|
+
element-local pseudo-classes such as `hover:` are supported. Dynamic class
|
|
4200
|
+
expressions, arbitrary values, parent-dependent variants, and unknown utilities stay unchanged
|
|
4201
|
+
and are reported with file/line evidence. A non-zero exit status means manual migration issues
|
|
4202
|
+
remain.
|
|
4203
|
+
|
|
4204
|
+
StyleX compilation is native to Nifra's Bun pipeline. Install the runtime and compiler peers,
|
|
4205
|
+
then register both the browser and SSR transforms:
|
|
4206
|
+
|
|
4207
|
+
```ts
|
|
4208
|
+
# Install the runtime and the optional compiler peers.
|
|
4209
|
+
bun add @stylexjs/stylex
|
|
4210
|
+
bun add -d @babel/core @stylexjs/babel-plugin @babel/plugin-syntax-flow \
|
|
4211
|
+
@babel/plugin-syntax-jsx @babel/plugin-syntax-typescript
|
|
4212
|
+
```
|
|
4213
|
+
|
|
4214
|
+
```ts
|
|
4215
|
+
// nifra.config.ts - Bun's client and SSR build transforms.
|
|
4216
|
+
import { stylexBunPlugin } from "@nifrajs/web/plugins/stylex"
|
|
4217
|
+
|
|
4218
|
+
export const clientPlugins = [stylexBunPlugin("dom")]
|
|
4219
|
+
export const serverPlugins = [stylexBunPlugin("ssr")]
|
|
4220
|
+
```
|
|
4221
|
+
|
|
4222
|
+
If the project intentionally uses Vite, add the Vite adapter alongside its existing Vite
|
|
4223
|
+
transforms. Nifra will use Vite when `vitePlugins` are the app's only transforms:
|
|
4224
|
+
|
|
4225
|
+
```ts
|
|
4226
|
+
// doc-check: skip - requires the third-party Vite React plugin
|
|
4227
|
+
// If the app intentionally uses Vite, keep StyleX in vitePlugins.
|
|
4228
|
+
import react from "@vitejs/plugin-react"
|
|
4229
|
+
import { stylexVite } from "@nifrajs/web/plugins/stylex"
|
|
4230
|
+
|
|
4231
|
+
export const vitePlugins = [react(), stylexVite()]
|
|
4232
|
+
```
|
|
4233
|
+
|
|
3795
4234
|
### Scope
|
|
3796
4235
|
|
|
3797
4236
|
`nifra build` defaults to a self-hosted Bun server. Use `--target node`,
|
|
@@ -3801,7 +4240,7 @@ the command printed by the build.
|
|
|
3801
4240
|
|
|
3802
4241
|
## Nifra - Coding agents
|
|
3803
4242
|
|
|
3804
|
-
>
|
|
4243
|
+
> Nifra's agent layer: live MCP tools for coding agents, bounded typed turns, resumable evidence, a coding-agent host, browser views, A2A and AG-UI bridges, and token-only telemetry.
|
|
3805
4244
|
|
|
3806
4245
|
Nifra ships an MCP server. It is not a documentation lookup bolted onto a framework: an agent
|
|
3807
4246
|
can read the project, learn the real API, run actual requests against the backend it just
|
|
@@ -3966,8 +4405,8 @@ nifra levels --min 1
|
|
|
3966
4405
|
|
|
3967
4406
|
### Building agent features, not just serving them
|
|
3968
4407
|
|
|
3969
|
-
The tools above let an agent work on your app.
|
|
3970
|
-
the app you are building is itself an AI feature.
|
|
4408
|
+
The tools above let an agent work on your app. Nifra also provides provider-neutral building
|
|
4409
|
+
blocks for the opposite case, where the app you are building is itself an AI feature.
|
|
3971
4410
|
|
|
3972
4411
|
**
|
|
3973
4412
|
`@nifrajs/prompt`
|
|
@@ -4009,6 +4448,99 @@ serves a SQLite database as its own MCP server, fail-closed: allowlisted schema
|
|
|
4009
4448
|
default, and read-only queries only when you opt in, with plan verification. Handing a model a
|
|
4010
4449
|
database connection is not the same as handing it a query tool, and this is the second one.
|
|
4011
4450
|
|
|
4451
|
+
### Run a coding agent
|
|
4452
|
+
|
|
4453
|
+
`@nifrajs/agent-protocol` is the small versioned session and event contract.
|
|
4454
|
+
`@nifrajs/coding-agent` provides the standalone `nifra-agent` host with
|
|
4455
|
+
bounded sessions, checkpoints, workflows, extensions, verification, and authenticated local
|
|
4456
|
+
RPC. `@nifrajs/pi` is an optional Pi backend; other backends implement the same
|
|
4457
|
+
protocol port.
|
|
4458
|
+
|
|
4459
|
+
```ts
|
|
4460
|
+
bun add @nifrajs/coding-agent @nifrajs/pi
|
|
4461
|
+
|
|
4462
|
+
# Interactive, one-shot, JSON, and local RPC modes are available.
|
|
4463
|
+
bunx nifra-agent --backend pi
|
|
4464
|
+
bunx nifra-agent --backend pi --message "run the checks and explain failures"
|
|
4465
|
+
```
|
|
4466
|
+
|
|
4467
|
+
The public host keeps live queues and captured evidence bounded, filters verification process
|
|
4468
|
+
environments, and treats extensions as an explicit opt-in. The local process adapter and
|
|
4469
|
+
extension worker are crash-containment helpers, not hostile-code sandboxes.
|
|
4470
|
+
|
|
4471
|
+
### Expose the same agent to other clients
|
|
4472
|
+
|
|
4473
|
+
`@nifrajs/a2a` mounts an A2A 1.0 card and JSON-RPC/SSE binding.
|
|
4474
|
+
`@nifrajs/ag-ui` mounts the AG-UI event stream. Both drive the same bounded runner,
|
|
4475
|
+
compose step evidence with telemetry, and support typed human-in-the-loop continuation. Model
|
|
4476
|
+
ports, state stores, capabilities, and approval transports are injected per request.
|
|
4477
|
+
|
|
4478
|
+
```ts
|
|
4479
|
+
import { server } from "@nifrajs/core"
|
|
4480
|
+
import { mountA2A } from "@nifrajs/a2a"
|
|
4481
|
+
import { mountAgUI } from "@nifrajs/ag-ui"
|
|
4482
|
+
import type { AgentPorts } from "@nifrajs/agent"
|
|
4483
|
+
import { agent } from "./agent"
|
|
4484
|
+
|
|
4485
|
+
declare const myModelPort: AgentPorts["model"]
|
|
4486
|
+
declare const myStateStore: NonNullable<AgentPorts["state"]>
|
|
4487
|
+
|
|
4488
|
+
const app = server()
|
|
4489
|
+
const ports = () => ({
|
|
4490
|
+
model: myModelPort,
|
|
4491
|
+
capabilities: ["search.read"],
|
|
4492
|
+
state: myStateStore, // scope this to the request subject
|
|
4493
|
+
})
|
|
4494
|
+
|
|
4495
|
+
mountA2A(app, {
|
|
4496
|
+
agent,
|
|
4497
|
+
card: { url: "https://api.example.com/a2a", version: "1.0.0" },
|
|
4498
|
+
ports,
|
|
4499
|
+
})
|
|
4500
|
+
mountAgUI(app, { agent, ports })
|
|
4501
|
+
|
|
4502
|
+
// A2A: GET the card, POST JSON-RPC, optional SSE streaming.
|
|
4503
|
+
// AG-UI: POST RunAgentInput, receive the event stream over SSE.
|
|
4504
|
+
```
|
|
4505
|
+
|
|
4506
|
+
These mounts deliberately do not authenticate callers: put the route behind your application's
|
|
4507
|
+
auth and authorization middleware, and scope every injected port to the request subject.
|
|
4508
|
+
|
|
4509
|
+
### Browser views and the Workbench
|
|
4510
|
+
|
|
4511
|
+
`@nifrajs/agent-app` is a backend-free browser SDK for negotiated commands, ordered
|
|
4512
|
+
and resumable event streams, approvals, handoffs, and Run Studio projections. Its public views
|
|
4513
|
+
contain structure - statuses, counters, coordinates, and error codes - rather than prompts,
|
|
4514
|
+
tool payloads, model output, or filesystem paths. The optional Workbench uses that same surface:
|
|
4515
|
+
run `bun run --filter '@nifrajs/workbench' dev -- --cwd /path/to/project` for the
|
|
4516
|
+
local browser client.
|
|
4517
|
+
|
|
4518
|
+
```ts
|
|
4519
|
+
import { AgentAppClient, HttpAgentTransport } from "@nifrajs/agent-app"
|
|
4520
|
+
|
|
4521
|
+
declare function currentToken(): string
|
|
4522
|
+
declare function render(view: unknown): void
|
|
4523
|
+
|
|
4524
|
+
const client = new AgentAppClient(new HttpAgentTransport({
|
|
4525
|
+
endpoint: "http://127.0.0.1:8787",
|
|
4526
|
+
authorize: () => currentToken(), // minted per request; never stored by the transport
|
|
4527
|
+
}))
|
|
4528
|
+
|
|
4529
|
+
const session = await client.createSession()
|
|
4530
|
+
for await (const view of client.send("summarize the diff")) {
|
|
4531
|
+
render(view) // content-free status, counts, coordinates, and error codes
|
|
4532
|
+
}
|
|
4533
|
+
```
|
|
4534
|
+
|
|
4535
|
+
### Evidence, streaming, and telemetry
|
|
4536
|
+
|
|
4537
|
+
`@nifrajs/agent` runs bounded typed turns with tool contracts, budgets, approvals,
|
|
4538
|
+
resumable token-only evidence, model deltas, and a transient shared-state channel. Add an
|
|
4539
|
+
`evidenceLog` to the HTTP seams for SSE replay after a dropped connection; replay
|
|
4540
|
+
resumes evidence and never re-executes the turn. `@nifrajs/agent-telemetry` converts
|
|
4541
|
+
the same constrained evidence into fail-open OpenTelemetry run and step spans. Providers,
|
|
4542
|
+
credentials, durable storage, retention, and tenant policy remain application-owned ports.
|
|
4543
|
+
|
|
4012
4544
|
### Projects without a web config
|
|
4013
4545
|
|
|
4014
4546
|
A backend-only project - the shape `create-nifra`'s default template produces - has
|
|
@@ -4654,9 +5186,9 @@ global state; a second copy nulls it out and every hook throws.
|
|
|
4654
5186
|
|
|
4655
5187
|
Nifra **dedupes React** in both the production build and the Vite dev server, so
|
|
4656
5188
|
the framework itself won't load two copies. The usual culprit is a
|
|
4657
|
-
**`file:`-linked package** (a local component
|
|
4658
|
-
`bun link` or reference with `
|
|
4659
|
-
its own `node_modules
|
|
5189
|
+
**`file:`- or `link:`-linked package** (a local component
|
|
5190
|
+
library you `bun link` or reference with `link:../lib`) that bundles its
|
|
5191
|
+
own React in its own `node_modules`. Fix the install first, if you can:
|
|
4660
5192
|
|
|
4661
5193
|
-
|
|
4662
5194
|
Make React a **peer dependency** of the linked package (not a regular
|
|
@@ -4672,6 +5204,70 @@ copy.
|
|
|
4672
5204
|
Delete the linked package's nested `node_modules/react` after linking if your
|
|
4673
5205
|
package manager duplicated it.
|
|
4674
5206
|
|
|
5207
|
+
#### When the duplicate can't be installed away: declare it single-copy
|
|
5208
|
+
|
|
5209
|
+
A `link:` dependency on a **separate checkout** is the case none of the
|
|
5210
|
+
above reaches. The linked package's files live in the other repo, so Node and Bun resolve their
|
|
5211
|
+
imports from _that_ repo's real path - and that repo's install owns its
|
|
5212
|
+
`node_modules`. Peer deps don't help (the copy is already installed there),
|
|
5213
|
+
`overrides` don't help (they govern your install, not theirs), and deleting the
|
|
5214
|
+
nested copy is undone by the next install in the sibling repo. Only a resolver can answer this:
|
|
5215
|
+
the walk has to be intercepted, not rearranged.
|
|
5216
|
+
|
|
5217
|
+
Declare the packages in your app's `package.json`. It is a **static**
|
|
5218
|
+
declaration on purpose - `nifra check` reads it without importing your config, so
|
|
5219
|
+
the preflight never executes app code:
|
|
5220
|
+
|
|
5221
|
+
```ts
|
|
5222
|
+
{
|
|
5223
|
+
"name": "my-app",
|
|
5224
|
+
"dependencies": {
|
|
5225
|
+
"react": "19.2.8",
|
|
5226
|
+
"@example/ui": "link:../design-system/packages/ui"
|
|
5227
|
+
},
|
|
5228
|
+
"nifra": {
|
|
5229
|
+
"singleCopy": ["react", "react-dom", "@nifrajs/*"]
|
|
5230
|
+
}
|
|
5231
|
+
}
|
|
5232
|
+
```
|
|
5233
|
+
|
|
5234
|
+
`"singleCopy": true` is shorthand for Nifra's built-in identity-sensitive set:
|
|
5235
|
+
`@nifrajs/*`, `react`, `react-dom`, `preact`,
|
|
5236
|
+
`solid-js`, `svelte`, `vue`. Entries may be exact names or a
|
|
5237
|
+
`@scope/*` pattern. `@nifrajs/*` belongs in this set for the same reason
|
|
5238
|
+
React does: two copies of `@nifrajs/core` are two distinct `Server`
|
|
5239
|
+
classes, so `.merge()` stops accepting an app built against the other one.
|
|
5240
|
+
|
|
5241
|
+
**The build honours the declaration on its own** -
|
|
5242
|
+
`buildClient` and `buildServer` inject the resolver, so bundled output
|
|
5243
|
+
already loads one copy. Unbundled phases do not: Bun's _runtime_ resolver never offers a
|
|
5244
|
+
bare specifier to a plugin, so `bun test`, `bun run`, and preloaded
|
|
5245
|
+
scripts still load both copies unless you preload the registrar:
|
|
5246
|
+
|
|
5247
|
+
```ts
|
|
5248
|
+
# bunfig.toml
|
|
5249
|
+
preload = ["@nifrajs/core/single-copy/register"]
|
|
5250
|
+
|
|
5251
|
+
[test]
|
|
5252
|
+
preload = ["@nifrajs/core/single-copy/register"]
|
|
5253
|
+
```
|
|
5254
|
+
|
|
5255
|
+
Both sections matter, and they are independent: `preload` covers
|
|
5256
|
+
`bun run`, `[test].preload` covers `bun test`. Declaring
|
|
5257
|
+
without preloading is a real state, not a mistake -
|
|
5258
|
+
`nifra check` reports it and names the phase left uncovered.
|
|
5259
|
+
|
|
5260
|
+
**What it will not do:** redirect across _versions_. If the two copies are
|
|
5261
|
+
`19.2.7` and `19.2.8`, the redirect is skipped and
|
|
5262
|
+
`nifra check` still fails with `version-skew`. Silently collapsing a
|
|
5263
|
+
version difference would trade a loud install problem for a quiet behavioural one; align the
|
|
5264
|
+
ranges instead.
|
|
5265
|
+
|
|
5266
|
+
A declared duplicate is **reported, not suppressed**.
|
|
5267
|
+
`nifra check` keeps printing the copies as a warning and
|
|
5268
|
+
`nifra doctor` lists them under "deduplicated by declaration", so the topology stays
|
|
5269
|
+
visible - it just stops being fatal.
|
|
5270
|
+
|
|
4675
5271
|
[!NOTE]
|
|
4676
5272
|
|
|
4677
5273
|
This applies to every framework with module-global render state, not just React (Preact,
|
|
@@ -5339,9 +5935,9 @@ export const hydrate = false // opt out of full-document hydration (static / i
|
|
|
5339
5935
|
export default function User(props) { /* props.data, props.actionData, props.params */ }
|
|
5340
5936
|
```
|
|
5341
5937
|
|
|
5342
|
-
[!NOTE] An `action` may return a
|
|
5343
|
-
|
|
5344
|
-
`actionData`.
|
|
5938
|
+
[!NOTE] An `action` may return a control-flow value - a `redirect()` or a
|
|
5939
|
+
`status(...)` render, or a hand-rolled `Response` - and it's passed
|
|
5940
|
+
through untouched. Any other return is serialized as `actionData`.
|
|
5345
5941
|
|
|
5346
5942
|
### Two ways to handle a request
|
|
5347
5943
|
|
|
@@ -6434,6 +7030,94 @@ If capabilities are configured, review a new snapshot and run
|
|
|
6434
7030
|
Exercise authentication, redirects, backend mounting, SSE/WebSocket routes, and each deploy
|
|
6435
7031
|
adapter the application uses.
|
|
6436
7032
|
|
|
7033
|
+
## Nifra 3.0 migration guide - upgrade from 2.x
|
|
7034
|
+
|
|
7035
|
+
> Upgrade a Nifra 2.x application to 3.0: automated dependency pins, the plain-data redirect return value, the frozen reserved typed-client segment keys and their codemod, the Node proxy transport default, and the release gates.
|
|
7036
|
+
|
|
7037
|
+
Nifra 3.0 makes a redirect the same plain-data value an ordinary return is, and freezes the
|
|
7038
|
+
reserved typed-client segment keys into a published contract. The upgrade command handles the
|
|
7039
|
+
deterministic dependency pins; this guide covers the two structural changes it deliberately
|
|
7040
|
+
cannot guess, plus the Node proxy transport default.
|
|
7041
|
+
|
|
7042
|
+
### 1. Run the executable upgrade
|
|
7043
|
+
|
|
7044
|
+
```ts
|
|
7045
|
+
|
|
7046
|
+
```
|
|
7047
|
+
|
|
7048
|
+
The command pins every matching `@nifrajs/*`, `Nifra`, and
|
|
7049
|
+
`create-nifra` dependency to `3.0.0` while preserving
|
|
7050
|
+
caret/tilde/exact style. No package is removed and no import specifier moves this release, so
|
|
7051
|
+
the runner only pins. Dry-run is the default; `--write` applies and verifies with
|
|
7052
|
+
`nifra check`.
|
|
7053
|
+
|
|
7054
|
+
### 2. Read redirects as plain data
|
|
7055
|
+
|
|
7056
|
+
`redirect(...)` now returns the same plain render value `status(...)`
|
|
7057
|
+
produces, not a Web `Response`. Same bytes on the wire, now with a
|
|
7058
|
+
`content-length` on Node instead of a chunked empty body. It is still returned or
|
|
7059
|
+
thrown from the same places - loader, action, layout gate - and `return redirect()`
|
|
7060
|
+
/ `throw redirect()` stay interchangeable, including the client-submit conversion to
|
|
7061
|
+
a 204 with `X-Nifra-Redirect`.
|
|
7062
|
+
|
|
7063
|
+
**Breaking:** the value is no longer a `Response`, so
|
|
7064
|
+
`.status`, `.headers`, and `instanceof Response` are gone from
|
|
7065
|
+
it. Read `.plain`, build one with `toResponse()` when needed, pass headers
|
|
7066
|
+
through the second argument, and assert on `.plain` in tests. A hand-rolled
|
|
7067
|
+
`Response` from a loader or action is untouched - only what `redirect()`
|
|
7068
|
+
itself returns changed.
|
|
7069
|
+
|
|
7070
|
+
```ts
|
|
7071
|
+
|
|
7072
|
+
```
|
|
7073
|
+
|
|
7074
|
+
### 3. Fix reserved typed-client segments
|
|
7075
|
+
|
|
7076
|
+
The reserved proxy keys are now a frozen, published contract. A route whose static path
|
|
7077
|
+
segment spells one of them - an HTTP verb in any casing, or `subscribe`,
|
|
7078
|
+
`ws`, `index`, `then` - is unreachable by property access,
|
|
7079
|
+
because the proxy resolves the reserved key before a path segment. The types now reject that
|
|
7080
|
+
access at compile time instead of silently reaching the wrong node.
|
|
7081
|
+
|
|
7082
|
+
```ts
|
|
7083
|
+
|
|
7084
|
+
```
|
|
7085
|
+
|
|
7086
|
+
Run `nifra fix --code NF-C018` to rewrite the affected call sites. It reads them
|
|
7087
|
+
from the compiler rather than a text search, so it finds every one and never mistakes a real
|
|
7088
|
+
`.delete` verb call for a path segment; a site it cannot rewrite confidently
|
|
7089
|
+
(bracket access, a node held in a variable) is reported and left alone.
|
|
7090
|
+
`nifra routes` annotates a colliding route with the spelling that reaches it, in
|
|
7091
|
+
both the table and `--json`. The set is exported as the one place it is written down.
|
|
7092
|
+
|
|
7093
|
+
```ts
|
|
7094
|
+
|
|
7095
|
+
```
|
|
7096
|
+
|
|
7097
|
+
### 4. Review the Node proxy transport (only if you use it)
|
|
7098
|
+
|
|
7099
|
+
On Node, `@nifrajs/proxy` now defaults to the undici transport, shipped from the new
|
|
7100
|
+
`@nifrajs/proxy/undici` subpath. Pass an explicit `transport` to
|
|
7101
|
+
`createProxy` to override it.
|
|
7102
|
+
|
|
7103
|
+
```ts
|
|
7104
|
+
|
|
7105
|
+
```
|
|
7106
|
+
|
|
7107
|
+
### 5. Run the release gates
|
|
7108
|
+
|
|
7109
|
+
-
|
|
7110
|
+
Run `nifra check --json` and fix every error, including any remaining NF-C018.
|
|
7111
|
+
|
|
7112
|
+
-
|
|
7113
|
+
If the project has `nifra.assurance.ts`, run `nifra assure --json`.
|
|
7114
|
+
|
|
7115
|
+
- Run the application test suite and a production build.
|
|
7116
|
+
|
|
7117
|
+
-
|
|
7118
|
+
Exercise every redirect path - loader, action, and layout gate - and, if the app proxies,
|
|
7119
|
+
each deploy adapter it uses.
|
|
7120
|
+
|
|
6437
7121
|
## Nifra - Migrating from Express, Hono, Fastify & Elysia
|
|
6438
7122
|
|
|
6439
7123
|
> Move a backend to Nifra: routing, middleware, validation, and body parsing map directly from Express, Hono, Fastify, and Elysia - and you gain a typed client, multi-runtime deploy, and optional SSR.
|
|
@@ -7495,26 +8179,278 @@ level that regressed comes back with the reason it broke.
|
|
|
7495
8179
|
|
|
7496
8180
|
# Package reference (READMEs)
|
|
7497
8181
|
|
|
7498
|
-
## @nifrajs/
|
|
8182
|
+
## @nifrajs/a2a
|
|
7499
8183
|
|
|
7500
|
-
|
|
8184
|
+
Mount a nifra agent as an [Agent2Agent (A2A)](https://a2a-protocol.org) protocol server. The agent card is served on GET, the A2A 1.0 JSON-RPC binding on POST: `SendMessage` runs one bounded agent turn, `SendStreamingMessage` streams step evidence over SSE, `GetTask` projects the stored turn state.
|
|
7501
8185
|
|
|
7502
|
-
|
|
7503
|
-
and telemetry are ports. The package never imports a model vendor and its state adapter stores only
|
|
7504
|
-
token-only turn evidence.
|
|
8186
|
+
A protocol bridge over [`@nifrajs/agent`](../agent) - the request body reuses core's single bounded, prototype-guarded trust boundary, and the model, durable state store, and approval transport are injected per request through the same `ports` factory `mountAgent` uses. Dependency-free beyond the two nifra peers.
|
|
7505
8187
|
|
|
7506
|
-
|
|
7507
|
-
import { createAgentState, runAgent } from "@nifrajs/agent"
|
|
8188
|
+
## Install
|
|
7508
8189
|
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
8190
|
+
```bash
|
|
8191
|
+
bun add @nifrajs/a2a @nifrajs/agent
|
|
8192
|
+
```
|
|
8193
|
+
|
|
8194
|
+
## Mount
|
|
8195
|
+
|
|
8196
|
+
```ts
|
|
8197
|
+
import { server } from "@nifrajs/core"
|
|
8198
|
+
import { mountA2A } from "@nifrajs/a2a"
|
|
8199
|
+
import { agent } from "./agent" // an AgentDefinition
|
|
8200
|
+
|
|
8201
|
+
const app = server()
|
|
8202
|
+
mountA2A(app, {
|
|
8203
|
+
agent,
|
|
8204
|
+
card: { url: "https://api.example.com/a2a", version: "1.0.0" },
|
|
8205
|
+
ports: (c) => ({
|
|
8206
|
+
model: myModelPort, // scope to the request subject
|
|
8207
|
+
capabilities: ["search.read"],
|
|
8208
|
+
state: myStateStore, // required for GetTask and resume
|
|
8209
|
+
}),
|
|
8210
|
+
})
|
|
8211
|
+
// GET /.well-known/agent-card.json - the agent card
|
|
8212
|
+
// POST /a2a - SendMessage | SendStreamingMessage | GetTask
|
|
8213
|
+
```
|
|
8214
|
+
|
|
8215
|
+
## Task mapping
|
|
8216
|
+
|
|
8217
|
+
One A2A task is one agent turn: `taskId` is the runner's `turnId`.
|
|
8218
|
+
|
|
8219
|
+
| Run result | Task state |
|
|
8220
|
+
| --- | --- |
|
|
8221
|
+
| completed with output | `TASK_STATE_COMPLETED` + an `output` artifact |
|
|
8222
|
+
| completed with a typed error | `TASK_STATE_FAILED` (error in `metadata`) |
|
|
8223
|
+
| suspended (approval, budget, model, max turns) | `TASK_STATE_INPUT_REQUIRED` |
|
|
8224
|
+
| suspended (cancelled) | `TASK_STATE_CANCELED` |
|
|
8225
|
+
|
|
8226
|
+
Agent input is `message.metadata.input` when present, otherwise the first `text` part. Structured output returns as a `text` part carrying JSON.
|
|
8227
|
+
|
|
8228
|
+
## Human-in-the-loop resume
|
|
8229
|
+
|
|
8230
|
+
A suspended task's status message carries the pending continuation in `metadata`. Send it back to continue the same task - the runtime keeps state token-only, so a suspended tool's input must be replayed in `continuation.input`:
|
|
8231
|
+
|
|
8232
|
+
```jsonc
|
|
8233
|
+
{
|
|
8234
|
+
"jsonrpc": "2.0", "id": 2, "method": "SendMessage",
|
|
8235
|
+
"params": {
|
|
8236
|
+
"message": {
|
|
8237
|
+
"messageId": "m2", "role": "ROLE_USER", "parts": [],
|
|
8238
|
+
"taskId": "<task id from the suspension>",
|
|
8239
|
+
"metadata": {
|
|
8240
|
+
"input": { "prompt": "go" },
|
|
8241
|
+
"resume": {
|
|
8242
|
+
"continuation": { "kind": "approval", "tool": "search.read", "effectId": "…", "input": { "q": "…" } },
|
|
8243
|
+
"approval": { "granted": true }
|
|
8244
|
+
}
|
|
8245
|
+
}
|
|
8246
|
+
}
|
|
8247
|
+
}
|
|
8248
|
+
}
|
|
8249
|
+
```
|
|
8250
|
+
|
|
8251
|
+
Cross-request registries (cancellation, subscription fan-out, push notifications) are deliberately out of scope for the stateless seam; those spec methods answer `UnsupportedOperationError` (-32004).
|
|
8252
|
+
|
|
8253
|
+
The seam performs no authentication or authorization - wrap it with your app's route guards and scope every port in `ports(c)` to the caller.
|
|
8254
|
+
|
|
8255
|
+
## Docs
|
|
8256
|
+
|
|
8257
|
+
Part of the **[nifra](https://nifra.dev)** full-stack TypeScript framework - one core, five UI libraries, every runtime. Scaffold a new app with `bun create nifra`.
|
|
8258
|
+
|
|
8259
|
+
For AI agents, see [`LLM.md`](./LLM.md) and the full corpus
|
|
8260
|
+
[`../../llms-full.txt`](../../llms-full.txt).
|
|
8261
|
+
|
|
8262
|
+
## @nifrajs/ag-ui
|
|
8263
|
+
|
|
8264
|
+
Mount a nifra agent as an [AG-UI](https://docs.ag-ui.com) (Agent-User Interaction protocol) endpoint: one POST accepting `RunAgentInput`, a stream of AG-UI events out over SSE - run lifecycle, step and tool-call events projected from the runner's step evidence, text message events for the output, and a typed continuation for human-in-the-loop resume.
|
|
8265
|
+
|
|
8266
|
+
A protocol bridge over [`@nifrajs/agent`](../agent) - the request body reuses core's single bounded, prototype-guarded trust boundary, and the model, durable state store, and approval transport are injected per request through the same `ports` factory `mountAgent` uses. Dependency-free beyond the two nifra peers.
|
|
8267
|
+
|
|
8268
|
+
## Install
|
|
8269
|
+
|
|
8270
|
+
```bash
|
|
8271
|
+
bun add @nifrajs/ag-ui @nifrajs/agent
|
|
8272
|
+
```
|
|
8273
|
+
|
|
8274
|
+
## Mount
|
|
8275
|
+
|
|
8276
|
+
```ts
|
|
8277
|
+
import { server } from "@nifrajs/core"
|
|
8278
|
+
import { mountAgUI } from "@nifrajs/ag-ui"
|
|
8279
|
+
import { agent } from "./agent" // an AgentDefinition
|
|
8280
|
+
|
|
8281
|
+
const app = server()
|
|
8282
|
+
mountAgUI(app, {
|
|
8283
|
+
agent,
|
|
8284
|
+
ports: (c) => ({
|
|
8285
|
+
model: myModelPort, // scope to the request subject
|
|
8286
|
+
capabilities: ["search.read"],
|
|
8287
|
+
state: myStateStore, // required for resume
|
|
8288
|
+
}),
|
|
8289
|
+
})
|
|
8290
|
+
// POST /agui - RunAgentInput in, AG-UI events out (SSE)
|
|
8291
|
+
```
|
|
8292
|
+
|
|
8293
|
+
## Event mapping
|
|
8294
|
+
|
|
8295
|
+
| Runner | AG-UI events |
|
|
8296
|
+
| --- | --- |
|
|
8297
|
+
| run starts | `RUN_STARTED`, then `CUSTOM { name: "nifra.turn" }` announcing the turn id |
|
|
8298
|
+
| tool evidence | `TOOL_CALL_START` / `TOOL_CALL_END`, then `TOOL_CALL_RESULT` whose `content` is the token-only outcome `{ "outcome": "committed" \| "failed" \| "denied", "code"? }` |
|
|
8299
|
+
| model, approval, budget, state evidence | `STEP_STARTED` / `STEP_FINISHED` |
|
|
8300
|
+
| model text deltas | live `TEXT_MESSAGE_START` / `_CONTENT` (see streaming below) |
|
|
8301
|
+
| model reasoning deltas | `REASONING_START` / `REASONING_MESSAGE_START` / `_CONTENT` / `_END` / `REASONING_END` |
|
|
8302
|
+
| model tool-args deltas | provisional `TOOL_CALL_START` + `TOOL_CALL_ARGS`, closed by the call's tool evidence |
|
|
8303
|
+
| shared state | `STATE_SNAPSHOT` on the seed and `STATE_DELTA` (RFC 6902 ops) per patch (see below) |
|
|
8304
|
+
| model usage deltas | summed per `(provider, model)` into the `usage: TokenUsage[]` array on `RUN_FINISHED` |
|
|
8305
|
+
| completed output | `TEXT_MESSAGE_START` / `_CONTENT` / `_END` (unless text was streamed), an optional `MESSAGES_SNAPSHOT` (see below), then `RUN_FINISHED` with `result` and `outcome: { "type": "success" }` |
|
|
8306
|
+
| completed with a typed error | `RUN_ERROR` |
|
|
8307
|
+
| suspended | `CUSTOM { name: "nifra.pending" }` with the continuation, then `RUN_FINISHED` with `outcome: { "type": "interrupt", "interrupts": [...] }` |
|
|
8308
|
+
|
|
8309
|
+
Evidence-derived events carry the evidence `timestamp`. The runtime is token-only by design - `TOOL_CALL_RESULT` reports the outcome and error code, never the tool's payload.
|
|
8310
|
+
|
|
8311
|
+
Agent input is `forwardedProps.input` when present, otherwise the content of the last `role: "user"` message.
|
|
8312
|
+
|
|
8313
|
+
## Token streaming
|
|
8314
|
+
|
|
8315
|
+
A model port that calls the request's optional `onDelta` callback (see `@nifrajs/agent`'s `AgentModelDelta`) streams live:
|
|
8316
|
+
|
|
8317
|
+
- `{ kind: "text", text }` opens a `TEXT_MESSAGE` and streams each chunk as `TEXT_MESSAGE_CONTENT`. When any text was streamed, the terminal text block is suppressed - the streamed text IS the assistant message, so a streaming port must stream all user-visible text. A non-streaming port keeps the single terminal block; nothing changes for it.
|
|
8318
|
+
- `{ kind: "reasoning", text }` streams a `REASONING_*` message.
|
|
8319
|
+
- `{ kind: "tool-args", name?, argsText }` opens a provisional `TOOL_CALL_START` (id `<turnId>:call:<n>`) and streams `TOOL_CALL_ARGS`. The tool evidence that follows closes the same call - `TOOL_CALL_END` plus the token-only `TOOL_CALL_RESULT` - instead of opening a second one.
|
|
8320
|
+
- `{ kind: "usage", provider?, model?, inputTokens?, ... }` never becomes a frame. The counts are summed per `(provider, model)` across the run's model decisions and stamped as the spec `usage: TokenUsage[]` array on the terminal `RUN_FINISHED` (success and interrupt alike); non-finite figures are ignored.
|
|
8321
|
+
|
|
8322
|
+
Each stream closes when a different delta kind starts, when tool evidence lands, or at the end of the run. Deltas are transient observer data: a `Last-Event-ID` replay carries evidence frames and the stored, unsuppressed terminal events only - the stored `RUN_FINISHED` keeps its `usage`.
|
|
8323
|
+
|
|
8324
|
+
## Shared state
|
|
8325
|
+
|
|
8326
|
+
The `ports` factory receives `(c, run)`; `run.sharedState` is the run's `AgentSharedState` channel and `run.turnId` the resolved turn id. `body.state` seeds the document and is announced with an upfront `STATE_SNAPSHOT`; every `patch` from a port or tool executor streams as `STATE_DELTA` carrying the RFC 6902 ops. A first patch on an unseeded document announces itself as a `STATE_SNAPSHOT` instead of a delta against a base the client never saw. The channel is per-run and transient - nothing in it is persisted.
|
|
8327
|
+
|
|
8328
|
+
```ts
|
|
8329
|
+
mountAgUI(app, {
|
|
8330
|
+
agent,
|
|
8331
|
+
ports: (c, run) => ({
|
|
8332
|
+
model: myStreamingModelPort(run.sharedState), // patch progress as the run advances
|
|
8333
|
+
capabilities: ["search.read"],
|
|
8334
|
+
}),
|
|
8335
|
+
})
|
|
8336
|
+
```
|
|
8337
|
+
|
|
8338
|
+
With `emitMessagesSnapshot: true`, a successful run also emits `MESSAGES_SNAPSHOT` - the request's `messages` echoed back with the assistant output message appended - before `RUN_FINISHED`. It is off by default: the snapshot echoes client message payloads, and terminal events persist to the evidence log when one is configured.
|
|
8339
|
+
|
|
8340
|
+
## Human-in-the-loop resume
|
|
8341
|
+
|
|
8342
|
+
A suspended run finishes with `outcome: { "type": "interrupt", "interrupts": [interrupt] }` where the interrupt is:
|
|
8343
|
+
|
|
8344
|
+
```jsonc
|
|
8345
|
+
{
|
|
8346
|
+
"id": "<turnId>",
|
|
8347
|
+
"reason": "approval", // approval | budget | model | cancelled | max_turns
|
|
8348
|
+
"toolCallId": "<effectId>", // present for tool suspensions
|
|
8349
|
+
"responseSchema": { /* JSON Schema for the resume payload */ },
|
|
8350
|
+
"metadata": { "turnId": "…", "continuation": { "kind": "approval", "tool": "…", "effectId": "…" } }
|
|
8351
|
+
}
|
|
8352
|
+
```
|
|
8353
|
+
|
|
8354
|
+
Resume with the AG-UI `resume` array. The runtime keeps state token-only - it holds no interrupt registry - so the payload must echo `metadata.continuation`, with the suspended tool's input replayed in `continuation.input`:
|
|
8355
|
+
|
|
8356
|
+
```jsonc
|
|
8357
|
+
{
|
|
8358
|
+
"threadId": "thread-1", "runId": "run-2", "messages": [],
|
|
8359
|
+
"forwardedProps": { "input": { "prompt": "go" } },
|
|
8360
|
+
"resume": [{
|
|
8361
|
+
"interruptId": "<interrupt id>",
|
|
8362
|
+
"status": "resolved", // "cancelled" without an approval resumes as a denial
|
|
8363
|
+
"payload": {
|
|
8364
|
+
"continuation": { "kind": "approval", "tool": "search.read", "effectId": "…", "input": { "q": "…" } },
|
|
8365
|
+
"approval": { "granted": true }
|
|
8366
|
+
}
|
|
8367
|
+
}]
|
|
8368
|
+
}
|
|
8369
|
+
```
|
|
8370
|
+
|
|
8371
|
+
The pre-interrupt form - the same `{ continuation, approval? }` object in `forwardedProps.resume` plus `forwardedProps.turnId` - keeps working. A resume that fails validation is ignored and the POST starts a fresh run.
|
|
8372
|
+
|
|
8373
|
+
## Resumable streams
|
|
8374
|
+
|
|
8375
|
+
Pass an `evidenceLog` to make a dropped SSE connection resumable. Evidence-derived frames then
|
|
8376
|
+
carry SSE `id: <seq>`; a client reconnects by re-POSTing the same body with a `Last-Event-ID`
|
|
8377
|
+
header and receives the missed events, rejoining a still-running turn live or replaying the stored
|
|
8378
|
+
terminal events - the run is never re-executed.
|
|
8379
|
+
|
|
8380
|
+
```ts
|
|
8381
|
+
import { createMemoryAgentEvidenceLog } from "@nifrajs/agent/events"
|
|
8382
|
+
|
|
8383
|
+
mountAgUI(app, { agent, ports, evidenceLog: createMemoryAgentEvidenceLog() })
|
|
8384
|
+
```
|
|
8385
|
+
|
|
8386
|
+
The in-memory log is the single-process dev/test reference; a durable, multi-process log is an
|
|
8387
|
+
adapter implementing the same `AgentEvidenceLog` interface.
|
|
8388
|
+
|
|
8389
|
+
The seam performs no authentication or authorization - wrap it with your app's route guards and scope every port in `ports(c)` to the caller.
|
|
8390
|
+
|
|
8391
|
+
## Docs
|
|
8392
|
+
|
|
8393
|
+
Part of the **[nifra](https://nifra.dev)** full-stack TypeScript framework - one core, five UI libraries, every runtime. Scaffold a new app with `bun create nifra`.
|
|
8394
|
+
|
|
8395
|
+
For AI agents, see [`LLM.md`](./LLM.md) and the full corpus
|
|
8396
|
+
[`../../llms-full.txt`](../../llms-full.txt).
|
|
8397
|
+
|
|
8398
|
+
## @nifrajs/agent
|
|
8399
|
+
|
|
8400
|
+
Provider-neutral, typed, resumable agent turns over Nifra tool contracts.
|
|
8401
|
+
|
|
8402
|
+
The package owns one bounded turn at a time. Model providers, state, approvals, budgets, idempotency,
|
|
8403
|
+
and telemetry are ports. The package never imports a model vendor and its state adapter stores only
|
|
8404
|
+
token-only turn evidence.
|
|
8405
|
+
|
|
8406
|
+
```ts
|
|
8407
|
+
import { createAgentState, runAgent } from "@nifrajs/agent"
|
|
8408
|
+
|
|
8409
|
+
const result = await runAgent(definition, { value: input }, ports, {
|
|
8410
|
+
state: createAgentState("support-1"),
|
|
8411
|
+
maxTurns: 8,
|
|
8412
|
+
})
|
|
7513
8413
|
```
|
|
7514
8414
|
|
|
7515
8415
|
The public in-memory adapters are for local development and tests. Durable state, provider
|
|
7516
8416
|
credentials, and operated policy remain adapter concerns.
|
|
7517
8417
|
|
|
8418
|
+
Gateway and deployment contracts are deliberately provider-neutral. Retry, fallback, budget,
|
|
8419
|
+
deadline, workspace, and hostile-code isolation claims are admitted only from a host-approved
|
|
8420
|
+
capability report. The local and replay reference profiles are not hostile-code sandboxes, and no
|
|
8421
|
+
public package loads provider credentials or promises durable execution.
|
|
8422
|
+
|
|
8423
|
+
Several telemetry consumers can observe the same run: `combineAgentTelemetry(a, b, ...)` fans step
|
|
8424
|
+
evidence out to every port in order, so an SSE evidence stream and an exporter (for example
|
|
8425
|
+
`@nifrajs/agent-telemetry`'s `traceAgentRun`) compose instead of displacing each other. The HTTP
|
|
8426
|
+
seams (`mountAgent`, `@nifrajs/a2a`, `@nifrajs/ag-ui`) compose their streaming evidence with any
|
|
8427
|
+
telemetry port supplied through `ports`.
|
|
8428
|
+
|
|
8429
|
+
A model port can stream: when the caller wires an `AgentDeltaSink` into `ports.deltas`, every model
|
|
8430
|
+
request carries an optional `onDelta` callback the port may call per chunk - user-visible text,
|
|
8431
|
+
reasoning text, the raw argument text of the tool call being formed, or a `usage` delta reporting
|
|
8432
|
+
the decision's settled token counts (optionally attributed to a provider and model, for observers
|
|
8433
|
+
to sum across the run). Deltas are transient
|
|
8434
|
+
observer data for live UIs (`@nifrajs/ag-ui` projects them onto `TEXT_MESSAGE_*`, `REASONING_*`,
|
|
8435
|
+
and `TOOL_CALL_ARGS` frames): they are never validated, persisted, or replayed, and a failing sink
|
|
8436
|
+
never fails the model step. `combineAgentDeltaSinks(a, b, ...)` fans deltas out the way
|
|
8437
|
+
`combineAgentTelemetry` fans evidence.
|
|
8438
|
+
|
|
8439
|
+
`createAgentSharedState(initial)` is the run's shared UI state channel: a JSON document any port or
|
|
8440
|
+
tool executor patches with RFC 6902 operations (`add`, `replace`, `remove`), with subscribers
|
|
8441
|
+
observing every applied batch. Patches apply atomically - an invalid op rejects the whole batch -
|
|
8442
|
+
and prototype-grafting pointer segments are refused. The document is per-run observer data, not
|
|
8443
|
+
turn state: nothing in it is persisted by the runtime. `@nifrajs/ag-ui` projects the channel onto
|
|
8444
|
+
AG-UI `STATE_SNAPSHOT`/`STATE_DELTA` events.
|
|
8445
|
+
|
|
8446
|
+
SSE streams are resumable: give `mountAgent` (or `@nifrajs/ag-ui`'s `mountAgUI`) an `evidenceLog`
|
|
8447
|
+
and `step` frames carry `id: <seq>`. A client that loses the connection re-POSTs the same `turnId`
|
|
8448
|
+
with a `Last-Event-ID` header and receives the missed evidence, rejoining a still-running turn live
|
|
8449
|
+
or replaying the stored terminal frame - the run is never re-executed.
|
|
8450
|
+
`createMemoryAgentEvidenceLog` (from `@nifrajs/agent/events`) is the single-process dev/test
|
|
8451
|
+
reference; a durable, multi-process log is an adapter implementing the same `AgentEvidenceLog`
|
|
8452
|
+
interface.
|
|
8453
|
+
|
|
7518
8454
|
Execution policies can be required by a tool contract. `createLocalProcessAdapter` applies cwd and
|
|
7519
8455
|
environment filtering, timeouts, and cancellation to child processes. The local adapter is NOT a
|
|
7520
8456
|
security boundary. Without OS-level sandboxing it contains crashes and accidents, not hostile code.
|
|
@@ -7522,6 +8458,111 @@ security boundary. Without OS-level sandboxing it contains crashes and accidents
|
|
|
7522
8458
|
For the compact agent contract, see [`LLM.md`](./LLM.md). The full machine-readable corpus is
|
|
7523
8459
|
[`../../llms-full.txt`](../../llms-full.txt).
|
|
7524
8460
|
|
|
8461
|
+
## @nifrajs/agent-app
|
|
8462
|
+
|
|
8463
|
+
A presentation-safe browser SDK for Nifra agent hosts.
|
|
8464
|
+
|
|
8465
|
+
This package depends on **only** `@nifrajs/agent-protocol`. It pulls in no backend, model provider,
|
|
8466
|
+
storage, or UI framework, so it can be bundled into browser-facing code without dragging a private
|
|
8467
|
+
engine or payload content across the boundary. Everything it surfaces upward is a content-free view
|
|
8468
|
+
model: identifiers, lifecycle statuses, counters, and opaque references. A prompt becomes a character
|
|
8469
|
+
count; a tool result becomes an `ok` flag and an error *code*; a compaction becomes before/after token
|
|
8470
|
+
counts.
|
|
8471
|
+
|
|
8472
|
+
## What it does
|
|
8473
|
+
|
|
8474
|
+
- **Feature negotiation.** On session creation the client intersects the features it can drive with the
|
|
8475
|
+
capabilities the host advertises, and gates the matching operations behind `requireFeature`.
|
|
8476
|
+
- **Caller auth.** An optional `authorize` hook mints a bearer token per request. The token is placed
|
|
8477
|
+
on the outgoing `Authorization` header and never stored on the transport, copied into a result, or
|
|
8478
|
+
written to a log.
|
|
8479
|
+
- **Ordered, deduplicated streaming.** A turn arrives as an ordered stream of `AgentEventView`s.
|
|
8480
|
+
Out-of-order and redelivered frames are reordered and de-duplicated by sequence; a bounded buffer
|
|
8481
|
+
skips an unfilled gap rather than stalling.
|
|
8482
|
+
- **Cursor resume.** A persisted log can be replayed from a cursor. A cursor whose next record was
|
|
8483
|
+
evicted from the retained window asks the caller to resync.
|
|
8484
|
+
- **Approvals and handoffs.** Pending approvals list as identifiers; decisions and handoff outcomes go
|
|
8485
|
+
back through negotiated commands.
|
|
8486
|
+
- **Run Studio views.** Run graphs, retry/recovery timelines, eval comparisons, and fault-injection
|
|
8487
|
+
rows consume only protocol evidence and bounded replay references.
|
|
8488
|
+
- **Escape hatch.** `command()` reaches host-specific surfaces outside the negotiated contract and
|
|
8489
|
+
still returns a bounded `CommandOutcome` - it never throws the credential.
|
|
8490
|
+
|
|
8491
|
+
## Usage
|
|
8492
|
+
|
|
8493
|
+
```ts
|
|
8494
|
+
import { AgentAppClient, HttpAgentTransport } from "@nifrajs/agent-app"
|
|
8495
|
+
|
|
8496
|
+
const transport = new HttpAgentTransport({
|
|
8497
|
+
endpoint: "http://127.0.0.1:8787",
|
|
8498
|
+
authorize: () => currentToken(), // per-request; never stored
|
|
8499
|
+
})
|
|
8500
|
+
const client = new AgentAppClient(transport)
|
|
8501
|
+
|
|
8502
|
+
const session = await client.createSession()
|
|
8503
|
+
if (client.supports("resume")) {
|
|
8504
|
+
const replay = await client.resume({ cursor: lastCursor })
|
|
8505
|
+
// replay.entries: { seq, at, type }[] - no payloads
|
|
8506
|
+
}
|
|
8507
|
+
|
|
8508
|
+
for await (const view of client.send("summarize the diff")) {
|
|
8509
|
+
// view is content-free: e.g. { kind: "assistant.delta", seq, chars }
|
|
8510
|
+
}
|
|
8511
|
+
```
|
|
8512
|
+
|
|
8513
|
+
## Boundary
|
|
8514
|
+
|
|
8515
|
+
The transport receives the host's full event stream in order to derive counts, but the client's public
|
|
8516
|
+
output is projected to content-free view models. That projection is the seam: an application built on
|
|
8517
|
+
this SDK can render progress and resolve interactions, and cannot reconstruct a prompt, tool payload,
|
|
8518
|
+
model completion, diagnostic report, or filesystem path. The `scripts/check-agent-boundary.ts` gate
|
|
8519
|
+
enforces that this package imports nothing but `@nifrajs/agent-protocol`.
|
|
8520
|
+
|
|
8521
|
+
The SDK is transport-neutral and opt-in: it does not retain payloads, provide identity or tenancy,
|
|
8522
|
+
claim a remote security boundary, or imply durable delivery. Production hosts own authorization,
|
|
8523
|
+
retention, and adapter policy.
|
|
8524
|
+
|
|
8525
|
+
## License
|
|
8526
|
+
|
|
8527
|
+
MIT
|
|
8528
|
+
|
|
8529
|
+
For AI agents, see [`LLM.md`](./LLM.md) and the full corpus
|
|
8530
|
+
[`../../llms-full.txt`](../../llms-full.txt).
|
|
8531
|
+
|
|
8532
|
+
## @nifrajs/agent-protocol
|
|
8533
|
+
|
|
8534
|
+
Small, backend-neutral contracts for local coding-agent sessions.
|
|
8535
|
+
|
|
8536
|
+
The package contains versioned session snapshots, streamed assistant/tool/approval
|
|
8537
|
+
events, bounded live event streams, and backend interfaces. It has no runtime
|
|
8538
|
+
dependencies and does not import Nifra framework packages, model SDKs, or UI code.
|
|
8539
|
+
|
|
8540
|
+
```ts
|
|
8541
|
+
import { createAgentEventStream } from "@nifrajs/agent-protocol"
|
|
8542
|
+
|
|
8543
|
+
const events = createAgentEventStream(256)
|
|
8544
|
+
events.push(/* a versioned AgentEvent */)
|
|
8545
|
+
```
|
|
8546
|
+
|
|
8547
|
+
Use `@nifrajs/pi` for the Pi backend or implement `AgentBackend` for another
|
|
8548
|
+
runtime. The protocol is intentionally small so CLI, desktop, mobile, and CI
|
|
8549
|
+
clients can share it without pulling in the Nifra application framework.
|
|
8550
|
+
|
|
8551
|
+
## Version 1 compatibility
|
|
8552
|
+
|
|
8553
|
+
Version 1 is additive. Hosts advertise capabilities and clients use only the negotiated intersection;
|
|
8554
|
+
an unsupported command is a stable `feature_unsupported` result. Optional fields are ignored by older
|
|
8555
|
+
peers, while a cursor gap returns `resync_required` instead of silently skipping evidence. A future
|
|
8556
|
+
major requires a recorded semantic incompatibility, dual decoders, cross-version fixtures, and an
|
|
8557
|
+
approved migration plan.
|
|
8558
|
+
|
|
8559
|
+
Run evidence and lifecycle values are structural only: identifiers, statuses, counters, timestamps,
|
|
8560
|
+
digests, and opaque references. Prompts, model output, tool arguments, and filesystem paths do not
|
|
8561
|
+
belong in these public contracts.
|
|
8562
|
+
|
|
8563
|
+
For AI agents, see [`LLM.md`](./LLM.md) and the full corpus
|
|
8564
|
+
[`../../llms-full.txt`](../../llms-full.txt).
|
|
8565
|
+
|
|
7525
8566
|
## @nifrajs/agent-telemetry
|
|
7526
8567
|
|
|
7527
8568
|
Child-span telemetry for AI tool calls made through Nifra tool and MCP endpoints.
|
|
@@ -7540,6 +8581,35 @@ Requests under `/_nifra/tool/*` and requests to `/mcp` receive tool-name, input-
|
|
|
7540
8581
|
duration, and status observations. When `@nifrajs/otel` owns the request observation, tool spans are
|
|
7541
8582
|
attached as children; otherwise the plugin creates a standalone observation. Other routes pass through.
|
|
7542
8583
|
|
|
8584
|
+
## Tracing agent runs
|
|
8585
|
+
|
|
8586
|
+
`traceAgentRun` turns a `@nifrajs/agent` run's step evidence into an OpenTelemetry trace: one
|
|
8587
|
+
`nifra.agent.run` span per run, one child span per evidence item, with tool names, effect ids, error
|
|
8588
|
+
codes, and effect-ledger heads carried as span attributes. Only the runner's constrained evidence
|
|
8589
|
+
fields are exported - prompts, tool inputs, and outputs cannot enter a trace.
|
|
8590
|
+
|
|
8591
|
+
Orchestration correlation is opt-in and cardinality-bounded. Allowed attributes are run, plan, node,
|
|
8592
|
+
attempt, evidence, replay, and trace coordinates plus bounded status/error codes. Content-bearing or
|
|
8593
|
+
unbounded attributes are rejected; the exporter is not a payload retention sink.
|
|
8594
|
+
|
|
8595
|
+
```ts
|
|
8596
|
+
import { traceAgentRun } from "@nifrajs/agent-telemetry"
|
|
8597
|
+
import { combineAgentTelemetry, runAgent } from "@nifrajs/agent"
|
|
8598
|
+
|
|
8599
|
+
const trace = traceAgentRun({ agent: agent.name, turnId, exporter })
|
|
8600
|
+
const result = await runAgent(agent, input, {
|
|
8601
|
+
...ports,
|
|
8602
|
+
telemetry: combineAgentTelemetry(ports.telemetry, trace.telemetry),
|
|
8603
|
+
})
|
|
8604
|
+
trace.end(result)
|
|
8605
|
+
```
|
|
8606
|
+
|
|
8607
|
+
Model evidence arrives as a started/terminal pair and becomes one timed `nifra.agent.model` span;
|
|
8608
|
+
tool, approval, budget, and state evidence are terminal-only and become instant children. Pass
|
|
8609
|
+
`parent` (for example the enclosing request observation's `context`) to nest runs under the HTTP
|
|
8610
|
+
span, or `traceparent` to continue an inbound W3C trace; `trace.context` is the run span's identity,
|
|
8611
|
+
forwardable with `traceHeaders`. Telemetry is fail-open: a throwing exporter never fails the turn.
|
|
8612
|
+
|
|
7543
8613
|
## For AI agents
|
|
7544
8614
|
|
|
7545
8615
|
Start with [`LLM.md`](./LLM.md) - this package's contract card (the exports you call + its footguns),
|
|
@@ -7691,8 +8761,8 @@ app.get("/me", async (c) => {
|
|
|
7691
8761
|
|
|
7692
8762
|
## Protect a route
|
|
7693
8763
|
|
|
7694
|
-
`requireSession(auth, request, options?)` returns the non-null session or **throws a `
|
|
7695
|
-
nifra
|
|
8764
|
+
`requireSession(auth, request, options?)` returns the non-null session or **throws a Nifra `ResponseResult`** -
|
|
8765
|
+
nifra handles the thrown `ResponseResult` as control flow, short-circuiting the handler:
|
|
7696
8766
|
|
|
7697
8767
|
```ts
|
|
7698
8768
|
import { requireSession } from "@nifrajs/better-auth"
|
|
@@ -7716,7 +8786,7 @@ export const loader = async ({ request }) => {
|
|
|
7716
8786
|
| --- | --- |
|
|
7717
8787
|
| `betterAuth(auth, options?)` | Plugin that mounts better-auth's handler at `${basePath}/*` for GET + POST. |
|
|
7718
8788
|
| `getSession(auth, request)` | `Promise<SessionOf<A> \| null>` - typed wrapper over `auth.api.getSession`. |
|
|
7719
|
-
| `requireSession(auth, request, options?)` | Returns the session or throws a `
|
|
8789
|
+
| `requireSession(auth, request, options?)` | Returns the session or throws a Nifra `ResponseResult` (302 `redirectTo` / 401). |
|
|
7720
8790
|
| `SessionOf<A>` | The non-null session payload type inferred from your `auth`. |
|
|
7721
8791
|
| `BetterAuthLike` | The structural contract a better-auth instance satisfies. |
|
|
7722
8792
|
|
|
@@ -7770,8 +8840,9 @@ await cache.invalidateTag(`user:${id}`)
|
|
|
7770
8840
|
|
|
7771
8841
|
## Stores
|
|
7772
8842
|
|
|
7773
|
-
The default `MemoryCache` is in-process with
|
|
7774
|
-
|
|
8843
|
+
The default `MemoryCache` is in-process with incremental expiry, a tag index, and a 10,000-entry LRU
|
|
8844
|
+
cap. Tune it with `new MemoryCache({ maxEntries: 2_000 })`; `maxEntries: 0` is the explicit unbounded
|
|
8845
|
+
opt-in. For a cache shared across instances, implement `CacheStore`
|
|
7775
8846
|
(`get` / `set` / `delete` / `invalidateTag` / `clear`) over CF KV, Redis, etc.:
|
|
7776
8847
|
|
|
7777
8848
|
```ts
|
|
@@ -7808,6 +8879,7 @@ nifra start [--port <n>] [--out <dir>] Run the generated Bun server at <out>
|
|
|
7808
8879
|
nifra context Print this project's API + page routes + conventions.
|
|
7809
8880
|
nifra mcp MCP server (stdio) exposing this project to a coding agent.
|
|
7810
8881
|
nifra check [--json] Gate: typecheck + lints; --json includes fixes/suggestions.
|
|
8882
|
+
nifra migrate --from tailwind --to stylex Dry-run safe static Tailwind → StyleX migration; --write applies it.
|
|
7811
8883
|
nifra assure [--config <file>] [--json] Gate reflected routes against enforcement evidence.
|
|
7812
8884
|
nifra capabilities check [--json] Gate effect provenance + the reviewed capability lockfile.
|
|
7813
8885
|
nifra manifest emit [--sign <key-ref>] Emit the hash-verified route trust artifact after assurance.
|
|
@@ -7870,6 +8942,15 @@ For hand-rolled own-API `fetch()` calls, `nifra check` stays conservative: simpl
|
|
|
7870
8942
|
that match a statically visible Nifra route get an exact typed-client rewrite diff; dynamic URLs, custom
|
|
7871
8943
|
headers, bodies, query strings, or ambiguous routes fall back to manual steps.
|
|
7872
8944
|
|
|
8945
|
+
## `nifra migrate --from tailwind --to stylex`
|
|
8946
|
+
|
|
8947
|
+
This command is a dry run by default. It rewrites static `className` attributes whose utilities have a
|
|
8948
|
+
direct StyleX equivalent into `stylex.props(...)` plus a local `stylex.create(...)` table. Use
|
|
8949
|
+
`--write` to apply the safe changes, and `--dir` to scan a project subdirectory. Responsive breakpoints
|
|
8950
|
+
and element-local pseudo-classes are supported; dynamic expressions, arbitrary values, parent-dependent
|
|
8951
|
+
variants, and unknown utilities are left untouched and reported with file and line evidence. A non-zero
|
|
8952
|
+
exit status means manual migration issues remain.
|
|
8953
|
+
|
|
7873
8954
|
When a library such as Better Auth intentionally owns a mounted prefix outside the Nifra contract,
|
|
7874
8955
|
declare that prefix in `nifra.check.json` so its relative calls do not keep CI red:
|
|
7875
8956
|
|
|
@@ -7996,6 +9077,76 @@ one cheap read instead of the whole corpus. For the wider framework: the repo's
|
|
|
7996
9077
|
[`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
|
|
7997
9078
|
done-gate, or `nifra mcp` to give the agent live project tools.
|
|
7998
9079
|
|
|
9080
|
+
## @nifrajs/coding-agent
|
|
9081
|
+
|
|
9082
|
+
Standalone, extensible Nifra coding-agent host and CLI.
|
|
9083
|
+
|
|
9084
|
+
The package provides `nifra-agent` in interactive, one-shot, JSON, and local
|
|
9085
|
+
loopback RPC modes. It adds sessions, checkpoints, bounded compaction,
|
|
9086
|
+
transactional TypeScript extensions, self-healing repair stages, workflows,
|
|
9087
|
+
bounded subagents, and Nifra verification descriptors without changing Nifra's
|
|
9088
|
+
framework runtime.
|
|
9089
|
+
|
|
9090
|
+
Extensions can register bounded workflows that are listed and run through the
|
|
9091
|
+
authenticated RPC surface. Capability manifests, project workspace policies,
|
|
9092
|
+
optional isolated-worktree leases, and a pre-activation syntax gate keep those
|
|
9093
|
+
customizations explicit and replaceable.
|
|
9094
|
+
|
|
9095
|
+
```sh
|
|
9096
|
+
bunx nifra-agent --backend pi
|
|
9097
|
+
bunx nifra-agent --backend pi --message "run the checks and explain failures"
|
|
9098
|
+
bunx nifra-agent --backend pi --verify-after-turn check --max-repair-attempts 2
|
|
9099
|
+
bunx nifra-agent --backend replay --replay ./session-events.jsonl --json
|
|
9100
|
+
```
|
|
9101
|
+
|
|
9102
|
+
When --verify-after-turn is enabled, a failed gate becomes a bounded repair turn: the host sends
|
|
9103
|
+
the failure diagnostics back to the agent, runs the gate again, and stops on success or after the
|
|
9104
|
+
configured attempt cap. Use --max-repair-attempts 0 for observe-only verification.
|
|
9105
|
+
|
|
9106
|
+
For embedding, use `CodingAgentHost` or `CodingAgentRpcServer`. The host keeps
|
|
9107
|
+
live event queues bounded, filters verification subprocess environments, and
|
|
9108
|
+
requires explicit local RPC authorization. Install this package only when an
|
|
9109
|
+
application wants the agent product.
|
|
9110
|
+
|
|
9111
|
+
RPC failures return actionable bounded error messages by default. For a trusted
|
|
9112
|
+
loopback debugger, set `exposeErrorStacks: true` (or pass
|
|
9113
|
+
`--expose-error-stacks` to `nifra-agent --rpc`) to include bounded exception
|
|
9114
|
+
stacks. This option is rejected for remote binding.
|
|
9115
|
+
|
|
9116
|
+
`IsolatedExtensionWorker` is an opt-in process-backed crash-containment seam for
|
|
9117
|
+
extensions. It is not a hostile-code sandbox; use OS-level isolation before
|
|
9118
|
+
loading code you do not trust.
|
|
9119
|
+
|
|
9120
|
+
`NifraBackend` is a small provider port for a future native backend. It accepts
|
|
9121
|
+
an injected model implementation and bounded tools without importing a provider
|
|
9122
|
+
SDK. `ReplayBackend` and `readReplayEvents` provide deterministic protocol
|
|
9123
|
+
replays for CI and Workbench regression tests.
|
|
9124
|
+
|
|
9125
|
+
## At-least-once run dispatch
|
|
9126
|
+
|
|
9127
|
+
`@nifrajs/coding-agent/orchestration` also exports an evidence-only run dispatch port and an adapter
|
|
9128
|
+
over `@nifrajs/jobs`. Dispatch is at-least-once: a lease may be delivered again after worker loss or
|
|
9129
|
+
lease expiry. Every logical node attempt receives a stable idempotency key derived from the plan,
|
|
9130
|
+
run, node, and attempt boundary. Effects must provide a matching proof before recovery can settle a
|
|
9131
|
+
completed boundary; an unproven post-effect failure is dead-lettered rather than guessed safe.
|
|
9132
|
+
|
|
9133
|
+
`createMemoryRunDispatchStore()` is disposable single-process test infrastructure. It makes no
|
|
9134
|
+
durability, hosted-worker, retention, tenant-authorization, or exactly-once guarantee. Durable
|
|
9135
|
+
operated adapters implement the exported `RunDispatchStore` and `DurableDispatchAdapter` ports in
|
|
9136
|
+
their own data layer, including authorization, row policy, retention, reconciliation, and worker
|
|
9137
|
+
health. The public package does not store prompts, model output, tool arguments, or job payloads in
|
|
9138
|
+
its dispatch evidence.
|
|
9139
|
+
|
|
9140
|
+
Legacy `FileSessionStore` files remain supported for explicit local compatibility. Use
|
|
9141
|
+
`nifra-agent --migrate-session <id> --migrate-from <legacy-dir> --migrate-to <evidence-dir>` to
|
|
9142
|
+
create a separately validated, evidence-only target. The source is left untouched and the command
|
|
9143
|
+
does not switch an active configuration pointer; see
|
|
9144
|
+
[`docs/agent-platform/protocol-and-session-migration.md`](../../docs/agent-platform/protocol-and-session-migration.md)
|
|
9145
|
+
for rollback and protocol compatibility details.
|
|
9146
|
+
|
|
9147
|
+
For AI agents, see [`LLM.md`](./LLM.md) and the full corpus
|
|
9148
|
+
[`../../llms-full.txt`](../../llms-full.txt).
|
|
9149
|
+
|
|
7999
9150
|
## @nifrajs/content
|
|
8000
9151
|
|
|
8001
9152
|
Typed, schema-validated content collections for nifra - Markdown + frontmatter, framework-agnostic.
|
|
@@ -8013,6 +9164,31 @@ bun add @nifrajs/content
|
|
|
8013
9164
|
- Reference: <https://nifra.dev/docs>
|
|
8014
9165
|
- AI-readable: <https://nifra.dev/llms.txt>
|
|
8015
9166
|
|
|
9167
|
+
## Typed indexes and joins
|
|
9168
|
+
|
|
9169
|
+
Build an equality lookup and deterministic query index from a baked collection. `where` is field
|
|
9170
|
+
equality, `range` supports typed string/number comparisons, sorting is stable (slug is the tie-breaker),
|
|
9171
|
+
and pages use an opaque cursor rather than an offset:
|
|
9172
|
+
|
|
9173
|
+
```ts
|
|
9174
|
+
const posts = indexCollection(await bakeCollection(blog), {
|
|
9175
|
+
by: "section",
|
|
9176
|
+
sort: { field: "publishedAt", dir: "desc" },
|
|
9177
|
+
})
|
|
9178
|
+
|
|
9179
|
+
const page = posts.query({ where: { section: "news" }, limit: 20 })
|
|
9180
|
+
const next = page.nextCursor === undefined
|
|
9181
|
+
? undefined
|
|
9182
|
+
: posts.query({ where: { section: "news" }, cursor: page.nextCursor, limit: 20 })
|
|
9183
|
+
```
|
|
9184
|
+
|
|
9185
|
+
`posts.baked` is JSON-safe and can be serialized into an edge bundle; `fromBakedIndex` rehydrates it
|
|
9186
|
+
without filesystem access. `joinCollections(left, right, "id")` gives one-to-many rows by default.
|
|
9187
|
+
Pass `{ cardinality: "one-to-one" }` to require unique right-side keys; duplicate right keys fail the
|
|
9188
|
+
build loudly. The join key must exist on both frontmatter types with the same TypeScript value type.
|
|
9189
|
+
These APIs index only validated local/baked content; credentialed CMS ingestion and tenant data remain
|
|
9190
|
+
outside this public package.
|
|
9191
|
+
|
|
8016
9192
|
MIT
|
|
8017
9193
|
|
|
8018
9194
|
## For AI agents
|
|
@@ -8063,12 +9239,37 @@ import { defineChannel, memoryChannelHub } from "@nifrajs/core/channel"
|
|
|
8063
9239
|
- **Inline or contract-first.** Write routes inline (types inferred from the
|
|
8064
9240
|
builder), or `defineContract(...)` + `implement(...)` for a decoupled, versionable
|
|
8065
9241
|
surface - handlers lift over unchanged.
|
|
9242
|
+
|
|
9243
|
+
### Scaling route tables
|
|
9244
|
+
|
|
9245
|
+
Fluent chains are the best fit for a small route surface. TypeScript's type-instantiation budget
|
|
9246
|
+
usually becomes the limiting factor around 95-100 chained routes because every call both infers its
|
|
9247
|
+
handler context and re-threads the growing typed registry. The runtime router is not the limit, and
|
|
9248
|
+
the routes remain fully typed when you compose them as short domain groups:
|
|
9249
|
+
|
|
9250
|
+
```ts
|
|
9251
|
+
const listings = server()
|
|
9252
|
+
.get("/listings", () => ({ ok: true }))
|
|
9253
|
+
.get("/listings/:id", (c) => ({ id: c.params.id }))
|
|
9254
|
+
const agents = server().get("/agents/:id", (c) => ({ id: c.params.id }))
|
|
9255
|
+
|
|
9256
|
+
const app = server().get("/health", () => ({ ok: true })).merge(listings).merge(agents)
|
|
9257
|
+
```
|
|
9258
|
+
|
|
9259
|
+
Each group's routes keep the middleware and assurance captured when that group was defined. For a
|
|
9260
|
+
contract-owned surface, `defineContract(...)` + `implement(...)` is the other escape hatch: the
|
|
9261
|
+
registry is declared as one object type, so it does not grow one fluent-instantiation level per
|
|
9262
|
+
route. Split groups before the compiler reports `TS2589`, rather than weakening the route types.
|
|
8066
9263
|
- **Validation at the boundary.** Per-route `body`/`query` is any
|
|
8067
9264
|
[Standard Schema](https://standardschema.dev) (zod/valibot/arktype, or `@nifrajs/schema`'s
|
|
8068
9265
|
`t`); invalid input is rejected with a structured `422` before the handler runs.
|
|
8069
9266
|
- **Lifecycle middleware.** `derive`/`decorate` extend the typed context;
|
|
8070
9267
|
`onRequest`/`beforeHandle`/`afterHandle`/`onResponse`/`onError` run around handlers;
|
|
8071
9268
|
`use(middleware)` applies a bundle.
|
|
9269
|
+
- **Portable response observation.** The header/body/raw observer methods are opt-in so ordinary
|
|
9270
|
+
servers stay lean: add `responseObserver()` from `@nifrajs/core/response-observer` before calling
|
|
9271
|
+
`onResponseHeaders`, `onResponseBody`, or `onResponseRaw`. Official middleware that uses these
|
|
9272
|
+
tiers installs the compatibility runtime automatically.
|
|
8072
9273
|
- **Hardening built in.** `stop({ drainMs })` graceful shutdown (+ opt-in SIGTERM/
|
|
8073
9274
|
SIGINT), `requestTimeoutMs` (+ `ctx.signal` and `ctx.budget`), a streaming body-size cap, and a
|
|
8074
9275
|
redacting structured `Logger`.
|
|
@@ -8283,6 +9484,98 @@ one cheap read instead of the whole corpus. For the wider framework: the repo's
|
|
|
8283
9484
|
[`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
|
|
8284
9485
|
done-gate, or `nifra mcp` to give the agent live project tools.
|
|
8285
9486
|
|
|
9487
|
+
## @nifrajs/edge
|
|
9488
|
+
|
|
9489
|
+
Compact fetch-handler server for edge and serverless runtimes - Cloudflare Workers, Vercel Edge, Deno Deploy, Bun. Keeps the `server().get().post()` DX and the full request trust boundary (bounded body read, Content-Length pre-reject, prototype-pollution guard, JSON / urlencoded framing) in a fraction of the bundle. Zero runtime dependencies beyond `@nifrajs/core`.
|
|
9490
|
+
|
|
9491
|
+
Part of the **[nifra](https://nifra.dev)** full-stack TypeScript framework - one core, five UI libraries, every runtime. Scaffold a new app with `bun create nifra`.
|
|
9492
|
+
|
|
9493
|
+
## Why
|
|
9494
|
+
|
|
9495
|
+
`@nifrajs/core`'s `server()` carries lifecycle hooks, cookies, response contracts, deadlines, WebSockets, and a plugin system. On an edge worker you often want none of that - just typed routing and a safe body. `@nifrajs/edge` is that subset: the same routing DX, the *same* body trust boundary (imported from core, never re-derived, so there is no second copy of the security contract to drift), and nothing else.
|
|
9496
|
+
|
|
9497
|
+
The rejection envelopes are byte-for-byte the full Server's - so an app can start on `@nifrajs/edge` and graduate to `@nifrajs/core`'s `server()` without its clients noticing.
|
|
9498
|
+
|
|
9499
|
+
## Install
|
|
9500
|
+
|
|
9501
|
+
```sh
|
|
9502
|
+
bun add @nifrajs/edge @nifrajs/core
|
|
9503
|
+
```
|
|
9504
|
+
|
|
9505
|
+
## Use
|
|
9506
|
+
|
|
9507
|
+
```ts
|
|
9508
|
+
// worker.ts
|
|
9509
|
+
import { server, type StandardSchemaV1 } from "@nifrajs/edge"
|
|
9510
|
+
|
|
9511
|
+
const createUser: StandardSchemaV1<{ name: string; age: number }> = /* zod, valibot, arktype, ... */
|
|
9512
|
+
|
|
9513
|
+
const app = server()
|
|
9514
|
+
.get("/users/:id", (c) => ({ id: c.params.id }))
|
|
9515
|
+
.post("/users", { body: createUser }, (c) => ({ created: c.body.name, age: c.body.age }))
|
|
9516
|
+
|
|
9517
|
+
export default app // { fetch } - a module worker handler
|
|
9518
|
+
```
|
|
9519
|
+
|
|
9520
|
+
`c.params` is typed from the route pattern. `c.body` is narrowed to the schema's output. Return a value (rendered as JSON) or a `Response` for full control. Throw a `Response` for an early exit; any other throw becomes a flat `500`.
|
|
9521
|
+
|
|
9522
|
+
## Context
|
|
9523
|
+
|
|
9524
|
+
| Member | What |
|
|
9525
|
+
| --- | --- |
|
|
9526
|
+
| `c.request` | the raw `Request` |
|
|
9527
|
+
| `c.params` | path params, typed from the pattern (`/users/:id` -> `{ id: string }`) |
|
|
9528
|
+
| `c.body` | parsed, schema-validated body (`undefined` on a body-less route) |
|
|
9529
|
+
| `c.query()` | query string parsed to an object, on demand |
|
|
9530
|
+
| `c.header(name)` | a request header (case-insensitive), or `null` |
|
|
9531
|
+
|
|
9532
|
+
## Options
|
|
9533
|
+
|
|
9534
|
+
```ts
|
|
9535
|
+
server({ maxBodyBytes: 256_000, protoPoisoning: "strip" })
|
|
9536
|
+
```
|
|
9537
|
+
|
|
9538
|
+
| Option | Default | What |
|
|
9539
|
+
| --- | --- | --- |
|
|
9540
|
+
| `maxBodyBytes` | `1_000_000` | body-size cap before a `413`, matching core |
|
|
9541
|
+
| `protoPoisoning` | `"reject"` | `__proto__` policy for JSON bodies: `"reject"` \| `"strip"` \| `"ignore"`, matching core |
|
|
9542
|
+
|
|
9543
|
+
## Security
|
|
9544
|
+
|
|
9545
|
+
The body trust boundary is on by default and imported from `@nifrajs/core` - the same lane the full Server runs, so there is one implementation, never a trimmed copy that could drift. On every body-bearing route it enforces:
|
|
9546
|
+
|
|
9547
|
+
| Guard | Effect |
|
|
9548
|
+
| --- | --- |
|
|
9549
|
+
| Streaming byte cap | a length-less (chunked) body is drained under `maxBodyBytes`; once over, the stream is **cancelled** and rejected `413` - it is never buffered whole |
|
|
9550
|
+
| Content-Length pre-reject | a declared length over `maxBodyBytes` is `413` before a byte is read; a malformed length is `400` |
|
|
9551
|
+
| Prototype-pollution guard | an own `__proto__` key (or a poisoning-shaped `constructor.prototype`) in a JSON body is rejected (`"reject"`, default) or removed (`"strip"`) before it reaches your handler |
|
|
9552
|
+
| Media-type framing | JSON and urlencoded bodies are framed and capped; other content types get `415` |
|
|
9553
|
+
|
|
9554
|
+
Rejection envelopes are byte-for-byte the full Server's.
|
|
9555
|
+
|
|
9556
|
+
**Whether you need this depends on the runtime:**
|
|
9557
|
+
|
|
9558
|
+
- **Stream runtimes** (Cloudflare Workers, Deno Deploy, Bun): the runtime hands your worker a live request stream with no size ceiling below its own memory limit. A single length-less request into an unguarded `.json()` buffers unbounded and can cross the isolate memory limit (~128 MB on Workers) - one request, one killed worker (and on auto-scaling platforms, a metered bill). Here the byte cap is **load-bearing**, not optional.
|
|
9559
|
+
- **Pre-capped serverless** (Vercel Edge ~4.5 MB, AWS API Gateway 6-10 MB, GCP 10-32 MB, Azure ~30 MB default): the platform already bounds the body at its edge, so the crash case is largely its job. The cap still earns its place by tightening that platform ceiling to your app's real intent and returning a consistent `413`. (Platform limits are documented ceilings - check current docs for your plan.)
|
|
9560
|
+
|
|
9561
|
+
The prototype-pollution guard is **platform-independent**: no runtime guards `JSON.parse` for you, and a `__proto__`-bearing object becomes pollution the moment downstream code merges it. The guard stops it at ingress. Both defenses tune via [Options](#options).
|
|
9562
|
+
|
|
9563
|
+
## Not included
|
|
9564
|
+
|
|
9565
|
+
By design: no lifecycle / `around` hooks, cookies, response contracts, deadlines, WebSockets, or plugins. Reach for `@nifrajs/core`'s `server()` when an app needs those.
|
|
9566
|
+
|
|
9567
|
+
## License
|
|
9568
|
+
|
|
9569
|
+
MIT
|
|
9570
|
+
|
|
9571
|
+
## For AI agents
|
|
9572
|
+
|
|
9573
|
+
Start with [`LLM.md`](./LLM.md) - this package's contract card (the exports you call + its footguns),
|
|
9574
|
+
one cheap read instead of the whole corpus. For the wider framework: the repo's
|
|
9575
|
+
[`AGENTS.md`](../../AGENTS.md) is the copy-paste quick reference, and
|
|
9576
|
+
[`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
|
|
9577
|
+
done-gate, or `nifra mcp` to give the agent live project tools.
|
|
9578
|
+
|
|
8286
9579
|
## @nifrajs/env
|
|
8287
9580
|
|
|
8288
9581
|
Typed, validated environment variables. Define a schema once at startup; get a **frozen, typed**
|
|
@@ -8377,6 +9670,126 @@ one cheap read instead of the whole corpus. For the wider framework: the repo's
|
|
|
8377
9670
|
[`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
|
|
8378
9671
|
done-gate, or `nifra mcp` to give the agent live project tools.
|
|
8379
9672
|
|
|
9673
|
+
## @nifrajs/graphql
|
|
9674
|
+
|
|
9675
|
+
Mount a GraphQL endpoint on a nifra app. A spec-compliant [GraphQL-over-HTTP](https://graphql.github.io/graphql-over-http/draft/) handler, `graphql-transport-ws` subscriptions over nifra's native WebSocket lane, and your typed nifra context piped straight into resolvers.
|
|
9676
|
+
|
|
9677
|
+
It executes with the `graphql` package's own `parse`/`validate`/`execute`/`subscribe` - no HTTP framework is re-bundled, the request body reuses core's single bounded, prototype-guarded trust boundary, and the query text is never logged.
|
|
9678
|
+
|
|
9679
|
+
## Install
|
|
9680
|
+
|
|
9681
|
+
```bash
|
|
9682
|
+
bun add @nifrajs/graphql graphql
|
|
9683
|
+
# subscriptions also need:
|
|
9684
|
+
bun add graphql-ws
|
|
9685
|
+
```
|
|
9686
|
+
|
|
9687
|
+
`graphql` is a required peer; `graphql-ws` is optional (only for subscriptions).
|
|
9688
|
+
|
|
9689
|
+
## Queries and mutations
|
|
9690
|
+
|
|
9691
|
+
```ts
|
|
9692
|
+
import { server } from "@nifrajs/core"
|
|
9693
|
+
import { mountGraphql } from "@nifrajs/graphql"
|
|
9694
|
+
import { buildSchema } from "graphql"
|
|
9695
|
+
|
|
9696
|
+
const schema = buildSchema(`
|
|
9697
|
+
type Query { hello: String }
|
|
9698
|
+
type Mutation { echo(msg: String!): String }
|
|
9699
|
+
`)
|
|
9700
|
+
|
|
9701
|
+
const rootValue = {
|
|
9702
|
+
hello: () => "world",
|
|
9703
|
+
echo: ({ msg }: { msg: string }) => msg,
|
|
9704
|
+
}
|
|
9705
|
+
|
|
9706
|
+
const app = server()
|
|
9707
|
+
mountGraphql(app, { schema, rootValue })
|
|
9708
|
+
// POST /graphql - queries + mutations
|
|
9709
|
+
// GET /graphql - queries only (idempotent, cacheable)
|
|
9710
|
+
```
|
|
9711
|
+
|
|
9712
|
+
Prefer the handler directly? Mount it yourself:
|
|
9713
|
+
|
|
9714
|
+
```ts
|
|
9715
|
+
import { respondGraphql } from "@nifrajs/graphql"
|
|
9716
|
+
|
|
9717
|
+
app.post("/graphql", (c) => respondGraphql(c.req, { schema, rootValue }))
|
|
9718
|
+
```
|
|
9719
|
+
|
|
9720
|
+
## Context injection
|
|
9721
|
+
|
|
9722
|
+
The one thing a plain third-party mount cannot do: derive the resolver `contextValue` from what your nifra handler already resolved (auth subject, env, params).
|
|
9723
|
+
|
|
9724
|
+
```ts
|
|
9725
|
+
mountGraphql(app, {
|
|
9726
|
+
schema,
|
|
9727
|
+
context: ({ request, nifra }) => ({
|
|
9728
|
+
user: nifra?.env, // nifra route context, when mounted via mountGraphql
|
|
9729
|
+
ip: request.headers.get("x-forwarded-for"),
|
|
9730
|
+
}),
|
|
9731
|
+
})
|
|
9732
|
+
```
|
|
9733
|
+
|
|
9734
|
+
Resolvers read it as their third argument.
|
|
9735
|
+
|
|
9736
|
+
## Subscriptions
|
|
9737
|
+
|
|
9738
|
+
Subscriptions run over the same route via `graphql-transport-ws`. Bring a subscription source - the bundled in-memory `createPubSub` is the reference implementation; swap in a durable bus (Redis, a Durable Object, NATS) that exposes the same `{ publish, subscribe }` shape for multi-instance deploys.
|
|
9739
|
+
|
|
9740
|
+
```ts
|
|
9741
|
+
import { server } from "@nifrajs/core"
|
|
9742
|
+
import { websocket } from "@nifrajs/core/ws"
|
|
9743
|
+
import { mountGraphql, createPubSub } from "@nifrajs/graphql"
|
|
9744
|
+
|
|
9745
|
+
const pubsub = createPubSub<number>()
|
|
9746
|
+
|
|
9747
|
+
const app = server().use(websocket())
|
|
9748
|
+
mountGraphql(app, {
|
|
9749
|
+
schema,
|
|
9750
|
+
context: () => ({ pubsub }),
|
|
9751
|
+
subscriptions: true,
|
|
9752
|
+
})
|
|
9753
|
+
|
|
9754
|
+
// A resolver:
|
|
9755
|
+
// count: { subscribe: (_, __, ctx) => ctx.pubsub.subscribe("count"), resolve: (n) => n }
|
|
9756
|
+
// Push an event from anywhere:
|
|
9757
|
+
pubsub.publish("count", 1)
|
|
9758
|
+
```
|
|
9759
|
+
|
|
9760
|
+
The route must negotiate the `graphql-transport-ws` subprotocol at the WebSocket layer for a browser `graphql-ws` client to connect.
|
|
9761
|
+
|
|
9762
|
+
## Options
|
|
9763
|
+
|
|
9764
|
+
| Option | Default | Purpose |
|
|
9765
|
+
| --- | --- | --- |
|
|
9766
|
+
| `schema` | - | Executable `GraphQLSchema` (required). |
|
|
9767
|
+
| `context` | `{}` | Build the resolver `contextValue` per operation. |
|
|
9768
|
+
| `rootValue` | - | Root value passed to the executor. |
|
|
9769
|
+
| `maxBodyBytes` | `1_000_000` | Request body cap; larger bodies answer 413. |
|
|
9770
|
+
| `protoPoisoning` | `"reject"` | Prototype-pollution policy for the JSON body. |
|
|
9771
|
+
| `allowedOrigins` | reflect `*` | CORS origin allowlist. |
|
|
9772
|
+
| `authorize` | - | Per-request guard; return `false` for 401. |
|
|
9773
|
+
| `enableGet` | `true` | Serve `GET /graphql` (queries only). |
|
|
9774
|
+
| `subscriptions` | `false` | `true` (reuse schema/context) or explicit WS options. |
|
|
9775
|
+
| `legacyJsonResponse` | `false` | Old always-200 `application/json` shape. |
|
|
9776
|
+
|
|
9777
|
+
## Responses
|
|
9778
|
+
|
|
9779
|
+
By default responses use the `application/graphql-response+json` media type with spec status codes: `200` for an executed result (including field errors in `errors`), `400` for a parse or validation failure, `401` for a rejected `authorize`, `405` for a mutation attempted over GET. Set `legacyJsonResponse: true` for the older always-`200` `application/json` behavior some clients expect.
|
|
9780
|
+
|
|
9781
|
+
## License
|
|
9782
|
+
|
|
9783
|
+
MIT
|
|
9784
|
+
|
|
9785
|
+
## For AI agents
|
|
9786
|
+
|
|
9787
|
+
Start with [`LLM.md`](./LLM.md) - this package's contract card (the exports you call + its footguns),
|
|
9788
|
+
one cheap read instead of the whole corpus. For the wider framework: the repo's
|
|
9789
|
+
[`AGENTS.md`](../../AGENTS.md) is the copy-paste quick reference, and
|
|
9790
|
+
[`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
|
|
9791
|
+
done-gate, or `nifra mcp` to give the agent live project tools.
|
|
9792
|
+
|
|
8380
9793
|
## @nifrajs/i18n
|
|
8381
9794
|
|
|
8382
9795
|
Framework-agnostic i18n for nifra - locale negotiation + a tiny ICU message formatter on the platform Intl. Dependency-free.
|
|
@@ -8463,6 +9876,32 @@ one cheap read instead of the whole corpus. For the wider framework: the repo's
|
|
|
8463
9876
|
[`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
|
|
8464
9877
|
done-gate, or `nifra mcp` to give the agent live project tools.
|
|
8465
9878
|
|
|
9879
|
+
## @nifrajs/island-trigger
|
|
9880
|
+
|
|
9881
|
+
Framework-neutral, browser-side trigger scheduling shared by Nifra’s two island runtimes:
|
|
9882
|
+
`@nifrajs/web/islands` and `@nifrajs/islets`.
|
|
9883
|
+
|
|
9884
|
+
It has no DOM or UI-framework dependency. The public contract is the small `scheduleTrigger`
|
|
9885
|
+
primitive with these strategies:
|
|
9886
|
+
|
|
9887
|
+
```ts
|
|
9888
|
+
import { scheduleTrigger } from "@nifrajs/island-trigger"
|
|
9889
|
+
|
|
9890
|
+
const dispose = scheduleTrigger({ media: "(min-width: 768px)" }, () => {
|
|
9891
|
+
// Activate the island.
|
|
9892
|
+
})
|
|
9893
|
+
|
|
9894
|
+
dispose() // cancel before the trigger fires
|
|
9895
|
+
```
|
|
9896
|
+
|
|
9897
|
+
`load`, `idle`, `visible`, and media-query triggers are one-shot. Idle and visibility strategies
|
|
9898
|
+
fall back safely when the browser capability is unavailable; malformed or oversized media queries
|
|
9899
|
+
remain inert. The package only schedules the callback - each island runtime owns its own markers,
|
|
9900
|
+
registry, signals, and framework integration.
|
|
9901
|
+
|
|
9902
|
+
For AI agents, see [`LLM.md`](./LLM.md). The wider reference is in
|
|
9903
|
+
[`llms-full.txt`](../../llms-full.txt).
|
|
9904
|
+
|
|
8466
9905
|
## @nifrajs/islets
|
|
8467
9906
|
|
|
8468
9907
|
Fine-grained signals + declarative DOM bindings for islands - **interactivity in ~1.4 KB gz**, no
|
|
@@ -8591,6 +10030,12 @@ const q = createQueue({ store: new RedisJobStore(redis) })
|
|
|
8591
10030
|
Leasing is at-least-once: a leased job is hidden for `leaseMs`; a worker that dies mid-job releases it
|
|
8592
10031
|
back automatically. Make handlers **idempotent**.
|
|
8593
10032
|
|
|
10033
|
+
The queue remains agent-agnostic. `@nifrajs/coding-agent` can place content-free run-dispatch
|
|
10034
|
+
identities in a dedicated `JobStore`, but this package does not import or define agent concepts. A
|
|
10035
|
+
`MemoryJobStore` is disposable single-process storage; production durability, authorization,
|
|
10036
|
+
retention, reconciliation, and worker coordination belong to the caller's operated adapter. No
|
|
10037
|
+
exactly-once delivery guarantee is implied by a lease.
|
|
10038
|
+
|
|
8594
10039
|
## Cloudflare Workers
|
|
8595
10040
|
|
|
8596
10041
|
Workers has no long-lived process, so don't call `start()`. Back the queue with a durable store and a
|
|
@@ -8650,6 +10095,10 @@ Mount `mcp.fetch` at `POST /mcp`. The package also exposes the JSON-RPC protocol
|
|
|
8650
10095
|
layers directly, plus `defineMcpWidget` and the React adapter for tool results that render UI in MCP
|
|
8651
10096
|
hosts.
|
|
8652
10097
|
|
|
10098
|
+
Clients that include `text/event-stream` in `Accept` receive progress notifications as they happen,
|
|
10099
|
+
followed by the final JSON-RPC response in the same stream. An SSE `GET /mcp` opens a cancellable
|
|
10100
|
+
server-message connection; a plain `GET /mcp` remains a health page.
|
|
10101
|
+
|
|
8653
10102
|
## For AI agents
|
|
8654
10103
|
|
|
8655
10104
|
Start with [`LLM.md`](./LLM.md) - this package's contract card (the exports you call + its footguns),
|
|
@@ -8779,7 +10228,9 @@ Bun GET, byte-identical on the wire). They are defaults - anything the request p
|
|
|
8779
10228
|
`securityHeaders` and the default `poweredBy` ship this way.
|
|
8780
10229
|
|
|
8781
10230
|
A middleware whose response hook only reads/writes **headers** but needs the request should use the
|
|
8782
|
-
portable `onResponseHeaders` hook -
|
|
10231
|
+
portable `onResponseHeaders` hook - enable the observer surface with
|
|
10232
|
+
`app.use(responseObserver())` from `@nifrajs/core/response-observer` before registering a custom
|
|
10233
|
+
hook. It remains one implementation, fast on every runtime: it mutates the
|
|
8783
10234
|
response's own `Headers` on Bun/Deno and the outcome record on Node's direct socket writer, never
|
|
8784
10235
|
materializing Web `Request`/`Response` objects. `cors` (origin reflection), static `cacheControl`,
|
|
8785
10236
|
`language`, and `poweredBy({ respectExisting: false })` are built on it. Stateful middleware (`rateLimit` with the built-in key derivation,
|
|
@@ -8898,7 +10349,13 @@ authority. If neither option is set, treat the host in `request.url` as client-c
|
|
|
8898
10349
|
|
|
8899
10350
|
The optional `static` root is served before `app.fetch` for GET and HEAD requests. It is a
|
|
8900
10351
|
public asset directory and must contain nothing private: no secrets, source maps, build
|
|
8901
|
-
metadata, or user uploads.
|
|
10352
|
+
metadata, or user uploads. The directory and its ancestor path must be read-only and owned by
|
|
10353
|
+
the service (or otherwise protected from untrusted local writers). Nifra resolves and confines
|
|
10354
|
+
the file before opening it and refuses symlinked final files, but Node does not expose a native
|
|
10355
|
+
per-component `openat` primitive; a process that can mutate the tree concurrently can still
|
|
10356
|
+
create a local TOCTOU race. Mutable or attacker-writable static trees are therefore outside the
|
|
10357
|
+
adapter's guarantee. Store user-controlled files outside the static root and serve them through
|
|
10358
|
+
an application or object-storage path with its own validation policy.
|
|
8902
10359
|
|
|
8903
10360
|
## Graceful shutdown on signals
|
|
8904
10361
|
|
|
@@ -9023,6 +10480,43 @@ one cheap read instead of the whole corpus. For the wider framework: the repo's
|
|
|
9023
10480
|
[`llms-full.txt`](../../llms-full.txt) is the full machine-readable corpus. Run `nifra check` as the
|
|
9024
10481
|
done-gate, or `nifra mcp` to give the agent live project tools.
|
|
9025
10482
|
|
|
10483
|
+
## @nifrajs/pi
|
|
10484
|
+
|
|
10485
|
+
Lightweight Pi JSONL/RPC adapter for the Nifra agent protocol.
|
|
10486
|
+
|
|
10487
|
+
It starts Pi in headless RPC mode, maps Pi lifecycle, assistant, tool,
|
|
10488
|
+
compaction, extension, and error events into `@nifrajs/agent-protocol`, and
|
|
10489
|
+
supports cancellation, reload, session identity, and bounded event buffering.
|
|
10490
|
+
|
|
10491
|
+
Reload defaults to a process restart with the same Pi session ID. This is the
|
|
10492
|
+
reliable reload primitive in Pi's documented RPC protocol: the transcript stays
|
|
10493
|
+
in Pi's session store while the new process loads changed extensions. The tiny
|
|
10494
|
+
public-API bridge is still loaded for interactive Pi use. Set
|
|
10495
|
+
`reloadCommand: "prompt"` only for an RPC implementation that dispatches slash
|
|
10496
|
+
commands, or `reloadCommand: "rpc"` for one that provides a top-level reload
|
|
10497
|
+
command. Set `enableReloadBridge: false` when supplying a custom bridge.
|
|
10498
|
+
|
|
10499
|
+
Set `enableNifraTools: true` to load the separately packaged Pi extension with
|
|
10500
|
+
`nifra_context`, `nifra_check`, `nifra_assure`, and `nifra_test` tools. The
|
|
10501
|
+
default is off so embedding Pi stays minimal.
|
|
10502
|
+
|
|
10503
|
+
```ts
|
|
10504
|
+
import { PiBackend } from "@nifrajs/pi"
|
|
10505
|
+
|
|
10506
|
+
const backend = new PiBackend()
|
|
10507
|
+
const session = await backend.createSession({ cwd: process.cwd() })
|
|
10508
|
+
for await (const event of backend.send({ sessionId: session.id, message: "inspect this project" })) {
|
|
10509
|
+
console.log(event.type)
|
|
10510
|
+
}
|
|
10511
|
+
```
|
|
10512
|
+
|
|
10513
|
+
Pi stays an optional dependency of the agent product. Nothing in this package is
|
|
10514
|
+
reachable from `@nifrajs/core`, `@nifrajs/client`, `@nifrajs/web`, or
|
|
10515
|
+
`@nifrajs/schema`.
|
|
10516
|
+
|
|
10517
|
+
For AI agents, see [`LLM.md`](./LLM.md) and the full corpus
|
|
10518
|
+
[`../../llms-full.txt`](../../llms-full.txt).
|
|
10519
|
+
|
|
9026
10520
|
## @nifrajs/prompt
|
|
9027
10521
|
|
|
9028
10522
|
Provider-neutral, type-safe prompts with Standard Schema input and validated structured output.
|
|
@@ -9076,7 +10570,7 @@ const upstream = createProxy({ upstream: "http://127.0.0.1:8081" })
|
|
|
9076
10570
|
const app = server().mountFetch("/api", upstream, { stripPrefix: true })
|
|
9077
10571
|
```
|
|
9078
10572
|
|
|
9079
|
-
The upstream is a **bare origin** fixed at construction - the forwarded URL is built by mutating a clone of that origin, never by resolving request-derived strings, so no request input can change which host is dialed. Hop-by-hop and `Connection`-nominated headers are stripped in both directions
|
|
10573
|
+
The upstream is a **bare origin** fixed at construction - the forwarded URL is built by mutating a clone of that origin, never by resolving request-derived strings, so no request input can change which host is dialed. Hop-by-hop and `Connection`-nominated headers are stripped in both directions. Caller IP/protocol metadata is dropped unless `forwardClientIp: true`; the inbound Host is never trusted, and `X-Forwarded-Host` is emitted only from a fixed `forwardedHost`. Upstream redirects are never followed, and TLS verification has no off switch. Unreachable upstreams answer a flat `502`; the deadline (`timeoutMs`, default 30s) answers `504`.
|
|
9080
10574
|
|
|
9081
10575
|
## Docs
|
|
9082
10576
|
|
|
@@ -9238,6 +10732,11 @@ pi install npm:@nifrajs/skills
|
|
|
9238
10732
|
/plugin install nifra@nifra
|
|
9239
10733
|
```
|
|
9240
10734
|
|
|
10735
|
+
The plugin registers the Nifra MCP server as well as the skills, so a fresh install has the live tools
|
|
10736
|
+
the skills tell it to prefer. Its launch spec is deliberately unpinned - a plugin is installed once and
|
|
10737
|
+
opened against many projects, so the CLI resolves per project and the server reports version skew
|
|
10738
|
+
itself rather than freezing one version across all of them.
|
|
10739
|
+
|
|
9241
10740
|
**Anything that reads a skills directory** (Cursor, `.agents/skills`, a project `.pi/skills`)
|
|
9242
10741
|
|
|
9243
10742
|
```sh
|
|
@@ -9254,6 +10753,9 @@ against the version installed in the project being edited:
|
|
|
9254
10753
|
bunx @nifrajs/cli init-agents # register the MCP server in an existing app
|
|
9255
10754
|
```
|
|
9256
10755
|
|
|
10756
|
+
The Claude Code plugin brings its own copy of that server, so `init-agents` is for the other surfaces -
|
|
10757
|
+
and for committing a version-pinned `.mcp.json` that every contributor on the project shares.
|
|
10758
|
+
|
|
9257
10759
|
Not in a Nifra project? The docs tools are hosted at `https://mcp.nifra.dev`.
|
|
9258
10760
|
|
|
9259
10761
|
That split is the anti-drift design: a skill that restated the API would rot on the next release,
|
|
@@ -9533,6 +11035,14 @@ that every call carries and captures cookies via a shared jar.
|
|
|
9533
11035
|
|
|
9534
11036
|
For a **stateless** request (no cookies), use `testClient` from `@nifrajs/client` directly.
|
|
9535
11037
|
|
|
11038
|
+
### Agent evaluation and failure matrix
|
|
11039
|
+
|
|
11040
|
+
`runAgentEvalComposition` composes trajectory replay, fault profiles, contract invariants,
|
|
11041
|
+
idempotency proofs, and adapter certification. Reports expose explicit invariant and rubric cases,
|
|
11042
|
+
stable regression IDs, schedule tokens, and digests; they do not retain prompts, tool payloads,
|
|
11043
|
+
model output, labels, or a single opaque quality score. The failure matrix covers model, tool,
|
|
11044
|
+
approval, cancellation, lease, cursor, registry, and deployment boundaries.
|
|
11045
|
+
|
|
9536
11046
|
## For AI agents
|
|
9537
11047
|
|
|
9538
11048
|
Start with [`LLM.md`](./LLM.md) - this package's contract card (the exports you call + its footguns),
|
|
@@ -9743,6 +11253,14 @@ Zero-framework render adapter for @nifrajs/web - auto-escaping tagged-template H
|
|
|
9743
11253
|
|
|
9744
11254
|
Part of the **[nifra](https://nifra.dev)** full-stack TypeScript framework - one core, five UI libraries, every runtime. Scaffold a new app with `bun create nifra`.
|
|
9745
11255
|
|
|
11256
|
+
## The AI-safe lane
|
|
11257
|
+
|
|
11258
|
+
Vanilla is the render adapter an agent gets right on the first try. It ships no framework runtime, so there is no hydration, no reactivity, and none of the failure modes (stale closures, hydration mismatch, what-re-runs-when) that trip up generated code. You get true SSR plus every server feature - loaders, actions, ISR/SSG, streaming, head management - unchanged from `@nifrajs/web`; those live in the core, not the view layer.
|
|
11259
|
+
|
|
11260
|
+
Interactivity is added with **islands**, not hydration: small imperative DOM enhancers over server-rendered elements. `defineIsland` types the props, `createIslandBus` coordinates islands over a typed channel, and every enhancer returns its cleanup - the one rule `nifra check` enforces (`NF-C020`). See the [islands cookbook](https://nifra.dev/docs/islands) for the counter, cart-badge, and filter patterns, or run `nifra scaffold` on a vanilla route for the golden stub.
|
|
11261
|
+
|
|
11262
|
+
Need a stateful app UI with reactive components? That is what the five framework adapters are for - reach for `@nifrajs/web-preact` or `@nifrajs/web-solid` when you want a small reactive runtime.
|
|
11263
|
+
|
|
9746
11264
|
## Install
|
|
9747
11265
|
|
|
9748
11266
|
```sh
|
|
@@ -9903,13 +11421,29 @@ done-gate, or `nifra mcp` to give the agent live project tools.
|
|
|
9903
11421
|
|
|
9904
11422
|
# Complete export index (generated from each package's src/index.ts)
|
|
9905
11423
|
|
|
11424
|
+
## @nifrajs/a2a
|
|
11425
|
+
|
|
11426
|
+
`A2A_ERROR_CODES`, `A2A_PROTOCOL_VERSION`, `A2AAgentCard`, `A2AAgentSkill`, `A2ACardInfo`, `A2AMountableApp`, `A2ARouteContext`, `A2ATaskState`, `AGENT_CARD_WELL_KNOWN_PATH`, `agentCard`, `mountA2A`, `MountA2AOptions`
|
|
11427
|
+
|
|
11428
|
+
## @nifrajs/ag-ui
|
|
11429
|
+
|
|
11430
|
+
`AgUIMountableApp`, `AgUIRouteContext`, `AgUIRunContext`, `AgUIRunUsage`, `mountAgUI`, `MountAgUIOptions`
|
|
11431
|
+
|
|
9906
11432
|
## @nifrajs/agent
|
|
9907
11433
|
|
|
9908
|
-
`AgentApprovalPort`, `AgentApprovalResult`, `AgentDefinition`, `AgentModelPort`, `AgentModelRequest`, `AgentModelResponse`, `AgentPendingContinuation`, `AgentPendingKind`, `AgentPorts`, `AgentRunResult`, `AgentStateStore`, `AgentStatus`, `AgentStepEvidence`, `AgentTelemetryPort`, `AgentToolContract`, `AgentToolDescriptor`, `AgentToolResult`, `AgentTranscript`, `AgentTurnBaseResult`, `AgentTurnError`, `AgentTurnInput`, `AgentTurnResult`, `AgentTurnState`, `createAgentState`, `createLocalProcessAdapter`, `ExecutionPolicy`, `ExecutionPolicyAdapter`, `LOCAL_PROCESS_LIMITATION`, `LocalProcessAdapter`, `LocalProcessAdapterOptions`, `LocalProcessPolicyError`, `LocalProcessRequest`, `LocalProcessResult`, `MemoryAgentStateStore`, `replayAgent`, `resumeAgent`, `runAgent`, `RunAgentOptions`, `turn`
|
|
11434
|
+
`AgentApprovalPort`, `AgentApprovalResult`, `AgentDefinition`, `AgentDeltaSink`, `AgentDeployment`, `AgentDeploymentAdapter`, `AgentDeploymentPlan`, `AgentModelDelta`, `AgentModelPort`, `AgentModelRequest`, `AgentModelResponse`, `AgentPendingContinuation`, `AgentPendingKind`, `AgentPorts`, `AgentRunResult`, `AgentSharedState`, `AgentStatePatchOp`, `AgentStateStore`, `AgentStatus`, `AgentStepEvidence`, `AgentTelemetryPort`, `AgentToolContract`, `AgentToolDescriptor`, `AgentToolResult`, `AgentTranscript`, `AgentTurnBaseResult`, `AgentTurnError`, `AgentTurnInput`, `AgentTurnResult`, `AgentTurnState`, `ApprovalClass`, `assertDeploymentAuthorityMonotonic`, `CAPABILITY_DESCRIPTOR_VERSION`, `CapabilityDescriptor`, `CapabilityKind`, `combineAgentDeltaSinks`, `combineAgentTelemetry`, `composeDescriptor`, `composeRegistrySnapshot`, `createAgentSharedState`, `createAgentState`, `createDeploymentAuthority`, `createLocalProcessAdapter`, `createStructuredOutputParser`, `DeploymentActivationOptions`, `DeploymentAuthority`, `DeploymentCancellation`, `DeploymentCancelRequest`, `DeploymentCancelResult`, `DeploymentCapabilities`, `DeploymentCapabilityReport`, `DeploymentDisposeRequest`, `DeploymentDisposeResult`, `DeploymentError`, `DeploymentErrorCode`, `DeploymentEvidence`, `DeploymentFilesystem`, `DeploymentInspection`, `DeploymentInspectRequest`, `DeploymentNetwork`, `DeploymentPrepareRequest`, `DeploymentPrepareResult`, `DeploymentProcess`, `DeploymentRuntime`, `DeploymentSecrets`, `DeploymentStartRequest`, `DeploymentStartResult`, `DeploymentState`, `descriptorFromTool`, `DescriptorInput`, `ExecutionPolicy`, `ExecutionPolicyAdapter`, `FakeModelGateway`, `FakeModelGatewayOptions`, `HostileCodeIsolation`, `IdempotencyClass`, `isModelGatewayErrorCode`, `IsolationClass`, `LOCAL_PROCESS_LIMITATION`, `LocalProcessAdapter`, `LocalProcessAdapterOptions`, `LocalProcessPolicyError`, `LocalProcessRequest`, `LocalProcessResult`, `MemoryAgentStateStore`, `MODEL_GATEWAY_ERROR_CODES`, `ModelGateway`, `ModelGatewayAttemptRequest`, `ModelGatewayBudget`, `ModelGatewayEnvelope`, `ModelGatewayError`, `ModelGatewayErrorCode`, `ModelGatewayEvidence`, `ModelGatewayExecutionResult`, `ModelGatewayFailure`, `ModelGatewayFailureError`, `ModelGatewayRawResult`, `ModelGatewayRequest`, `ModelGatewayResult`, `ModelGatewaySuccess`, `ModelGatewayTerminalFailure`, `ModelGatewayUsage`, `ModelRoute`, `ModelRoutePolicy`, `ModelRouteRef`, `parseCapabilityDescriptor`, `parseDeploymentCapabilityReport`, `parseDeploymentPlan`, `parseModelGatewayError`, `parseModelGatewayResult`, `REGISTRY_SNAPSHOT_VERSION`, `RegistryError`, `RegistryErrorCode`, `RegistrySnapshot`, `replayAgent`, `ReplayModelGateway`, `ReplayModelGatewayOptions`, `resumeAgent`, `RetryClass`, `runAgent`, `RunAgentOptions`, `runModelGateway`, `structuredOutputParser`, `StructuredOutputParser`, `ToolDescriptorOptions`, `turn`
|
|
11435
|
+
|
|
11436
|
+
## @nifrajs/agent-app
|
|
11437
|
+
|
|
11438
|
+
`AGENT_APP_FEATURES`, `AgentAppClient`, `AgentAppClientOptions`, `AgentAppError`, `AgentEventView`, `AgentTransport`, `AgentTransportError`, `AgentTransportRequest`, `ApprovalRequiredView`, `ApprovalResolvedView`, `AssistantChunkView`, `AuthProvider`, `boundaryCommands`, `BoundaryDecisionResult`, `boundaryIsStale`, `BoundaryItemView`, `BoundaryStateView`, `CommandOutcome`, `CreateSessionInput`, `EvalComparisonView`, `EvidenceTimelineView`, `ExtensionReloadedView`, `FaultInjectionView`, `HandoffView`, `HttpAgentTransport`, `HttpAgentTransportOptions`, `MemoryCompactedView`, `OrderedEventBuffer`, `parseEventStream`, `PendingApprovalView`, `RegistryCapabilityView`, `RepairRequiredView`, `ReplayEntryView`, `ReplayResult`, `ResolveHandoffInput`, `ResumeInput`, `RunStudioNodeState`, `RunStudioNodeView`, `RunStudioView`, `RunView`, `SessionFailedView`, `SessionLifecycleView`, `SessionStoppedView`, `SessionView`, `toEvalComparisonView`, `toEventView`, `toEvidenceTimelineView`, `toFaultInjectionViews`, `toHandoffView`, `ToolCompletedView`, `ToolDeltaView`, `ToolStartedView`, `toRegistryCapabilityView`, `toRunStudioView`, `toRunView`, `toSessionView`, `TurnStartedView`, `VerificationCompletedView`, `virtualizeEvidenceRows`
|
|
11439
|
+
|
|
11440
|
+
## @nifrajs/agent-protocol
|
|
11441
|
+
|
|
11442
|
+
`AGENT_PROTOCOL_VERSION`, `AgentApprovalRequiredEvent`, `AgentApprovalResolvedEvent`, `AgentAssistantDeltaEvent`, `AgentAssistantMessageEvent`, `AgentBackend`, `AgentBackendInfo`, `agentError`, `AgentError`, `AgentEvent`, `AgentEventPayload`, `AgentEventSink`, `AgentEventStream`, `AgentEventType`, `AgentExtensionReloadedEvent`, `AgentMemoryCompactedEvent`, `AgentRepairRequiredEvent`, `AgentRepairTask`, `AgentSessionCheckpoint`, `AgentSessionCompletedEvent`, `AgentSessionEventBase`, `AgentSessionFailedEvent`, `AgentSessionSnapshot`, `AgentSessionStartedEvent`, `AgentSessionStatus`, `AgentSessionStoppedEvent`, `AgentSessionUpdatedEvent`, `AgentToolCompletedEvent`, `AgentToolDeltaEvent`, `AgentToolStartedEvent`, `AgentTurnStartedEvent`, `AgentVerificationCompletedEvent`, `createAgentEventStream`, `CreateSessionInput`, `ForkSessionInput`, `ForkSessionResult`, `isAgentEvent`, `ReloadResult`, `SendMessageInput`
|
|
9909
11443
|
|
|
9910
11444
|
## @nifrajs/agent-telemetry
|
|
9911
11445
|
|
|
9912
|
-
`agentTelemetry`, `AgentTelemetryOptions`, `consoleAgentExporter`
|
|
11446
|
+
`AgentRunEvidence`, `AgentRunOutcome`, `AgentRunTrace`, `agentTelemetry`, `AgentTelemetryOptions`, `consoleAgentExporter`, `orchestrationTelemetry`, `OrchestrationTelemetry`, `OrchestrationTelemetryEvent`, `OrchestrationTelemetryKind`, `OrchestrationTelemetryOptions`, `traceAgentRun`, `TraceAgentRunOptions`
|
|
9913
11447
|
|
|
9914
11448
|
## @nifrajs/auth
|
|
9915
11449
|
|
|
@@ -9929,15 +11463,19 @@ done-gate, or `nifra mcp` to give the agent live project tools.
|
|
|
9929
11463
|
|
|
9930
11464
|
## @nifrajs/client
|
|
9931
11465
|
|
|
9932
|
-
`ActionArgs`, `ActionData`, `ApiError`, `ApiProxy`, `client`, `ClientOptions`, `ClientRetryOptions`, `FetchFn`, `inProcessClient`, `InProcessClient`, `InProcessClientOptions`, `Jsonify`, `LoaderArgs`, `LoaderData`, `RegistryOf`, `ResponseContractViolation`, `Result`, `SubscribeOptions`, `Subscription`, `testClient`, `Treaty`, `TreatyFromRegistry`, `WsCallOptions`, `WsHandle`
|
|
11466
|
+
`ActionArgs`, `ActionData`, `ApiError`, `ApiProxy`, `client`, `ClientOptions`, `ClientRetryOptions`, `FetchFn`, `inProcessClient`, `InProcessClient`, `InProcessClientOptions`, `Jsonify`, `LoaderArgs`, `LoaderData`, `RegistryOf`, `RESERVED_EXACT_KEYS`, `RESERVED_KEY_READOUT`, `RESERVED_VERB_KEYS`, `reservedKeyFor`, `ResponseContractViolation`, `Result`, `SubscribeOptions`, `Subscription`, `testClient`, `Treaty`, `TreatyFromRegistry`, `WsCallOptions`, `WsHandle`
|
|
11467
|
+
|
|
11468
|
+
## @nifrajs/coding-agent
|
|
11469
|
+
|
|
11470
|
+
`AGENT_CAPABILITY_MANIFEST_VERSION`, `AGENT_PRESETS`, `AgentCapability`, `AgentCapabilityManifest`, `AgentPlan`, `AgentPreset`, `AgentPresetName`, `ApprovalDecision`, `ApprovalManager`, `ApprovalManagerOptions`, `ApprovalMatchRejection`, `ApprovalMatchResult`, `ApprovalRequest`, `approvalRequestFromEvent`, `approvalResolvedEvent`, `BoundedSubagentRunner`, `BoundedText`, `CapabilityDescriptor`, `CiDeploymentAdapter`, `CodingAgentExtension`, `CodingAgentHost`, `CodingAgentHostOptions`, `CodingAgentRpcServer`, `CodingAgentRpcServerHandle`, `CodingAgentRpcServerOptions`, `CompactionReport`, `ContextRecord`, `ContextWindow`, `ContextWindowOptions`, `createCapabilityManifest`, `createCiDeploymentAdapter`, `createLocalProcessDeploymentAdapter`, `createNativeGatewayModelPort`, `createNifraTools`, `createPresetSpec`, `createReplayDeploymentAdapter`, `createVerificationRepairTask`, `deniedCapabilities`, `DEPLOYMENT_REFERENCE_PROFILES`, `discoverExtensions`, `ExtensionCommand`, `ExtensionContext`, `extensionDescriptor`, `ExtensionDescriptorOptions`, `extensionDescriptors`, `ExtensionDescriptorSource`, `ExtensionEventHandler`, `ExtensionHost`, `ExtensionHostOptions`, `ExtensionProvider`, `ExtensionReloadResult`, `ExtensionSubagent`, `ExtensionTool`, `FileSessionStore`, `FileSessionStoreOptions`, `getAgentPreset`, `HandoffCoordinator`, `HandoffCoordinatorOptions`, `HandoffDecision`, `HandoffError`, `HandoffRejection`, `HandoffView`, `HealingEvent`, `HealingOptions`, `HealingResult`, `IsolatedExtensionSnapshot`, `IsolatedExtensionTool`, `IsolatedExtensionWorker`, `IsolatedExtensionWorkerOptions`, `LocalProcessDeploymentAdapter`, `migrateLegacySession`, `MigrateLegacySessionOptions`, `NativeApprovalPort`, `NativeGatewayModelPortOptions`, `NativeMessage`, `NativeModelChunk`, `NativeModelPort`, `NativeModelRequest`, `NativeModelResponse`, `NativeTool`, `NIFRA_AGENT_INSTRUCTIONS`, `NifraAgentTool`, `NifraBackend`, `NifraBackendOptions`, `NifraContextOptions`, `NifraContextResult`, `OpenHandoffInput`, `parseCapabilityManifest`, `parseSessionEvidenceRecord`, `PiBackend`, `PiBackendOptions`, `PlanEvent`, `PlanPhase`, `PlanResult`, `PlanRunner`, `PlanRunnerOptions`, `ProjectDiffOptions`, `ProjectDiffResult`, `readBoundedText`, `readProjectDiff`, `readReplayEvents`, `RepairProposal`, `ReplayBackend`, `ReplayBackendOptions`, `ReplayDeploymentAdapter`, `runNifraContext`, `runNifraVerification`, `SelfHealingController`, `SESSION_EVIDENCE_VERSION`, `SessionEvidenceRecord`, `SessionLogEntry`, `SessionMigrationError`, `SessionMigrationReport`, `SessionStore`, `stableSessionEventCode`, `SubagentExecutor`, `SubagentResult`, `SubagentRunnerOptions`, `SubagentSpec`, `UiExtensionHost`, `UiExtensionHostOptions`, `UiExtensionManifest`, `UiExtensionSlot`, `UiReloadResult`, `UiStatusWidget`, `UiThemeDescriptor`, `validateExtensionModule`, `VerificationOptions`, `VerificationRepairTask`, `VerificationResult`, `WorkflowContext`, `WorkflowEvent`, `WorkflowResult`, `WorkflowRunner`, `WorkflowRunnerOptions`, `WorkflowStep`
|
|
9933
11471
|
|
|
9934
11472
|
## @nifrajs/content
|
|
9935
11473
|
|
|
9936
|
-
`bakeCollection`, `BakedCollection`, `Entry`, `fromBaked`, `InferSchema`, `parseEntry`, `ParseEntryOptions`, `parseFrontmatter`, `StandardSchemaV1`, `StaticCollection`
|
|
11474
|
+
`bakeCollection`, `BakedCollection`, `BakedCollectionIndex`, `BakedCollectionJoin`, `BakedIndexBucket`, `ContentFieldKey`, `Entry`, `fromBaked`, `fromBakedIndex`, `fromBakedJoin`, `indexCollection`, `IndexedCollection`, `IndexedJoin`, `IndexOptions`, `IndexPage`, `IndexQueryOptions`, `IndexRange`, `IndexRanges`, `IndexSort`, `IndexWhere`, `InferSchema`, `JoinCardinality`, `joinCollections`, `JoinedRow`, `parseEntry`, `ParseEntryOptions`, `parseFrontmatter`, `SharedKey`, `StandardSchemaV1`, `StaticCollection`
|
|
9937
11475
|
|
|
9938
11476
|
## @nifrajs/core
|
|
9939
11477
|
|
|
9940
|
-
`Version`, `VERSION`
|
|
11478
|
+
`AdmissionController`, `AdmissionDecision`, `AnyServer`, `commonSecretPatterns`, `Context`, `ContextPlugin`, `cookieNamePrefix`, `CookieOptions`, `CookieSecret`, `defineContextPlugin`, `defineIdentityPlugin`, `definePlugin`, `DefinePluginResult`, `defineRouterPlugin`, `DurableObjectNamespaceLike`, `ExecutionContext`, `FetchApp`, `FRAMEWORK_NAME`, `FrameworkError`, `FrameworkName`, `Handler`, `IdentityPlugin`, `InferInput`, `InferOutput`, `isSameOriginPath`, `isSameOriginRequest`, `jsonLogger`, `LambdaEvent`, `LambdaHandler`, `LambdaResponse`, `LambdaV1Event`, `LambdaV2Event`, `LogFields`, `Logger`, `McpPromptDescriptor`, `McpResourceDescriptor`, `Method`, `METHODS`, `Middleware`, `NetlifyEvent`, `NetlifyHandler`, `NifraFeatureVersion`, `NifraPlugin`, `NifraWebSocket`, `NodeRequestContext`, `NodeRequestHook`, `NodeResponseContext`, `NodeResponseHook`, `NodeServeOutcome`, `OnRequestResult`, `Params`, `parseCookies`, `pathnameOf`, `PlainRender`, `Platform`, `PlatformResponse`, `PluginTypeCollapsed`, `Prettify`, `PromptArgument`, `PromptMessage`, `redactLogFields`, `RedactOptions`, `Registry`, `ResponseBodyHook`, `ResponseBodyReplacement`, `ResponseControls`, `ResponseFinalization`, `ResponseHeadersHook`, `ResponseHeadersView`, `ResponseMapFor`, `ResponseResult`, `RouteConfigError`, `RouteConfigErrorCode`, `RouteDescriptor`, `RouteInfo`, `RouteInfoFor`, `Router`, `RouterMatch`, `RouteSchema`, `RunningServer`, `ScheduledController`, `ScheduledHandler`, `serializeCookie`, `server`, `Server`, `ServerOptions`, `signValue`, `silentLogger`, `SSEContext`, `SSEInit`, `SSEMessage`, `SSEStream`, `StandardIssue`, `StandardResult`, `StandardSchemaV1`, `StandardTypes`, `StandardWebSocket`, `status`, `StatusResponse`, `toFetchHandler`, `toLambdaHandler`, `toNetlifyHandler`, `ToolAnnotations`, `toVercelHandler`, `TypedSSEStream`, `unsignValue`, `UrlParts`, `urlPartsOf`, `ValidationOutcome`, `VercelHandler`, `Version`, `VERSION`, `WebSocketContext`, `WebSocketData`, `WebSocketHandler`, `WebSocketUpgradeOutcome`
|
|
9941
11479
|
|
|
9942
11480
|
## @nifrajs/cron
|
|
9943
11481
|
|
|
@@ -9951,6 +11489,10 @@ done-gate, or `nifra mcp` to give the agent live project tools.
|
|
|
9951
11489
|
|
|
9952
11490
|
`devtools`, `DevToolsClientOptions`, `devtoolsClientScript`, `DevToolsEvent`, `DevToolsOptions`, `DevToolsQuery`, `filterDevToolsEvents`
|
|
9953
11491
|
|
|
11492
|
+
## @nifrajs/edge
|
|
11493
|
+
|
|
11494
|
+
`EdgeContext`, `EdgeHandler`, `EdgeOptions`, `EdgeServer`, `Method`, `Params`, `QueryValue`, `server`, `StandardSchemaV1`, `toFetchHandler`
|
|
11495
|
+
|
|
9954
11496
|
## @nifrajs/env
|
|
9955
11497
|
|
|
9956
11498
|
`boolean`, `defineEnv`, `DefineEnvOptions`, `enumValue`, `env`, `EnvResult`, `EnvShape`, `InferOutput`, `number`, `port`, `StandardResult`, `StandardSchemaV1`, `string`, `url`
|
|
@@ -9959,6 +11501,10 @@ done-gate, or `nifra mcp` to give the agent live project tools.
|
|
|
9959
11501
|
|
|
9960
11502
|
`createEventRegistry`, `defineEventContract`, `EventContract`, `EventContractError`, `EventEnvelope`, `EventParseResult`, `EventRegistry`, `RegistryParseResult`
|
|
9961
11503
|
|
|
11504
|
+
## @nifrajs/graphql
|
|
11505
|
+
|
|
11506
|
+
`buildContext`, `createPubSub`, `GraphqlContextBuilder`, `GraphqlContextInput`, `GraphqlHttpOptions`, `GraphqlPubSub`, `graphqlWebSocket`, `GraphqlWsOptions`, `mountGraphql`, `MountGraphqlOptions`, `NifraContextLike`, `respondGraphql`
|
|
11507
|
+
|
|
9962
11508
|
## @nifrajs/i18n
|
|
9963
11509
|
|
|
9964
11510
|
`createFormatter`, `Formatter`, `Locale`, `LocaleParts`, `LocaleSource`, `Messages`, `negotiateLocale`, `NegotiateOptions`, `ResolvedLocale`, `resolveLocale`
|
|
@@ -9967,9 +11513,13 @@ done-gate, or `nifra mcp` to give the agent live project tools.
|
|
|
9967
11513
|
|
|
9968
11514
|
`cloudflareLoader`, `CloudflareLoaderOptions`, `createPngRasterizer`, `createResvgRasterizer`, `HtmlImageAttrs`, `identityLoader`, `imageDimensions`, `ImageFormat`, `ImageInfo`, `ImageLoader`, `ImageProps`, `OgImageOptions`, `OgImageRasterized`, `OgImageRasterizer`, `ogImageResponse`, `PngRenderer`, `readImageDimensions`, `renderOgImage`, `ResolvedImage`, `resolveImage`, `ResvgConstructor`, `ResvgRenderer`, `selfHostedLoader`, `SelfHostedLoaderOptions`, `signImageUrl`, `SignImageUrlOptions`, `toHtmlAttrs`
|
|
9969
11515
|
|
|
11516
|
+
## @nifrajs/island-trigger
|
|
11517
|
+
|
|
11518
|
+
`IslandStrategy`, `MAX_MEDIA_QUERY_LENGTH`, `scheduleTrigger`, `TriggerOptions`
|
|
11519
|
+
|
|
9970
11520
|
## @nifrajs/islets
|
|
9971
11521
|
|
|
9972
|
-
`batch`, `BindableElement`, `BindableRoot`, `bindScope`, `computed`, `effect`, `island`, `IslandContext`, `IslandHost`, `IslandScope`, `IslandSetup`, `islandState`, `mountIslands`, `signal`, `Signal`
|
|
11522
|
+
`batch`, `BindableElement`, `BindableRoot`, `bindScope`, `computed`, `effect`, `island`, `IslandContext`, `IslandHost`, `IslandScope`, `IslandSetup`, `islandState`, `IslandStrategy`, `MountIslandOptions`, `mountIslands`, `signal`, `Signal`
|
|
9973
11523
|
|
|
9974
11524
|
## @nifrajs/jobs
|
|
9975
11525
|
|
|
@@ -9999,13 +11549,17 @@ done-gate, or `nifra mcp` to give the agent live project tools.
|
|
|
9999
11549
|
|
|
10000
11550
|
`ActiveObservation`, `AttributeValue`, `causalitySpanLink`, `combineObservationAdapters`, `consoleSpanExporter`, `createObservationLifecycle`, `effectTracing`, `EffectTracingOptions`, `EffectTracingPlugin`, `EndObservation`, `formatTraceparent`, `generateSpanId`, `generateTraceId`, `NifraSpan`, `ObservationAdapter`, `ObservationClock`, `ObservationContext`, `ObservationLifecycle`, `ObservationLifecycleOptions`, `ObservationLink`, `ObservationParent`, `otlpExporter`, `OtlpExporter`, `OtlpExporterOptions`, `ParsedTraceparent`, `parseTraceparent`, `SpanStatus`, `StartObservation`, `TraceContext`, `traceHeaders`, `tracing`, `TracingOptions`
|
|
10001
11551
|
|
|
11552
|
+
## @nifrajs/pi
|
|
11553
|
+
|
|
11554
|
+
`PiBackend`, `PiBackendOptions`
|
|
11555
|
+
|
|
10002
11556
|
## @nifrajs/prompt
|
|
10003
11557
|
|
|
10004
11558
|
`prompt`, `Prompt`, `PromptInputError`, `PromptMessage`, `PromptOutputError`, `PromptRequest`, `PromptResponseFormat`, `RunOptions`
|
|
10005
11559
|
|
|
10006
11560
|
## @nifrajs/proxy
|
|
10007
11561
|
|
|
10008
|
-
`createProxy`, `ProxyContext`, `ProxyHandler`, `ProxyOptions`
|
|
11562
|
+
`createProxy`, `fetchTransport`, `FetchTransportOptions`, `NativeProxyTransport`, `NativeProxyTransportRequest`, `NativeProxyUpstreamResponse`, `NodeNativeProxyRequest`, `NodeNativeProxyResponse`, `ProxyContext`, `ProxyHandler`, `ProxyOptions`, `ProxyTransport`, `ProxyUpstreamRequest`, `ProxyUpstreamResponse`
|
|
10009
11563
|
|
|
10010
11564
|
## @nifrajs/runner
|
|
10011
11565
|
|
|
@@ -10021,7 +11575,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
|
|
|
10021
11575
|
|
|
10022
11576
|
## @nifrajs/testing
|
|
10023
11577
|
|
|
10024
|
-
`AdapterCertificationError`, `AdapterCertificationProfile`, `AdapterCertificationReport`, `AdversarialContractError`, `AdversarialContractOptions`, `AdversarialContractReport`, `AdversarialContractResult`, `AppLike`, `assertAdapterCertification`, `assertAdversarialContract`, `assertIncidentReplays`, `assertTrajectoryInvariants`, `cacheStoreCertificationProfile`, `CapturedRequest`, `CapturedRequestInput`, `captureIncident`, `CaptureIncidentOptions`, `CertifiableCacheEntry`, `CertifiableCacheStore`, `CertifiableDomainEvent`, `CertifiableEventDeliveryAdapter`, `CertifiableEventRecord`, `CertifiableJobStore`, `CertifiableRuntimeAdapter`, `CertifiableRuntimeServer`, `CertifiableStorageAdapter`, `CertificationCapabilityEvidence`, `CertificationCheck`, `CertificationCheckEvidence`, `certifyAdapter`, `checkTrajectoryInvariants`, `ContractCaseContext`, `ContractCaseKind`, `ContractCoverageGap`, `ContractCoverageGapCode`, `ContractReplay`, `ContractRuntime`, `ContractTarget`, `ContractTestApp`, `ContractWitness`, `cookieJar`, `CookieJar`, `createFailureLab`, `createTrajectoryTranscript`, `CreateTrajectoryTranscriptOptions`, `defineCertificationProfile`, `defineFaultProfile`, `EffectLedger`, `eventDeliveryCertificationProfile`, `FailureDirective`, `FailureEvidence`, `FailureInjectedError`, `FailureKind`, `FailureLab`, `FailureLabOptions`, `FailureReplay`, `FailureScenario`, `FailureScenarioReport`, `FaultProfile`, `FaultProfileFault`, `FaultProfileFaultKind`, `FaultProfileReport`, `FaultProfileScenario`, `FaultProfileScenarioReport`, `generateRegressionTest`, `GenerateRegressionTestOptions`, `httpToolAdapter`, `IdempotencyDivergence`, `IdempotencyProof`, `IncidentCapsule`, `IncidentReplayError`, `IncidentReplayResult`, `inProcessToolAdapter`, `jobStoreCertificationProfile`, `mcpToolAdapter`, `proveIdempotency`, `recordTrajectory`, `redactForEmission`, `referenceFaultProfile`, `replayIncident`, `ReplayIncidentOptions`, `replayTrajectory`, `ReplayTrajectoryOptions`, `runAdversarialContract`, `runFailureScenario`, `runFaultProfile`, `RunFaultProfileOptions`, `runtimeAdapterCertificationProfile`, `runTrajectory`, `shapeOf`, `storageAdapterCertificationProfile`, `testSession`, `TestSession`, `TestSessionOptions`, `testToolAdapter`, `TrajectoryInvariantId`, `TrajectoryInvariantOptions`, `TrajectoryInvariantResult`, `trajectoryRegressionId`, `TrajectoryReplayResult`, `TrajectoryRun`, `TrajectoryTranscript`, `verifyAdapterCertification`
|
|
11578
|
+
`AdapterCertificationError`, `AdapterCertificationProfile`, `AdapterCertificationReport`, `AdversarialContractError`, `AdversarialContractOptions`, `AdversarialContractReport`, `AdversarialContractResult`, `AgentEvalCase`, `AgentEvalComponentEvidence`, `AgentEvalCompositionOptions`, `AgentEvalCompositionReport`, `AgentEvalRegressionError`, `AgentEvalReport`, `AgentEvalSuite`, `AgentEvalSuiteSpec`, `AgentFailureMatrixCase`, `AgentFailureMatrixError`, `AgentFailureMatrixKind`, `AgentFailureMatrixReport`, `AppLike`, `assertAdapterCertification`, `assertAdversarialContract`, `assertAgentEval`, `assertAgentEvalBaseline`, `assertAgentFailureMatrix`, `assertIncidentReplays`, `assertTrajectoryInvariants`, `BaselineComparison`, `BaselineOptions`, `cacheStoreCertificationProfile`, `CapturedRequest`, `CapturedRequestInput`, `captureIncident`, `CaptureIncidentOptions`, `CaseComparison`, `CaseResult`, `CertifiableCacheEntry`, `CertifiableCacheStore`, `CertifiableDeploymentAdapter`, `CertifiableDescriptorAdapter`, `CertifiableDomainEvent`, `CertifiableEventDeliveryAdapter`, `CertifiableEventRecord`, `CertifiableJobStore`, `CertifiableModelGateway`, `CertifiableRuntimeAdapter`, `CertifiableRuntimeServer`, `CertifiableStorageAdapter`, `CertificationCapabilityEvidence`, `CertificationCheck`, `CertificationCheckEvidence`, `certifyAdapter`, `checkTrajectoryInvariants`, `compareAgentEvalBaseline`, `ComparisonCode`, `ContractCaseContext`, `ContractCaseKind`, `ContractCoverageGap`, `ContractCoverageGapCode`, `ContractLabHandler`, `ContractLabRuntimeAdapter`, `ContractLabServer`, `ContractLabWitness`, `contractLabWitnesses`, `ContractReplay`, `ContractRuntime`, `ContractTarget`, `ContractTestApp`, `ContractWitness`, `cookieJar`, `CookieJar`, `createFailureLab`, `createReferenceContractLabHandler`, `createTrajectoryTranscript`, `CreateTrajectoryTranscriptOptions`, `defineAgentEvalSuite`, `defineCertificationProfile`, `defineFaultProfile`, `deploymentAdapterCertificationProfile`, `deploymentCertificationProfile`, `EffectLedger`, `eventDeliveryCertificationProfile`, `FailureDirective`, `FailureEvidence`, `FailureInjectedError`, `FailureKind`, `FailureLab`, `FailureLabOptions`, `FailureReplay`, `FailureScenario`, `FailureScenarioReport`, `FaultProfile`, `FaultProfileFault`, `FaultProfileFaultKind`, `FaultProfileReport`, `FaultProfileScenario`, `FaultProfileScenarioReport`, `gatewayCertificationProfile`, `generateRegressionTest`, `GenerateRegressionTestOptions`, `httpToolAdapter`, `IdempotencyDivergence`, `IdempotencyProof`, `IncidentCapsule`, `IncidentReplayError`, `IncidentReplayResult`, `inProcessToolAdapter`, `jobStoreCertificationProfile`, `mcpToolAdapter`, `modelGatewayCertificationProfile`, `parseRubricVerdict`, `proveIdempotency`, `recordTrajectory`, `redactForEmission`, `referenceFaultProfile`, `registryCertificationProfile`, `replayIncident`, `ReplayIncidentOptions`, `replayTrajectory`, `ReplayTrajectoryOptions`, `RubricShape`, `RubricSpec`, `RubricVerdict`, `runAdversarialContract`, `runAgentEvalComposition`, `runAgentFailureMatrix`, `runContractLab`, `runContractLabOverHttp`, `runContractLabThroughAdapter`, `runFailureScenario`, `runFaultProfile`, `RunFaultProfileOptions`, `runtimeAdapterCertificationProfile`, `runTrajectory`, `ScoreTolerance`, `shapeOf`, `storageAdapterCertificationProfile`, `testSession`, `TestSession`, `TestSessionOptions`, `testToolAdapter`, `TrajectoryInvariantId`, `TrajectoryInvariantOptions`, `TrajectoryInvariantResult`, `trajectoryRegressionId`, `TrajectoryReplayResult`, `TrajectoryRun`, `TrajectoryTranscript`, `verifyAdapterCertification`
|
|
10025
11579
|
|
|
10026
11580
|
## @nifrajs/ts-plugin
|
|
10027
11581
|
|
|
@@ -10033,7 +11587,7 @@ done-gate, or `nifra mcp` to give the agent live project tools.
|
|
|
10033
11587
|
|
|
10034
11588
|
## @nifrajs/web
|
|
10035
11589
|
|
|
10036
|
-
`Action`, `ACTION_GLOBAL`, `
|
|
11590
|
+
`Action`, `ACTION_GLOBAL`, `assertRenderAdapterConformance`, `assertStaticBoundaryImports`, `Blocker`, `BlockerController`, `BlockerFunction`, `BlockerLocation`, `BlockerState`, `Boundary`, `BOUNDARY_GLOBAL`, `BoundaryDescriptor`, `boundaryDescriptors`, `BoundaryError`, `BoundaryMode`, `boundaryModeKey`, `BoundaryRegistration`, `BoundaryRequestCtx`, `BoundaryState`, `BoundaryStates`, `BoundaryStatus`, `BrowserNavigate`, `buildManifest`, `CachedResponse`, `CacheStore`, `canonical`, `ClientAction`, `ClientActionArgs`, `ClientActionResult`, `ClientLoader`, `ClientLoaderArgs`, `ClientRequestBody`, `ClientRouteHooks`, `ClientRouter`, `ClientRouterOptions`, `createClientRouter`, `createMatcher`, `createMutation`, `createQueryClient`, `createWebApp`, `CreateWebAppOptions`, `DATA_GLOBAL`, `DATA_HEADER`, `DEFAULT_DEV_PORT`, `defer`, `Deferred`, `DehydratedState`, `disableDraft`, `DRAFT_COOKIE`, `DraftCookieControls`, `DynamicBoundary`, `DynamicBoundaryBatch`, `enableDraft`, `EnableDraftOptions`, `enumerateStaticRoutes`, `Fetcher`, `FetcherState`, `FetchRouteData`, `filePathToPattern`, `filePathToPatterns`, `FontDisplay`, `fontFace`, `FontFace`, `fontPreload`, `FontPreloadInput`, `FontSource`, `generateClientEntry`, `GenerateClientEntryOptions`, `generateRouteSearchTypes`, `GenerateRouteSearchTypesOptions`, `generateServerManifest`, `GenerateServerManifestOptions`, `getBrowserNavigate`, `GetStaticPaths`, `gone`, `hashQueryKey`, `IDLE_BLOCKER`, `InertScriptType`, `InfiniteData`, `InfiniteQueryHandle`, `InfiniteQueryOptions`, `InterceptBoundary`, `isDraftEnabled`, `ISR_REVALIDATE_HEADER`, `ISR_REVALIDATE_TAGS_HEADER`, `ISR_STATUS_HEADER`, `ISRApp`, `ISROptions`, `ISRPlatform`, `jsonLd`, `KVCacheStore`, `KVCacheStoreOptions`, `KVNamespaceLike`, `LAYOUT_DATA_GLOBAL`, `LayoutEntry`, `LinkDescriptor`, `Loader`, `LoaderContext`, `Manifest`, `MemoryCacheStore`, `MemoryCacheStoreOptions`, `MemoryStaticBoundaryCache`, `mergeHeads`, `Meta`, `MetaArgs`, `MetaDescriptor`, `MetaInput`, `MountRouterOptions`, `MutationCallbacks`, `MutationHandle`, `MutationState`, `MutationStatus`, `NAV_FROM_HEADER`, `NavigateFunction`, `NavigateOptions`, `NavigateSearchOf`, `NavigateTargetInput`, `notFound`, `openGraph`, `OpenGraphInput`, `PendingBoundary`, `PRE_HYDRATION_GUARD`, `previewEndpoint`, `PreviewEndpointOptions`, `PublicDirCache`, `QueryClient`, `QueryClientOptions`, `QueryHandle`, `QueryOptions`, `QueryState`, `QueryStatus`, `redirect`, `REDIRECT_HEADER`, `RedirectOptions`, `registerBlocker`, `RenderAdapter`, `RenderAdapterConformanceError`, `RenderAdapterConformanceFixture`, `RenderAssemblyCache`, `RenderedPage`, `renderPage`, `RenderPageInput`, `RenderPageOptions`, `renderPageResult`, `RenderProps`, `resolveDynamicBoundaries`, `resolveMeta`, `resolveNavigate`, `resolvePublicPath`, `resolveStaticBoundaries`, `RETAIN_HEADER`, `revalidate`, `REVALIDATE_HEADER`, `revalidateEndpoint`, `RevalidateEndpointOptions`, `RevalidateResult`, `ROOT_ATTRIBUTE`, `ROUTE_GLOBAL`, `RouteEntry`, `RouteMatch`, `RouteModule`, `RoutePattern`, `RouterState`, `RouteSearch`, `ScriptDescriptor`, `searchOf`, `SearchOf`, `searchOfChain`, `serializeData`, `serializeSearch`, `servePublicDir`, `ServePublicDirOptions`, `SERVER_FN_MODULE`, `SERVER_ONLY_MODULE`, `ServerOnly`, `setBlockerController`, `setBrowserNavigate`, `setSsrModuleLoader`, `ssrModuleLoader`, `SsrModuleLoader`, `startDynamicBoundaries`, `StaticBoundary`, `StaticBoundaryCache`, `StaticBoundaryImportEdge`, `StaticBoundaryRoot`, `StaticCtx`, `StaticPath`, `StaticPaths`, `StaticRoutes`, `STATUS_HEADER`, `statusPage`, `StatusPageOptions`, `Submission`, `SubmitOptions`, `unsafeInlineScript`, `UnsafeScriptDescriptor`, `withISR`
|
|
10037
11591
|
|
|
10038
11592
|
## @nifrajs/web-preact
|
|
10039
11593
|
|