@nhtio/adk 1.20260609.0 → 1.20260610.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 (134) hide show
  1. package/CHANGELOG.md +132 -9
  2. package/batteries/llm/ollama/helpers.cjs +9 -0
  3. package/batteries/llm/ollama/helpers.cjs.map +1 -1
  4. package/batteries/llm/ollama/helpers.mjs +9 -0
  5. package/batteries/llm/ollama/helpers.mjs.map +1 -1
  6. package/batteries/llm/openai_chat_completions/helpers.cjs +19 -0
  7. package/batteries/llm/openai_chat_completions/helpers.cjs.map +1 -1
  8. package/batteries/llm/openai_chat_completions/helpers.mjs +19 -0
  9. package/batteries/llm/openai_chat_completions/helpers.mjs.map +1 -1
  10. package/batteries/media/builder.d.ts +245 -0
  11. package/batteries/media/contracts.cjs +119 -0
  12. package/batteries/media/contracts.cjs.map +1 -0
  13. package/batteries/media/contracts.d.ts +321 -0
  14. package/batteries/media/contracts.mjs +110 -0
  15. package/batteries/media/contracts.mjs.map +1 -0
  16. package/batteries/media/engines/audio_decode.cjs +92 -0
  17. package/batteries/media/engines/audio_decode.cjs.map +1 -0
  18. package/batteries/media/engines/audio_decode.d.ts +46 -0
  19. package/batteries/media/engines/audio_decode.mjs +90 -0
  20. package/batteries/media/engines/audio_decode.mjs.map +1 -0
  21. package/batteries/media/engines/execa_executor.cjs +64 -0
  22. package/batteries/media/engines/execa_executor.cjs.map +1 -0
  23. package/batteries/media/engines/execa_executor.d.ts +54 -0
  24. package/batteries/media/engines/execa_executor.mjs +62 -0
  25. package/batteries/media/engines/execa_executor.mjs.map +1 -0
  26. package/batteries/media/engines/fs_workspace.cjs +84 -0
  27. package/batteries/media/engines/fs_workspace.cjs.map +1 -0
  28. package/batteries/media/engines/fs_workspace.d.ts +51 -0
  29. package/batteries/media/engines/fs_workspace.mjs +82 -0
  30. package/batteries/media/engines/fs_workspace.mjs.map +1 -0
  31. package/batteries/media/engines/jimp.cjs +116 -0
  32. package/batteries/media/engines/jimp.cjs.map +1 -0
  33. package/batteries/media/engines/jimp.d.ts +32 -0
  34. package/batteries/media/engines/jimp.mjs +114 -0
  35. package/batteries/media/engines/jimp.mjs.map +1 -0
  36. package/batteries/media/engines/sharp.cjs +120 -0
  37. package/batteries/media/engines/sharp.cjs.map +1 -0
  38. package/batteries/media/engines/sharp.d.ts +42 -0
  39. package/batteries/media/engines/sharp.mjs +117 -0
  40. package/batteries/media/engines/sharp.mjs.map +1 -0
  41. package/batteries/media/engines/soffice.cjs +246 -0
  42. package/batteries/media/engines/soffice.cjs.map +1 -0
  43. package/batteries/media/engines/soffice.d.ts +39 -0
  44. package/batteries/media/engines/soffice.mjs +244 -0
  45. package/batteries/media/engines/soffice.mjs.map +1 -0
  46. package/batteries/media/engines/tesseract_js.cjs +87 -0
  47. package/batteries/media/engines/tesseract_js.cjs.map +1 -0
  48. package/batteries/media/engines/tesseract_js.d.ts +41 -0
  49. package/batteries/media/engines/tesseract_js.mjs +85 -0
  50. package/batteries/media/engines/tesseract_js.mjs.map +1 -0
  51. package/batteries/media/engines/transformers_asr.cjs +111 -0
  52. package/batteries/media/engines/transformers_asr.cjs.map +1 -0
  53. package/batteries/media/engines/transformers_asr.d.ts +41 -0
  54. package/batteries/media/engines/transformers_asr.mjs +109 -0
  55. package/batteries/media/engines/transformers_asr.mjs.map +1 -0
  56. package/batteries/media/exceptions.d.ts +103 -0
  57. package/batteries/media/forge.cjs +403 -0
  58. package/batteries/media/forge.cjs.map +1 -0
  59. package/batteries/media/forge.d.ts +90 -0
  60. package/batteries/media/forge.mjs +399 -0
  61. package/batteries/media/forge.mjs.map +1 -0
  62. package/batteries/media/formats.d.ts +72 -0
  63. package/batteries/media/index.d.ts +136 -0
  64. package/batteries/media/lint.cjs +339 -0
  65. package/batteries/media/lint.cjs.map +1 -0
  66. package/batteries/media/lint.d.ts +117 -0
  67. package/batteries/media/lint.mjs +331 -0
  68. package/batteries/media/lint.mjs.map +1 -0
  69. package/batteries/media/pipe.d.ts +66 -0
  70. package/batteries/media/plan.d.ts +133 -0
  71. package/batteries/media/registry.d.ts +92 -0
  72. package/batteries/media/runtime.d.ts +105 -0
  73. package/batteries/media/steps/doc.d.ts +33 -0
  74. package/batteries/media/steps/image_audio.d.ts +24 -0
  75. package/batteries/media/steps/ingest.d.ts +25 -0
  76. package/batteries/media/steps/pages.d.ts +18 -0
  77. package/batteries/media/steps/sheet.d.ts +36 -0
  78. package/batteries/media/steps/slides.d.ts +35 -0
  79. package/batteries/media/steps/text.d.ts +43 -0
  80. package/batteries/media/validate.d.ts +49 -0
  81. package/batteries/media/verbs.d.ts +126 -0
  82. package/batteries/media.cjs +3049 -0
  83. package/batteries/media.cjs.map +1 -0
  84. package/batteries/media.mjs +3009 -0
  85. package/batteries/media.mjs.map +1 -0
  86. package/batteries/tools/_shared/index.d.ts +142 -0
  87. package/batteries/tools/_shared.cjs +173 -0
  88. package/batteries/tools/_shared.cjs.map +1 -0
  89. package/batteries/tools/_shared.mjs +164 -0
  90. package/batteries/tools/_shared.mjs.map +1 -0
  91. package/batteries/tools/index.d.ts +2 -0
  92. package/batteries/tools/scrapper/exceptions.d.ts +21 -0
  93. package/batteries/tools/scrapper/index.d.ts +172 -0
  94. package/batteries/tools/scrapper/shared.d.ts +146 -0
  95. package/batteries/tools/scrapper.cjs +8 -0
  96. package/batteries/tools/scrapper.mjs +2 -0
  97. package/batteries/tools/searxng/index.d.ts +54 -20
  98. package/batteries/tools/searxng.cjs +2 -1
  99. package/batteries/tools/searxng.mjs +2 -2
  100. package/batteries/tools/web_retrieval/index.d.ts +186 -0
  101. package/batteries/tools/web_retrieval.cjs +206 -0
  102. package/batteries/tools/web_retrieval.cjs.map +1 -0
  103. package/batteries/tools/web_retrieval.mjs +201 -0
  104. package/batteries/tools/web_retrieval.mjs.map +1 -0
  105. package/batteries/tools.cjs +13 -1
  106. package/batteries/tools.mjs +4 -2
  107. package/batteries.cjs +13 -1
  108. package/batteries.mjs +4 -2
  109. package/common.d.ts +1 -1
  110. package/eslint.cjs +1 -1
  111. package/eslint.mjs +1 -1
  112. package/exceptions-C7FSHEnV.mjs +87 -0
  113. package/exceptions-C7FSHEnV.mjs.map +1 -0
  114. package/exceptions-CQi_lNs1.js +152 -0
  115. package/exceptions-CQi_lNs1.js.map +1 -0
  116. package/index.cjs +2 -2
  117. package/index.mjs +2 -2
  118. package/mcp/adk-docs-corpus.json +1 -1
  119. package/package.json +301 -178
  120. package/scrapper-BOLWYGbD.js +463 -0
  121. package/scrapper-BOLWYGbD.js.map +1 -0
  122. package/scrapper-hDKlNuCT.mjs +433 -0
  123. package/scrapper-hDKlNuCT.mjs.map +1 -0
  124. package/{searxng-Bkrwhwhw.js → searxng-CJtEpa8p.js} +82 -85
  125. package/searxng-CJtEpa8p.js.map +1 -0
  126. package/{searxng-CyA-nEu5.mjs → searxng-riarj_0u.mjs} +76 -85
  127. package/searxng-riarj_0u.mjs.map +1 -0
  128. package/skills/adk-assembly/SKILL.md +2 -2
  129. package/validate-BFaUYHDN.js +1298 -0
  130. package/validate-BFaUYHDN.js.map +1 -0
  131. package/validate-DSZ3wicB.mjs +1215 -0
  132. package/validate-DSZ3wicB.mjs.map +1 -0
  133. package/searxng-Bkrwhwhw.js.map +0 -1
  134. package/searxng-CyA-nEu5.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,84 @@ All notable changes to `@nhtio/adk` are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## 2026-06-10
9
+
10
+ ### Added
11
+
12
+ - **The Media Pipeline battery (`@nhtio/adk/batteries/media`)** — a knex-inspired local media
13
+ pipeline: one declarative `MediaPlan` with three front-ends (a chainable thenable builder, a
14
+ pipe-string DSL, and JSON ops) compiling identically, executed as an `@nhtio/middleware` onion
15
+ over in-memory bytes. Most stacks process media by shipping bytes to an external API or
16
+ flooding the context window; this is the third option — local processing, no external APIs by
17
+ default, your data stays in your infrastructure unless an engine you composed says otherwise.
18
+ Verbs cover documents (select/split/merge/reorder/redact/sanitize/normalize/update_text/diff/
19
+ apply_patch/convert/extract assets), unified text extraction (`extract text` routes PDF, DOCX,
20
+ XLSX, ODT/ODS/ODP, PPTX, plain text, and images through one verb, with OCR fallback for
21
+ scanned input), chunking and metadata, ten `sheet.*` mutations (ExcelJS), eight `slides.*`
22
+ mutations (JSZip OOXML surgery), fused `image.*` transforms (adjacent steps cost one
23
+ decode/encode), and `audio.transcribe` (decode → 16 kHz mono resample → ASR).
24
+ - **The pipe DSL** — the LLM-facing surface: `select pages=2-5 | redact match=/…/ | convert
25
+ to=pdf`. Named args only, separator-insensitive verb folding, 1-based indices, bare-number-is-
26
+ index/quoted-string-is-name targeting, quoted-JSON structured payloads, inline `@id` media
27
+ refs, and two-layer model-actionable errors (position-bearing syntax errors plus semantic
28
+ did-you-mean narrowed to the deployment's configured engines, every message ending in a
29
+ corrective exemplar). Round-trip is fixed-point and pipe/ops forms produce identical plans.
30
+ - **Engines as self-declaring capability providers** (`@nhtio/adk/batteries/media/contracts` +
31
+ one subpath per implementation): a `MediaEngine` is `{ id, converts?, mutates? }` — exactly
32
+ two capability shapes, because a media engine only ever changes the format or changes the
33
+ content. `ConvertCapability` declares uniform from×to blocks over MIME patterns and format
34
+ tokens (OCR is `image/*`→txt, transcription is `pcm`→txt/srt/vtt/json, audio decoding is
35
+ `audio/*`→pcm, PDF embedded-image extraction is `pdf`→images multi-output); a new capability
36
+ is a new edge in the data, never a new contract. Engines are supplied as a **flat ordered
37
+ array** (`engines: [resolver, …]`) resolved eagerly at construction — declarations drive
38
+ verb narrowing; heavy peers still lazy-load inside capability methods. Dispatch is one rule
39
+ everywhere: capability filter, then an optional `selection` middleware onion (stages may
40
+ exclude or reorder candidates, never add — the seam for content-dependent quality rules like
41
+ routing complex workbooks past a pure-JS converter to LibreOffice), then array order among
42
+ survivors. Convert computes shortest multi-hop paths (up to three hops) through the declared
43
+ format graph when no direct edge exists, with lossy/virtual tokens (txt, json, srt, `pcm`,
44
+ `images`) as endpoints, never intermediates. `ConvertRequest.options` is a typed,
45
+ consumer-augmentable `ConvertOptions` interface (declaration merging against the contracts
46
+ subpath). Bundled: `engines/jimp` (cross-env image mutate), `engines/sharp` (Node mutate
47
+ incl. webp/avif + `fromSharp` BYO adapter), `engines/tesseract_js` (cross-env OCR convert;
48
+ languages required), `engines/audio_decode` (cross-env audio→pcm, no ffmpeg),
49
+ `engines/transformers_asr` (cross-env Whisper pcm→text; model id required — no silent
50
+ multi-hundred-MB downloads), and `engines/soffice` (the LibreOffice convert matrix, which
51
+ now also covers ODS/legacy-xls→xlsx — sheet normalization is just a conversion edge, not a
52
+ separate engine). Binary-backed engines compose two further BYO contracts: `BinaryExecutor`
53
+ (bundled `engines/execa_executor`) and `ScratchWorkspace` (bundled `engines/fs_workspace`;
54
+ explicit root, no `os.tmpdir()` default) — process execution and filesystem access are
55
+ movable seams, not Node assumptions. The registry is exported (`buildEngineRegistry`) for
56
+ standalone dispatch.
57
+ - **A battery-scoped ESLint plugin for the media pipeline**
58
+ (`@nhtio/adk/batteries/media/lint`, namespace `adk-media`) — battery-specific contracts ship
59
+ with the battery, not the core `@nhtio/adk/eslint` plugin. Three rules:
60
+ `adk-media/prefer-engine-resolver` (static value imports of bundled engine subpaths — the
61
+ canonical supply form is the dynamic-import resolver; type-only imports pass),
62
+ `adk-media/no-shadowed-engine` (an engine whose statically-known capabilities are fully
63
+ covered by an earlier engine in the array is dead code under first-capable-wins dispatch),
64
+ and `adk-media/augment-contracts-module` (`ConvertOptions` declaration merging that targets
65
+ any module other than `batteries/media/contracts` silently never merges).
66
+ - **Forged agent tools** (`@nhtio/adk/batteries/media/forge`): `forgeMediaTools(mp, { surface })`
67
+ mints either the composite surface (one `media_query` tool taking `{ media_id, q | ops }`,
68
+ its description embedding the engine-narrowed grammar with toPipe-generated examples, plus
69
+ `list_media`) or the granular surface (one tool per available verb). Outputs persist via
70
+ `ctx.storeMediaBytes` and return first-party `Media`; processing and DSL failures render as
71
+ readable `Error (CODE): …` strings the model can repair from. An optional `gate?: ToolGateFn`
72
+ runs before every execution — the human-approval/RBAC seam built on `ctx.waitFor`.
73
+ - **Inline media id-markers in every LLM battery.** Rendered media (attachments and tool
74
+ results) is now preceded by a harness-authored `[media id: <id> | <filename>]` text block so
75
+ models can reference media by id in tool calls without a discovery round-trip. The marker is
76
+ structural reference data from the harness-controlled `Media.id` — no authority, fixed
77
+ phrasing, outside the untrusted envelope. OpenAI is the reference implementation (WebLLM
78
+ inherits); Ollama emits the same shape on its text channel.
79
+ - **Gate seam retrofit for SearXNG and Scrapper.** Both factory batteries now accept the same
80
+ optional `gate?: ToolGateFn`, run before the HTTP request — network side effects deserve the
81
+ approval seam too. Additive and backward-compatible.
82
+ - New optional peer dependencies (pulled only by the engine/parser that needs them): `moo`,
83
+ `pdf-lib`, `pdf-parse`, `mammoth`, `exceljs`, `jszip`, `jimp`, `sharp`, `audio-decode`,
84
+ `@huggingface/transformers`, `tesseract.js`, `execa`.
85
+
8
86
  ## 2026-06-09
9
87
 
10
88
  ### Fixed
@@ -71,13 +149,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
71
149
 
72
150
  ### Added
73
151
 
152
+ - **Scrapper web-extraction tool battery (`@nhtio/adk/batteries/tools/scrapper`).** Tools for any
153
+ [Scrapper](https://github.com/amerkurev/scrapper) instance — a headless-browser service that gives
154
+ an agent browser-grade page reading (JS-rendered pages a plain fetch can't see) as a **stateless**
155
+ HTTP call: fresh incognito context per request, no stored session/cookies/credentials. Two verbs,
156
+ each with an async factory (accepts a dynamic-import `artifact` resolver) and a sync variant:
157
+ `createScrapperArticleTool`/`…Sync` (`/api/article`) and `createScrapperLinksTool`/`…Sync`
158
+ (`/api/links`). Like the SearXNG battery these are factories (not constants) and must not be
159
+ bulk-registered via `Object.values(batteries)`.
160
+ - **Per-parameter disposition** — for every modeled knob the factory chooses: `fixed` (pinned;
161
+ sent always, removed from the model schema), `defaults` (model-overridable), or open
162
+ (model-settable). `url` is always required; `fixedQuery` is a raw kebab passthrough for
163
+ un-modeled params, keeping the battery generic across instances/versions.
164
+ - **Two distinct header channels** — `config.headers` (static or sync/async resolver) authenticates
165
+ to the Scrapper *instance*; the `extra_http_headers` *param* (`'K:v;K2:v2'`) is what the scraper's
166
+ browser sends to the *target site*.
167
+ - Same SearXNG-style two-level output (`resultFormat` normalized/raw/either), `artifact` resolver,
168
+ and input/output middleware pipelines (`shortCircuit`, fresh runner per call). Errors degrade to
169
+ `Error:` strings (parses Scrapper's `{detail:[{msg}]}`; missing `url` → HTTP 422); bad config →
170
+ `E_INVALID_SCRAPPER_CONFIG`. Documented as a featured-battery page with TSDoc `@warning`s for the
171
+ `scroll_down`-needs-`sleep` and instance-relative-URI gotchas. Cross-env unit spec (stubbed
172
+ `fetch`, disposition, resolver, all-three-artifact round-trips) + env-gated live integration spec
173
+ (`TEST_SCRAPPER_URL` / `TEST_SCRAPPER_HEADERS`).
174
+
175
+ - **Web-retrieval RAG glue (`@nhtio/adk/batteries/tools/web_retrieval`).** The shared seam from
176
+ search/scrape results to turn `Retrievable`s, used by both the Scrapper and SearXNG batteries.
177
+ Pure converters — `searxngResultsToRetrievables`, `scrapperArticleToRetrievable`,
178
+ `scrapperLinksToRetrievables` — return plain `RawRetrievable[]` (zero core-class instantiation;
179
+ core referenced as `import type` only). `storeRetrievables(ctx, raws, { retrievable })` constructs
180
+ and stores records via a **resolver-injected** `Retrievable` constructor (ctor / sync / async /
181
+ dynamic-import), so the module never value-imports core. Long page text becomes a reader-backed
182
+ `SpooledArtifact` via a caller `spool` hook (the converter recommends an open
183
+ `ArtifactConstructorResolver` for the content — markdown/json/text — so a consumer's own subclass
184
+ works unchanged; no chunker). Web content defaults to `trustTier: 'third-party-public'` (a
185
+ constant, not URL inference — CONTRIBUTING DD#12).
186
+
187
+ - **Shared tool-battery helpers (`@nhtio/adk/batteries/tools/_shared`).** Internal building blocks
188
+ for the configured-HTTP tool batteries: `resolveArtifact`/`resolveArtifactSync` (resolver → sync
189
+ `() => Ctor`), the onion middleware-pipeline runners (fresh runner per call, short-circuit +
190
+ non-terminal detection), header resolution, and the `ArtifactResolver`/`SyncArtifactResolver`
191
+ types. SearXNG and Scrapper both build on it instead of carrying copies.
192
+
74
193
  - **SearXNG search tool battery (`@nhtio/adk/batteries/tools/searxng`).** A web-search tool for any
75
- [SearXNG](https://docs.searxng.org/dev/search_api.html) instance, exposed via a **factory** —
76
- `createSearxngSearchTool(config)` rather than a ready-made constant. It is the first
77
- factory-style tool battery: a search tool has to know *which* instance to query and is usually
78
- behind custom authentication, so it needs per-deployment config that cannot be baked in at module
79
- load. Because it exports a factory (not a `Tool`), it must not be bulk-registered via
80
- `Object.values(batteries)` — call the factory first, then register the returned tool.
194
+ [SearXNG](https://docs.searxng.org/dev/search_api.html) instance, exposed via **factories** —
195
+ async `createSearxngSearchTool(config)` and sync `createSearxngSearchToolSync(config)` rather
196
+ than a ready-made constant. It is the first factory-style tool battery: a search tool has to know
197
+ *which* instance to query and is usually behind custom authentication, so it needs per-deployment
198
+ config that cannot be baked in at module load. Because it exports factories (not a `Tool`), they
199
+ must not be bulk-registered via `Object.values(batteries)` — call a factory first, then register
200
+ the returned tool.
81
201
  - **Custom-header auth** — `config.headers` accepts a static `Record<string,string>` or a
82
202
  sync/async resolver (`() => headers | Promise<headers>`); the resolver runs on every search, so
83
203
  refreshable bearer tokens work. Caller headers override the default `Accept`/`User-Agent`.
@@ -92,9 +212,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
92
212
  hit); output stages filter/re-rank `ctx.results`, mutate `ctx.raw`, or set `ctx.output` verbatim
93
213
  (e.g. rendered markdown). A `ctx.stash` Map carries across both; a fresh runner is minted per
94
214
  invocation (middleware runners are single-use).
95
- - **Configurable spool artifact** — `config.artifactConstructor` (default `() => SpooledJsonArtifact`)
96
- is passed straight through to the `Tool`; set `() => SpooledMarkdownArtifact` or
97
- `() => SpooledArtifact` to match a custom `outputPipeline` render.
215
+ - **Configurable spool artifact (resolver)** — `config.artifact` (default `() => SpooledJsonArtifact`)
216
+ is an open `ArtifactConstructorResolver`: a ctor, a sync resolver, or via the async factory —
217
+ an async/dynamic-import resolver (`() => import('@nhtio/adk/spooled_artifact').then(m => m.SpooledMarkdownArtifact)`),
218
+ so a consumer's own `SpooledArtifact` subclass works with no battery change. The async factory
219
+ resolves it before building the `Tool` (whose `artifactConstructor` must be sync); the sync
220
+ factory accepts only the sync subset.
98
221
  - **Graceful failures** — a disabled-JSON instance (SearXNG disables JSON by default → HTTP 403),
99
222
  network errors, timeouts, and thrown pipeline stages all return `Error:` strings the model can
100
223
  react to; only malformed args throw (`E_INVALID_TOOL_ARGS`). Invalid config throws the
@@ -84,6 +84,13 @@ var renderSyntheticMediaDescription = (media, byteLen) => `[media: ${media.filen
84
84
  * the message's `images[]` array (returned via `image`); every other modality is unsupported and
85
85
  * routes through `unsupportedMediaPolicy` to a text envelope (returned via `text`) or throws.
86
86
  */
87
+ /**
88
+ * The inline media id-marker (cross-battery convention; see the OpenAI battery's
89
+ * `renderMediaIdMarker`): structural reference text authored by the harness from the
90
+ * harness-controlled `Media.id`, rendered alongside each media so the model can reference it
91
+ * by id in tool calls. Carries no authority; renders outside the untrusted envelope.
92
+ */
93
+ var renderMediaIdMarker = (media) => `[media id: ${media.id} | ${media.filename}]`;
87
94
  var renderMediaForOllama = async (input) => {
88
95
  const { media, toolName, nonce, unsupportedMediaPolicy, warn } = input;
89
96
  const modality = modalityHazardToAttr(media.modalityHazard);
@@ -159,6 +166,7 @@ var renderOllamaTimelineMessage = async (input) => {
159
166
  renderUntrustedContent: require_helpers.renderUntrustedContent,
160
167
  warn
161
168
  });
169
+ extraTexts.push(renderMediaIdMarker(media));
162
170
  if (rendered.image !== void 0) images.push(rendered.image);
163
171
  if (rendered.text !== void 0) extraTexts.push(rendered.text);
164
172
  }
@@ -224,6 +232,7 @@ var renderOllamaToolCallResult = async (input) => {
224
232
  renderUntrustedContent: input.renderUntrustedContent,
225
233
  warn
226
234
  });
235
+ parts.push(renderMediaIdMarker(media));
227
236
  if (rendered.text !== void 0) parts.push(rendered.text);
228
237
  else {
229
238
  const byteLen = await media.byteLength();
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.cjs","names":[],"sources":["../../../../src/batteries/llm/ollama/helpers.ts"],"sourcesContent":["/**\n * Swappable translation helpers for rendering ADK state into native Ollama `/api/chat` requests.\n *\n * @module @nhtio/adk/batteries/llm/ollama/helpers\n *\n * @remarks\n * The wire-shape-agnostic helpers (`renderUntrustedContent`, `renderMemories`,\n * `renderChatCompletionsSystemPrompt`, `toolsToChatCompletionsTools`, …) are shared with the OpenAI\n * battery via the internal `../chat_common/helpers` submodule and re-exported here under their\n * original names. Only the Ollama-WIRE-SPECIFIC helpers are defined here:\n * `renderOllamaTimelineMessage` (flat `content` + base64 `images[]` + `thinking`),\n * `renderOllamaToolCallResult` (string-only result content), `buildOllamaHistory` (synthetic\n * `assistant.tool_calls` with object-form `arguments` + `tool`-role messages labelled by\n * `tool_name`), and `ollamaToolsFromTools` (alias of the shared tool-definition renderer — native\n * `/api/chat` uses the same function-tool wire shape).\n *\n * Native `/api/chat` supports only base64 `images[]`; every non-image modality routes through the\n * `unsupportedMediaPolicy` fallback (stash text / synthetic description) or throws.\n */\n\nimport { Media } from '@nhtio/adk/common'\nimport { isInstanceOf } from '@nhtio/adk/guards'\nimport { E_OLLAMA_UNSUPPORTED_MEDIA_MODALITY } from './exceptions'\nimport {\n escapeXmlAttribute,\n memoryToAttrs,\n retrievableToAttrs,\n renderTrustedContent,\n renderUntrustedContent,\n toolsToChatCompletionsTools,\n} from '../chat_common/helpers'\nimport type { ChatHelpersCommon } from '../chat_common/types'\nimport type {\n OllamaMessage,\n OllamaTool,\n OllamaHelpers,\n MemoryAttrs,\n RetrievableAttrs,\n ChatCompletionsBucketOrder,\n UnsupportedMediaPolicy,\n} from './types'\nimport type {\n Tool,\n ArtifactTool,\n ToolRegistry,\n Tokenizable,\n Memory,\n Message,\n Thought,\n ToolCall,\n Retrievable,\n SpooledArtifact,\n MediaModalityHazard,\n MediaStashEntry,\n} from '@nhtio/adk/common'\n\n// ─── Re-exported wire-shape-agnostic helpers (shared submodule) ───────────────\nexport {\n descriptionToChatCompletionsJsonSchema,\n defaultDescriptionToChatCompletionsJsonSchema,\n renderUntrustedContent,\n defaultRenderUntrustedContent,\n renderTrustedContent,\n defaultRenderTrustedContent,\n renderStandingInstructions,\n defaultRenderStandingInstructions,\n renderMemories,\n defaultRenderMemories,\n renderRetrievableSafetyDirective,\n defaultRenderRetrievableSafetyDirective,\n renderFirstPartyRetrievables,\n defaultRenderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables,\n defaultRenderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables,\n defaultRenderThirdPartyPrivateRetrievables,\n renderRetrievables,\n defaultRenderRetrievables,\n renderThought,\n defaultRenderThought,\n filterThoughts,\n defaultFilterThoughts,\n toolsToChatCompletionsTools,\n defaultToolsToChatCompletionsTools,\n renderChatCompletionsSystemPrompt,\n defaultRenderChatCompletionsSystemPrompt,\n} from '../chat_common/helpers'\n\n// ─── ollamaToolsFromTools (alias — native tool wire == Chat Completions wire) ──\n\n/**\n * Convert ADK tools to the native Ollama `tools[]` wire. Native `/api/chat` uses the identical\n * `{ type: 'function', function: { name, description, parameters } }` shape as Chat Completions, so\n * this is an alias of the shared renderer.\n */\nexport const ollamaToolsFromTools = (\n tools: ReadonlyArray<Tool | ArtifactTool>,\n deps: Parameters<typeof toolsToChatCompletionsTools>[1]\n): OllamaTool[] => toolsToChatCompletionsTools(tools, deps)\n/** Default implementation of {@link OllamaHelpers}-style tool translation; alias of {@link ollamaToolsFromTools}. */\nexport const defaultOllamaToolsFromTools = ollamaToolsFromTools\n\n// ─── Media rendering (Ollama native — images only) ────────────────────────────\n\nconst DEFAULT_STASH_FALLBACK_KEYS: ReadonlyArray<string> = [\n 'text:transcript',\n 'text:caption',\n 'text:description',\n]\n\nconst modalityHazardToAttr = (h: MediaModalityHazard): 'inert' | 'extractable' | 'opaque' => {\n if (h === 'inert') return 'inert'\n if (h === 'extractable-instructions') return 'extractable'\n return 'opaque'\n}\n\nconst formatBytesHumanReadable = (bytes: number | undefined): string => {\n if (bytes === undefined || !Number.isFinite(bytes)) return 'unknown size'\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`\n}\n\nconst isMediaTextStashEntry = (e: unknown): e is MediaStashEntry => {\n if (!e || typeof e !== 'object') return false\n const r = e as Record<string, unknown>\n return typeof r.value === 'string' && typeof r.trustTier === 'string'\n}\n\nconst resolveFallbackStash = (\n media: Media,\n keys: ReadonlyArray<string>\n): { text: string; entryTier: MediaStashEntry['trustTier'] } | undefined => {\n for (const key of keys) {\n const entry = media.stash.get(key)\n if (isMediaTextStashEntry(entry)) {\n return { text: entry.value as string, entryTier: entry.trustTier }\n }\n }\n return undefined\n}\n\nconst renderTextInEnvelope = (\n text: string,\n args: {\n trustTier: MediaStashEntry['trustTier']\n modality: 'inert' | 'extractable' | 'opaque'\n nonce: string\n toolName: string | undefined\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n }\n): string => {\n if (args.trustTier === 'first-party') {\n return args.renderTrustedContent(text, {\n nonce: args.nonce,\n kind: 'media-fallback',\n tool: args.toolName,\n modality: args.modality,\n })\n }\n return args.renderUntrustedContent(text, {\n nonce: args.nonce,\n kind: 'media-fallback',\n tool: args.toolName,\n modality: args.modality,\n })\n}\n\nconst renderSyntheticMediaDescription = (media: Media, byteLen: number | undefined): string =>\n `[media: ${media.filename}, ${media.mimeType}, ${formatBytesHumanReadable(byteLen)}]`\n\n/**\n * Render a single {@link Media} for the native Ollama wire. Images become a base64 entry pushed to\n * the message's `images[]` array (returned via `image`); every other modality is unsupported and\n * routes through `unsupportedMediaPolicy` to a text envelope (returned via `text`) or throws.\n */\nconst renderMediaForOllama = async (input: {\n media: Media\n toolName: string | undefined\n nonce: string\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n warn?: (msg: string) => void\n}): Promise<{ image?: string; text?: string }> => {\n const { media, toolName, nonce, unsupportedMediaPolicy, warn } = input\n const modality = modalityHazardToAttr(media.modalityHazard)\n\n if (media.kind === 'image') {\n const b64 = await media.asBase64()\n return { image: b64 }\n }\n\n // Non-image modality — native /api/chat has no representation for it.\n const fallbackText = async (\n keys: ReadonlyArray<string>,\n allowSyntheticFallthrough: boolean\n ): Promise<{ text: string }> => {\n const fallback = resolveFallbackStash(media, keys)\n if (fallback) {\n return {\n text: renderTextInEnvelope(fallback.text, {\n trustTier: fallback.entryTier,\n modality,\n nonce,\n toolName,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n }),\n }\n }\n if (!allowSyntheticFallthrough) {\n warn?.(\n `unsupportedMediaPolicy='fallback-stash' for ${media.filename}: no matching stash entry — falling through to synthetic description.`\n )\n }\n const byteLen = await media.byteLength()\n return {\n text: renderTextInEnvelope(renderSyntheticMediaDescription(media, byteLen), {\n trustTier: media.trustTier,\n modality,\n nonce,\n toolName,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n }),\n }\n }\n\n if (unsupportedMediaPolicy === 'throw') {\n throw new E_OLLAMA_UNSUPPORTED_MEDIA_MODALITY([media.kind, media.mimeType, media.filename])\n }\n if (\n unsupportedMediaPolicy === 'fallback-stash' ||\n (typeof unsupportedMediaPolicy === 'object' && unsupportedMediaPolicy.mode === 'fallback-stash')\n ) {\n const keys =\n typeof unsupportedMediaPolicy === 'object'\n ? unsupportedMediaPolicy.stashKeys\n : DEFAULT_STASH_FALLBACK_KEYS\n return fallbackText(keys, false)\n }\n return fallbackText([], true)\n}\n\n// ─── renderOllamaTimelineMessage ──────────────────────────────────────────────\n\n/**\n * Renders a single timeline {@link @nhtio/adk!Message} into a native Ollama message — flattening any\n * media into the base64 `images[]` array, surfacing reasoning as `thinking`, and wrapping textual\n * bodies in the appropriate trust envelope.\n */\nexport const renderOllamaTimelineMessage = async (input: {\n message: Message\n selfIdentity: string\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n warn?: (msg: string) => void\n}): Promise<OllamaMessage> => {\n const { message, selfIdentity, unsupportedMediaPolicy, warn } = input\n const identifier =\n message.identity?.identifier !== undefined && message.identity?.identifier !== null\n ? String(message.identity.identifier)\n : ''\n const representationRaw =\n message.identity?.representation !== undefined && message.identity?.representation !== null\n ? message.identity.representation.toString()\n : ''\n const representation = representationRaw.length > 0 ? representationRaw : identifier\n const text = message.content !== undefined ? message.content.toString() : ''\n const createdAtStr = message.createdAt.toISO?.() ?? ''\n const createdAtAttr = createdAtStr ? ` createdAt=\"${escapeXmlAttribute(createdAtStr)}\"` : ''\n const attachments = message.attachments\n\n // Build the text envelope (same identity logic as the OpenAI battery — wire-agnostic).\n let envelopeText: string\n let role: 'user' | 'assistant'\n if (message.role === 'user') {\n role = 'user'\n if (identifier.length === 0) {\n envelopeText = text\n } else {\n const fromAttr = escapeXmlAttribute(representation)\n envelopeText = `<message_${message.id} from=\"${fromAttr}\" role=\"user\"${createdAtAttr}>\\n${text}\\n</message_${message.id}>`\n }\n } else {\n role = 'assistant'\n if (identifier.length === 0 || identifier === selfIdentity) {\n envelopeText = text\n } else {\n const fromAttr = escapeXmlAttribute(representation)\n envelopeText = `<peer_agent_output_${message.id} from=\"${fromAttr}\"${createdAtAttr}>\\n${text}\\n</peer_agent_output_${message.id}>`\n }\n }\n\n const images: string[] = []\n const extraTexts: string[] = []\n for (const media of attachments) {\n const rendered = await renderMediaForOllama({\n media,\n toolName: undefined,\n nonce: message.id,\n unsupportedMediaPolicy,\n renderTrustedContent,\n renderUntrustedContent,\n warn,\n })\n if (rendered.image !== undefined) images.push(rendered.image)\n if (rendered.text !== undefined) extraTexts.push(rendered.text)\n }\n\n // Non-image fallbacks (text envelopes) are appended to the message content; images ride in the\n // separate native `images[]` field.\n const contentParts: string[] = []\n if (envelopeText.length > 0) contentParts.push(envelopeText)\n for (const t of extraTexts) contentParts.push(t)\n const out: OllamaMessage = { role, content: contentParts.join('\\n') }\n if (images.length > 0) out.images = images\n return out\n}\n/** Default timeline-message renderer; alias of {@link renderOllamaTimelineMessage}. */\nexport const defaultRenderOllamaTimelineMessage = renderOllamaTimelineMessage\n\n// ─── renderOllamaToolCallResult ───────────────────────────────────────────────\n\nconst looksLikeSpooledArtifact = (value: unknown): value is SpooledArtifact => {\n if (!value || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n return (\n typeof v.asString === 'function' &&\n typeof v.byteLength === 'function' &&\n typeof v.lineCount === 'function' &&\n typeof v.estimateTokens === 'function'\n )\n}\n\nconst renderArtifactHandleBody = (\n toolCall: ToolCall,\n artifact: SpooledArtifact,\n byteLength: number,\n lineCount: number\n): string => {\n const ctor = (\n artifact as unknown as {\n constructor: { toolMethods?: ReadonlyArray<{ name: string; description?: string }> }\n }\n ).constructor\n const methods = ctor?.toolMethods ?? []\n const lines: string[] = []\n lines.push(`This tool returned a large artifact that was not inlined to preserve context budget.`)\n lines.push(``)\n lines.push(`Artifact metadata:`)\n lines.push(`- callId: ${toolCall.id}`)\n lines.push(`- kind: ${ctor?.constructor?.name ?? 'SpooledArtifact'}`)\n lines.push(`- byteLength: ${byteLength}`)\n lines.push(`- lineCount: ${lineCount}`)\n lines.push(``)\n lines.push(`To read this artifact in this turn, call one of the following tools with`)\n lines.push(`callId=${toolCall.id}:`)\n for (const m of methods) {\n if (m.description) {\n lines.push(`- ${m.name} — ${m.description}`)\n } else {\n lines.push(`- ${m.name}`)\n }\n }\n lines.push(``)\n lines.push(\n `The artifact persists in this turn's context — multiple queries against the same callId are allowed and efficient. Do not assume the body has been inlined anywhere else.`\n )\n return lines.join('\\n')\n}\n\n/**\n * Render a tool-call result to native Ollama tool-message content (always a string). Media results\n * are routed through the internal media renderer: images cannot ride on a tool-role message's\n * `content`, so an image result is replaced with a short text marker (the image bytes are not\n * re-sent on a tool message); non-image media use the same fallback-text path as elsewhere.\n */\nexport const renderOllamaToolCallResult = async (input: {\n toolCall: ToolCall\n results: Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[]\n tool: Tool | ArtifactTool | undefined\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n warn?: (msg: string) => void\n}): Promise<string> => {\n const { toolCall, results, tool, warn, unsupportedMediaPolicy } = input\n const isTrusted =\n tool !== null && tool !== undefined && (tool as { trusted?: boolean }).trusted === true\n\n if (tool === undefined) {\n warn?.(\n `Tool \"${toolCall.tool}\" is not present in the bound tool registry at render time; defaulting to untrusted envelope.`\n )\n }\n\n // Media silo — bypasses Tool.trusted (Trust-Is-Content rule).\n const isMediaResult = Media.isMedia(results)\n const isMediaArrayResult =\n Array.isArray(results) && results.length > 0 && results.every((r) => Media.isMedia(r))\n if (isMediaResult || isMediaArrayResult) {\n const mediaList = isMediaResult ? [results as Media] : (results as Media[])\n const parts: string[] = []\n for (const media of mediaList) {\n const rendered = await renderMediaForOllama({\n media,\n toolName: toolCall.tool,\n nonce: toolCall.checksum,\n unsupportedMediaPolicy,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n warn,\n })\n if (rendered.text !== undefined) {\n parts.push(rendered.text)\n } else {\n // An image tool-result cannot be carried on a tool-role message's string content; emit a\n // text marker in its place so the model knows an image was produced.\n const byteLen = await media.byteLength()\n parts.push(\n input.renderUntrustedContent(renderSyntheticMediaDescription(media, byteLen), {\n nonce: toolCall.checksum,\n kind: 'tool-result-image',\n tool: toolCall.tool,\n modality: modalityHazardToAttr(media.modalityHazard),\n })\n )\n }\n }\n return parts.join('\\n')\n }\n\n // SpooledArtifact[] silo.\n if (Array.isArray(results)) {\n const parts: string[] = []\n for (const a of results) {\n parts.push(await (a as SpooledArtifact).asString())\n }\n const joined = parts.join('\\n\\n')\n return isTrusted\n ? input.renderTrustedContent(joined, {\n nonce: toolCall.checksum,\n kind: 'trusted-tool-result',\n tool: toolCall.tool,\n })\n : input.renderUntrustedContent(joined, {\n nonce: toolCall.checksum,\n kind: 'tool-result',\n tool: toolCall.tool,\n })\n }\n\n const isSpooled = looksLikeSpooledArtifact(results)\n\n // Handle-pattern branch: spooled + inline=false → always untrusted (queryable-data).\n if (isSpooled && toolCall.inline === false) {\n const artifact = results as SpooledArtifact\n let byteLength = 0\n let lineCount = 0\n try {\n byteLength = await artifact.byteLength()\n } catch {\n byteLength = 0\n }\n try {\n lineCount = await artifact.lineCount()\n } catch {\n lineCount = 0\n }\n const body = renderArtifactHandleBody(toolCall, artifact, byteLength, lineCount)\n return input.renderUntrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'artifact-handle',\n tool: toolCall.tool,\n })\n }\n\n if (!isSpooled && toolCall.inline === false) {\n warn?.(\n `Tool call ${toolCall.id} has inline=false but results is a Tokenizable (not a SpooledArtifact); rendering inline anyway.`\n )\n }\n\n const body = isSpooled\n ? await (results as SpooledArtifact).asString()\n : (results as Tokenizable).toString()\n\n return isTrusted\n ? input.renderTrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'trusted-tool-result',\n tool: toolCall.tool,\n })\n : input.renderUntrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'tool-result',\n tool: toolCall.tool,\n })\n}\n/** Default tool-call-result renderer; alias of {@link renderOllamaToolCallResult}. */\nexport const defaultRenderOllamaToolCallResult = renderOllamaToolCallResult\n\n// ─── buildOllamaHistory ───────────────────────────────────────────────────────\n\ntype TimelineItem =\n | { kind: 'message'; createdAt: number; value: Message }\n | { kind: 'thought'; createdAt: number; value: Thought }\n | { kind: 'toolCall'; createdAt: number; value: ToolCall }\n\n/**\n * Assembles the complete native Ollama message history for a dispatch — system prompt and content\n * buckets, the interleaved timeline of messages/thoughts/tool calls, and the collected opaque\n * reasoning payloads — by delegating to the injected sub-renderers.\n */\nexport const buildOllamaHistory = async (input: {\n systemPrompt: Tokenizable\n standingInstructions: Iterable<Tokenizable>\n memories: Iterable<Memory>\n retrievables: Iterable<Retrievable>\n messages: Iterable<Message>\n thoughts: Iterable<Thought>\n toolCalls: Iterable<ToolCall>\n tools: ToolRegistry\n renderedToolCallResults: Map<string, string>\n bucketOrder: ChatCompletionsBucketOrder\n selfIdentity: string\n thoughtSurfacing: 'all-self' | 'latest-self' | 'all'\n replayCompatibility: ReadonlyArray<string>\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n renderOllamaToolCallResult: OllamaHelpers['renderOllamaToolCallResult']\n renderChatCompletionsSystemPrompt: ChatHelpersCommon['renderChatCompletionsSystemPrompt']\n renderStandingInstructions: ChatHelpersCommon['renderStandingInstructions']\n renderMemories: ChatHelpersCommon['renderMemories']\n renderRetrievables: ChatHelpersCommon['renderRetrievables']\n renderRetrievableSafetyDirective: ChatHelpersCommon['renderRetrievableSafetyDirective']\n renderFirstPartyRetrievables: ChatHelpersCommon['renderFirstPartyRetrievables']\n renderThirdPartyPublicRetrievables: ChatHelpersCommon['renderThirdPartyPublicRetrievables']\n renderThirdPartyPrivateRetrievables: ChatHelpersCommon['renderThirdPartyPrivateRetrievables']\n renderOllamaTimelineMessage: OllamaHelpers['renderOllamaTimelineMessage']\n renderThought: ChatHelpersCommon['renderThought']\n filterThoughts: ChatHelpersCommon['filterThoughts']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n warn?: (msg: string) => void\n}): Promise<{\n messages: OllamaMessage[]\n reasoningPayloads: Array<{ id: string; replayCompatibility: string; payload: unknown }>\n}> => {\n const out: OllamaMessage[] = []\n const reasoningPayloads: Array<{ id: string; replayCompatibility: string; payload: unknown }> = []\n\n const buckets = input.bucketOrder\n const timelineIdx = buckets.indexOf('timeline')\n\n const leadingSystem = await input.renderChatCompletionsSystemPrompt({\n systemPrompt: input.systemPrompt,\n standingInstructions: input.standingInstructions,\n memories: input.memories,\n retrievables: input.retrievables,\n bucketOrder: buckets,\n renderStandingInstructions: input.renderStandingInstructions,\n renderMemories: input.renderMemories,\n renderRetrievables: input.renderRetrievables,\n renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n renderUntrustedContent: input.renderUntrustedContent,\n })\n if (leadingSystem.length > 0) {\n out.push({ role: 'system', content: leadingSystem })\n }\n\n const includesTimeline = timelineIdx !== -1\n if (includesTimeline) {\n const survivingThoughts = input.filterThoughts(\n input.thoughts,\n input.thoughtSurfacing,\n input.selfIdentity,\n input.replayCompatibility\n )\n\n const items: TimelineItem[] = []\n for (const m of input.messages) {\n items.push({ kind: 'message', createdAt: m.createdAt.toMillis(), value: m })\n }\n for (const t of survivingThoughts) {\n items.push({ kind: 'thought', createdAt: t.createdAt.toMillis(), value: t })\n }\n for (const tc of input.toolCalls) {\n items.push({ kind: 'toolCall', createdAt: tc.createdAt.toMillis(), value: tc })\n }\n items.sort((a, b) => a.createdAt - b.createdAt)\n\n const replaySet = new Set<string>([...input.replayCompatibility])\n\n for (const item of items) {\n if (item.kind === 'message') {\n out.push(\n await input.renderOllamaTimelineMessage({\n message: item.value,\n selfIdentity: input.selfIdentity,\n unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n warn: input.warn,\n })\n )\n } else if (item.kind === 'thought') {\n const t = item.value\n const identifier = String(t.identity?.identifier ?? '')\n const isSelf = identifier === input.selfIdentity\n const hasPayload = t.payload !== undefined\n const compatTag = t.replayCompatibility\n\n if (hasPayload && compatTag && replaySet.has(compatTag)) {\n reasoningPayloads.push({ id: t.id, replayCompatibility: compatTag, payload: t.payload })\n const envelope = input.renderThought(\n t.content.toString(),\n {\n nonce: t.id,\n kind: 'opaque-reasoning',\n from: identifier,\n createdAt: t.createdAt?.toISO?.() ?? undefined,\n replayCompatibility: compatTag,\n },\n t.payload\n )\n out.push({ role: 'assistant', content: envelope })\n } else if (!hasPayload) {\n const envelope = input.renderThought(t.content.toString(), {\n nonce: t.id,\n kind: isSelf ? 'self-reasoning' : 'peer-reasoning',\n from: identifier,\n createdAt: t.createdAt?.toISO?.() ?? undefined,\n })\n out.push({ role: 'assistant', content: envelope })\n }\n // else: opaque, non-matching → elided.\n } else {\n // tool call: synthetic assistant message carrying tool_calls[] (object-form arguments),\n // followed by a tool-role message labelled by `tool_name` (NOT tool_call_id).\n const tc = item.value\n const args =\n tc.args !== null && typeof tc.args === 'object' && !Array.isArray(tc.args)\n ? (tc.args as Record<string, unknown>)\n : {}\n out.push({\n role: 'assistant',\n content: '',\n tool_calls: [{ function: { name: tc.tool, arguments: args } }],\n })\n\n let rendered = input.renderedToolCallResults.get(tc.id)\n if (rendered === undefined) {\n const tool = input.tools.get?.(tc.tool)\n rendered = await input.renderOllamaToolCallResult({\n toolCall: tc,\n results: tc.results as\n | Tokenizable\n | SpooledArtifact\n | SpooledArtifact[]\n | Media\n | Media[],\n tool: tool as Tool | ArtifactTool | undefined,\n renderUntrustedContent: input.renderUntrustedContent,\n renderTrustedContent: input.renderTrustedContent,\n unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n warn: input.warn,\n })\n }\n out.push({ role: 'tool', content: rendered, tool_name: tc.tool })\n }\n }\n }\n\n if (includesTimeline) {\n const trailingParts: string[] = []\n for (let i = timelineIdx + 1; i < buckets.length; i++) {\n const label = buckets[i]!\n if (label === 'standingInstructions') {\n const block = input.renderStandingInstructions(input.standingInstructions)\n if (block.length > 0) trailingParts.push(block)\n } else if (label === 'memories') {\n const wrapped: Array<{ memory: Memory; attrs: MemoryAttrs }> = []\n for (const m of input.memories) {\n wrapped.push(memoryToAttrs(m))\n }\n const block = input.renderMemories(wrapped)\n if (block.length > 0) trailingParts.push(block)\n } else if (label === 'retrievables') {\n const wrapped: Array<{ retrievable: Retrievable; attrs: RetrievableAttrs }> = []\n for (const r of input.retrievables) {\n wrapped.push(retrievableToAttrs(r))\n }\n const block = await input.renderRetrievables(wrapped, {\n renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n renderUntrustedContent: input.renderUntrustedContent,\n })\n if (block.length > 0) trailingParts.push(block)\n }\n }\n if (trailingParts.length > 0) {\n out.push({ role: 'system', content: trailingParts.join('\\n\\n') })\n }\n }\n\n return { messages: out, reasoningPayloads }\n}\n/** Default native-history assembler; alias of {@link buildOllamaHistory}. */\nexport const defaultBuildOllamaHistory = buildOllamaHistory\n\n// suppress unused\nvoid isInstanceOf\n"],"mappings":"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"}
1
+ {"version":3,"file":"helpers.cjs","names":[],"sources":["../../../../src/batteries/llm/ollama/helpers.ts"],"sourcesContent":["/**\n * Swappable translation helpers for rendering ADK state into native Ollama `/api/chat` requests.\n *\n * @module @nhtio/adk/batteries/llm/ollama/helpers\n *\n * @remarks\n * The wire-shape-agnostic helpers (`renderUntrustedContent`, `renderMemories`,\n * `renderChatCompletionsSystemPrompt`, `toolsToChatCompletionsTools`, …) are shared with the OpenAI\n * battery via the internal `../chat_common/helpers` submodule and re-exported here under their\n * original names. Only the Ollama-WIRE-SPECIFIC helpers are defined here:\n * `renderOllamaTimelineMessage` (flat `content` + base64 `images[]` + `thinking`),\n * `renderOllamaToolCallResult` (string-only result content), `buildOllamaHistory` (synthetic\n * `assistant.tool_calls` with object-form `arguments` + `tool`-role messages labelled by\n * `tool_name`), and `ollamaToolsFromTools` (alias of the shared tool-definition renderer — native\n * `/api/chat` uses the same function-tool wire shape).\n *\n * Native `/api/chat` supports only base64 `images[]`; every non-image modality routes through the\n * `unsupportedMediaPolicy` fallback (stash text / synthetic description) or throws.\n */\n\nimport { Media } from '@nhtio/adk/common'\nimport { isInstanceOf } from '@nhtio/adk/guards'\nimport { E_OLLAMA_UNSUPPORTED_MEDIA_MODALITY } from './exceptions'\nimport {\n escapeXmlAttribute,\n memoryToAttrs,\n retrievableToAttrs,\n renderTrustedContent,\n renderUntrustedContent,\n toolsToChatCompletionsTools,\n} from '../chat_common/helpers'\nimport type { ChatHelpersCommon } from '../chat_common/types'\nimport type {\n OllamaMessage,\n OllamaTool,\n OllamaHelpers,\n MemoryAttrs,\n RetrievableAttrs,\n ChatCompletionsBucketOrder,\n UnsupportedMediaPolicy,\n} from './types'\nimport type {\n Tool,\n ArtifactTool,\n ToolRegistry,\n Tokenizable,\n Memory,\n Message,\n Thought,\n ToolCall,\n Retrievable,\n SpooledArtifact,\n MediaModalityHazard,\n MediaStashEntry,\n} from '@nhtio/adk/common'\n\n// ─── Re-exported wire-shape-agnostic helpers (shared submodule) ───────────────\nexport {\n descriptionToChatCompletionsJsonSchema,\n defaultDescriptionToChatCompletionsJsonSchema,\n renderUntrustedContent,\n defaultRenderUntrustedContent,\n renderTrustedContent,\n defaultRenderTrustedContent,\n renderStandingInstructions,\n defaultRenderStandingInstructions,\n renderMemories,\n defaultRenderMemories,\n renderRetrievableSafetyDirective,\n defaultRenderRetrievableSafetyDirective,\n renderFirstPartyRetrievables,\n defaultRenderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables,\n defaultRenderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables,\n defaultRenderThirdPartyPrivateRetrievables,\n renderRetrievables,\n defaultRenderRetrievables,\n renderThought,\n defaultRenderThought,\n filterThoughts,\n defaultFilterThoughts,\n toolsToChatCompletionsTools,\n defaultToolsToChatCompletionsTools,\n renderChatCompletionsSystemPrompt,\n defaultRenderChatCompletionsSystemPrompt,\n} from '../chat_common/helpers'\n\n// ─── ollamaToolsFromTools (alias — native tool wire == Chat Completions wire) ──\n\n/**\n * Convert ADK tools to the native Ollama `tools[]` wire. Native `/api/chat` uses the identical\n * `{ type: 'function', function: { name, description, parameters } }` shape as Chat Completions, so\n * this is an alias of the shared renderer.\n */\nexport const ollamaToolsFromTools = (\n tools: ReadonlyArray<Tool | ArtifactTool>,\n deps: Parameters<typeof toolsToChatCompletionsTools>[1]\n): OllamaTool[] => toolsToChatCompletionsTools(tools, deps)\n/** Default implementation of {@link OllamaHelpers}-style tool translation; alias of {@link ollamaToolsFromTools}. */\nexport const defaultOllamaToolsFromTools = ollamaToolsFromTools\n\n// ─── Media rendering (Ollama native — images only) ────────────────────────────\n\nconst DEFAULT_STASH_FALLBACK_KEYS: ReadonlyArray<string> = [\n 'text:transcript',\n 'text:caption',\n 'text:description',\n]\n\nconst modalityHazardToAttr = (h: MediaModalityHazard): 'inert' | 'extractable' | 'opaque' => {\n if (h === 'inert') return 'inert'\n if (h === 'extractable-instructions') return 'extractable'\n return 'opaque'\n}\n\nconst formatBytesHumanReadable = (bytes: number | undefined): string => {\n if (bytes === undefined || !Number.isFinite(bytes)) return 'unknown size'\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`\n}\n\nconst isMediaTextStashEntry = (e: unknown): e is MediaStashEntry => {\n if (!e || typeof e !== 'object') return false\n const r = e as Record<string, unknown>\n return typeof r.value === 'string' && typeof r.trustTier === 'string'\n}\n\nconst resolveFallbackStash = (\n media: Media,\n keys: ReadonlyArray<string>\n): { text: string; entryTier: MediaStashEntry['trustTier'] } | undefined => {\n for (const key of keys) {\n const entry = media.stash.get(key)\n if (isMediaTextStashEntry(entry)) {\n return { text: entry.value as string, entryTier: entry.trustTier }\n }\n }\n return undefined\n}\n\nconst renderTextInEnvelope = (\n text: string,\n args: {\n trustTier: MediaStashEntry['trustTier']\n modality: 'inert' | 'extractable' | 'opaque'\n nonce: string\n toolName: string | undefined\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n }\n): string => {\n if (args.trustTier === 'first-party') {\n return args.renderTrustedContent(text, {\n nonce: args.nonce,\n kind: 'media-fallback',\n tool: args.toolName,\n modality: args.modality,\n })\n }\n return args.renderUntrustedContent(text, {\n nonce: args.nonce,\n kind: 'media-fallback',\n tool: args.toolName,\n modality: args.modality,\n })\n}\n\nconst renderSyntheticMediaDescription = (media: Media, byteLen: number | undefined): string =>\n `[media: ${media.filename}, ${media.mimeType}, ${formatBytesHumanReadable(byteLen)}]`\n\n/**\n * Render a single {@link Media} for the native Ollama wire. Images become a base64 entry pushed to\n * the message's `images[]` array (returned via `image`); every other modality is unsupported and\n * routes through `unsupportedMediaPolicy` to a text envelope (returned via `text`) or throws.\n */\n/**\n * The inline media id-marker (cross-battery convention; see the OpenAI battery's\n * `renderMediaIdMarker`): structural reference text authored by the harness from the\n * harness-controlled `Media.id`, rendered alongside each media so the model can reference it\n * by id in tool calls. Carries no authority; renders outside the untrusted envelope.\n */\nconst renderMediaIdMarker = (media: Media): string => `[media id: ${media.id} | ${media.filename}]`\n\nconst renderMediaForOllama = async (input: {\n media: Media\n toolName: string | undefined\n nonce: string\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n warn?: (msg: string) => void\n}): Promise<{ image?: string; text?: string }> => {\n const { media, toolName, nonce, unsupportedMediaPolicy, warn } = input\n const modality = modalityHazardToAttr(media.modalityHazard)\n\n if (media.kind === 'image') {\n const b64 = await media.asBase64()\n return { image: b64 }\n }\n\n // Non-image modality — native /api/chat has no representation for it.\n const fallbackText = async (\n keys: ReadonlyArray<string>,\n allowSyntheticFallthrough: boolean\n ): Promise<{ text: string }> => {\n const fallback = resolveFallbackStash(media, keys)\n if (fallback) {\n return {\n text: renderTextInEnvelope(fallback.text, {\n trustTier: fallback.entryTier,\n modality,\n nonce,\n toolName,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n }),\n }\n }\n if (!allowSyntheticFallthrough) {\n warn?.(\n `unsupportedMediaPolicy='fallback-stash' for ${media.filename}: no matching stash entry — falling through to synthetic description.`\n )\n }\n const byteLen = await media.byteLength()\n return {\n text: renderTextInEnvelope(renderSyntheticMediaDescription(media, byteLen), {\n trustTier: media.trustTier,\n modality,\n nonce,\n toolName,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n }),\n }\n }\n\n if (unsupportedMediaPolicy === 'throw') {\n throw new E_OLLAMA_UNSUPPORTED_MEDIA_MODALITY([media.kind, media.mimeType, media.filename])\n }\n if (\n unsupportedMediaPolicy === 'fallback-stash' ||\n (typeof unsupportedMediaPolicy === 'object' && unsupportedMediaPolicy.mode === 'fallback-stash')\n ) {\n const keys =\n typeof unsupportedMediaPolicy === 'object'\n ? unsupportedMediaPolicy.stashKeys\n : DEFAULT_STASH_FALLBACK_KEYS\n return fallbackText(keys, false)\n }\n return fallbackText([], true)\n}\n\n// ─── renderOllamaTimelineMessage ──────────────────────────────────────────────\n\n/**\n * Renders a single timeline {@link @nhtio/adk!Message} into a native Ollama message — flattening any\n * media into the base64 `images[]` array, surfacing reasoning as `thinking`, and wrapping textual\n * bodies in the appropriate trust envelope.\n */\nexport const renderOllamaTimelineMessage = async (input: {\n message: Message\n selfIdentity: string\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n warn?: (msg: string) => void\n}): Promise<OllamaMessage> => {\n const { message, selfIdentity, unsupportedMediaPolicy, warn } = input\n const identifier =\n message.identity?.identifier !== undefined && message.identity?.identifier !== null\n ? String(message.identity.identifier)\n : ''\n const representationRaw =\n message.identity?.representation !== undefined && message.identity?.representation !== null\n ? message.identity.representation.toString()\n : ''\n const representation = representationRaw.length > 0 ? representationRaw : identifier\n const text = message.content !== undefined ? message.content.toString() : ''\n const createdAtStr = message.createdAt.toISO?.() ?? ''\n const createdAtAttr = createdAtStr ? ` createdAt=\"${escapeXmlAttribute(createdAtStr)}\"` : ''\n const attachments = message.attachments\n\n // Build the text envelope (same identity logic as the OpenAI battery — wire-agnostic).\n let envelopeText: string\n let role: 'user' | 'assistant'\n if (message.role === 'user') {\n role = 'user'\n if (identifier.length === 0) {\n envelopeText = text\n } else {\n const fromAttr = escapeXmlAttribute(representation)\n envelopeText = `<message_${message.id} from=\"${fromAttr}\" role=\"user\"${createdAtAttr}>\\n${text}\\n</message_${message.id}>`\n }\n } else {\n role = 'assistant'\n if (identifier.length === 0 || identifier === selfIdentity) {\n envelopeText = text\n } else {\n const fromAttr = escapeXmlAttribute(representation)\n envelopeText = `<peer_agent_output_${message.id} from=\"${fromAttr}\"${createdAtAttr}>\\n${text}\\n</peer_agent_output_${message.id}>`\n }\n }\n\n const images: string[] = []\n const extraTexts: string[] = []\n for (const media of attachments) {\n const rendered = await renderMediaForOllama({\n media,\n toolName: undefined,\n nonce: message.id,\n unsupportedMediaPolicy,\n renderTrustedContent,\n renderUntrustedContent,\n warn,\n })\n extraTexts.push(renderMediaIdMarker(media))\n if (rendered.image !== undefined) images.push(rendered.image)\n if (rendered.text !== undefined) extraTexts.push(rendered.text)\n }\n\n // Non-image fallbacks (text envelopes) are appended to the message content; images ride in the\n // separate native `images[]` field.\n const contentParts: string[] = []\n if (envelopeText.length > 0) contentParts.push(envelopeText)\n for (const t of extraTexts) contentParts.push(t)\n const out: OllamaMessage = { role, content: contentParts.join('\\n') }\n if (images.length > 0) out.images = images\n return out\n}\n/** Default timeline-message renderer; alias of {@link renderOllamaTimelineMessage}. */\nexport const defaultRenderOllamaTimelineMessage = renderOllamaTimelineMessage\n\n// ─── renderOllamaToolCallResult ───────────────────────────────────────────────\n\nconst looksLikeSpooledArtifact = (value: unknown): value is SpooledArtifact => {\n if (!value || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n return (\n typeof v.asString === 'function' &&\n typeof v.byteLength === 'function' &&\n typeof v.lineCount === 'function' &&\n typeof v.estimateTokens === 'function'\n )\n}\n\nconst renderArtifactHandleBody = (\n toolCall: ToolCall,\n artifact: SpooledArtifact,\n byteLength: number,\n lineCount: number\n): string => {\n const ctor = (\n artifact as unknown as {\n constructor: { toolMethods?: ReadonlyArray<{ name: string; description?: string }> }\n }\n ).constructor\n const methods = ctor?.toolMethods ?? []\n const lines: string[] = []\n lines.push(`This tool returned a large artifact that was not inlined to preserve context budget.`)\n lines.push(``)\n lines.push(`Artifact metadata:`)\n lines.push(`- callId: ${toolCall.id}`)\n lines.push(`- kind: ${ctor?.constructor?.name ?? 'SpooledArtifact'}`)\n lines.push(`- byteLength: ${byteLength}`)\n lines.push(`- lineCount: ${lineCount}`)\n lines.push(``)\n lines.push(`To read this artifact in this turn, call one of the following tools with`)\n lines.push(`callId=${toolCall.id}:`)\n for (const m of methods) {\n if (m.description) {\n lines.push(`- ${m.name} — ${m.description}`)\n } else {\n lines.push(`- ${m.name}`)\n }\n }\n lines.push(``)\n lines.push(\n `The artifact persists in this turn's context — multiple queries against the same callId are allowed and efficient. Do not assume the body has been inlined anywhere else.`\n )\n return lines.join('\\n')\n}\n\n/**\n * Render a tool-call result to native Ollama tool-message content (always a string). Media results\n * are routed through the internal media renderer: images cannot ride on a tool-role message's\n * `content`, so an image result is replaced with a short text marker (the image bytes are not\n * re-sent on a tool message); non-image media use the same fallback-text path as elsewhere.\n */\nexport const renderOllamaToolCallResult = async (input: {\n toolCall: ToolCall\n results: Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[]\n tool: Tool | ArtifactTool | undefined\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n warn?: (msg: string) => void\n}): Promise<string> => {\n const { toolCall, results, tool, warn, unsupportedMediaPolicy } = input\n const isTrusted =\n tool !== null && tool !== undefined && (tool as { trusted?: boolean }).trusted === true\n\n if (tool === undefined) {\n warn?.(\n `Tool \"${toolCall.tool}\" is not present in the bound tool registry at render time; defaulting to untrusted envelope.`\n )\n }\n\n // Media silo — bypasses Tool.trusted (Trust-Is-Content rule).\n const isMediaResult = Media.isMedia(results)\n const isMediaArrayResult =\n Array.isArray(results) && results.length > 0 && results.every((r) => Media.isMedia(r))\n if (isMediaResult || isMediaArrayResult) {\n const mediaList = isMediaResult ? [results as Media] : (results as Media[])\n const parts: string[] = []\n for (const media of mediaList) {\n const rendered = await renderMediaForOllama({\n media,\n toolName: toolCall.tool,\n nonce: toolCall.checksum,\n unsupportedMediaPolicy,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n warn,\n })\n parts.push(renderMediaIdMarker(media))\n if (rendered.text !== undefined) {\n parts.push(rendered.text)\n } else {\n // An image tool-result cannot be carried on a tool-role message's string content; emit a\n // text marker in its place so the model knows an image was produced.\n const byteLen = await media.byteLength()\n parts.push(\n input.renderUntrustedContent(renderSyntheticMediaDescription(media, byteLen), {\n nonce: toolCall.checksum,\n kind: 'tool-result-image',\n tool: toolCall.tool,\n modality: modalityHazardToAttr(media.modalityHazard),\n })\n )\n }\n }\n return parts.join('\\n')\n }\n\n // SpooledArtifact[] silo.\n if (Array.isArray(results)) {\n const parts: string[] = []\n for (const a of results) {\n parts.push(await (a as SpooledArtifact).asString())\n }\n const joined = parts.join('\\n\\n')\n return isTrusted\n ? input.renderTrustedContent(joined, {\n nonce: toolCall.checksum,\n kind: 'trusted-tool-result',\n tool: toolCall.tool,\n })\n : input.renderUntrustedContent(joined, {\n nonce: toolCall.checksum,\n kind: 'tool-result',\n tool: toolCall.tool,\n })\n }\n\n const isSpooled = looksLikeSpooledArtifact(results)\n\n // Handle-pattern branch: spooled + inline=false → always untrusted (queryable-data).\n if (isSpooled && toolCall.inline === false) {\n const artifact = results as SpooledArtifact\n let byteLength = 0\n let lineCount = 0\n try {\n byteLength = await artifact.byteLength()\n } catch {\n byteLength = 0\n }\n try {\n lineCount = await artifact.lineCount()\n } catch {\n lineCount = 0\n }\n const body = renderArtifactHandleBody(toolCall, artifact, byteLength, lineCount)\n return input.renderUntrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'artifact-handle',\n tool: toolCall.tool,\n })\n }\n\n if (!isSpooled && toolCall.inline === false) {\n warn?.(\n `Tool call ${toolCall.id} has inline=false but results is a Tokenizable (not a SpooledArtifact); rendering inline anyway.`\n )\n }\n\n const body = isSpooled\n ? await (results as SpooledArtifact).asString()\n : (results as Tokenizable).toString()\n\n return isTrusted\n ? input.renderTrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'trusted-tool-result',\n tool: toolCall.tool,\n })\n : input.renderUntrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'tool-result',\n tool: toolCall.tool,\n })\n}\n/** Default tool-call-result renderer; alias of {@link renderOllamaToolCallResult}. */\nexport const defaultRenderOllamaToolCallResult = renderOllamaToolCallResult\n\n// ─── buildOllamaHistory ───────────────────────────────────────────────────────\n\ntype TimelineItem =\n | { kind: 'message'; createdAt: number; value: Message }\n | { kind: 'thought'; createdAt: number; value: Thought }\n | { kind: 'toolCall'; createdAt: number; value: ToolCall }\n\n/**\n * Assembles the complete native Ollama message history for a dispatch — system prompt and content\n * buckets, the interleaved timeline of messages/thoughts/tool calls, and the collected opaque\n * reasoning payloads — by delegating to the injected sub-renderers.\n */\nexport const buildOllamaHistory = async (input: {\n systemPrompt: Tokenizable\n standingInstructions: Iterable<Tokenizable>\n memories: Iterable<Memory>\n retrievables: Iterable<Retrievable>\n messages: Iterable<Message>\n thoughts: Iterable<Thought>\n toolCalls: Iterable<ToolCall>\n tools: ToolRegistry\n renderedToolCallResults: Map<string, string>\n bucketOrder: ChatCompletionsBucketOrder\n selfIdentity: string\n thoughtSurfacing: 'all-self' | 'latest-self' | 'all'\n replayCompatibility: ReadonlyArray<string>\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n renderOllamaToolCallResult: OllamaHelpers['renderOllamaToolCallResult']\n renderChatCompletionsSystemPrompt: ChatHelpersCommon['renderChatCompletionsSystemPrompt']\n renderStandingInstructions: ChatHelpersCommon['renderStandingInstructions']\n renderMemories: ChatHelpersCommon['renderMemories']\n renderRetrievables: ChatHelpersCommon['renderRetrievables']\n renderRetrievableSafetyDirective: ChatHelpersCommon['renderRetrievableSafetyDirective']\n renderFirstPartyRetrievables: ChatHelpersCommon['renderFirstPartyRetrievables']\n renderThirdPartyPublicRetrievables: ChatHelpersCommon['renderThirdPartyPublicRetrievables']\n renderThirdPartyPrivateRetrievables: ChatHelpersCommon['renderThirdPartyPrivateRetrievables']\n renderOllamaTimelineMessage: OllamaHelpers['renderOllamaTimelineMessage']\n renderThought: ChatHelpersCommon['renderThought']\n filterThoughts: ChatHelpersCommon['filterThoughts']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n warn?: (msg: string) => void\n}): Promise<{\n messages: OllamaMessage[]\n reasoningPayloads: Array<{ id: string; replayCompatibility: string; payload: unknown }>\n}> => {\n const out: OllamaMessage[] = []\n const reasoningPayloads: Array<{ id: string; replayCompatibility: string; payload: unknown }> = []\n\n const buckets = input.bucketOrder\n const timelineIdx = buckets.indexOf('timeline')\n\n const leadingSystem = await input.renderChatCompletionsSystemPrompt({\n systemPrompt: input.systemPrompt,\n standingInstructions: input.standingInstructions,\n memories: input.memories,\n retrievables: input.retrievables,\n bucketOrder: buckets,\n renderStandingInstructions: input.renderStandingInstructions,\n renderMemories: input.renderMemories,\n renderRetrievables: input.renderRetrievables,\n renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n renderUntrustedContent: input.renderUntrustedContent,\n })\n if (leadingSystem.length > 0) {\n out.push({ role: 'system', content: leadingSystem })\n }\n\n const includesTimeline = timelineIdx !== -1\n if (includesTimeline) {\n const survivingThoughts = input.filterThoughts(\n input.thoughts,\n input.thoughtSurfacing,\n input.selfIdentity,\n input.replayCompatibility\n )\n\n const items: TimelineItem[] = []\n for (const m of input.messages) {\n items.push({ kind: 'message', createdAt: m.createdAt.toMillis(), value: m })\n }\n for (const t of survivingThoughts) {\n items.push({ kind: 'thought', createdAt: t.createdAt.toMillis(), value: t })\n }\n for (const tc of input.toolCalls) {\n items.push({ kind: 'toolCall', createdAt: tc.createdAt.toMillis(), value: tc })\n }\n items.sort((a, b) => a.createdAt - b.createdAt)\n\n const replaySet = new Set<string>([...input.replayCompatibility])\n\n for (const item of items) {\n if (item.kind === 'message') {\n out.push(\n await input.renderOllamaTimelineMessage({\n message: item.value,\n selfIdentity: input.selfIdentity,\n unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n warn: input.warn,\n })\n )\n } else if (item.kind === 'thought') {\n const t = item.value\n const identifier = String(t.identity?.identifier ?? '')\n const isSelf = identifier === input.selfIdentity\n const hasPayload = t.payload !== undefined\n const compatTag = t.replayCompatibility\n\n if (hasPayload && compatTag && replaySet.has(compatTag)) {\n reasoningPayloads.push({ id: t.id, replayCompatibility: compatTag, payload: t.payload })\n const envelope = input.renderThought(\n t.content.toString(),\n {\n nonce: t.id,\n kind: 'opaque-reasoning',\n from: identifier,\n createdAt: t.createdAt?.toISO?.() ?? undefined,\n replayCompatibility: compatTag,\n },\n t.payload\n )\n out.push({ role: 'assistant', content: envelope })\n } else if (!hasPayload) {\n const envelope = input.renderThought(t.content.toString(), {\n nonce: t.id,\n kind: isSelf ? 'self-reasoning' : 'peer-reasoning',\n from: identifier,\n createdAt: t.createdAt?.toISO?.() ?? undefined,\n })\n out.push({ role: 'assistant', content: envelope })\n }\n // else: opaque, non-matching → elided.\n } else {\n // tool call: synthetic assistant message carrying tool_calls[] (object-form arguments),\n // followed by a tool-role message labelled by `tool_name` (NOT tool_call_id).\n const tc = item.value\n const args =\n tc.args !== null && typeof tc.args === 'object' && !Array.isArray(tc.args)\n ? (tc.args as Record<string, unknown>)\n : {}\n out.push({\n role: 'assistant',\n content: '',\n tool_calls: [{ function: { name: tc.tool, arguments: args } }],\n })\n\n let rendered = input.renderedToolCallResults.get(tc.id)\n if (rendered === undefined) {\n const tool = input.tools.get?.(tc.tool)\n rendered = await input.renderOllamaToolCallResult({\n toolCall: tc,\n results: tc.results as\n | Tokenizable\n | SpooledArtifact\n | SpooledArtifact[]\n | Media\n | Media[],\n tool: tool as Tool | ArtifactTool | undefined,\n renderUntrustedContent: input.renderUntrustedContent,\n renderTrustedContent: input.renderTrustedContent,\n unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n warn: input.warn,\n })\n }\n out.push({ role: 'tool', content: rendered, tool_name: tc.tool })\n }\n }\n }\n\n if (includesTimeline) {\n const trailingParts: string[] = []\n for (let i = timelineIdx + 1; i < buckets.length; i++) {\n const label = buckets[i]!\n if (label === 'standingInstructions') {\n const block = input.renderStandingInstructions(input.standingInstructions)\n if (block.length > 0) trailingParts.push(block)\n } else if (label === 'memories') {\n const wrapped: Array<{ memory: Memory; attrs: MemoryAttrs }> = []\n for (const m of input.memories) {\n wrapped.push(memoryToAttrs(m))\n }\n const block = input.renderMemories(wrapped)\n if (block.length > 0) trailingParts.push(block)\n } else if (label === 'retrievables') {\n const wrapped: Array<{ retrievable: Retrievable; attrs: RetrievableAttrs }> = []\n for (const r of input.retrievables) {\n wrapped.push(retrievableToAttrs(r))\n }\n const block = await input.renderRetrievables(wrapped, {\n renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n renderUntrustedContent: input.renderUntrustedContent,\n })\n if (block.length > 0) trailingParts.push(block)\n }\n }\n if (trailingParts.length > 0) {\n out.push({ role: 'system', content: trailingParts.join('\\n\\n') })\n }\n }\n\n return { messages: out, reasoningPayloads }\n}\n/** Default native-history assembler; alias of {@link buildOllamaHistory}. */\nexport const defaultBuildOllamaHistory = buildOllamaHistory\n\n// suppress unused\nvoid isInstanceOf\n"],"mappings":"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"}
@@ -82,6 +82,13 @@ var renderSyntheticMediaDescription = (media, byteLen) => `[media: ${media.filen
82
82
  * the message's `images[]` array (returned via `image`); every other modality is unsupported and
83
83
  * routes through `unsupportedMediaPolicy` to a text envelope (returned via `text`) or throws.
84
84
  */
85
+ /**
86
+ * The inline media id-marker (cross-battery convention; see the OpenAI battery's
87
+ * `renderMediaIdMarker`): structural reference text authored by the harness from the
88
+ * harness-controlled `Media.id`, rendered alongside each media so the model can reference it
89
+ * by id in tool calls. Carries no authority; renders outside the untrusted envelope.
90
+ */
91
+ var renderMediaIdMarker = (media) => `[media id: ${media.id} | ${media.filename}]`;
85
92
  var renderMediaForOllama = async (input) => {
86
93
  const { media, toolName, nonce, unsupportedMediaPolicy, warn } = input;
87
94
  const modality = modalityHazardToAttr(media.modalityHazard);
@@ -157,6 +164,7 @@ var renderOllamaTimelineMessage = async (input) => {
157
164
  renderUntrustedContent,
158
165
  warn
159
166
  });
167
+ extraTexts.push(renderMediaIdMarker(media));
160
168
  if (rendered.image !== void 0) images.push(rendered.image);
161
169
  if (rendered.text !== void 0) extraTexts.push(rendered.text);
162
170
  }
@@ -222,6 +230,7 @@ var renderOllamaToolCallResult = async (input) => {
222
230
  renderUntrustedContent: input.renderUntrustedContent,
223
231
  warn
224
232
  });
233
+ parts.push(renderMediaIdMarker(media));
225
234
  if (rendered.text !== void 0) parts.push(rendered.text);
226
235
  else {
227
236
  const byteLen = await media.byteLength();
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.mjs","names":[],"sources":["../../../../src/batteries/llm/ollama/helpers.ts"],"sourcesContent":["/**\n * Swappable translation helpers for rendering ADK state into native Ollama `/api/chat` requests.\n *\n * @module @nhtio/adk/batteries/llm/ollama/helpers\n *\n * @remarks\n * The wire-shape-agnostic helpers (`renderUntrustedContent`, `renderMemories`,\n * `renderChatCompletionsSystemPrompt`, `toolsToChatCompletionsTools`, …) are shared with the OpenAI\n * battery via the internal `../chat_common/helpers` submodule and re-exported here under their\n * original names. Only the Ollama-WIRE-SPECIFIC helpers are defined here:\n * `renderOllamaTimelineMessage` (flat `content` + base64 `images[]` + `thinking`),\n * `renderOllamaToolCallResult` (string-only result content), `buildOllamaHistory` (synthetic\n * `assistant.tool_calls` with object-form `arguments` + `tool`-role messages labelled by\n * `tool_name`), and `ollamaToolsFromTools` (alias of the shared tool-definition renderer — native\n * `/api/chat` uses the same function-tool wire shape).\n *\n * Native `/api/chat` supports only base64 `images[]`; every non-image modality routes through the\n * `unsupportedMediaPolicy` fallback (stash text / synthetic description) or throws.\n */\n\nimport { Media } from '@nhtio/adk/common'\nimport { isInstanceOf } from '@nhtio/adk/guards'\nimport { E_OLLAMA_UNSUPPORTED_MEDIA_MODALITY } from './exceptions'\nimport {\n escapeXmlAttribute,\n memoryToAttrs,\n retrievableToAttrs,\n renderTrustedContent,\n renderUntrustedContent,\n toolsToChatCompletionsTools,\n} from '../chat_common/helpers'\nimport type { ChatHelpersCommon } from '../chat_common/types'\nimport type {\n OllamaMessage,\n OllamaTool,\n OllamaHelpers,\n MemoryAttrs,\n RetrievableAttrs,\n ChatCompletionsBucketOrder,\n UnsupportedMediaPolicy,\n} from './types'\nimport type {\n Tool,\n ArtifactTool,\n ToolRegistry,\n Tokenizable,\n Memory,\n Message,\n Thought,\n ToolCall,\n Retrievable,\n SpooledArtifact,\n MediaModalityHazard,\n MediaStashEntry,\n} from '@nhtio/adk/common'\n\n// ─── Re-exported wire-shape-agnostic helpers (shared submodule) ───────────────\nexport {\n descriptionToChatCompletionsJsonSchema,\n defaultDescriptionToChatCompletionsJsonSchema,\n renderUntrustedContent,\n defaultRenderUntrustedContent,\n renderTrustedContent,\n defaultRenderTrustedContent,\n renderStandingInstructions,\n defaultRenderStandingInstructions,\n renderMemories,\n defaultRenderMemories,\n renderRetrievableSafetyDirective,\n defaultRenderRetrievableSafetyDirective,\n renderFirstPartyRetrievables,\n defaultRenderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables,\n defaultRenderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables,\n defaultRenderThirdPartyPrivateRetrievables,\n renderRetrievables,\n defaultRenderRetrievables,\n renderThought,\n defaultRenderThought,\n filterThoughts,\n defaultFilterThoughts,\n toolsToChatCompletionsTools,\n defaultToolsToChatCompletionsTools,\n renderChatCompletionsSystemPrompt,\n defaultRenderChatCompletionsSystemPrompt,\n} from '../chat_common/helpers'\n\n// ─── ollamaToolsFromTools (alias — native tool wire == Chat Completions wire) ──\n\n/**\n * Convert ADK tools to the native Ollama `tools[]` wire. Native `/api/chat` uses the identical\n * `{ type: 'function', function: { name, description, parameters } }` shape as Chat Completions, so\n * this is an alias of the shared renderer.\n */\nexport const ollamaToolsFromTools = (\n tools: ReadonlyArray<Tool | ArtifactTool>,\n deps: Parameters<typeof toolsToChatCompletionsTools>[1]\n): OllamaTool[] => toolsToChatCompletionsTools(tools, deps)\n/** Default implementation of {@link OllamaHelpers}-style tool translation; alias of {@link ollamaToolsFromTools}. */\nexport const defaultOllamaToolsFromTools = ollamaToolsFromTools\n\n// ─── Media rendering (Ollama native — images only) ────────────────────────────\n\nconst DEFAULT_STASH_FALLBACK_KEYS: ReadonlyArray<string> = [\n 'text:transcript',\n 'text:caption',\n 'text:description',\n]\n\nconst modalityHazardToAttr = (h: MediaModalityHazard): 'inert' | 'extractable' | 'opaque' => {\n if (h === 'inert') return 'inert'\n if (h === 'extractable-instructions') return 'extractable'\n return 'opaque'\n}\n\nconst formatBytesHumanReadable = (bytes: number | undefined): string => {\n if (bytes === undefined || !Number.isFinite(bytes)) return 'unknown size'\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`\n}\n\nconst isMediaTextStashEntry = (e: unknown): e is MediaStashEntry => {\n if (!e || typeof e !== 'object') return false\n const r = e as Record<string, unknown>\n return typeof r.value === 'string' && typeof r.trustTier === 'string'\n}\n\nconst resolveFallbackStash = (\n media: Media,\n keys: ReadonlyArray<string>\n): { text: string; entryTier: MediaStashEntry['trustTier'] } | undefined => {\n for (const key of keys) {\n const entry = media.stash.get(key)\n if (isMediaTextStashEntry(entry)) {\n return { text: entry.value as string, entryTier: entry.trustTier }\n }\n }\n return undefined\n}\n\nconst renderTextInEnvelope = (\n text: string,\n args: {\n trustTier: MediaStashEntry['trustTier']\n modality: 'inert' | 'extractable' | 'opaque'\n nonce: string\n toolName: string | undefined\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n }\n): string => {\n if (args.trustTier === 'first-party') {\n return args.renderTrustedContent(text, {\n nonce: args.nonce,\n kind: 'media-fallback',\n tool: args.toolName,\n modality: args.modality,\n })\n }\n return args.renderUntrustedContent(text, {\n nonce: args.nonce,\n kind: 'media-fallback',\n tool: args.toolName,\n modality: args.modality,\n })\n}\n\nconst renderSyntheticMediaDescription = (media: Media, byteLen: number | undefined): string =>\n `[media: ${media.filename}, ${media.mimeType}, ${formatBytesHumanReadable(byteLen)}]`\n\n/**\n * Render a single {@link Media} for the native Ollama wire. Images become a base64 entry pushed to\n * the message's `images[]` array (returned via `image`); every other modality is unsupported and\n * routes through `unsupportedMediaPolicy` to a text envelope (returned via `text`) or throws.\n */\nconst renderMediaForOllama = async (input: {\n media: Media\n toolName: string | undefined\n nonce: string\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n warn?: (msg: string) => void\n}): Promise<{ image?: string; text?: string }> => {\n const { media, toolName, nonce, unsupportedMediaPolicy, warn } = input\n const modality = modalityHazardToAttr(media.modalityHazard)\n\n if (media.kind === 'image') {\n const b64 = await media.asBase64()\n return { image: b64 }\n }\n\n // Non-image modality — native /api/chat has no representation for it.\n const fallbackText = async (\n keys: ReadonlyArray<string>,\n allowSyntheticFallthrough: boolean\n ): Promise<{ text: string }> => {\n const fallback = resolveFallbackStash(media, keys)\n if (fallback) {\n return {\n text: renderTextInEnvelope(fallback.text, {\n trustTier: fallback.entryTier,\n modality,\n nonce,\n toolName,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n }),\n }\n }\n if (!allowSyntheticFallthrough) {\n warn?.(\n `unsupportedMediaPolicy='fallback-stash' for ${media.filename}: no matching stash entry — falling through to synthetic description.`\n )\n }\n const byteLen = await media.byteLength()\n return {\n text: renderTextInEnvelope(renderSyntheticMediaDescription(media, byteLen), {\n trustTier: media.trustTier,\n modality,\n nonce,\n toolName,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n }),\n }\n }\n\n if (unsupportedMediaPolicy === 'throw') {\n throw new E_OLLAMA_UNSUPPORTED_MEDIA_MODALITY([media.kind, media.mimeType, media.filename])\n }\n if (\n unsupportedMediaPolicy === 'fallback-stash' ||\n (typeof unsupportedMediaPolicy === 'object' && unsupportedMediaPolicy.mode === 'fallback-stash')\n ) {\n const keys =\n typeof unsupportedMediaPolicy === 'object'\n ? unsupportedMediaPolicy.stashKeys\n : DEFAULT_STASH_FALLBACK_KEYS\n return fallbackText(keys, false)\n }\n return fallbackText([], true)\n}\n\n// ─── renderOllamaTimelineMessage ──────────────────────────────────────────────\n\n/**\n * Renders a single timeline {@link @nhtio/adk!Message} into a native Ollama message — flattening any\n * media into the base64 `images[]` array, surfacing reasoning as `thinking`, and wrapping textual\n * bodies in the appropriate trust envelope.\n */\nexport const renderOllamaTimelineMessage = async (input: {\n message: Message\n selfIdentity: string\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n warn?: (msg: string) => void\n}): Promise<OllamaMessage> => {\n const { message, selfIdentity, unsupportedMediaPolicy, warn } = input\n const identifier =\n message.identity?.identifier !== undefined && message.identity?.identifier !== null\n ? String(message.identity.identifier)\n : ''\n const representationRaw =\n message.identity?.representation !== undefined && message.identity?.representation !== null\n ? message.identity.representation.toString()\n : ''\n const representation = representationRaw.length > 0 ? representationRaw : identifier\n const text = message.content !== undefined ? message.content.toString() : ''\n const createdAtStr = message.createdAt.toISO?.() ?? ''\n const createdAtAttr = createdAtStr ? ` createdAt=\"${escapeXmlAttribute(createdAtStr)}\"` : ''\n const attachments = message.attachments\n\n // Build the text envelope (same identity logic as the OpenAI battery — wire-agnostic).\n let envelopeText: string\n let role: 'user' | 'assistant'\n if (message.role === 'user') {\n role = 'user'\n if (identifier.length === 0) {\n envelopeText = text\n } else {\n const fromAttr = escapeXmlAttribute(representation)\n envelopeText = `<message_${message.id} from=\"${fromAttr}\" role=\"user\"${createdAtAttr}>\\n${text}\\n</message_${message.id}>`\n }\n } else {\n role = 'assistant'\n if (identifier.length === 0 || identifier === selfIdentity) {\n envelopeText = text\n } else {\n const fromAttr = escapeXmlAttribute(representation)\n envelopeText = `<peer_agent_output_${message.id} from=\"${fromAttr}\"${createdAtAttr}>\\n${text}\\n</peer_agent_output_${message.id}>`\n }\n }\n\n const images: string[] = []\n const extraTexts: string[] = []\n for (const media of attachments) {\n const rendered = await renderMediaForOllama({\n media,\n toolName: undefined,\n nonce: message.id,\n unsupportedMediaPolicy,\n renderTrustedContent,\n renderUntrustedContent,\n warn,\n })\n if (rendered.image !== undefined) images.push(rendered.image)\n if (rendered.text !== undefined) extraTexts.push(rendered.text)\n }\n\n // Non-image fallbacks (text envelopes) are appended to the message content; images ride in the\n // separate native `images[]` field.\n const contentParts: string[] = []\n if (envelopeText.length > 0) contentParts.push(envelopeText)\n for (const t of extraTexts) contentParts.push(t)\n const out: OllamaMessage = { role, content: contentParts.join('\\n') }\n if (images.length > 0) out.images = images\n return out\n}\n/** Default timeline-message renderer; alias of {@link renderOllamaTimelineMessage}. */\nexport const defaultRenderOllamaTimelineMessage = renderOllamaTimelineMessage\n\n// ─── renderOllamaToolCallResult ───────────────────────────────────────────────\n\nconst looksLikeSpooledArtifact = (value: unknown): value is SpooledArtifact => {\n if (!value || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n return (\n typeof v.asString === 'function' &&\n typeof v.byteLength === 'function' &&\n typeof v.lineCount === 'function' &&\n typeof v.estimateTokens === 'function'\n )\n}\n\nconst renderArtifactHandleBody = (\n toolCall: ToolCall,\n artifact: SpooledArtifact,\n byteLength: number,\n lineCount: number\n): string => {\n const ctor = (\n artifact as unknown as {\n constructor: { toolMethods?: ReadonlyArray<{ name: string; description?: string }> }\n }\n ).constructor\n const methods = ctor?.toolMethods ?? []\n const lines: string[] = []\n lines.push(`This tool returned a large artifact that was not inlined to preserve context budget.`)\n lines.push(``)\n lines.push(`Artifact metadata:`)\n lines.push(`- callId: ${toolCall.id}`)\n lines.push(`- kind: ${ctor?.constructor?.name ?? 'SpooledArtifact'}`)\n lines.push(`- byteLength: ${byteLength}`)\n lines.push(`- lineCount: ${lineCount}`)\n lines.push(``)\n lines.push(`To read this artifact in this turn, call one of the following tools with`)\n lines.push(`callId=${toolCall.id}:`)\n for (const m of methods) {\n if (m.description) {\n lines.push(`- ${m.name} — ${m.description}`)\n } else {\n lines.push(`- ${m.name}`)\n }\n }\n lines.push(``)\n lines.push(\n `The artifact persists in this turn's context — multiple queries against the same callId are allowed and efficient. Do not assume the body has been inlined anywhere else.`\n )\n return lines.join('\\n')\n}\n\n/**\n * Render a tool-call result to native Ollama tool-message content (always a string). Media results\n * are routed through the internal media renderer: images cannot ride on a tool-role message's\n * `content`, so an image result is replaced with a short text marker (the image bytes are not\n * re-sent on a tool message); non-image media use the same fallback-text path as elsewhere.\n */\nexport const renderOllamaToolCallResult = async (input: {\n toolCall: ToolCall\n results: Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[]\n tool: Tool | ArtifactTool | undefined\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n warn?: (msg: string) => void\n}): Promise<string> => {\n const { toolCall, results, tool, warn, unsupportedMediaPolicy } = input\n const isTrusted =\n tool !== null && tool !== undefined && (tool as { trusted?: boolean }).trusted === true\n\n if (tool === undefined) {\n warn?.(\n `Tool \"${toolCall.tool}\" is not present in the bound tool registry at render time; defaulting to untrusted envelope.`\n )\n }\n\n // Media silo — bypasses Tool.trusted (Trust-Is-Content rule).\n const isMediaResult = Media.isMedia(results)\n const isMediaArrayResult =\n Array.isArray(results) && results.length > 0 && results.every((r) => Media.isMedia(r))\n if (isMediaResult || isMediaArrayResult) {\n const mediaList = isMediaResult ? [results as Media] : (results as Media[])\n const parts: string[] = []\n for (const media of mediaList) {\n const rendered = await renderMediaForOllama({\n media,\n toolName: toolCall.tool,\n nonce: toolCall.checksum,\n unsupportedMediaPolicy,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n warn,\n })\n if (rendered.text !== undefined) {\n parts.push(rendered.text)\n } else {\n // An image tool-result cannot be carried on a tool-role message's string content; emit a\n // text marker in its place so the model knows an image was produced.\n const byteLen = await media.byteLength()\n parts.push(\n input.renderUntrustedContent(renderSyntheticMediaDescription(media, byteLen), {\n nonce: toolCall.checksum,\n kind: 'tool-result-image',\n tool: toolCall.tool,\n modality: modalityHazardToAttr(media.modalityHazard),\n })\n )\n }\n }\n return parts.join('\\n')\n }\n\n // SpooledArtifact[] silo.\n if (Array.isArray(results)) {\n const parts: string[] = []\n for (const a of results) {\n parts.push(await (a as SpooledArtifact).asString())\n }\n const joined = parts.join('\\n\\n')\n return isTrusted\n ? input.renderTrustedContent(joined, {\n nonce: toolCall.checksum,\n kind: 'trusted-tool-result',\n tool: toolCall.tool,\n })\n : input.renderUntrustedContent(joined, {\n nonce: toolCall.checksum,\n kind: 'tool-result',\n tool: toolCall.tool,\n })\n }\n\n const isSpooled = looksLikeSpooledArtifact(results)\n\n // Handle-pattern branch: spooled + inline=false → always untrusted (queryable-data).\n if (isSpooled && toolCall.inline === false) {\n const artifact = results as SpooledArtifact\n let byteLength = 0\n let lineCount = 0\n try {\n byteLength = await artifact.byteLength()\n } catch {\n byteLength = 0\n }\n try {\n lineCount = await artifact.lineCount()\n } catch {\n lineCount = 0\n }\n const body = renderArtifactHandleBody(toolCall, artifact, byteLength, lineCount)\n return input.renderUntrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'artifact-handle',\n tool: toolCall.tool,\n })\n }\n\n if (!isSpooled && toolCall.inline === false) {\n warn?.(\n `Tool call ${toolCall.id} has inline=false but results is a Tokenizable (not a SpooledArtifact); rendering inline anyway.`\n )\n }\n\n const body = isSpooled\n ? await (results as SpooledArtifact).asString()\n : (results as Tokenizable).toString()\n\n return isTrusted\n ? input.renderTrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'trusted-tool-result',\n tool: toolCall.tool,\n })\n : input.renderUntrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'tool-result',\n tool: toolCall.tool,\n })\n}\n/** Default tool-call-result renderer; alias of {@link renderOllamaToolCallResult}. */\nexport const defaultRenderOllamaToolCallResult = renderOllamaToolCallResult\n\n// ─── buildOllamaHistory ───────────────────────────────────────────────────────\n\ntype TimelineItem =\n | { kind: 'message'; createdAt: number; value: Message }\n | { kind: 'thought'; createdAt: number; value: Thought }\n | { kind: 'toolCall'; createdAt: number; value: ToolCall }\n\n/**\n * Assembles the complete native Ollama message history for a dispatch — system prompt and content\n * buckets, the interleaved timeline of messages/thoughts/tool calls, and the collected opaque\n * reasoning payloads — by delegating to the injected sub-renderers.\n */\nexport const buildOllamaHistory = async (input: {\n systemPrompt: Tokenizable\n standingInstructions: Iterable<Tokenizable>\n memories: Iterable<Memory>\n retrievables: Iterable<Retrievable>\n messages: Iterable<Message>\n thoughts: Iterable<Thought>\n toolCalls: Iterable<ToolCall>\n tools: ToolRegistry\n renderedToolCallResults: Map<string, string>\n bucketOrder: ChatCompletionsBucketOrder\n selfIdentity: string\n thoughtSurfacing: 'all-self' | 'latest-self' | 'all'\n replayCompatibility: ReadonlyArray<string>\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n renderOllamaToolCallResult: OllamaHelpers['renderOllamaToolCallResult']\n renderChatCompletionsSystemPrompt: ChatHelpersCommon['renderChatCompletionsSystemPrompt']\n renderStandingInstructions: ChatHelpersCommon['renderStandingInstructions']\n renderMemories: ChatHelpersCommon['renderMemories']\n renderRetrievables: ChatHelpersCommon['renderRetrievables']\n renderRetrievableSafetyDirective: ChatHelpersCommon['renderRetrievableSafetyDirective']\n renderFirstPartyRetrievables: ChatHelpersCommon['renderFirstPartyRetrievables']\n renderThirdPartyPublicRetrievables: ChatHelpersCommon['renderThirdPartyPublicRetrievables']\n renderThirdPartyPrivateRetrievables: ChatHelpersCommon['renderThirdPartyPrivateRetrievables']\n renderOllamaTimelineMessage: OllamaHelpers['renderOllamaTimelineMessage']\n renderThought: ChatHelpersCommon['renderThought']\n filterThoughts: ChatHelpersCommon['filterThoughts']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n warn?: (msg: string) => void\n}): Promise<{\n messages: OllamaMessage[]\n reasoningPayloads: Array<{ id: string; replayCompatibility: string; payload: unknown }>\n}> => {\n const out: OllamaMessage[] = []\n const reasoningPayloads: Array<{ id: string; replayCompatibility: string; payload: unknown }> = []\n\n const buckets = input.bucketOrder\n const timelineIdx = buckets.indexOf('timeline')\n\n const leadingSystem = await input.renderChatCompletionsSystemPrompt({\n systemPrompt: input.systemPrompt,\n standingInstructions: input.standingInstructions,\n memories: input.memories,\n retrievables: input.retrievables,\n bucketOrder: buckets,\n renderStandingInstructions: input.renderStandingInstructions,\n renderMemories: input.renderMemories,\n renderRetrievables: input.renderRetrievables,\n renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n renderUntrustedContent: input.renderUntrustedContent,\n })\n if (leadingSystem.length > 0) {\n out.push({ role: 'system', content: leadingSystem })\n }\n\n const includesTimeline = timelineIdx !== -1\n if (includesTimeline) {\n const survivingThoughts = input.filterThoughts(\n input.thoughts,\n input.thoughtSurfacing,\n input.selfIdentity,\n input.replayCompatibility\n )\n\n const items: TimelineItem[] = []\n for (const m of input.messages) {\n items.push({ kind: 'message', createdAt: m.createdAt.toMillis(), value: m })\n }\n for (const t of survivingThoughts) {\n items.push({ kind: 'thought', createdAt: t.createdAt.toMillis(), value: t })\n }\n for (const tc of input.toolCalls) {\n items.push({ kind: 'toolCall', createdAt: tc.createdAt.toMillis(), value: tc })\n }\n items.sort((a, b) => a.createdAt - b.createdAt)\n\n const replaySet = new Set<string>([...input.replayCompatibility])\n\n for (const item of items) {\n if (item.kind === 'message') {\n out.push(\n await input.renderOllamaTimelineMessage({\n message: item.value,\n selfIdentity: input.selfIdentity,\n unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n warn: input.warn,\n })\n )\n } else if (item.kind === 'thought') {\n const t = item.value\n const identifier = String(t.identity?.identifier ?? '')\n const isSelf = identifier === input.selfIdentity\n const hasPayload = t.payload !== undefined\n const compatTag = t.replayCompatibility\n\n if (hasPayload && compatTag && replaySet.has(compatTag)) {\n reasoningPayloads.push({ id: t.id, replayCompatibility: compatTag, payload: t.payload })\n const envelope = input.renderThought(\n t.content.toString(),\n {\n nonce: t.id,\n kind: 'opaque-reasoning',\n from: identifier,\n createdAt: t.createdAt?.toISO?.() ?? undefined,\n replayCompatibility: compatTag,\n },\n t.payload\n )\n out.push({ role: 'assistant', content: envelope })\n } else if (!hasPayload) {\n const envelope = input.renderThought(t.content.toString(), {\n nonce: t.id,\n kind: isSelf ? 'self-reasoning' : 'peer-reasoning',\n from: identifier,\n createdAt: t.createdAt?.toISO?.() ?? undefined,\n })\n out.push({ role: 'assistant', content: envelope })\n }\n // else: opaque, non-matching → elided.\n } else {\n // tool call: synthetic assistant message carrying tool_calls[] (object-form arguments),\n // followed by a tool-role message labelled by `tool_name` (NOT tool_call_id).\n const tc = item.value\n const args =\n tc.args !== null && typeof tc.args === 'object' && !Array.isArray(tc.args)\n ? (tc.args as Record<string, unknown>)\n : {}\n out.push({\n role: 'assistant',\n content: '',\n tool_calls: [{ function: { name: tc.tool, arguments: args } }],\n })\n\n let rendered = input.renderedToolCallResults.get(tc.id)\n if (rendered === undefined) {\n const tool = input.tools.get?.(tc.tool)\n rendered = await input.renderOllamaToolCallResult({\n toolCall: tc,\n results: tc.results as\n | Tokenizable\n | SpooledArtifact\n | SpooledArtifact[]\n | Media\n | Media[],\n tool: tool as Tool | ArtifactTool | undefined,\n renderUntrustedContent: input.renderUntrustedContent,\n renderTrustedContent: input.renderTrustedContent,\n unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n warn: input.warn,\n })\n }\n out.push({ role: 'tool', content: rendered, tool_name: tc.tool })\n }\n }\n }\n\n if (includesTimeline) {\n const trailingParts: string[] = []\n for (let i = timelineIdx + 1; i < buckets.length; i++) {\n const label = buckets[i]!\n if (label === 'standingInstructions') {\n const block = input.renderStandingInstructions(input.standingInstructions)\n if (block.length > 0) trailingParts.push(block)\n } else if (label === 'memories') {\n const wrapped: Array<{ memory: Memory; attrs: MemoryAttrs }> = []\n for (const m of input.memories) {\n wrapped.push(memoryToAttrs(m))\n }\n const block = input.renderMemories(wrapped)\n if (block.length > 0) trailingParts.push(block)\n } else if (label === 'retrievables') {\n const wrapped: Array<{ retrievable: Retrievable; attrs: RetrievableAttrs }> = []\n for (const r of input.retrievables) {\n wrapped.push(retrievableToAttrs(r))\n }\n const block = await input.renderRetrievables(wrapped, {\n renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n renderUntrustedContent: input.renderUntrustedContent,\n })\n if (block.length > 0) trailingParts.push(block)\n }\n }\n if (trailingParts.length > 0) {\n out.push({ role: 'system', content: trailingParts.join('\\n\\n') })\n }\n }\n\n return { messages: out, reasoningPayloads }\n}\n/** Default native-history assembler; alias of {@link buildOllamaHistory}. */\nexport const defaultBuildOllamaHistory = buildOllamaHistory\n\n// suppress unused\nvoid isInstanceOf\n"],"mappings":"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"}
1
+ {"version":3,"file":"helpers.mjs","names":[],"sources":["../../../../src/batteries/llm/ollama/helpers.ts"],"sourcesContent":["/**\n * Swappable translation helpers for rendering ADK state into native Ollama `/api/chat` requests.\n *\n * @module @nhtio/adk/batteries/llm/ollama/helpers\n *\n * @remarks\n * The wire-shape-agnostic helpers (`renderUntrustedContent`, `renderMemories`,\n * `renderChatCompletionsSystemPrompt`, `toolsToChatCompletionsTools`, …) are shared with the OpenAI\n * battery via the internal `../chat_common/helpers` submodule and re-exported here under their\n * original names. Only the Ollama-WIRE-SPECIFIC helpers are defined here:\n * `renderOllamaTimelineMessage` (flat `content` + base64 `images[]` + `thinking`),\n * `renderOllamaToolCallResult` (string-only result content), `buildOllamaHistory` (synthetic\n * `assistant.tool_calls` with object-form `arguments` + `tool`-role messages labelled by\n * `tool_name`), and `ollamaToolsFromTools` (alias of the shared tool-definition renderer — native\n * `/api/chat` uses the same function-tool wire shape).\n *\n * Native `/api/chat` supports only base64 `images[]`; every non-image modality routes through the\n * `unsupportedMediaPolicy` fallback (stash text / synthetic description) or throws.\n */\n\nimport { Media } from '@nhtio/adk/common'\nimport { isInstanceOf } from '@nhtio/adk/guards'\nimport { E_OLLAMA_UNSUPPORTED_MEDIA_MODALITY } from './exceptions'\nimport {\n escapeXmlAttribute,\n memoryToAttrs,\n retrievableToAttrs,\n renderTrustedContent,\n renderUntrustedContent,\n toolsToChatCompletionsTools,\n} from '../chat_common/helpers'\nimport type { ChatHelpersCommon } from '../chat_common/types'\nimport type {\n OllamaMessage,\n OllamaTool,\n OllamaHelpers,\n MemoryAttrs,\n RetrievableAttrs,\n ChatCompletionsBucketOrder,\n UnsupportedMediaPolicy,\n} from './types'\nimport type {\n Tool,\n ArtifactTool,\n ToolRegistry,\n Tokenizable,\n Memory,\n Message,\n Thought,\n ToolCall,\n Retrievable,\n SpooledArtifact,\n MediaModalityHazard,\n MediaStashEntry,\n} from '@nhtio/adk/common'\n\n// ─── Re-exported wire-shape-agnostic helpers (shared submodule) ───────────────\nexport {\n descriptionToChatCompletionsJsonSchema,\n defaultDescriptionToChatCompletionsJsonSchema,\n renderUntrustedContent,\n defaultRenderUntrustedContent,\n renderTrustedContent,\n defaultRenderTrustedContent,\n renderStandingInstructions,\n defaultRenderStandingInstructions,\n renderMemories,\n defaultRenderMemories,\n renderRetrievableSafetyDirective,\n defaultRenderRetrievableSafetyDirective,\n renderFirstPartyRetrievables,\n defaultRenderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables,\n defaultRenderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables,\n defaultRenderThirdPartyPrivateRetrievables,\n renderRetrievables,\n defaultRenderRetrievables,\n renderThought,\n defaultRenderThought,\n filterThoughts,\n defaultFilterThoughts,\n toolsToChatCompletionsTools,\n defaultToolsToChatCompletionsTools,\n renderChatCompletionsSystemPrompt,\n defaultRenderChatCompletionsSystemPrompt,\n} from '../chat_common/helpers'\n\n// ─── ollamaToolsFromTools (alias — native tool wire == Chat Completions wire) ──\n\n/**\n * Convert ADK tools to the native Ollama `tools[]` wire. Native `/api/chat` uses the identical\n * `{ type: 'function', function: { name, description, parameters } }` shape as Chat Completions, so\n * this is an alias of the shared renderer.\n */\nexport const ollamaToolsFromTools = (\n tools: ReadonlyArray<Tool | ArtifactTool>,\n deps: Parameters<typeof toolsToChatCompletionsTools>[1]\n): OllamaTool[] => toolsToChatCompletionsTools(tools, deps)\n/** Default implementation of {@link OllamaHelpers}-style tool translation; alias of {@link ollamaToolsFromTools}. */\nexport const defaultOllamaToolsFromTools = ollamaToolsFromTools\n\n// ─── Media rendering (Ollama native — images only) ────────────────────────────\n\nconst DEFAULT_STASH_FALLBACK_KEYS: ReadonlyArray<string> = [\n 'text:transcript',\n 'text:caption',\n 'text:description',\n]\n\nconst modalityHazardToAttr = (h: MediaModalityHazard): 'inert' | 'extractable' | 'opaque' => {\n if (h === 'inert') return 'inert'\n if (h === 'extractable-instructions') return 'extractable'\n return 'opaque'\n}\n\nconst formatBytesHumanReadable = (bytes: number | undefined): string => {\n if (bytes === undefined || !Number.isFinite(bytes)) return 'unknown size'\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`\n}\n\nconst isMediaTextStashEntry = (e: unknown): e is MediaStashEntry => {\n if (!e || typeof e !== 'object') return false\n const r = e as Record<string, unknown>\n return typeof r.value === 'string' && typeof r.trustTier === 'string'\n}\n\nconst resolveFallbackStash = (\n media: Media,\n keys: ReadonlyArray<string>\n): { text: string; entryTier: MediaStashEntry['trustTier'] } | undefined => {\n for (const key of keys) {\n const entry = media.stash.get(key)\n if (isMediaTextStashEntry(entry)) {\n return { text: entry.value as string, entryTier: entry.trustTier }\n }\n }\n return undefined\n}\n\nconst renderTextInEnvelope = (\n text: string,\n args: {\n trustTier: MediaStashEntry['trustTier']\n modality: 'inert' | 'extractable' | 'opaque'\n nonce: string\n toolName: string | undefined\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n }\n): string => {\n if (args.trustTier === 'first-party') {\n return args.renderTrustedContent(text, {\n nonce: args.nonce,\n kind: 'media-fallback',\n tool: args.toolName,\n modality: args.modality,\n })\n }\n return args.renderUntrustedContent(text, {\n nonce: args.nonce,\n kind: 'media-fallback',\n tool: args.toolName,\n modality: args.modality,\n })\n}\n\nconst renderSyntheticMediaDescription = (media: Media, byteLen: number | undefined): string =>\n `[media: ${media.filename}, ${media.mimeType}, ${formatBytesHumanReadable(byteLen)}]`\n\n/**\n * Render a single {@link Media} for the native Ollama wire. Images become a base64 entry pushed to\n * the message's `images[]` array (returned via `image`); every other modality is unsupported and\n * routes through `unsupportedMediaPolicy` to a text envelope (returned via `text`) or throws.\n */\n/**\n * The inline media id-marker (cross-battery convention; see the OpenAI battery's\n * `renderMediaIdMarker`): structural reference text authored by the harness from the\n * harness-controlled `Media.id`, rendered alongside each media so the model can reference it\n * by id in tool calls. Carries no authority; renders outside the untrusted envelope.\n */\nconst renderMediaIdMarker = (media: Media): string => `[media id: ${media.id} | ${media.filename}]`\n\nconst renderMediaForOllama = async (input: {\n media: Media\n toolName: string | undefined\n nonce: string\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n warn?: (msg: string) => void\n}): Promise<{ image?: string; text?: string }> => {\n const { media, toolName, nonce, unsupportedMediaPolicy, warn } = input\n const modality = modalityHazardToAttr(media.modalityHazard)\n\n if (media.kind === 'image') {\n const b64 = await media.asBase64()\n return { image: b64 }\n }\n\n // Non-image modality — native /api/chat has no representation for it.\n const fallbackText = async (\n keys: ReadonlyArray<string>,\n allowSyntheticFallthrough: boolean\n ): Promise<{ text: string }> => {\n const fallback = resolveFallbackStash(media, keys)\n if (fallback) {\n return {\n text: renderTextInEnvelope(fallback.text, {\n trustTier: fallback.entryTier,\n modality,\n nonce,\n toolName,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n }),\n }\n }\n if (!allowSyntheticFallthrough) {\n warn?.(\n `unsupportedMediaPolicy='fallback-stash' for ${media.filename}: no matching stash entry — falling through to synthetic description.`\n )\n }\n const byteLen = await media.byteLength()\n return {\n text: renderTextInEnvelope(renderSyntheticMediaDescription(media, byteLen), {\n trustTier: media.trustTier,\n modality,\n nonce,\n toolName,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n }),\n }\n }\n\n if (unsupportedMediaPolicy === 'throw') {\n throw new E_OLLAMA_UNSUPPORTED_MEDIA_MODALITY([media.kind, media.mimeType, media.filename])\n }\n if (\n unsupportedMediaPolicy === 'fallback-stash' ||\n (typeof unsupportedMediaPolicy === 'object' && unsupportedMediaPolicy.mode === 'fallback-stash')\n ) {\n const keys =\n typeof unsupportedMediaPolicy === 'object'\n ? unsupportedMediaPolicy.stashKeys\n : DEFAULT_STASH_FALLBACK_KEYS\n return fallbackText(keys, false)\n }\n return fallbackText([], true)\n}\n\n// ─── renderOllamaTimelineMessage ──────────────────────────────────────────────\n\n/**\n * Renders a single timeline {@link @nhtio/adk!Message} into a native Ollama message — flattening any\n * media into the base64 `images[]` array, surfacing reasoning as `thinking`, and wrapping textual\n * bodies in the appropriate trust envelope.\n */\nexport const renderOllamaTimelineMessage = async (input: {\n message: Message\n selfIdentity: string\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n warn?: (msg: string) => void\n}): Promise<OllamaMessage> => {\n const { message, selfIdentity, unsupportedMediaPolicy, warn } = input\n const identifier =\n message.identity?.identifier !== undefined && message.identity?.identifier !== null\n ? String(message.identity.identifier)\n : ''\n const representationRaw =\n message.identity?.representation !== undefined && message.identity?.representation !== null\n ? message.identity.representation.toString()\n : ''\n const representation = representationRaw.length > 0 ? representationRaw : identifier\n const text = message.content !== undefined ? message.content.toString() : ''\n const createdAtStr = message.createdAt.toISO?.() ?? ''\n const createdAtAttr = createdAtStr ? ` createdAt=\"${escapeXmlAttribute(createdAtStr)}\"` : ''\n const attachments = message.attachments\n\n // Build the text envelope (same identity logic as the OpenAI battery — wire-agnostic).\n let envelopeText: string\n let role: 'user' | 'assistant'\n if (message.role === 'user') {\n role = 'user'\n if (identifier.length === 0) {\n envelopeText = text\n } else {\n const fromAttr = escapeXmlAttribute(representation)\n envelopeText = `<message_${message.id} from=\"${fromAttr}\" role=\"user\"${createdAtAttr}>\\n${text}\\n</message_${message.id}>`\n }\n } else {\n role = 'assistant'\n if (identifier.length === 0 || identifier === selfIdentity) {\n envelopeText = text\n } else {\n const fromAttr = escapeXmlAttribute(representation)\n envelopeText = `<peer_agent_output_${message.id} from=\"${fromAttr}\"${createdAtAttr}>\\n${text}\\n</peer_agent_output_${message.id}>`\n }\n }\n\n const images: string[] = []\n const extraTexts: string[] = []\n for (const media of attachments) {\n const rendered = await renderMediaForOllama({\n media,\n toolName: undefined,\n nonce: message.id,\n unsupportedMediaPolicy,\n renderTrustedContent,\n renderUntrustedContent,\n warn,\n })\n extraTexts.push(renderMediaIdMarker(media))\n if (rendered.image !== undefined) images.push(rendered.image)\n if (rendered.text !== undefined) extraTexts.push(rendered.text)\n }\n\n // Non-image fallbacks (text envelopes) are appended to the message content; images ride in the\n // separate native `images[]` field.\n const contentParts: string[] = []\n if (envelopeText.length > 0) contentParts.push(envelopeText)\n for (const t of extraTexts) contentParts.push(t)\n const out: OllamaMessage = { role, content: contentParts.join('\\n') }\n if (images.length > 0) out.images = images\n return out\n}\n/** Default timeline-message renderer; alias of {@link renderOllamaTimelineMessage}. */\nexport const defaultRenderOllamaTimelineMessage = renderOllamaTimelineMessage\n\n// ─── renderOllamaToolCallResult ───────────────────────────────────────────────\n\nconst looksLikeSpooledArtifact = (value: unknown): value is SpooledArtifact => {\n if (!value || typeof value !== 'object') return false\n const v = value as Record<string, unknown>\n return (\n typeof v.asString === 'function' &&\n typeof v.byteLength === 'function' &&\n typeof v.lineCount === 'function' &&\n typeof v.estimateTokens === 'function'\n )\n}\n\nconst renderArtifactHandleBody = (\n toolCall: ToolCall,\n artifact: SpooledArtifact,\n byteLength: number,\n lineCount: number\n): string => {\n const ctor = (\n artifact as unknown as {\n constructor: { toolMethods?: ReadonlyArray<{ name: string; description?: string }> }\n }\n ).constructor\n const methods = ctor?.toolMethods ?? []\n const lines: string[] = []\n lines.push(`This tool returned a large artifact that was not inlined to preserve context budget.`)\n lines.push(``)\n lines.push(`Artifact metadata:`)\n lines.push(`- callId: ${toolCall.id}`)\n lines.push(`- kind: ${ctor?.constructor?.name ?? 'SpooledArtifact'}`)\n lines.push(`- byteLength: ${byteLength}`)\n lines.push(`- lineCount: ${lineCount}`)\n lines.push(``)\n lines.push(`To read this artifact in this turn, call one of the following tools with`)\n lines.push(`callId=${toolCall.id}:`)\n for (const m of methods) {\n if (m.description) {\n lines.push(`- ${m.name} — ${m.description}`)\n } else {\n lines.push(`- ${m.name}`)\n }\n }\n lines.push(``)\n lines.push(\n `The artifact persists in this turn's context — multiple queries against the same callId are allowed and efficient. Do not assume the body has been inlined anywhere else.`\n )\n return lines.join('\\n')\n}\n\n/**\n * Render a tool-call result to native Ollama tool-message content (always a string). Media results\n * are routed through the internal media renderer: images cannot ride on a tool-role message's\n * `content`, so an image result is replaced with a short text marker (the image bytes are not\n * re-sent on a tool message); non-image media use the same fallback-text path as elsewhere.\n */\nexport const renderOllamaToolCallResult = async (input: {\n toolCall: ToolCall\n results: Tokenizable | SpooledArtifact | SpooledArtifact[] | Media | Media[]\n tool: Tool | ArtifactTool | undefined\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n warn?: (msg: string) => void\n}): Promise<string> => {\n const { toolCall, results, tool, warn, unsupportedMediaPolicy } = input\n const isTrusted =\n tool !== null && tool !== undefined && (tool as { trusted?: boolean }).trusted === true\n\n if (tool === undefined) {\n warn?.(\n `Tool \"${toolCall.tool}\" is not present in the bound tool registry at render time; defaulting to untrusted envelope.`\n )\n }\n\n // Media silo — bypasses Tool.trusted (Trust-Is-Content rule).\n const isMediaResult = Media.isMedia(results)\n const isMediaArrayResult =\n Array.isArray(results) && results.length > 0 && results.every((r) => Media.isMedia(r))\n if (isMediaResult || isMediaArrayResult) {\n const mediaList = isMediaResult ? [results as Media] : (results as Media[])\n const parts: string[] = []\n for (const media of mediaList) {\n const rendered = await renderMediaForOllama({\n media,\n toolName: toolCall.tool,\n nonce: toolCall.checksum,\n unsupportedMediaPolicy,\n renderTrustedContent: input.renderTrustedContent,\n renderUntrustedContent: input.renderUntrustedContent,\n warn,\n })\n parts.push(renderMediaIdMarker(media))\n if (rendered.text !== undefined) {\n parts.push(rendered.text)\n } else {\n // An image tool-result cannot be carried on a tool-role message's string content; emit a\n // text marker in its place so the model knows an image was produced.\n const byteLen = await media.byteLength()\n parts.push(\n input.renderUntrustedContent(renderSyntheticMediaDescription(media, byteLen), {\n nonce: toolCall.checksum,\n kind: 'tool-result-image',\n tool: toolCall.tool,\n modality: modalityHazardToAttr(media.modalityHazard),\n })\n )\n }\n }\n return parts.join('\\n')\n }\n\n // SpooledArtifact[] silo.\n if (Array.isArray(results)) {\n const parts: string[] = []\n for (const a of results) {\n parts.push(await (a as SpooledArtifact).asString())\n }\n const joined = parts.join('\\n\\n')\n return isTrusted\n ? input.renderTrustedContent(joined, {\n nonce: toolCall.checksum,\n kind: 'trusted-tool-result',\n tool: toolCall.tool,\n })\n : input.renderUntrustedContent(joined, {\n nonce: toolCall.checksum,\n kind: 'tool-result',\n tool: toolCall.tool,\n })\n }\n\n const isSpooled = looksLikeSpooledArtifact(results)\n\n // Handle-pattern branch: spooled + inline=false → always untrusted (queryable-data).\n if (isSpooled && toolCall.inline === false) {\n const artifact = results as SpooledArtifact\n let byteLength = 0\n let lineCount = 0\n try {\n byteLength = await artifact.byteLength()\n } catch {\n byteLength = 0\n }\n try {\n lineCount = await artifact.lineCount()\n } catch {\n lineCount = 0\n }\n const body = renderArtifactHandleBody(toolCall, artifact, byteLength, lineCount)\n return input.renderUntrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'artifact-handle',\n tool: toolCall.tool,\n })\n }\n\n if (!isSpooled && toolCall.inline === false) {\n warn?.(\n `Tool call ${toolCall.id} has inline=false but results is a Tokenizable (not a SpooledArtifact); rendering inline anyway.`\n )\n }\n\n const body = isSpooled\n ? await (results as SpooledArtifact).asString()\n : (results as Tokenizable).toString()\n\n return isTrusted\n ? input.renderTrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'trusted-tool-result',\n tool: toolCall.tool,\n })\n : input.renderUntrustedContent(body, {\n nonce: toolCall.checksum,\n kind: 'tool-result',\n tool: toolCall.tool,\n })\n}\n/** Default tool-call-result renderer; alias of {@link renderOllamaToolCallResult}. */\nexport const defaultRenderOllamaToolCallResult = renderOllamaToolCallResult\n\n// ─── buildOllamaHistory ───────────────────────────────────────────────────────\n\ntype TimelineItem =\n | { kind: 'message'; createdAt: number; value: Message }\n | { kind: 'thought'; createdAt: number; value: Thought }\n | { kind: 'toolCall'; createdAt: number; value: ToolCall }\n\n/**\n * Assembles the complete native Ollama message history for a dispatch — system prompt and content\n * buckets, the interleaved timeline of messages/thoughts/tool calls, and the collected opaque\n * reasoning payloads — by delegating to the injected sub-renderers.\n */\nexport const buildOllamaHistory = async (input: {\n systemPrompt: Tokenizable\n standingInstructions: Iterable<Tokenizable>\n memories: Iterable<Memory>\n retrievables: Iterable<Retrievable>\n messages: Iterable<Message>\n thoughts: Iterable<Thought>\n toolCalls: Iterable<ToolCall>\n tools: ToolRegistry\n renderedToolCallResults: Map<string, string>\n bucketOrder: ChatCompletionsBucketOrder\n selfIdentity: string\n thoughtSurfacing: 'all-self' | 'latest-self' | 'all'\n replayCompatibility: ReadonlyArray<string>\n unsupportedMediaPolicy: UnsupportedMediaPolicy\n renderOllamaToolCallResult: OllamaHelpers['renderOllamaToolCallResult']\n renderChatCompletionsSystemPrompt: ChatHelpersCommon['renderChatCompletionsSystemPrompt']\n renderStandingInstructions: ChatHelpersCommon['renderStandingInstructions']\n renderMemories: ChatHelpersCommon['renderMemories']\n renderRetrievables: ChatHelpersCommon['renderRetrievables']\n renderRetrievableSafetyDirective: ChatHelpersCommon['renderRetrievableSafetyDirective']\n renderFirstPartyRetrievables: ChatHelpersCommon['renderFirstPartyRetrievables']\n renderThirdPartyPublicRetrievables: ChatHelpersCommon['renderThirdPartyPublicRetrievables']\n renderThirdPartyPrivateRetrievables: ChatHelpersCommon['renderThirdPartyPrivateRetrievables']\n renderOllamaTimelineMessage: OllamaHelpers['renderOllamaTimelineMessage']\n renderThought: ChatHelpersCommon['renderThought']\n filterThoughts: ChatHelpersCommon['filterThoughts']\n renderUntrustedContent: ChatHelpersCommon['renderUntrustedContent']\n renderTrustedContent: ChatHelpersCommon['renderTrustedContent']\n warn?: (msg: string) => void\n}): Promise<{\n messages: OllamaMessage[]\n reasoningPayloads: Array<{ id: string; replayCompatibility: string; payload: unknown }>\n}> => {\n const out: OllamaMessage[] = []\n const reasoningPayloads: Array<{ id: string; replayCompatibility: string; payload: unknown }> = []\n\n const buckets = input.bucketOrder\n const timelineIdx = buckets.indexOf('timeline')\n\n const leadingSystem = await input.renderChatCompletionsSystemPrompt({\n systemPrompt: input.systemPrompt,\n standingInstructions: input.standingInstructions,\n memories: input.memories,\n retrievables: input.retrievables,\n bucketOrder: buckets,\n renderStandingInstructions: input.renderStandingInstructions,\n renderMemories: input.renderMemories,\n renderRetrievables: input.renderRetrievables,\n renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n renderUntrustedContent: input.renderUntrustedContent,\n })\n if (leadingSystem.length > 0) {\n out.push({ role: 'system', content: leadingSystem })\n }\n\n const includesTimeline = timelineIdx !== -1\n if (includesTimeline) {\n const survivingThoughts = input.filterThoughts(\n input.thoughts,\n input.thoughtSurfacing,\n input.selfIdentity,\n input.replayCompatibility\n )\n\n const items: TimelineItem[] = []\n for (const m of input.messages) {\n items.push({ kind: 'message', createdAt: m.createdAt.toMillis(), value: m })\n }\n for (const t of survivingThoughts) {\n items.push({ kind: 'thought', createdAt: t.createdAt.toMillis(), value: t })\n }\n for (const tc of input.toolCalls) {\n items.push({ kind: 'toolCall', createdAt: tc.createdAt.toMillis(), value: tc })\n }\n items.sort((a, b) => a.createdAt - b.createdAt)\n\n const replaySet = new Set<string>([...input.replayCompatibility])\n\n for (const item of items) {\n if (item.kind === 'message') {\n out.push(\n await input.renderOllamaTimelineMessage({\n message: item.value,\n selfIdentity: input.selfIdentity,\n unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n warn: input.warn,\n })\n )\n } else if (item.kind === 'thought') {\n const t = item.value\n const identifier = String(t.identity?.identifier ?? '')\n const isSelf = identifier === input.selfIdentity\n const hasPayload = t.payload !== undefined\n const compatTag = t.replayCompatibility\n\n if (hasPayload && compatTag && replaySet.has(compatTag)) {\n reasoningPayloads.push({ id: t.id, replayCompatibility: compatTag, payload: t.payload })\n const envelope = input.renderThought(\n t.content.toString(),\n {\n nonce: t.id,\n kind: 'opaque-reasoning',\n from: identifier,\n createdAt: t.createdAt?.toISO?.() ?? undefined,\n replayCompatibility: compatTag,\n },\n t.payload\n )\n out.push({ role: 'assistant', content: envelope })\n } else if (!hasPayload) {\n const envelope = input.renderThought(t.content.toString(), {\n nonce: t.id,\n kind: isSelf ? 'self-reasoning' : 'peer-reasoning',\n from: identifier,\n createdAt: t.createdAt?.toISO?.() ?? undefined,\n })\n out.push({ role: 'assistant', content: envelope })\n }\n // else: opaque, non-matching → elided.\n } else {\n // tool call: synthetic assistant message carrying tool_calls[] (object-form arguments),\n // followed by a tool-role message labelled by `tool_name` (NOT tool_call_id).\n const tc = item.value\n const args =\n tc.args !== null && typeof tc.args === 'object' && !Array.isArray(tc.args)\n ? (tc.args as Record<string, unknown>)\n : {}\n out.push({\n role: 'assistant',\n content: '',\n tool_calls: [{ function: { name: tc.tool, arguments: args } }],\n })\n\n let rendered = input.renderedToolCallResults.get(tc.id)\n if (rendered === undefined) {\n const tool = input.tools.get?.(tc.tool)\n rendered = await input.renderOllamaToolCallResult({\n toolCall: tc,\n results: tc.results as\n | Tokenizable\n | SpooledArtifact\n | SpooledArtifact[]\n | Media\n | Media[],\n tool: tool as Tool | ArtifactTool | undefined,\n renderUntrustedContent: input.renderUntrustedContent,\n renderTrustedContent: input.renderTrustedContent,\n unsupportedMediaPolicy: input.unsupportedMediaPolicy,\n warn: input.warn,\n })\n }\n out.push({ role: 'tool', content: rendered, tool_name: tc.tool })\n }\n }\n }\n\n if (includesTimeline) {\n const trailingParts: string[] = []\n for (let i = timelineIdx + 1; i < buckets.length; i++) {\n const label = buckets[i]!\n if (label === 'standingInstructions') {\n const block = input.renderStandingInstructions(input.standingInstructions)\n if (block.length > 0) trailingParts.push(block)\n } else if (label === 'memories') {\n const wrapped: Array<{ memory: Memory; attrs: MemoryAttrs }> = []\n for (const m of input.memories) {\n wrapped.push(memoryToAttrs(m))\n }\n const block = input.renderMemories(wrapped)\n if (block.length > 0) trailingParts.push(block)\n } else if (label === 'retrievables') {\n const wrapped: Array<{ retrievable: Retrievable; attrs: RetrievableAttrs }> = []\n for (const r of input.retrievables) {\n wrapped.push(retrievableToAttrs(r))\n }\n const block = await input.renderRetrievables(wrapped, {\n renderRetrievableSafetyDirective: input.renderRetrievableSafetyDirective,\n renderFirstPartyRetrievables: input.renderFirstPartyRetrievables,\n renderThirdPartyPublicRetrievables: input.renderThirdPartyPublicRetrievables,\n renderThirdPartyPrivateRetrievables: input.renderThirdPartyPrivateRetrievables,\n renderUntrustedContent: input.renderUntrustedContent,\n })\n if (block.length > 0) trailingParts.push(block)\n }\n }\n if (trailingParts.length > 0) {\n out.push({ role: 'system', content: trailingParts.join('\\n\\n') })\n }\n }\n\n return { messages: out, reasoningPayloads }\n}\n/** Default native-history assembler; alias of {@link buildOllamaHistory}. */\nexport const defaultBuildOllamaHistory = buildOllamaHistory\n\n// suppress unused\nvoid isInstanceOf\n"],"mappings":"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"}