@alquimia-ai/tools 2.7.0 → 2.8.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 (63) hide show
  1. package/README.md +88 -12
  2. package/dist/actions/index.d.mts +1 -1
  3. package/dist/actions/index.d.ts +1 -1
  4. package/dist/adapters/fetch.d.mts +1 -0
  5. package/dist/adapters/fetch.d.ts +1 -0
  6. package/dist/adapters/fetch.js +4 -0
  7. package/dist/adapters/fetch.js.map +1 -1
  8. package/dist/adapters/fetch.mjs +4 -0
  9. package/dist/adapters/fetch.mjs.map +1 -1
  10. package/dist/adapters/index.d.mts +1 -0
  11. package/dist/adapters/index.d.ts +1 -0
  12. package/dist/adapters/index.js.map +1 -1
  13. package/dist/adapters/next.d.mts +1 -0
  14. package/dist/adapters/next.d.ts +1 -0
  15. package/dist/adapters/next.js +4 -0
  16. package/dist/adapters/next.js.map +1 -1
  17. package/dist/adapters/next.mjs +4 -0
  18. package/dist/adapters/next.mjs.map +1 -1
  19. package/dist/approvals-CcnmqUkQ.d.ts +59 -0
  20. package/dist/approvals-dn4sd_Ot.d.mts +59 -0
  21. package/dist/hooks/index.d.mts +36 -5
  22. package/dist/hooks/index.d.ts +36 -5
  23. package/dist/hooks/index.js +208 -12
  24. package/dist/hooks/index.js.map +1 -1
  25. package/dist/hooks/index.mjs +208 -12
  26. package/dist/hooks/index.mjs.map +1 -1
  27. package/dist/next/index.d.mts +7 -0
  28. package/dist/next/index.d.ts +7 -0
  29. package/dist/next/index.js +56 -40
  30. package/dist/next/index.js.map +1 -1
  31. package/dist/next/index.mjs +56 -40
  32. package/dist/next/index.mjs.map +1 -1
  33. package/dist/providers/index.d.mts +3 -3
  34. package/dist/providers/index.d.ts +3 -3
  35. package/dist/{providers-mx21gNgZ.d.ts → providers-J_Z9rQ3Q.d.ts} +1 -1
  36. package/dist/{providers-B4IOiGfr.d.mts → providers-YKiEag2L.d.mts} +1 -1
  37. package/dist/proxy.d.mts +2 -0
  38. package/dist/proxy.d.ts +2 -0
  39. package/dist/proxy.js +47 -40
  40. package/dist/proxy.js.map +1 -1
  41. package/dist/proxy.mjs +47 -40
  42. package/dist/proxy.mjs.map +1 -1
  43. package/dist/sdk/index.d.mts +25 -3
  44. package/dist/sdk/index.d.ts +25 -3
  45. package/dist/sdk/index.js +73 -10
  46. package/dist/sdk/index.js.map +1 -1
  47. package/dist/sdk/index.mjs +73 -10
  48. package/dist/sdk/index.mjs.map +1 -1
  49. package/dist/services/index.d.mts +1 -1
  50. package/dist/services/index.d.ts +1 -1
  51. package/dist/{type-D-JaSMkV.d.ts → type-BFtGEEb4.d.ts} +1 -1
  52. package/dist/{type-61gaZga-.d.mts → type-C_sKpIM1.d.mts} +1 -1
  53. package/dist/types/index.d.mts +23 -2
  54. package/dist/types/index.d.ts +23 -2
  55. package/dist/utils/index.d.mts +1 -1
  56. package/dist/utils/index.d.ts +1 -1
  57. package/dist/worklog/index.d.mts +1 -0
  58. package/dist/worklog/index.d.ts +1 -0
  59. package/dist/worklog/index.js +75 -2
  60. package/dist/worklog/index.js.map +1 -1
  61. package/dist/worklog/index.mjs +75 -2
  62. package/dist/worklog/index.mjs.map +1 -1
  63. package/package.json +1 -1
package/README.md CHANGED
@@ -21,6 +21,7 @@ It ships no UI. Pair it with [`@alquimia-ai/ui`](../ui) for the component librar
21
21
  - [Multimodal and audio input](#multimodal-and-audio-input)
22
22
  - [Attachments and blobs](#attachments-and-blobs)
23
23
  - [Client tools and GenUI](#client-tools-and-genui)
24
+ - [Human approval](#human-approval)
24
25
  - [Worklog](#worklog)
25
26
  - [Providers](#providers)
26
27
  - [Server proxy](#server-proxy)
@@ -62,11 +63,12 @@ useAlquimia / AlquimiaSDK
62
63
  └─ adapter.resolveStreamUrl() ─→ handleStream ───────────────→ GET /event/stream/{taskId}
63
64
  └─ adapter.resolveBlobUploadUrl() → handleBlobUpload ────────→ POST /context/blob/upload
64
65
  └─ adapter.resolveToolCompletionUrl() → handleToolCompletion → POST /event/tool-completion
66
+ └─ adapter.resolveToolApprovalUrl() ──→ handleToolApproval ───→ POST /event/tool-approval
65
67
  ↑
66
68
  Authorization: Bearer <apiKey>
67
69
  ```
68
70
 
69
- The proxy exists for two reasons. The obvious one is that the API key must not reach the browser. The load-bearing one is that the stream leg uses `EventSource`, and **`EventSource` cannot set request headers** — so `getHeaders()` is honoured on infer, blob upload and tool-completion (all axios POSTs) and silently ignored on the stream. If your runtime or its gateway requires auth on every request, a server hop on the stream is not optional.
71
+ The proxy exists for two reasons. The obvious one is that the API key must not reach the browser. The load-bearing one is that the stream leg uses `EventSource`, and **`EventSource` cannot set request headers** — so `getHeaders()` is honoured on infer, blob upload, tool-completion and tool-approval (all axios POSTs) and silently ignored on the stream. If your runtime or its gateway requires auth on every request, a server hop on the stream is not optional.
70
72
 
71
73
  Three supported topologies:
72
74
 
@@ -82,7 +84,7 @@ Three supported topologies:
82
84
 
83
85
  ### Next.js App Router
84
86
 
85
- Four route files, five lines each:
87
+ Five route files, five lines each:
86
88
 
87
89
  ```ts
88
90
  // app/api/chat/[...path]/route.ts
@@ -100,9 +102,10 @@ export const POST = handlers.handleInfer;
100
102
  // app/api/stream/[...path]/route.ts → export const GET = handlers.handleStream;
101
103
  // app/api/blob/upload/route.ts → export const POST = handlers.handleBlobUpload;
102
104
  // app/api/tool-completion/route.ts → export const POST = handlers.handleToolCompletion;
105
+ // app/api/tool-approval/route.ts → export const POST = handlers.handleToolApproval;
103
106
  ```
104
107
 
105
- The last two take no `[...path]` segment: identity travels in headers, and the pending tool call is correlated by `control_id` in the body.
108
+ The last three take no `[...path]` segment: identity travels in headers, and the pending tool call or approval is correlated by `control_id` in the body.
106
109
 
107
110
  ```tsx
108
111
  'use client';
@@ -138,6 +141,7 @@ app.post('/chat/:path{.+}', (c) => handler.handleInfer(c.req.raw, c.req.param('p
138
141
  app.get('/stream/:path{.+}', (c) => handler.handleStream(c.req.raw, c.req.param('path')));
139
142
  app.post('/blob/upload', (c) => handler.handleBlobUpload(c.req.raw));
140
143
  app.post('/tool-completion', (c) => handler.handleToolCompletion(c.req.raw));
144
+ app.post('/tool-approval', (c) => handler.handleToolApproval(c.req.raw));
141
145
  ```
142
146
 
143
147
  The handlers speak the Web Fetch API (`Request` → `Response`), so any modern runtime works.
@@ -159,6 +163,7 @@ const adapter: AlquimiaAdapter = {
159
163
  resolveStreamUrl: (taskId) => `${STREAM_PROXY}/event/stream/${taskId}`,
160
164
  resolveBlobUploadUrl: () => `${BACKEND}/context/blob/upload`,
161
165
  resolveToolCompletionUrl: () => `${BACKEND}/event/tool-completion`,
166
+ resolveToolApprovalUrl: () => `${BACKEND}/event/tool-approval`,
162
167
  getHeaders: () => ({ Authorization: `Bearer ${API_KEY}` }),
163
168
  };
164
169
  ```
@@ -232,6 +237,10 @@ const alquimia = useAlquimia({
232
237
 
233
238
  `activeTool`, `setActiveTool`, `pendingClientTool`, `completeToolExecution`, `genui`.
234
239
 
240
+ **Human approval**
241
+
242
+ `toolApprovals`, `pendingApprovals`, `approveTool` — see [Human approval](#human-approval).
243
+
235
244
  **Trace**
236
245
 
237
246
  `worklog` — a `WorklogState`, or `undefined` unless `options.worklog` is on.
@@ -279,7 +288,9 @@ const streamUrl = sdk.getUrlStream();
279
288
  | `getUrlStream()` | SSE URL for the task, with the traceparent appended as a query param |
280
289
  | `getStreamId()` / `getTaskId()` | the runtime `taskid` |
281
290
  | `getVersionTag()` | the registry version the runtime resolved |
291
+ | `getAgentspaceId()` | the agentspace the runtime resolved |
282
292
  | `submitToolResult(response)` | POST tool-completion for a pending client tool |
293
+ | `submitToolApproval(controlId, approved, message?)` → `ToolApprovalResult` | POST tool-approval for a pending human-approval gate |
283
294
 
284
295
  ### Side channels
285
296
 
@@ -301,7 +312,7 @@ const streamUrl = sdk.getUrlStream();
301
312
  1. POST /event/infer/{assistantId}
302
313
  body { query, session_id, user_id, ... }
303
314
  headers assistant-id, session-id, user-id, task-id, x-trace-parent
304
- → CommonAttributes { taskid, versiontag, attachments }
315
+ → CommonAttributes { taskid, agentspaceid, versiontag, attachments }
305
316
 
306
317
  2. GET /event/stream/{taskid} (EventSource)
307
318
  ← assistant deltas, thinkings, tool events
@@ -309,8 +320,13 @@ const streamUrl = sdk.getUrlStream();
309
320
 
310
321
  3. POST /event/tool-completion (only if the agent called a client tool)
311
322
  body ToolExecutionResponse { control_id, tool_name, status, result }
312
- headers taskid, sessionid, userid, assistantid, versiontag
323
+ headers taskid, sessionid, userid, assistantid, agentspaceid, versiontag
313
324
  → the run resumes on the same stream
325
+
326
+ 4. POST /event/tool-approval (only if a tool call needs human approval)
327
+ body ToolApprovalEvent { control_id, result, message? }
328
+ headers same as step 3
329
+ → the parked call runs (approved) or fails back to the agent (rejected)
314
330
  ```
315
331
 
316
332
  Step 3 is what makes client tools and GenUI work: the runtime parks the task, the browser answers, the run continues. The correlation headers are not decoration — the runtime looks the parked task up by them, and rejects a completion whose `control_id` it is not awaiting with a `409`.
@@ -416,6 +432,64 @@ Components come from `@alquimia-ai/ui/components/genui` (`A2uiRenderer`, `coreUi
416
432
 
417
433
  ---
418
434
 
435
+ ## Human approval
436
+
437
+ When the runtime's authorization policy resolves a tool call to `REQUIRE_APPROVAL` — an operation classified `destructive`, or one with `approval_required` set — the run parks and the stream carries a `HumanApprovalRequired` instead of the tool execution. Nothing resumes it until someone answers `POST /event/tool-approval`. The hook tracks these gates always, not only with `options.worklog`, because an unanswered gate hangs the conversation.
438
+
439
+ ```tsx
440
+ const alquimia = useAlquimia({ assistantId, adapter });
441
+
442
+ alquimia.pendingApprovals.map((a) => (
443
+ <div key={a.controlId}>
444
+ Run <code>{a.toolName}</code> with <pre>{JSON.stringify(a.arguments, null, 2)}</pre>
445
+ {a.canAnswer && (
446
+ <>
447
+ <button onClick={() => alquimia.approveTool(a.controlId, true)}>Approve</button>
448
+ <button onClick={() => alquimia.approveTool(a.controlId, false, 'not now')}>Reject</button>
449
+ </>
450
+ )}
451
+ </div>
452
+ ));
453
+ ```
454
+
455
+ `@alquimia-ai/ui` ships this as `ToolApprovalCard`, and `AssistantChat` renders it in place when you pass the whole hook return.
456
+
457
+ Each `ToolApproval` in `toolApprovals` (all gates) and `pendingApprovals` (undecided ones) carries:
458
+
459
+ | Field | Meaning |
460
+ |---|---|
461
+ | `controlId` | the gate's id — what `approveTool` takes. Not the parked tool call's id (`toolCallId`). |
462
+ | `toolName`, `arguments` | what is being approved. Show them: approving a call blind is not approval. |
463
+ | `status` | `pending` → `submitting` → `approved` / `rejected` |
464
+ | `decision` | the decision **as the worklog records it**, or `null` |
465
+ | `reason` | the rejection reason, if one was given |
466
+ | `decidedHere` | this client made the accepted decision |
467
+ | `canAnswer` | offering buttons can still work — `false` for a channel-owned gate or after a terminal refusal |
468
+ | `lastResult` | the runtime's answer to this client's last submission |
469
+ | `afterCount` | message count the gate was raised after, for anchoring it in the chat |
470
+
471
+ A gate settles when its `HumanApprovalRequiredResponse` arrives on the stream, whoever made the decision — another operator, or the channel the conversation came from. `approveTool` shows an accepted local decision right away, but `decision` only ever comes from the stream. The worklog records the decision and its reason, not the approver: the runtime keeps that in its audit trail.
472
+
473
+ `approveTool` never throws for a refusal. It resolves to a `ToolApprovalResult` whose `outcome` tells the cases apart, since the runtime answers most of them with a `409` and a different `detail`:
474
+
475
+ | `outcome` | Runtime answer | What to do |
476
+ |---|---|---|
477
+ | `accepted` | 200 | nothing — the stream will confirm |
478
+ | `already-decided` | 409, a decision is already recorded | someone else answered; wait for the stream |
479
+ | `wrong-channel` | 409, must be answered through its original channel | remove the buttons and say where to answer |
480
+ | `not-pending` | 409, no pending approval for this control id | stale; nothing to answer |
481
+ | `forbidden` | 401 / 403 | the caller lacks an approver role (`TOOL_APPROVAL_ROLES`, default `editor,operator`; platform and org admins always pass) or is not bound to the agentspace |
482
+ | `not-found` | 404 | the task finished or expired |
483
+ | `error` | anything else | retryable — `canAnswer` stays `true` |
484
+
485
+ The runtime authorizes the approver, not the app: a static API token in the proxy maps to `API_TOKEN_ROLES` (default `platform-admin`) and passes unless that was narrowed. If your proxy forwards an end-user token instead, that user needs an approver role. The SDK sends the `agentspaceid` the runtime returned on infer, which a non-admin caller is checked against.
486
+
487
+ A gate whose MCP server runs its own approval over the originating channel (the `mcp_approval` runtime extension) is flagged `channelOwned` from the request itself, so buttons are never offered for it.
488
+
489
+ Outside the hook, `foldApprovals` / `reduceApprovals` / `pendingApprovals` in `/worklog` derive the same state from any list of worklog records, and `sdk.submitToolApproval()` posts the decision.
490
+
491
+ ---
492
+
419
493
  ## Worklog
420
494
 
421
495
  The worklog is the agent's execution trace, normalized into a tree you can render as "show your work".
@@ -434,7 +508,7 @@ Each runtime event class maps to an interpreter that says which bucket it belong
434
508
  | `answer` | `AssistantInference(+Response)` — the run envelope |
435
509
  | `safeguard` | `ShieldInference(+Response)`, `ShieldBlockedResponse` |
436
510
  | `reasoning` | `ResponseInference(+Response)` |
437
- | `tool` | `ServerToolExecution`, `BuiltinToolExecution`, `ClientToolExecution`, `UnknownToolExecution`, `ToolSchema`, `HumanApprovalRequired`, and their responses |
511
+ | `tool` | `ServerToolExecution`, `BuiltinToolExecution`, `ClientToolExecution`, `UnknownToolExecution`, `ToolSchema`, `HumanApprovalRequired` (titled with the tool awaiting approval), and their responses |
438
512
  | `a2a` | `A2AInference`, `AgentDiscovery(+Response)` |
439
513
  | `memory` | `ContextPersistence`, `ContextFlush(+Response)` |
440
514
  | `knowledge` | `KnowledgeRetrieval(+Response)` |
@@ -481,15 +555,17 @@ createAlquimiaProxyHandler({
481
555
  streamRoute: 'event/stream',
482
556
  blobUploadRoute: 'context/blob/upload',
483
557
  toolCompletionRoute: 'event/tool-completion',
558
+ toolApprovalRoute: 'event/tool-approval',
484
559
  })
485
560
  ```
486
561
 
487
- Returns `handleInfer`, `handleStream`, `handleBlobUpload`, `handleToolCompletion`.
562
+ Returns `handleInfer`, `handleStream`, `handleBlobUpload`, `handleToolCompletion`, `handleToolApproval`.
488
563
 
489
564
  What it does beyond adding the bearer token:
490
565
 
491
566
  - Forwards identity headers on infer/stream/blob upload: `session-id`, `user-id`, `assistant-id`, `task-id`, `parent-task-id`, `agentspace-id`, `channel-id`, `depth`.
492
- - Forwards correlation headers on tool-completion: `taskid`, `sessionid`, `userid`, `assistantid`, `parenttaskid`, `agentspaceid`, `channelid`, `depth`, `versiontag`.
567
+ - Forwards correlation headers on tool-completion and tool-approval: `taskid`, `sessionid`, `userid`, `assistantid`, `parenttaskid`, `agentspaceid`, `channelid`, `depth`, `versiontag`.
568
+ - Passes the runtime's status and body through on tool-completion and tool-approval, so a `409`'s `detail` reaches the SDK intact.
493
569
  - Preserves the infer query string, so `?version_tag=` and `?agentspace_id=` survive the hop.
494
570
  - Streams the SSE body through untouched.
495
571
  - Turns the stream's `?trace_parent=` query param back into an `x-trace-parent` header, and does not pass the param upstream.
@@ -508,7 +584,7 @@ Infer and stream are two HTTP calls that must land in **one** trace, and `EventS
508
584
 
509
585
  `@alquimia-ai/tools/types` covers both the wire and the view model.
510
586
 
511
- **Wire:** `CommonAttributes` (with `versiontag`), `InferInitResponse`, `Content` / `ContentPart` / `TextContentPart` / `ImageContentPart` / `NonStandardContentPart`, `RuntimeBlob`, `AttachmentPayload`, `NativeToolsEvaluationStrategy`, `RuntimeEvent` and the `/event/*` payload union, `TTSResult`, `RatingData`.
587
+ **Wire:** `CommonAttributes` (with `versiontag`), `InferInitResponse`, `ToolApprovalEvent`, `ToolApprovalResult` / `ToolApprovalOutcome`, `Content` / `ContentPart` / `TextContentPart` / `ImageContentPart` / `NonStandardContentPart`, `RuntimeBlob`, `AttachmentPayload`, `NativeToolsEvaluationStrategy`, `RuntimeEvent` and the `/event/*` payload union, `TTSResult`, `RatingData`.
512
588
 
513
589
  **View:** `AlquimiaMessage`, `AlquimiaEventData`, `AIMessageChunk`, `AssistantInferenceResponse`, `ToolEvent`, `Tooler`, `ThinkingsInferenceResponse`, `GenuiSurfaceItem`, `ActionResponse`.
514
590
 
@@ -522,13 +598,13 @@ Infer and stream are two HTTP calls that must land in **one** trace, and `EventS
522
598
  | `/adapters/next` | `createNextJsAdapter` |
523
599
  | `/adapters/fetch` | `createFetchAdapter` |
524
600
  | `/sdk` | `AlquimiaSDK` |
525
- | `/hooks` | `useAlquimia`, `useRatings` |
601
+ | `/hooks` | `useAlquimia`, `useRatings`, `ToolApproval` |
526
602
  | `/proxy` | `createAlquimiaProxyHandler`, `ProxyConfig` |
527
- | `/next` | `createNextJsRouteHandlers`, `handleChatRequest`, `handleStreamRequest`, `initConversation` |
603
+ | `/next` | `createNextJsRouteHandlers` (incl. `handleToolApproval`), `handleChatRequest`, `handleStreamRequest`, `initConversation` |
528
604
  | `/providers` | provider base classes and implementations |
529
605
  | `/providers/elastic` | `ElasticLoggerProvider` |
530
606
  | `/genui` | the GenUI protocol |
531
- | `/worklog` | reducer, registry, types, `useWorklog` |
607
+ | `/worklog` | reducer, registry, types, `useWorklog`, approval derivation (`foldApprovals`, `pendingApprovals`) |
532
608
  | `/actions` | `initConversation`, CRUD helpers, `handleApmRequest` |
533
609
  | `/services` | Elastic APM RUM |
534
610
  | `/types` | wire + view types |
@@ -1,4 +1,4 @@
1
- import { B as BaseAPIConfig } from '../type-61gaZga-.mjs';
1
+ import { B as BaseAPIConfig } from '../type-C_sKpIM1.mjs';
2
2
  export { i as initConversation } from '../session.action-DirvOWt0.mjs';
3
3
  import '@elastic/apm-rum';
4
4
  import 'ai';
@@ -1,4 +1,4 @@
1
- import { B as BaseAPIConfig } from '../type-D-JaSMkV.js';
1
+ import { B as BaseAPIConfig } from '../type-BFtGEEb4.js';
2
2
  export { i as initConversation } from '../session.action-DirvOWt0.js';
3
3
  import '@elastic/apm-rum';
4
4
  import 'ai';
@@ -7,6 +7,7 @@ interface FetchAdapterOptions {
7
7
  streamPath?: string;
8
8
  blobUploadPath?: string;
9
9
  toolCompletionPath?: string;
10
+ toolApprovalPath?: string;
10
11
  busMode?: boolean;
11
12
  }
12
13
  declare function createFetchAdapter(options: FetchAdapterOptions): AlquimiaAdapter;
@@ -7,6 +7,7 @@ interface FetchAdapterOptions {
7
7
  streamPath?: string;
8
8
  blobUploadPath?: string;
9
9
  toolCompletionPath?: string;
10
+ toolApprovalPath?: string;
10
11
  busMode?: boolean;
11
12
  }
12
13
  declare function createFetchAdapter(options: FetchAdapterOptions): AlquimiaAdapter;
@@ -28,6 +28,7 @@ function createFetchAdapter(options) {
28
28
  const streamPath = options.streamPath ?? "/stream";
29
29
  const blobUploadPath = options.blobUploadPath ?? "/blob/upload";
30
30
  const toolCompletionPath = options.toolCompletionPath ?? "/tool-completion";
31
+ const toolApprovalPath = options.toolApprovalPath ?? "/tool-approval";
31
32
  const busMode = options.busMode ?? false;
32
33
  const baseUrl = options.baseUrl.replace(/\/$/, "");
33
34
  return {
@@ -44,6 +45,9 @@ function createFetchAdapter(options) {
44
45
  resolveToolCompletionUrl() {
45
46
  return `${baseUrl}${toolCompletionPath}`;
46
47
  },
48
+ resolveToolApprovalUrl() {
49
+ return `${baseUrl}${toolApprovalPath}`;
50
+ },
47
51
  getHeaders: options.getHeaders
48
52
  };
49
53
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/fetch.ts"],"sourcesContent":["import type { AlquimiaAdapter } from './index';\n\nexport interface FetchAdapterOptions {\n baseUrl: string;\n getHeaders?: () => Record<string, string>;\n inferPath?: string; // default: '/chat'\n streamPath?: string; // default: '/stream'\n blobUploadPath?: string; // default: '/blob/upload'\n toolCompletionPath?: string; // default: '/tool-completion'\n busMode?: boolean; // default: false\n}\n\nexport function createFetchAdapter(options: FetchAdapterOptions): AlquimiaAdapter {\n const inferPath = options.inferPath ?? '/chat';\n const streamPath = options.streamPath ?? '/stream';\n const blobUploadPath = options.blobUploadPath ?? '/blob/upload';\n const toolCompletionPath = options.toolCompletionPath ?? '/tool-completion';\n const busMode = options.busMode ?? false;\n const baseUrl = options.baseUrl.replace(/\\/$/, '');\n\n return {\n resolveInferUrl(assistantId: string): string {\n return `${baseUrl}${inferPath}/${assistantId}`;\n },\n resolveStreamUrl(streamId: string): string {\n const url = `${baseUrl}${streamPath}/${streamId}`;\n return busMode ? `${url}${url.includes('?') ? '&' : '?'}bus_mode=true` : url;\n },\n resolveBlobUploadUrl(): string {\n return `${baseUrl}${blobUploadPath}`;\n },\n resolveToolCompletionUrl(): string {\n return `${baseUrl}${toolCompletionPath}`;\n },\n getHeaders: options.getHeaders,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAYO,SAAS,mBAAmB,SAA+C;AAChF,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAM,qBAAqB,QAAQ,sBAAsB;AACzD,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AAEjD,SAAO;AAAA,IACL,gBAAgB,aAA6B;AAC3C,aAAO,GAAG,OAAO,GAAG,SAAS,IAAI,WAAW;AAAA,IAC9C;AAAA,IACA,iBAAiB,UAA0B;AACzC,YAAM,MAAM,GAAG,OAAO,GAAG,UAAU,IAAI,QAAQ;AAC/C,aAAO,UAAU,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,kBAAkB;AAAA,IAC3E;AAAA,IACA,uBAA+B;AAC7B,aAAO,GAAG,OAAO,GAAG,cAAc;AAAA,IACpC;AAAA,IACA,2BAAmC;AACjC,aAAO,GAAG,OAAO,GAAG,kBAAkB;AAAA,IACxC;AAAA,IACA,YAAY,QAAQ;AAAA,EACtB;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/adapters/fetch.ts"],"sourcesContent":["import type { AlquimiaAdapter } from './index';\n\nexport interface FetchAdapterOptions {\n baseUrl: string;\n getHeaders?: () => Record<string, string>;\n inferPath?: string; // default: '/chat'\n streamPath?: string; // default: '/stream'\n blobUploadPath?: string; // default: '/blob/upload'\n toolCompletionPath?: string; // default: '/tool-completion'\n toolApprovalPath?: string; // default: '/tool-approval'\n busMode?: boolean; // default: false\n}\n\nexport function createFetchAdapter(options: FetchAdapterOptions): AlquimiaAdapter {\n const inferPath = options.inferPath ?? '/chat';\n const streamPath = options.streamPath ?? '/stream';\n const blobUploadPath = options.blobUploadPath ?? '/blob/upload';\n const toolCompletionPath = options.toolCompletionPath ?? '/tool-completion';\n const toolApprovalPath = options.toolApprovalPath ?? '/tool-approval';\n const busMode = options.busMode ?? false;\n const baseUrl = options.baseUrl.replace(/\\/$/, '');\n\n return {\n resolveInferUrl(assistantId: string): string {\n return `${baseUrl}${inferPath}/${assistantId}`;\n },\n resolveStreamUrl(streamId: string): string {\n const url = `${baseUrl}${streamPath}/${streamId}`;\n return busMode ? `${url}${url.includes('?') ? '&' : '?'}bus_mode=true` : url;\n },\n resolveBlobUploadUrl(): string {\n return `${baseUrl}${blobUploadPath}`;\n },\n resolveToolCompletionUrl(): string {\n return `${baseUrl}${toolCompletionPath}`;\n },\n resolveToolApprovalUrl(): string {\n return `${baseUrl}${toolApprovalPath}`;\n },\n getHeaders: options.getHeaders,\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAaO,SAAS,mBAAmB,SAA+C;AAChF,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAM,qBAAqB,QAAQ,sBAAsB;AACzD,QAAM,mBAAmB,QAAQ,oBAAoB;AACrD,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AAEjD,SAAO;AAAA,IACL,gBAAgB,aAA6B;AAC3C,aAAO,GAAG,OAAO,GAAG,SAAS,IAAI,WAAW;AAAA,IAC9C;AAAA,IACA,iBAAiB,UAA0B;AACzC,YAAM,MAAM,GAAG,OAAO,GAAG,UAAU,IAAI,QAAQ;AAC/C,aAAO,UAAU,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,kBAAkB;AAAA,IAC3E;AAAA,IACA,uBAA+B;AAC7B,aAAO,GAAG,OAAO,GAAG,cAAc;AAAA,IACpC;AAAA,IACA,2BAAmC;AACjC,aAAO,GAAG,OAAO,GAAG,kBAAkB;AAAA,IACxC;AAAA,IACA,yBAAiC;AAC/B,aAAO,GAAG,OAAO,GAAG,gBAAgB;AAAA,IACtC;AAAA,IACA,YAAY,QAAQ;AAAA,EACtB;AACF;","names":[]}
@@ -4,6 +4,7 @@ function createFetchAdapter(options) {
4
4
  const streamPath = options.streamPath ?? "/stream";
5
5
  const blobUploadPath = options.blobUploadPath ?? "/blob/upload";
6
6
  const toolCompletionPath = options.toolCompletionPath ?? "/tool-completion";
7
+ const toolApprovalPath = options.toolApprovalPath ?? "/tool-approval";
7
8
  const busMode = options.busMode ?? false;
8
9
  const baseUrl = options.baseUrl.replace(/\/$/, "");
9
10
  return {
@@ -20,6 +21,9 @@ function createFetchAdapter(options) {
20
21
  resolveToolCompletionUrl() {
21
22
  return `${baseUrl}${toolCompletionPath}`;
22
23
  },
24
+ resolveToolApprovalUrl() {
25
+ return `${baseUrl}${toolApprovalPath}`;
26
+ },
23
27
  getHeaders: options.getHeaders
24
28
  };
25
29
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/fetch.ts"],"sourcesContent":["import type { AlquimiaAdapter } from './index';\n\nexport interface FetchAdapterOptions {\n baseUrl: string;\n getHeaders?: () => Record<string, string>;\n inferPath?: string; // default: '/chat'\n streamPath?: string; // default: '/stream'\n blobUploadPath?: string; // default: '/blob/upload'\n toolCompletionPath?: string; // default: '/tool-completion'\n busMode?: boolean; // default: false\n}\n\nexport function createFetchAdapter(options: FetchAdapterOptions): AlquimiaAdapter {\n const inferPath = options.inferPath ?? '/chat';\n const streamPath = options.streamPath ?? '/stream';\n const blobUploadPath = options.blobUploadPath ?? '/blob/upload';\n const toolCompletionPath = options.toolCompletionPath ?? '/tool-completion';\n const busMode = options.busMode ?? false;\n const baseUrl = options.baseUrl.replace(/\\/$/, '');\n\n return {\n resolveInferUrl(assistantId: string): string {\n return `${baseUrl}${inferPath}/${assistantId}`;\n },\n resolveStreamUrl(streamId: string): string {\n const url = `${baseUrl}${streamPath}/${streamId}`;\n return busMode ? `${url}${url.includes('?') ? '&' : '?'}bus_mode=true` : url;\n },\n resolveBlobUploadUrl(): string {\n return `${baseUrl}${blobUploadPath}`;\n },\n resolveToolCompletionUrl(): string {\n return `${baseUrl}${toolCompletionPath}`;\n },\n getHeaders: options.getHeaders,\n };\n}\n"],"mappings":";AAYO,SAAS,mBAAmB,SAA+C;AAChF,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAM,qBAAqB,QAAQ,sBAAsB;AACzD,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AAEjD,SAAO;AAAA,IACL,gBAAgB,aAA6B;AAC3C,aAAO,GAAG,OAAO,GAAG,SAAS,IAAI,WAAW;AAAA,IAC9C;AAAA,IACA,iBAAiB,UAA0B;AACzC,YAAM,MAAM,GAAG,OAAO,GAAG,UAAU,IAAI,QAAQ;AAC/C,aAAO,UAAU,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,kBAAkB;AAAA,IAC3E;AAAA,IACA,uBAA+B;AAC7B,aAAO,GAAG,OAAO,GAAG,cAAc;AAAA,IACpC;AAAA,IACA,2BAAmC;AACjC,aAAO,GAAG,OAAO,GAAG,kBAAkB;AAAA,IACxC;AAAA,IACA,YAAY,QAAQ;AAAA,EACtB;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/adapters/fetch.ts"],"sourcesContent":["import type { AlquimiaAdapter } from './index';\n\nexport interface FetchAdapterOptions {\n baseUrl: string;\n getHeaders?: () => Record<string, string>;\n inferPath?: string; // default: '/chat'\n streamPath?: string; // default: '/stream'\n blobUploadPath?: string; // default: '/blob/upload'\n toolCompletionPath?: string; // default: '/tool-completion'\n toolApprovalPath?: string; // default: '/tool-approval'\n busMode?: boolean; // default: false\n}\n\nexport function createFetchAdapter(options: FetchAdapterOptions): AlquimiaAdapter {\n const inferPath = options.inferPath ?? '/chat';\n const streamPath = options.streamPath ?? '/stream';\n const blobUploadPath = options.blobUploadPath ?? '/blob/upload';\n const toolCompletionPath = options.toolCompletionPath ?? '/tool-completion';\n const toolApprovalPath = options.toolApprovalPath ?? '/tool-approval';\n const busMode = options.busMode ?? false;\n const baseUrl = options.baseUrl.replace(/\\/$/, '');\n\n return {\n resolveInferUrl(assistantId: string): string {\n return `${baseUrl}${inferPath}/${assistantId}`;\n },\n resolveStreamUrl(streamId: string): string {\n const url = `${baseUrl}${streamPath}/${streamId}`;\n return busMode ? `${url}${url.includes('?') ? '&' : '?'}bus_mode=true` : url;\n },\n resolveBlobUploadUrl(): string {\n return `${baseUrl}${blobUploadPath}`;\n },\n resolveToolCompletionUrl(): string {\n return `${baseUrl}${toolCompletionPath}`;\n },\n resolveToolApprovalUrl(): string {\n return `${baseUrl}${toolApprovalPath}`;\n },\n getHeaders: options.getHeaders,\n };\n}\n"],"mappings":";AAaO,SAAS,mBAAmB,SAA+C;AAChF,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,aAAa,QAAQ,cAAc;AACzC,QAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAM,qBAAqB,QAAQ,sBAAsB;AACzD,QAAM,mBAAmB,QAAQ,oBAAoB;AACrD,QAAM,UAAU,QAAQ,WAAW;AACnC,QAAM,UAAU,QAAQ,QAAQ,QAAQ,OAAO,EAAE;AAEjD,SAAO;AAAA,IACL,gBAAgB,aAA6B;AAC3C,aAAO,GAAG,OAAO,GAAG,SAAS,IAAI,WAAW;AAAA,IAC9C;AAAA,IACA,iBAAiB,UAA0B;AACzC,YAAM,MAAM,GAAG,OAAO,GAAG,UAAU,IAAI,QAAQ;AAC/C,aAAO,UAAU,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,kBAAkB;AAAA,IAC3E;AAAA,IACA,uBAA+B;AAC7B,aAAO,GAAG,OAAO,GAAG,cAAc;AAAA,IACpC;AAAA,IACA,2BAAmC;AACjC,aAAO,GAAG,OAAO,GAAG,kBAAkB;AAAA,IACxC;AAAA,IACA,yBAAiC;AAC/B,aAAO,GAAG,OAAO,GAAG,gBAAgB;AAAA,IACtC;AAAA,IACA,YAAY,QAAQ;AAAA,EACtB;AACF;","names":[]}
@@ -3,6 +3,7 @@ interface AlquimiaAdapter {
3
3
  resolveStreamUrl(_streamId: string): string;
4
4
  resolveBlobUploadUrl(): string;
5
5
  resolveToolCompletionUrl?(): string;
6
+ resolveToolApprovalUrl?(): string;
6
7
  getHeaders?(): Record<string, string>;
7
8
  }
8
9
  interface AlquimiaSDKOptions {
@@ -3,6 +3,7 @@ interface AlquimiaAdapter {
3
3
  resolveStreamUrl(_streamId: string): string;
4
4
  resolveBlobUploadUrl(): string;
5
5
  resolveToolCompletionUrl?(): string;
6
+ resolveToolApprovalUrl?(): string;
6
7
  getHeaders?(): Record<string, string>;
7
8
  }
8
9
  interface AlquimiaSDKOptions {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/index.ts"],"sourcesContent":["export interface AlquimiaAdapter {\n resolveInferUrl(_assistantId: string): string;\n resolveStreamUrl(_streamId: string): string;\n resolveBlobUploadUrl(): string;\n resolveToolCompletionUrl?(): string;\n getHeaders?(): Record<string, string>;\n}\n\nexport interface AlquimiaSDKOptions {\n enforceCharacterization?: boolean;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
1
+ {"version":3,"sources":["../../src/adapters/index.ts"],"sourcesContent":["export interface AlquimiaAdapter {\n resolveInferUrl(_assistantId: string): string;\n resolveStreamUrl(_streamId: string): string;\n resolveBlobUploadUrl(): string;\n resolveToolCompletionUrl?(): string;\n resolveToolApprovalUrl?(): string;\n getHeaders?(): Record<string, string>;\n}\n\nexport interface AlquimiaSDKOptions {\n enforceCharacterization?: boolean;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
@@ -5,6 +5,7 @@ interface NextJsAdapterOptions {
5
5
  streamRoute?: string;
6
6
  blobUploadRoute?: string;
7
7
  toolCompletionRoute?: string;
8
+ toolApprovalRoute?: string;
8
9
  busMode?: boolean;
9
10
  }
10
11
  declare function createNextJsAdapter(options?: NextJsAdapterOptions): AlquimiaAdapter;
@@ -5,6 +5,7 @@ interface NextJsAdapterOptions {
5
5
  streamRoute?: string;
6
6
  blobUploadRoute?: string;
7
7
  toolCompletionRoute?: string;
8
+ toolApprovalRoute?: string;
8
9
  busMode?: boolean;
9
10
  }
10
11
  declare function createNextJsAdapter(options?: NextJsAdapterOptions): AlquimiaAdapter;
@@ -28,6 +28,7 @@ function createNextJsAdapter(options) {
28
28
  const streamRoute = options?.streamRoute ?? "/api/stream";
29
29
  const blobUploadRoute = options?.blobUploadRoute ?? "/api/blob/upload";
30
30
  const toolCompletionRoute = options?.toolCompletionRoute ?? "/api/tool-completion";
31
+ const toolApprovalRoute = options?.toolApprovalRoute ?? "/api/tool-approval";
31
32
  const busMode = options?.busMode ?? false;
32
33
  return {
33
34
  resolveInferUrl(assistantId) {
@@ -42,6 +43,9 @@ function createNextJsAdapter(options) {
42
43
  },
43
44
  resolveToolCompletionUrl() {
44
45
  return toolCompletionRoute;
46
+ },
47
+ resolveToolApprovalUrl() {
48
+ return toolApprovalRoute;
45
49
  }
46
50
  };
47
51
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/next.ts"],"sourcesContent":["import type { AlquimiaAdapter } from './index';\n\nexport interface NextJsAdapterOptions {\n inferRoute?: string; // default: '/api/chat'\n streamRoute?: string; // default: '/api/stream'\n blobUploadRoute?: string; // default: '/api/blob/upload'\n toolCompletionRoute?: string; // default: '/api/tool-completion'\n busMode?: boolean; // default: false\n}\n\nexport function createNextJsAdapter(options?: NextJsAdapterOptions): AlquimiaAdapter {\n const inferRoute = options?.inferRoute ?? '/api/chat';\n const streamRoute = options?.streamRoute ?? '/api/stream';\n const blobUploadRoute = options?.blobUploadRoute ?? '/api/blob/upload';\n const toolCompletionRoute = options?.toolCompletionRoute ?? '/api/tool-completion';\n const busMode = options?.busMode ?? false;\n\n return {\n resolveInferUrl(assistantId: string): string {\n return `${inferRoute.replace(/\\/$/, '')}/${encodeURIComponent(assistantId)}`;\n },\n resolveStreamUrl(streamId: string): string {\n const url = `${streamRoute}/${streamId}`;\n return busMode ? `${url}${url.includes('?') ? '&' : '?'}bus_mode=true` : url;\n },\n resolveBlobUploadUrl(): string {\n return blobUploadRoute;\n },\n resolveToolCompletionUrl(): string {\n return toolCompletionRoute;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAUO,SAAS,oBAAoB,SAAiD;AACnF,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,cAAc,SAAS,eAAe;AAC5C,QAAM,kBAAkB,SAAS,mBAAmB;AACpD,QAAM,sBAAsB,SAAS,uBAAuB;AAC5D,QAAM,UAAU,SAAS,WAAW;AAEpC,SAAO;AAAA,IACL,gBAAgB,aAA6B;AAC3C,aAAO,GAAG,WAAW,QAAQ,OAAO,EAAE,CAAC,IAAI,mBAAmB,WAAW,CAAC;AAAA,IAC5E;AAAA,IACA,iBAAiB,UAA0B;AACzC,YAAM,MAAM,GAAG,WAAW,IAAI,QAAQ;AACtC,aAAO,UAAU,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,kBAAkB;AAAA,IAC3E;AAAA,IACA,uBAA+B;AAC7B,aAAO;AAAA,IACT;AAAA,IACA,2BAAmC;AACjC,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/adapters/next.ts"],"sourcesContent":["import type { AlquimiaAdapter } from './index';\n\nexport interface NextJsAdapterOptions {\n inferRoute?: string; // default: '/api/chat'\n streamRoute?: string; // default: '/api/stream'\n blobUploadRoute?: string; // default: '/api/blob/upload'\n toolCompletionRoute?: string; // default: '/api/tool-completion'\n toolApprovalRoute?: string; // default: '/api/tool-approval'\n busMode?: boolean; // default: false\n}\n\nexport function createNextJsAdapter(options?: NextJsAdapterOptions): AlquimiaAdapter {\n const inferRoute = options?.inferRoute ?? '/api/chat';\n const streamRoute = options?.streamRoute ?? '/api/stream';\n const blobUploadRoute = options?.blobUploadRoute ?? '/api/blob/upload';\n const toolCompletionRoute = options?.toolCompletionRoute ?? '/api/tool-completion';\n const toolApprovalRoute = options?.toolApprovalRoute ?? '/api/tool-approval';\n const busMode = options?.busMode ?? false;\n\n return {\n resolveInferUrl(assistantId: string): string {\n return `${inferRoute.replace(/\\/$/, '')}/${encodeURIComponent(assistantId)}`;\n },\n resolveStreamUrl(streamId: string): string {\n const url = `${streamRoute}/${streamId}`;\n return busMode ? `${url}${url.includes('?') ? '&' : '?'}bus_mode=true` : url;\n },\n resolveBlobUploadUrl(): string {\n return blobUploadRoute;\n },\n resolveToolCompletionUrl(): string {\n return toolCompletionRoute;\n },\n resolveToolApprovalUrl(): string {\n return toolApprovalRoute;\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAWO,SAAS,oBAAoB,SAAiD;AACnF,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,cAAc,SAAS,eAAe;AAC5C,QAAM,kBAAkB,SAAS,mBAAmB;AACpD,QAAM,sBAAsB,SAAS,uBAAuB;AAC5D,QAAM,oBAAoB,SAAS,qBAAqB;AACxD,QAAM,UAAU,SAAS,WAAW;AAEpC,SAAO;AAAA,IACL,gBAAgB,aAA6B;AAC3C,aAAO,GAAG,WAAW,QAAQ,OAAO,EAAE,CAAC,IAAI,mBAAmB,WAAW,CAAC;AAAA,IAC5E;AAAA,IACA,iBAAiB,UAA0B;AACzC,YAAM,MAAM,GAAG,WAAW,IAAI,QAAQ;AACtC,aAAO,UAAU,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,kBAAkB;AAAA,IAC3E;AAAA,IACA,uBAA+B;AAC7B,aAAO;AAAA,IACT;AAAA,IACA,2BAAmC;AACjC,aAAO;AAAA,IACT;AAAA,IACA,yBAAiC;AAC/B,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -4,6 +4,7 @@ function createNextJsAdapter(options) {
4
4
  const streamRoute = options?.streamRoute ?? "/api/stream";
5
5
  const blobUploadRoute = options?.blobUploadRoute ?? "/api/blob/upload";
6
6
  const toolCompletionRoute = options?.toolCompletionRoute ?? "/api/tool-completion";
7
+ const toolApprovalRoute = options?.toolApprovalRoute ?? "/api/tool-approval";
7
8
  const busMode = options?.busMode ?? false;
8
9
  return {
9
10
  resolveInferUrl(assistantId) {
@@ -18,6 +19,9 @@ function createNextJsAdapter(options) {
18
19
  },
19
20
  resolveToolCompletionUrl() {
20
21
  return toolCompletionRoute;
22
+ },
23
+ resolveToolApprovalUrl() {
24
+ return toolApprovalRoute;
21
25
  }
22
26
  };
23
27
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/adapters/next.ts"],"sourcesContent":["import type { AlquimiaAdapter } from './index';\n\nexport interface NextJsAdapterOptions {\n inferRoute?: string; // default: '/api/chat'\n streamRoute?: string; // default: '/api/stream'\n blobUploadRoute?: string; // default: '/api/blob/upload'\n toolCompletionRoute?: string; // default: '/api/tool-completion'\n busMode?: boolean; // default: false\n}\n\nexport function createNextJsAdapter(options?: NextJsAdapterOptions): AlquimiaAdapter {\n const inferRoute = options?.inferRoute ?? '/api/chat';\n const streamRoute = options?.streamRoute ?? '/api/stream';\n const blobUploadRoute = options?.blobUploadRoute ?? '/api/blob/upload';\n const toolCompletionRoute = options?.toolCompletionRoute ?? '/api/tool-completion';\n const busMode = options?.busMode ?? false;\n\n return {\n resolveInferUrl(assistantId: string): string {\n return `${inferRoute.replace(/\\/$/, '')}/${encodeURIComponent(assistantId)}`;\n },\n resolveStreamUrl(streamId: string): string {\n const url = `${streamRoute}/${streamId}`;\n return busMode ? `${url}${url.includes('?') ? '&' : '?'}bus_mode=true` : url;\n },\n resolveBlobUploadUrl(): string {\n return blobUploadRoute;\n },\n resolveToolCompletionUrl(): string {\n return toolCompletionRoute;\n },\n };\n}\n"],"mappings":";AAUO,SAAS,oBAAoB,SAAiD;AACnF,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,cAAc,SAAS,eAAe;AAC5C,QAAM,kBAAkB,SAAS,mBAAmB;AACpD,QAAM,sBAAsB,SAAS,uBAAuB;AAC5D,QAAM,UAAU,SAAS,WAAW;AAEpC,SAAO;AAAA,IACL,gBAAgB,aAA6B;AAC3C,aAAO,GAAG,WAAW,QAAQ,OAAO,EAAE,CAAC,IAAI,mBAAmB,WAAW,CAAC;AAAA,IAC5E;AAAA,IACA,iBAAiB,UAA0B;AACzC,YAAM,MAAM,GAAG,WAAW,IAAI,QAAQ;AACtC,aAAO,UAAU,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,kBAAkB;AAAA,IAC3E;AAAA,IACA,uBAA+B;AAC7B,aAAO;AAAA,IACT;AAAA,IACA,2BAAmC;AACjC,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/adapters/next.ts"],"sourcesContent":["import type { AlquimiaAdapter } from './index';\n\nexport interface NextJsAdapterOptions {\n inferRoute?: string; // default: '/api/chat'\n streamRoute?: string; // default: '/api/stream'\n blobUploadRoute?: string; // default: '/api/blob/upload'\n toolCompletionRoute?: string; // default: '/api/tool-completion'\n toolApprovalRoute?: string; // default: '/api/tool-approval'\n busMode?: boolean; // default: false\n}\n\nexport function createNextJsAdapter(options?: NextJsAdapterOptions): AlquimiaAdapter {\n const inferRoute = options?.inferRoute ?? '/api/chat';\n const streamRoute = options?.streamRoute ?? '/api/stream';\n const blobUploadRoute = options?.blobUploadRoute ?? '/api/blob/upload';\n const toolCompletionRoute = options?.toolCompletionRoute ?? '/api/tool-completion';\n const toolApprovalRoute = options?.toolApprovalRoute ?? '/api/tool-approval';\n const busMode = options?.busMode ?? false;\n\n return {\n resolveInferUrl(assistantId: string): string {\n return `${inferRoute.replace(/\\/$/, '')}/${encodeURIComponent(assistantId)}`;\n },\n resolveStreamUrl(streamId: string): string {\n const url = `${streamRoute}/${streamId}`;\n return busMode ? `${url}${url.includes('?') ? '&' : '?'}bus_mode=true` : url;\n },\n resolveBlobUploadUrl(): string {\n return blobUploadRoute;\n },\n resolveToolCompletionUrl(): string {\n return toolCompletionRoute;\n },\n resolveToolApprovalUrl(): string {\n return toolApprovalRoute;\n },\n };\n}\n"],"mappings":";AAWO,SAAS,oBAAoB,SAAiD;AACnF,QAAM,aAAa,SAAS,cAAc;AAC1C,QAAM,cAAc,SAAS,eAAe;AAC5C,QAAM,kBAAkB,SAAS,mBAAmB;AACpD,QAAM,sBAAsB,SAAS,uBAAuB;AAC5D,QAAM,oBAAoB,SAAS,qBAAqB;AACxD,QAAM,UAAU,SAAS,WAAW;AAEpC,SAAO;AAAA,IACL,gBAAgB,aAA6B;AAC3C,aAAO,GAAG,WAAW,QAAQ,OAAO,EAAE,CAAC,IAAI,mBAAmB,WAAW,CAAC;AAAA,IAC5E;AAAA,IACA,iBAAiB,UAA0B;AACzC,YAAM,MAAM,GAAG,WAAW,IAAI,QAAQ;AACtC,aAAO,UAAU,GAAG,GAAG,GAAG,IAAI,SAAS,GAAG,IAAI,MAAM,GAAG,kBAAkB;AAAA,IAC3E;AAAA,IACA,uBAA+B;AAC7B,aAAO;AAAA,IACT;AAAA,IACA,2BAAmC;AACjC,aAAO;AAAA,IACT;AAAA,IACA,yBAAiC;AAC/B,aAAO;AAAA,IACT;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,59 @@
1
+ import { W as WorklogRecord } from './types-lOliroPw.js';
2
+
3
+ /**
4
+ * Human-approval gates, derived from the worklog.
5
+ *
6
+ * When the runtime's authz policy resolves a tool call to `REQUIRE_APPROVAL`,
7
+ * core parks the call and records a `HumanApprovalRequired` whose `data` is the
8
+ * command minus its conversation: `{ parameters: <the tool execution> }`. The
9
+ * gate closes with a `HumanApprovalRequiredResponse` under the same
10
+ * `control_id`, whichever channel the decision came through — so the stream,
11
+ * not the local submit, is the source of truth for "settled".
12
+ */
13
+ /** A decision as the worklog records it. */
14
+ interface ApprovalDecision {
15
+ approved: boolean;
16
+ /**
17
+ * Rejection reason. Core records `result or message` as the response data,
18
+ * so an approval never carries one and a rejection carries the reason when
19
+ * the approver gave it.
20
+ */
21
+ reason: string | null;
22
+ decidedAt: string;
23
+ }
24
+ /** One approval gate, pending or settled. */
25
+ interface ApprovalRequest {
26
+ /** The `HumanApprovalRequired` control id — the one `/event/tool-approval` expects. */
27
+ controlId: string;
28
+ /** Name of the parked tool call; `null` until the request record is seen. */
29
+ toolName: string | null;
30
+ /** Control id of the parked tool execution itself (distinct from `controlId`). */
31
+ toolCallId: string | null;
32
+ /** Arguments the tool would be called with. What is actually being approved. */
33
+ arguments: unknown;
34
+ /**
35
+ * The gate belongs to an MCP server that runs its own approval over the
36
+ * task's originating channel (the `mcp_approval` runtime extension). The
37
+ * runtime refuses an HTTP decision for it with a 409, so offering buttons
38
+ * would be a lie.
39
+ */
40
+ channelOwned: boolean;
41
+ requestedAt: string | null;
42
+ /** `null` while pending. */
43
+ decision: ApprovalDecision | null;
44
+ }
45
+ interface ApprovalsState {
46
+ /** Gates in the order they were first seen. */
47
+ order: string[];
48
+ byId: Record<string, ApprovalRequest>;
49
+ }
50
+ declare function initialApprovalsState(): ApprovalsState;
51
+ /** Fold one worklog record into the approvals state. Records of other classes are a no-op. */
52
+ declare function reduceApprovals(state: ApprovalsState, record: WorklogRecord): ApprovalsState;
53
+ declare function foldApprovals(records: WorklogRecord[]): ApprovalsState;
54
+ /** All gates, in first-seen order. */
55
+ declare function listApprovals(state: ApprovalsState): ApprovalRequest[];
56
+ /** Gates with no recorded decision yet. */
57
+ declare function pendingApprovals(state: ApprovalsState): ApprovalRequest[];
58
+
59
+ export { type ApprovalRequest as A, type ApprovalDecision as a, type ApprovalsState as b, foldApprovals as f, initialApprovalsState as i, listApprovals as l, pendingApprovals as p, reduceApprovals as r };
@@ -0,0 +1,59 @@
1
+ import { W as WorklogRecord } from './types-lOliroPw.mjs';
2
+
3
+ /**
4
+ * Human-approval gates, derived from the worklog.
5
+ *
6
+ * When the runtime's authz policy resolves a tool call to `REQUIRE_APPROVAL`,
7
+ * core parks the call and records a `HumanApprovalRequired` whose `data` is the
8
+ * command minus its conversation: `{ parameters: <the tool execution> }`. The
9
+ * gate closes with a `HumanApprovalRequiredResponse` under the same
10
+ * `control_id`, whichever channel the decision came through — so the stream,
11
+ * not the local submit, is the source of truth for "settled".
12
+ */
13
+ /** A decision as the worklog records it. */
14
+ interface ApprovalDecision {
15
+ approved: boolean;
16
+ /**
17
+ * Rejection reason. Core records `result or message` as the response data,
18
+ * so an approval never carries one and a rejection carries the reason when
19
+ * the approver gave it.
20
+ */
21
+ reason: string | null;
22
+ decidedAt: string;
23
+ }
24
+ /** One approval gate, pending or settled. */
25
+ interface ApprovalRequest {
26
+ /** The `HumanApprovalRequired` control id — the one `/event/tool-approval` expects. */
27
+ controlId: string;
28
+ /** Name of the parked tool call; `null` until the request record is seen. */
29
+ toolName: string | null;
30
+ /** Control id of the parked tool execution itself (distinct from `controlId`). */
31
+ toolCallId: string | null;
32
+ /** Arguments the tool would be called with. What is actually being approved. */
33
+ arguments: unknown;
34
+ /**
35
+ * The gate belongs to an MCP server that runs its own approval over the
36
+ * task's originating channel (the `mcp_approval` runtime extension). The
37
+ * runtime refuses an HTTP decision for it with a 409, so offering buttons
38
+ * would be a lie.
39
+ */
40
+ channelOwned: boolean;
41
+ requestedAt: string | null;
42
+ /** `null` while pending. */
43
+ decision: ApprovalDecision | null;
44
+ }
45
+ interface ApprovalsState {
46
+ /** Gates in the order they were first seen. */
47
+ order: string[];
48
+ byId: Record<string, ApprovalRequest>;
49
+ }
50
+ declare function initialApprovalsState(): ApprovalsState;
51
+ /** Fold one worklog record into the approvals state. Records of other classes are a no-op. */
52
+ declare function reduceApprovals(state: ApprovalsState, record: WorklogRecord): ApprovalsState;
53
+ declare function foldApprovals(records: WorklogRecord[]): ApprovalsState;
54
+ /** All gates, in first-seen order. */
55
+ declare function listApprovals(state: ApprovalsState): ApprovalRequest[];
56
+ /** Gates with no recorded decision yet. */
57
+ declare function pendingApprovals(state: ApprovalsState): ApprovalRequest[];
58
+
59
+ export { type ApprovalRequest as A, type ApprovalDecision as a, type ApprovalsState as b, foldApprovals as f, initialApprovalsState as i, listApprovals as l, pendingApprovals as p, reduceApprovals as r };
@@ -1,11 +1,13 @@
1
1
  import * as react from 'react';
2
2
  import { AlquimiaSDK } from '../sdk/index.mjs';
3
3
  import { AlquimiaAdapter } from '../adapters/index.mjs';
4
- import { W as WhisperProvider, S as StableDiffusionProvider, C as CharacterizationProvider, R as RatingsProvider, L as LoggerProvider } from '../providers-B4IOiGfr.mjs';
5
- import { G as GenuiSurfaceItem, e as AlquimiaMessage, F as ToolEvent, a as AIMessageChunk, R as RatingData } from '../type-61gaZga-.mjs';
6
- import { T as ToolExecutionResponse } from '../types-CMVbyEv8.mjs';
7
- import { a as WorklogState } from '../types-lOliroPw.mjs';
4
+ import { W as WhisperProvider, S as StableDiffusionProvider, C as CharacterizationProvider, R as RatingsProvider, L as LoggerProvider } from '../providers-YKiEag2L.mjs';
5
+ import { G as GenuiSurfaceItem, a as AlquimiaMessage, b as ToolEvent, c as AIMessageChunk, R as RatingData } from '../type-C_sKpIM1.mjs';
6
+ import { ToolApprovalResult } from '../types/index.mjs';
8
7
  import { createMessageId } from '../utils/index.mjs';
8
+ import { a as WorklogState } from '../types-lOliroPw.mjs';
9
+ import { A as ApprovalRequest } from '../approvals-dn4sd_Ot.mjs';
10
+ import { T as ToolExecutionResponse } from '../types-CMVbyEv8.mjs';
9
11
  import { C as CatalogManifest } from '../registry-Bcu_ZYL1.mjs';
10
12
  import { U as UIAction } from '../actions-BjDPJdyA.mjs';
11
13
  import '@elastic/apm-rum';
@@ -40,11 +42,40 @@ interface UseAlquimiaConfig {
40
42
  source?: 'client' | 'agent';
41
43
  };
42
44
  }
45
+ /**
46
+ * A human-approval gate as the hook exposes it: what the worklog says, overlaid
47
+ * with this client's own submission.
48
+ */
49
+ interface ToolApproval extends ApprovalRequest {
50
+ /**
51
+ * `pending` until someone decides; `submitting` while this client's call is
52
+ * in flight; `approved`/`rejected` once the runtime accepted a decision —
53
+ * this client's (optimistically, before the stream confirms) or anyone's.
54
+ */
55
+ status: 'pending' | 'submitting' | 'approved' | 'rejected';
56
+ /** Rejection reason, from the worklog or from this client's submission. */
57
+ reason: string | null;
58
+ /** `true` when the accepted decision was made from this client. */
59
+ decidedHere: boolean;
60
+ /**
61
+ * Whether offering Approve / Reject here can still work. `false` for a
62
+ * channel-owned gate, and after the runtime refused this client with a 409,
63
+ * 403 or 404 — retrying those can only fail the same way.
64
+ */
65
+ canAnswer: boolean;
66
+ /** The runtime's answer to this client's last submission, if any. */
67
+ lastResult: ToolApprovalResult | null;
68
+ /** Message count the gate was raised after, for anchoring it in the chat. */
69
+ afterCount: number;
70
+ }
43
71
  declare function useAlquimia(config: UseAlquimiaConfig): {
44
72
  sdk: AlquimiaSDK;
45
73
  activeTool: any;
46
74
  pendingClientTool: PendingClientTool | null;
47
75
  completeToolExecution: (controlId: string, result: ToolExecutionResponse) => Promise<void>;
76
+ toolApprovals: ToolApproval[];
77
+ pendingApprovals: ToolApproval[];
78
+ approveTool: (controlId: string, approved: boolean, message?: string) => Promise<ToolApprovalResult>;
48
79
  genui: {
49
80
  surfaces: GenuiSurfaceItem[];
50
81
  onAgentAction: (controlId: string) => (action: UIAction) => void;
@@ -105,4 +136,4 @@ declare function useRatings({ assistantId, sendRating, topicId, onError }: UseRa
105
136
  hasReviewed: boolean;
106
137
  };
107
138
 
108
- export { useAlquimia, useRatings };
139
+ export { type ToolApproval, type UseAlquimiaConfig, useAlquimia, useRatings };