@tangle-network/agent-app 0.43.25 → 0.43.26

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 (44) hide show
  1. package/dist/app-auth/index.d.ts +1 -1
  2. package/dist/app-auth/index.js +1 -1
  3. package/dist/assistant/index.d.ts +1 -0
  4. package/dist/assistant/index.js +2 -1
  5. package/dist/assistant/index.js.map +1 -1
  6. package/dist/chat-routes/index.d.ts +276 -0
  7. package/dist/chat-routes/index.js +564 -0
  8. package/dist/chat-routes/index.js.map +1 -0
  9. package/dist/chat-store/index.d.ts +3 -2
  10. package/dist/chat-store/index.js +7 -3
  11. package/dist/chat-store/index.js.map +1 -1
  12. package/dist/{chunk-4H77LX3V.js → chunk-5EQCITY3.js} +2 -20
  13. package/dist/chunk-5EQCITY3.js.map +1 -0
  14. package/dist/chunk-5SV5PSU7.js +80 -0
  15. package/dist/chunk-5SV5PSU7.js.map +1 -0
  16. package/dist/chunk-7LNGJDNA.js +1 -0
  17. package/dist/chunk-7LNGJDNA.js.map +1 -0
  18. package/dist/{chunk-77RLNLFP.js → chunk-ATRJULKZ.js} +41 -5
  19. package/dist/chunk-ATRJULKZ.js.map +1 -0
  20. package/dist/{chunk-PEPXQTJ3.js → chunk-FCQP75JT.js} +16 -5
  21. package/dist/chunk-FCQP75JT.js.map +1 -0
  22. package/dist/chunk-I2R2XT4M.js +62 -0
  23. package/dist/chunk-I2R2XT4M.js.map +1 -0
  24. package/dist/{chunk-AVBANQ67.js → chunk-TKVJE63N.js} +10 -1
  25. package/dist/{chunk-AVBANQ67.js.map → chunk-TKVJE63N.js.map} +1 -1
  26. package/dist/{chunk-U7DLCPJ6.js → chunk-Y4QHNQ75.js} +1 -1
  27. package/dist/core-7qIM7svy.d.ts +21 -0
  28. package/dist/index.d.ts +2 -1
  29. package/dist/index.js +49 -44
  30. package/dist/interactions/index.js +2 -1
  31. package/dist/{parts-BeRnK54I.d.ts → parts-BcbitSNp.d.ts} +12 -21
  32. package/dist/platform/index.d.ts +1 -1
  33. package/dist/platform/index.js +3 -1
  34. package/dist/platform/index.js.map +1 -1
  35. package/dist/{sso-Df4wtL8D.d.ts → sso-CNOsARMJ.d.ts} +16 -1
  36. package/dist/stream/index.js +1 -1
  37. package/dist/web-react/index.d.ts +24 -4
  38. package/dist/web-react/index.js +5 -1
  39. package/dist/wire-BaUF66AS.d.ts +61 -0
  40. package/package.json +6 -1
  41. package/dist/chunk-4H77LX3V.js.map +0 -1
  42. package/dist/chunk-77RLNLFP.js.map +0 -1
  43. package/dist/chunk-PEPXQTJ3.js.map +0 -1
  44. /package/dist/{chunk-U7DLCPJ6.js.map → chunk-Y4QHNQ75.js.map} +0 -0
@@ -0,0 +1,276 @@
1
+ import { C as ChatTurnRequestPayload, a as ChatTurnPartInput, b as ChatTurnFilePartInput } from '../wire-BaUF66AS.js';
2
+ export { c as ChatTurnInputError, d as ChatTurnTextPartInput, I as INLINE_PARTS_MAX_BYTES, e as assertPromptPartsWithinCap, f as chatTurnRequestInit, p as parseChatTurnParts, g as promptPartsByteSize } from '../wire-BaUF66AS.js';
3
+ import { ChatTurnIdentity, ChatTurnProducer } from '@tangle-network/agent-runtime';
4
+ import { c as ChatMessagePart } from '../parts-BcbitSNp.js';
5
+ import { InteractionAnswerRoute, InteractionAnswerRouteOptions } from '../interactions/index.js';
6
+ import { PersistedChatMessageForTurn, TurnEventStore } from '../stream/index.js';
7
+ import '@tangle-network/agent-interface';
8
+ import '../contract-DYbTzEDf.js';
9
+
10
+ /**
11
+ * `createChatTurnRoutes` — the assembled server chat vertical (issue #188
12
+ * Phase 1). One factory composing the pieces every product re-wired by hand:
13
+ *
14
+ * body parse/validate → `/web` `parseJsonObjectBody` + `./wire`
15
+ * turn identity → `/stream` `resolveChatTurn` + agent-runtime
16
+ * `deriveExecutionId`
17
+ * producer → injected seam (sandbox lane via
18
+ * `createSandboxChatProducer`; router lane is the
19
+ * product's own `ChatTurnProducer`)
20
+ * turn engine → agent-runtime `handleChatTurn` (verbatim)
21
+ * durability → `/stream` turn-buffer tap, wired BY DEFAULT
22
+ * (tee + drain keeps the turn running after a
23
+ * client drop; replay serves the buffered tail)
24
+ * persistence → injected `/chat-store`-shaped store
25
+ * (user row on send, assistant row on completion)
26
+ * interactions answer → `/interactions` `createInteractionAnswerRoute`
27
+ *
28
+ * Handlers are web-standard `Request → Response` (Workers, Node 18+, Deno) —
29
+ * no router import. Auth/access is one injected `authorize` seam, composable
30
+ * with `/app-auth` guards but not coupled to them.
31
+ */
32
+
33
+ /** Usage receipt persisted onto the assistant message (the flattened
34
+ * `step-finish` shape `/chat-store`'s columns mirror). */
35
+ interface ChatTurnUsage {
36
+ inputTokens?: number;
37
+ outputTokens?: number;
38
+ reasoningTokens?: number;
39
+ cacheReadTokens?: number;
40
+ cacheWriteTokens?: number;
41
+ costUsd?: number;
42
+ }
43
+ /** What the route persists — a structural subset of `/chat-store`'s
44
+ * `ChatStore`, so `createChatStore(db, tables)` satisfies it directly and a
45
+ * product with its own persistence adapts without importing drizzle. */
46
+ interface ChatTurnMessageStore {
47
+ listMessages(threadId: string): Promise<Array<{
48
+ id: string;
49
+ role: 'user' | 'assistant' | 'system' | 'tool';
50
+ content: string;
51
+ parts?: ChatMessagePart[] | null;
52
+ }>>;
53
+ appendMessage(input: {
54
+ threadId: string;
55
+ role: 'user' | 'assistant';
56
+ content: string;
57
+ parts?: ChatMessagePart[];
58
+ model?: string | null;
59
+ inputTokens?: number | null;
60
+ outputTokens?: number | null;
61
+ reasoningTokens?: number | null;
62
+ cacheReadTokens?: number | null;
63
+ cacheWriteTokens?: number | null;
64
+ costUsd?: number | null;
65
+ }): Promise<unknown>;
66
+ }
67
+ /** `ChatTurnProducer` plus the persisted projection the assembly reads after
68
+ * drain. `createSandboxChatProducer` returns this; a router-lane producer
69
+ * may omit the optional members (finalText persists as a single text part). */
70
+ interface ChatTurnRouteProducer extends ChatTurnProducer {
71
+ assistantParts?(): Array<Record<string, unknown>>;
72
+ usage?(): ChatTurnUsage;
73
+ model?: string;
74
+ }
75
+ type ChatTurnAuthorization<TContext> = {
76
+ ok: true;
77
+ tenantId: string;
78
+ userId: string;
79
+ context: TContext;
80
+ } | {
81
+ ok: false;
82
+ response: Response;
83
+ };
84
+ interface ChatTurnAuthorizeArgs {
85
+ request: Request;
86
+ intent: 'turn' | 'replay';
87
+ /** Parsed, validated POST body (turn intent only). */
88
+ body?: ChatTurnRequestPayload;
89
+ /** The buffered turn id being replayed (replay intent only). */
90
+ turnId?: string;
91
+ }
92
+ interface ChatTurnProduceArgs<TContext> {
93
+ request: Request;
94
+ body: ChatTurnRequestPayload;
95
+ identity: ChatTurnIdentity;
96
+ context: TContext;
97
+ /** The message to send: plain text, or parts when the client attached
98
+ * files (a text part is prepended from `content` when present). */
99
+ prompt: string | ChatTurnPartInput[];
100
+ /** Stable id for cross-process reconnect (`deriveExecutionId`). */
101
+ executionId: string;
102
+ /** The turn-buffer id announced to the client for replay. */
103
+ turnStreamId: string;
104
+ priorMessages: PersistedChatMessageForTurn[];
105
+ }
106
+ interface CreateChatTurnRoutesOptions<TContext = void> {
107
+ /** Names the product in `deriveExecutionId` so retries land on the same
108
+ * substrate execution. */
109
+ projectId: string;
110
+ /** Authenticate + authorize the caller for a turn or a replay. The only
111
+ * product-supplied access step: session auth, thread/workspace access,
112
+ * seat/balance gates, rate limits all live here. */
113
+ authorize(args: ChatTurnAuthorizeArgs): Promise<ChatTurnAuthorization<TContext>>;
114
+ /** Thread/message persistence (`/chat-store`'s store or a product adapter). */
115
+ store: ChatTurnMessageStore;
116
+ /** Turn-event buffer (`createD1TurnEventStore(env.DB)` in production,
117
+ * `createMemoryTurnEventStore()` in tests). Wired by default — every turn
118
+ * is buffered and replayable. */
119
+ turnStore: TurnEventStore;
120
+ /** Build the turn's event stream. Sandbox lane: `streamSandboxPrompt(...)`
121
+ * wrapped in `createSandboxChatProducer`. Router/openai-compat lane: the
122
+ * product's own producer. May be async (box resolution). */
123
+ produce(args: ChatTurnProduceArgs<TContext>): ChatTurnRouteProducer | Promise<ChatTurnRouteProducer>;
124
+ /** Pre-persist transform of the final text (e.g. `/redact`'s `redactPII`).
125
+ * Live stream is never altered. */
126
+ transformFinalText?(text: string): string | Promise<string>;
127
+ /** Post-processing after a successful turn (billing, titles, audit). Errors
128
+ * are swallowed by the engine — they never fail a streamed turn. */
129
+ onTurnComplete?(input: {
130
+ identity: ChatTurnIdentity;
131
+ finalText: string;
132
+ context: TContext;
133
+ }): Promise<void>;
134
+ /** Per-event side channel (product broadcast). The turn-buffer tap is
135
+ * already wired; this runs in addition. */
136
+ onEvent?(event: {
137
+ type: string;
138
+ data?: Record<string, unknown>;
139
+ }, context: TContext): void | Promise<void>;
140
+ /** Trace flush handed to `waitUntil` (OTLP export). */
141
+ traceFlush?(context: TContext): Promise<void>;
142
+ /** Compose the interaction-answer endpoints (`/interactions`). Omit when the
143
+ * product has no sidecar ask channel. */
144
+ interactions?: InteractionAnswerRouteOptions;
145
+ /** Byte budget for inline prompt parts. Default `INLINE_PARTS_MAX_BYTES`. */
146
+ maxInlinePartBytes?: number;
147
+ /** Per-flush coalescer for the turn buffer. Default `coalesceDeltas` (this
148
+ * assembly streams the client vocabulary's `{type:'text'|'reasoning',
149
+ * text}` lines, which it merges). A producer streaming raw
150
+ * `message.part.updated` events passes `coalesceChatStreamEvents`. */
151
+ coalesceTurnEvents?: (events: unknown[]) => unknown[];
152
+ replay?: {
153
+ pollMs?: number;
154
+ timeoutMs?: number;
155
+ };
156
+ log?: (message: string, meta?: Record<string, unknown>) => void;
157
+ }
158
+ interface ChatTurnRoutes {
159
+ /** POST — run one turn, streaming NDJSON. First line is
160
+ * `{type:'turn', turnId}` (the replay handle); the rest is the engine's
161
+ * event protocol. Pass the platform's `waitUntil` so the turn keeps
162
+ * running (and buffering) after a client disconnect. */
163
+ turn(request: Request, ctx?: {
164
+ waitUntil?(p: Promise<unknown>): void;
165
+ }): Promise<Response>;
166
+ /** GET — replay a buffered turn from `?fromSeq=` (0 = everything), then
167
+ * follow it live until it completes. */
168
+ replay(request: Request, params: {
169
+ turnId: string;
170
+ }): Promise<Response>;
171
+ /** list/answer endpoints from `/interactions`; null when not configured. */
172
+ interactions: InteractionAnswerRoute | null;
173
+ }
174
+ declare function createChatTurnRoutes<TContext = void>(options: CreateChatTurnRoutesOptions<TContext>): ChatTurnRoutes;
175
+
176
+ /**
177
+ * Sandbox lane: bridge a raw sandbox event stream (`streamSandboxPrompt`) into
178
+ * the `ChatTurnProducer` shape agent-runtime's `handleChatTurn` consumes AND
179
+ * the client vocabulary `/web-react`'s `dispatchChatStreamLine` already parses
180
+ * (`text` / `reasoning` / `tool_call` / `tool_result` / `usage` /
181
+ * `interaction`). Legal and tax each hand-rolled this mapping differently;
182
+ * this is that middle, composed from `/stream`'s normalizers — no new loop
183
+ * logic, no SDK import (the event source is an injected `AsyncIterable`).
184
+ *
185
+ * Alongside the live mapping it accumulates the PERSISTED projection — the
186
+ * `message.parts` rows `/chat-store` stores — via `normalizePersistedPart` /
187
+ * `mergePersistedPart` / `finalizeAssistantParts`, plus the usage receipt from
188
+ * `step-finish` parts. `createChatTurnRoutes` reads both after drain.
189
+ */
190
+
191
+ interface SandboxChatProducerOptions {
192
+ /** The raw sandbox event stream (e.g. `streamSandboxPrompt(...)`). */
193
+ events: AsyncIterable<unknown>;
194
+ /** Recorded on the persisted assistant message. */
195
+ model?: string;
196
+ /** Which ask kinds the product renders a card for. Anything else is
197
+ * auto-declined (see `declineInteraction`) so the run never hangs in the
198
+ * broker waiting on a card no client will show. Default: question/plan. */
199
+ isRenderableInteraction?: (kind: string) => boolean;
200
+ /** Resolve a non-renderable ask (wire `respondToSessionInteraction` with the
201
+ * session's sidecar connection). Without it, non-renderable asks are only
202
+ * logged — the run stays blocked until the broker times out. */
203
+ declineInteraction?: (id: string) => Promise<void>;
204
+ log?: (message: string, meta?: Record<string, unknown>) => void;
205
+ }
206
+ declare function createSandboxChatProducer(options: SandboxChatProducerOptions): ChatTurnRouteProducer;
207
+
208
+ /**
209
+ * `createUploadRoute` — the multimodal middle. Accepts multipart file uploads
210
+ * and returns `PromptInputPart`-shaped descriptors the client echoes back on
211
+ * send (`ChatTurnRequestPayload.parts`):
212
+ *
213
+ * ≤ inlineMaxBytes (700 KiB default) → inline `data:` URI part — rides the
214
+ * turn body directly, no sandbox round trip.
215
+ * > inlineMaxBytes → written into the sandbox workspace (base64 through the
216
+ * structural `write` seam — `box.fs` satisfies it) and referenced by
217
+ * `path`. Mandatory two-step: the gateway caps request bodies at ~1 MiB,
218
+ * so a large file can never ride the prompt POST.
219
+ *
220
+ * The sink is structural (no sandbox-SDK import); products pass `box.fs`.
221
+ */
222
+
223
+ /** 700 KiB: base64 inflates ~4/3, so an inline part stays comfortably under
224
+ * the ~1 MiB gateway body cap alongside the JSON envelope. */
225
+ declare const UPLOAD_INLINE_MAX_BYTES: number;
226
+ /** 8 MiB default ceiling per file — one base64 `write` call handles it. Raise
227
+ * it only with a sink that can take the bigger single write. */
228
+ declare const UPLOAD_MAX_FILE_BYTES: number;
229
+ /** Structural match of the sandbox SDK's `box.fs` write surface (v0.10.5+:
230
+ * `encoding: 'base64'` is the worker-safe binary path). */
231
+ interface SandboxUploadSink {
232
+ write(path: string, content: string, options?: {
233
+ encoding?: 'utf8' | 'base64';
234
+ }): Promise<unknown>;
235
+ }
236
+ type UploadAuthorization = {
237
+ ok: true;
238
+ /** Where large files land. Absent/null: only inline uploads are
239
+ * accepted and an over-inline-cap file is rejected with 413. */
240
+ sink?: SandboxUploadSink | null;
241
+ /** Per-request override of the workspace directory large files go to. */
242
+ uploadDir?: string;
243
+ } | {
244
+ ok: false;
245
+ response: Response;
246
+ };
247
+ interface CreateUploadRouteOptions {
248
+ /** Authenticate the caller and resolve the sandbox file sink (usually
249
+ * `ensureWorkspaceSandbox(...)` → `box.fs`). */
250
+ authorize(args: {
251
+ request: Request;
252
+ }): Promise<UploadAuthorization>;
253
+ /** Inline-vs-sandbox threshold. Default {@link UPLOAD_INLINE_MAX_BYTES}. */
254
+ inlineMaxBytes?: number;
255
+ /** Hard per-file cap. Default {@link UPLOAD_MAX_FILE_BYTES}. */
256
+ maxFileBytes?: number;
257
+ /** Workspace directory for path-ref files. Default `'uploads'`. */
258
+ uploadDir?: string;
259
+ }
260
+ /** One uploaded file, ready for the composer chip and the turn body. */
261
+ interface UploadedChatFile {
262
+ id: string;
263
+ name: string;
264
+ size: number;
265
+ mediaType: string;
266
+ /** True when the part carries the bytes inline (`data:` URI). */
267
+ inline: boolean;
268
+ /** Echo this back verbatim in `ChatTurnRequestPayload.parts`. */
269
+ part: ChatTurnFilePartInput;
270
+ }
271
+ /** Path-safe file name: basename only, conservative charset, length-capped. */
272
+ declare function sanitizeUploadFilename(name: string): string;
273
+ declare function bytesToBase64(bytes: Uint8Array): string;
274
+ declare function createUploadRoute(options: CreateUploadRouteOptions): (request: Request) => Promise<Response>;
275
+
276
+ export { type ChatTurnAuthorization, type ChatTurnAuthorizeArgs, ChatTurnFilePartInput, type ChatTurnMessageStore, ChatTurnPartInput, type ChatTurnProduceArgs, ChatTurnRequestPayload, type ChatTurnRouteProducer, type ChatTurnRoutes, type ChatTurnUsage, type CreateChatTurnRoutesOptions, type CreateUploadRouteOptions, type SandboxChatProducerOptions, type SandboxUploadSink, UPLOAD_INLINE_MAX_BYTES, UPLOAD_MAX_FILE_BYTES, type UploadAuthorization, type UploadedChatFile, bytesToBase64, createChatTurnRoutes, createSandboxChatProducer, createUploadRoute, sanitizeUploadFilename };