@tangle-network/agent-app 0.43.40 → 0.43.41
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.
- package/dist/assistant/index.d.ts +1 -1
- package/dist/assistant/index.js +2 -2
- package/dist/chat-routes/index.d.ts +2 -2
- package/dist/chat-routes/index.js +9 -1
- package/dist/chat-routes/index.js.map +1 -1
- package/dist/chunk-2EO7CPL3.js +191 -0
- package/dist/chunk-2EO7CPL3.js.map +1 -0
- package/dist/{chunk-D4HB72W2.js → chunk-KM766NN3.js} +159 -25
- package/dist/chunk-KM766NN3.js.map +1 -0
- package/dist/file-index-Bw_IQE_G.d.ts +194 -0
- package/dist/web-react/index.d.ts +94 -2
- package/dist/web-react/index.js +19 -3
- package/package.json +1 -1
- package/dist/chunk-5SV5PSU7.js +0 -80
- package/dist/chunk-5SV5PSU7.js.map +0 -1
- package/dist/chunk-D4HB72W2.js.map +0 -1
- package/dist/wire-BaUF66AS.d.ts +0 -61
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire contract between the chat client (composer + `streamChatTurn`) and the
|
|
3
|
+
* assembled server vertical (`createChatTurnRoutes`). Import-free on purpose:
|
|
4
|
+
* `/web-react` re-exports these types into browser bundles, so nothing here may
|
|
5
|
+
* reach a Node builtin or an engine package.
|
|
6
|
+
*
|
|
7
|
+
* The part shape mirrors the sandbox SDK's `PromptInputPart` structurally
|
|
8
|
+
* (text | image | file with filename/mediaType/url/path/content) — derived
|
|
9
|
+
* here, not imported, so the client bundle never touches the SDK.
|
|
10
|
+
*/
|
|
11
|
+
interface ChatTurnTextPartInput {
|
|
12
|
+
type: 'text';
|
|
13
|
+
text: string;
|
|
14
|
+
}
|
|
15
|
+
/** A non-text prompt part the upload route hands back and the client echoes
|
|
16
|
+
* on send. `url` carries an inline `data:` URI for small files; `path` is a
|
|
17
|
+
* sandbox workspace reference for large ones (the >1 MiB gateway body cap
|
|
18
|
+
* makes the two-step upload mandatory). */
|
|
19
|
+
interface ChatTurnFilePartInput {
|
|
20
|
+
type: 'image' | 'file';
|
|
21
|
+
filename?: string;
|
|
22
|
+
mediaType?: string;
|
|
23
|
+
url?: string;
|
|
24
|
+
path?: string;
|
|
25
|
+
content?: string;
|
|
26
|
+
}
|
|
27
|
+
type ChatTurnPartInput = ChatTurnTextPartInput | ChatTurnFilePartInput;
|
|
28
|
+
/** POST body for the turn route. `content` may be empty when `parts` carry the
|
|
29
|
+
* message (an image-only send). Product routing fields (workspaceId etc.) ride
|
|
30
|
+
* alongside and are read by the product's `authorize` seam. */
|
|
31
|
+
interface ChatTurnRequestPayload {
|
|
32
|
+
threadId: string;
|
|
33
|
+
content?: string;
|
|
34
|
+
/** Non-text parts from the upload route, echoed back verbatim. */
|
|
35
|
+
parts?: ChatTurnFilePartInput[];
|
|
36
|
+
model?: string;
|
|
37
|
+
effort?: 'auto' | 'low' | 'medium' | 'high';
|
|
38
|
+
harness?: string;
|
|
39
|
+
/** Client-generated idempotency key for the logical turn (retry-safe). */
|
|
40
|
+
turnId?: string;
|
|
41
|
+
[key: string]: unknown;
|
|
42
|
+
}
|
|
43
|
+
/** `fetch` init for the turn route — the one place the client wire shape is
|
|
44
|
+
* serialized, so composer glue and products never drift from the server's
|
|
45
|
+
* parser. */
|
|
46
|
+
declare function chatTurnRequestInit(payload: ChatTurnRequestPayload): RequestInit;
|
|
47
|
+
declare const INLINE_PARTS_MAX_BYTES = 950000;
|
|
48
|
+
declare class ChatTurnInputError extends Error {
|
|
49
|
+
readonly status: number;
|
|
50
|
+
readonly code: string;
|
|
51
|
+
constructor(message: string, status?: number, code?: string);
|
|
52
|
+
}
|
|
53
|
+
declare function promptPartsByteSize(parts: ChatTurnPartInput[]): number;
|
|
54
|
+
/** Throws `ChatTurnInputError` (413) when the parts' inline payload would blow
|
|
55
|
+
* the gateway cap. Path-ref parts are tiny by construction and always pass. */
|
|
56
|
+
declare function assertPromptPartsWithinCap(parts: ChatTurnPartInput[], maxBytes?: number): void;
|
|
57
|
+
/** A file mention resolved from the composer's `@`-picker: the
|
|
58
|
+
* workspace-relative path plus enough metadata to build a prompt part and
|
|
59
|
+
* pointer text. `path` is the canonical identity — the mention pill's
|
|
60
|
+
* `MentionItem.id` for the file kind (`/web-react`'s `useFileMentions`). */
|
|
61
|
+
interface FileMention {
|
|
62
|
+
path: string;
|
|
63
|
+
name: string;
|
|
64
|
+
size?: number;
|
|
65
|
+
}
|
|
66
|
+
/** The `image/*` mime for a mention path by extension, or `undefined` for
|
|
67
|
+
* anything not in the known image set (dispatched as `type: 'file'`). */
|
|
68
|
+
declare function mediaTypeForMentionPath(path: string): string | undefined;
|
|
69
|
+
interface FileMentionsToPartsOptions {
|
|
70
|
+
/** Resolve a mention's workspace-relative path to the absolute path the
|
|
71
|
+
* dispatched part should carry (e.g. a host prefixing the in-box vault
|
|
72
|
+
* root). Default: identity — the path travels unchanged. */
|
|
73
|
+
resolvePath?: (path: string) => string;
|
|
74
|
+
}
|
|
75
|
+
/** Maps resolved file mentions to path-only `ChatTurnFilePartInput`s —
|
|
76
|
+
* `image` vs `file` by extension, and always a `path`, never a `url` (the
|
|
77
|
+
* url/path XOR invariant: a mention is a sandbox path reference, never
|
|
78
|
+
* inline bytes). */
|
|
79
|
+
declare function fileMentionsToParts(mentions: readonly FileMention[], opts?: FileMentionsToPartsOptions): ChatTurnFilePartInput[];
|
|
80
|
+
/** The agent-facing pointer block appended to the dispatched prompt — never
|
|
81
|
+
* persisted in message `content`. Empty array → `''` so callers can append
|
|
82
|
+
* unconditionally. This is the sole producer of that text: the current
|
|
83
|
+
* turn's dispatch and any history projection built from the same mention
|
|
84
|
+
* list both route through here, so the two can't drift apart. */
|
|
85
|
+
declare function buildMentionPromptBlock(mentions: readonly Pick<FileMention, 'name' | 'path'>[]): string;
|
|
86
|
+
/** Validates the untyped `parts` array off the wire. Returns the typed parts
|
|
87
|
+
* or throws `ChatTurnInputError` (400) naming the offending entry. */
|
|
88
|
+
declare function parseChatTurnParts(raw: unknown): ChatTurnFilePartInput[];
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* `createSandboxFileIndexRoute` — server side of `@`-file-mentions
|
|
92
|
+
* (companion to sandbox-ui#184's composer mention primitive). Serves a flat,
|
|
93
|
+
* ignore-filtered listing of the workspace sandbox so `useFileMentions`
|
|
94
|
+
* (`/web-react`) can filter it client-side without a round trip per
|
|
95
|
+
* keystroke.
|
|
96
|
+
*
|
|
97
|
+
* Same seam style as `createUploadRoute`: `authorize({ request })` resolves a
|
|
98
|
+
* structural `{ tree(path, opts) }` handle (the shape of the sandbox SDK's
|
|
99
|
+
* `box.fs.tree`) — no SDK import here. `authorize` also carries the
|
|
100
|
+
* cold-box signal: a sandbox that isn't running yet answers `{ status:
|
|
101
|
+
* 'warming' }` directly, never provisions-and-waits inside this route.
|
|
102
|
+
*/
|
|
103
|
+
|
|
104
|
+
/** One entry from a structural `tree()` scan. Mirrors the sandbox SDK's
|
|
105
|
+
* `FileTreeFile` (`path`, `size`, `mtime`) — `mtime` is unused here so it's
|
|
106
|
+
* omitted from the structural match. */
|
|
107
|
+
interface SandboxTreeFile {
|
|
108
|
+
path: string;
|
|
109
|
+
size: number;
|
|
110
|
+
}
|
|
111
|
+
/** Structural match of the sandbox SDK's `box.fs.tree` result shape
|
|
112
|
+
* (`FileTreeResult`). `stats.truncated` is the only stat this route reads;
|
|
113
|
+
* the rest ride through unread on the real SDK type. */
|
|
114
|
+
interface SandboxTreeResult {
|
|
115
|
+
root: string;
|
|
116
|
+
files: SandboxTreeFile[];
|
|
117
|
+
stats: {
|
|
118
|
+
truncated: boolean;
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
/** Structural match of the sandbox SDK's `box.fs` tree surface. */
|
|
122
|
+
interface SandboxFileTreeSource {
|
|
123
|
+
tree(path: string, options?: {
|
|
124
|
+
maxDepth?: number;
|
|
125
|
+
}): Promise<SandboxTreeResult>;
|
|
126
|
+
}
|
|
127
|
+
interface FileIndexReadyResponse {
|
|
128
|
+
status: 'ready';
|
|
129
|
+
/** Workspace-relative entries. Same shape as `FileMention` (`./wire`) so a
|
|
130
|
+
* client can hand a response entry straight to `fileMentionsToParts` /
|
|
131
|
+
* `buildMentionPromptBlock` without remapping. */
|
|
132
|
+
files: FileMention[];
|
|
133
|
+
/** True when either the underlying scan truncated (SDK-side cap) or this
|
|
134
|
+
* route's own `maxEntries` cap trimmed the filtered list. The client
|
|
135
|
+
* should show "showing first N files" rather than imply completeness. */
|
|
136
|
+
truncated: boolean;
|
|
137
|
+
generatedAt: string;
|
|
138
|
+
}
|
|
139
|
+
/** Cold-box answer: no provisioning happened, no files were scanned. The
|
|
140
|
+
* client shows a warming state and retries — this route never blocks on a
|
|
141
|
+
* box coming up. */
|
|
142
|
+
interface FileIndexWarmingResponse {
|
|
143
|
+
status: 'warming';
|
|
144
|
+
}
|
|
145
|
+
type FileIndexResponse = FileIndexReadyResponse | FileIndexWarmingResponse;
|
|
146
|
+
/** Short-TTL cache seam so repeat popover opens in the same session don't
|
|
147
|
+
* re-scan the workspace. Host-provided (e.g. a KV binding); `key` is
|
|
148
|
+
* whatever `authorize` returns as `cacheKey` — this route treats it opaquely. */
|
|
149
|
+
interface FileIndexCache {
|
|
150
|
+
get(key: string): Promise<FileIndexReadyResponse | null> | FileIndexReadyResponse | null;
|
|
151
|
+
put(key: string, value: FileIndexReadyResponse, options?: {
|
|
152
|
+
ttlSeconds?: number;
|
|
153
|
+
}): Promise<void> | void;
|
|
154
|
+
}
|
|
155
|
+
type FileIndexAuthorization = {
|
|
156
|
+
status: 'ready';
|
|
157
|
+
/** Structural sandbox `fs` handle, usually `ensureWorkspaceSandbox(...)` → `box.fs`. */
|
|
158
|
+
fs: SandboxFileTreeSource;
|
|
159
|
+
/** Workspace root to index (e.g. `/home/agent`). */
|
|
160
|
+
root: string;
|
|
161
|
+
/** Extra ignore segments for this request, merged with the route's
|
|
162
|
+
* defaults + `CreateSandboxFileIndexRouteOptions.ignore`. */
|
|
163
|
+
ignore?: string[];
|
|
164
|
+
/** Opaque cache key for the optional cache seam. Omit to skip caching
|
|
165
|
+
* for this request (e.g. a workspace the host chooses not to cache). */
|
|
166
|
+
cacheKey?: string;
|
|
167
|
+
} | {
|
|
168
|
+
status: 'warming';
|
|
169
|
+
} | {
|
|
170
|
+
status: 'denied';
|
|
171
|
+
response: Response;
|
|
172
|
+
};
|
|
173
|
+
interface CreateSandboxFileIndexRouteOptions {
|
|
174
|
+
/** Authenticate the caller, resolve the sandbox `fs` handle, and signal a
|
|
175
|
+
* cold box — never provisions or waits. */
|
|
176
|
+
authorize(args: {
|
|
177
|
+
request: Request;
|
|
178
|
+
}): Promise<FileIndexAuthorization>;
|
|
179
|
+
/** Extra ignore segments beyond the route's defaults (node_modules, .git,
|
|
180
|
+
* dotfiles/dot-dirs, common build dirs). Matched as exact path-segment
|
|
181
|
+
* names, same rule as the defaults. */
|
|
182
|
+
ignore?: string[];
|
|
183
|
+
/** Passed to `fs.tree` as `options.maxDepth`. Default 12. */
|
|
184
|
+
maxDepth?: number;
|
|
185
|
+
/** Hard cap on entries returned after filtering. Default 5000. */
|
|
186
|
+
maxEntries?: number;
|
|
187
|
+
/** Optional host-provided cache seam. */
|
|
188
|
+
cache?: FileIndexCache;
|
|
189
|
+
/** Cache TTL in seconds when `cache` is set. Default 20. */
|
|
190
|
+
cacheTtlSeconds?: number;
|
|
191
|
+
}
|
|
192
|
+
declare function createSandboxFileIndexRoute(options: CreateSandboxFileIndexRouteOptions): (request: Request) => Promise<Response>;
|
|
193
|
+
|
|
194
|
+
export { type ChatTurnRequestPayload as C, type FileIndexAuthorization as F, INLINE_PARTS_MAX_BYTES as I, type SandboxFileTreeSource as S, type ChatTurnPartInput as a, type ChatTurnFilePartInput as b, ChatTurnInputError as c, type ChatTurnTextPartInput as d, type CreateSandboxFileIndexRouteOptions as e, type FileIndexCache as f, type FileIndexReadyResponse as g, type FileIndexResponse as h, type FileIndexWarmingResponse as i, type FileMention as j, type FileMentionsToPartsOptions as k, type SandboxTreeFile as l, type SandboxTreeResult as m, assertPromptPartsWithinCap as n, buildMentionPromptBlock as o, chatTurnRequestInit as p, createSandboxFileIndexRoute as q, fileMentionsToParts as r, mediaTypeForMentionPath as s, parseChatTurnParts as t, promptPartsByteSize as u };
|
|
@@ -4,12 +4,13 @@ import { C as ChatInteraction, a as ChatInteractionField, b as ChatInteractionSt
|
|
|
4
4
|
export { d as ComposerAnswerDelivery, I as INTERACTION_CANCEL_EVENT, e as INTERACTION_EVENT, f as INTERACTION_RESOLVED_EVENT, h as InteractionPersistedPart, N as NoticeKind, j as NoticePersistedPart, P as ParseInteractionResult, k as canTransitionInteractionStatus, l as cancelStatusFor, m as composerAnswerData, n as composerAnswerDeliveries, o as dedupeQuestionInteractionsByContent, p as fieldAcceptsFreeText, q as interactionFromWireRequest, r as interactionPartKey, s as interactionToPersistedPart, t as isRenderableInteractionKind, u as isSafeInteractionFieldKey, v as isTerminalInteractionStatus, w as noticePart, x as noticePartKey, y as parseInteractionCancel, z as parseInteractionRequest, A as persistedPartToInteraction, B as questionInteractionContentSignature } from '../contract-DYbTzEDf.js';
|
|
5
5
|
import { InteractionData } from '@tangle-network/agent-interface';
|
|
6
6
|
export { InteractionData, InteractionOutcome, InteractionRequest } from '@tangle-network/agent-interface';
|
|
7
|
+
import { j as FileMention } from '../file-index-Bw_IQE_G.js';
|
|
8
|
+
export { b as ChatTurnFilePartInput, a as ChatTurnPartInput, C as ChatTurnRequestPayload, g as FileIndexReadyResponse, h as FileIndexResponse, i as FileIndexWarmingResponse, o as buildMentionPromptBlock, p as chatTurnRequestInit, r as fileMentionsToParts, s as mediaTypeForMentionPath } from '../file-index-Bw_IQE_G.js';
|
|
7
9
|
import { S as StepAgentActivity } from '../agent-activity-C8ZG0F0M.js';
|
|
8
10
|
import { a as FlowTrace } from '../flow-types-Cb_AblZs.js';
|
|
9
11
|
export { S as SandboxTerminalConnection, a as SandboxTerminalConnectionResponse, U as UseSandboxTerminalConnectionOptions, b as UseSandboxTerminalConnectionResult, t as tabTerminalConnectionId, u as useSandboxTerminalConnection } from '../sandbox-terminal-BIIC__CP.js';
|
|
10
12
|
import { CatalogModel } from '../catalog/index.js';
|
|
11
13
|
import { Harness } from '../harness/index.js';
|
|
12
|
-
export { b as ChatTurnFilePartInput, a as ChatTurnPartInput, C as ChatTurnRequestPayload, f as chatTurnRequestInit } from '../wire-BaUF66AS.js';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* Client-side chat-stream consumption — the NDJSON parse loop every agent
|
|
@@ -363,6 +364,97 @@ interface UseChatInteractionsResult {
|
|
|
363
364
|
}
|
|
364
365
|
declare function useChatInteractions(): UseChatInteractionsResult;
|
|
365
366
|
|
|
367
|
+
/**
|
|
368
|
+
* `useFileMentions` — the glue a host passes straight into `AgentComposer`'s
|
|
369
|
+
* `mention` prop (`@tangle-network/sandbox-ui#184`) to wire up `@`-file
|
|
370
|
+
* mentions against `createSandboxFileIndexRoute` (`/chat-routes`).
|
|
371
|
+
*
|
|
372
|
+
* Fetches the index once per session from `indexUrl`, refreshes it in the
|
|
373
|
+
* background whenever the popover opens (a `fetchItems` call) if the cached
|
|
374
|
+
* copy has aged past `refreshAfterMs`, and answers every keystroke from an
|
|
375
|
+
* in-memory fuzzy filter — no per-keystroke network round trip. The returned
|
|
376
|
+
* `refresh()` lets a caller force a re-fetch immediately instead of waiting
|
|
377
|
+
* on `refreshAfterMs` — e.g. right after the agent creates a file mid-session.
|
|
378
|
+
*
|
|
379
|
+
* `MentionItem`/the `mention` prop shape mirror the FROZEN contract from
|
|
380
|
+
* sandbox-ui#184 structurally (no import: `/web-react` stays dependency-free
|
|
381
|
+
* beyond React, and `@tangle-network/sandbox-ui` is an optional peer).
|
|
382
|
+
*/
|
|
383
|
+
|
|
384
|
+
/** Mirrors sandbox-ui#184's `MentionItem` — the atomic pill's payload. For a
|
|
385
|
+
* file mention, `id` is the workspace-relative path (the pill's stable
|
|
386
|
+
* identity and the `@<id>` serialization sandbox-ui uses to round-trip
|
|
387
|
+
* `value`), `label` is the display name, and `detail` carries the full path
|
|
388
|
+
* for the popover row's secondary line. */
|
|
389
|
+
interface MentionItem {
|
|
390
|
+
id: string;
|
|
391
|
+
label: string;
|
|
392
|
+
detail?: string;
|
|
393
|
+
kind?: string;
|
|
394
|
+
}
|
|
395
|
+
/** Mirrors sandbox-ui#184's `AgentComposerProps['mention']` shape — plug the
|
|
396
|
+
* hook's `mention` return value straight into that prop. */
|
|
397
|
+
interface ComposerMentionProp {
|
|
398
|
+
trigger?: string;
|
|
399
|
+
fetchItems(query: string): Promise<MentionItem[]>;
|
|
400
|
+
onMentionsChange?(mentions: MentionItem[]): void;
|
|
401
|
+
renderItem?(item: MentionItem): ReactNode;
|
|
402
|
+
emptyText?: string;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Ranks `files` against `query` (case-insensitive), capped to `limit`:
|
|
406
|
+
* name-prefix matches first, then name-substring, then path-substring.
|
|
407
|
+
* Within a tier, shorter names sort first (the more specific match), then
|
|
408
|
+
* alphabetically by path for a stable order. An empty query returns the
|
|
409
|
+
* first `limit` entries unranked — the popover's default list before typing.
|
|
410
|
+
* Pure and dependency-free (no fuzzy-match library) so it's cheap enough to
|
|
411
|
+
* re-run on every keystroke against a 10k-entry index.
|
|
412
|
+
*/
|
|
413
|
+
declare function rankFileMentions(files: readonly FileMention[], query: string, limit: number): FileMention[];
|
|
414
|
+
/** Max popover results per query — enough to show a useful spread of matches
|
|
415
|
+
* without pushing the fuzzy-filtered list past what a popover can usefully
|
|
416
|
+
* render in one screen. */
|
|
417
|
+
declare const DEFAULT_MENTION_LIMIT = 20;
|
|
418
|
+
/** How long a `ready` index is served before a background refetch — long
|
|
419
|
+
* enough that a full session's worth of popover opens don't repeatedly hit
|
|
420
|
+
* the index endpoint, short enough that a stale listing doesn't linger too
|
|
421
|
+
* far past workspace file changes. Callers who need the index current right
|
|
422
|
+
* now (e.g. just after the agent creates a file) call `refresh()` instead of
|
|
423
|
+
* waiting on this window. */
|
|
424
|
+
declare const INDEX_REFRESH_AFTER_MS: number;
|
|
425
|
+
/** Popover empty-state copy for a `ready` index whose query matched nothing.
|
|
426
|
+
* Loading/warming/error states have their own copy — see `emptyTextFor`. */
|
|
427
|
+
declare const DEFAULT_MENTION_EMPTY_TEXT = "No matching files";
|
|
428
|
+
interface UseFileMentionsOptions {
|
|
429
|
+
/** GET endpoint returning `FileIndexResponse` (a `createSandboxFileIndexRoute`). */
|
|
430
|
+
indexUrl: string;
|
|
431
|
+
/** Max popover results per query. Default {@link DEFAULT_MENTION_LIMIT}. */
|
|
432
|
+
limit?: number;
|
|
433
|
+
/** How long a `ready` index is served without a background refetch.
|
|
434
|
+
* Default {@link INDEX_REFRESH_AFTER_MS}. */
|
|
435
|
+
refreshAfterMs?: number;
|
|
436
|
+
/** `fetch` override for tests / non-global-fetch hosts. Default `fetch`. */
|
|
437
|
+
fetchImpl?: typeof fetch;
|
|
438
|
+
/** Text shown in the popover's empty state once the index is loaded and
|
|
439
|
+
* the query matched nothing. Default {@link DEFAULT_MENTION_EMPTY_TEXT}. */
|
|
440
|
+
emptyText?: string;
|
|
441
|
+
}
|
|
442
|
+
interface UseFileMentionsResult {
|
|
443
|
+
/** Spread straight into `AgentComposer`'s `mention` prop. */
|
|
444
|
+
mention: ComposerMentionProp;
|
|
445
|
+
/** The files currently referenced by mentions in the composer's value —
|
|
446
|
+
* the send-body list (map through `fileMentionsToParts`). */
|
|
447
|
+
mentions: FileMention[];
|
|
448
|
+
/** Drop all currently-referenced mentions (e.g. after a successful send). */
|
|
449
|
+
clearMentions: () => void;
|
|
450
|
+
/** Force a re-fetch of the index right now, ignoring `refreshAfterMs` — for
|
|
451
|
+
* example right after the agent creates a file mid-session, so the next
|
|
452
|
+
* popover open sees it. Dedupes against an already-in-flight load rather
|
|
453
|
+
* than firing a second request. */
|
|
454
|
+
refresh: () => Promise<void>;
|
|
455
|
+
}
|
|
456
|
+
declare function useFileMentions(options: UseFileMentionsOptions): UseFileMentionsResult;
|
|
457
|
+
|
|
366
458
|
/**
|
|
367
459
|
* Provider brand marks — real logo path data (simple-icons / SVG Logos, both
|
|
368
460
|
* CC0) inlined so the picker shows actual provider identity instead of
|
|
@@ -792,4 +884,4 @@ declare function useThinkingSeconds(active: boolean): number;
|
|
|
792
884
|
*/
|
|
793
885
|
declare function ChatMessages({ messages, models, renderMarkdown, renderExtras, userLabel, agentLabel, loading, approval, onToolCallClick, toolRenderers, error, onRetry, renderEmpty, emptyState, header, }: ChatMessagesProps): react.JSX.Element;
|
|
794
886
|
|
|
795
|
-
export { type ActivityTone, type AgentActivityPage, AgentActivityPanel, type AgentActivityPanelProps, type AgentActivityRecord, AgentSessionControls, type AgentSessionControlsProps, CatalogModel, ChatComposer, type ChatComposerProps, type ChatEmptyDoor, ChatEmptyState, type ChatEmptyStateProps, ChatInteraction, ChatInteractionField, ChatInteractionStatus, type ChatMessageMetrics, type ChatMessageSegment, ChatMessages, type ChatMessagesProps, ChatSelectField, type ChatStreamCallbacks, type ChatStreamToolCall, type ChatStreamToolResult, type ChatToolCallInfo, type ChatUiMessage, type ComposerFile, type ComposerFilePart, type ConsumeChatStreamResult, DEFAULT_EFFORT_LEVELS, type EffortLevel, EffortPicker, type EffortPickerProps, type FieldValues, FlowWaterfall, type FlowWaterfallProps, INTERACTION_SUBMIT_TIMEOUT_MESSAGE, INTERACTION_SUBMIT_TIMEOUT_MS, InteractionActionButton, type InteractionAnswerSubmission, type InteractionAnswerSubmitterOptions, InteractionBadge, type InteractionBadgeVariant, InteractionCancelData, InteractionPlanCard, type InteractionPlanCardProps, InteractionQuestionCard, type InteractionQuestionCardProps, InteractionRequestWire, type InteractionSubmitResult, MissionActivityLane, type MissionActivityLaneProps, ModelPicker, type ModelPickerProps, type ProposalApprovalHandlers, ProviderLogo, type ProviderLogoProps, QuestionOptionList, type QuestionOptionListProps, RunDrillIn, type RunDrillInProps, SeatPaywall, type SeatPaywallProps, type SmoothRevealOptions, type StreamChatOptions, type SubmitInteractionAnswer, type ToolDetailRenderers, type ToolRunRecord, type ToolRunStep, type UseChatInteractionsResult, type WaterfallRow, activityTone, buildAnswerData, cancelChatInteraction, consumeChatStream, createInteractionAnswerSubmitter, dispatchChatStreamLine, fieldAnswer, formatActivityCost, formatActivityDuration, formatModelCost, formatTokensPerSecond, hasSecretField, interactionStatusLabels, interactionTerminalNotes, isLateAnswerableStatus, lateAnswerMessage, mergeActivityPages, nextRevealCount, pendingApprovalOf, resolveChatInteraction, responseErrorMessage, restoreChatInteractions, streamChatTurn, terminalizePendingChatInteractions, upsertChatInteraction, useChatInteractions, usePending, usePopover, useSmoothText, useThinkingSeconds, waterfallLayout };
|
|
887
|
+
export { type ActivityTone, type AgentActivityPage, AgentActivityPanel, type AgentActivityPanelProps, type AgentActivityRecord, AgentSessionControls, type AgentSessionControlsProps, CatalogModel, ChatComposer, type ChatComposerProps, type ChatEmptyDoor, ChatEmptyState, type ChatEmptyStateProps, ChatInteraction, ChatInteractionField, ChatInteractionStatus, type ChatMessageMetrics, type ChatMessageSegment, ChatMessages, type ChatMessagesProps, ChatSelectField, type ChatStreamCallbacks, type ChatStreamToolCall, type ChatStreamToolResult, type ChatToolCallInfo, type ChatUiMessage, type ComposerFile, type ComposerFilePart, type ComposerMentionProp, type ConsumeChatStreamResult, DEFAULT_EFFORT_LEVELS, DEFAULT_MENTION_EMPTY_TEXT, DEFAULT_MENTION_LIMIT, type EffortLevel, EffortPicker, type EffortPickerProps, type FieldValues, FileMention, FlowWaterfall, type FlowWaterfallProps, INDEX_REFRESH_AFTER_MS, INTERACTION_SUBMIT_TIMEOUT_MESSAGE, INTERACTION_SUBMIT_TIMEOUT_MS, InteractionActionButton, type InteractionAnswerSubmission, type InteractionAnswerSubmitterOptions, InteractionBadge, type InteractionBadgeVariant, InteractionCancelData, InteractionPlanCard, type InteractionPlanCardProps, InteractionQuestionCard, type InteractionQuestionCardProps, InteractionRequestWire, type InteractionSubmitResult, type MentionItem, MissionActivityLane, type MissionActivityLaneProps, ModelPicker, type ModelPickerProps, type ProposalApprovalHandlers, ProviderLogo, type ProviderLogoProps, QuestionOptionList, type QuestionOptionListProps, RunDrillIn, type RunDrillInProps, SeatPaywall, type SeatPaywallProps, type SmoothRevealOptions, type StreamChatOptions, type SubmitInteractionAnswer, type ToolDetailRenderers, type ToolRunRecord, type ToolRunStep, type UseChatInteractionsResult, type UseFileMentionsOptions, type UseFileMentionsResult, type WaterfallRow, activityTone, buildAnswerData, cancelChatInteraction, consumeChatStream, createInteractionAnswerSubmitter, dispatchChatStreamLine, fieldAnswer, formatActivityCost, formatActivityDuration, formatModelCost, formatTokensPerSecond, hasSecretField, interactionStatusLabels, interactionTerminalNotes, isLateAnswerableStatus, lateAnswerMessage, mergeActivityPages, nextRevealCount, pendingApprovalOf, rankFileMentions, resolveChatInteraction, responseErrorMessage, restoreChatInteractions, streamChatTurn, terminalizePendingChatInteractions, upsertChatInteraction, useChatInteractions, useFileMentions, usePending, usePopover, useSmoothText, useThinkingSeconds, waterfallLayout };
|
package/dist/web-react/index.js
CHANGED
|
@@ -5,8 +5,11 @@ import {
|
|
|
5
5
|
ChatEmptyState,
|
|
6
6
|
ChatMessages,
|
|
7
7
|
DEFAULT_EFFORT_LEVELS,
|
|
8
|
+
DEFAULT_MENTION_EMPTY_TEXT,
|
|
9
|
+
DEFAULT_MENTION_LIMIT,
|
|
8
10
|
EffortPicker,
|
|
9
11
|
FlowWaterfall,
|
|
12
|
+
INDEX_REFRESH_AFTER_MS,
|
|
10
13
|
INTERACTION_SUBMIT_TIMEOUT_MESSAGE,
|
|
11
14
|
INTERACTION_SUBMIT_TIMEOUT_MS,
|
|
12
15
|
InteractionActionButton,
|
|
@@ -38,6 +41,7 @@ import {
|
|
|
38
41
|
mergeActivityPages,
|
|
39
42
|
nextRevealCount,
|
|
40
43
|
pendingApprovalOf,
|
|
44
|
+
rankFileMentions,
|
|
41
45
|
resolveChatInteraction,
|
|
42
46
|
responseErrorMessage,
|
|
43
47
|
restoreChatInteractions,
|
|
@@ -45,19 +49,23 @@ import {
|
|
|
45
49
|
terminalizePendingChatInteractions,
|
|
46
50
|
upsertChatInteraction,
|
|
47
51
|
useChatInteractions,
|
|
52
|
+
useFileMentions,
|
|
48
53
|
usePending,
|
|
49
54
|
usePopover,
|
|
50
55
|
useSmoothText,
|
|
51
56
|
useThinkingSeconds,
|
|
52
57
|
waterfallLayout
|
|
53
|
-
} from "../chunk-
|
|
58
|
+
} from "../chunk-KM766NN3.js";
|
|
54
59
|
import {
|
|
55
60
|
tabTerminalConnectionId,
|
|
56
61
|
useSandboxTerminalConnection
|
|
57
62
|
} from "../chunk-65P3HJY3.js";
|
|
58
63
|
import {
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
buildMentionPromptBlock,
|
|
65
|
+
chatTurnRequestInit,
|
|
66
|
+
fileMentionsToParts,
|
|
67
|
+
mediaTypeForMentionPath
|
|
68
|
+
} from "../chunk-2EO7CPL3.js";
|
|
61
69
|
import "../chunk-2QI7XV2T.js";
|
|
62
70
|
import {
|
|
63
71
|
INTERACTION_CANCEL_EVENT,
|
|
@@ -90,8 +98,11 @@ export {
|
|
|
90
98
|
ChatEmptyState,
|
|
91
99
|
ChatMessages,
|
|
92
100
|
DEFAULT_EFFORT_LEVELS,
|
|
101
|
+
DEFAULT_MENTION_EMPTY_TEXT,
|
|
102
|
+
DEFAULT_MENTION_LIMIT,
|
|
93
103
|
EffortPicker,
|
|
94
104
|
FlowWaterfall,
|
|
105
|
+
INDEX_REFRESH_AFTER_MS,
|
|
95
106
|
INTERACTION_CANCEL_EVENT,
|
|
96
107
|
INTERACTION_EVENT,
|
|
97
108
|
INTERACTION_RESOLVED_EVENT,
|
|
@@ -109,6 +120,7 @@ export {
|
|
|
109
120
|
SeatPaywall,
|
|
110
121
|
activityTone,
|
|
111
122
|
buildAnswerData,
|
|
123
|
+
buildMentionPromptBlock,
|
|
112
124
|
canTransitionInteractionStatus,
|
|
113
125
|
cancelChatInteraction,
|
|
114
126
|
cancelStatusFor,
|
|
@@ -121,6 +133,7 @@ export {
|
|
|
121
133
|
dispatchChatStreamLine,
|
|
122
134
|
fieldAcceptsFreeText,
|
|
123
135
|
fieldAnswer,
|
|
136
|
+
fileMentionsToParts,
|
|
124
137
|
formatActivityCost,
|
|
125
138
|
formatActivityDuration,
|
|
126
139
|
formatModelCost,
|
|
@@ -136,6 +149,7 @@ export {
|
|
|
136
149
|
isSafeInteractionFieldKey,
|
|
137
150
|
isTerminalInteractionStatus,
|
|
138
151
|
lateAnswerMessage,
|
|
152
|
+
mediaTypeForMentionPath,
|
|
139
153
|
mergeActivityPages,
|
|
140
154
|
nextRevealCount,
|
|
141
155
|
noticePart,
|
|
@@ -145,6 +159,7 @@ export {
|
|
|
145
159
|
pendingApprovalOf,
|
|
146
160
|
persistedPartToInteraction,
|
|
147
161
|
questionInteractionContentSignature,
|
|
162
|
+
rankFileMentions,
|
|
148
163
|
resolveChatInteraction,
|
|
149
164
|
responseErrorMessage,
|
|
150
165
|
restoreChatInteractions,
|
|
@@ -153,6 +168,7 @@ export {
|
|
|
153
168
|
terminalizePendingChatInteractions,
|
|
154
169
|
upsertChatInteraction,
|
|
155
170
|
useChatInteractions,
|
|
171
|
+
useFileMentions,
|
|
156
172
|
usePending,
|
|
157
173
|
usePopover,
|
|
158
174
|
useSandboxTerminalConnection,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-app",
|
|
3
|
-
"version": "0.43.
|
|
3
|
+
"version": "0.43.41",
|
|
4
4
|
"packageManager": "pnpm@10.33.4",
|
|
5
5
|
"description": "Application-shell framework for Tangle agent products: a bounded tool loop, the structured agent→app tool side channel, integration-hub client, per-workspace billing, and crypto — composed over the Tangle agent substrate through typed seams.",
|
|
6
6
|
"keywords": [
|
package/dist/chunk-5SV5PSU7.js
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
// src/chat-routes/wire.ts
|
|
2
|
-
function chatTurnRequestInit(payload) {
|
|
3
|
-
return {
|
|
4
|
-
method: "POST",
|
|
5
|
-
headers: { "Content-Type": "application/json" },
|
|
6
|
-
body: JSON.stringify(payload)
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
|
-
var INLINE_PARTS_MAX_BYTES = 95e4;
|
|
10
|
-
var ChatTurnInputError = class extends Error {
|
|
11
|
-
constructor(message, status = 400, code = "INVALID_CHAT_TURN") {
|
|
12
|
-
super(message);
|
|
13
|
-
this.status = status;
|
|
14
|
-
this.code = code;
|
|
15
|
-
this.name = "ChatTurnInputError";
|
|
16
|
-
}
|
|
17
|
-
status;
|
|
18
|
-
code;
|
|
19
|
-
};
|
|
20
|
-
function partByteSize(part) {
|
|
21
|
-
let bytes = 0;
|
|
22
|
-
if (part.type === "text") return part.text.length;
|
|
23
|
-
if (part.url) bytes += part.url.length;
|
|
24
|
-
if (part.content) bytes += part.content.length;
|
|
25
|
-
if (part.path) bytes += part.path.length;
|
|
26
|
-
return bytes;
|
|
27
|
-
}
|
|
28
|
-
function promptPartsByteSize(parts) {
|
|
29
|
-
return parts.reduce((total, part) => total + partByteSize(part), 0);
|
|
30
|
-
}
|
|
31
|
-
function assertPromptPartsWithinCap(parts, maxBytes = INLINE_PARTS_MAX_BYTES) {
|
|
32
|
-
const total = promptPartsByteSize(parts);
|
|
33
|
-
if (total <= maxBytes) return;
|
|
34
|
-
const largest = [...parts].sort((a, b) => partByteSize(b) - partByteSize(a))[0];
|
|
35
|
-
const largestName = largest && largest.type !== "text" ? largest.filename ?? largest.path ?? largest.type : "text";
|
|
36
|
-
throw new ChatTurnInputError(
|
|
37
|
-
`Inline prompt parts total ${total}B, over the ${maxBytes}B budget (largest: ${largestName}, ${largest ? partByteSize(largest) : 0}B). Upload large files through the upload route so they travel as sandbox path references.`,
|
|
38
|
-
413,
|
|
39
|
-
"PROMPT_PARTS_TOO_LARGE"
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
function parseChatTurnParts(raw) {
|
|
43
|
-
if (raw === void 0 || raw === null) return [];
|
|
44
|
-
if (!Array.isArray(raw)) throw new ChatTurnInputError("parts must be an array");
|
|
45
|
-
return raw.map((entry, index) => {
|
|
46
|
-
const part = entry;
|
|
47
|
-
if (!part || typeof part !== "object") {
|
|
48
|
-
throw new ChatTurnInputError(`parts[${index}] must be an object`);
|
|
49
|
-
}
|
|
50
|
-
if (part.type !== "image" && part.type !== "file") {
|
|
51
|
-
throw new ChatTurnInputError(`parts[${index}].type must be 'image' or 'file'`);
|
|
52
|
-
}
|
|
53
|
-
for (const key of ["filename", "mediaType", "url", "path", "content"]) {
|
|
54
|
-
if (part[key] !== void 0 && typeof part[key] !== "string") {
|
|
55
|
-
throw new ChatTurnInputError(`parts[${index}].${key} must be a string`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
if (!part.url && !part.path && !part.content) {
|
|
59
|
-
throw new ChatTurnInputError(`parts[${index}] needs a url, path, or content`);
|
|
60
|
-
}
|
|
61
|
-
return {
|
|
62
|
-
type: part.type,
|
|
63
|
-
...part.filename !== void 0 ? { filename: part.filename } : {},
|
|
64
|
-
...part.mediaType !== void 0 ? { mediaType: part.mediaType } : {},
|
|
65
|
-
...part.url !== void 0 ? { url: part.url } : {},
|
|
66
|
-
...part.path !== void 0 ? { path: part.path } : {},
|
|
67
|
-
...part.content !== void 0 ? { content: part.content } : {}
|
|
68
|
-
};
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export {
|
|
73
|
-
chatTurnRequestInit,
|
|
74
|
-
INLINE_PARTS_MAX_BYTES,
|
|
75
|
-
ChatTurnInputError,
|
|
76
|
-
promptPartsByteSize,
|
|
77
|
-
assertPromptPartsWithinCap,
|
|
78
|
-
parseChatTurnParts
|
|
79
|
-
};
|
|
80
|
-
//# sourceMappingURL=chunk-5SV5PSU7.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/chat-routes/wire.ts"],"sourcesContent":["/**\n * Wire contract between the chat client (composer + `streamChatTurn`) and the\n * assembled server vertical (`createChatTurnRoutes`). Import-free on purpose:\n * `/web-react` re-exports these types into browser bundles, so nothing here may\n * reach a Node builtin or an engine package.\n *\n * The part shape mirrors the sandbox SDK's `PromptInputPart` structurally\n * (text | image | file with filename/mediaType/url/path/content) — derived\n * here, not imported, so the client bundle never touches the SDK.\n */\n\nexport interface ChatTurnTextPartInput {\n type: 'text'\n text: string\n}\n\n/** A non-text prompt part the upload route hands back and the client echoes\n * on send. `url` carries an inline `data:` URI for small files; `path` is a\n * sandbox workspace reference for large ones (the >1 MiB gateway body cap\n * makes the two-step upload mandatory). */\nexport interface ChatTurnFilePartInput {\n type: 'image' | 'file'\n filename?: string\n mediaType?: string\n url?: string\n path?: string\n content?: string\n}\n\nexport type ChatTurnPartInput = ChatTurnTextPartInput | ChatTurnFilePartInput\n\n/** POST body for the turn route. `content` may be empty when `parts` carry the\n * message (an image-only send). Product routing fields (workspaceId etc.) ride\n * alongside and are read by the product's `authorize` seam. */\nexport interface ChatTurnRequestPayload {\n threadId: string\n content?: string\n /** Non-text parts from the upload route, echoed back verbatim. */\n parts?: ChatTurnFilePartInput[]\n model?: string\n effort?: 'auto' | 'low' | 'medium' | 'high'\n harness?: string\n /** Client-generated idempotency key for the logical turn (retry-safe). */\n turnId?: string\n [key: string]: unknown\n}\n\n/** `fetch` init for the turn route — the one place the client wire shape is\n * serialized, so composer glue and products never drift from the server's\n * parser. */\nexport function chatTurnRequestInit(payload: ChatTurnRequestPayload): RequestInit {\n return {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n }\n}\n\n// ── inline-part byte budget ─────────────────────────────────────────────────\n//\n// The sandbox gateway caps request bodies at 1 MiB; a turn body whose inline\n// `data:` parts exceed it dies at the gateway with an opaque 413. Enforce the\n// budget at the route boundary instead, with headroom for the JSON envelope\n// (same fail-loud-at-the-choke-point style as /sandbox's provision-payload and\n// env-size gates).\n\nexport const INLINE_PARTS_MAX_BYTES = 950_000\n\nexport class ChatTurnInputError extends Error {\n constructor(message: string, readonly status = 400, readonly code = 'INVALID_CHAT_TURN') {\n super(message)\n this.name = 'ChatTurnInputError'\n }\n}\n\nfunction partByteSize(part: ChatTurnPartInput): number {\n let bytes = 0\n if (part.type === 'text') return part.text.length\n if (part.url) bytes += part.url.length\n if (part.content) bytes += part.content.length\n if (part.path) bytes += part.path.length\n return bytes\n}\n\nexport function promptPartsByteSize(parts: ChatTurnPartInput[]): number {\n return parts.reduce((total, part) => total + partByteSize(part), 0)\n}\n\n/** Throws `ChatTurnInputError` (413) when the parts' inline payload would blow\n * the gateway cap. Path-ref parts are tiny by construction and always pass. */\nexport function assertPromptPartsWithinCap(\n parts: ChatTurnPartInput[],\n maxBytes = INLINE_PARTS_MAX_BYTES,\n): void {\n const total = promptPartsByteSize(parts)\n if (total <= maxBytes) return\n const largest = [...parts].sort((a, b) => partByteSize(b) - partByteSize(a))[0]\n const largestName = largest && largest.type !== 'text' ? largest.filename ?? largest.path ?? largest.type : 'text'\n throw new ChatTurnInputError(\n `Inline prompt parts total ${total}B, over the ${maxBytes}B budget (largest: ${largestName}, ${largest ? partByteSize(largest) : 0}B). ` +\n 'Upload large files through the upload route so they travel as sandbox path references.',\n 413,\n 'PROMPT_PARTS_TOO_LARGE',\n )\n}\n\n/** Validates the untyped `parts` array off the wire. Returns the typed parts\n * or throws `ChatTurnInputError` (400) naming the offending entry. */\nexport function parseChatTurnParts(raw: unknown): ChatTurnFilePartInput[] {\n if (raw === undefined || raw === null) return []\n if (!Array.isArray(raw)) throw new ChatTurnInputError('parts must be an array')\n return raw.map((entry, index) => {\n const part = entry as Record<string, unknown> | null\n if (!part || typeof part !== 'object') {\n throw new ChatTurnInputError(`parts[${index}] must be an object`)\n }\n if (part.type !== 'image' && part.type !== 'file') {\n throw new ChatTurnInputError(`parts[${index}].type must be 'image' or 'file'`)\n }\n for (const key of ['filename', 'mediaType', 'url', 'path', 'content'] as const) {\n if (part[key] !== undefined && typeof part[key] !== 'string') {\n throw new ChatTurnInputError(`parts[${index}].${key} must be a string`)\n }\n }\n if (!part.url && !part.path && !part.content) {\n throw new ChatTurnInputError(`parts[${index}] needs a url, path, or content`)\n }\n return {\n type: part.type,\n ...(part.filename !== undefined ? { filename: part.filename as string } : {}),\n ...(part.mediaType !== undefined ? { mediaType: part.mediaType as string } : {}),\n ...(part.url !== undefined ? { url: part.url as string } : {}),\n ...(part.path !== undefined ? { path: part.path as string } : {}),\n ...(part.content !== undefined ? { content: part.content as string } : {}),\n }\n })\n}\n"],"mappings":";AAkDO,SAAS,oBAAoB,SAA8C;AAChF,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,OAAO;AAAA,EAC9B;AACF;AAUO,IAAM,yBAAyB;AAE/B,IAAM,qBAAN,cAAiC,MAAM;AAAA,EAC5C,YAAY,SAA0B,SAAS,KAAc,OAAO,qBAAqB;AACvF,UAAM,OAAO;AADuB;AAAuB;AAE3D,SAAK,OAAO;AAAA,EACd;AAAA,EAHsC;AAAA,EAAuB;AAI/D;AAEA,SAAS,aAAa,MAAiC;AACrD,MAAI,QAAQ;AACZ,MAAI,KAAK,SAAS,OAAQ,QAAO,KAAK,KAAK;AAC3C,MAAI,KAAK,IAAK,UAAS,KAAK,IAAI;AAChC,MAAI,KAAK,QAAS,UAAS,KAAK,QAAQ;AACxC,MAAI,KAAK,KAAM,UAAS,KAAK,KAAK;AAClC,SAAO;AACT;AAEO,SAAS,oBAAoB,OAAoC;AACtE,SAAO,MAAM,OAAO,CAAC,OAAO,SAAS,QAAQ,aAAa,IAAI,GAAG,CAAC;AACpE;AAIO,SAAS,2BACd,OACA,WAAW,wBACL;AACN,QAAM,QAAQ,oBAAoB,KAAK;AACvC,MAAI,SAAS,SAAU;AACvB,QAAM,UAAU,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,aAAa,CAAC,IAAI,aAAa,CAAC,CAAC,EAAE,CAAC;AAC9E,QAAM,cAAc,WAAW,QAAQ,SAAS,SAAS,QAAQ,YAAY,QAAQ,QAAQ,QAAQ,OAAO;AAC5G,QAAM,IAAI;AAAA,IACR,6BAA6B,KAAK,eAAe,QAAQ,sBAAsB,WAAW,KAAK,UAAU,aAAa,OAAO,IAAI,CAAC;AAAA,IAElI;AAAA,IACA;AAAA,EACF;AACF;AAIO,SAAS,mBAAmB,KAAuC;AACxE,MAAI,QAAQ,UAAa,QAAQ,KAAM,QAAO,CAAC;AAC/C,MAAI,CAAC,MAAM,QAAQ,GAAG,EAAG,OAAM,IAAI,mBAAmB,wBAAwB;AAC9E,SAAO,IAAI,IAAI,CAAC,OAAO,UAAU;AAC/B,UAAM,OAAO;AACb,QAAI,CAAC,QAAQ,OAAO,SAAS,UAAU;AACrC,YAAM,IAAI,mBAAmB,SAAS,KAAK,qBAAqB;AAAA,IAClE;AACA,QAAI,KAAK,SAAS,WAAW,KAAK,SAAS,QAAQ;AACjD,YAAM,IAAI,mBAAmB,SAAS,KAAK,kCAAkC;AAAA,IAC/E;AACA,eAAW,OAAO,CAAC,YAAY,aAAa,OAAO,QAAQ,SAAS,GAAY;AAC9E,UAAI,KAAK,GAAG,MAAM,UAAa,OAAO,KAAK,GAAG,MAAM,UAAU;AAC5D,cAAM,IAAI,mBAAmB,SAAS,KAAK,KAAK,GAAG,mBAAmB;AAAA,MACxE;AAAA,IACF;AACA,QAAI,CAAC,KAAK,OAAO,CAAC,KAAK,QAAQ,CAAC,KAAK,SAAS;AAC5C,YAAM,IAAI,mBAAmB,SAAS,KAAK,iCAAiC;AAAA,IAC9E;AACA,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,GAAI,KAAK,aAAa,SAAY,EAAE,UAAU,KAAK,SAAmB,IAAI,CAAC;AAAA,MAC3E,GAAI,KAAK,cAAc,SAAY,EAAE,WAAW,KAAK,UAAoB,IAAI,CAAC;AAAA,MAC9E,GAAI,KAAK,QAAQ,SAAY,EAAE,KAAK,KAAK,IAAc,IAAI,CAAC;AAAA,MAC5D,GAAI,KAAK,SAAS,SAAY,EAAE,MAAM,KAAK,KAAe,IAAI,CAAC;AAAA,MAC/D,GAAI,KAAK,YAAY,SAAY,EAAE,SAAS,KAAK,QAAkB,IAAI,CAAC;AAAA,IAC1E;AAAA,EACF,CAAC;AACH;","names":[]}
|