@niadra/sdk 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +15 -6
  3. package/dist/ai-sdk.cjs +3 -4
  4. package/dist/ai-sdk.cjs.map +1 -1
  5. package/dist/ai-sdk.d.cts +3 -3
  6. package/dist/ai-sdk.d.ts +3 -3
  7. package/dist/ai-sdk.js +3 -4
  8. package/dist/ai-sdk.js.map +1 -1
  9. package/dist/anthropic.cjs +1 -1
  10. package/dist/anthropic.cjs.map +1 -1
  11. package/dist/anthropic.d.cts +4 -4
  12. package/dist/anthropic.d.ts +4 -4
  13. package/dist/anthropic.js +1 -1
  14. package/dist/anthropic.js.map +1 -1
  15. package/dist/bedrock.cjs +1 -1
  16. package/dist/bedrock.cjs.map +1 -1
  17. package/dist/bedrock.d.cts +4 -4
  18. package/dist/bedrock.d.ts +4 -4
  19. package/dist/bedrock.js +1 -1
  20. package/dist/bedrock.js.map +1 -1
  21. package/dist/cli.js +107 -51
  22. package/dist/cli.js.map +1 -1
  23. package/dist/{client-DsIxZxZk.d.cts → client-B_ip8T2o.d.cts} +69 -14
  24. package/dist/{client-DsIxZxZk.d.ts → client-B_ip8T2o.d.ts} +69 -14
  25. package/dist/cloudflare-agents.cjs +1 -1
  26. package/dist/cloudflare-agents.cjs.map +1 -1
  27. package/dist/cloudflare-agents.d.cts +3 -3
  28. package/dist/cloudflare-agents.d.ts +3 -3
  29. package/dist/cloudflare-agents.js +1 -1
  30. package/dist/cloudflare-agents.js.map +1 -1
  31. package/dist/elevenlabs.cjs +1 -1
  32. package/dist/elevenlabs.cjs.map +1 -1
  33. package/dist/elevenlabs.d.cts +5 -5
  34. package/dist/elevenlabs.d.ts +5 -5
  35. package/dist/elevenlabs.js +1 -1
  36. package/dist/elevenlabs.js.map +1 -1
  37. package/dist/genkit.cjs +1 -1
  38. package/dist/genkit.cjs.map +1 -1
  39. package/dist/genkit.d.cts +3 -3
  40. package/dist/genkit.d.ts +3 -3
  41. package/dist/genkit.js +1 -1
  42. package/dist/genkit.js.map +1 -1
  43. package/dist/google-adk.cjs +1 -1
  44. package/dist/google-adk.cjs.map +1 -1
  45. package/dist/google-adk.d.cts +3 -3
  46. package/dist/google-adk.d.ts +3 -3
  47. package/dist/google-adk.js +1 -1
  48. package/dist/google-adk.js.map +1 -1
  49. package/dist/google-genai.cjs +1 -1
  50. package/dist/google-genai.cjs.map +1 -1
  51. package/dist/google-genai.d.cts +4 -4
  52. package/dist/google-genai.d.ts +4 -4
  53. package/dist/google-genai.js +1 -1
  54. package/dist/google-genai.js.map +1 -1
  55. package/dist/index.cjs +106 -48
  56. package/dist/index.cjs.map +1 -1
  57. package/dist/index.d.cts +6 -8
  58. package/dist/index.d.ts +6 -8
  59. package/dist/index.js +106 -48
  60. package/dist/index.js.map +1 -1
  61. package/dist/{intercept-D7qFCaRb.d.ts → intercept-CBaPK_-k.d.ts} +1 -1
  62. package/dist/{intercept-0_lJE6k1.d.cts → intercept-CxmBLfoj.d.cts} +1 -1
  63. package/dist/langchain.cjs +3 -4
  64. package/dist/langchain.cjs.map +1 -1
  65. package/dist/langchain.d.cts +3 -3
  66. package/dist/langchain.d.ts +3 -3
  67. package/dist/langchain.js +3 -4
  68. package/dist/langchain.js.map +1 -1
  69. package/dist/livekit.cjs +1 -1
  70. package/dist/livekit.cjs.map +1 -1
  71. package/dist/livekit.d.cts +3 -3
  72. package/dist/livekit.d.ts +3 -3
  73. package/dist/livekit.js +1 -1
  74. package/dist/livekit.js.map +1 -1
  75. package/dist/llamaindex.cjs +1 -1
  76. package/dist/llamaindex.cjs.map +1 -1
  77. package/dist/llamaindex.d.cts +3 -3
  78. package/dist/llamaindex.d.ts +3 -3
  79. package/dist/llamaindex.js +1 -1
  80. package/dist/llamaindex.js.map +1 -1
  81. package/dist/mastra.cjs +3 -4
  82. package/dist/mastra.cjs.map +1 -1
  83. package/dist/mastra.d.cts +3 -3
  84. package/dist/mastra.d.ts +3 -3
  85. package/dist/mastra.js +3 -4
  86. package/dist/mastra.js.map +1 -1
  87. package/dist/openai-agents.cjs +1 -1
  88. package/dist/openai-agents.cjs.map +1 -1
  89. package/dist/openai-agents.d.cts +3 -3
  90. package/dist/openai-agents.d.ts +3 -3
  91. package/dist/openai-agents.js +1 -1
  92. package/dist/openai-agents.js.map +1 -1
  93. package/dist/retell.cjs +1 -1
  94. package/dist/retell.cjs.map +1 -1
  95. package/dist/retell.d.cts +5 -5
  96. package/dist/retell.d.ts +5 -5
  97. package/dist/retell.js +1 -1
  98. package/dist/retell.js.map +1 -1
  99. package/dist/{shared-Bb5B59Bu.d.ts → shared-BLkAbvuf.d.ts} +1 -1
  100. package/dist/{shared-DTPWVlWm.d.cts → shared-DEkF2Y_z.d.cts} +1 -1
  101. package/dist/strands.cjs +1 -1
  102. package/dist/strands.cjs.map +1 -1
  103. package/dist/strands.d.cts +3 -3
  104. package/dist/strands.d.ts +3 -3
  105. package/dist/strands.js +1 -1
  106. package/dist/strands.js.map +1 -1
  107. package/dist/twilio.d.cts +4 -4
  108. package/dist/twilio.d.ts +4 -4
  109. package/dist/vapi.cjs +1 -1
  110. package/dist/vapi.cjs.map +1 -1
  111. package/dist/vapi.d.cts +5 -5
  112. package/dist/vapi.d.ts +5 -5
  113. package/dist/vapi.js +1 -1
  114. package/dist/vapi.js.map +1 -1
  115. package/dist/voltagent.cjs +1 -1
  116. package/dist/voltagent.cjs.map +1 -1
  117. package/dist/voltagent.d.cts +3 -3
  118. package/dist/voltagent.d.ts +3 -3
  119. package/dist/voltagent.js +1 -1
  120. package/dist/voltagent.js.map +1 -1
  121. package/dist/{webhook-1ozGyksG.d.ts → webhook-BaraTaA9.d.ts} +1 -1
  122. package/dist/{webhook-CG4om_DK.d.cts → webhook-CuR0Wckd.d.cts} +1 -1
  123. package/dist/whatsapp.d.cts +2 -2
  124. package/dist/whatsapp.d.ts +2 -2
  125. package/package.json +1 -1
package/dist/livekit.cjs CHANGED
@@ -37,7 +37,7 @@ var handles = {
37
37
 
38
38
  // src/context.ts
39
39
  function emptyResult(error) {
40
- return { text: "", suffix: "", variables: {}, pack: null, source: "none", response: null, error, constraints: null, state: null, coordination: null };
40
+ return { text: "", suffix: "", variables: {}, pack: null, source: "none", ageMs: null, response: null, error, constraints: null, state: null, coordination: null };
41
41
  }
42
42
 
43
43
  // src/integrations/shared.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/handles.ts","../src/context.ts","../src/integrations/shared.ts","../src/integrations/livekit.ts"],"names":["llm","voice"],"mappings":"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","file":"livekit.cjs","sourcesContent":["import { NiadraValidationError } from \"./errors.js\";\nimport type { Handle, ObjectRef } from \"./types/common.js\";\nimport type { SubjectKind } from \"./types/vocabulary.js\";\n\ninterface HandleOptions {\n /** Overrides the subject kind the server would infer from the handle type. */\n subjectKind?: SubjectKind;\n}\n\nfunction build(type: Handle[\"type\"], value: string, scope?: string, options?: HandleOptions): Handle {\n const handle: Handle = { type, value };\n if (scope !== undefined) handle.scope = scope;\n if (options?.subjectKind !== undefined) handle.subject_kind = options.subjectKind;\n return handle;\n}\n\n/**\n * Builders for the handle types the API accepts. They only assemble the object; the value is\n * normalized and validated on the server, which is the single source of truth for matching.\n *\n * @example\n * niadra.context({ subject: handles.phone(\"+5511987654321\"), conversation_id: \"wa-8812\" })\n */\nexport const handles = {\n /** A phone number in E.164 form, such as `+5511987654321`. */\n phone: (e164: string, options?: HandleOptions): Handle => build(\"phone_e164\", e164, undefined, options),\n email: (address: string, options?: HandleOptions): Handle => build(\"email\", address, undefined, options),\n /** The WhatsApp id (`wa_id`) the Cloud API reports for a contact. */\n waId: (value: string, options?: HandleOptions): Handle => build(\"wa_id\", value, undefined, options),\n waJid: (value: string, options?: HandleOptions): Handle => build(\"wa_jid\", value, undefined, options),\n waLid: (value: string, options?: HandleOptions): Handle => build(\"wa_lid\", value, undefined, options),\n /** A business-scoped WhatsApp user id; `businessAccount` is the WhatsApp Business account it belongs to. */\n waBsuid: (value: string, businessAccount: string, options?: HandleOptions): Handle =>\n build(\"wa_bsuid\", value, businessAccount, options),\n /** The user id in your own app or site. */\n appUserId: (value: string, options?: HandleOptions): Handle => build(\"app_user_id\", value, undefined, options),\n /** The id of a person or organization in a system of record; `system` names that system, such as `crm`. */\n systemId: (value: string, system: string, options?: HandleOptions): Handle =>\n build(\"system_id\", value, system, options),\n /** An HMAC of a national document number; `country` is its ISO 3166-1 alpha-2 code. */\n govIdHmac: (value: string, country: string, options?: HandleOptions): Handle =>\n build(\"gov_id_hmac\", value, country, options),\n /** An HMAC of a company registry number. Identifies an organization. */\n orgRegistryHmac: (value: string, country: string): Handle =>\n build(\"org_registry_hmac\", value, country, { subjectKind: \"account\" }),\n /** An e-mail domain, such as `acme.com`. Identifies an organization. */\n emailDomain: (domain: string): Handle => build(\"email_domain\", domain, undefined, { subjectKind: \"account\" }),\n /** An anonymous visitor or device id, before the person is known. */\n anonId: (value: string, options?: HandleOptions): Handle => build(\"anon_id\", value, undefined, options),\n} as const;\n\n/**\n * Accepts an `ObjectRef` or the `type:namespace:id` shorthand. The id may itself contain\n * colons (`invoice:erp:2026:0823`); only the first two separate the parts.\n */\nexport function toObjectRef(object: ObjectRef | string): ObjectRef {\n if (typeof object !== \"string\") return object;\n const first = object.indexOf(\":\");\n const second = first < 0 ? -1 : object.indexOf(\":\", first + 1);\n if (first <= 0 || second <= first + 1 || second === object.length - 1) {\n throw new NiadraValidationError(\"object must look like `type:namespace:id`\");\n }\n return { type: object.slice(0, first), namespace: object.slice(first + 1, second), id: object.slice(second + 1) };\n}\n","import { NiadraValidationError } from \"./errors.js\";\nimport { includeText } from \"./constraints/text.js\";\nimport type { NiadraError } from \"./errors.js\";\nimport { toObjectRef } from \"./handles.js\";\nimport type { Handle, ObjectRef } from \"./types/common.js\";\nimport type {\n ContextFormat,\n ContextPack,\n ContextRequest,\n ContextResponse,\n CoordinationBlock,\n Include,\n LiveTurn,\n PrefetchRequest,\n TargetModel,\n} from \"./types/context.js\";\nimport type { ConstraintsBlock } from \"./types/signals.js\";\nimport type { StateView } from \"./types/state.js\";\nimport type { Verification, View } from \"./types/vocabulary.js\";\n\n/** Arguments of `context()`. Pass exactly one of `subject` or `object`. */\nexport interface ContextParams {\n /** The customer, by any handle the server knows. */\n subject?: Handle;\n /** A business object, such as an invoice, when the task is about the object rather than a person. */\n object?: ObjectRef | string;\n /** The account or partner the person acts for. Requires an active link between the two. */\n about?: Handle;\n /** Defaults to `chat`. */\n view?: View;\n /**\n * The level proven in this conversation. The server may answer with a lower effective level\n * when the source's ceiling is lower; see `response.verification`.\n */\n verification?: Verification;\n /** Enables the per-conversation cache and the server's pinning of the pack. */\n conversation_id?: string;\n /** For internal agents: the task plays the role of the conversation. */\n task_id?: string;\n /**\n * Other words than the turn to pick this read's slots by. Up to 2,000 characters. Wins over\n * `turn`, and like it never changes the pack.\n */\n query?: string;\n /**\n * The customer's last turn; a conversation passes it for you. It goes as `query` and the answer\n * adds `slots`, what the turn selected from memory, in `suffix`, while the pack stays the\n * conversation's pinned one (and is cached as without it).\n */\n turn?: string | null;\n /** Ask only for what changed since this source last read the subject. */\n delta?: boolean;\n /** The model that will read the pack, so the server can size it for that model's prompt cache. */\n target?: TargetModel;\n /** `json` also returns the pack as typed sections in `pack` (`context-pack.v1`). Defaults to `text`. */\n format?: ContextFormat;\n /**\n * Adds `why` to each of `pack.slots`, naming the retrieval channels that\n * ranked it, the fused score, the weights version and, for a derived line, the rule behind it.\n * Requires `format: \"json\"`. It changes nothing else: the pinned text, the slots chosen and the\n * receipt are the same bytes with or without it.\n */\n explain?: boolean;\n /**\n * Blocks read in the same round trip: `[\"constraints\"]` returns the subject's constraints block, `[\"state\"]`\n * the state of their objects. Each only where the space turned its feature on; a block the space does not\n * serve is left out and not asked again for a while, and the read goes on. The blocks are cached with the\n * pack, so a read that fails serves the last good ones too.\n */\n include?: Include[];\n}\n\n/** Arguments of `prefetch()`: who the turn is about, as in `context()`, and the turn so far. */\nexport interface PrefetchParams {\n subject?: Handle;\n object?: ObjectRef | string;\n about?: Handle;\n /** Defaults to `voice`, where partial transcripts come from. */\n view?: View;\n verification?: Verification;\n conversation_id?: string;\n task_id?: string;\n /** The partial transcript of the customer's turn. */\n text: string;\n}\n\n/** Per-call options shared by every read method. */\nexport interface RequestOptions {\n /** Overrides the method's default time budget, in milliseconds. */\n timeout?: number | undefined;\n /** Cancels the wait. A request shared with other callers keeps running for them. */\n signal?: AbortSignal | undefined;\n /** Extra headers, such as a W3C `traceparent`. */\n headers?: Record<string, string> | undefined;\n}\n\nexport interface ContextOptions extends RequestOptions {\n /** Pass `false` to skip the per-conversation cache for this call. */\n cache?: boolean | undefined;\n /** For `conversation.context()` and `task.context()`: blocks read in the same round trip. */\n include?: Include[] | undefined;\n /** For `conversation.context()` and `task.context()`: `json` also returns `pack`. */\n format?: ContextFormat | undefined;\n /**\n * For `conversation.context()` and `task.context()`: adds `why` to each of `pack.slots`.\n * Requires `format: \"json\"`.\n */\n explain?: boolean | undefined;\n}\n\n/**\n * Where a `context()` result came from.\n *\n * - `network`: a response the server just sent (or confirmed unchanged).\n * - `cache`: a pack younger than the cache TTL; no request was made.\n * - `stale`: an older pack returned at once while a background request refreshes it.\n * - `fallback`: the request failed and this is the last good pack for the conversation.\n * - `none`: nothing was available; `text` is empty and `error` says why.\n */\nexport type ContextSource = \"network\" | \"cache\" | \"stale\" | \"fallback\" | \"none\";\n\n/** What `context()` resolves to. Always usable: on failure `text` is an empty string. */\nexport interface ContextResult {\n /** The pack, ready for the system prompt. Empty when there is nothing to inject. */\n text: string;\n /**\n * The parts that change turn by turn and belong at the end of the prompt, after the\n * conversation: the live turns from other channels, this turn's slots (what the customer's last\n * turn selected from memory), the blocks asked for by `include` (the state view, the constraints) and the\n * delta, in that order, as the API places them. Empty when there are none.\n */\n suffix: string;\n /** Named values from the pack, for templates that place them individually. */\n variables: Record<string, string>;\n /** The pack as typed sections, when read with `format: \"json\"`; otherwise `null`. */\n pack: ContextPack | null;\n source: ContextSource;\n /** The response this result was built from; `null` when `source` is `none`. */\n response: ContextResponse | null;\n /** What went wrong, when `source` is `fallback` or `none`. */\n error: NiadraError | null;\n /** With `include: [\"constraints\"]`: the subject's constraints block. */\n constraints?: ConstraintsBlock | null;\n /** With `include: [\"state\"]`: the state of the subject's objects. */\n state?: StateView | null;\n /** With `include: [\"coordination\"]`: what coordination knows of the subject. */\n coordination?: CoordinationBlock | null;\n}\n\nconst VIEW = /^(voice|chat|brief|full|custom|account|partner|task:[a-z0-9_]{1,40})$/;\nconst MAX_QUERY = 2000;\n\n/** Validates the arguments and builds the wire request, without `known_etag`. */\nexport function buildContextRequest(params: ContextParams): ContextRequest {\n if ((params.subject === undefined) === (params.object === undefined)) {\n throw new NiadraValidationError(\"pass exactly one of `subject` or `object`\");\n }\n if (params.conversation_id && params.task_id) {\n throw new NiadraValidationError(\"pass `conversation_id` or `task_id`, not both\");\n }\n if (params.view !== undefined && !VIEW.test(params.view)) {\n throw new NiadraValidationError(\"unknown view; task views look like `task:billing`\");\n }\n if (params.query !== undefined && params.query.length > MAX_QUERY) {\n throw new NiadraValidationError(`query is longer than ${MAX_QUERY} characters`);\n }\n\n const request: ContextRequest = { view: params.view ?? \"chat\" };\n if (params.subject) request.subject = params.subject;\n if (params.object !== undefined) request.object = toObjectRef(params.object);\n if (params.about) request.about = params.about;\n if (params.verification) request.verification = params.verification;\n if (params.conversation_id) request.conversation_id = params.conversation_id;\n if (params.task_id) request.task_id = params.task_id;\n if (params.query) request.query = params.query;\n if (params.delta) request.delta = true;\n if (params.target) request.target = params.target;\n const format: string = params.format ?? \"text\";\n if (format !== \"text\" && format !== \"json\") throw new NiadraValidationError(\"format is `text` or `json`\");\n if (format === \"json\") request.format = \"json\";\n if (params.explain) {\n if (format !== \"json\") throw new NiadraValidationError('explain requires format: \"json\"');\n request.explain = true;\n }\n if (params.include?.length) request.include = [...new Set(params.include)];\n return request;\n}\n\n/** Validates the arguments of `prefetch()` and builds the wire request. */\nexport function buildPrefetchRequest(params: PrefetchParams): PrefetchRequest {\n if ((params.subject === undefined) === (params.object === undefined)) {\n throw new NiadraValidationError(\"pass exactly one of `subject` or `object`\");\n }\n if (params.conversation_id && params.task_id) {\n throw new NiadraValidationError(\"pass `conversation_id` or `task_id`, not both\");\n }\n if (params.view !== undefined && !VIEW.test(params.view)) {\n throw new NiadraValidationError(\"unknown view; task views look like `task:billing`\");\n }\n const text = params.text.trim();\n if (!text || text.length > MAX_QUERY) throw new NiadraValidationError(`text must be 1 to ${MAX_QUERY} characters`);\n const request: PrefetchRequest = { view: params.view ?? \"voice\", query: text };\n if (params.subject) request.subject = params.subject;\n if (params.object !== undefined) request.object = toObjectRef(params.object);\n if (params.about) request.about = params.about;\n if (params.verification) request.verification = params.verification;\n if (params.conversation_id) request.conversation_id = params.conversation_id;\n if (params.task_id) request.task_id = params.task_id;\n return request;\n}\n\n/** Packs are only cached inside a conversation or task, the unit the server pins them to. */\nexport function cacheScope(request: Pick<ContextRequest, \"conversation_id\" | \"task_id\">): string | null {\n if (request.conversation_id) return `conversation:${request.conversation_id}`;\n if (request.task_id) return `task:${request.task_id}`;\n return null;\n}\n\n/**\n * Every field that changes what the server would compile goes into the key, in a fixed order.\n * `delta` does not: a plain read and a delta read of one conversation get the same pinned\n * bytes, so they share one entry.\n */\nexport function cacheKey(request: ContextRequest): string {\n return JSON.stringify([\n request.subject ?? null,\n request.object ?? null,\n request.about ?? null,\n request.view ?? \"chat\",\n request.verification ?? \"V0\",\n request.conversation_id ?? null,\n request.task_id ?? null,\n request.query ?? null,\n request.target ?? null,\n request.format ?? \"text\",\n request.explain ?? false,\n request.include ?? null,\n ]);\n}\n\n/**\n * Applies a `not_modified` answer to the cached pack: the pinned text and its metadata stay,\n * while the parts outside the pin (live turns, delta, coverage, timing) come from the new answer.\n */\nexport function mergeNotModified(cached: ContextResponse, fresh: ContextResponse): ContextResponse {\n return {\n ...fresh,\n not_modified: false,\n text: cached.text ?? null,\n variables: cached.variables,\n version: cached.version,\n etag: cached.etag,\n manifest_hash: cached.manifest_hash ?? null,\n withheld: cached.withheld,\n cache: cached.cache ?? null,\n pack: cached.pack ?? null,\n // The blocks sit outside the pinned pack: a fresh block wins, and a missing one keeps the cached.\n constraints: fresh.constraints ?? cached.constraints ?? null,\n state: fresh.state ?? cached.state ?? null,\n coordination: fresh.coordination ?? cached.coordination ?? null,\n };\n}\n\nexport function resultFrom(\n response: ContextResponse,\n source: ContextSource,\n error: NiadraError | null = null,\n): ContextResult {\n // A conversation in the control group gets an empty pack on purpose; it is not an error.\n const holdout = response.path === \"holdout\";\n const text = holdout ? \"\" : (response.text ?? \"\");\n const pack = holdout ? null : (response.pack ?? null);\n const blocks = {\n constraints: response.constraints ?? null,\n state: response.state ?? null,\n coordination: response.coordination ?? null,\n };\n return { text, suffix: renderSuffix(response), variables: response.variables, pack, source, response, error, ...blocks };\n}\n\nexport function emptyResult(error: NiadraError | null): ContextResult {\n return { text: \"\", suffix: \"\", variables: {}, pack: null, source: \"none\", response: null, error, constraints: null, state: null, coordination: null };\n}\n\n/**\n * Renders the live turns, the slots and the delta for the end of the prompt, in that order. Kept\n * outside the pinned pack so that the prompt prefix stays byte-identical across turns and the\n * model provider's prompt cache keeps hitting. Returns an empty string when there is nothing to add.\n */\nexport function renderSuffix(response: ContextResponse): string {\n if (response.path === \"holdout\") return \"\";\n const included = includeText(response.text, response.state, response.constraints);\n return [renderLive(response), response.slots ?? \"\", included, response.delta ?? \"\"].filter(Boolean).join(\"\\n\\n\");\n}\n\n/**\n * Renders the live turns (recent turns from other channels that the pack has not absorbed\n * yet) as one tagged block, or an empty string when there are none. `complete=\"false\"` tells\n * the model the list may be missing turns because the server could not read all of them.\n */\nexport function renderLive(response: ContextResponse): string {\n if (response.path === \"holdout\" || response.live.length === 0) return \"\";\n const complete = response.live_complete ? \"\" : ' complete=\"false\"';\n const lines = response.live.map(renderLiveTurn).join(\"\\n\");\n return `<live_turns source=\"niadra\"${complete}>\\n${lines}\\n</live_turns>`;\n}\n\nfunction renderLiveTurn(turn: LiveTurn): string {\n return `[${utcSeconds(turn.at)}] ${turn.channel} · ${turn.speaker}: ${turn.text}`;\n}\n\n/** The same timestamp form in every SDK, whatever precision or offset the server sent. */\nfunction utcSeconds(at: string): string {\n const ms = Date.parse(at);\n return Number.isNaN(ms) ? at : `${new Date(ms).toISOString().slice(0, 19)}Z`;\n}\n","/**\n * What every framework adapter shares: the five primitives (context before the model call, the\n * turns, the tools, the verification and the handoff) wired the same way, and fail-open.\n *\n * Nothing here throws into the framework: a failed read gives an empty context, a failed write\n * is logged without content, and the agent keeps working without memory.\n */\n\nimport { recordedTool } from \"../capture/tool.js\";\nimport type { Played } from \"../replay/playback.js\";\nimport type { AgentMemoryParams } from \"../agent-memory.js\";\nimport type { TurnParams } from \"../agent-session.js\";\nimport type { CallCapture, TurnFrame } from \"../capture/frame.js\";\nimport type { ContextOptions, ContextResult } from \"../context.js\";\nimport { emptyResult } from \"../context.js\";\nimport type { Conversation, TurnOptions } from \"../conversation.js\";\nimport type { Logger } from \"../logger.js\";\nimport type { Task } from \"../task.js\";\nimport type { BoundTools } from \"../tools.js\";\nimport type { Handle } from \"../types/common.js\";\nimport type { Verification, VerifyMethod } from \"../types/vocabulary.js\";\n\n/** A customer conversation or an internal agent's task. */\nexport type Session = Conversation | Task;\n\n/** A session, or a function that finds the one the current call belongs to (`null` passes the call through). */\nexport type SessionResolver<S extends Session = Session> = S | (() => S | null | undefined);\n\n/** What the framework proved about the person, recorded with `verify()` before the first context read. */\nexport interface Proof {\n method: VerifyMethod;\n level: Verification;\n /** Defaults to the session's subject. */\n handle?: Handle;\n}\n\n/** A proof, or a function that reads it from the framework when the first context is needed. */\nexport type ProofSource =\n | Proof\n | null\n | undefined\n | (() => Proof | null | undefined | PromiseLike<Proof | null | undefined>);\n\n/**\n * The agent's own working notes: `true` puts the block before the customer's context and offers\n * `search_agent_memory`; `{ write: true }` also offers `remember` (for a key with the\n * `agent_memory:write` scope); the other fields go to `agentMemory()`.\n */\nexport type AgentMemoryOption = boolean | (AgentMemoryParams & { write?: boolean });\n\n/** What goes into the prompt for one model call. */\nexport interface Read {\n context: ContextResult;\n /** The agent's own notes, or an empty string. */\n memory: string;\n /** What goes after the instructions: the notes, then the customer's pack. */\n prefix: string;\n /** What goes at the end: live turns, the turn's slots and deltas. */\n suffix: string;\n}\n\n/** A tool as every framework needs it: the name, the text for the model, the JSON Schema and the call. */\ninterface ToolSpec {\n name: string;\n description: string;\n /** JSON Schema of the arguments. None of them names the customer. */\n parameters: Record<string, unknown>;\n /** Runs the call and returns the text for the model. Never rejects in fail-open mode. */\n execute(args: string | Record<string, unknown>): Promise<string>;\n}\n\nconst ATTESTED: Record<string, Verification> = { A: \"V2\", B: \"V1\", C: \"V1\" };\n\n/**\n * The proof a carrier's STIR/SHAKEN attestation gives a phone call: `A` proves V2, `B` and `C`\n * prove V1, anything else proves nothing (`null`). Accepts the bare letter or the forms carriers\n * and platforms send, such as Twilio's `TN-Validation-Passed-A`.\n */\nexport function attestationProof(attestation: string | null | undefined): Proof | null {\n if (!attestation) return null;\n const value = attestation.trim().toUpperCase();\n if (value.includes(\"FAILED\") || value.startsWith(\"NO-\")) return null;\n const letter = value.length === 1 ? value : /PASSED-([ABC])$/.exec(value)?.[1];\n const level = letter ? ATTESTED[letter] : undefined;\n return level ? { method: \"network_attestation\", level } : null;\n}\n\nexport function resolveSession<S extends Session>(source: SessionResolver<S>): S | null {\n if (typeof source !== \"function\") return source;\n try {\n return source() ?? null;\n } catch {\n return null;\n }\n}\n\nfunction isConversation(session: Session): session is Conversation {\n return \"customer\" in session && typeof session.customer === \"function\";\n}\n\n/** A phone number as an E.164 handle, or `null` when it does not look like one. */\nexport function phoneHandle(value: string | null | undefined): Handle | null {\n const raw = value?.trim().replace(/^tel:/i, \"\").replace(/[\\s().-]/g, \"\");\n if (!raw) return null;\n const e164 = raw.startsWith(\"+\") ? raw : `+${raw}`;\n return /^\\+[1-9]\\d{6,14}$/.test(e164) ? { type: \"phone_e164\", value: e164 } : null;\n}\n\nexport function errorName(error: unknown): string {\n return error instanceof Error ? error.name : typeof error;\n}\n\n/**\n * One session as an adapter drives it. Keeps the verification to a single call made before the\n * first context read, and turns every failure into a log line.\n */\nexport class Bridge {\n private proving: Promise<void> | null = null;\n /** `begin()` started the first read of a call: the first `context()` waits for it with `ready()`. */\n private begun = false;\n private opened = false;\n\n constructor(\n readonly session: Session,\n private readonly proof?: ProofSource,\n private readonly memory: AgentMemoryOption = false,\n ) {}\n\n /**\n * The context and, when enabled, the agent's notes, read side by side within the same budget.\n * Never rejects.\n */\n async read(options: ContextOptions = {}): Promise<Read> {\n const memoryParams = this.memory === false ? null : this.memory === true ? {} : withoutWrite(this.memory);\n const [context, memory] = await Promise.all([\n this.context(options),\n memoryParams ? this.agentMemory(memoryParams, options) : Promise.resolve(\"\"),\n ]);\n return { context, memory, prefix: [memory, context.text].filter(Boolean).join(\"\\n\\n\"), suffix: context.suffix };\n }\n\n get logger(): Logger {\n return this.session.logger;\n }\n\n /**\n * Starts the first read of a call now, in the background, after the proof when one was given (the\n * pack depends on the level it proves): at call start, so the read runs while the call is set up.\n * The first `context()` then waits for it within `timeouts.contextVoiceStart`. Never throws.\n */\n begin(): void {\n const session = this.session;\n if (!isConversation(session)) return;\n const start = (): void => {\n this.safe(\"start the first read\", () => {\n // False off the voice read path (a chat view, the cache off): reads go on as before.\n this.begun = session.begin();\n });\n };\n if (this.proof === undefined || this.proof === null) start();\n else void this.verifyOnce().then(start);\n }\n\n /** Verifies once (when a proof was given), then reads the context. Never rejects. */\n async context(options: ContextOptions = {}): Promise<ContextResult> {\n await this.verifyOnce();\n try {\n const session = this.session;\n if (this.begun && !this.opened && isConversation(session)) {\n this.opened = true;\n // The call's first read, begun at call start: waited for within its own, longer budget.\n await session.ready(options.timeout === undefined ? {} : { timeout: options.timeout });\n }\n return await this.session.context(options);\n } catch (error) {\n this.logger.warn(`could not read context (${errorName(error)})`);\n return emptyResult(null);\n }\n }\n\n /** Records that `context` went into the prompt, unless it was empty for a reason other than the holdout. */\n injected(context: ContextResult): void {\n if (!context.text && !context.suffix && context.response?.path !== \"holdout\") return;\n this.safe(\"mark the injection\", () => {\n this.session.markInjected(context);\n });\n }\n\n customer(text: string, options: TurnOptions = {}): void {\n const session = this.session;\n if (!text.trim() || !isConversation(session)) return;\n this.safe(\"record the customer's turn\", () => session.customer(text, options));\n }\n\n /** Sends the customer's turn so far, while they speak. In the background; never throws. */\n prefetch(text: string): void {\n const session = this.session;\n if (!text.trim() || !isConversation(session)) return;\n this.safe(\"prefetch the turn\", () => session.prefetch(text));\n }\n\n agent(text: string, options: TurnOptions = {}): void {\n if (!text.trim()) return;\n this.safe(\"record the agent's turn\", () => this.session.agent(text, options));\n }\n\n /** Records a transfer. Tasks have no transfer; the call is ignored for them. */\n async handoff(target: \"agent\" | \"human\", reason?: string): Promise<void> {\n const session = this.session;\n if (!isConversation(session)) return;\n try {\n await session.handoff(reason ? { target, reason } : { target });\n } catch (error) {\n this.logger.warn(`could not record the handoff (${errorName(error)})`);\n }\n }\n\n async end(): Promise<void> {\n try {\n await this.session.end();\n } catch (error) {\n this.logger.warn(`could not end the session (${errorName(error)})`);\n }\n }\n\n /** The navigation kit as plain specs (with the agent's memory tools when enabled), or none for a task about an object only. */\n tools(): ToolSpec[] {\n let bound: BoundTools | null;\n try {\n const memory = this.memory;\n bound = this.session.tools(memory === false ? {} : { agentMemory: true, writeAgentMemory: memory !== true && memory.write === true });\n } catch (error) {\n this.logger.warn(`could not build the tools (${errorName(error)})`);\n return [];\n }\n return bound ? toolSpecs(bound) : [];\n }\n\n private async agentMemory(params: AgentMemoryParams, options: ContextOptions): Promise<string> {\n try {\n const result = await this.session.agentMemory(params, options.timeout === undefined ? {} : { timeout: options.timeout });\n return result.text;\n } catch (error) {\n this.logger.warn(`could not read the agent's memory (${errorName(error)})`);\n return \"\";\n }\n }\n\n private async verifyOnce(): Promise<void> {\n if (this.proof === undefined || this.proof === null) return;\n this.proving ??= this.runVerify();\n await this.proving;\n }\n\n private async runVerify(): Promise<void> {\n try {\n const source = this.proof;\n const proof = typeof source === \"function\" ? await source() : source;\n if (!proof) return;\n await this.session.verify(proof);\n } catch (error) {\n this.logger.warn(`could not record the verification (${errorName(error)})`);\n }\n }\n\n private safe(what: string, run: () => unknown): void {\n try {\n run();\n } catch (error) {\n this.logger.warn(`could not ${what} (${errorName(error)})`);\n }\n }\n}\n\nfunction withoutWrite(option: AgentMemoryParams & { write?: boolean }): AgentMemoryParams {\n const { write: _, ...params } = option;\n return params;\n}\n\n/** The bound kit as specs. The customer stays inside `bound`; no parameter names them. */\nfunction toolSpecs(bound: BoundTools): ToolSpec[] {\n return bound.definitions.map(({ function: definition }) => ({\n name: definition.name,\n description: definition.description,\n parameters: definition.parameters,\n execute: (args) => bound.call(definition.name, args),\n }));\n}\n\n/** The text of a message content in the shapes model APIs use: a string, or a list of text parts. */\nexport function textOf(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n const parts: string[] = [];\n for (const part of content as unknown[]) {\n if (typeof part === \"string\") parts.push(part);\n else if (isRecord(part) && typeof part.text === \"string\" && (part.type === undefined || part.type === \"text\")) {\n parts.push(part.text);\n }\n }\n return parts.join(\"\");\n}\n\nexport function isRecord(value: unknown): value is Record<PropertyKey, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\n/** A non-negative integer, or `null`. */\nexport function count(value: unknown): number | null {\n return typeof value === \"number\" && Number.isInteger(value) && value >= 0 ? value : null;\n}\n\n/**\n * The turn records an adapter keeps from its framework's callbacks, keyed by the framework's own ids (a\n * run, a request, a tool call id). A run starting while the session has a turn in progress (yours, from\n * `conversation.turn()`, or a replay's) records into it; otherwise the adapter opens its own turn and closes\n * it when the run ends. A tool call recorded here is taken over by a `tool()` wrapper running inside it, so\n * the call is recorded once. Every method does nothing when turns are off and never throws.\n */\nexport class TurnHooks {\n /** Runs held open at most; past it the oldest run's turn closes, incomplete (a run whose end never came). */\n static readonly MAX_OPEN = 100;\n private readonly frames = new Map<string, { frame: TurnFrame; own: boolean }>();\n private readonly calls = new Map<string, CallCapture>();\n\n constructor(\n readonly adapter: string,\n readonly enabled: boolean,\n ) {}\n\n /** The turn of the run `key`: the session's turn in progress, or a new one of its own. */\n open(session: Session, key: string, params: TurnParams = {}): TurnFrame | undefined {\n if (!this.enabled) return undefined;\n const held = this.frames.get(key);\n if (held !== undefined) return held.frame;\n try {\n const active = session.activeTurn();\n if (active !== undefined && !this.owns(active)) {\n this.frames.set(key, { frame: active, own: false });\n return active;\n }\n const frame = session.openTurn({ ...params, adapter: this.adapter });\n this.frames.set(key, { frame, own: true });\n if (this.frames.size > TurnHooks.MAX_OPEN) {\n const [oldest] = this.frames.keys();\n if (oldest !== undefined) {\n this.frames.get(oldest)?.frame.incomplete();\n this.close(oldest);\n }\n }\n return frame;\n } catch (error) {\n session.logger.warn(`could not open the turn (${errorName(error)})`);\n return undefined;\n }\n }\n\n /** The turn of `key`, else the session's turn in progress. */\n frame(session: Session, key?: string): TurnFrame | undefined {\n if (!this.enabled) return undefined;\n const held = key === undefined ? undefined : this.frames.get(key);\n const frame = held?.frame ?? session.activeTurn();\n return frame === undefined || frame.closed ? undefined : frame;\n }\n\n has(key: string): boolean {\n return this.frames.has(key);\n }\n\n private owns(frame: TurnFrame): boolean {\n for (const held of this.frames.values()) if (held.own && held.frame === frame) return true;\n return false;\n }\n\n /** Ends the run `key`: a turn the adapter opened closes; the calls it left open failed. */\n close(key: string, error?: unknown): void {\n const held = this.frames.get(key);\n if (held === undefined) return;\n this.frames.delete(key);\n for (const [callKey, call] of this.calls) {\n if (call.frame !== held.frame) continue;\n this.calls.delete(callKey);\n if (held.own) call.failed(error ?? \"error\");\n }\n if (held.own) held.frame.close(error);\n }\n\n /** A tool call starting, keyed by `callKey`; `callId` is the provider's id of the call, when there is one. */\n toolStart(session: Session, callKey: string, name: string, args: unknown, options: { frameKey?: string; callId?: string | null } = {}): void {\n const frame = this.frame(session, options.frameKey);\n if (frame === undefined) return;\n try {\n this.calls.set(callKey, frame.toolCall(name, args, { callId: options.callId ?? null, adoptable: true }));\n } catch {\n frame.incomplete();\n }\n }\n\n /**\n * In a replay, how a framework tool the adapter stands in for answers: the recorded result of a call with the\n * same arguments, or empty (a divergence), never the live tool. `null` outside a replay, and for a function\n * wrapped with `tool()`, which answers itself.\n */\n replayed(session: Session, name: string, args: unknown, fn?: unknown, frameKey?: string): Played | null {\n const frame = this.enabled ? this.frame(session, frameKey) : session.activeTurn();\n if (frame?.playback == null || (fn !== undefined && recordedTool(fn) !== null)) return null;\n return frame.playback.answer(name, args, false);\n }\n\n toolEnd(callKey: string, result?: unknown, error?: unknown): void {\n const call = this.calls.get(callKey);\n if (call === undefined) return;\n this.calls.delete(callKey);\n try {\n if (error !== undefined) call.failed(error);\n else call.result(result);\n } catch {\n call.frame.incomplete();\n }\n }\n\n /** A model call that ended, with its tokens when the framework reported them. */\n model(\n session: Session,\n model: string | null | undefined,\n tokens: { in?: number | null; out?: number | null; cached?: number | null } = {},\n frameKey?: string,\n ): void {\n const frame = this.frame(session, frameKey);\n if (frame === undefined) return;\n try {\n frame.modelCall(model, { tokensIn: tokens.in ?? null, tokensOut: tokens.out ?? null, tokensCached: tokens.cached ?? 0 });\n } catch {\n frame.incomplete();\n }\n }\n}\n","/**\n * Niadra for LiveKit Agents (Node, `@livekit/agents` 1.9).\n *\n * The same hook as LiveKit's own RAG recipe: `onUserTurnCompleted(turnCtx, newMessage)`. There\n * the customer's final transcript is recorded, the conversation's pack goes into the turn's chat\n * context as a system message right after the agent's instructions, and the suffix (live turns\n * from other channels, what the caller's turn needs from memory, and deltas) goes after the new message. The read sends the caller's turn along. The turn context is\n * a copy LiveKit builds for this reply only, so nothing piles up in the agent's history and the prompt prefix\n * stays byte-identical turn after turn. Session events record the agent's answers (with the\n * LLM usage LiveKit measured), handoffs between agents and the end of the call.\n *\n * `NiadraMemory` starts the caller's first read when it is built (`begin()`), so it runs while the\n * session starts, and the first reply waits for it within `timeouts.contextVoiceStart` (1.5 s).\n * After that no turn waits on a round trip for the pack: it comes from memory at once. While the\n * caller is still speaking, each `user_input_transcribed` event (interim or final) sends the turn\n * so far with `prefetch()`, in the background: the server warms the caller's memory, and once the\n * words stop changing the SDK reads the turn with them, so the slots are there when LiveKit ends\n * the turn. A turn waits at most 200 ms for such a read still on its way, then answers without\n * the slots; a prefetch never holds or fails a turn.\n *\n * @example\n * const caller = ctx.room.remoteParticipants.values().next().value;\n * const convo = niadra.conversation({ subject: sipSubject(caller), channel: \"voice\", conversation_id: sipConversationId(caller, ctx.room.name) });\n * const memory = new NiadraMemory({ conversation: convo, verify: attestationProof(caller.attributes[\"sip.h.x-stir-verstat\"]) });\n * const agent = new NiadraAgent({ instructions: \"You are the support line of Acme.\", memory });\n * memory.attach(session);\n * await session.start({ agent, room: ctx.room });\n */\n\nimport { llm, voice } from \"@livekit/agents\";\nimport type { Conversation } from \"../conversation.js\";\nimport { handles } from \"../handles.js\";\nimport type { Handle } from \"../types/common.js\";\nimport type { ModelUsage } from \"../types/events.js\";\nimport { Bridge, count, errorName } from \"./shared.js\";\nimport type { AgentMemoryOption, ProofSource } from \"./shared.js\";\n\nexport { attestationProof } from \"./shared.js\";\nexport type { AgentMemoryOption, Proof, ProofSource } from \"./shared.js\";\n\n/** Instructions LiveKit keeps at the head of the chat context; the pack goes after them. */\nconst LEADING_IDS = new Set([\"lk.agent_task.instructions\", \"lk.expressive.instructions\"]);\nconst INSTRUCTION_ROLES = new Set([\"system\", \"developer\"]);\nconst CONTEXT_ID = \"niadra.context\";\n\n/** `llm.tool` with a raw JSON Schema, which it accepts but cannot infer argument types from. */\nconst rawTool = llm.tool as unknown as (options: {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n execute: (args: Record<string, unknown> | undefined) => Promise<unknown>;\n}) => llm.FunctionTool;\nconst SUFFIX_ID = \"niadra.suffix\";\n\nexport interface NiadraMemoryOptions {\n /** The call, opened with `channel: \"voice\"` so reads use the voice view and budget. */\n conversation: Conversation;\n /**\n * What the call proved before the first read, such as the carrier's attestation\n * (`attestationProof(...)`). Recorded once with `verify()` before the first context.\n */\n verify?: ProofSource;\n /** Records the agent's answers from `conversation_item_added`. Defaults to `true`. */\n recordAgent?: boolean;\n /** Puts the agent's own notes before the caller's context and adds its memory tools. */\n agentMemory?: AgentMemoryOption;\n}\n\n/** Participant fields the helpers read. A `RemoteParticipant` has them. */\nexport interface ParticipantLike {\n identity: string;\n attributes?: Record<string, string> | undefined;\n}\n\n/**\n * The caller as a handle: the phone number LiveKit SIP puts in `sip.phoneNumber` (E.164, `+` added\n * when missing), otherwise the participant identity as your app's user id.\n */\nexport function sipSubject(participant: ParticipantLike): Handle {\n const phone = participant.attributes?.[\"sip.phoneNumber\"]?.trim();\n if (phone) return handles.phone(phone.startsWith(\"+\") ? phone : `+${phone}`);\n return handles.appUserId(participant.identity);\n}\n\n/** The call id LiveKit SIP puts in `sip.callID`, otherwise the room name. */\nexport function sipConversationId(participant: ParticipantLike, roomName: string): string {\n const callId = participant.attributes?.[\"sip.callID\"]?.trim();\n if (callId) return callId;\n return roomName;\n}\n\n/**\n * The memory of one call, shared by every agent that takes part in it. Put its\n * `onUserTurnCompleted` in your agent (or use `NiadraAgent`), its `toolset()` in the agent's\n * tools, and `attach()` it to the session.\n */\nexport class NiadraMemory {\n readonly conversation: Conversation;\n private readonly bridge: Bridge;\n private readonly recordAgent: boolean;\n private readonly customerTurns = new Set<string>();\n private usage: ModelUsage | null = null;\n /** The final transcript segments of the turn the caller is still speaking. */\n private heard: string[] = [];\n\n constructor(options: NiadraMemoryOptions) {\n this.conversation = options.conversation;\n this.bridge = new Bridge(options.conversation, options.verify, options.agentMemory);\n this.bridge.begin(); // the call is starting: its first read runs meanwhile\n this.recordAgent = options.recordAgent ?? true;\n }\n\n /**\n * Records the customer's final transcript, then puts the pack after the instructions and the\n * suffix after the new message, for this reply only. Never throws.\n */\n async onUserTurnCompleted(turnCtx: llm.ChatContext, newMessage: llm.ChatMessage): Promise<void> {\n this.recordCustomer(newMessage);\n const read = await this.bridge.read();\n try {\n const items = turnCtx.items;\n for (const id of [CONTEXT_ID, SUFFIX_ID]) {\n const index = items.findIndex((item) => item.id === id);\n if (index >= 0) items.splice(index, 1);\n }\n if (read.prefix) {\n let position = 0;\n while (position < items.length && isInstruction(items[position])) position++;\n const message = turnCtx.addMessage({ id: CONTEXT_ID, role: \"system\", content: read.prefix });\n items.splice(items.indexOf(message), 1);\n items.splice(position, 0, message);\n }\n // Pushed last with the current time: LiveKit inserts the new message by its own, earlier,\n // timestamp, so the suffix stays after it.\n if (read.suffix) turnCtx.addMessage({ id: SUFFIX_ID, role: \"system\", content: read.suffix });\n this.bridge.injected(read.context);\n } catch (error) {\n this.bridge.logger.warn(`could not inject context (${errorName(error)})`);\n }\n }\n\n /**\n * Listens to the session: the agent's answers, handoffs between agents and the end of the call.\n * Returns a function that stops listening.\n */\n attach(session: voice.AgentSession): () => void {\n const onItem = (event: voice.ConversationItemAddedEvent): void => {\n this.onItem(event.item);\n };\n const onMetrics = (event: voice.MetricsCollectedEvent): void => {\n const metrics = event.metrics;\n if (metrics.type === \"llm_metrics\") this.usage = usageOf(metrics);\n };\n const onClose = (): void => {\n void this.bridge.end();\n };\n const onTranscribed = (event: voice.UserInputTranscribedEvent): void => {\n this.bridge.prefetch(this.hearing(event.transcript, event.isFinal));\n };\n session.on(voice.AgentSessionEventTypes.ConversationItemAdded, onItem);\n session.on(voice.AgentSessionEventTypes.MetricsCollected, onMetrics);\n session.on(voice.AgentSessionEventTypes.UserInputTranscribed, onTranscribed);\n session.on(voice.AgentSessionEventTypes.Close, onClose);\n return () => {\n session.off(voice.AgentSessionEventTypes.ConversationItemAdded, onItem);\n session.off(voice.AgentSessionEventTypes.MetricsCollected, onMetrics);\n session.off(voice.AgentSessionEventTypes.UserInputTranscribed, onTranscribed);\n session.off(voice.AgentSessionEventTypes.Close, onClose);\n };\n }\n\n /** The navigation kit as LiveKit function tools, bound to this caller. */\n tools(): llm.FunctionTool[] {\n return this.bridge.tools().map((spec) =>\n rawTool({\n name: spec.name,\n description: spec.description,\n parameters: spec.parameters,\n // LiveKit serializes what a tool returns; the parsed result keeps the model's JSON unescaped.\n execute: async (args) => parsed(await spec.execute(args ?? {})),\n }),\n );\n }\n\n /** The same tools grouped as one toolset, to add next to your own. */\n toolset(): llm.Toolset {\n return new llm.Toolset({ id: \"niadra\", tools: this.tools() });\n }\n\n /**\n * Records a transfer to a person, such as a SIP transfer to the queue. Call it right before\n * the transfer, so the attendant's screen can read the context at once.\n */\n handoffToHuman(reason?: string): Promise<void> {\n return this.bridge.handoff(\"human\", reason);\n }\n\n private onItem(item: llm.ChatMessage | llm.AgentHandoffItem): void {\n if (item.type === \"agent_handoff\") {\n const reason = item.oldAgentId ? `${item.oldAgentId} to ${item.newAgentId}` : `to ${item.newAgentId}`;\n void this.bridge.handoff(\"agent\", reason);\n return;\n }\n if (item.role === \"user\") {\n this.recordCustomer(item);\n return;\n }\n if (item.role !== \"assistant\" || !this.recordAgent) return;\n const text = item.textContent ?? \"\";\n const usage = this.usage;\n this.usage = null;\n this.bridge.agent(text, usage ? { usage, idempotency_key: item.id } : { idempotency_key: item.id });\n }\n\n /** The turn so far: its final segments and, when `transcript` is interim, that one too. */\n private hearing(transcript: string, isFinal: boolean): string {\n const text = transcript.trim();\n if (isFinal && text) {\n this.heard.push(text);\n return this.heard.join(\" \");\n }\n return (text ? [...this.heard, text] : this.heard).join(\" \");\n }\n\n private recordCustomer(message: llm.ChatMessage): void {\n if (this.customerTurns.has(message.id)) return;\n this.customerTurns.add(message.id);\n this.heard = [];\n const confidence = message.transcriptConfidence;\n this.bridge.customer(message.textContent ?? \"\", {\n idempotency_key: message.id,\n ...(typeof confidence === \"number\" && confidence >= 0 && confidence <= 1 ? { stt_confidence: confidence } : {}),\n });\n }\n}\n\nexport interface NiadraAgentOptions<UserData> extends voice.AgentOptions<UserData> {\n memory: NiadraMemory;\n /** Adds the navigation kit to the agent's tools. Defaults to `true`. */\n historyTools?: boolean;\n}\n\n/**\n * A LiveKit `Agent` with Niadra wired in: context before each reply and the navigation kit\n * among its tools. Subclasses that override `onUserTurnCompleted` call `super.onUserTurnCompleted`.\n */\nexport class NiadraAgent<UserData = unknown> extends voice.Agent<UserData> {\n readonly memory: NiadraMemory;\n\n constructor({ memory, historyTools = true, ...options }: NiadraAgentOptions<UserData>) {\n const tools = historyTools ? withToolset(options.tools, memory.toolset()) : options.tools;\n super(tools === undefined ? options : { ...options, tools });\n this.memory = memory;\n }\n\n override async onUserTurnCompleted(turnCtx: llm.ChatContext, newMessage: llm.ChatMessage): Promise<void> {\n await this.memory.onUserTurnCompleted(turnCtx, newMessage);\n }\n}\n\nfunction withToolset<UserData>(\n tools: llm.ToolContextLike<UserData> | undefined,\n toolset: llm.Toolset,\n): llm.ToolContextLike<UserData> {\n const base = tools === undefined ? [] : llm.toToolContext(tools).tools;\n return new llm.ToolContext<UserData>([...base, toolset]);\n}\n\nfunction parsed(text: string): unknown {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return text;\n }\n}\n\nfunction isInstruction(item: llm.ChatItem | undefined): boolean {\n if (!item) return false;\n if (LEADING_IDS.has(item.id)) return true;\n return item.type === \"message\" && INSTRUCTION_ROLES.has(item.role);\n}\n\nfunction usageOf(metrics: { promptTokens: number; promptCachedTokens: number; cacheCreationTokens?: number | undefined; metadata?: { modelProvider?: string | undefined; modelName?: string | undefined } | undefined }): ModelUsage | null {\n const provider = metrics.metadata?.modelProvider?.toLowerCase();\n const model = metrics.metadata?.modelName;\n const prompt = count(metrics.promptTokens);\n // Test doubles and some plugins report \"unknown\"; a turn without usage is better than a wrong one.\n if (!provider || !model || provider === \"unknown\" || model === \"unknown\" || !prompt) return null;\n const cached = count(metrics.promptCachedTokens) ?? 0;\n const written = count(metrics.cacheCreationTokens) ?? 0;\n return { provider, model, prompt_tokens: Math.max(prompt, cached + written), cached_tokens: cached, cache_write_tokens: written };\n}\n"]}
1
+ {"version":3,"sources":["../src/handles.ts","../src/context.ts","../src/integrations/shared.ts","../src/integrations/livekit.ts"],"names":["llm","voice"],"mappings":"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","file":"livekit.cjs","sourcesContent":["import { NiadraValidationError } from \"./errors.js\";\nimport type { Handle, ObjectRef } from \"./types/common.js\";\nimport type { SubjectKind } from \"./types/vocabulary.js\";\n\ninterface HandleOptions {\n /** Overrides the subject kind the server would infer from the handle type. */\n subjectKind?: SubjectKind;\n}\n\nfunction build(type: Handle[\"type\"], value: string, scope?: string, options?: HandleOptions): Handle {\n const handle: Handle = { type, value };\n if (scope !== undefined) handle.scope = scope;\n if (options?.subjectKind !== undefined) handle.subject_kind = options.subjectKind;\n return handle;\n}\n\n/**\n * Builders for the handle types the API accepts. They only assemble the object; the value is\n * normalized and validated on the server, which is the single source of truth for matching.\n *\n * @example\n * niadra.context({ subject: handles.phone(\"+5511987654321\"), conversation_id: \"wa-8812\" })\n */\nexport const handles = {\n /** A phone number in E.164 form, such as `+5511987654321`. */\n phone: (e164: string, options?: HandleOptions): Handle => build(\"phone_e164\", e164, undefined, options),\n email: (address: string, options?: HandleOptions): Handle => build(\"email\", address, undefined, options),\n /** The WhatsApp id (`wa_id`) the Cloud API reports for a contact. */\n waId: (value: string, options?: HandleOptions): Handle => build(\"wa_id\", value, undefined, options),\n waJid: (value: string, options?: HandleOptions): Handle => build(\"wa_jid\", value, undefined, options),\n waLid: (value: string, options?: HandleOptions): Handle => build(\"wa_lid\", value, undefined, options),\n /** A business-scoped WhatsApp user id; `businessAccount` is the WhatsApp Business account it belongs to. */\n waBsuid: (value: string, businessAccount: string, options?: HandleOptions): Handle =>\n build(\"wa_bsuid\", value, businessAccount, options),\n /** The user id in your own app or site. */\n appUserId: (value: string, options?: HandleOptions): Handle => build(\"app_user_id\", value, undefined, options),\n /** The id of a person or organization in a system of record; `system` names that system, such as `crm`. */\n systemId: (value: string, system: string, options?: HandleOptions): Handle =>\n build(\"system_id\", value, system, options),\n /** An HMAC of a national document number; `country` is its ISO 3166-1 alpha-2 code. */\n govIdHmac: (value: string, country: string, options?: HandleOptions): Handle =>\n build(\"gov_id_hmac\", value, country, options),\n /** An HMAC of a company registry number. Identifies an organization. */\n orgRegistryHmac: (value: string, country: string): Handle =>\n build(\"org_registry_hmac\", value, country, { subjectKind: \"account\" }),\n /** An e-mail domain, such as `acme.com`. Identifies an organization. */\n emailDomain: (domain: string): Handle => build(\"email_domain\", domain, undefined, { subjectKind: \"account\" }),\n /** An anonymous visitor or device id, before the person is known. */\n anonId: (value: string, options?: HandleOptions): Handle => build(\"anon_id\", value, undefined, options),\n} as const;\n\n/**\n * Accepts an `ObjectRef` or the `type:namespace:id` shorthand. The id may itself contain\n * colons (`invoice:erp:2026:0823`); only the first two separate the parts.\n */\nexport function toObjectRef(object: ObjectRef | string): ObjectRef {\n if (typeof object !== \"string\") return object;\n const first = object.indexOf(\":\");\n const second = first < 0 ? -1 : object.indexOf(\":\", first + 1);\n if (first <= 0 || second <= first + 1 || second === object.length - 1) {\n throw new NiadraValidationError(\"object must look like `type:namespace:id`\");\n }\n return { type: object.slice(0, first), namespace: object.slice(first + 1, second), id: object.slice(second + 1) };\n}\n","import { NiadraValidationError } from \"./errors.js\";\nimport { includeText } from \"./constraints/text.js\";\nimport type { NiadraError } from \"./errors.js\";\nimport { toObjectRef } from \"./handles.js\";\nimport type { Handle, ObjectRef } from \"./types/common.js\";\nimport type {\n ContextFormat,\n ContextPack,\n ContextRequest,\n ContextResponse,\n CoordinationBlock,\n Include,\n LiveTurn,\n PrefetchRequest,\n TargetModel,\n} from \"./types/context.js\";\nimport type { ConstraintsBlock } from \"./types/signals.js\";\nimport type { StateView } from \"./types/state.js\";\nimport type { Verification, View } from \"./types/vocabulary.js\";\n\n/** Arguments of `context()`. Pass exactly one of `subject` or `object`. */\nexport interface ContextParams {\n /** The customer, by any handle the server knows. */\n subject?: Handle;\n /** A business object, such as an invoice, when the task is about the object rather than a person. */\n object?: ObjectRef | string;\n /** The account or partner the person acts for. Requires an active link between the two. */\n about?: Handle;\n /** Defaults to `chat`. */\n view?: View;\n /**\n * The level proven in this conversation. The server may answer with a lower effective level\n * when the source's ceiling is lower; see `response.verification`.\n */\n verification?: Verification;\n /** Enables the per-conversation cache and the server's pinning of the pack. */\n conversation_id?: string;\n /** For internal agents: the task plays the role of the conversation. */\n task_id?: string;\n /**\n * Other words than the turn to pick this read's slots by. Up to 2,000 characters. Wins over\n * `turn`, and like it never changes the pack.\n */\n query?: string;\n /**\n * The customer's last turn; a conversation passes it for you. It goes as `query` and the answer\n * adds `slots`, what the turn selected from memory, in `suffix`, while the pack stays the\n * conversation's pinned one (and is cached as without it).\n */\n turn?: string | null;\n /** Ask only for what changed since this source last read the subject. */\n delta?: boolean;\n /** The model that will read the pack, so the server can size it for that model's prompt cache. */\n target?: TargetModel;\n /** `json` also returns the pack as typed sections in `pack` (`context-pack.v1`). Defaults to `text`. */\n format?: ContextFormat;\n /**\n * Adds `why` to each of `pack.slots`, naming the retrieval channels that\n * ranked it, the fused score, the weights version and, for a derived line, the rule behind it.\n * Requires `format: \"json\"`. It changes nothing else: the pinned text, the slots chosen and the\n * receipt are the same bytes with or without it.\n */\n explain?: boolean;\n /**\n * Blocks read in the same round trip: `[\"constraints\"]` returns the subject's constraints block, `[\"state\"]`\n * the state of their objects. Each only where the space turned its feature on; a block the space does not\n * serve is left out and not asked again for a while, and the read goes on. The blocks are cached with the\n * pack, so a read that fails serves the last good ones too.\n */\n include?: Include[];\n}\n\n/** Arguments of `prefetch()`: who the turn is about, as in `context()`, and the turn so far. */\nexport interface PrefetchParams {\n subject?: Handle;\n object?: ObjectRef | string;\n about?: Handle;\n /** Defaults to `voice`, where partial transcripts come from. */\n view?: View;\n verification?: Verification;\n conversation_id?: string;\n task_id?: string;\n /** The partial transcript of the customer's turn. */\n text: string;\n}\n\n/** Per-call options shared by every read method. */\nexport interface RequestOptions {\n /** Overrides the method's default time budget, in milliseconds. */\n timeout?: number | undefined;\n /** Cancels the wait. A request shared with other callers keeps running for them. */\n signal?: AbortSignal | undefined;\n /** Extra headers, such as a W3C `traceparent`. */\n headers?: Record<string, string> | undefined;\n}\n\nexport interface ContextOptions extends RequestOptions {\n /** Pass `false` to skip the per-conversation cache for this call. */\n cache?: boolean | undefined;\n /** For `conversation.context()` and `task.context()`: blocks read in the same round trip. */\n include?: Include[] | undefined;\n /** For `conversation.context()` and `task.context()`: `json` also returns `pack`. */\n format?: ContextFormat | undefined;\n /**\n * For `conversation.context()` and `task.context()`: adds `why` to each of `pack.slots`.\n * Requires `format: \"json\"`.\n */\n explain?: boolean | undefined;\n}\n\n/**\n * Where a `context()` result came from.\n *\n * - `network`: a response the server just sent (or confirmed unchanged).\n * - `cache`: a pack younger than the cache TTL; no request was made.\n * - `stale`: an older pack returned at once while a background request refreshes it.\n * - `fallback`: the request failed and this is the last good pack for the conversation.\n * - `none`: nothing was available; `text` is empty and `error` says why.\n */\nexport type ContextSource = \"network\" | \"cache\" | \"stale\" | \"fallback\" | \"none\";\n\n/** What `context()` resolves to. Always usable: on failure `text` is an empty string. */\nexport interface ContextResult {\n /** The pack, ready for the system prompt. Empty when there is nothing to inject. */\n text: string;\n /**\n * The parts that change turn by turn and belong at the end of the prompt, after the\n * conversation: the live turns from other channels, this turn's slots (what the customer's last\n * turn selected from memory), the blocks asked for by `include` (the state view, the constraints) and the\n * delta, in that order, as the API places them. Empty when there are none.\n */\n suffix: string;\n /** Named values from the pack, for templates that place them individually. */\n variables: Record<string, string>;\n /** The pack as typed sections, when read with `format: \"json\"`; otherwise `null`. */\n pack: ContextPack | null;\n source: ContextSource;\n /**\n * How long ago Niadra sent or confirmed the pack served, in milliseconds: 0 for an answer just received,\n * growing while a cached pack is served (`cache`, `stale`, or `fallback` with Niadra down), and `null` when\n * there is no pack.\n */\n ageMs: number | null;\n /** The response this result was built from; `null` when `source` is `none`. */\n response: ContextResponse | null;\n /** What went wrong, when `source` is `fallback` or `none`. */\n error: NiadraError | null;\n /** With `include: [\"constraints\"]`: the subject's constraints block. */\n constraints?: ConstraintsBlock | null;\n /** With `include: [\"state\"]`: the state of the subject's objects. */\n state?: StateView | null;\n /** With `include: [\"coordination\"]`: what coordination knows of the subject. */\n coordination?: CoordinationBlock | null;\n}\n\nconst VIEW = /^(voice|chat|brief|full|custom|account|partner|task:[a-z0-9_]{1,40})$/;\nconst MAX_QUERY = 2000;\n\n/** Validates the arguments and builds the wire request, without `known_etag`. */\nexport function buildContextRequest(params: ContextParams): ContextRequest {\n if ((params.subject === undefined) === (params.object === undefined)) {\n throw new NiadraValidationError(\"pass exactly one of `subject` or `object`\");\n }\n if (params.conversation_id && params.task_id) {\n throw new NiadraValidationError(\"pass `conversation_id` or `task_id`, not both\");\n }\n if (params.view !== undefined && !VIEW.test(params.view)) {\n throw new NiadraValidationError(\"unknown view; task views look like `task:billing`\");\n }\n if (params.query !== undefined && params.query.length > MAX_QUERY) {\n throw new NiadraValidationError(`query is longer than ${MAX_QUERY} characters`);\n }\n\n const request: ContextRequest = { view: params.view ?? \"chat\" };\n if (params.subject) request.subject = params.subject;\n if (params.object !== undefined) request.object = toObjectRef(params.object);\n if (params.about) request.about = params.about;\n if (params.verification) request.verification = params.verification;\n if (params.conversation_id) request.conversation_id = params.conversation_id;\n if (params.task_id) request.task_id = params.task_id;\n if (params.query) request.query = params.query;\n if (params.delta) request.delta = true;\n if (params.target) request.target = params.target;\n const format: string = params.format ?? \"text\";\n if (format !== \"text\" && format !== \"json\") throw new NiadraValidationError(\"format is `text` or `json`\");\n if (format === \"json\") request.format = \"json\";\n if (params.explain) {\n if (format !== \"json\") throw new NiadraValidationError('explain requires format: \"json\"');\n request.explain = true;\n }\n if (params.include?.length) request.include = [...new Set(params.include)];\n return request;\n}\n\n/** Validates the arguments of `prefetch()` and builds the wire request. */\nexport function buildPrefetchRequest(params: PrefetchParams): PrefetchRequest {\n if ((params.subject === undefined) === (params.object === undefined)) {\n throw new NiadraValidationError(\"pass exactly one of `subject` or `object`\");\n }\n if (params.conversation_id && params.task_id) {\n throw new NiadraValidationError(\"pass `conversation_id` or `task_id`, not both\");\n }\n if (params.view !== undefined && !VIEW.test(params.view)) {\n throw new NiadraValidationError(\"unknown view; task views look like `task:billing`\");\n }\n const text = params.text.trim();\n if (!text || text.length > MAX_QUERY) throw new NiadraValidationError(`text must be 1 to ${MAX_QUERY} characters`);\n const request: PrefetchRequest = { view: params.view ?? \"voice\", query: text };\n if (params.subject) request.subject = params.subject;\n if (params.object !== undefined) request.object = toObjectRef(params.object);\n if (params.about) request.about = params.about;\n if (params.verification) request.verification = params.verification;\n if (params.conversation_id) request.conversation_id = params.conversation_id;\n if (params.task_id) request.task_id = params.task_id;\n return request;\n}\n\n/** Packs are only cached inside a conversation or task, the unit the server pins them to. */\nexport function cacheScope(request: Pick<ContextRequest, \"conversation_id\" | \"task_id\">): string | null {\n if (request.conversation_id) return `conversation:${request.conversation_id}`;\n if (request.task_id) return `task:${request.task_id}`;\n return null;\n}\n\n/**\n * Every field that changes what the server would compile goes into the key, in a fixed order.\n * `delta` does not: a plain read and a delta read of one conversation get the same pinned\n * bytes, so they share one entry.\n */\nexport function cacheKey(request: ContextRequest): string {\n return JSON.stringify([\n request.subject ?? null,\n request.object ?? null,\n request.about ?? null,\n request.view ?? \"chat\",\n request.verification ?? \"V0\",\n request.conversation_id ?? null,\n request.task_id ?? null,\n request.query ?? null,\n request.target ?? null,\n request.format ?? \"text\",\n request.explain ?? false,\n request.include ?? null,\n ]);\n}\n\n/**\n * Applies a `not_modified` answer to the cached pack: the pinned text and its metadata stay,\n * while the parts outside the pin (live turns, delta, coverage, timing) come from the new answer.\n */\nexport function mergeNotModified(cached: ContextResponse, fresh: ContextResponse): ContextResponse {\n return {\n ...fresh,\n not_modified: false,\n text: cached.text ?? null,\n variables: cached.variables,\n version: cached.version,\n etag: cached.etag,\n manifest_hash: cached.manifest_hash ?? null,\n withheld: cached.withheld,\n cache: cached.cache ?? null,\n pack: cached.pack ?? null,\n // The blocks sit outside the pinned pack: a fresh block wins, and a missing one keeps the cached.\n constraints: fresh.constraints ?? cached.constraints ?? null,\n state: fresh.state ?? cached.state ?? null,\n coordination: fresh.coordination ?? cached.coordination ?? null,\n };\n}\n\nexport function resultFrom(\n response: ContextResponse,\n source: ContextSource,\n error: NiadraError | null = null,\n ageMs: number | null = 0,\n): ContextResult {\n // A conversation in the control group gets an empty pack on purpose; it is not an error.\n const holdout = response.path === \"holdout\";\n const text = holdout ? \"\" : (response.text ?? \"\");\n const pack = holdout ? null : (response.pack ?? null);\n const blocks = {\n constraints: response.constraints ?? null,\n state: response.state ?? null,\n coordination: response.coordination ?? null,\n };\n return { text, suffix: renderSuffix(response), variables: response.variables, pack, source, ageMs, response, error, ...blocks };\n}\n\nexport function emptyResult(error: NiadraError | null): ContextResult {\n return { text: \"\", suffix: \"\", variables: {}, pack: null, source: \"none\", ageMs: null, response: null, error, constraints: null, state: null, coordination: null };\n}\n\n/**\n * Renders the live turns, the slots and the delta for the end of the prompt, in that order. Kept\n * outside the pinned pack so that the prompt prefix stays byte-identical across turns and the\n * model provider's prompt cache keeps hitting. Returns an empty string when there is nothing to add.\n */\nexport function renderSuffix(response: ContextResponse): string {\n if (response.path === \"holdout\") return \"\";\n const included = includeText(response.text, response.state, response.constraints);\n return [renderLive(response), response.slots ?? \"\", included, response.delta ?? \"\"].filter(Boolean).join(\"\\n\\n\");\n}\n\n/**\n * Renders the live turns (recent turns from other channels that the pack has not absorbed\n * yet) as one tagged block, or an empty string when there are none. `complete=\"false\"` tells\n * the model the list may be missing turns because the server could not read all of them.\n */\nexport function renderLive(response: ContextResponse): string {\n if (response.path === \"holdout\" || response.live.length === 0) return \"\";\n const complete = response.live_complete ? \"\" : ' complete=\"false\"';\n const lines = response.live.map(renderLiveTurn).join(\"\\n\");\n return `<live_turns source=\"niadra\"${complete}>\\n${lines}\\n</live_turns>`;\n}\n\nfunction renderLiveTurn(turn: LiveTurn): string {\n return `[${utcSeconds(turn.at)}] ${turn.channel} · ${turn.speaker}: ${turn.text}`;\n}\n\n/** The same timestamp form in every SDK, whatever precision or offset the server sent. */\nfunction utcSeconds(at: string): string {\n const ms = Date.parse(at);\n return Number.isNaN(ms) ? at : `${new Date(ms).toISOString().slice(0, 19)}Z`;\n}\n","/**\n * What every framework adapter shares: the five primitives (context before the model call, the\n * turns, the tools, the verification and the handoff) wired the same way, and fail-open.\n *\n * Nothing here throws into the framework: a failed read gives an empty context, a failed write\n * is logged without content, and the agent keeps working without memory.\n */\n\nimport { recordedTool } from \"../capture/tool.js\";\nimport type { Played } from \"../replay/playback.js\";\nimport type { AgentMemoryParams } from \"../agent-memory.js\";\nimport type { TurnParams } from \"../agent-session.js\";\nimport type { CallCapture, TurnFrame } from \"../capture/frame.js\";\nimport type { ContextOptions, ContextResult } from \"../context.js\";\nimport { emptyResult } from \"../context.js\";\nimport type { Conversation, TurnOptions } from \"../conversation.js\";\nimport type { Logger } from \"../logger.js\";\nimport type { Task } from \"../task.js\";\nimport type { BoundTools } from \"../tools.js\";\nimport type { Handle } from \"../types/common.js\";\nimport type { Verification, VerifyMethod } from \"../types/vocabulary.js\";\n\n/** A customer conversation or an internal agent's task. */\nexport type Session = Conversation | Task;\n\n/** A session, or a function that finds the one the current call belongs to (`null` passes the call through). */\nexport type SessionResolver<S extends Session = Session> = S | (() => S | null | undefined);\n\n/** What the framework proved about the person, recorded with `verify()` before the first context read. */\nexport interface Proof {\n method: VerifyMethod;\n level: Verification;\n /** Defaults to the session's subject. */\n handle?: Handle;\n}\n\n/** A proof, or a function that reads it from the framework when the first context is needed. */\nexport type ProofSource =\n | Proof\n | null\n | undefined\n | (() => Proof | null | undefined | PromiseLike<Proof | null | undefined>);\n\n/**\n * The agent's own working notes: `true` puts the block before the customer's context and offers\n * `search_agent_memory`; `{ write: true }` also offers `remember` (for a key with the\n * `agent_memory:write` scope); the other fields go to `agentMemory()`.\n */\nexport type AgentMemoryOption = boolean | (AgentMemoryParams & { write?: boolean });\n\n/** What goes into the prompt for one model call. */\nexport interface Read {\n context: ContextResult;\n /** The agent's own notes, or an empty string. */\n memory: string;\n /** What goes after the instructions: the notes, then the customer's pack. */\n prefix: string;\n /** What goes at the end: live turns, the turn's slots and deltas. */\n suffix: string;\n}\n\n/** A tool as every framework needs it: the name, the text for the model, the JSON Schema and the call. */\ninterface ToolSpec {\n name: string;\n description: string;\n /** JSON Schema of the arguments. None of them names the customer. */\n parameters: Record<string, unknown>;\n /** Runs the call and returns the text for the model. Never rejects in fail-open mode. */\n execute(args: string | Record<string, unknown>): Promise<string>;\n}\n\nconst ATTESTED: Record<string, Verification> = { A: \"V2\", B: \"V1\", C: \"V1\" };\n\n/**\n * The proof a carrier's STIR/SHAKEN attestation gives a phone call: `A` proves V2, `B` and `C`\n * prove V1, anything else proves nothing (`null`). Accepts the bare letter or the forms carriers\n * and platforms send, such as Twilio's `TN-Validation-Passed-A`.\n */\nexport function attestationProof(attestation: string | null | undefined): Proof | null {\n if (!attestation) return null;\n const value = attestation.trim().toUpperCase();\n if (value.includes(\"FAILED\") || value.startsWith(\"NO-\")) return null;\n const letter = value.length === 1 ? value : /PASSED-([ABC])$/.exec(value)?.[1];\n const level = letter ? ATTESTED[letter] : undefined;\n return level ? { method: \"network_attestation\", level } : null;\n}\n\nexport function resolveSession<S extends Session>(source: SessionResolver<S>): S | null {\n if (typeof source !== \"function\") return source;\n try {\n return source() ?? null;\n } catch {\n return null;\n }\n}\n\nfunction isConversation(session: Session): session is Conversation {\n return \"customer\" in session && typeof session.customer === \"function\";\n}\n\n/** A phone number as an E.164 handle, or `null` when it does not look like one. */\nexport function phoneHandle(value: string | null | undefined): Handle | null {\n const raw = value?.trim().replace(/^tel:/i, \"\").replace(/[\\s().-]/g, \"\");\n if (!raw) return null;\n const e164 = raw.startsWith(\"+\") ? raw : `+${raw}`;\n return /^\\+[1-9]\\d{6,14}$/.test(e164) ? { type: \"phone_e164\", value: e164 } : null;\n}\n\nexport function errorName(error: unknown): string {\n return error instanceof Error ? error.name : typeof error;\n}\n\n/**\n * One session as an adapter drives it. Keeps the verification to a single call made before the\n * first context read, and turns every failure into a log line.\n */\nexport class Bridge {\n private proving: Promise<void> | null = null;\n /** `begin()` started the first read of a call: the first `context()` waits for it with `ready()`. */\n private begun = false;\n private opened = false;\n\n constructor(\n readonly session: Session,\n private readonly proof?: ProofSource,\n private readonly memory: AgentMemoryOption = false,\n ) {}\n\n /**\n * The context and, when enabled, the agent's notes, read side by side within the same budget.\n * Never rejects.\n */\n async read(options: ContextOptions = {}): Promise<Read> {\n const memoryParams = this.memory === false ? null : this.memory === true ? {} : withoutWrite(this.memory);\n const [context, memory] = await Promise.all([\n this.context(options),\n memoryParams ? this.agentMemory(memoryParams, options) : Promise.resolve(\"\"),\n ]);\n return { context, memory, prefix: [memory, context.text].filter(Boolean).join(\"\\n\\n\"), suffix: context.suffix };\n }\n\n get logger(): Logger {\n return this.session.logger;\n }\n\n /**\n * Starts the first read of a call now, in the background, after the proof when one was given (the\n * pack depends on the level it proves): at call start, so the read runs while the call is set up.\n * The first `context()` then waits for it within `timeouts.contextVoiceStart`. Never throws.\n */\n begin(): void {\n const session = this.session;\n if (!isConversation(session)) return;\n const start = (): void => {\n this.safe(\"start the first read\", () => {\n // False off the voice read path (a chat view, the cache off): reads go on as before.\n this.begun = session.begin();\n });\n };\n if (this.proof === undefined || this.proof === null) start();\n else void this.verifyOnce().then(start);\n }\n\n /** Verifies once (when a proof was given), then reads the context. Never rejects. */\n async context(options: ContextOptions = {}): Promise<ContextResult> {\n await this.verifyOnce();\n try {\n const session = this.session;\n if (this.begun && !this.opened && isConversation(session)) {\n this.opened = true;\n // The call's first read, begun at call start: waited for within its own, longer budget.\n await session.ready(options.timeout === undefined ? {} : { timeout: options.timeout });\n }\n return await this.session.context(options);\n } catch (error) {\n this.logger.warn(`could not read context (${errorName(error)})`);\n return emptyResult(null);\n }\n }\n\n /** Records that `context` went into the prompt, unless it was empty for a reason other than the holdout. */\n injected(context: ContextResult): void {\n if (!context.text && !context.suffix && context.response?.path !== \"holdout\") return;\n this.safe(\"mark the injection\", () => {\n this.session.markInjected(context);\n });\n }\n\n customer(text: string, options: TurnOptions = {}): void {\n const session = this.session;\n if (!text.trim() || !isConversation(session)) return;\n this.safe(\"record the customer's turn\", () => session.customer(text, options));\n }\n\n /** Sends the customer's turn so far, while they speak. In the background; never throws. */\n prefetch(text: string): void {\n const session = this.session;\n if (!text.trim() || !isConversation(session)) return;\n this.safe(\"prefetch the turn\", () => session.prefetch(text));\n }\n\n agent(text: string, options: TurnOptions = {}): void {\n if (!text.trim()) return;\n this.safe(\"record the agent's turn\", () => this.session.agent(text, options));\n }\n\n /** Records a transfer. Tasks have no transfer; the call is ignored for them. */\n async handoff(target: \"agent\" | \"human\", reason?: string): Promise<void> {\n const session = this.session;\n if (!isConversation(session)) return;\n try {\n await session.handoff(reason ? { target, reason } : { target });\n } catch (error) {\n this.logger.warn(`could not record the handoff (${errorName(error)})`);\n }\n }\n\n async end(): Promise<void> {\n try {\n await this.session.end();\n } catch (error) {\n this.logger.warn(`could not end the session (${errorName(error)})`);\n }\n }\n\n /** The navigation kit as plain specs (with the agent's memory tools when enabled), or none for a task about an object only. */\n tools(): ToolSpec[] {\n let bound: BoundTools | null;\n try {\n const memory = this.memory;\n bound = this.session.tools(memory === false ? {} : { agentMemory: true, writeAgentMemory: memory !== true && memory.write === true });\n } catch (error) {\n this.logger.warn(`could not build the tools (${errorName(error)})`);\n return [];\n }\n return bound ? toolSpecs(bound) : [];\n }\n\n private async agentMemory(params: AgentMemoryParams, options: ContextOptions): Promise<string> {\n try {\n const result = await this.session.agentMemory(params, options.timeout === undefined ? {} : { timeout: options.timeout });\n return result.text;\n } catch (error) {\n this.logger.warn(`could not read the agent's memory (${errorName(error)})`);\n return \"\";\n }\n }\n\n private async verifyOnce(): Promise<void> {\n if (this.proof === undefined || this.proof === null) return;\n this.proving ??= this.runVerify();\n await this.proving;\n }\n\n private async runVerify(): Promise<void> {\n try {\n const source = this.proof;\n const proof = typeof source === \"function\" ? await source() : source;\n if (!proof) return;\n await this.session.verify(proof);\n } catch (error) {\n this.logger.warn(`could not record the verification (${errorName(error)})`);\n }\n }\n\n private safe(what: string, run: () => unknown): void {\n try {\n run();\n } catch (error) {\n this.logger.warn(`could not ${what} (${errorName(error)})`);\n }\n }\n}\n\nfunction withoutWrite(option: AgentMemoryParams & { write?: boolean }): AgentMemoryParams {\n const { write: _, ...params } = option;\n return params;\n}\n\n/** The bound kit as specs. The customer stays inside `bound`; no parameter names them. */\nfunction toolSpecs(bound: BoundTools): ToolSpec[] {\n return bound.definitions.map(({ function: definition }) => ({\n name: definition.name,\n description: definition.description,\n parameters: definition.parameters,\n execute: (args) => bound.call(definition.name, args),\n }));\n}\n\n/** The text of a message content in the shapes model APIs use: a string, or a list of text parts. */\nexport function textOf(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n const parts: string[] = [];\n for (const part of content as unknown[]) {\n if (typeof part === \"string\") parts.push(part);\n else if (isRecord(part) && typeof part.text === \"string\" && (part.type === undefined || part.type === \"text\")) {\n parts.push(part.text);\n }\n }\n return parts.join(\"\");\n}\n\nexport function isRecord(value: unknown): value is Record<PropertyKey, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\n/** A non-negative integer, or `null`. */\nexport function count(value: unknown): number | null {\n return typeof value === \"number\" && Number.isInteger(value) && value >= 0 ? value : null;\n}\n\n/**\n * The turn records an adapter keeps from its framework's callbacks, keyed by the framework's own ids (a\n * run, a request, a tool call id). A run starting while the session has a turn in progress (yours, from\n * `conversation.turn()`, or a replay's) records into it; otherwise the adapter opens its own turn and closes\n * it when the run ends. A tool call recorded here is taken over by a `tool()` wrapper running inside it, so\n * the call is recorded once. Every method does nothing when turns are off and never throws.\n */\nexport class TurnHooks {\n /** Runs held open at most; past it the oldest run's turn closes, incomplete (a run whose end never came). */\n static readonly MAX_OPEN = 100;\n private readonly frames = new Map<string, { frame: TurnFrame; own: boolean }>();\n private readonly calls = new Map<string, CallCapture>();\n\n constructor(\n readonly adapter: string,\n readonly enabled: boolean,\n ) {}\n\n /** The turn of the run `key`: the session's turn in progress, or a new one of its own. */\n open(session: Session, key: string, params: TurnParams = {}): TurnFrame | undefined {\n if (!this.enabled) return undefined;\n const held = this.frames.get(key);\n if (held !== undefined) return held.frame;\n try {\n const active = session.activeTurn();\n if (active !== undefined && !this.owns(active)) {\n this.frames.set(key, { frame: active, own: false });\n return active;\n }\n const frame = session.openTurn({ ...params, adapter: this.adapter });\n this.frames.set(key, { frame, own: true });\n if (this.frames.size > TurnHooks.MAX_OPEN) {\n const [oldest] = this.frames.keys();\n if (oldest !== undefined) {\n this.frames.get(oldest)?.frame.incomplete();\n this.close(oldest);\n }\n }\n return frame;\n } catch (error) {\n session.logger.warn(`could not open the turn (${errorName(error)})`);\n return undefined;\n }\n }\n\n /** The turn of `key`, else the session's turn in progress. */\n frame(session: Session, key?: string): TurnFrame | undefined {\n if (!this.enabled) return undefined;\n const held = key === undefined ? undefined : this.frames.get(key);\n const frame = held?.frame ?? session.activeTurn();\n return frame === undefined || frame.closed ? undefined : frame;\n }\n\n has(key: string): boolean {\n return this.frames.has(key);\n }\n\n private owns(frame: TurnFrame): boolean {\n for (const held of this.frames.values()) if (held.own && held.frame === frame) return true;\n return false;\n }\n\n /** Ends the run `key`: a turn the adapter opened closes; the calls it left open failed. */\n close(key: string, error?: unknown): void {\n const held = this.frames.get(key);\n if (held === undefined) return;\n this.frames.delete(key);\n for (const [callKey, call] of this.calls) {\n if (call.frame !== held.frame) continue;\n this.calls.delete(callKey);\n if (held.own) call.failed(error ?? \"error\");\n }\n if (held.own) held.frame.close(error);\n }\n\n /** A tool call starting, keyed by `callKey`; `callId` is the provider's id of the call, when there is one. */\n toolStart(session: Session, callKey: string, name: string, args: unknown, options: { frameKey?: string; callId?: string | null } = {}): void {\n const frame = this.frame(session, options.frameKey);\n if (frame === undefined) return;\n try {\n this.calls.set(callKey, frame.toolCall(name, args, { callId: options.callId ?? null, adoptable: true }));\n } catch {\n frame.incomplete();\n }\n }\n\n /**\n * In a replay, how a framework tool the adapter stands in for answers: the recorded result of a call with the\n * same arguments, or empty (a divergence), never the live tool. `null` outside a replay, and for a function\n * wrapped with `tool()`, which answers itself.\n */\n replayed(session: Session, name: string, args: unknown, fn?: unknown, frameKey?: string): Played | null {\n const frame = this.enabled ? this.frame(session, frameKey) : session.activeTurn();\n if (frame?.playback == null || (fn !== undefined && recordedTool(fn) !== null)) return null;\n return frame.playback.answer(name, args, false);\n }\n\n toolEnd(callKey: string, result?: unknown, error?: unknown): void {\n const call = this.calls.get(callKey);\n if (call === undefined) return;\n this.calls.delete(callKey);\n try {\n if (error !== undefined) call.failed(error);\n else call.result(result);\n } catch {\n call.frame.incomplete();\n }\n }\n\n /** A model call that ended, with its tokens when the framework reported them. */\n model(\n session: Session,\n model: string | null | undefined,\n tokens: { in?: number | null; out?: number | null; cached?: number | null } = {},\n frameKey?: string,\n ): void {\n const frame = this.frame(session, frameKey);\n if (frame === undefined) return;\n try {\n frame.modelCall(model, { tokensIn: tokens.in ?? null, tokensOut: tokens.out ?? null, tokensCached: tokens.cached ?? 0 });\n } catch {\n frame.incomplete();\n }\n }\n}\n","/**\n * Niadra for LiveKit Agents (Node, `@livekit/agents` 1.9).\n *\n * The same hook as LiveKit's own RAG recipe: `onUserTurnCompleted(turnCtx, newMessage)`. There\n * the customer's final transcript is recorded, the conversation's pack goes into the turn's chat\n * context as a system message right after the agent's instructions, and the suffix (live turns\n * from other channels, what the caller's turn needs from memory, and deltas) goes after the new message. The read sends the caller's turn along. The turn context is\n * a copy LiveKit builds for this reply only, so nothing piles up in the agent's history and the prompt prefix\n * stays byte-identical turn after turn. Session events record the agent's answers (with the\n * LLM usage LiveKit measured), handoffs between agents and the end of the call.\n *\n * `NiadraMemory` starts the caller's first read when it is built (`begin()`), so it runs while the\n * session starts, and the first reply waits for it within `timeouts.contextVoiceStart` (1.5 s).\n * After that no turn waits on a round trip for the pack: it comes from memory at once. While the\n * caller is still speaking, each `user_input_transcribed` event (interim or final) sends the turn\n * so far with `prefetch()`, in the background: the server warms the caller's memory, and once the\n * words stop changing the SDK reads the turn with them, so the slots are there when LiveKit ends\n * the turn. A turn waits at most 200 ms for such a read still on its way, then answers without\n * the slots; a prefetch never holds or fails a turn.\n *\n * @example\n * const caller = ctx.room.remoteParticipants.values().next().value;\n * const convo = niadra.conversation({ subject: sipSubject(caller), channel: \"voice\", conversation_id: sipConversationId(caller, ctx.room.name) });\n * const memory = new NiadraMemory({ conversation: convo, verify: attestationProof(caller.attributes[\"sip.h.x-stir-verstat\"]) });\n * const agent = new NiadraAgent({ instructions: \"You are the support line of Acme.\", memory });\n * memory.attach(session);\n * await session.start({ agent, room: ctx.room });\n */\n\nimport { llm, voice } from \"@livekit/agents\";\nimport type { Conversation } from \"../conversation.js\";\nimport { handles } from \"../handles.js\";\nimport type { Handle } from \"../types/common.js\";\nimport type { ModelUsage } from \"../types/events.js\";\nimport { Bridge, count, errorName } from \"./shared.js\";\nimport type { AgentMemoryOption, ProofSource } from \"./shared.js\";\n\nexport { attestationProof } from \"./shared.js\";\nexport type { AgentMemoryOption, Proof, ProofSource } from \"./shared.js\";\n\n/** Instructions LiveKit keeps at the head of the chat context; the pack goes after them. */\nconst LEADING_IDS = new Set([\"lk.agent_task.instructions\", \"lk.expressive.instructions\"]);\nconst INSTRUCTION_ROLES = new Set([\"system\", \"developer\"]);\nconst CONTEXT_ID = \"niadra.context\";\n\n/** `llm.tool` with a raw JSON Schema, which it accepts but cannot infer argument types from. */\nconst rawTool = llm.tool as unknown as (options: {\n name: string;\n description: string;\n parameters: Record<string, unknown>;\n execute: (args: Record<string, unknown> | undefined) => Promise<unknown>;\n}) => llm.FunctionTool;\nconst SUFFIX_ID = \"niadra.suffix\";\n\nexport interface NiadraMemoryOptions {\n /** The call, opened with `channel: \"voice\"` so reads use the voice view and budget. */\n conversation: Conversation;\n /**\n * What the call proved before the first read, such as the carrier's attestation\n * (`attestationProof(...)`). Recorded once with `verify()` before the first context.\n */\n verify?: ProofSource;\n /** Records the agent's answers from `conversation_item_added`. Defaults to `true`. */\n recordAgent?: boolean;\n /** Puts the agent's own notes before the caller's context and adds its memory tools. */\n agentMemory?: AgentMemoryOption;\n}\n\n/** Participant fields the helpers read. A `RemoteParticipant` has them. */\nexport interface ParticipantLike {\n identity: string;\n attributes?: Record<string, string> | undefined;\n}\n\n/**\n * The caller as a handle: the phone number LiveKit SIP puts in `sip.phoneNumber` (E.164, `+` added\n * when missing), otherwise the participant identity as your app's user id.\n */\nexport function sipSubject(participant: ParticipantLike): Handle {\n const phone = participant.attributes?.[\"sip.phoneNumber\"]?.trim();\n if (phone) return handles.phone(phone.startsWith(\"+\") ? phone : `+${phone}`);\n return handles.appUserId(participant.identity);\n}\n\n/** The call id LiveKit SIP puts in `sip.callID`, otherwise the room name. */\nexport function sipConversationId(participant: ParticipantLike, roomName: string): string {\n const callId = participant.attributes?.[\"sip.callID\"]?.trim();\n if (callId) return callId;\n return roomName;\n}\n\n/**\n * The memory of one call, shared by every agent that takes part in it. Put its\n * `onUserTurnCompleted` in your agent (or use `NiadraAgent`), its `toolset()` in the agent's\n * tools, and `attach()` it to the session.\n */\nexport class NiadraMemory {\n readonly conversation: Conversation;\n private readonly bridge: Bridge;\n private readonly recordAgent: boolean;\n private readonly customerTurns = new Set<string>();\n private usage: ModelUsage | null = null;\n /** The final transcript segments of the turn the caller is still speaking. */\n private heard: string[] = [];\n\n constructor(options: NiadraMemoryOptions) {\n this.conversation = options.conversation;\n this.bridge = new Bridge(options.conversation, options.verify, options.agentMemory);\n this.bridge.begin(); // the call is starting: its first read runs meanwhile\n this.recordAgent = options.recordAgent ?? true;\n }\n\n /**\n * Records the customer's final transcript, then puts the pack after the instructions and the\n * suffix after the new message, for this reply only. Never throws.\n */\n async onUserTurnCompleted(turnCtx: llm.ChatContext, newMessage: llm.ChatMessage): Promise<void> {\n this.recordCustomer(newMessage);\n const read = await this.bridge.read();\n try {\n const items = turnCtx.items;\n for (const id of [CONTEXT_ID, SUFFIX_ID]) {\n const index = items.findIndex((item) => item.id === id);\n if (index >= 0) items.splice(index, 1);\n }\n if (read.prefix) {\n let position = 0;\n while (position < items.length && isInstruction(items[position])) position++;\n const message = turnCtx.addMessage({ id: CONTEXT_ID, role: \"system\", content: read.prefix });\n items.splice(items.indexOf(message), 1);\n items.splice(position, 0, message);\n }\n // Pushed last with the current time: LiveKit inserts the new message by its own, earlier,\n // timestamp, so the suffix stays after it.\n if (read.suffix) turnCtx.addMessage({ id: SUFFIX_ID, role: \"system\", content: read.suffix });\n this.bridge.injected(read.context);\n } catch (error) {\n this.bridge.logger.warn(`could not inject context (${errorName(error)})`);\n }\n }\n\n /**\n * Listens to the session: the agent's answers, handoffs between agents and the end of the call.\n * Returns a function that stops listening.\n */\n attach(session: voice.AgentSession): () => void {\n const onItem = (event: voice.ConversationItemAddedEvent): void => {\n this.onItem(event.item);\n };\n const onMetrics = (event: voice.MetricsCollectedEvent): void => {\n const metrics = event.metrics;\n if (metrics.type === \"llm_metrics\") this.usage = usageOf(metrics);\n };\n const onClose = (): void => {\n void this.bridge.end();\n };\n const onTranscribed = (event: voice.UserInputTranscribedEvent): void => {\n this.bridge.prefetch(this.hearing(event.transcript, event.isFinal));\n };\n session.on(voice.AgentSessionEventTypes.ConversationItemAdded, onItem);\n session.on(voice.AgentSessionEventTypes.MetricsCollected, onMetrics);\n session.on(voice.AgentSessionEventTypes.UserInputTranscribed, onTranscribed);\n session.on(voice.AgentSessionEventTypes.Close, onClose);\n return () => {\n session.off(voice.AgentSessionEventTypes.ConversationItemAdded, onItem);\n session.off(voice.AgentSessionEventTypes.MetricsCollected, onMetrics);\n session.off(voice.AgentSessionEventTypes.UserInputTranscribed, onTranscribed);\n session.off(voice.AgentSessionEventTypes.Close, onClose);\n };\n }\n\n /** The navigation kit as LiveKit function tools, bound to this caller. */\n tools(): llm.FunctionTool[] {\n return this.bridge.tools().map((spec) =>\n rawTool({\n name: spec.name,\n description: spec.description,\n parameters: spec.parameters,\n // LiveKit serializes what a tool returns; the parsed result keeps the model's JSON unescaped.\n execute: async (args) => parsed(await spec.execute(args ?? {})),\n }),\n );\n }\n\n /** The same tools grouped as one toolset, to add next to your own. */\n toolset(): llm.Toolset {\n return new llm.Toolset({ id: \"niadra\", tools: this.tools() });\n }\n\n /**\n * Records a transfer to a person, such as a SIP transfer to the queue. Call it right before\n * the transfer, so the attendant's screen can read the context at once.\n */\n handoffToHuman(reason?: string): Promise<void> {\n return this.bridge.handoff(\"human\", reason);\n }\n\n private onItem(item: llm.ChatMessage | llm.AgentHandoffItem): void {\n if (item.type === \"agent_handoff\") {\n const reason = item.oldAgentId ? `${item.oldAgentId} to ${item.newAgentId}` : `to ${item.newAgentId}`;\n void this.bridge.handoff(\"agent\", reason);\n return;\n }\n if (item.role === \"user\") {\n this.recordCustomer(item);\n return;\n }\n if (item.role !== \"assistant\" || !this.recordAgent) return;\n const text = item.textContent ?? \"\";\n const usage = this.usage;\n this.usage = null;\n this.bridge.agent(text, usage ? { usage, idempotency_key: item.id } : { idempotency_key: item.id });\n }\n\n /** The turn so far: its final segments and, when `transcript` is interim, that one too. */\n private hearing(transcript: string, isFinal: boolean): string {\n const text = transcript.trim();\n if (isFinal && text) {\n this.heard.push(text);\n return this.heard.join(\" \");\n }\n return (text ? [...this.heard, text] : this.heard).join(\" \");\n }\n\n private recordCustomer(message: llm.ChatMessage): void {\n if (this.customerTurns.has(message.id)) return;\n this.customerTurns.add(message.id);\n this.heard = [];\n const confidence = message.transcriptConfidence;\n this.bridge.customer(message.textContent ?? \"\", {\n idempotency_key: message.id,\n ...(typeof confidence === \"number\" && confidence >= 0 && confidence <= 1 ? { stt_confidence: confidence } : {}),\n });\n }\n}\n\nexport interface NiadraAgentOptions<UserData> extends voice.AgentOptions<UserData> {\n memory: NiadraMemory;\n /** Adds the navigation kit to the agent's tools. Defaults to `true`. */\n historyTools?: boolean;\n}\n\n/**\n * A LiveKit `Agent` with Niadra wired in: context before each reply and the navigation kit\n * among its tools. Subclasses that override `onUserTurnCompleted` call `super.onUserTurnCompleted`.\n */\nexport class NiadraAgent<UserData = unknown> extends voice.Agent<UserData> {\n readonly memory: NiadraMemory;\n\n constructor({ memory, historyTools = true, ...options }: NiadraAgentOptions<UserData>) {\n const tools = historyTools ? withToolset(options.tools, memory.toolset()) : options.tools;\n super(tools === undefined ? options : { ...options, tools });\n this.memory = memory;\n }\n\n override async onUserTurnCompleted(turnCtx: llm.ChatContext, newMessage: llm.ChatMessage): Promise<void> {\n await this.memory.onUserTurnCompleted(turnCtx, newMessage);\n }\n}\n\nfunction withToolset<UserData>(\n tools: llm.ToolContextLike<UserData> | undefined,\n toolset: llm.Toolset,\n): llm.ToolContextLike<UserData> {\n const base = tools === undefined ? [] : llm.toToolContext(tools).tools;\n return new llm.ToolContext<UserData>([...base, toolset]);\n}\n\nfunction parsed(text: string): unknown {\n try {\n return JSON.parse(text) as unknown;\n } catch {\n return text;\n }\n}\n\nfunction isInstruction(item: llm.ChatItem | undefined): boolean {\n if (!item) return false;\n if (LEADING_IDS.has(item.id)) return true;\n return item.type === \"message\" && INSTRUCTION_ROLES.has(item.role);\n}\n\nfunction usageOf(metrics: { promptTokens: number; promptCachedTokens: number; cacheCreationTokens?: number | undefined; metadata?: { modelProvider?: string | undefined; modelName?: string | undefined } | undefined }): ModelUsage | null {\n const provider = metrics.metadata?.modelProvider?.toLowerCase();\n const model = metrics.metadata?.modelName;\n const prompt = count(metrics.promptTokens);\n // Test doubles and some plugins report \"unknown\"; a turn without usage is better than a wrong one.\n if (!provider || !model || provider === \"unknown\" || model === \"unknown\" || !prompt) return null;\n const cached = count(metrics.promptCachedTokens) ?? 0;\n const written = count(metrics.cacheCreationTokens) ?? 0;\n return { provider, model, prompt_tokens: Math.max(prompt, cached + written), cached_tokens: cached, cache_write_tokens: written };\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { voice, llm } from '@livekit/agents';
2
- import { bt as Conversation, h as Handle } from './client-DsIxZxZk.cjs';
3
- import { a as ProofSource, A as AgentMemoryOption } from './shared-DTPWVlWm.cjs';
4
- export { P as Proof, c as attestationProof } from './shared-DTPWVlWm.cjs';
2
+ import { bs as Conversation, g as Handle } from './client-B_ip8T2o.cjs';
3
+ import { a as ProofSource, A as AgentMemoryOption } from './shared-DEkF2Y_z.cjs';
4
+ export { P as Proof, c as attestationProof } from './shared-DEkF2Y_z.cjs';
5
5
 
6
6
  /**
7
7
  * Niadra for LiveKit Agents (Node, `@livekit/agents` 1.9).
package/dist/livekit.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { voice, llm } from '@livekit/agents';
2
- import { bt as Conversation, h as Handle } from './client-DsIxZxZk.js';
3
- import { a as ProofSource, A as AgentMemoryOption } from './shared-Bb5B59Bu.js';
4
- export { P as Proof, c as attestationProof } from './shared-Bb5B59Bu.js';
2
+ import { bs as Conversation, g as Handle } from './client-B_ip8T2o.js';
3
+ import { a as ProofSource, A as AgentMemoryOption } from './shared-BLkAbvuf.js';
4
+ export { P as Proof, c as attestationProof } from './shared-BLkAbvuf.js';
5
5
 
6
6
  /**
7
7
  * Niadra for LiveKit Agents (Node, `@livekit/agents` 1.9).
package/dist/livekit.js CHANGED
@@ -35,7 +35,7 @@ var handles = {
35
35
 
36
36
  // src/context.ts
37
37
  function emptyResult(error) {
38
- return { text: "", suffix: "", variables: {}, pack: null, source: "none", response: null, error, constraints: null, state: null, coordination: null };
38
+ return { text: "", suffix: "", variables: {}, pack: null, source: "none", ageMs: null, response: null, error, constraints: null, state: null, coordination: null };
39
39
  }
40
40
 
41
41
  // src/integrations/shared.ts