@proveanything/smartlinks 2.0.9 → 2.0.11

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.
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 2.0.9 | Generated: 2026-09-21T16:23:55.650Z
3
+ Version: 2.0.11 | Generated: 2026-09-21T19:28:09.956Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -580,6 +580,11 @@ interface ResponsesRequest {
580
580
  max_concurrent_subagents?: number
581
581
  }
582
582
  service_tier?: 'auto' | 'standard' | 'flex' | 'priority'
583
+ server_tools?: boolean | AiToolName[]
584
+ allowCapabilities?: AiToolCapability[]
585
+ only?: AiToolName[]
586
+ exclude?: AiToolName[]
587
+ maxSteps?: number
583
588
  }
584
589
  ```
585
590
 
@@ -604,6 +609,7 @@ interface ResponsesResult {
604
609
  conversation?: unknown
605
610
  provider: 'openai'
606
611
  responseTime: number
612
+ _agent?: ResponsesAgentTrace
607
613
  }
608
614
  ```
609
615
 
@@ -1010,14 +1016,98 @@ interface AISearchPhotosRequest {
1010
1016
  **AISearchPhotosPhoto** (interface)
1011
1017
  ```typescript
1012
1018
  interface AISearchPhotosPhoto {
1019
+ id?: string
1013
1020
  url: string
1021
+ thumb?: string
1014
1022
  alt?: string
1023
+ width?: number
1024
+ height?: number
1015
1025
  photographer?: string
1016
1026
  photographerUrl?: string
1017
1027
  [key: string]: any
1018
1028
  }
1019
1029
  ```
1020
1030
 
1031
+ **AISearchPhotosResponse** (interface)
1032
+ ```typescript
1033
+ interface AISearchPhotosResponse {
1034
+ provider: string
1035
+ results: AISearchPhotosPhoto[]
1036
+ total?: number
1037
+ total_pages?: number
1038
+ [key: string]: any
1039
+ }
1040
+ ```
1041
+
1042
+ **AIGeneratedImage** (interface)
1043
+ ```typescript
1044
+ interface AIGeneratedImage {
1045
+ url: string | null
1046
+ b64_json: string | null
1047
+ revised_prompt?: string
1048
+ [key: string]: any
1049
+ }
1050
+ ```
1051
+
1052
+ **AIGenerateImageResponse** (interface)
1053
+ ```typescript
1054
+ interface AIGenerateImageResponse {
1055
+ provider: string
1056
+ model?: string
1057
+ images: AIGeneratedImage[]
1058
+ [key: string]: any
1059
+ }
1060
+ ```
1061
+
1062
+ **AIGenerateContentCandidate** (interface)
1063
+ ```typescript
1064
+ interface AIGenerateContentCandidate {
1065
+ content?: { parts?: Array<{ text?: string; [k: string]: any }>; role?: string; [k: string]: any }
1066
+ finishReason?: string
1067
+ [key: string]: any
1068
+ }
1069
+ ```
1070
+
1071
+ **AIGenerateContentResponse** (interface)
1072
+ ```typescript
1073
+ interface AIGenerateContentResponse {
1074
+ provider?: string
1075
+ model?: string
1076
+ candidates?: AIGenerateContentCandidate[]
1077
+ usageMetadata?: {
1078
+ promptTokenCount?: number
1079
+ candidatesTokenCount?: number
1080
+ totalTokenCount?: number
1081
+ [k: string]: any
1082
+ }
1083
+ responseTime?: number
1084
+ [key: string]: any
1085
+ }
1086
+ ```
1087
+
1088
+ **AIUploadedFile** (interface)
1089
+ ```typescript
1090
+ interface AIUploadedFile {
1091
+ name?: string
1092
+ uri?: string
1093
+ url?: string
1094
+ mimeType?: string
1095
+ sizeBytes?: number | string
1096
+ state?: string
1097
+ [key: string]: any
1098
+ }
1099
+ ```
1100
+
1101
+ **AICacheRef** (interface)
1102
+ ```typescript
1103
+ interface AICacheRef {
1104
+ name?: string
1105
+ model?: string
1106
+ expireTime?: string
1107
+ [key: string]: any
1108
+ }
1109
+ ```
1110
+
1021
1111
  **AgentRunRequest** (interface)
1022
1112
  ```typescript
1023
1113
  interface AgentRunRequest {
@@ -1104,6 +1194,258 @@ interface CatalogResponse {
1104
1194
  }
1105
1195
  ```
1106
1196
 
1197
+ **WebFetchPageArgs** (interface)
1198
+ ```typescript
1199
+ interface WebFetchPageArgs {
1200
+ url: string; type?: string; forceRefresh?: boolean
1201
+ }
1202
+ ```
1203
+
1204
+ **WebExtractSchemaArgs** (interface)
1205
+ ```typescript
1206
+ interface WebExtractSchemaArgs {
1207
+ url: string; schemaType?: string; forceRefresh?: boolean
1208
+ }
1209
+ ```
1210
+
1211
+ **WebScreenshotArgs** (interface)
1212
+ ```typescript
1213
+ interface WebScreenshotArgs {
1214
+ url: string
1215
+ }
1216
+ ```
1217
+
1218
+ **WebSearchArgs** (interface)
1219
+ ```typescript
1220
+ interface WebSearchArgs {
1221
+ query: string; limit?: number; scrapeContent?: boolean
1222
+ }
1223
+ ```
1224
+
1225
+ **BrandAssetsArgs** (interface)
1226
+ ```typescript
1227
+ interface BrandAssetsArgs {
1228
+ url: string
1229
+ }
1230
+ ```
1231
+
1232
+ **DocumentReadArgs** (interface)
1233
+ ```typescript
1234
+ interface DocumentReadArgs {
1235
+ url: string; forceRefresh?: boolean
1236
+ }
1237
+ ```
1238
+
1239
+ **DataExtractArgs** (interface)
1240
+ ```typescript
1241
+ interface DataExtractArgs {
1242
+ url: string; schema?: Record<string, any>; prompt?: string
1243
+ }
1244
+ ```
1245
+
1246
+ **ImageDescribeArgs** (interface)
1247
+ ```typescript
1248
+ interface ImageDescribeArgs {
1249
+ imageUrl: string; prompt?: string
1250
+ }
1251
+ ```
1252
+
1253
+ **ImageGenerateArgs** (interface)
1254
+ ```typescript
1255
+ interface ImageGenerateArgs {
1256
+ prompt: string; size?: string; provider?: 'openai' | 'gemini'
1257
+ }
1258
+ ```
1259
+
1260
+ **ImageFromReferenceArgs** (interface)
1261
+ ```typescript
1262
+ interface ImageFromReferenceArgs {
1263
+ prompt: string; imageUrls: string[]; size?: string; model?: string
1264
+ }
1265
+ ```
1266
+
1267
+ **ImageSearchStockArgs** (interface)
1268
+ ```typescript
1269
+ interface ImageSearchStockArgs {
1270
+ query: string; per_page?: number; orientation?: 'landscape' | 'portrait' | 'squarish'
1271
+ }
1272
+ ```
1273
+
1274
+ **ImageTransformArgs** (interface)
1275
+ ```typescript
1276
+ interface ImageTransformArgs {
1277
+ imageUrl: string
1278
+ resize?: { width?: number; height?: number; fit?: 'cover' | 'contain' | 'fill' | 'inside' | 'outside'; allowUpscale?: boolean }
1279
+ crop?: { left: number; top: number; width: number; height: number }
1280
+ rotate?: number
1281
+ flip?: boolean
1282
+ flop?: boolean
1283
+ grayscale?: boolean
1284
+ tint?: string
1285
+ modulate?: { brightness?: number; saturation?: number; hue?: number; lightness?: number }
1286
+ format?: 'jpeg' | 'png' | 'webp' | 'avif'
1287
+ quality?: number
1288
+ }
1289
+ ```
1290
+
1291
+ **PdfCreateArgs** (interface)
1292
+ ```typescript
1293
+ interface PdfCreateArgs {
1294
+ html: string; format?: string; landscape?: boolean
1295
+ }
1296
+ ```
1297
+
1298
+ **PdfFillArgs** (interface)
1299
+ ```typescript
1300
+ interface PdfFillArgs {
1301
+ url: string; fields: Record<string, string | number | boolean>; flatten?: boolean
1302
+ }
1303
+ ```
1304
+
1305
+ **PdfMergeArgs** (interface)
1306
+ ```typescript
1307
+ interface PdfMergeArgs {
1308
+ urls: string[]
1309
+ }
1310
+ ```
1311
+
1312
+ **HttpRequestArgs** (interface)
1313
+ ```typescript
1314
+ interface HttpRequestArgs {
1315
+ url: string; method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD'; headers?: Record<string, string>; body?: any
1316
+ }
1317
+ ```
1318
+
1319
+ **TranslateArgs** (interface)
1320
+ ```typescript
1321
+ interface TranslateArgs {
1322
+ text: string; targetLanguages: string[]; sourceLanguage?: string
1323
+ }
1324
+ ```
1325
+
1326
+ **AiToolArgsMap** (interface)
1327
+ ```typescript
1328
+ interface AiToolArgsMap {
1329
+ 'web.fetchPage': WebFetchPageArgs
1330
+ 'web.extractSchema': WebExtractSchemaArgs
1331
+ 'web.screenshot': WebScreenshotArgs
1332
+ 'web.search': WebSearchArgs
1333
+ 'brand.assets': BrandAssetsArgs
1334
+ 'document.read': DocumentReadArgs
1335
+ 'data.extract': DataExtractArgs
1336
+ 'image.describe': ImageDescribeArgs
1337
+ 'image.generate': ImageGenerateArgs
1338
+ 'image.fromReference': ImageFromReferenceArgs
1339
+ 'image.searchStock': ImageSearchStockArgs
1340
+ 'image.transform': ImageTransformArgs
1341
+ 'pdf.create': PdfCreateArgs
1342
+ 'pdf.fill': PdfFillArgs
1343
+ 'pdf.merge': PdfMergeArgs
1344
+ 'http.request': HttpRequestArgs
1345
+ 'translate': TranslateArgs
1346
+ }
1347
+ ```
1348
+
1349
+ **WebSearchResultItem** (interface)
1350
+ ```typescript
1351
+ interface WebSearchResultItem {
1352
+ url: string | null; title: string | null; description: string | null; markdown?: string
1353
+ }
1354
+ ```
1355
+
1356
+ **WebSearchResult** (interface)
1357
+ ```typescript
1358
+ interface WebSearchResult {
1359
+ query: string; results: WebSearchResultItem[]
1360
+ }
1361
+ ```
1362
+
1363
+ **DocumentReadResult** (interface)
1364
+ ```typescript
1365
+ interface DocumentReadResult {
1366
+ url: string; text: string | null; metadata?: any; provider?: string; cached?: boolean
1367
+ }
1368
+ ```
1369
+
1370
+ **DataExtractResult** (interface)
1371
+ ```typescript
1372
+ interface DataExtractResult {
1373
+ url: string; data: Record<string, any>
1374
+ }
1375
+ ```
1376
+
1377
+ **WebFetchPageResult** (interface)
1378
+ ```typescript
1379
+ interface WebFetchPageResult {
1380
+ url: string; markdown?: string | null; html?: string | null; metadata?: any; schemas?: any[]; provider?: string; cached?: boolean; status?: number | null
1381
+ }
1382
+ ```
1383
+
1384
+ **ImageDescribeResult** (interface)
1385
+ ```typescript
1386
+ interface ImageDescribeResult {
1387
+ imageUrl: string; text: string | null
1388
+ }
1389
+ ```
1390
+
1391
+ **HostedAssetResult** (interface)
1392
+ ```typescript
1393
+ interface HostedAssetResult {
1394
+ hostedUrl: string | null; contentType?: string; info?: { width?: number; height?: number; format?: string; size?: number }
1395
+ }
1396
+ ```
1397
+
1398
+ **HttpRequestResult** (interface)
1399
+ ```typescript
1400
+ interface HttpRequestResult {
1401
+ status: number; headers: Record<string, any>; body: any; truncated: boolean; finalUrl: string
1402
+ }
1403
+ ```
1404
+
1405
+ **TranslateResult** (interface)
1406
+ ```typescript
1407
+ interface TranslateResult {
1408
+ translations: Record<string, string>; sourceLanguage: string
1409
+ }
1410
+ ```
1411
+
1412
+ **ResponsesAgentTrace** (interface)
1413
+ ```typescript
1414
+ interface ResponsesAgentTrace {
1415
+ steps: number
1416
+ maxStepsReached: boolean
1417
+ toolResults: AgentToolResult[]
1418
+ availableTools: string[]
1419
+ }
1420
+ ```
1421
+
1422
+ **AgentToolCallEvent** (interface)
1423
+ ```typescript
1424
+ interface AgentToolCallEvent {
1425
+ type: 'agent.tool_call'; name: string; args: Record<string, any>
1426
+ }
1427
+ ```
1428
+
1429
+ **AgentToolResultEvent** (interface)
1430
+ ```typescript
1431
+ interface AgentToolResultEvent {
1432
+ type: 'agent.tool_result'; name: string; isError: boolean; result: any
1433
+ }
1434
+ ```
1435
+
1436
+ **AgentResponseCompletedEvent** (interface)
1437
+ ```typescript
1438
+ interface AgentResponseCompletedEvent {
1439
+ type: 'response.completed'; response: ResponsesResult; _agent: ResponsesAgentTrace
1440
+ }
1441
+ ```
1442
+
1443
+ **AiToolCapability** = ``
1444
+
1445
+ **AiToolName** = ``
1446
+
1447
+ **AgentStreamEvent** = ``
1448
+
1107
1449
  ### analytics
1108
1450
 
1109
1451
  **AnalyticsLocation** (interface)
@@ -81,12 +81,21 @@ Identical to server functions — nothing new to reason about:
81
81
  Untrusted third-party tools run in the platform's isolated runner — the same boundary as untrusted
82
82
  server functions.
83
83
 
84
- ## Replacing `app.admin.json` AI setup
84
+ ## Working with `app.admin.json` (complement, not replacement)
85
85
 
86
- This supersedes the `app.admin.json` "AI setup" schema-extraction model (the outer agent reading a
87
- schema and handing back JSON blobs). Instead the app owns its domain logic and exposes **real,
88
- capability-scoped actions** the agent invokes — with multi-turn and streaming. The AI-schema path is
89
- **deprecated as of V2** (still works through the V2 line; removed later).
86
+ `app.admin.json` stays the **canonical declarative config contract** — setup questions, config schema,
87
+ import fields, tunable settings, content hints. It's inspectable, validatable, deterministic, and
88
+ reused by many consumers at once (the admin form renderer, AI setup, a signup journey asking the same
89
+ questions, bulk import). Agent tools **do not replace it — they serve and adapt it**:
90
+
91
+ - Keep the declarative schema as the default and source of truth.
92
+ - When you want *dynamic, contextual* behaviour — "which questions for **this** collection?", "the
93
+ config schema as it stands right now", "apply these answers" — expose a small function/tool that
94
+ reads the declaration and returns a tailored result. **Static-first; dynamic only where it earns its
95
+ keep.**
96
+
97
+ There's no rip-and-replace and nothing to migrate off: an app happy with its `app.admin.json` keeps
98
+ it untouched.
90
99
 
91
100
  ## What ships now vs staged
92
101
 
@@ -96,16 +105,19 @@ capability-scoped actions** the agent invokes — with multi-turn and streaming.
96
105
  | SDK types for it; tool descriptors surfaced for discovery | `tools/call` streaming, cancellation, cross-app toolbelt arbitration |
97
106
  | Your handlers run today via http/event | Human-approval UX for `approval: "require"` |
98
107
 
99
- ## Adopting this in an existing app
108
+ ## Adopting this — opt-in, per app, no fleet migration
109
+
110
+ Agent tools are **purely additive**. There is **no migration pass**, and nothing breaks if you never
111
+ adopt them — an existing app on the V2 SDK simply *gains the ability* to add them whenever you want.
112
+ You do **not** touch every app; you turn it on for one app at a time.
100
113
 
101
- Do it in order — each step is a drop-in migration prompt (see the migration steps that ship with the
102
- SDK). Roughly:
114
+ To turn them on for a single app (say, an FAQ app), once it's on the V2 SDK:
103
115
 
104
- 1. **Server functions** — add the `functions` block + build target + test harness (if the app
105
- doesn't have them). See [server-functions.md](server-functions.md).
116
+ 1. **Server functions** — add the `functions` block + build target + test harness if the app doesn't
117
+ already have them. See [server-functions.md](server-functions.md).
106
118
  2. **Expose tools** — add the `agent` block to the functions you want the agent to call; give each a
107
- title/description/input schema and an approval mode.
108
- 3. **Retire `app.admin.json` AI setup** — move any AI-authoring behaviour to tools; drop the
109
- AI-schema block.
119
+ title / description / input schema and an approval mode.
110
120
 
111
- Steps 1–2 are safe to ship now; step 3 as you migrate each app off the old AI path.
121
+ That's it — declare and build. The live agent loop is staged (see the table above); until it ships,
122
+ your handlers still run via http/event, so declaring tools now is **forward-compatible, not
123
+ speculative breakage**. `app.admin.json` stays as-is throughout — nothing to retire.
package/docs/ai.md CHANGED
@@ -257,6 +257,85 @@ const response = await ai.chat.responses.create('my-collection', {
257
257
  console.log(response.output);
258
258
  ```
259
259
 
260
+ ### Server-side tools (built-in agent loop)
261
+
262
+ The example above is **client-relayed** tool calling: you define the tools, the model returns
263
+ `tool_call` requests, and *your app* executes them and sends results back. For the common tools —
264
+ reading and searching the web, vision, reading documents, generating images — the platform ships a
265
+ curated, tested **built-in toolset it runs itself**. Opt in with `server_tools` and the server
266
+ executes each tool and feeds the result back automatically, looping until the model has its answer.
267
+ You get one final response; no relay code.
268
+
269
+ ```typescript
270
+ // Enable the whole built-in toolset:
271
+ const res = await ai.chat.responses.create('my-collection', {
272
+ model: 'balanced',
273
+ input: 'Research acme.com and summarise what they sell, with their brand colours.',
274
+ server_tools: true
275
+ });
276
+ console.log(res.output_text);
277
+ console.log(res._agent.toolResults); // trace: which tools ran, with what result
278
+ ```
279
+
280
+ Scope it to specific tools (recommended — smaller blast radius, faster), by name or capability:
281
+
282
+ ```typescript
283
+ import { AI_TOOL_NAMES } from '@proveanything/smartlinks';
284
+
285
+ const res = await ai.chat.responses.create('my-collection', {
286
+ input: 'Find the current price of this product and return it as JSON.',
287
+ server_tools: [AI_TOOL_NAMES.WEB_SEARCH, AI_TOOL_NAMES.DATA_EXTRACT],
288
+ // or: allowCapabilities: ['web:read'], exclude: ['image.generate'],
289
+ maxSteps: 6 // cap model round-trips (1–12, default 8)
290
+ });
291
+ ```
292
+
293
+ **Streaming** surfaces tool progress as it happens — ideal for a "thinking…" UI. You get
294
+ `agent.tool_call` / `agent.tool_result` events, then a final `response.completed`:
295
+
296
+ ```typescript
297
+ const stream = await ai.chat.responses.create('my-collection', {
298
+ input: 'Research acme.com', server_tools: true, stream: true
299
+ });
300
+ for await (const ev of stream) {
301
+ if (ev.type === 'agent.tool_call') showStep(`Running ${ev.name}…`);
302
+ if (ev.type === 'agent.tool_result') showStep(`${ev.name} done`);
303
+ if (ev.type === 'response.completed') render(ev.response.output_text);
304
+ }
305
+ ```
306
+
307
+ `server_tools` can't be combined with `previous_response_id`/`conversation` yet — pass prior turns
308
+ in `input`.
309
+
310
+ #### Built-in tools
311
+
312
+ | Tool | Does |
313
+ |------|------|
314
+ | `web.search` | Live web search → candidate results (url/title/description). |
315
+ | `web.fetchPage` | Fetch a page → clean markdown + metadata + schema.org JSON-LD. |
316
+ | `web.extractSchema` | Return only a page's schema.org data of a given `@type` (deterministic). |
317
+ | `document.read` | Read a document at a URL — **PDF, deck, doc**, or article — into markdown. |
318
+ | `data.extract` | Page + JSON-schema/prompt → **typed JSON** (turn a page into UI data). |
319
+ | `brand.assets` | Extract a site's logo, colours, and design. |
320
+ | `web.screenshot` | Screenshot a page → hosted image URL (feed to `image.describe`). |
321
+ | `image.describe` | Vision: describe an image / read its text. |
322
+ | `image.generate` | Generate an image from a prompt → hosted URL. |
323
+ | `image.fromReference` | Image-to-image: generate guided by reference image(s). |
324
+ | `image.searchStock` | Search real stock photos (Unsplash). |
325
+ | `image.transform` | Resize / crop / rotate / grayscale / format-convert / compress → hosted URL. |
326
+ | `pdf.create` | Render HTML → PDF → hosted URL. |
327
+ | `pdf.fill` | Fill an AcroForm PDF's fields → hosted URL. |
328
+ | `pdf.merge` | Merge several PDFs into one → hosted URL. |
329
+ | `http.request` | SSRF-guarded outbound HTTP(S) to a public URL (call a REST API). |
330
+ | `translate` | Translate text into one or more languages (generic, model-based). |
331
+
332
+ Discover tools two ways:
333
+ - **Design time (typed):** import `BUILTIN_AI_TOOLS`, `AI_TOOL_NAMES`, and the per-tool arg types
334
+ (`WebSearchArgs`, `DataExtractArgs`, …) from the SDK. This is the core set — stable, versioned,
335
+ documented here.
336
+ - **Runtime (live):** `await ai.catalog(collectionId)` returns the registry as the server sees it,
337
+ including any future app-contributed tools. The built-in set above is always present.
338
+
260
339
  ### Recommended Models
261
340
 
262
341
  For agentic workflows on `v1/responses`, GPT-5.6 ships in three tiers. Pass either the full model
@@ -42,7 +42,7 @@ The manifest is loaded automatically by the platform for every collection page.
42
42
  "version": "1.2.0",
43
43
  "platformRevision": "R5",
44
44
  "moduleFormat": "dual",
45
- "sharedDependencies": "v5"
45
+ "sharedDependencies": "v6"
46
46
  },
47
47
 
48
48
  "admin": "app.admin.json",
@@ -148,7 +148,7 @@ The manifest is loaded automatically by the platform for every collection page.
148
148
  | `version` | string | ✅ | SemVer string, e.g. `"1.2.0"` |
149
149
  | `platformRevision` | string | ❌ | Platform revision tag this build targets, e.g. `"R5"` (see [host-dependency-contract.md](host-dependency-contract.md)) |
150
150
  | `moduleFormat` | `"umd"` \| `"esm"` \| `"dual"` | ❌ | How the host loads this app's bundles. Absent = `"umd"`. See [Module format](#module-format-umd-vs-esm) below. |
151
- | `sharedDependencies` | string | ❌ | Shared-dependency contract version the bundle was built against, e.g. `"v5"`. Used by the host to pick a compatible ESM import map. |
151
+ | `sharedDependencies` | string | ❌ | Shared-dependency contract version the bundle was built against, e.g. `"v6"`. Used by the host to pick a compatible ESM import map. |
152
152
  | `globals` | object | ❌ | Per-app namespaced UMD globals (R4.7+), e.g. `{ "widgets": "MyAppWidgets" }`. UMD-only; ESM bundles don't need it. |
153
153
  | `seo.priority` | number | ❌ | Controls which app's `title`/`description`/`ogImage` wins when multiple apps are on the same page. Default `0`; higher wins. See the [Executor guide](executor.md). |
154
154
 
@@ -646,6 +646,8 @@ SmartLinks manifests are **AI-discoverable, -configurable, and -importable**: th
646
646
 
647
647
  When you change your config shape, keep all three in sync: `app.manifest.json` (widget `settings`, containers, executor, linkable), `app.admin.json` (setup / import / tunable), and `ai-guide.md` (prose guidance).
648
648
 
649
+ This declarative model is canonical and works today. An app may **optionally** layer agent tools on top — a function that reads the declaration and returns a *context-adapted* result (e.g. "which setup questions for this collection?") — without changing the schema. That's additive and opt-in; see [agent-tools.md](agent-tools.md).
650
+
649
651
  ## Reading the Files at Runtime
650
652
 
651
653
  ### Manifest — available from the widgets endpoint
@@ -32,7 +32,7 @@ export default defineConfig({
32
32
  'react', 'react-dom', 'react/jsx-runtime',
33
33
  '@proveanything/smartlinks',
34
34
  'react-router-dom', '@tanstack/react-query',
35
- 'lucide-react', 'date-fns', 'liquidjs', 'class-variance-authority',
35
+ 'lucide-react', 'date-fns', 'liquidjs', 'marked', 'class-variance-authority',
36
36
  '@radix-ui/react-slot', '@radix-ui/react-dialog', '@radix-ui/react-popover',
37
37
  '@radix-ui/react-tooltip', '@radix-ui/react-tabs', '@radix-ui/react-accordion',
38
38
  '@radix-ui/react-select', '@radix-ui/react-scroll-area', '@radix-ui/react-label',
@@ -44,7 +44,7 @@ export default defineConfig({
44
44
  '@proveanything/smartlinks': 'SL',
45
45
  'react-router-dom': 'ReactRouterDOM', '@tanstack/react-query': 'ReactQuery',
46
46
  'lucide-react': 'LucideReact', 'date-fns': 'dateFns', 'liquidjs': 'LiquidJS',
47
- 'class-variance-authority': 'CVA',
47
+ 'marked': 'marked', 'class-variance-authority': 'CVA',
48
48
  '@radix-ui/react-slot': 'RadixSlot', '@radix-ui/react-dialog': 'RadixDialog',
49
49
  '@radix-ui/react-popover': 'RadixPopover', '@radix-ui/react-tooltip': 'RadixTooltip',
50
50
  '@radix-ui/react-tabs': 'RadixTabs', '@radix-ui/react-accordion': 'RadixAccordion',
@@ -71,6 +71,7 @@ export default defineConfig({
71
71
  | `lucide-react` | `LucideReact` | 1.47 |
72
72
  | `date-fns` | `dateFns` | 4.4 |
73
73
  | `liquidjs` | `LiquidJS` | 10.27+ |
74
+ | `marked` | `marked` | 12+ |
74
75
  | `class-variance-authority` | `CVA` | 0.7 |
75
76
  | `@radix-ui/react-slot` | `RadixSlot` | 1.2.4 |
76
77
  | `@radix-ui/react-dialog` | `RadixDialog` | 1.1.23 |
@@ -85,7 +86,10 @@ export default defineConfig({
85
86
  | `@radix-ui/react-progress` | `RadixProgress` | 1.1.8 |
86
87
  | `@radix-ui/react-avatar` | `RadixAvatar` | 1.1.11 |
87
88
 
88
- `liquidjs` is **host-provided** — externalise it, don't ship a second copy (frequently missed).
89
+ `liquidjs` and `marked` are **host-provided** — externalise them, don't ship a second copy
90
+ (frequently missed). `marked` is new in **contract v6**: the portal and hub render markdown in the
91
+ container, so an app should use the host's renderer rather than bundling its own. `marked` does not
92
+ sanitise HTML — if you render untrusted markdown, sanitise the output (e.g. DOMPurify) yourself.
89
93
 
90
94
  ## Backwards compatibility
91
95
 
@@ -111,7 +115,7 @@ app ships the Tailwind 4 CSS-first layout as the default; see its README.)
111
115
 
112
116
  React **19.3** · Vite **8.3** · react-router-dom **7.18** · Tailwind **4.3** (CSS-first) ·
113
117
  TypeScript **6.0** · ESLint **10.11** · `@proveanything/smartlinks` **2.0.5** ·
114
- `@proveanything/smartlinks-utils-ui` **1.16.4** · liquidjs **10.29**.
118
+ `@proveanything/smartlinks-utils-ui` **1.16.4** · liquidjs **10.29** · marked **12+**.
115
119
 
116
120
  > **TypeScript 7** (the native/Go compiler) is **deliberately deferred** — tooling hasn't settled.
117
121
  > Target **TS 6** for R5; it compiles existing code with no source changes.
@@ -138,8 +142,8 @@ never drift:
138
142
 
139
143
  ```ts
140
144
  import {
141
- SHARED_DEPENDENCY_CONTRACT_VERSION, // 'v5'
142
- SHARED_DEPENDENCIES, // [{ specifier, globalName, minVersion, importMapPath }, …] (25)
145
+ SHARED_DEPENDENCY_CONTRACT_VERSION, // 'v6'
146
+ SHARED_DEPENDENCIES, // [{ specifier, globalName, minVersion, importMapPath }, …] (26)
143
147
  SHARED_DEPENDENCY_SPECIFIERS, // bare specifiers — drop straight into a bundler `external` list
144
148
  getHostSharedDependencies, // what the live host advertises at runtime, or null
145
149
  } from '@proveanything/smartlinks'
package/docs/overview.md CHANGED
@@ -60,7 +60,7 @@ The SmartLinks SDK (`@proveanything/smartlinks`) includes comprehensive document
60
60
  | **Mobile Admin Container** | `docs/mobile-admin-container.md` | Building a separate Capacitor-aware mobile admin bundle for field operators |
61
61
  | **Executors** | `docs/executor.md` | Building executor bundles for SEO, LLM content, programmatic config |
62
62
  | **Server Functions** | `docs/server-functions.md` | App-authored server-side functions `(ctx, event) ⇒ result`: security model, runtime surface, invoking |
63
- | **Agent Tools** | `docs/agent-tools.md` | Exposing your app's actions to the SmartLinks agent — an MCP facade over server functions; declare now, live loop staged; replaces `app.admin.json` AI setup |
63
+ | **Agent Tools** | `docs/agent-tools.md` | Exposing your app's actions to the SmartLinks agent — an MCP facade over server functions; **opt-in per app, additive, no migration**; complements `app.admin.json` (functions serve/adapt it, don't replace it); live loop staged |
64
64
  | **Deploying & Registering** | `docs/deploying-apps.md` | Getting your app into the platform: fast dev publish, channels, deploy keys, registering releases |
65
65
  | **Host Dependency Contract (R5)** | `docs/host-dependency-contract.md` | The libraries the host provides (React 19, Router 7, Radix, liquidjs, …), the externalise-don't-bundle rule + Vite config, and React-18 backwards-compat |
66
66
  | **Deep Linking** | `docs/deep-link-discovery.md` | URL state management, navigable states, portal menus, AI nav |